bosh_openstack_cpi 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -14,6 +14,16 @@ begin
14
14
  rescue LoadError
15
15
  end
16
16
 
17
+ begin
18
+ require "bundler_task"
19
+ rescue LoadError
20
+ end
21
+
22
+ begin
23
+ require "ci_task"
24
+ rescue LoadError
25
+ end
26
+
17
27
  gem_helper = Bundler::GemHelper.new(Dir.pwd)
18
28
 
19
29
  desc "Build CPI gem into the pkg directory"
@@ -21,10 +31,14 @@ task "build" do
21
31
  gem_helper.build_gem
22
32
  end
23
33
 
24
- desc "Build and install CPI into system gems"
25
- task "install" do
26
- Rake::Task["bundler:install"].invoke
27
- gem_helper.install_gem
34
+ if defined?(BundlerTask)
35
+ BundlerTask.new
36
+
37
+ desc "Build and install CPI into system gems"
38
+ task "install" do
39
+ Rake::Task["bundler:install"].invoke
40
+ gem_helper.install_gem
41
+ end
28
42
  end
29
43
 
30
44
  if defined?(RSpec)
@@ -34,6 +48,12 @@ if defined?(RSpec)
34
48
  t.pattern = "spec/unit/**/*_spec.rb"
35
49
  t.rspec_opts = %w(--format progress --colour)
36
50
  end
51
+
52
+ if defined?(CiTask)
53
+ CiTask.new do |task|
54
+ task.rspec_task = rspec_task
55
+ end
56
+ end
37
57
  end
38
58
 
39
59
  desc "Run tests"
