vagrant-auto_network 0.1.0 → 0.2.0

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.
data/CHANGELOG ADDED
@@ -0,0 +1,12 @@
1
+ vagrant-auto_network
2
+ ====================
3
+
4
+ 0.2.0
5
+ -----
6
+
7
+ 2013-08-07
8
+
9
+ This is a backwards compatible feature release. It reimplements the
10
+ auto_network functionality as part of the :private_network network config
11
+ method. It also implements persistent leases so that machines in different
12
+ Vagrant environments all have unique addresses.
data/README.markdown CHANGED
@@ -26,14 +26,13 @@ Usage
26
26
  node.vm.box = "centos-5-i386"
27
27
 
28
28
  node.vm.extend AutoNetwork::Mixin
29
- node.vm.auto_network!
29
+ node.vm.network :private_network, :auto_network => true
30
30
  end
31
31
 
32
32
  config.vm.define 'second' do |node|
33
33
  node.vm.box = "centos-5-i386"
34
34
 
35
- node.vm.extend AutoNetwork::Mixin
36
- node.vm.auto_network!
35
+ node.vm.network :private_network, :auto_network => true
37
36
  end
38
37
  end
39
38
 
@@ -54,8 +53,8 @@ To change this, add the following _before_ the Vagrant configuration block:
54
53
  Contact
55
54
  -------
56
55
 
