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.
- data/bin/bosh_openstack_console +5 -0
- data/lib/cloud/openstack/cloud.rb +88 -16
- data/lib/cloud/openstack/version.rb +1 -1
- data/spec/unit/create_stemcell_spec.rb +95 -2
- data/spec/unit/delete_stemcell_spec.rb +58 -4
- metadata +10 -10
data/bin/bosh_openstack_console
CHANGED
@@ -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.
|
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 =>
|
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
|
-
|
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 = @
|
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
|
@@ -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
|
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 =
|
11
|
-
|
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.
|
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-
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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:
|
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:
|
168
|
+
hash: 4125051121174364727
|
169
169
|
requirements: []
|
170
170
|
rubyforge_project:
|
171
171
|
rubygems_version: 1.8.24
|