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.
- data/.gitignore +2 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +20 -0
- data/README.md +103 -0
- data/Rakefile +18 -0
- data/bin/vcloud-query +84 -0
- data/jenkins.sh +10 -0
- data/lib/vcloud/core.rb +23 -0
- data/lib/vcloud/core/compute_metadata.rb +13 -0
- data/lib/vcloud/core/edge_gateway.rb +46 -0
- data/lib/vcloud/core/entity.rb +23 -0
- data/lib/vcloud/core/metadata_helper.rb +29 -0
- data/lib/vcloud/core/org_vdc_network.rb +102 -0
- data/lib/vcloud/core/query.rb +142 -0
- data/lib/vcloud/core/vapp.rb +118 -0
- data/lib/vcloud/core/vapp_template.rb +39 -0
- data/lib/vcloud/core/vdc.rb +37 -0
- data/lib/vcloud/core/version.rb +5 -0
- data/lib/vcloud/core/vm.rb +162 -0
- data/lib/vcloud/fog.rb +5 -0
- data/lib/vcloud/fog/content_types.rb +20 -0
- data/lib/vcloud/fog/model_interface.rb +33 -0
- data/lib/vcloud/fog/relation.rb +8 -0
- data/lib/vcloud/fog/service_interface.rb +257 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/stub_fog_interface.rb +59 -0
- data/spec/vcloud/core/edge_gateway_spec.rb +79 -0
- data/spec/vcloud/core/metadata_helper_spec.rb +89 -0
- data/spec/vcloud/core/org_vdc_network_spec.rb +257 -0
- data/spec/vcloud/core/query_spec.rb +111 -0
- data/spec/vcloud/core/vapp_spec.rb +173 -0
- data/spec/vcloud/core/vapp_template_spec.rb +77 -0
- data/spec/vcloud/core/vdc_spec.rb +68 -0
- data/spec/vcloud/core/vm_spec.rb +290 -0
- data/spec/vcloud/data/basic_preamble_test.erb +8 -0
- data/spec/vcloud/data/basic_preamble_test.erb.OUT +8 -0
- data/spec/vcloud/fog/fog_model_interface_spec.rb +25 -0
- data/spec/vcloud/fog/service_interface_spec.rb +30 -0
- data/vcloud-core.gemspec +30 -0
- metadata +198 -0
data/lib/vcloud/fog.rb
ADDED
@@ -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,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
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -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
|