bosh_openstack_cpi 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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