cloudstack_spec 0.0.4
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.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +127 -0
- data/Rakefile +2 -0
- data/bin/cloudstackspec-init +7 -0
- data/cloudstack_spec.gemspec +29 -0
- data/examples/output_example.txt +56 -0
- data/lib/cloudstack_spec.rb +56 -0
- data/lib/cloudstack_spec/helper.rb +9 -0
- data/lib/cloudstack_spec/helper/api.rb +40 -0
- data/lib/cloudstack_spec/helper/resource.rb +19 -0
- data/lib/cloudstack_spec/matcher.rb +12 -0
- data/lib/cloudstack_spec/matcher/be_allocated.rb +23 -0
- data/lib/cloudstack_spec/matcher/be_created.rb +30 -0
- data/lib/cloudstack_spec/matcher/be_ready.rb +17 -0
- data/lib/cloudstack_spec/matcher/be_running.rb +17 -0
- data/lib/cloudstack_spec/matcher/be_set.rb +18 -0
- data/lib/cloudstack_spec/resource.rb +1 -0
- data/lib/cloudstack_spec/resource/account.rb +102 -0
- data/lib/cloudstack_spec/resource/base.rb +58 -0
- data/lib/cloudstack_spec/resource/domain.rb +71 -0
- data/lib/cloudstack_spec/resource/network.rb +90 -0
- data/lib/cloudstack_spec/resource/project.rb +66 -0
- data/lib/cloudstack_spec/resource/snapshot.rb +53 -0
- data/lib/cloudstack_spec/resource/system_vm.rb +55 -0
- data/lib/cloudstack_spec/resource/template.rb +41 -0
- data/lib/cloudstack_spec/resource/template_from_snapshot.rb +73 -0
- data/lib/cloudstack_spec/resource/virtual_machine.rb +245 -0
- data/lib/cloudstack_spec/resource/vpc.rb +139 -0
- data/lib/cloudstack_spec/resource/vpc_tier.rb +81 -0
- data/lib/cloudstack_spec/resource/zone.rb +51 -0
- data/lib/cloudstack_spec/setup.rb +191 -0
- data/lib/cloudstack_spec/version.rb +3 -0
- data/spec/config.yml +5 -0
- data/spec/lib/1_zone_spec.rb +18 -0
- data/spec/lib/domain_spec.rb +20 -0
- data/spec/lib/network_spec.rb +45 -0
- data/spec/lib/snapshot_spec.rb +41 -0
- data/spec/lib/template_spec.rb +11 -0
- data/spec/lib/virtual_machine_spec.rb +17 -0
- data/spec/lib/vpc_spec.rb +40 -0
- data/spec/preprod/001_zone_spec.rb +65 -0
- data/spec/preprod/010_domain_spec.rb +18 -0
- data/spec/preprod/snapshot_spec.rb +27 -0
- data/spec/spec_helper.rb +31 -0
- metadata +207 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
module CloudstackSpec::Resource
|
2
|
+
class Snapshot < Base
|
3
|
+
|
4
|
+
def initialize(name='root_disk')
|
5
|
+
@volume_name = name
|
6
|
+
@connection = CloudstackSpec::Helper::Api.new.connection
|
7
|
+
@version = CloudstackSpec::Helper::Api.new.version
|
8
|
+
end
|
9
|
+
|
10
|
+
def exist?
|
11
|
+
snapshots = @connection.list_snapshots(volumeid: get_volume_id)
|
12
|
+
if ! snapshots.empty?
|
13
|
+
if snapshots['count'] >= 1
|
14
|
+
return true
|
15
|
+
end
|
16
|
+
else
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def created?
|
22
|
+
# start the VM creation job
|
23
|
+
# Return {true/false}
|
24
|
+
#if self.exist?
|
25
|
+
# creation_job = "Already exist"
|
26
|
+
# puts " #{creation_job}"
|
27
|
+
# return false
|
28
|
+
#end
|
29
|
+
begin
|
30
|
+
newsnap = @connection.create_snapshot(volumeid: get_volume_id)
|
31
|
+
creation_job = newsnap['jobid']
|
32
|
+
rescue Exception => e
|
33
|
+
creation_job = "vm creation fail with #{e.message}"
|
34
|
+
end
|
35
|
+
if UUID.validate(creation_job) == true
|
36
|
+
puts " jobid: #{creation_job}"
|
37
|
+
return job_status?(creation_job)
|
38
|
+
else
|
39
|
+
puts " #{creation_job}"
|
40
|
+
return false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
private
|
46
|
+
def get_volume_id
|
47
|
+
vol = @connection.list_volumes(virtualmachineid: $vm['id'])
|
48
|
+
vol = vol['volume'].first
|
49
|
+
return vol['id']
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module CloudstackSpec::Resource
|
2
|
+
class SystemVm < Base
|
3
|
+
# All about system VM...
|
4
|
+
|
5
|
+
def initialize(name=nil, zonename=nil)
|
6
|
+
@name = name
|
7
|
+
@connection = CloudstackSpec::Helper::Api.new.connection
|
8
|
+
|
9
|
+
case @name
|
10
|
+
when 'cpvm' && 'consoleproxy'
|
11
|
+
@systemvmtype = 'consoleproxy'
|
12
|
+
when 'ssvm' && 'secondarystoragevm'
|
13
|
+
@systemvmtype = 'secondarystoragevm'
|
14
|
+
else
|
15
|
+
@systemvmtype = nil
|
16
|
+
end
|
17
|
+
@zone = get_zone(zonename)
|
18
|
+
|
19
|
+
@sysvm = @connection.list_system_vms(:systemvmtype => @systemvmtype, zoneid: @zone['id'])
|
20
|
+
@vmcount = @sysvm['count']
|
21
|
+
@sysvm = @sysvm['systemvm'].first
|
22
|
+
@runner = Specinfra::Runner
|
23
|
+
end
|
24
|
+
|
25
|
+
def exist?
|
26
|
+
begin
|
27
|
+
if @vmcount.nil?
|
28
|
+
return false
|
29
|
+
else
|
30
|
+
return true
|
31
|
+
end
|
32
|
+
rescue Exception => e
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def running?
|
38
|
+
begin
|
39
|
+
if @sysvm['state'] == 'Running'
|
40
|
+
return true
|
41
|
+
else
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
rescue
|
45
|
+
return false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def reachable?(port, proto, timeout)
|
50
|
+
ip = @sysvm['publicip']
|
51
|
+
@runner.check_host_is_reachable(ip, port, proto, timeout)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module CloudstackSpec::Resource
|
2
|
+
class Template < Base
|
3
|
+
# do nothing
|
4
|
+
|
5
|
+
def tpl
|
6
|
+
@connection.list_templates(:templatefilter => "all", :name => name)
|
7
|
+
end
|
8
|
+
|
9
|
+
def exist?
|
10
|
+
begin
|
11
|
+
if tpl['count'].nil?
|
12
|
+
return false
|
13
|
+
else
|
14
|
+
return true
|
15
|
+
end
|
16
|
+
rescue Exception => e
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def ready?
|
22
|
+
if ! tpl["count"].nil?
|
23
|
+
isready = tpl["template"].first["isready"]
|
24
|
+
if isready
|
25
|
+
return true
|
26
|
+
else
|
27
|
+
return tpl["template"].first["status"]
|
28
|
+
end
|
29
|
+
else
|
30
|
+
return "#{name}: not found"
|
31
|
+
#return false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_from_vm(origin_vm)
|
36
|
+
origin_vm
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module CloudstackSpec::Resource
|
2
|
+
class TemplateFromSnapshot < Base
|
3
|
+
# do nothing
|
4
|
+
|
5
|
+
def tpl
|
6
|
+
@connection.list_templates(:templatefilter => "all", :name => name)
|
7
|
+
end
|
8
|
+
|
9
|
+
def exist?
|
10
|
+
begin
|
11
|
+
if tpl['count'].nil?
|
12
|
+
return false
|
13
|
+
else
|
14
|
+
return true
|
15
|
+
end
|
16
|
+
rescue Exception => e
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def ready?
|
22
|
+
if ! tpl["count"].nil?
|
23
|
+
isready = tpl["template"].first["isready"]
|
24
|
+
if isready
|
25
|
+
return true
|
26
|
+
else
|
27
|
+
return tpl["template"].first["status"]
|
28
|
+
end
|
29
|
+
else
|
30
|
+
return "#{name}: not found"
|
31
|
+
#return false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def created?
|
36
|
+
if self.exist?
|
37
|
+
return 'template already exist'
|
38
|
+
else
|
39
|
+
snapshot = get_snapshot
|
40
|
+
if ! snapshot.empty?
|
41
|
+
new_template = @connection.create_template(
|
42
|
+
name: @name,
|
43
|
+
displaytext: @name,
|
44
|
+
ostypeid: get_vm['ostypeid'],
|
45
|
+
passwordenabled: 'true',
|
46
|
+
snapshotid: get_snapshot['id']
|
47
|
+
)
|
48
|
+
creation_job = new_template['jobid']
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def get_vm
|
57
|
+
vm = @connection.list_virtual_machines(name: @name)
|
58
|
+
vm = vm['virtualmachine'].first
|
59
|
+
return vm
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_volume
|
63
|
+
vol = @connection.list_volumes(virtualmachineid: get_vm['id'])
|
64
|
+
return vol['volume'].first
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_snapshot
|
68
|
+
snapshot = @connection.list_snapshots(volumeid: get_volume['id'])
|
69
|
+
return snapshot['snapshot'].first
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,245 @@
|
|
1
|
+
module CloudstackSpec::Resource
|
2
|
+
class VirtualMachine < Base
|
3
|
+
# do nothing
|
4
|
+
attr_reader :name, :template_name, :zonename
|
5
|
+
|
6
|
+
def initialize(name='rspec-test1', zonename=nil)
|
7
|
+
@name = name
|
8
|
+
@template_name = ''
|
9
|
+
@connection = CloudstackSpec::Helper::Api.new.connection
|
10
|
+
@zone = get_zone(zonename)
|
11
|
+
@runner = Specinfra::Runner
|
12
|
+
end
|
13
|
+
|
14
|
+
def exist?
|
15
|
+
begin
|
16
|
+
if vm.empty?
|
17
|
+
return false
|
18
|
+
else
|
19
|
+
return true
|
20
|
+
end
|
21
|
+
rescue Exception => e
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def running?
|
27
|
+
begin
|
28
|
+
if vm['state'] == 'Running'
|
29
|
+
return true
|
30
|
+
else
|
31
|
+
return false
|
32
|
+
end
|
33
|
+
rescue
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def reachable?(port, proto, timeout)
|
39
|
+
pf_rule = get_pf_rule
|
40
|
+
if pf_rule.empty?
|
41
|
+
ip = vm['nic'].first['ipaddress']
|
42
|
+
else
|
43
|
+
ip = pf_rule['ipaddress']
|
44
|
+
port = pf_rule['publicport']
|
45
|
+
proto = pf_rule['protocol']
|
46
|
+
end
|
47
|
+
@runner.check_host_is_reachable(ip, port, proto, timeout)
|
48
|
+
end
|
49
|
+
|
50
|
+
def created?
|
51
|
+
# start the VM creation job
|
52
|
+
# Return {true/false}
|
53
|
+
if self.exist?
|
54
|
+
creation_job = "Already exist"
|
55
|
+
puts " #{creation_job}"
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
|
59
|
+
if ! self.template_name.nil?
|
60
|
+
if validate_template_status == false
|
61
|
+
puts " Template not valid"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
begin
|
65
|
+
newvm = create_virtual_machine(@name)
|
66
|
+
creation_job = newvm['jobid']
|
67
|
+
rescue Exception => exception
|
68
|
+
creation_job = "vm creation fail with #{exception.message}"
|
69
|
+
end
|
70
|
+
if UUID.validate(creation_job) == true
|
71
|
+
return job_status?(creation_job)
|
72
|
+
else
|
73
|
+
puts " #{creation_job}"
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def destroy?
|
79
|
+
if self.exist?
|
80
|
+
job = @connection.destroy_virtual_machine(id: vm['id'], expunge: true)
|
81
|
+
job_status?(job['jobid'])
|
82
|
+
else
|
83
|
+
puts " Does not exist"
|
84
|
+
return false
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def open_pf_ssh
|
89
|
+
# open port forwarding for ssh (tcp:22)
|
90
|
+
port = 22
|
91
|
+
proto = 'tcp'
|
92
|
+
sleep(5) # give move time to the vm to complete booting.
|
93
|
+
if get_pf_rule.empty?
|
94
|
+
new_rule = @connection.create_port_forwarding_rule(
|
95
|
+
ipaddressid: publicip_id,
|
96
|
+
virtualmachineid: vm['id'],
|
97
|
+
privateport: port,
|
98
|
+
publicport: port,
|
99
|
+
networkid: vm['nic'].first['networkid'],
|
100
|
+
protocol: proto )
|
101
|
+
else
|
102
|
+
#puts " Port Forwarging rule already exist"
|
103
|
+
end
|
104
|
+
return true
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def validate_template_status
|
112
|
+
# if template_name define
|
113
|
+
# make sure the template is ready otherwise, wait.
|
114
|
+
# puts get_template
|
115
|
+
if get_template['isready']
|
116
|
+
template_status = true
|
117
|
+
else
|
118
|
+
until get_template['isready']
|
119
|
+
if get_template['status'].nil?
|
120
|
+
puts " Template not ready: #{get_template['name']}"
|
121
|
+
puts " ERROR in CloudStack: status is empty"
|
122
|
+
print " Template download in progress..."
|
123
|
+
until ! get_template['status'].nil?
|
124
|
+
print '.'
|
125
|
+
sleep 5
|
126
|
+
end # end loop
|
127
|
+
end
|
128
|
+
if get_template['status'].include? "%"
|
129
|
+
puts " Template not ready: #{get_template['name']}"
|
130
|
+
print " Template download in progress..."
|
131
|
+
until ! get_template['status'].include? "%"
|
132
|
+
print '.'
|
133
|
+
sleep 5
|
134
|
+
end # end loop
|
135
|
+
elsif get_template['status'].include? "Installing"
|
136
|
+
puts " Template not ready: #{get_template['name']}"
|
137
|
+
print " Template is installing..."
|
138
|
+
until ! get_template['status'].include? "Installing"
|
139
|
+
print '.'
|
140
|
+
sleep 5
|
141
|
+
end # end loop
|
142
|
+
else
|
143
|
+
template_status = false
|
144
|
+
break
|
145
|
+
end
|
146
|
+
end # end loop
|
147
|
+
if get_template['isready']
|
148
|
+
template_status = true
|
149
|
+
end
|
150
|
+
end
|
151
|
+
return template_status
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
def vm
|
156
|
+
vm = @connection.list_virtual_machines(name: @name, zoneid: @zone['id'])
|
157
|
+
if vm.empty?
|
158
|
+
$vm = {}
|
159
|
+
return {}
|
160
|
+
else
|
161
|
+
$vm = vm['virtualmachine'].first
|
162
|
+
return vm['virtualmachine'].first
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def get_template
|
167
|
+
tpl = @connection.list_templates(:templatefilter => "featured", id: get_template_id)
|
168
|
+
tpl = tpl['template'].first
|
169
|
+
return tpl
|
170
|
+
end
|
171
|
+
|
172
|
+
def get_template_id
|
173
|
+
if self.template_name.empty?
|
174
|
+
tpl = @connection.list_templates(:templatefilter => "featured", :zoneid => @zone['id'])
|
175
|
+
else
|
176
|
+
tpl = @connection.list_templates(:name => self.template_name, :templatefilter => "all", :zoneid => @zone['id'])
|
177
|
+
end
|
178
|
+
if ! tpl.empty?
|
179
|
+
tpl = tpl['template'].first['id']
|
180
|
+
return tpl
|
181
|
+
else
|
182
|
+
return 'no featured template found'
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def get_network_id(network_name)
|
187
|
+
# CloudStack API does not search by name for networks
|
188
|
+
networks = @connection.list_networks(zoneid: @zone['id'])['network']
|
189
|
+
return "NO NETWORK FOUND" if networks.nil?
|
190
|
+
networks = networks.select { |net| net['name'] == network_name }
|
191
|
+
return networks.first['id']
|
192
|
+
end
|
193
|
+
|
194
|
+
def get_systemoffering_id(offering_name=nil)
|
195
|
+
if offering_name.nil?
|
196
|
+
systemofferingid = @connection.list_service_offerings()['serviceoffering'].first['id']
|
197
|
+
else
|
198
|
+
systemofferingid = @connection.list_service_offerings(:name => offering_name)['serviceoffering'].first['id']
|
199
|
+
end
|
200
|
+
if UUID.validate(systemofferingid)
|
201
|
+
return systemofferingid
|
202
|
+
else
|
203
|
+
return "invalid systemoffering"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def create_virtual_machine(name='rspec-test1',network_name='tier11',offering_name=nil)
|
208
|
+
networkid = get_network_id(network_name)
|
209
|
+
jobid = @connection.deploy_virtual_machine(
|
210
|
+
zoneid: @zone['id'],
|
211
|
+
serviceofferingid: get_systemoffering_id,
|
212
|
+
templateid: get_template_id,
|
213
|
+
name: name,
|
214
|
+
displayname: name,
|
215
|
+
networkids: networkid
|
216
|
+
)
|
217
|
+
end
|
218
|
+
|
219
|
+
def publicip_id
|
220
|
+
# public ip not used for SourceNAT
|
221
|
+
public_ip = @connection.list_public_ip_addresses(vpcid: $vpc['id'], issourcenat: false)
|
222
|
+
if public_ip.empty?
|
223
|
+
puts " Associating Public IP to VPC"
|
224
|
+
newip = @connection.associate_ip_address(vpcid: $vpc['id'])
|
225
|
+
sleep 5
|
226
|
+
public_ip = @connection.list_public_ip_addresses(vpcid: $vpc['id'], issourcenat: false)
|
227
|
+
end
|
228
|
+
public_ip = public_ip['publicipaddress'].first
|
229
|
+
return public_ip['id']
|
230
|
+
end
|
231
|
+
|
232
|
+
def get_pf_rule
|
233
|
+
# retrieve Port Forwarding Rule for the VM if it exist
|
234
|
+
pf_rules = @connection.list_port_forwarding_rules
|
235
|
+
pf_rules = pf_rules['portforwardingrule']
|
236
|
+
if pf_rules.nil?
|
237
|
+
return {}
|
238
|
+
else
|
239
|
+
pf_rule = pf_rules.select { |rule| rule['virtualmachineid'] == vm['id'] }
|
240
|
+
pf_rule.first
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
end
|