Skip to content
This repository has been archived by the owner on Feb 11, 2022. It is now read-only.

Additional Network Interfaces Support #358

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
38 changes: 34 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ This provider exposes quite a few provider-specific configuration options:
for credentials.
* `block_device_mapping` - Amazon EC2 Block Device Mapping Property
* `elb` - The ELB name to attach to the instance.
* `additional_network_interfaces` - An array of the extra network interfaces to create and attach once the machine is up

These can be set like typical provider-specific configuration:

Expand Down Expand Up @@ -265,6 +266,38 @@ Vagrant.configure("2") do |config|
end
```

### Additional Network Adapters

You can add extra network adapters to your instance after boot.

```ruby
Vagrant.configure("2") do |config|
# ... other stuff

config.vm.provider "aws" do |aws|

# subnet & security groups for primary network interface with device index 0
aws.subnet_id = 'subnet-caba8084'
aws.security_groups = 'sg-edb6e09b'

# add additonal interfaces after boot
aws.additional_network_interfaces = [
{
:device_index => 1,
:subnet_id => 'subnet-2f76b4e7',
:security_groups => ['sg-b2a58ce3', 'sg-008f7950'],
:private_ip_address => '172.16.110.200' #optional
},
{
:device_index => 2,
:subnet_id => 'subnet-e9725abc',
:security_groups => ['sg-0ded8ff6']
}
]
end
end
```

## Development

To work on the `vagrant-aws` plugin, clone this repository out, and use
Expand All @@ -283,10 +316,7 @@ $ bundle exec rake
If those pass, you're ready to start developing the plugin. You can test
the plugin without installing it into your Vagrant environment by just
creating a `Vagrantfile` in the top level of this directory (it is gitignored)
and add the following line to your `Vagrantfile`
```ruby
Vagrant.require_plugin "vagrant-aws"
```

Use bundler to execute Vagrant:
```
$ bundle exec vagrant up --provider=aws
Expand Down
8 changes: 6 additions & 2 deletions lib/vagrant-aws/action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ def self.action_destroy
next
end
b3.use ConnectAWS
b3.use ElbDeregisterInstance
b3.use TerminateInstance
b3.use DestroyAdditionalNetworkInterfaces
b3.use ElbDeregisterInstance
b3.use TerminateInstance
b3.use ProvisionerCleanup if defined?(ProvisionerCleanup)
end
else
Expand Down Expand Up @@ -157,6 +158,7 @@ def self.action_up
else
b1.use action_prepare_boot
b1.use RunInstance # launch a new instance
b1.use RegisterAdditionalNetworkInterfaces
end
end
end
Expand Down Expand Up @@ -204,6 +206,8 @@ def self.action_reload
autoload :WarnNetworks, action_root.join("warn_networks")
autoload :ElbRegisterInstance, action_root.join("elb_register_instance")
autoload :ElbDeregisterInstance, action_root.join("elb_deregister_instance")
autoload :RegisterAdditionalNetworkInterfaces, action_root.join("network_adapters_register")
autoload :DestroyAdditionalNetworkInterfaces, action_root.join("network_adapters_destroy")
end
end
end
31 changes: 31 additions & 0 deletions lib/vagrant-aws/action/network_adapters_destroy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require 'vagrant-aws/util/network_adapters'

module VagrantPlugins
module AWS
module Action
class DestroyAdditionalNetworkInterfaces
include NetworkAdapter

def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant_aws::action::network_adapters_register")
end

def call(env)

interfaces = env[:machine].provider_config.additional_network_interfaces

interfaces.each do |intf|
env[:ui].info(I18n.t("vagrant_aws.destroy_network_interface"))
env[:ui].info(" -- Device Index: #{intf[:device_index]}")
env[:ui].info(" -- Attached To: #{env[:machine].id}")
destroy_adapter env, intf[:device_index], env[:machine].id
end

@app.call(env)

end
end
end
end
end
33 changes: 33 additions & 0 deletions lib/vagrant-aws/action/network_adapters_register.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require 'vagrant-aws/util/network_adapters'

module VagrantPlugins
module AWS
module Action
class RegisterAdditionalNetworkInterfaces
include NetworkAdapter

def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant_aws::action::network_adapters_register")
end

def call(env)

@app.call(env)

interfaces = env[:machine].provider_config.additional_network_interfaces

interfaces.each do |intf|
env[:ui].info(I18n.t("vagrant_aws.creating_network_interface"))
env[:ui].info(" -- Device Index: #{intf[:device_index]}")
env[:ui].info(" -- Subnet ID: #{intf[:subnet_id]}")
env[:ui].info(" -- Security Groups: #{intf[:security_groups]}")
env[:ui].info(" -- IP: #{intf[:private_ip_address]}")
register_adapter env, intf[:device_index], intf[:subnet_id], intf[:security_groups], intf[:private_ip_address], env[:machine].id
end

end
end
end
end
end
4 changes: 2 additions & 2 deletions lib/vagrant-aws/action/run_instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def call(env)
iam_instance_profile_name = region_config.iam_instance_profile_name
monitoring = region_config.monitoring
ebs_optimized = region_config.ebs_optimized
associate_public_ip = region_config.associate_public_ip
associate_public_ip = region_config.associate_public_ip

# If there is no keypair then warn the user
if !keypair
Expand Down Expand Up @@ -90,7 +90,7 @@ def call(env)
:instance_initiated_shutdown_behavior => terminate_on_shutdown == true ? "terminate" : nil,
:monitoring => monitoring,
:ebs_optimized => ebs_optimized,
:associate_public_ip => associate_public_ip
:associate_public_ip => associate_public_ip
}
if !security_groups.empty?
security_group_key = options[:subnet_id].nil? ? :groups : :security_group_ids
Expand Down
9 changes: 8 additions & 1 deletion lib/vagrant-aws/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ class Config < Vagrant.plugin("2", :config)
# @return [String]
attr_accessor :elb

# The additional network adapters which should
# be attached to instance
#
# @return [Array<Hash>]
attr_accessor :additional_network_interfaces

def initialize(region_specific=false)
@access_key_id = UNSET_VALUE
@ami = UNSET_VALUE
Expand Down Expand Up @@ -190,6 +196,7 @@ def initialize(region_specific=false)
@ebs_optimized = UNSET_VALUE
@associate_public_ip = UNSET_VALUE
@elb = UNSET_VALUE
@additional_network_interfaces = []

# Internal state (prefix with __ so they aren't automatically
# merged)
Expand Down Expand Up @@ -389,7 +396,7 @@ def validate(machine)
end

errors << I18n.interpolate("vagrant_aws.config.ami_required", :region => @region) if config.ami.nil?
end
end

{ "AWS Provider" => errors }
end
Expand Down
66 changes: 66 additions & 0 deletions lib/vagrant-aws/util/network_adapters.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
module VagrantPlugins
module AWS
module NetworkAdapter

def ip_attributes(ips)
return {} if ips.nil?

attrs = { 'PrivateIpAddresses.0.Primary' => true }

if ips.kind_of?(Array)
ips.each_with_index do |ip, i|
attrs["PrivateIpAddresses.#{i}.PrivateIpAddress"] = ip
end
else
attrs["PrivateIpAddresses.0.PrivateIpAddress"] = ips
end

attrs
end

def security_group_attributes(security_groups)
attrs = {}

if security_groups.kind_of?(Array)
security_groups.each_with_index do |sid, i|
attrs["SecurityGroupId.#{i + 1}"] = sid
end
else
attrs["SecurityGroupId.1"] = security_groups
end

attrs
end

def register_adapter(env, device_index, subnet_id, security_groups, private_ip_address, instance_id)

options = {}
options.merge! security_group_attributes(security_groups)
options.merge! ip_attributes(private_ip_address)

interface = env[:aws_compute].create_network_interface(
subnet_id,
options
).body['networkInterface']

env[:aws_compute].attach_network_interface(interface['networkInterfaceId'], instance_id, device_index)
end

def destroy_adapter(env, device_index, instance_id)
interface = env[:aws_compute].network_interfaces.all('attachment.instance-id' => instance_id, 'attachment.device-index' => device_index ).first

if interface.nil?
return
end

if !interface.attachment.nil? && interface.attachment != {}
env[:aws_compute].detach_network_interface(interface.attachment['attachmentId'], true)
interface.wait_for { attachment.nil? || attachment == {} }
end

interface.destroy
end

end
end
end
4 changes: 4 additions & 0 deletions locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ en:
will_not_destroy: |-
The instance '%{name}' will not be destroyed, since the confirmation
was declined.
creating_network_interface: |-
Creating additional network interface with the following settings...
destroy_network_interface: |-
Destroying additional network interface...

config:
access_key_id_required: |-
Expand Down
1 change: 1 addition & 0 deletions spec/vagrant-aws/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
its("monitoring") { should == false }
its("ebs_optimized") { should == false }
its("associate_public_ip") { should == false }
its("additional_network_interfaces") { should == [] }
end

describe "overriding defaults" do
Expand Down