@@ -0,0 +1,103 @@
1
+ # BOSH OpenStack Cloud Provider Interface
2
+ # Copyright (c) 2012 Piston Cloud Computing, Inc.
3
+
4
+ For online documentation see: http://rubydoc.info/gems/bosh_openstack_cpi/
5
+
6
+ ## Options
7
+
8
+ These options are passed to the OpenStack CPI when it is instantiated.
9
+
10
+ ### OpenStack options
11
+
12
+ * `auth_url` (required)
13
+ URL of the OpenStack Identity endpoint to connect to
14
+ * `username` (required)
15
+ OpenStack user name
16
+ * `api_key` (required)
17
+ OpenStack API key
18
+ * `tenant` (required)
19
+ OpenStack tenant name
20
+ * `region` (optional)
21
+ OpenStack region
22
+ * `default_key_name` (required)
23
+ default OpenStack ssh key name to assign to created virtual machines
24
+ * `default_security_group` (required)
25
+ default OpenStack security group to assign to created virtual machines
26
+ * `private_key` (required)
27
+ local path to the ssh private key, must match `default_key_name`
28
+
29
+ ### Registry options
30
+
31
+ The registry options are passed to the Openstack CPI by the BOSH director based on the settings in `director.yml`, but can be overridden if needed.
32
+
33
+ * `endpoint` (required)
34
+ OpenStack registry URL
35
+ * `user` (required)
36
+ OpenStack registry user
37
+ * `password` (required)
38
+ rOpenStack egistry password
39
+
40
+ ### Agent options
41
+
42
+ Agent options are passed to the OpenStack CPI by the BOSH director based on the settings in `director.yml`, but can be overridden if needed.
43
+
44
+ ### Resource pool options
45
+
46
+ These options are specified under `cloud_options` in the `resource_pools` section of a BOSH deployment manifest.
47
+
48
+ * `instance_type` (required)
49
+ which type of instance (OpenStack flavor) the VMs should belong to
50
+ * `availability_zone` (optional)
51
+ the OpenStack availability zone the VMs should be created in
52
+
53
+ ### Network options
54
+
55
+ These options are specified under `cloud_options` in the `networks` section of a BOSH deployment manifest.
56
+
57
+ * `type` (required)
58
+ can be either `dynamic` for a DHCP assigned IP by OpenStack, or `vip` to use a Floating IP (which needs to be already allocated)
59
+
60
+ ## Example
61
+
62
+ This is a sample of how OpenStack specific properties are used in a BOSH deployment manifest:
63
+
64
+ ---
65
+ name: sample
66
+ director_uuid: 38ce80c3-e9e9-4aac-ba61-97c676631b91
67
+
68
+ ...
69
+
70
+ networks:
71
+ - name: nginx_network
72
+ type: vip
73
+ cloud_properties: {}
74
+ - name: default
75
+ type: dynamic
76
+ cloud_properties:
77
+ security_groups:
78
+ - default
79
+
80
+ ...
81
+
82
+ resource_pools:
83
+ - name: common
84
+ network: default
85
+ size: 3
86
+ stemcell:
87
+ name: bosh-stemcell
88
+ version: 0.6.7
89
+ cloud_properties:
90
+ instance_type: m1.small
91
+
92
+ ...
93
+
94
+ properties:
95
+ openstack:
96
+ auth_url: http://pistoncloud.com/:5000/v2.0/tokens
97
+ username: christopher
98
+ api_key: QRoqsenPsNGX6
99
+ tenant: Bosh
100
+ region: us-west
101
+ default_key_name: bosh
102
+ default_security_groups: ["bosh"]
103
+ private_key: /home/bosh/.ssh/bosh.pem
@@ -0,0 +1,82 @@
1
+ #OpenStack CPI Implementation #
2
+ OpenStack CPI is an implementation of BOSH CPI. It allows BOSH to interface with various services in OpenStack like glance, controller and registry. In the sections below we outline the implementation details for each of the method in CPI interface.
3
+
4
+ ##Initialize ##
5
+
6
+ Implementation of `def initialize(options)` method.
7
+
8
+ 1. Validate the `options` passed to this method
9
+ 2. In the second step the parameters are extracted from `options` object to populate the following properties
10
+ + `@agent_properties`
11
+ + `@openstack_properties`
12
+ + `@registry_propertiess`
13
+ 3. Populate the `openstack_params` and connect to remove Nova Service
14
+ 1. Instantiate `Fog::Compute` instance
15
+ 2. `Fog::Compute::OpenStack` instance is created
16
+ 3. A New `Fog::Connection` object connects with the remove Nova Compute Service
17
+ 4. Populate the `glance_params`and connect to remove Glance service
18
+ 1. Instantiate `Fog::Image` instance
19
+ 2. `Fog::Image::OpenStack` instance is created
20
+ 3. A New `Fog::Connection` object connects with the remove Glance Service
21
+ 5. Instantiate `Registry_Client`.
22
+
23
+ Figure below shows the flow of control.
24
+
25
+ ![openstack_cpi_initialize](https://raw.github.com/piston/openstack-bosh-cpi/master/images/openstack_cpi_initialize.png)
26
+
27
+ ##Create Stemcell ##
28
+
29
+ Implementation of method `create_stemcell(image_path, cloud_properties)`
30
+ Steps outlined below are the flow control implemented to extract and upload kernel image, ramdisk and stem cell image.
31
+
32
+ 1. Extract parameters from the `cloud_properties`. Check if `kernel_file` parameter exists, instantiate `kernel_image` object
33
+ 2. Construct `kernel_params`
34
+ 3. Upload `kernel_image` to glance service by calling the method `upload_image(kernel_params)`
35
+ 4. If params contain `ramdisk_file`
36
+ 5. Instantiate ramdisk_image object and populate `ramdisk_parama`
37
+ 6. Upload the `ramdisk_image` to glance service by calling `upload(ramdisk_params)`
38
+ 7. Populate `image_params` for the stem cell to be uploaded to glance service
39
+ 8. Call the method `upload_image(image_params)`
40
+
41
+ Figure below shows the flow control for the method `create_stemcell(image_path, cloud_properties)`
42
+
43
+ ![openstack_cpi_createstemcell](https://raw.github.com/piston/openstack-bosh-cpi/master/images/openstack_cpi_createstemcell.png)
44
+
45
+ ##Delete Stemcell
46
+
47
+ ![openstack_cpi_deletestemcell](https://raw.github.com/piston/openstack-bosh-cpi/master/images/openstack_cpi_deletestemcell.png)
48
+
49
+ ##Create VM ##
50
+
51
+ ![openstack_cpi_create_vm](https://raw.github.com/piston/openstack-bosh-cpi/master/images/openstack_cpi_create_vm.png)
52
+
53
+ ##Delete VM ##
54
+
55
+ Implementation of `delete_vm(server_id)`. This method deletes the VM created in Nova Compute.
56
+
57
+ 1. Get the `server_id` of the VM to be deleted
58
+ * 1.1, 1.2 : Send the request `get_server_details` to Compute API Server through `Fog::Connection`
59
+ 2. If `server` object returned is not null call `server.destroy`. This will send `delete_server` request to Nova Compute.
60
+ * 2.1, 2.2 : Create and send the `delete_server` request through `Fog::Connection`
61
+ 3. Delete the settings from Registry by calling `delete_settings` method.
62
+
63
+ Figure below shows the flow control for `delete_vm` method
64
+
65
+ ![openstack_cpi_delete_vm](https://raw.github.com/piston/openstack-bosh-cpi/master/images/openstack_cpi_delete_vm.png)
66
+
67
+ ##Create Disk ##
68
+
69
+ 1. Check if size passed is integer, is greater than 1024 and less than 1024*1000, else throw an error
70
+ 2. Create `volume_params`
71
+ 3. Call `create()volume_params)` on `Fog::Compute` service
72
+ 1. `create_volume` request on `Fog::Volume::OpenStack`
73
+ 2. Opens a `Fog::Connection` request to access the remote service and create a volume.
74
+
75
+ Figure below shows the flow control of `create_disk` method
76
+
77
+ ![openstack_cpi_create_disk](https://raw.github.com/piston/openstack-bosh-cpi/master/images/openstack_cpi_create_disk.png)
78
+
79
+ ##Delete Disk##
80
+
81
+ This method deletes the volume created in OpenStack Nova Volume
82
+ ![openstack_cpi_delete_disk](https://raw.github.com/piston/openstack-bosh-cpi/master/images/openstack_cpi_delete_disk.png)
@@ -91,7 +91,7 @@ module Bosh::OpenStackCloud
91
91
  # 1. Unpack image to temp directory
92
92
  unpack_image(tmp_dir, image_path)
93
93
  root_image = File.join(tmp_dir, "root.img")
94
-
94
+
95
95
  # 2. If image contains a kernel file, upload it to glance service
96
96
  kernel_id = nil
97
97
  if cloud_properties["kernel_id"]
@@ -122,7 +122,7 @@ module Bosh::OpenStackCloud
122
122
  ramdisk_id = cloud_properties["ramdisk_id"]
123
123
  elsif cloud_properties["ramdisk_file"]
124
124
  ramdisk_image = File.join(tmp_dir, cloud_properties["ramdisk_file"])
125
- unless File.exists?(kernel_image)
125
+ unless File.exists?(ramdisk_image)
126
126
  cloud_error("Ramdisk image " \
127
127
  "#{cloud_properties['ramdisk_file']} " \
128
128
  "is missing from stemcell archive")
@@ -234,18 +234,9 @@ module Bosh::OpenStackCloud
234
234
  network_spec = nil, disk_locality = nil, environment = nil)
235
235
  with_thread_name("create_vm(#{agent_id}, ...)") do
236
236
  @logger.info("Creating new server...")
237
- network_configurator = NetworkConfigurator.new(network_spec)
238
-
239
237
  server_name = "vm-#{generate_unique_name}"
240
- user_data = {
241
- "registry" => {
242
- "endpoint" => @registry.endpoint
243
- },
244
- "server" => {
245
- "name" => server_name
246
- }
247
- }
248
238
 
239
+ network_configurator = NetworkConfigurator.new(network_spec)
249
240
  security_groups =
250
241
  network_configurator.security_groups(@default_security_groups)
251
242
  @logger.debug("Using security groups: `#{security_groups.join(', ')}'")
@@ -269,7 +260,8 @@ module Bosh::OpenStackCloud
269
260
  :flavor_ref => flavor.id,
270
261
  :key_name => resource_pool["key_name"] || @default_key_name,
271
262
  :security_groups => security_groups,
272
- :user_data => Yajl::Encoder.encode(user_data)
263
+ :user_data => Yajl::Encoder.encode(user_data(server_name,
264
+ network_spec))
273
265
  }
274
266
 
275
267
  availability_zone = select_availability_zone(disk_locality,
@@ -489,6 +481,26 @@ module Bosh::OpenStackCloud
489
481
  end
490
482
  end
491
483
 
484
+ ##
485
+ # Set metadata for an OpenStack server
486
+ #
487
+ # @param [String] server_id OpenStack server UUID
488
+ # @param [Hash] metadata Metadata key/value pairs
489
+ # @return [void]
490
+ def set_vm_metadata(server_id, metadata)
491
+ with_thread_name("set_vm_metadata(#{server_id}, ...)") do
492
+ server = @openstack.servers.get(server_id)
493
+ unless server
494
+ cloud_error("Server `#{server_id}' not found")
495
+ end
496
+
497
+ metadata.each do |name, value|
498
+ value = "" if value.nil? # value is required
499
+ server.metadata.update(name => value)
500
+ end
501
+ end
502
+ end
503
+
492
504
  ##
493
505
  # Validates the deployment
494
506
  #
@@ -543,6 +555,39 @@ module Bosh::OpenStackCloud
543
555
  UUIDTools::UUID.random_create.to_s
544
556
  end
545
557
 
558
+ ##
559
+ # Prepare server user data
560
+ #
561
+ # @param [String] server_name server name
562
+ # @param [Hash] network_spec network specification
563
+ # @return [Hash] server user data
564
+ def user_data(server_name, network_spec)
565
+ data = {}
566
+
567
+ data["registry"] = { "endpoint" => @registry.endpoint }
568
+ data["server"] = { "name" => server_name }
569
+
570
+ with_dns(network_spec) do |servers|
571
+ data["dns"] = { "nameserver" => servers }
572
+ end
573
+
574
+ data
575
+ end
576
+
577
+ ##
578
+ # Extract dns server list from network spec and yield the the list
579
+ #
580
+ # @param [Hash] network_spec network specification for instance
581
+ # @yield [Array]
582
+ def with_dns(network_spec)
583
+ network_spec.each_value do |properties|
584
+ if properties.has_key?("dns") && !properties["dns"].nil?
585
+ yield properties["dns"]
586
+ return
587
+ end
588
+ end
589
+ end
590
+
546
591
  ##
547
592
  # Generates initial agent settings. These settings will be read by agent
548
593
  # from OpenStack registry (also a BOSH component) on a target server. Disk
@@ -696,7 +741,6 @@ module Bosh::OpenStackCloud
696
741
  cloud_error("Failed to unpack stemcell root image" \
697
742
  "tar exit status #{$?.exitstatus}: #{output}")
698
743
  end
699
-
700
744
  root_image = File.join(tmp_dir, "root.img")
701
745
  unless File.exists?(root_image)
702
746
  cloud_error("Root image is missing from stemcell archive")
@@ -710,8 +754,8 @@ module Bosh::OpenStackCloud
710
754
  # @return [void]
711
755
  # @raise [ArgumentError] if options are not valid
712
756
  def validate_options
713
- unless @options.has_key?("openstack") &&
714
- @options["openstack"].is_a?(Hash) &&
757
+ unless @options["openstack"].is_a?(Hash) &&
758
+ @options.has_key?("openstack") &&
715
759
  @options["openstack"]["auth_url"] &&
716
760
  @options["openstack"]["username"] &&
717
761
  @options["openstack"]["api_key"] &&
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Bosh
4
4
  module OpenStackCloud
5
- VERSION = "0.0.5"
5
+ VERSION = "0.0.6"
6
6
  end
7
7
  end
@@ -9,6 +9,9 @@ Bundler.setup(:default, :test)
9
9
 
10
10
  require "rspec"
11
11
  require "tmpdir"
12
+ require 'zlib'
13
+ require 'archive/tar/minitar'
14
+ include Archive::Tar
12
15
 
13
16
  require "cloud/openstack"
14
17
 
@@ -13,6 +13,40 @@ describe Bosh::OpenStackCloud::Cloud do
13
13
  cloud.should be_an_instance_of(Bosh::OpenStackCloud::Cloud)
14
14
  end
15
15
 
16
- end
16
+ it "raises ArgumentError on initializing with blank options" do
17
+ options = Hash.new("options")
18
+ expect {
19
+ Bosh::OpenStackCloud::Cloud.new(options)
20
+ }.to raise_error(ArgumentError)
21
+ end
22
+
23
+ it "raises ArgumentError on initializing with non Hashoptions" do
24
+ options = "this is a string"
25
+ expect {
26
+ Bosh::OpenStackCloud::Cloud.new(options)
27
+ }.to raise_error(ArgumentError)
28
+ end
17
29
 
30
+ it "should create a Cloud Instance on giving valid params" do
31
+ openstack = { "auth_url" => "http://localhost/",
32
+ "username" =>"testuser",
33
+ "api_key" => "test_api_key",
34
+ "tenant" => "test_tenant"
35
+ }
36
+ registry = { "endpoint" => "http://0.0.0.0",
37
+ "user" => "testuser",
38
+ "password" => "password"
39
+ }
40
+ options = { "openstack" => openstack,
41
+ "registry" => registry
42
+ }
43
+ socket_error = false
44
+ begin
45
+ cloud = Bosh::OpenStackCloud::Cloud.new(options)
46
+ rescue Excon::Errors::SocketError => e
47
+ socket_error = true
48
+ end
49
+ socket_error.should be_true
50
+ end
51
+ end
18
52
  end
@@ -196,6 +196,120 @@ describe Bosh::OpenStackCloud::Cloud do
196
196
  sc_id.should == "i-bar"
197
197
  end
198
198
 
199
- end
199
+ it "should throw an error for non existent root image in stemcell archive" do
200
+ begin
201
+ dir = Dir.mkdir("tmp")
202
+ Dir.chdir 'tmp'
203
+
204
+ kernel_img = File.new('kernel.img', 'w')
205
+ ramdisk_img = File.new('initrd.img', 'w')
206
+
207
+ tgz = Zlib::GzipWriter.new(File.open('stemcell.tgz', 'wb'))
208
+ array = ['kernel.img']
209
+
210
+ Minitar.pack(array, tgz)
211
+
212
+ cloud = mock_glance
213
+ error_expected = "Root image is missing from stemcell archive"
214
+ error_actual = ""
215
+ begin
216
+ cloud.create_stemcell("./stemcell.tgz", {
217
+ "name" => "bosh-stemcell",
218
+ "version" => "x.y.z",
219
+ "container_format" => "ami",
220
+ "disk_format" => "ami",
221
+ "kernel_file" => "kernel.img",
222
+ "ramdisk_file" => "initrd.img"
223
+ })
224
+ rescue Bosh::Clouds::CloudError => e
225
+ error_actual = e.to_s
226
+ end
227
+ error_actual.should eq(error_expected)
228
+ ensure
229
+ File.delete('kernel.img')
230
+ File.delete('initrd.img')
231
+ File.delete('stemcell.tgz')
232
+ Dir.chdir '..'
233
+ Dir.delete('tmp')
234
+ end
235
+ end
236
+
237
+ it "should throw an error for non existent kernel image in stemcell archive" do
238
+ begin
239
+ dir = Dir.mkdir("tmp")
240
+ Dir.chdir 'tmp'
241
+ root_img = File.new('root.img','w')
242
+ if root_img
243
+ root_img.syswrite("ABCDEF")
244
+ end
245
+ ramdisk_img = File.new('initrd.img', 'w')
246
+
247
+ tgz = Zlib::GzipWriter.new(File.open('stemcell.tgz', 'wb'))
248
+ array = ['root.img']
249
+
250
+ Minitar.pack(array, tgz)
251
+
252
+ cloud = mock_glance
253
+ error_expected = "Kernel image kernel.img is missing from stemcell archive"
254
+ error_actual = ""
255
+ begin
256
+ cloud.create_stemcell("./stemcell.tgz", {
257
+ "name" => "bosh-stemcell",
258
+ "version" => "x.y.z",
259
+ "container_format" => "ami",
260
+ "disk_format" => "ami",
261
+ "kernel_file" => "kernel.img",
262
+ "ramdisk_file" => "initrd.img"
263
+ })
264
+ rescue Bosh::Clouds::CloudError => e
265
+ error_actual = e.to_s
266
+ end
267
+ error_actual.should eq(error_expected)
268
+ ensure
269
+ File.delete('root.img')
270
+ File.delete('initrd.img')
271
+ File.delete('stemcell.tgz')
272
+ Dir.chdir '..'
273
+ Dir.delete('tmp')
274
+ end
275
+ end
276
+
277
+ it "should throw an error for non existent ramdisk image in stemcell archive" do
278
+ begin
279
+ dir = Dir.mkdir("tmp")
280
+ Dir.chdir 'tmp'
281
+ root_img = File.new('root.img','w')
282
+ if root_img
283
+ root_img.syswrite("ABCDEF")
284
+ end
200
285
 
286
+ tgz = Zlib::GzipWriter.new(File.open('stemcell.tgz', 'wb'))
287
+ array = ['root.img']
288
+
289
+ Minitar.pack(array, tgz)
290
+
291
+ cloud = mock_glance
292
+ error_expected = "Ramdisk image initrd.img is missing from stemcell archive"
293
+ error_actual = ""
294
+ begin
295
+ cloud.create_stemcell("./stemcell.tgz", {
296
+ "name" => "bosh-stemcell",
297
+ "version" => "x.y.z",
298
+ "container_format" => "ami",
299
+ "disk_format" => "ami",
300
+ #"kernel_file" => "kernel.img",
301
+ "ramdisk_file" => "initrd.img"
302
+ })
303
+ rescue Bosh::Clouds::CloudError => e
304
+ error_actual = e.to_s
305
+ end
306
+ error_actual.should eq(error_expected)
307
+ ensure
308
+ File.delete('root.img')
309
+ File.delete('stemcell.tgz')
310
+ Dir.chdir '..'
311
+ Dir.delete('tmp')
312
+ end
313
+ end
314
+ end
201
315
  end
@@ -79,6 +79,52 @@ describe Bosh::OpenStackCloud::Cloud, "create_vm" do
79
79
  vm_id.should == "i-test"
80
80
  end
81
81
 
82
+ it "passes dns servers in server user data when present" do
83
+ unique_name = UUIDTools::UUID.random_create.to_s
84
+
85
+ user_data = {
86
+ "registry" => {
87
+ "endpoint" => "http://registry:3333"
88
+ },
89
+ "server" => {
90
+ "name" => "vm-#{unique_name}"
91
+ },
92
+ "dns" => {
93
+ "nameserver" => ["1.2.3.4"]
94
+ }
95
+ }
96
+ server = double("server", :id => "i-test", :name => "i-test")
97
+ image = double("image", :id => "sc-id", :name => "sc-id")
98
+ flavor = double("flavor", :id => "f-test", :name => "m1.tiny")
99
+ address = double("address", :id => "a-test", :ip => "10.0.0.1",
100
+ :instance_id => "i-test")
101
+ network_spec = dynamic_network_spec
102
+ network_spec["dns"] = ["1.2.3.4"]
103
+
104
+ cloud = mock_cloud do |openstack|
105
+ openstack.servers.should_receive(:create).
106
+ with(openstack_params(unique_name, user_data, %w[default])).
107
+ and_return(server)
108
+ openstack.images.should_receive(:find).and_return(image)
109
+ openstack.flavors.should_receive(:find).and_return(flavor)
110
+ openstack.addresses.should_receive(:each).and_yield(address)
111
+ end
112
+
113
+ cloud.should_receive(:generate_unique_name).and_return(unique_name)
114
+ address.should_receive(:server=).with(nil)
115
+ cloud.should_receive(:wait_resource).with(server, :active, :state)
116
+
117
+ @registry.should_receive(:update_settings).
118
+ with("i-test", agent_settings(unique_name, network_spec))
119
+
120
+ vm_id = cloud.create_vm("agent-id", "sc-id",
121
+ resource_pool_spec,
122
+ { "network_a" => network_spec },
123
+ nil, { "test_env" => "value" })
124
+ vm_id.should == "i-test"
125
+ end
126
+
127
+
82
128
  it "creates an OpenStack server with security group" do
83
129
  unique_name = UUIDTools::UUID.random_create.to_s
84
130
  user_data = {
@@ -0,0 +1,34 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ require File.expand_path("../../spec_helper", __FILE__)
4
+
5
+ describe Bosh::OpenStackCloud::Cloud do
6
+ before :each do
7
+ @server = double("server", :id => "i-foobar")
8
+ @metadata = double("metadata")
9
+
10
+ @cloud = mock_cloud do |openstack|
11
+ openstack.servers.should_receive(:get).
12
+ with("i-foobar").and_return(@server)
13
+ end
14
+ end
15
+
16
+ it "should set metadata" do
17
+ metadata = {:job => "job", :index => "index"}
18
+
19
+ @server.should_receive(:metadata).and_return(@metadata, @metadata)
20
+ @metadata.should_receive(:update).with(:job => "job")
21
+ @metadata.should_receive(:update).with(:index => "index")
22
+
23
+ @cloud.set_vm_metadata("i-foobar", metadata)
24
+ end
25
+
26
+ it "should set metadata with a nil value" do
27
+ metadata = {:deployment => nil}
28
+
29
+ @server.should_receive(:metadata).and_return(@metadata)
30
+ @metadata.should_receive(:update).with(:deployment => "")
31
+
32
+ @cloud.set_vm_metadata("i-foobar", metadata)
33
+ end
34
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh_openstack_cpi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-10 00:00:00.000000000 Z
12
+ date: 2013-01-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fog
@@ -126,6 +126,8 @@ files:
126
126
  - lib/cloud/openstack/version.rb
127
127
  - lib/cloud/openstack/vip_network.rb
128
128
  - README.md
129
+ - USAGE.md
130
+ - bosh_cpi.md
129
131
  - Rakefile
130
132
  - spec/assets/sample_config.yml
131
133
  - spec/integration/cpi_test.rb
@@ -143,6 +145,7 @@ files:
143
145
  - spec/unit/helpers_spec.rb
144
146
  - spec/unit/network_configurator_spec.rb
145
147
  - spec/unit/reboot_vm_spec.rb
148
+ - spec/unit/set_vm_metadata_spec.rb
146
149
  - spec/unit/validate_deployment_spec.rb
147
150
  homepage: http://www.pistoncloud.com
148
151
  licenses: []
@@ -185,5 +188,6 @@ test_files:
185
188
  - spec/unit/helpers_spec.rb
186
189
  - spec/unit/network_configurator_spec.rb
187
190
  - spec/unit/reboot_vm_spec.rb
191
+ - spec/unit/set_vm_metadata_spec.rb
188
192
  - spec/unit/validate_deployment_spec.rb
189
193
  has_rdoc: