bosh_openstack_cpi 0.0.2 → 0.0.3

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.
@@ -49,6 +49,10 @@ module ConsoleHelpers
49
49
  cpi.openstack
50
50
  end
51
51
 
52
+ def glance
53
+ cpi.glance
54
+ end
55
+
52
56
  def registry
53
57
  cpi.registry
54
58
  end
@@ -70,5 +74,6 @@ end
70
74
  puts "=> Welcome to BOSH OpenStack CPI console"
71
75
  puts "You can use 'cpi' to access CPI methods"
72
76
  puts "You can use 'openstack' to access Fog::Compute::OpenStack methods"
77
+ puts "You can use 'glance' to access Fog::Image::OpenStack methods"
73
78
 
74
79
  IRB.start
@@ -56,37 +56,72 @@ module Bosh::OpenStackCloud
56
56
  # @param [String] image_path local filesystem path to a stemcell image
57
57
  # @param [Hash] cloud_properties CPI-specific properties
58
58
  def create_stemcell(image_path, cloud_properties)
59
- # TODO: refactor into several smaller methods
60
59
  with_thread_name("create_stemcell(#{image_path}...)") do
61
60
  begin
62
61
  Dir.mktmpdir do |tmp_dir|
63
62
  @logger.info("Extracting stemcell to `#{tmp_dir}'")
63
+ image_name = "BOSH-#{generate_unique_name}"
64
64
 
65
65
  # 1. Unpack image to temp directory
66
66
  unpack_image(tmp_dir, image_path)
67
67
  root_image = File.join(tmp_dir, "root.img")
68
68
 
69
- # 2. Upload image using Glance service
69
+ # 2. If image contains a kernel file, upload it
70
+ kernel_id = nil
71
+ if cloud_properties["kernel_id"]
72
+ kernel_id = cloud_properties["kernel_id"]
73
+ elsif cloud_properties["kernel_file"]
74
+ kernel_image = File.join(tmp_dir, cloud_properties["kernel_file"])
75
+ unless File.exists?(kernel_image)
76
+ cloud_error("Kernel image is missing from stemcell archive")
77
+ end
78
+ kernel_params = {
79
+ :name => "AKI-#{image_name}",
80
+ :disk_format => "aki",
81
+ :container_format => "aki",
82
+ :location => kernel_image,
83
+ :properties => {
84
+ :stemcell => image_name
85
+ }
86
+ }
87
+ kernel_id = upload_image(kernel_params)
88
+ end
89
+
90
+ # 3. If image contains a ramdisk file, upload it
91
+ ramdisk_id = nil
92
+ if cloud_properties["ramdisk_id"]
93
+ ramdisk_id = cloud_properties["ramdisk_id"]
94
+ elsif cloud_properties["ramdisk_file"]
95
+ ramdisk_image = File.join(tmp_dir, cloud_properties["ramdisk_file"])
96
+ unless File.exists?(kernel_image)
97
+ cloud_error("Ramdisk image is missing from stemcell archive")
98
+ end
99
+ ramdisk_params = {
100
+ :name => "ARI-#{image_name}",
101
+ :disk_format => "ari",
102
+ :container_format => "ari",
103
+ :location => ramdisk_image,
104
+ :properties => {
105
+ :stemcell => image_name
106
+ }
107
+ }
108
+ ramdisk_id = upload_image(ramdisk_params)
109
+ end
110
+
111
+ # 4. Upload image using Glance service
70
112
  image_params = {
71
- :name => "BOSH-#{generate_unique_name}",
113
+ :name => image_name,
72
114
  :disk_format => cloud_properties["disk_format"],
73
115
  :container_format => cloud_properties["container_format"],
74
- :properties => {
75
- :kernel_id => cloud_properties["kernel_id"],
76
- :ramdisk_id => cloud_properties["ramdisk_id"],
77
- },
78
116
  :location => root_image,
79
117
  :is_public => true
80
118
  }
119
+ image_properties = {}
120
+ image_properties[:kernel_id] = kernel_id if kernel_id
121
+ image_properties[:ramdisk_id] = ramdisk_id if ramdisk_id
122
+ image_params[:properties] = image_properties unless image_properties.empty?
81
123
 
82
- @logger.info("Creating new image...")
83
- image = @glance.images.create(image_params)
84
- state = image.status
85
-
86
- @logger.info("Creating new image `#{image.id}', state is `#{state}'")
87
- wait_resource(image, state, :active)
88
-
89
- image.id.to_s
124
+ upload_image(image_params)
90
125
  end
91
126
  rescue => e
92
127
  @logger.error(e)
@@ -101,7 +136,30 @@ module Bosh::OpenStackCloud
101
136
  def delete_stemcell(stemcell_id)
102
137
  with_thread_name("delete_stemcell(#{stemcell_id})") do
103
138
  @logger.info("Deleting `#{stemcell_id}' stemcell")
104
- image = @openstack.images.get(stemcell_id)
139
+ image = @glance.images.find_by_id(stemcell_id)
140
+
141
+ kernel_id = image.properties["kernel_id"]
142
+ if kernel_id
143
+ kernel = @glance.images.find_by_id(kernel_id)
144
+ if kernel.properties["stemcell"]
145
+ if kernel.properties["stemcell"] == image.name
146
+ @logger.info("Deleting `#{stemcell_id}' stemcell kernel")
147
+ kernel.destroy
148
+ end
149
+ end
150
+ end
151
+
152
+ ramdisk_id = image.properties["ramdisk_id"]
153
+ if ramdisk_id
154
+ ramdisk = @glance.images.find_by_id(ramdisk_id)
155
+ if ramdisk.properties["stemcell"]
156
+ if ramdisk.properties["stemcell"] == image.name
157
+ @logger.info("Deleting `#{stemcell_id}' stemcell ramdisk")
158
+ ramdisk.destroy
159
+ end
160
+ end
161
+ end
162
+
105
163
  image.destroy
106
164
  end
107
165
  end
@@ -456,6 +514,20 @@ module Bosh::OpenStackCloud
456
514
  wait_resource(volume, state, :available)
457
515
  end
458
516
 
517
+ ##
518
+ # Uploads a new image to OpenStack via Glance
519
+ # @param [Hash] image_params Image params
520
+ def upload_image(image_params)
521
+ @logger.info("Creating new image...")
522
+ image = @glance.images.create(image_params)
523
+ state = image.status
524
+
525
+ @logger.info("Creating new image `#{image.id}', state is `#{state}'")
526
+ wait_resource(image, state, :active)
527
+
528
+ image.id.to_s
529
+ end
530
+
459
531
  ##
460
532
  # Reads current server id from OpenStack metadata. We are assuming
461
533
  # server id cannot change while current process is running
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Bosh
4
4
  module OpenStackCloud
5
- VERSION = "0.0.2"
5
+ VERSION = "0.0.3"
6
6
  end
7
7
  end
@@ -10,7 +10,36 @@ describe Bosh::OpenStackCloud::Cloud do
10
10
 
11
11
  describe "Image upload based flow" do
12
12
 
13
- it "creates stemcell by uploading an image via Glance" do
13
+ it "creates stemcell by uploading an image without kernel nor ramdisk" do
14
+ image = double("image", :id => "i-bar", :name => "i-bar")
15
+ unique_name = UUIDTools::UUID.random_create.to_s
16
+ image_params = {
17
+ :name => "BOSH-#{unique_name}",
18
+ :disk_format => "ami",
19
+ :container_format => "ami",
20
+ :location => "#{@tmp_dir}/root.img",
21
+ :is_public => true
22
+ }
23
+
24
+ cloud = mock_glance do |glance|
25
+ glance.images.should_receive(:create).with(image_params).and_return(image)
26
+ end
27
+
28
+ Dir.should_receive(:mktmpdir).and_yield(@tmp_dir)
29
+ cloud.should_receive(:unpack_image).with(@tmp_dir, "/tmp/foo")
30
+ cloud.should_receive(:generate_unique_name).and_return(unique_name)
31
+ image.should_receive(:status).and_return(:queued)
32
+ cloud.should_receive(:wait_resource).with(image, :queued, :active)
33
+
34
+ sc_id = cloud.create_stemcell("/tmp/foo", {
35
+ "container_format" => "ami",
36
+ "disk_format" => "ami"
37
+ })
38
+
39
+ sc_id.should == "i-bar"
40
+ end
41
+
42
+ it "creates stemcell by uploading an image using kernel and ramdisk id's" do
14
43
  image = double("image", :id => "i-bar", :name => "i-bar")
15
44
  unique_name = UUIDTools::UUID.random_create.to_s
16
45
  image_params = {
@@ -39,7 +68,71 @@ describe Bosh::OpenStackCloud::Cloud do
39
68
  "container_format" => "ami",
40
69
  "disk_format" => "ami",
41
70
  "kernel_id" => "k-id",
42
- "ramdisk_id" => "r-id"
71
+ "ramdisk_id" => "r-id",
72
+ "kernel_file" => "kernel.img",
73
+ "ramdisk_file" => "initrd.img"
74
+ })
75
+
76
+ sc_id.should == "i-bar"
77
+ end
78
+
79
+ it "creates stemcell by uploading image, kernel and ramdisk" do
80
+ image = double("image", :id => "i-bar", :name => "i-bar")
81
+ kernel = double("image", :id => "k-img-id", :name => "k-img-id")
82
+ ramdisk = double("image", :id => "r-img-id", :name => "r-img-id")
83
+ unique_name = UUIDTools::UUID.random_create.to_s
84
+ kernel_params = {
85
+ :name => "AKI-BOSH-#{unique_name}",
86
+ :disk_format => "aki",
87
+ :container_format => "aki",
88
+ :location => "#{@tmp_dir}/kernel.img",
89
+ :properties => {
90
+ :stemcell => "BOSH-#{unique_name}",
91
+ }
92
+ }
93
+ ramdisk_params = {
94
+ :name => "ARI-BOSH-#{unique_name}",
95
+ :disk_format => "ari",
96
+ :container_format => "ari",
97
+ :location => "#{@tmp_dir}/initrd.img",
98
+ :properties => {
99
+ :stemcell => "BOSH-#{unique_name}",
100
+ }
101
+ }
102
+ image_params = {
103
+ :name => "BOSH-#{unique_name}",
104
+ :disk_format => "ami",
105
+ :container_format => "ami",
106
+ :location => "#{@tmp_dir}/root.img",
107
+ :is_public => true,
108
+ :properties => {
109
+ :kernel_id => "k-img-id",
110
+ :ramdisk_id => "r-img-id",
111
+ }
112
+ }
113
+
114
+ cloud = mock_glance do |glance|
115
+ glance.images.should_receive(:create).with(kernel_params).and_return(kernel)
116
+ glance.images.should_receive(:create).with(ramdisk_params).and_return(ramdisk)
117
+ glance.images.should_receive(:create).with(image_params).and_return(image)
118
+ end
119
+
120
+ Dir.should_receive(:mktmpdir).and_yield(@tmp_dir)
121
+ cloud.should_receive(:unpack_image).with(@tmp_dir, "/tmp/foo")
122
+ File.stub(:exists?).and_return(true)
123
+ cloud.should_receive(:generate_unique_name).and_return(unique_name)
124
+ kernel.should_receive(:status).and_return(:queued)
125
+ cloud.should_receive(:wait_resource).with(kernel, :queued, :active)
126
+ ramdisk.should_receive(:status).and_return(:queued)
127
+ cloud.should_receive(:wait_resource).with(ramdisk, :queued, :active)
128
+ image.should_receive(:status).and_return(:queued)
129
+ cloud.should_receive(:wait_resource).with(image, :queued, :active)
130
+
131
+ sc_id = cloud.create_stemcell("/tmp/foo", {
132
+ "container_format" => "ami",
133
+ "disk_format" => "ami",
134
+ "kernel_file" => "kernel.img",
135
+ "ramdisk_file" => "initrd.img"
43
136
  })
44
137
 
45
138
  sc_id.should == "i-bar"
@@ -4,11 +4,65 @@ require File.expand_path("../../spec_helper", __FILE__)
4
4
 
5
5
  describe Bosh::OpenStackCloud::Cloud do
6
6
 
7
- it "deregisters OpenStack image" do
8
- image = double("image", :id => "i-foo")
7
+ it "deregisters OpenStack image with no kernel nor ramdisk associated" do
8
+ image = double("image", :id => "i-foo", :name => "i-foo",
9
+ :properties => {})
9
10
 
10
- cloud = mock_cloud do |openstack|
11
- openstack.images.stub(:get).with("i-foo").and_return(image)
11
+ cloud = mock_glance do |glance|
12
+ glance.images.stub(:find_by_id).with("i-foo").and_return(image)
13
+ end
14
+
15
+ image.should_receive(:destroy)
16
+
17
+ cloud.delete_stemcell("i-foo")
18
+ end
19
+
20
+ it "deregisters OpenStack image, kernel and ramdisk" do
21
+ image = double("image", :id => "i-foo", :name => "i-foo",
22
+ :properties => {"kernel_id" => "k-id", "ramdisk_id" => "r-id"})
23
+ kernel = double("image", :id => "k-id", :properties => {"stemcell" => "i-foo"})
24
+ ramdisk = double("image", :id => "r-id", :properties => {"stemcell" => "i-foo"})
25
+
26
+ cloud = mock_glance do |glance|
27
+ glance.images.stub(:find_by_id).with("i-foo").and_return(image)
28
+ glance.images.stub(:find_by_id).with("k-id").and_return(kernel)
29
+ glance.images.stub(:find_by_id).with("r-id").and_return(ramdisk)
30
+ end
31
+
32
+ kernel.should_receive(:destroy)
33
+ ramdisk.should_receive(:destroy)
34
+ image.should_receive(:destroy)
35
+
36
+ cloud.delete_stemcell("i-foo")
37
+ end
38
+
39
+ it "deregisters OpenStack image with kernel and ramdisk not uploaded by the CPI" do
40
+ image = double("image", :id => "i-foo", :name => "i-foo",
41
+ :properties => {"kernel_id" => "k-id", "ramdisk_id" => "r-id"})
42
+ kernel = double("image", :id => "k-id", :properties => {})
43
+ ramdisk = double("image", :id => "r-id", :properties => {})
44
+
45
+ cloud = mock_glance do |glance|
46
+ glance.images.stub(:find_by_id).with("i-foo").and_return(image)
47
+ glance.images.stub(:find_by_id).with("k-id").and_return(kernel)
48
+ glance.images.stub(:find_by_id).with("r-id").and_return(ramdisk)
49
+ end
50
+
51
+ image.should_receive(:destroy)
52
+
53
+ cloud.delete_stemcell("i-foo")
54
+ end
55
+
56
+ it "deregisters OpenStack image with kernel and ramdisk that belongs to other stemcell" do
57
+ image = double("image", :id => "i-foo", :name => "i-foo",
58
+ :properties => {"kernel_id" => "k-id", "ramdisk_id" => "r-id"})
59
+ kernel = double("image", :id => "k-id", :properties => {"stemcell" => "i-bar"})
60
+ ramdisk = double("image", :id => "r-id", :properties => {"stemcell" => "i-bar"})
61
+
62
+ cloud = mock_glance do |glance|
63
+ glance.images.stub(:find_by_id).with("i-foo").and_return(image)
64
+ glance.images.stub(:find_by_id).with("k-id").and_return(kernel)
65
+ glance.images.stub(:find_by_id).with("r-id").and_return(ramdisk)
12
66
  end
13
67
 
14
68
  image.should_receive(:destroy)
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.2
4
+ version: 0.0.3
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-07-18 00:00:00.000000000 Z
12
+ date: 2012-08-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fog
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 1.4.0
21
+ version: 1.5.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: 1.4.0
29
+ version: 1.5.0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: bosh_common
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ! '>='
36
36
  - !ruby/object:Gem::Version
37
- version: 0.4.0
37
+ version: 0.5.0
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
- version: 0.4.0
45
+ version: 0.5.0
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: bosh_cpi
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - ! '>='
52
52
  - !ruby/object:Gem::Version
53
- version: 0.4.3
53
+ version: 0.4.4
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
- version: 0.4.3
61
+ version: 0.4.4
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: httpclient
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -156,7 +156,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
156
156
  version: '0'
157
157
  segments:
158
158
  - 0
159
- hash: -5012446851796113
159
+ hash: 4125051121174364727
160
160
  required_rubygems_version: !ruby/object:Gem::Requirement
161
161
  none: false
162
162
  requirements:
@@ -165,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
165
  version: '0'
166
166
  segments:
167
167
  - 0
168
- hash: -5012446851796113
168
+ hash: 4125051121174364727
169
169
  requirements: []
170
170
  rubyforge_project:
171
171
  rubygems_version: 1.8.24