bosh_aws_cpi 0.7.0 → 1.5.0.pre.1113

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/README.md +22 -19
  2. data/bin/bosh_aws_console +1 -13
  3. data/lib/bosh_aws_cpi.rb +1 -1
  4. data/lib/cloud/aws/aki_picker.rb +7 -7
  5. data/lib/cloud/aws/availability_zone_selector.rb +40 -0
  6. data/lib/cloud/aws/cloud.rb +359 -476
  7. data/lib/cloud/aws/dynamic_network.rb +0 -6
  8. data/lib/cloud/aws/helpers.rb +10 -68
  9. data/lib/cloud/aws/instance_manager.rb +171 -0
  10. data/lib/cloud/aws/manual_network.rb +26 -0
  11. data/lib/cloud/aws/network_configurator.rb +33 -62
  12. data/lib/cloud/aws/resource_wait.rb +189 -0
  13. data/lib/cloud/aws/stemcell.rb +68 -0
  14. data/lib/cloud/aws/stemcell_creator.rb +114 -0
  15. data/lib/cloud/aws/tag_manager.rb +30 -0
  16. data/lib/cloud/aws/version.rb +1 -1
  17. data/lib/cloud/aws/vip_network.rb +9 -7
  18. data/lib/cloud/aws.rb +11 -2
  19. data/scripts/stemcell-copy.sh +37 -0
  20. metadata +45 -81
  21. data/Rakefile +0 -50
  22. data/lib/cloud/aws/registry_client.rb +0 -109
  23. data/spec/assets/stemcell-copy +0 -31
  24. data/spec/integration/cpi_test.rb +0 -78
  25. data/spec/spec_helper.rb +0 -121
  26. data/spec/unit/aki_picker_spec.rb +0 -29
  27. data/spec/unit/attach_disk_spec.rb +0 -143
  28. data/spec/unit/cloud_spec.rb +0 -32
  29. data/spec/unit/configure_networks_spec.rb +0 -113
  30. data/spec/unit/create_disk_spec.rb +0 -73
  31. data/spec/unit/create_stemcell_spec.rb +0 -113
  32. data/spec/unit/create_vm_spec.rb +0 -249
  33. data/spec/unit/delete_disk_spec.rb +0 -34
  34. data/spec/unit/delete_stemcell_spec.rb +0 -29
  35. data/spec/unit/delete_vm_spec.rb +0 -25
  36. data/spec/unit/detach_disk_spec.rb +0 -63
  37. data/spec/unit/helpers_spec.rb +0 -64
  38. data/spec/unit/network_configurator_spec.rb +0 -57
  39. data/spec/unit/reboot_vm_spec.rb +0 -38
  40. data/spec/unit/set_vm_metadata_spec.rb +0 -30
  41. data/spec/unit/validate_deployment_spec.rb +0 -16
