vcloud-core 0.0.1

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.
Files changed (40) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +9 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.md +103 -0
  5. data/Rakefile +18 -0
  6. data/bin/vcloud-query +84 -0
  7. data/jenkins.sh +10 -0
  8. data/lib/vcloud/core.rb +23 -0
  9. data/lib/vcloud/core/compute_metadata.rb +13 -0
  10. data/lib/vcloud/core/edge_gateway.rb +46 -0
  11. data/lib/vcloud/core/entity.rb +23 -0
  12. data/lib/vcloud/core/metadata_helper.rb +29 -0
  13. data/lib/vcloud/core/org_vdc_network.rb +102 -0
  14. data/lib/vcloud/core/query.rb +142 -0
  15. data/lib/vcloud/core/vapp.rb +118 -0
  16. data/lib/vcloud/core/vapp_template.rb +39 -0
  17. data/lib/vcloud/core/vdc.rb +37 -0
  18. data/lib/vcloud/core/version.rb +5 -0
  19. data/lib/vcloud/core/vm.rb +162 -0
  20. data/lib/vcloud/fog.rb +5 -0
  21. data/lib/vcloud/fog/content_types.rb +20 -0
  22. data/lib/vcloud/fog/model_interface.rb +33 -0
  23. data/lib/vcloud/fog/relation.rb +8 -0
  24. data/lib/vcloud/fog/service_interface.rb +257 -0
  25. data/spec/spec_helper.rb +26 -0
  26. data/spec/support/stub_fog_interface.rb +59 -0
  27. data/spec/vcloud/core/edge_gateway_spec.rb +79 -0
  28. data/spec/vcloud/core/metadata_helper_spec.rb +89 -0
  29. data/spec/vcloud/core/org_vdc_network_spec.rb +257 -0
  30. data/spec/vcloud/core/query_spec.rb +111 -0
  31. data/spec/vcloud/core/vapp_spec.rb +173 -0
  32. data/spec/vcloud/core/vapp_template_spec.rb +77 -0
  33. data/spec/vcloud/core/vdc_spec.rb +68 -0
  34. data/spec/vcloud/core/vm_spec.rb +290 -0
  35. data/spec/vcloud/data/basic_preamble_test.erb +8 -0
  36. data/spec/vcloud/data/basic_preamble_test.erb.OUT +8 -0
  37. data/spec/vcloud/fog/fog_model_interface_spec.rb +25 -0
  38. data/spec/vcloud/fog/service_interface_spec.rb +30 -0
  39. data/vcloud-core.gemspec +30 -0
  40. metadata +198 -0
data/lib/vcloud/fog.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'fog'
2
+ require 'vcloud/fog/content_types'
3
+ require 'vcloud/fog/relation'
4
+ require 'vcloud/fog/service_interface'
5
+ require 'vcloud/fog/model_interface'
@@ -0,0 +1,20 @@
1
+ module Vcloud
2
+ module Fog
3
+ module ContentTypes
4
+ CATALOG = 'application/vnd.vmware.vcloud.catalog+xml'
5
+ ORG = 'application/vnd.vmware.vcloud.org+xml'
6
+ VDC = 'application/vnd.vmware.vcloud.vdc+xml'
7
+ CATALOG_ITEM = 'application/vnd.vmware.vcloud.catalogItem+xml'
8
+ NETWORK = 'application/vnd.vmware.vcloud.network+xml'
9
+ METADATA = 'application/vnd.vmware.vcloud.metadata.value+xml'
10
+ end
11
+
12
+ module MetadataValueType
13
+ String = 'MetadataStringValue'
14
+ Number = 'MetadataNumberValue'
15
+ DateTime = 'MetadataDateTimeValue'
16
+ Boolean = 'MetadataBooleanValue'
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ module Vcloud
2
+ module Fog
3
+ class ModelInterface
4
+ def initialize
5
+ @vcloud = ::Fog::Compute::VcloudDirector.new
6
+ end
7
+
8
+ def org_name
9
+ @vcloud.org_name
10
+ end
11
+
12
+ def current_organization
13
+ @vcloud.organizations.get_by_name org_name
14
+ end
15
+
16
+ def current_vdc vdc_id
17
+ current_organization.vdcs.detect { |v| v.id == vdc_id }
18
+ end
19
+
20
+ def get_vm_by_href href
21
+ vm = @vcloud.get_vms_in_lease_from_query(
22
+ {
23
+ :filter => "href==#{href}"
24
+ }).body[:VMRecord].first
25
+ return nil unless vm
26
+ vdc = current_vdc(vm[:vdc].split('/').last)
27
+ vapp = vdc.vapps.get_by_name(vm[:containerName])
28
+ vapp.vms.first
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ module Vcloud
2
+ module Fog
3
+ module RELATION
4
+ PARENT = 'up'
5
+ CHILD = 'down'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,257 @@
1
+ require 'forwardable'
2
+
3
+ module Vcloud
4
+ module Fog
5
+ class ServiceInterface
6
+ extend Forwardable
7
+
8
+ def_delegators :@fog, :get_vapp, :organizations, :org_name, :delete_vapp, :vcloud_token, :end_point,
9
+ :get_execute_query, :get_vapp_metadata, :power_off_vapp, :shutdown_vapp, :session,
10
+ :post_instantiate_vapp_template, :put_memory, :put_cpu, :power_on_vapp, :put_vapp_metadata_value,
11
+ :put_vm, :get_edge_gateway, :get_network, :delete_network, :post_create_org_vdc_network
12
+
13
+ #########################
14
+ # FogFacade Inner class to represent a logic free facade over our interactions with Fog
15
+
16
+ class FogFacade
17
+ def initialize
18
+ @vcloud = ::Fog::Compute::VcloudDirector.new
19
+ end
20
+
21
+ def get_vdc(name)
22
+ @vcloud.get_vdc(name).body
23
+ end
24
+
25
+ def get_organization (name)
26
+ @vcloud.get_organization(name).body
27
+ end
28
+
29
+ def session
30
+ @vcloud.get_current_session.body
31
+ end
32
+
33
+ def get_vapps_in_lease_from_query(options)
34
+ @vcloud.get_vapps_in_lease_from_query(options).body
35
+ end
36
+
37
+ def get_catalog_item(id)
38
+ @vcloud.get_catalog_item(id).body
39
+ end
40
+
41
+ def post_instantiate_vapp_template(vdc, template, name, params)
42
+ Vcloud::Core.logger.info("instantiating #{name} vapp in #{vdc[:name]}")
43
+ vapp = @vcloud.post_instantiate_vapp_template(extract_id(vdc), template, name, params).body
44
+ @vcloud.process_task(vapp[:Tasks][:Task])
45
+ @vcloud.get_vapp(extract_id(vapp)).body
46
+ end
47
+
48
+ def put_memory(vm_id, memory)
49
+ Vcloud::Core.logger.info("putting #{memory}MB memory into VM #{vm_id}")
50
+ task = @vcloud.put_memory(vm_id, memory).body
51
+ @vcloud.process_task(task)
52
+ end
53
+
54
+ def get_vapp(id)
55
+ @vcloud.get_vapp(id).body
56
+ end
57
+
58
+ def put_network_connection_system_section_vapp(vm_id, section)
59
+ task = @vcloud.put_network_connection_system_section_vapp(vm_id, section).body
60
+ @vcloud.process_task(task)
61
+ end
62
+
63
+ def put_cpu(vm_id, cpu)
64
+ Vcloud::Core.logger.info("putting #{cpu} CPU(s) into VM #{vm_id}")
65
+ task = @vcloud.put_cpu(vm_id, cpu).body
66
+ @vcloud.process_task(task)
67
+ end
68
+
69
+ def put_vm(id, name, options={})
70
+ Vcloud::Core.logger.info("updating name : #{name}, :options => #{options} in vm : #{id}")
71
+ task = @vcloud.put_vm(id, name, options).body
72
+ @vcloud.process_task(task)
73
+ end
74
+
75
+ def vcloud_token
76
+ @vcloud.vcloud_token
77
+ end
78
+
79
+ def end_point
80
+ @vcloud.end_point
81
+ end
82
+
83
+ def put_guest_customization_section_vapp(vm_id, customization_req)
84
+ task = @vcloud.put_guest_customization_section_vapp(vm_id, customization_req).body
85
+ @vcloud.process_task(task)
86
+ end
87
+
88
+ def get_execute_query(type=nil, options={})
89
+ @vcloud.get_execute_query(type, options).body
90
+ end
91
+
92
+ def get_vapp_metadata(id)
93
+ @vcloud.get_vapp_metadata(id).body
94
+ end
95
+
96
+
97
+ def organizations
98
+ @vcloud.organizations
99
+ end
100
+
101
+ def org_name
102
+ @vcloud.org_name
103
+ end
104
+
105
+ def delete_vapp(vapp_id)
106
+ task = @vcloud.delete_vapp(vapp_id).body
107
+ @vcloud.process_task(task)
108
+ end
109
+
110
+ def get_network(id)
111
+ @vcloud.get_network(id).body
112
+ end
113
+
114
+ def delete_network(id)
115
+ task = @vcloud.delete_network(id).body
116
+ @vcloud.process_task(task)
117
+ end
118
+
119
+ def post_create_org_vdc_network(vdc_id, name, options)
120
+ Vcloud::Core.logger.info("creating #{options[:fence_mode]} OrgVdcNetwork #{name} in vDC #{vdc_id}")
121
+ attrs = @vcloud.post_create_org_vdc_network(vdc_id, name, options).body
122
+ @vcloud.process_task(attrs[:Tasks][:Task])
123
+ get_network(extract_id(attrs))
124
+ end
125
+
126
+ def power_off_vapp(vapp_id)
127
+ task = @vcloud.post_power_off_vapp(vapp_id).body
128
+ @vcloud.process_task(task)
129
+ end
130
+
131
+ def power_on_vapp(vapp_id)
132
+ Vcloud::Core.logger.info("Powering on vApp #{vapp_id}")
133
+ task = @vcloud.post_power_on_vapp(vapp_id).body
134
+ @vcloud.process_task(task)
135
+ end
136
+
137
+ def shutdown_vapp(vapp_id)
138
+ task = @vcloud.post_shutdown_vapp(vapp_id).body
139
+ @vcloud.process_task(task)
140
+ end
141
+
142
+ def get_catalog(id)
143
+ @vcloud.get_catalog(id).body
144
+ end
145
+
146
+ def put_vapp_metadata_value(id, k, v)
147
+ Vcloud::Core.logger.info("putting metadata pair '#{k}'=>'#{v}' to #{id}")
148
+ # need to convert key to_s since Fog 0.17 borks on symbol key
149
+ task = @vcloud.put_vapp_metadata_item_metadata(id, k.to_s, v).body
150
+ @vcloud.process_task(task)
151
+ end
152
+
153
+ def get_edge_gateway(id)
154
+ @vcloud.get_edge_gateway(id).body
155
+ end
156
+
157
+ private
158
+ def extract_id(link)
159
+ link[:href].split('/').last
160
+ end
161
+ end
162
+ #
163
+ #########################
164
+
165
+
166
+
167
+ def initialize (fog = FogFacade.new)
168
+ @fog = fog
169
+ end
170
+
171
+ def org
172
+ link = session[:Link].select { |l| l[:rel] == RELATION::CHILD }.detect do |l|
173
+ l[:type] == ContentTypes::ORG
174
+ end
175
+ @fog.get_organization(link[:href].split('/').last)
176
+ end
177
+
178
+ def get_vapp_by_name_and_vdc_name name, vdc_name
179
+ response_body = @fog.get_vapps_in_lease_from_query({:filter => "name==#{name}"})
180
+ response_body[:VAppRecord].detect { |record| record[:vdcName] == vdc_name }
181
+ end
182
+
183
+ def catalog(name)
184
+ link = org[:Link].select { |l| l[:rel] == RELATION::CHILD }.detect do |l|
185
+ l[:type] == ContentTypes::CATALOG && l[:name] == name
186
+ end
187
+ raise "catalog #{name} cannot be found" unless link
188
+ @fog.get_catalog(extract_id(link))
189
+ end
190
+
191
+ def vdc(name)
192
+ link = org[:Link].select { |l| l[:rel] == RELATION::CHILD }.detect do |l|
193
+ l[:type] == ContentTypes::VDC && l[:name] == name
194
+ end
195
+ raise "vdc #{name} cannot be found" unless link
196
+ @fog.get_vdc(link[:href].split('/').last)
197
+
198
+ end
199
+
200
+ def template(catalog_name, template_name)
201
+ link = catalog(catalog_name)[:CatalogItems][:CatalogItem].detect do |l|
202
+ l[:type] == ContentTypes::CATALOG_ITEM && l[:name].match(template_name)
203
+ end
204
+ if link.nil?
205
+ Vcloud::Core.logger.warn("Template #{template_name} not found in catalog #{catalog_name}")
206
+ return nil
207
+ end
208
+ catalog_item = @fog.get_catalog_item(extract_id(link))
209
+ catalog_item[:Entity]
210
+ end
211
+
212
+
213
+ def put_network_connection_system_section_vapp(vm_id, section)
214
+ begin
215
+ Vcloud::Core.logger.info("adding NIC into VM #{vm_id}")
216
+ @fog.put_network_connection_system_section_vapp(vm_id, section)
217
+ rescue
218
+ Vcloud::Core.logger.info("failed to put_network_connection_system_section_vapp for vm : #{vm_id} ")
219
+ Vcloud::Core.logger.info("requested network section : #{section.inspect}")
220
+ raise
221
+ end
222
+ end
223
+
224
+ def find_networks(network_names, vdc_name)
225
+ network_names.collect do |network|
226
+ vdc(vdc_name)[:AvailableNetworks][:Network].detect do |l|
227
+ l[:type] == ContentTypes::NETWORK && l[:name] == network
228
+ end
229
+ end
230
+ end
231
+
232
+ def put_guest_customization_section(vm_id, vm_name, script)
233
+ begin
234
+ Vcloud::Core.logger.info("configuring guest customization section for vm : #{vm_id}")
235
+ customization_req = {
236
+ :Enabled => true,
237
+ :CustomizationScript => script,
238
+ :ComputerName => vm_name
239
+ }
240
+ @fog.put_guest_customization_section_vapp(vm_id, customization_req)
241
+ rescue
242
+ Vcloud::Core.logger.info("=== interpolated preamble:")
243
+ Vcloud::Core.logger.info(script)
244
+ raise
245
+ end
246
+ end
247
+
248
+ private
249
+ def extract_id(link)
250
+ link[:href].split('/').last
251
+ end
252
+
253
+ end
254
+
255
+ end
256
+ end
257
+
@@ -0,0 +1,26 @@
1
+ require 'simplecov'
2
+
3
+ SimpleCov.profiles.define 'gem' do
4
+ add_filter '/spec/'
5
+ add_filter '/features/'
6
+ add_filter '/vendor/'
7
+
8
+ add_group 'Libraries', '/lib/'
9
+ end
10
+
11
+ SimpleCov.start 'gem'
12
+
13
+ require 'bundler/setup'
14
+ require 'vcloud/core'
15
+ require 'support/stub_fog_interface.rb'
16
+
17
+
18
+ SimpleCov.at_exit do
19
+ SimpleCov.result.format!
20
+ # do not change the coverage percentage, instead add more unit tests to fix coverage failures.
21
+ if SimpleCov.result.covered_percent < 71
22
+ print "ERROR::BAD_COVERAGE\n"
23
+ print "Coverage is less than acceptable limit(71%). Please add more tests to improve the coverage"
24
+ exit(1)
25
+ end
26
+ end
@@ -0,0 +1,59 @@
1
+ require 'ostruct'
2
+
3
+ class StubFogInterface
4
+
5
+ def name
6
+ 'Test vDC 1'
7
+ end
8
+
9
+ def vdc_object_by_name(vdc_name)
10
+ vdc = OpenStruct.new
11
+ vdc.name = 'test-vdc-1'
12
+ vdc
13
+ end
14
+
15
+ def template
16
+ { :href => '/vappTemplate-12345678-90ab-cdef-0123-4567890abcde' }
17
+ end
18
+
19
+ def find_networks(network_names, vdc_name)
20
+ [{
21
+ :name => 'org-vdc-1-net-1',
22
+ :href => '/org-vdc-1-net-1-id',
23
+ }]
24
+ end
25
+
26
+ def get_vapp(id)
27
+ { :name => 'test-vapp-1' }
28
+ end
29
+
30
+ def get_edge_gateway(id)
31
+ {
32
+ :name => 'test-edgegw-1',
33
+ :href => "/#{id}",
34
+ }
35
+ end
36
+
37
+ def vdc(name)
38
+ { }
39
+ end
40
+
41
+ def post_instantiate_vapp_template(vdc, template, name, params)
42
+ {
43
+ :href => '/test-vapp-1-id',
44
+ :Children => {
45
+ :Vm => ['bogus vm data']
46
+ }
47
+ }
48
+ end
49
+
50
+ def get_vapp_by_vdc_and_name
51
+ { }
52
+ end
53
+
54
+ def template(catalog_name, name)
55
+ { :href => '/vappTemplate-12345678-90ab-cdef-0123-4567890abcde' }
56
+ end
57
+
58
+
59
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ module Vcloud
4
+ module Core
5
+ describe EdgeGateway do
6
+
7
+ before(:each) do
8
+ @edgegw_id = '12345678-1234-1234-1234-000000111454'
9
+ @mock_fog_interface = StubFogInterface.new
10
+ Vcloud::Fog::ServiceInterface.stub(:new).and_return(@mock_fog_interface)
11
+ end
12
+
13
+ context "Class public interface" do
14
+ it { EdgeGateway.should respond_to(:get_ids_by_name) }
15
+ it { EdgeGateway.should respond_to(:get_by_name) }
16
+ end
17
+
18
+ context "Instance public interface" do
19
+ subject { EdgeGateway.new(@edgegw_id) }
20
+ it { should respond_to(:id) }
21
+ it { should respond_to(:name) }
22
+ it { should respond_to(:href) }
23
+ end
24
+
25
+ context "#initialize" do
26
+
27
+ it "should be constructable from just an id reference" do
28
+ obj = EdgeGateway.new(@edgegw_id)
29
+ expect(obj.class).to be(Vcloud::Core::EdgeGateway)
30
+ end
31
+
32
+ it "should store the id specified" do
33
+ obj = EdgeGateway.new(@edgegw_id)
34
+ expect(obj.id) == @edgegw_id
35
+ end
36
+
37
+ it "should raise error if id is not in correct format" do
38
+ bogus_id = '123123-bogus-id-123445'
39
+ expect{ EdgeGateway.new(bogus_id) }.to raise_error("EdgeGateway id : #{bogus_id} is not in correct format" )
40
+ end
41
+
42
+ end
43
+
44
+ context "#get_by_name" do
45
+
46
+ it "should return a EdgeGateway object if name exists" do
47
+ q_results = [
48
+ { :name => 'edgegw-test-1', :href => "/#{@edgegw_id}" }
49
+ ]
50
+ mock_query = double(:query, :get_all_results => q_results)
51
+ Vcloud::Query.should_receive(:new).with('edgeGateway', :filter => "name==edgegw-test-1").and_return(mock_query)
52
+ @obj = EdgeGateway.get_by_name('edgegw-test-1')
53
+ expect(@obj.class).to be(Vcloud::Core::EdgeGateway)
54
+ end
55
+
56
+ it "should return an object with the correct id if name exists" do
57
+ q_results = [
58
+ { :name => 'edgegw-test-1', :href => "/#{@edgegw_id}" }
59
+ ]
60
+ mock_query = double(:query, :get_all_results => q_results)
61
+ Vcloud::Query.should_receive(:new).with('edgeGateway', :filter => "name==edgegw-test-1").and_return(mock_query)
62
+ @obj = EdgeGateway.get_by_name('edgegw-test-1')
63
+ expect(@obj.id) == @edgegw_id
64
+ end
65
+
66
+ it "should raise an error if no edgegw with that name exists" do
67
+ q_results = [ ]
68
+ mock_query = double(:query, :get_all_results => q_results)
69
+ Vcloud::Query.should_receive(:new).with('edgeGateway', :filter => "name==edgegw-test-1").and_return(mock_query)
70
+ expect{ EdgeGateway.get_by_name('edgegw-test-1') }.to raise_exception(RuntimeError, "edgeGateway edgegw-test-1 not found")
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+
79
+ end