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

Additional Network Interfaces Support [Ported #358 to latest codebase] #485

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,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
* `unregister_elb_from_az` - Removes the ELB from the AZ on removal of the last instance if true (default). In non default VPC this has to be false.
* `terminate_on_shutdown` - Indicates whether an instance stops or terminates
when you initiate shutdown from the instance.
Expand Down Expand Up @@ -298,6 +299,39 @@ 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 Down
7 changes: 5 additions & 2 deletions lib/vagrant-aws/action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ def self.action_destroy
b3.use MessageNotCreated
next
end

b3.use ConnectAWS
b3.use DestroyAdditionalNetworkInterfaces
b3.use ElbDeregisterInstance
b3.use ProvisionerCleanup, :before if defined?(ProvisionerCleanup)
b3.use TerminateInstance
b3.use ProvisionerCleanup if defined?(ProvisionerCleanup)
end
else
b2.use MessageWillNotDestroy
Expand Down Expand Up @@ -158,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 @@ -205,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
8 changes: 8 additions & 0 deletions lib/vagrant-aws/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,13 @@ class Config < Vagrant.plugin("2", :config)
# @return [String]
attr_accessor :aws_profile

# 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 @@ -233,6 +240,7 @@ def initialize(region_specific=false)
@tenancy = UNSET_VALUE
@aws_dir = UNSET_VALUE
@aws_profile = UNSET_VALUE
@additional_network_interfaces = []

# Internal state (prefix with __ so they aren't automatically
# merged)
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 @@ -62,6 +62,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 @@ -58,6 +58,7 @@
its("associate_public_ip") { should == false }
its("unregister_elb_from_az") { should == true }
its("tenancy") { should == "default" }
its("additional_network_interfaces") { should == [] }
end

describe "overriding defaults" do
Expand Down