@@ -1,78 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- require File.expand_path("../../spec_helper", __FILE__)
4
-
5
- require "tempfile"
6
-
7
- describe Bosh::AwsCloud::Cloud do
8
-
9
- before(:each) do
10
- unless ENV["CPI_CONFIG_FILE"]
11
- raise "Please provide CPI_CONFIG_FILE environment variable"
12
- end
13
- @config = YAML.load_file(ENV["CPI_CONFIG_FILE"])
14
- @logger = Logger.new(STDOUT)
15
- end
16
-
17
- let(:cpi) do
18
- cpi = Bosh::AwsCloud::Cloud.new(@config)
19
- cpi.logger = @logger
20
-
21
- # As we inject the configuration file from the outside, we don't care
22
- # about spinning up the registry ourselves. However we don't want to bother
23
- # EC2 at all if registry is not working, so just in case we perform a test
24
- # health check against whatever has been provided.
25
- cpi.registry.update_settings("foo", { "bar" => "baz" })
26
- cpi.registry.read_settings("foo").should == { "bar" => "baz"}
27
-
28
- cpi
29
- end
30
-
31
- it "exercises a VM lifecycle" do
32
- instance_id = cpi.create_vm(
33
- "agent-007", "ami-809a48e9",
34
- { "instance_type" => "m1.small" },
35
- { "default" => { "type" => "dynamic" }},
36
- [], { "key" => "value" })
37
-
38
- instance_id.should_not be_nil
39
-
40
- settings = cpi.registry.read_settings(instance_id)
41
- settings["vm"].should be_a(Hash)
42
- settings["vm"]["name"].should_not be_nil
43
- settings["agent_id"].should == "agent-007"
44
- settings["networks"].should == { "default" => { "type" => "dynamic" }}
45
- settings["disks"].should == {
46
- "system" => "/dev/sda",
47
- "ephemeral" => "/dev/sdb",
48
- "persistent" => {}
49
- }
50
-
51
- settings["env"].should == { "key" => "value" }
52
-
53
- volume_id = cpi.create_disk(2048)
54
- volume_id.should_not be_nil
55
-
56
- cpi.attach_disk(instance_id, volume_id)
57
- settings = cpi.registry.read_settings(instance_id)
58
- settings["disks"]["persistent"].should == { volume_id => "/dev/sdf" }
59
-
60
- cpi.detach_disk(instance_id, volume_id)
61
- settings = cpi.registry.read_settings(instance_id)
62
- settings["disks"]["persistent"].should == {}
63
-
64
- # TODO: test configure_networks (need an elastic IP at hand for that)
65
-
66
- cpi.delete_vm(instance_id)
67
- cpi.delete_disk(volume_id)
68
-
69
- # Test below would fail: EC2 still reports the instance as 'terminated'
70
- # for some time.
71
- # cpi.ec2.instances[instance_id].should be_nil
72
-
73
- expect {
74
- cpi.registry.read_settings(instance_id)
75
- }.to raise_error(/HTTP 404/)
76
- end
77
-
78
- end
data/spec/spec_helper.rb DELETED
@@ -1,121 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
4
-
5
- require "rubygems"
6
- require "bundler"
7
- Bundler.setup(:default, :test)
8
-
9
- require "rspec"
10
- require "tmpdir"
11
-
12
- require "cloud/aws"
13
-
14
- class AwsConfig
15
- attr_accessor :db, :logger, :uuid
16
- end
17
-
18
- aws_config = AwsConfig.new
19
- aws_config.db = nil # AWS CPI doesn't need DB
20
- aws_config.logger = Logger.new(StringIO.new)
21
- aws_config.logger.level = Logger::DEBUG
22
-
23
- Bosh::Clouds::Config.configure(aws_config)
24
-
25
- MOCK_AWS_ACCESS_KEY_ID = "foo"
26
- MOCK_AWS_SECRET_ACCESS_KEY = "bar"
27
-
28
- def internal_to(*args, &block)
29
- example = describe *args, &block
30
- klass = args[0]
31
- if klass.is_a? Class
32
- saved_private_instance_methods = klass.private_instance_methods
33
- example.before do
34
- klass.class_eval { public *saved_private_instance_methods }
35
- end
36
- example.after do
37
- klass.class_eval { private *saved_private_instance_methods }
38
- end
39
- end
40
- end
41
-
42
- def mock_cloud_options
43
- {
44
- "aws" => {
45
- "access_key_id" => MOCK_AWS_ACCESS_KEY_ID,
46
- "secret_access_key" => MOCK_AWS_SECRET_ACCESS_KEY
47
- },
48
- "registry" => {
49
- "endpoint" => "localhost:42288",
50
- "user" => "admin",
51
- "password" => "admin"
52
- },
53
- "agent" => {
54
- "foo" => "bar",
55
- "baz" => "zaz"
56
- }
57
- }
58
- end
59
-
60
- def make_cloud(options = nil)
61
- Bosh::AwsCloud::Cloud.new(options || mock_cloud_options)
62
- end
63
-
64
- def mock_registry(endpoint = "http://registry:3333")
65
- registry = mock("registry", :endpoint => endpoint)
66
- Bosh::AwsCloud::RegistryClient.stub!(:new).and_return(registry)
67
- registry
68
- end
69
-
70
- def mock_cloud(options = nil)
71
- ec2 = mock_ec2
72
- AWS::EC2.stub(:new).and_return(ec2)
73
-
74
- yield ec2 if block_given?
75
-
76
- Bosh::AwsCloud::Cloud.new(options || mock_cloud_options)
77
- end
78
-
79
- def mock_ec2
80
- ec2 = double(AWS::EC2,
81
- :instances => double("instances"),
82
- :volumes => double("volumes"),
83
- :images =>double("images"))
84
-
85
- yield ec2 if block_given?
86
-
87
- ec2
88
- end
89
-
90
- def dynamic_network_spec
91
- {
92
- "type" => "dynamic",
93
- "cloud_properties" => {
94
- "security_groups" => %w[default]
95
- }
96
- }
97
- end
98
-
99
- def vip_network_spec
100
- {
101
- "type" => "vip",
102
- "ip" => "10.0.0.1"
103
- }
104
- end
105
-
106
- def combined_network_spec
107
- {
108
- "network_a" => dynamic_network_spec,
109
- "network_b" => vip_network_spec
110
- }
111
- end
112
-
113
- def resource_pool_spec
114
- {
115
- "key_name" => "test_key",
116
- "availability_zone" => "foobar-1a",
117
- "instance_type" => "m3.zb"
118
- }
119
- end
120
-
121
-
@@ -1,29 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Bosh::AwsCloud::AKIPicker do
4
- let(:akis) {
5
- [
6
- double("image-1", :root_device_name => "/dev/sda1",
7
- :image_location => "pv-grub-hd00_1.03-x86_64.gz",
8
- :image_id => "aki-b4aa75dd"),
9
- double("image-2", :root_device_name => "/dev/sda1",
10
- :image_location => "pv-grub-hd00_1.02-x86_64.gz",
11
- :image_id => "aki-b4aa75d0")
12
- ]
13
- }
14
- let(:logger) {double("logger", :info => nil)}
15
- let(:picker) {Bosh::AwsCloud::AKIPicker.new(double("ec2"))}
16
-
17
- it "should pick the AKI with the highest version" do
18
- picker.should_receive(:logger).and_return(logger)
19
- picker.should_receive(:fetch_akis).and_return(akis)
20
- picker.pick("x86_64", "/dev/sda1").should == "aki-b4aa75dd"
21
- end
22
-
23
- it "should raise an error when it can't pick an AKI" do
24
- picker.should_receive(:fetch_akis).and_return(akis)
25
- expect {
26
- picker.pick("foo", "bar")
27
- }.to raise_error Bosh::Clouds::CloudError, "unable to find AKI"
28
- end
29
- end
@@ -1,143 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- require File.expand_path("../../spec_helper", __FILE__)
4
-
5
- describe Bosh::AwsCloud::Cloud do
6
-
7
- before(:each) do
8
- @registry = mock_registry
9
- end
10
-
11
- it "attaches EC2 volume to an instance" do
12
- instance = double("instance", :id => "i-test")
13
- volume = double("volume", :id => "v-foobar")
14
- attachment = double("attachment", :device => "/dev/sdf")
15
-
16
- cloud = mock_cloud do |ec2|
17
- ec2.instances.should_receive(:[]).with("i-test").and_return(instance)
18
- ec2.volumes.should_receive(:[]).with("v-foobar").and_return(volume)
19
- end
20
-
21
- volume.should_receive(:attach_to).
22
- with(instance, "/dev/sdf").and_return(attachment)
23
-
24
- instance.should_receive(:block_device_mappings).and_return({})
25
-
26
- cloud.should_receive(:wait_resource).with(attachment, :attached)
27
-
28
- old_settings = { "foo" => "bar" }
29
- new_settings = {
30
- "foo" => "bar",
31
- "disks" => {
32
- "persistent" => {
33
- "v-foobar" => "/dev/sdf"
34
- }
35
- }
36
- }
37
-
38
- @registry.should_receive(:read_settings).
39
- with("i-test").
40
- and_return(old_settings)
41
-
42
- @registry.should_receive(:update_settings).with("i-test", new_settings)
43
-
44
- cloud.attach_disk("i-test", "v-foobar")
45
- end
46
-
47
- it "picks available device name" do
48
- instance = double("instance", :id => "i-test")
49
- volume = double("volume", :id => "v-foobar")
50
- attachment = double("attachment", :device => "/dev/sdh")
51
-
52
- cloud = mock_cloud do |ec2|
53
- ec2.instances.should_receive(:[]).with("i-test").and_return(instance)
54
- ec2.volumes.should_receive(:[]).with("v-foobar").and_return(volume)
55
- end
56
-
57
- instance.should_receive(:block_device_mappings).
58
- and_return({ "/dev/sdf" => "foo", "/dev/sdg" => "bar" })
59
-
60
- volume.should_receive(:attach_to).
61
- with(instance, "/dev/sdh").and_return(attachment)
62
-
63
- cloud.should_receive(:wait_resource).with(attachment, :attached)
64
-
65
- old_settings = { "foo" => "bar" }
66
- new_settings = {
67
- "foo" => "bar",
68
- "disks" => {
69
- "persistent" => {
70
- "v-foobar" => "/dev/sdh"
71
- }
72
- }
73
- }
74
-
75
- @registry.should_receive(:read_settings).
76
- with("i-test").
77
- and_return(old_settings)
78
-
79
- @registry.should_receive(:update_settings).with("i-test", new_settings)
80
-
81
- cloud.attach_disk("i-test", "v-foobar")
82
- end
83
-
84
- it "picks available device name" do
85
- instance = double("instance", :id => "i-test")
86
- volume = double("volume", :id => "v-foobar")
87
- attachment = double("attachment", :device => "/dev/sdh")
88
-
89
- cloud = mock_cloud do |ec2|
90
- ec2.instances.should_receive(:[]).with("i-test").and_return(instance)
91
- ec2.volumes.should_receive(:[]).with("v-foobar").and_return(volume)
92
- end
93
-
94
- instance.should_receive(:block_device_mappings).
95
- and_return({ "/dev/sdf" => "foo", "/dev/sdg" => "bar" })
96
-
97
- volume.should_receive(:attach_to).
98
- with(instance, "/dev/sdh").and_return(attachment)
99
-
100
- cloud.should_receive(:wait_resource).with(attachment, :attached)
101
-
102
- old_settings = { "foo" => "bar" }
103
- new_settings = {
104
- "foo" => "bar",
105
- "disks" => {
106
- "persistent" => {
107
- "v-foobar" => "/dev/sdh"
108
- }
109
- }
110
- }
111
-
112
- @registry.should_receive(:read_settings).
113
- with("i-test").
114
- and_return(old_settings)
115
-
116
- @registry.should_receive(:update_settings).with("i-test", new_settings)
117
-
118
- cloud.attach_disk("i-test", "v-foobar")
119
- end
120
-
121
- it "raises an error when sdf..sdp are all reserved" do
122
- instance = double("instance", :id => "i-test")
123
- volume = double("volume", :id => "v-foobar")
124
-
125
- cloud = mock_cloud do |ec2|
126
- ec2.instances.should_receive(:[]).with("i-test").and_return(instance)
127
- ec2.volumes.should_receive(:[]).with("v-foobar").and_return(volume)
128
- end
129
-
130
- all_mappings = ("f".."p").inject({}) do |hash, char|
131
- hash["/dev/sd#{char}"] = "foo"
132
- hash
133
- end
134
-
135
- instance.should_receive(:block_device_mappings).
136
- and_return(all_mappings)
137
-
138
- expect {
139
- cloud.attach_disk("i-test", "v-foobar")
140
- }.to raise_error(Bosh::Clouds::CloudError, /too many disks attached/)
141
- end
142
-
143
- end
@@ -1,32 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- require File.expand_path("../../spec_helper", __FILE__)
4
-
5
- describe Bosh::AwsCloud::Cloud do
6
-
7
- describe "creating via provider" do
8
-
9
- it "can be created using Bosh::Cloud::Provider" do
10
- cloud = Bosh::Clouds::Provider.create(:aws, mock_cloud_options)
11
- cloud.should be_an_instance_of(Bosh::AwsCloud::Cloud)
12
- end
13
-
14
- end
15
-
16
- internal_to Bosh::AwsCloud::Cloud do
17
-
18
- it "should not find stemcell-copy" do
19
- cloud = Bosh::Clouds::Provider.create(:aws, mock_cloud_options)
20
- cloud.has_stemcell_copy("/usr/bin:/usr/sbin").should be_nil
21
- end
22
-
23
- it "should find stemcell-copy" do
24
- cloud = Bosh::Clouds::Provider.create(:aws, mock_cloud_options)
25
- path = ENV["PATH"]
26
- path += ":#{File.expand_path('../../assets', __FILE__)}"
27
- cloud.has_stemcell_copy(path).should_not be_nil
28
- end
29
-
30
- end
31
-
32
- end
@@ -1,113 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- require File.expand_path("../../spec_helper", __FILE__)
4
-
5
- describe Bosh::AwsCloud::Cloud do
6
-
7
- before(:each) do
8
- @registry = mock_registry
9
- end
10
-
11
- it "forces recreation when security groups differ" do
12
- sec_grp = double("security_group", :name => "newgroup")
13
- instance = double("instance",
14
- :id => "i-foobar",
15
- :security_groups => [sec_grp])
16
-
17
- cloud = mock_cloud do |ec2|
18
- ec2.instances.stub(:[]).
19
- with("i-foobar").
20
- and_return(instance)
21
- end
22
-
23
- lambda {
24
- cloud.configure_networks("i-foobar", combined_network_spec)
25
- }.should raise_error Bosh::Clouds::NotSupported
26
- end
27
-
28
- it "adds elastic ip from to the instance for vip network" do
29
- sec_grp = double("security_group", :name => "default")
30
- instance = double("instance",
31
- :id => "i-foobar",
32
- :security_groups => [sec_grp])
33
-
34
- cloud = mock_cloud do |ec2|
35
- ec2.instances.stub(:[]).
36
- with("i-foobar").
37
- and_return(instance)
38
- end
39
-
40
- old_settings = { "foo" => "bar", "networks" => "baz" }
41
- new_settings = { "foo" => "bar", "networks" => combined_network_spec }
42
-
43
- @registry.should_receive(:read_settings).
44
- with("i-foobar").
45
- and_return(old_settings)
46
-
47
- @registry.should_receive(:update_settings).with("i-foobar", new_settings)
48
-
49
- instance.should_receive(:associate_elastic_ip).with("10.0.0.1")
50
-
51
- cloud.configure_networks("i-foobar", combined_network_spec)
52
- end
53
-
54
- it "removes elastic ip from the instance if vip network is gone" do
55
- sec_grp = double("security_group", :name => "default")
56
- instance = double("instance",
57
- :id => "i-foobar",
58
- :security_groups => [sec_grp])
59
-
60
- cloud = mock_cloud do |ec2|
61
- ec2.instances.stub(:[]).
62
- with("i-foobar").
63
- and_return(instance)
64
- end
65
-
66
- instance.should_receive(:elastic_ip).and_return("10.0.0.1")
67
- instance.should_receive(:disassociate_elastic_ip)
68
-
69
- old_settings = { "foo" => "bar", "networks" => combined_network_spec }
70
- new_settings = {
71
- "foo" => "bar",
72
- "networks" => {
73
- "net_a" => dynamic_network_spec
74
- }
75
- }
76
-
77
- @registry.should_receive(:read_settings).
78
- with("i-foobar").
79
- and_return(old_settings)
80
-
81
- @registry.should_receive(:update_settings).with("i-foobar", new_settings)
82
-
83
- cloud.configure_networks("i-foobar", "net_a" => dynamic_network_spec)
84
- end
85
-
86
- it "performs network sanity check" do
87
- expect {
88
- mock_cloud.configure_networks("i-foobar", "net_a" => vip_network_spec)
89
- }.to raise_error(Bosh::Clouds::CloudError,
90
- "At least one dynamic network should be defined")
91
-
92
- expect {
93
- mock_cloud.configure_networks("i-foobar",
94
- "net_a" => vip_network_spec,
95
- "net_b" => vip_network_spec)
96
- }.to raise_error(Bosh::Clouds::CloudError,
97
- /More than one vip network/)
98
-
99
- expect {
100
- mock_cloud.configure_networks("i-foobar",
101
- "net_a" => dynamic_network_spec,
102
- "net_b" => dynamic_network_spec)
103
- }.to raise_error(Bosh::Clouds::CloudError,
104
- /More than one dynamic network/)
105
-
106
- expect {
107
- mock_cloud.configure_networks("i-foobar",
108
- "net_a" => { "type" => "foo" })
109
- }.to raise_error(Bosh::Clouds::CloudError,
110
- /Invalid network type `foo'/)
111
- end
112
-
113
- end
@@ -1,73 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- require File.expand_path("../../spec_helper", __FILE__)
4
-
5
- describe Bosh::AwsCloud::Cloud do
6
-
7
- it "creates an EC2 volume" do
8
- disk_params = {
9
- :size => 2,
10
- :availability_zone => "us-east-1a"
11
- }
12
-
13
- volume = double("volume", :id => "v-foobar")
14
-
15
- cloud = mock_cloud do |ec2|
16
- ec2.volumes.should_receive(:create).with(disk_params).and_return(volume)
17
- end
18
-
19
- cloud.should_receive(:wait_resource).with(volume, :available)
20
-
21
- cloud.create_disk(2048).should == "v-foobar"
22
- end
23
-
24
- it "rounds up disk size" do
25
- disk_params = {
26
- :size => 3,
27
- :availability_zone => "us-east-1a"
28
- }
29
-
30
- volume = double("volume", :id => "v-foobar")
31
-
32
- cloud = mock_cloud do |ec2|
33
- ec2.volumes.should_receive(:create).with(disk_params).and_return(volume)
34
- end
35
-
36
- cloud.should_receive(:wait_resource).with(volume, :available)
37
-
38
- cloud.create_disk(2049)
39
- end
40
-
41
- it "check min and max disk size" do
42
- expect {
43
- mock_cloud.create_disk(100)
44
- }.to raise_error(Bosh::Clouds::CloudError, /minimum disk size is 1 GiB/)
45
-
46
- expect {
47
- mock_cloud.create_disk(2000 * 1024)
48
- }.to raise_error(Bosh::Clouds::CloudError, /maximum disk size is 1 TiB/)
49
- end
50
-
51
- it "puts disk in the same AZ as an instance" do
52
- disk_params = {
53
- :size => 1,
54
- :availability_zone => "foobar-land"
55
- }
56
-
57
- instance = double("instance",
58
- :id => "i-test",
59
- :availability_zone => "foobar-land")
60
-
61
- volume = double("volume", :id => "v-foobar")
62
-
63
- cloud = mock_cloud do |ec2|
64
- ec2.volumes.should_receive(:create).with(disk_params).and_return(volume)
65
- ec2.instances.stub(:[]).with("i-test").and_return(instance)
66
- end
67
-
68
- cloud.should_receive(:wait_resource).with(volume, :available)
69
-
70
- cloud.create_disk(1024, "i-test")
71
- end
72
-
73
- end