57
- * Source code: https://github.com/adrienthebo/vagrant-auto\_network
58
- * Issue tracker: https://github.com/adrienthebo/vagrant-auto\_network/issues
56
+ * [Source code](https://github.com/adrienthebo/vagrant-auto_network)
57
+ * [Issue tracker](https://github.com/adrienthebo/vagrant-auto_network/issues)
59
58
 
60
59
  If you have questions or concerns about this module, contact finch on Freenode,
61
60
  or email adrien@puppetlabs.com.
data/lib/auto_network.rb CHANGED
@@ -1,13 +1,12 @@
1
- require 'auto_network/mixin'
2
-
3
1
  module AutoNetwork
4
- class << self
5
- def default_pool
6
- @default_pool ||= '10.20.1.0/24'
7
- end
8
2
 
9
- def default_pool=(pool)
10
- @default_pool = pool
11
- end
12
- end
3
+ require 'auto_network/default_pool'
4
+ extend DefaultPool
5
+
6
+ require 'auto_network/action'
7
+ require 'auto_network/mixin'
8
+ require 'auto_network/plugin'
9
+ require 'auto_network/version'
13
10
  end
11
+
12
+ I18n.load_path << File.expand_path('../templates/locales/en.yml', File.dirname(__FILE__))
@@ -0,0 +1,8 @@
1
+ module AutoNetwork
2
+ module Action
3
+ require 'auto_network/action/load_pool'
4
+ require 'auto_network/action/filter_networks'
5
+ require 'auto_network/action/release'
6
+ require 'auto_network/action/request'
7
+ end
8
+ end
@@ -0,0 +1,49 @@
1
+ require 'auto_network/action_helpers'
2
+ require 'log4r'
3
+
4
+ class AutoNetwork::Action::FilterNetworks
5
+
6
+ include AutoNetwork::ActionHelpers
7
+
8
+ def initialize(app, env)
9
+ @app, @env = app, env
10
+
11
+ @logger = Log4r::Logger.new('vagrant::auto_network::filter_networks')
12
+ end
13
+
14
+ # Convert auto_network interfaces to static private_network interfaces.
15
+ #
16
+ # @param env [Hash]
17
+ #
18
+ # @option env [AutoNetwork::Pool] auto_network_pool The global auto network pool
19
+ # @option env [Vagrant::Environment] env The Vagrant environment containing
20
+ # the active machines that need to be filtered.
21
+ #
22
+ # @return [void]
23
+ def call(env)
24
+ @env = env
25
+
26
+ @pool = @env[:auto_network_pool]
27
+ global_env = @env[:env]
28
+
29
+ machines_for_env(global_env).each do |machine|
30
+ assign_address(machine) if machine_has_address?(machine)
31
+ end
32
+
33
+ @app.call(@env)
34
+ end
35
+
36
+ private
37
+
38
+ def machines_for_env(global_env)
39
+ global_env.active_machines.map { |vm_id| global_env.machine(*vm_id) }
40
+ end
41
+
42
+ def assign_address(machine)
43
+ machine_auto_networks(machine).each do |net|
44
+ addr = @pool.address_for(machine)
45
+ @logger.info "Reassigning #{addr.inspect} to existing machine #{machine.id}"
46
+ filter_private_network(net, addr)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,50 @@
1
+ require 'auto_network'
2
+ require 'yaml'
3
+
4
+ class AutoNetwork::Action::LoadPool
5
+
6
+ def initialize(app, env)
7
+ @app, @env = app, env
8
+
9
+ @config_path = @env[:home_path].join('auto_network')
10
+ @statefile = @config_path.join('pool.yaml')
11
+ end
12
+
13
+ # Handle the loading and unloading of the auto_network pool
14
+ #
15
+ # @param env [Hash]
16
+ #
17
+ # @option env [AutoNetwork::Pool] auto_network_pool The global auto network pool
18
+ # @option env [Vagrant::Environment] env The Vagrant environment containing
19
+ # the active machines that need to be filtered.
20
+ #
21
+ # @return [void]
22
+ def call(env)
23
+ @env = env
24
+
25
+ deserialize!
26
+ @app.call(@env)
27
+ serialize!
28
+ end
29
+
30
+ private
31
+
32
+ def deserialize!
33
+ pool = nil
34
+ if @statefile.exist?
35
+ pool = YAML.load(@statefile.read)
36
+ else
37
+ range = AutoNetwork.default_pool
38
+ @env[:ui].info "No auto_network pool available, generating a pool with the range #{range}"
39
+ pool = AutoNetwork::Pool.new(range)
40
+ end
41
+ @env[:auto_network_pool] = pool
42
+ end
43
+
44
+ def serialize!
45
+ @config_path.mkpath unless @config_path.exist?
46
+
47
+ pool_data = YAML.dump(@env[:auto_network_pool])
48
+ @statefile.open('w') { |fh| fh.write(pool_data) }
49
+ end
50
+ end
@@ -0,0 +1,37 @@
1
+ require 'auto_network/action_helpers'
2
+
3
+ class AutoNetwork::Action::Release
4
+
5
+ include AutoNetwork::ActionHelpers
6
+
7
+ def initialize(app, env)
8
+ @app, @env = app, env
9
+ end
10
+
11
+ # Release auto_network IP address on VM destruction
12
+ #
13
+ # @param env [Hash]
14
+ #
15
+ # @option env [AutoNetwork::Pool] auto_network_pool The global auto network pool
16
+ # @option env [Vagrant::Machine] machine The Vagrant machine being destroyed
17
+ #
18
+ # @return [void]
19
+ def call(env)
20
+ @env = env
21
+
22
+ @machine = @env[:machine]
23
+ @pool = @env[:auto_network_pool]
24
+
25
+ release_network_addresses if machine_has_address?(@machine)
26
+
27
+ @app.call(@env)
28
+ end
29
+
30
+ private
31
+
32
+ def release_network_addresses
33
+ addr = @pool.address_for(@machine)
34
+ @env[:ui].info "Releasing #{addr.inspect} from #{@machine.id}", :prefix => true
35
+ @pool.release(@machine)
36
+ end
37
+ end
@@ -0,0 +1,39 @@
1
+ require 'auto_network/action_helpers'
2
+
3
+ class AutoNetwork::Action::Request
4
+
5
+ include AutoNetwork::ActionHelpers
6
+
7
+ def initialize(app, env)
8
+ @app, @env = app, env
9
+ end
10
+
11
+ # Request an auto_network IP address on VM creation
12
+ #
13
+ # @param env [Hash]
14
+ #
15
+ # @option env [AutoNetwork::Pool] auto_network_pool The global auto network pool
16
+ # @option env [Vagrant::Machine] machine The Vagrant machine being created
17
+ #
18
+ # @return [void]
19
+ def call(env)
20
+ @env = env
21
+
22
+ @pool = @env[:auto_network_pool]
23
+ @machine = @env[:machine]
24
+
25
+ request_address unless machine_has_address?(@machine)
26
+
27
+ @app.call(@env)
28
+ end
29
+
30
+ private
31
+
32
+ def request_address
33
+ machine_auto_networks(@machine).each do |net|
34
+ addr = @pool.request(@machine)
35
+ @env[:ui].info "Assigning #{addr.inspect} to '#{@machine.id}'", :prefix => true
36
+ filter_private_network(net, addr)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,40 @@
1
+ module AutoNetwork
2
+ module ActionHelpers
3
+
4
+ # Determine if the given machine exists and has an auto_network address
5
+ #
6
+ # @param [Vagrant::Machine]
7
+ #
8
+ # @return [true, false]
9
+ def machine_has_address?(machine)
10
+ !!(machine and @pool.address_for(machine))
11
+ end
12
+
13
+ # Fetch all private networks that are tagged for auto networking
14
+ #
15
+ # @param iface [Array<Symbol, Hash>]
16
+ #
17
+ # @return [Array<Symbol, Hash>] All auto_networks
18
+ def machine_auto_networks(machine)
19
+ machine.config.vm.networks.select do |(net_type, options)|
20
+ net_type == :private_network and options[:auto_network]
21
+ end
22
+ end
23
+
24
+ # Convert an auto network to a private network with a static IP address.
25
+ #
26
+ # This does an in-place modification of the private_network options hash
27
+ # to strip out the auto_network configuration and make this behave like a
28
+ # normal private network interface with a static IP address.
29
+ #
30
+ # @param iface [Array<Symbol, Hash>]
31
+ # @param addr [String] The static IP address to assign to the private network
32
+ #
33
+ # @return [void]
34
+ def filter_private_network(iface, addr)
35
+ opts = iface[1]
36
+ opts.delete(:auto_network)
37
+ opts[:ip] = addr
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ module AutoNetwork::DefaultPool
2
+ def default_pool
3
+ @default_pool ||= '10.20.1.0/24'
4
+ end
5
+
6
+ def default_pool=(pool)
7
+ @default_pool = pool
8
+ end
9
+ end
@@ -1,15 +1,12 @@
1
1
  require 'auto_network/pool'
2
2
 
3
3
  module AutoNetwork
4
-
5
- # Extension to vagrant VM configuration to automatically configure an
6
- # internal network.
7
- module Mixin
8
-
9
- def auto_network!
10
- pool = AutoNetwork::Pool.instance
11
- addr = pool.next
12
- network :private_network, :ip => addr
4
+ # Extension to vagrant VM configuration to automatically configure an
5
+ # internal network.
6
+ module Mixin
7
+ def auto_network!
8
+ puts "AutoNetwork::Mixin is deprecated, use config.vm.network :private_network, :auto_network => true"
9
+ network :private_network, :auto_network => true
10
+ end
13
11
  end
14
12
  end
15
- end
@@ -0,0 +1,32 @@
1
+ require 'vagrant'
2
+ require 'auto_network/action'
3
+
4
+ module AutoNetwork
5
+ class Plugin < Vagrant.plugin('2')
6
+ name 'auto_network'
7
+
8
+ description <<-DESC
9
+ This plugin adds support for automatically configuring Vagrant hostonly
10
+ networks.
11
+ DESC
12
+
13
+ action_hook('Auto network: initialize address pool') do |hook|
14
+ hook.prepend AutoNetwork::Action::LoadPool
15
+ end
16
+
17
+ action_hook('Auto network: filter private networks', :environment_load) do |hook|
18
+ action = AutoNetwork::Action::LoadPool
19
+ hook.after(action, AutoNetwork::Action::FilterNetworks)
20
+ end
21
+
22
+ action_hook('Auto network: request address', :machine_action_up) do |hook|
23
+ action = VagrantPlugins::ProviderVirtualBox::Action::Network
24
+ hook.before(action, AutoNetwork::Action::Request)
25
+ end
26
+
27
+ action_hook('Auto network: release address', :machine_action_destroy) do |hook|
28
+ action = VagrantPlugins::ProviderVirtualBox::Action::Destroy
29
+ hook.before(action, AutoNetwork::Action::Release)
30
+ end
31
+ end
32
+ end
@@ -1,39 +1,73 @@
1
- require 'auto_network'
2
-
3
- require 'ipaddress'
1
+ require 'ipaddr'
4
2
 
5
3
  module AutoNetwork
6
- class Pool
4
+ class Pool
7
5
 
8
- class PoolExhaustedError < StandardError; end
6
+ class PoolExhaustedError < Vagrant::Errors::VagrantError
7
+ error_key(:pool_exhausted, 'vagrant_auto_network')
8
+ end
9
9
 
10
- # Provide a single instance of this class
11
- #
12
- # @return [AutoNetwork::Pool]
13
- def self.instance
14
- @myself ||= new
15
- end
10
+ # @param network_addr [String] The network address range to use as the
11
+ # address pool.
12
+ def initialize(network_range)
13
+ @network_range = network_range
14
+ generate_pool
15
+ end
16
16
 
17
- # @param addr [String] The network address range to use as the address pool.
18
- # Defaults to `AutoNetwork.default_pool`
19
- def initialize(addr = AutoNetwork.default_pool)
20
- @addr = addr
21
- @network = IPAddress.parse(addr)
17
+ # Retrieve an IP address for the given machine. If a machine already has
18
+ # an IP address requested, then return that.
19
+ #
20
+ # @param machine [Vagrant::Machine]
21
+ def request(machine)
22
+ if (address = address_for(machine))
23
+ return address
24
+ elsif (address = next_available_lease)
25
+ @pool[address] = machine.id
26
+ return address
27
+ else
28
+ raise PoolExhaustedError,
29
+ :name => machine.name,
30
+ :network => @network_range
31
+ end
32
+ end
22
33
 
23
- @range = @network.hosts
24
- # Drop the first IP address as it should be reserved for the host system
25
- @range.shift
26
- end
34
+ # Release an IP address associated with a machine
35
+ #
36
+ # @param machine [Vagrant::Machine]
37
+ def release(machine)
38
+ if (address = address_for(machine))
39
+ @pool[address] = nil
40
+ end
41
+ end
27
42
 
28
- # @return [String] The string representation of the next available address
29
- # @raise [PoolExhaustedError] There are no remaining addresses in the pool.
30
- def next
31
- if @range.empty?
32
- raise PoolExhaustedError, "No addresses remaining in network address pool #{addr.inspect}"
43
+ def address_for(machine)
44
+ return nil if machine.id.nil?
45
+ next_addr, _ = @pool.find { |(addr, id)| machine.id == id }
46
+
47
+ next_addr
33
48
  end
34
49
 
35
- addr = @range.shift
36
- addr.address
50
+ private
51
+
52
+ def next_available_lease
53
+ next_addr, _ = @pool.find { |(addr, id)| id.nil? }
54
+
55
+ next_addr
56
+ end
57
+
58
+ def generate_pool
59
+ network = IPAddr.new(@network_range)
60
+ addresses = network.to_range.to_a
61
+
62
+ addresses.delete_at(-1) # Strip out the broadcast address
63
+ addresses.delete_at(1) # And the first address (should be used by the host)
64
+ addresses.delete_at(0) # And the network address
65
+
66
+ @pool = {}
67
+
68
+ addresses.map(&:to_s).each do |addr|
69
+ @pool[addr] = nil
70
+ end
71
+ end
37
72
  end
38
73
  end
39
- end
@@ -1,3 +1,3 @@
1
1
  module AutoNetwork
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -0,0 +1,9 @@
1
+ ---
2
+ en:
3
+ vagrant_auto_network:
4
+ pool_exhausted: |-
5
+ The machine '%{name}' tried to get an automatic network address, but all
6
+ ip addresses in the network range '%{network}' have been used. This is
7
+ probably due to VMs being deleted outside of Vagrant. Check the
8
+ auto_network pool configuration file and remove the machine IDs from
9
+ addresses that are no longer in use, or add addresses to the pool.
@@ -13,8 +13,8 @@ Gem::Specification.new do |gem|
13
13
 
14
14
  gem.summary = "Automatically create an internal network for all vagrant boxes"
15
15
 
16
- gem.add_dependency 'ipaddress'
17
-
18
16
  gem.files = %x{git ls-files -z}.split("\0")
19
17
  gem.require_path = 'lib'
18
+
19
+ gem.license = 'Apache 2.0'
20
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-auto_network
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,40 +9,35 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-07 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: ipaddress
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
12
+ date: 2013-08-08 00:00:00.000000000 Z
13
+ dependencies: []
30
14
  description:
31
15
  email: adrien@somethingsinistral.net
32
16
  executables: []
33
17
  extensions: []
34
18
  extra_rdoc_files: []
35
19
  files:
20
+ - CHANGELOG
36
21
  - Gemfile
37
22
  - README.markdown
38
23
  - lib/auto_network.rb
24
+ - lib/auto_network/action.rb
25
+ - lib/auto_network/action/filter_networks.rb
26
+ - lib/auto_network/action/load_pool.rb
27
+ - lib/auto_network/action/release.rb
28
+ - lib/auto_network/action/request.rb
29
+ - lib/auto_network/action_helpers.rb
30
+ - lib/auto_network/default_pool.rb
39
31
  - lib/auto_network/mixin.rb
32
+ - lib/auto_network/plugin.rb
40
33
  - lib/auto_network/pool.rb
41
34
  - lib/auto_network/version.rb
42
35
  - lib/vagrant-auto_network.rb
36
+ - templates/locales/en.yml
43
37
  - vagrant-auto_network.gemspec
44
38
  homepage: https://github.com/adrienthebo/vagrant-auto_network
45
- licenses: []
39
+ licenses:
40
+ - Apache 2.0
46
41
  post_install_message:
47
42
  rdoc_options: []
48
43
  require_paths: