vagrant-vsphere-ddns 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/Gemfile +9 -0
- data/README.md +91 -0
- data/Rakefile +1 -0
- data/lib/vagrant-vsphere-ddns/action/get_ssh_info.rb +46 -0
- data/lib/vagrant-vsphere-ddns/action/wait_for_ip_address.rb +43 -0
- data/lib/vagrant-vsphere-ddns/action.rb +22 -0
- data/lib/vagrant-vsphere-ddns/config.rb +24 -0
- data/lib/vagrant-vsphere-ddns/errors.rb +15 -0
- data/lib/vagrant-vsphere-ddns/plugin.rb +35 -0
- data/lib/vagrant-vsphere-ddns/version.rb +5 -0
- data/lib/vagrant-vsphere-ddns.rb +17 -0
- data/locales/en.yml +5 -0
- data/scripts/dns_update.py +38 -0
- data/vagrant-vsphere-ddns.gemspec +20 -0
- metadata +74 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9a19f218ad9a80e8502c8d0055e560c146407609
|
4
|
+
data.tar.gz: ad1b4de8e83023895691897eb3c7782c61e676dd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 39df719870d78d8202eee4bdd13d6d20eeaacfaeeb49e568007314842112f5f47860e629dbb62e520ee45c96640dd75e54c49250f5f8a9af023fa970c8c11c34
|
7
|
+
data.tar.gz: ff5755841aa2075b885784d2b47c835809cfb333f01c73cf08aba2ce3cb28e63f0d78d13245eb3482620fc57fef14d8e8ffcdd1bbf69dcaeee37e62265fa1388
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# Vagrant vSphere DDNS plugin
|
2
|
+
|
3
|
+
This is a PoC [Vagrant](http://www.vagrantup.com) plugin that enables Vagrant to connect to vSphere VMs via dynamic domain names based on MAC addresses.
|
4
|
+
This trivial plugin enables SSH connection to VMs that do not have guest tools installed.
|
5
|
+
|
6
|
+
This plugin does not work out of the box and requires custom DHCP and DNS settings.
|
7
|
+
This configuration is however not implemented in the plugin itself and has to be performed manually in advance.
|
8
|
+
|
9
|
+
## Requirements
|
10
|
+
|
11
|
+
* Vagrant
|
12
|
+
* vagrant-vsphere plugin
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
Plugin can be configured by following settings:
|
17
|
+
* `ddns.host`
|
18
|
+
* Hostname that will be used for SSH connections instead of guest IP address
|
19
|
+
* Patterns mac0, mac1, ... will be replaced by VMs MAC address
|
20
|
+
* `ddns.timeout`
|
21
|
+
* Defines how long the plugin will wait for successfull DNS resolution (default is 120 seconds)
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
Vagrant.configure("2") do |config|
|
25
|
+
config.vm.box = 'dummy-vsphere-box'
|
26
|
+
|
27
|
+
config.ddns.host = "%{mac0}.local"
|
28
|
+
config.ddns.timeout = 120
|
29
|
+
|
30
|
+
config.vm.provider :vsphere do |vsphere|
|
31
|
+
vsphere.host = 'HOST NAME OF YOUR VSPHERE INSTANCE'
|
32
|
+
vsphere.compute_resource_name = 'YOUR COMPUTE RESOURCE'
|
33
|
+
vsphere.resource_pool_name = 'YOUR RESOURCE POOL'
|
34
|
+
vsphere.template_name = '/PATH/TO/YOUR VM TEMPLATE'
|
35
|
+
vsphere.name = 'NEW VM NAME'
|
36
|
+
vsphere.user = 'YOUR VMWARE USER'
|
37
|
+
vsphere.password = 'YOUR VMWARE PASSWORD'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
After running `vagrant up --provider=vsphere` Vagrant will attempt to reach VM using specified domain name
|
43
|
+
(e.g. `005056a44d89.local`) and fail if this it can not be resolved for 2 minutes.
|
44
|
+
|
45
|
+
## DHCP and DNS settings
|
46
|
+
|
47
|
+
* Allow dynamic DNS updates in Bind in `/etc/bind/named.conf.local`
|
48
|
+
```bash
|
49
|
+
...
|
50
|
+
include "/etc/bind/ddns.key";
|
51
|
+
|
52
|
+
zone ".local" {
|
53
|
+
type master;
|
54
|
+
forwarders {};
|
55
|
+
file "/var/lib/bind/db.local";
|
56
|
+
allow-update { key dhcpupdate; };
|
57
|
+
};
|
58
|
+
...
|
59
|
+
```
|
60
|
+
* Execute [custom script](./scripts/dns_update.py) on DHCP events in `/etc/dhcp/dhcpd.conf`
|
61
|
+
```bash
|
62
|
+
...
|
63
|
+
on commit {
|
64
|
+
execute("/etc/dhcp/dns_update.py",
|
65
|
+
"--action", "commit",
|
66
|
+
"--ip", binary-to-ascii(10, 8, ".", leased-address),
|
67
|
+
"--mac", binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)),
|
68
|
+
"--zone", config-option domain-name,
|
69
|
+
"--key_file", "/etc/dhcp/ddns.key"
|
70
|
+
);
|
71
|
+
}
|
72
|
+
on release {
|
73
|
+
execute("/etc/dhcp/dns_update.py",
|
74
|
+
"--action", "release",
|
75
|
+
"--ip", binary-to-ascii(10, 8, ".", leased-address),
|
76
|
+
"--mac", binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)),
|
77
|
+
"--zone", config-option domain-name,
|
78
|
+
"--key_file", "/etc/dhcp/ddns.key"
|
79
|
+
);
|
80
|
+
}
|
81
|
+
on expiry {
|
82
|
+
execute("/etc/dhcp/dns_update.py",
|
83
|
+
"--action", "expiry",
|
84
|
+
"--ip", binary-to-ascii(10, 8, ".", leased-address),
|
85
|
+
"--mac", binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)),
|
86
|
+
"--zone", config-option domain-name,
|
87
|
+
"--key_file", "/etc/dhcp/ddns.key"
|
88
|
+
);
|
89
|
+
}
|
90
|
+
...
|
91
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rbvmomi'
|
2
|
+
require 'vSphere/util/vim_helpers'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module VSphereDDNS
|
6
|
+
module Action
|
7
|
+
class GetSshInfo
|
8
|
+
include VagrantPlugins::VSphere::Util::VimHelpers
|
9
|
+
|
10
|
+
def initialize(app, env)
|
11
|
+
@app = app
|
12
|
+
@logger = Log4r::Logger.new("vagrant::vsphere-ddns::get_ssh_info")
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
env[:machine_ssh_info] = get_ssh_info(env[:vSphere_connection], env[:machine])
|
17
|
+
if !env[:machine_ssh_info].nil?
|
18
|
+
@logger.info("SSH info: %s:%s" % [env[:machine_ssh_info][:host], env[:machine_ssh_info][:port]])
|
19
|
+
end
|
20
|
+
@app.call env
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def get_ssh_info(connection, machine)
|
26
|
+
return nil if machine.config.ddns.host.nil?
|
27
|
+
return nil if machine.id.nil?
|
28
|
+
vm = get_vm_by_uuid connection, machine
|
29
|
+
return nil if vm.nil?
|
30
|
+
|
31
|
+
format_data = {}
|
32
|
+
vm.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard).each_with_index do |card, id|
|
33
|
+
break if card.nil?
|
34
|
+
format_data["mac#{id}".to_sym] = (card.macAddress.scan /[a-f0-9]/).join
|
35
|
+
end
|
36
|
+
|
37
|
+
{
|
38
|
+
host: machine.config.ddns.host % format_data,
|
39
|
+
port: (machine.config.ssh.port.nil? ? 22 : machine.config.ssh.port)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'log4r'
|
3
|
+
require 'resolv'
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module VSphereDDNS
|
7
|
+
module Action
|
8
|
+
class WaitForIPAddress
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new("vagrant::vsphere-ddns::wait_for_ip_address")
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
timeout = env[:machine].config.ddns.ssh_timeout
|
16
|
+
@logger.info("Trying to resolve #{env[:machine_ssh_info][:host]} (timeout #{timeout} seconds)")
|
17
|
+
|
18
|
+
Timeout.timeout(timeout) do
|
19
|
+
while true
|
20
|
+
# If a ctrl-c came through, break out
|
21
|
+
return if env[:interrupted]
|
22
|
+
|
23
|
+
begin
|
24
|
+
ip_address = Resolv.getaddress(env[:machine_ssh_info][:host])
|
25
|
+
@logger.info("Host #{env[:machine_ssh_info][:host]} resolved to #{ip_address}")
|
26
|
+
break
|
27
|
+
rescue Resolv::ResolvError
|
28
|
+
@logger.warn("Could not resolve: #{env[:machine_ssh_info][:host]}")
|
29
|
+
end
|
30
|
+
sleep 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
return if env[:interrupted]
|
34
|
+
@app.call(env)
|
35
|
+
|
36
|
+
rescue Timeout::Error
|
37
|
+
raise Errors::IPAddrTimeout
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
require 'vagrant/action/builder'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module VSphereDDNS
|
6
|
+
module Action
|
7
|
+
include Vagrant::Action::Builtin
|
8
|
+
|
9
|
+
def self.action_get_ssh_info
|
10
|
+
Vagrant::Action::Builder.new.tap do |b|
|
11
|
+
b.use GetSshInfo
|
12
|
+
b.use WaitForIPAddress
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# autoload
|
17
|
+
action_root = Pathname.new(File.expand_path('../action', __FILE__))
|
18
|
+
autoload :GetSshInfo, action_root.join('get_ssh_info')
|
19
|
+
autoload :WaitForIPAddress, action_root.join("wait_for_ip_address")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VSphereDDNS
|
5
|
+
class Config < Vagrant.plugin('2', :config)
|
6
|
+
attr_accessor :host
|
7
|
+
attr_accessor :ssh_timeout
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@host = UNSET_VALUE
|
11
|
+
@ssh_timeout = UNSET_VALUE
|
12
|
+
end
|
13
|
+
|
14
|
+
def finalize!
|
15
|
+
@ssh_timeout = 120 if @ssh_timeout == UNSET_VALUE
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate(machine)
|
19
|
+
errors = _detected_errors
|
20
|
+
{ 'vagrant-vsphere-ddns' => errors }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VSphereDNS
|
5
|
+
module Errors
|
6
|
+
class VSphereDDNSError < Vagrant::Errors::VagrantError
|
7
|
+
error_namespace("vagrant-vsphere-ddns.errors")
|
8
|
+
end
|
9
|
+
|
10
|
+
class IPAddrTimeout < VSphereDDNSError
|
11
|
+
error_key(:ip_addr_timeout)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
begin
|
2
|
+
require 'vagrant'
|
3
|
+
rescue LoadError
|
4
|
+
raise 'The plugin must be run within Vagrant.'
|
5
|
+
end
|
6
|
+
|
7
|
+
module VagrantPlugins
|
8
|
+
module VSphereDDNS
|
9
|
+
class Plugin < Vagrant.plugin('2')
|
10
|
+
name 'vsphere-ddns'
|
11
|
+
description 'Enables Vagrant to connect to vSphere VMs via dynamic domain names based on MAC addresses'
|
12
|
+
|
13
|
+
config(:ddns) do
|
14
|
+
require_relative 'config'
|
15
|
+
init!
|
16
|
+
Config
|
17
|
+
end
|
18
|
+
|
19
|
+
action_hook :get_ssh_info, :machine_action_get_ssh_info do |hook|
|
20
|
+
require_relative 'action'
|
21
|
+
hook.after VagrantPlugins::VSphere::Action::GetSshInfo, VagrantPlugins::VSphereDDNS::Action::action_get_ssh_info
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def self.init!
|
27
|
+
return if defined?(@_init)
|
28
|
+
I18n.load_path << File.expand_path('locales/en.yml', VagrantPlugins::VSphereDDNS.source_root)
|
29
|
+
I18n.reload!
|
30
|
+
@_init = true
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'vagrant-vsphere-ddns/plugin'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module VSphereDDNS
|
6
|
+
lib_path = Pathname.new(File.expand_path('../vagrant-vsphere-ddns', __FILE__))
|
7
|
+
autoload :Action, lib_path.join('action')
|
8
|
+
autoload :Errors, lib_path.join('errors')
|
9
|
+
|
10
|
+
# This returns the path to the source of this plugin.
|
11
|
+
#
|
12
|
+
# @return [Pathname]
|
13
|
+
def self.source_root
|
14
|
+
@source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/locales/en.yml
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
import sys
|
5
|
+
import argparse
|
6
|
+
import logging
|
7
|
+
import subprocess
|
8
|
+
|
9
|
+
if __name__=='__main__':
|
10
|
+
parser = argparse.ArgumentParser()
|
11
|
+
parser.add_argument('-d', '--debug', action='store_true', default=False)
|
12
|
+
parser.add_argument('-a','--action', choices=('commit', 'release', 'expiry'), required=True)
|
13
|
+
parser.add_argument('-i','--ip', required=True)
|
14
|
+
parser.add_argument('-m','--mac', required=True)
|
15
|
+
parser.add_argument('--key_file', required=True)
|
16
|
+
parser.add_argument('--server', default='127.0.0.1')
|
17
|
+
parser.add_argument('--ttl', type=int, default=600)
|
18
|
+
parser.add_argument('--zone', required=True)
|
19
|
+
|
20
|
+
args = parser.parse_args()
|
21
|
+
logging.basicConfig(level=(logging.DEBUG if args.debug else logging.INFO), format='%(asctime)s %(levelname)-5.5s [%(name)s] %(message)s')
|
22
|
+
logging.debug('arguments: %s' % sys.argv)
|
23
|
+
|
24
|
+
mac = ''.join([format(int(x, 16), '02x') for x in args.mac.replace('-',':').split(':')])
|
25
|
+
|
26
|
+
params = "server %s\nzone %s\n" % (args.server, args.zone)
|
27
|
+
if args.action == 'commit':
|
28
|
+
params += "update add %s.%s %d IN A %s\n" % (mac, args.zone, args.ttl, args.ip)
|
29
|
+
else:
|
30
|
+
params += "update delete %s.%s. A\n" % (mac, args.zone)
|
31
|
+
if args.debug:
|
32
|
+
params += "show\n"
|
33
|
+
params += "send\n"
|
34
|
+
|
35
|
+
logging.debug('nsupdate params: %s' % params)
|
36
|
+
ret = subprocess.call('/usr/bin/nsupdate -k %s -v << EOF\n%s\nEOF' % (args.key_file, params), shell=True)
|
37
|
+
logging.debug('nsupdate returned %d' % (ret))
|
38
|
+
sys.exit(ret)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
3
|
+
require 'vagrant-vsphere-ddns/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'vagrant-vsphere-ddns'
|
7
|
+
s.version = VagrantPlugins::VSphereDDNS::VERSION
|
8
|
+
s.authors = ['Tobias']
|
9
|
+
s.email = ['tsmolka@gmail.com']
|
10
|
+
s.homepage = 'https://github.com/tsmolka/vagrant-vsphere-ddns'
|
11
|
+
s.license = 'GPL-2.0'
|
12
|
+
s.summary = 'VMWare vSphere DDNS plugin'
|
13
|
+
s.description = 'Enables Vagrant to connect to vSphere VMs via dynamic domain names based on MAC addresses'
|
14
|
+
root_path = File.dirname(__FILE__)
|
15
|
+
s.add_dependency 'vagrant-vsphere', '~> 1.9'
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
18
|
+
s.executables = s.files.grep(/^bin\//) { |f| File.basename(f) }
|
19
|
+
s.require_path = 'lib'
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vagrant-vsphere-ddns
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tobias
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: vagrant-vsphere
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.9'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.9'
|
27
|
+
description: Enables Vagrant to connect to vSphere VMs via dynamic domain names based
|
28
|
+
on MAC addresses
|
29
|
+
email:
|
30
|
+
- tsmolka@gmail.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- ".gitignore"
|
36
|
+
- Gemfile
|
37
|
+
- README.md
|
38
|
+
- Rakefile
|
39
|
+
- lib/vagrant-vsphere-ddns.rb
|
40
|
+
- lib/vagrant-vsphere-ddns/action.rb
|
41
|
+
- lib/vagrant-vsphere-ddns/action/get_ssh_info.rb
|
42
|
+
- lib/vagrant-vsphere-ddns/action/wait_for_ip_address.rb
|
43
|
+
- lib/vagrant-vsphere-ddns/config.rb
|
44
|
+
- lib/vagrant-vsphere-ddns/errors.rb
|
45
|
+
- lib/vagrant-vsphere-ddns/plugin.rb
|
46
|
+
- lib/vagrant-vsphere-ddns/version.rb
|
47
|
+
- locales/en.yml
|
48
|
+
- scripts/dns_update.py
|
49
|
+
- vagrant-vsphere-ddns.gemspec
|
50
|
+
homepage: https://github.com/tsmolka/vagrant-vsphere-ddns
|
51
|
+
licenses:
|
52
|
+
- GPL-2.0
|
53
|
+
metadata: {}
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
requirements: []
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 2.4.5.1
|
71
|
+
signing_key:
|
72
|
+
specification_version: 4
|
73
|
+
summary: VMWare vSphere DDNS plugin
|
74
|
+
test_files: []
|