knife-vcenter 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb5fd4c5ff94dae14a1fa45b1624ead2f0c89b04c130cd82fe59085b84e76b1c
4
- data.tar.gz: 9c18082a34dfc47c62f67b8d7aa073a869ec4ee83c19fe0e141dab6e51552768
3
+ metadata.gz: f5b64c8898d3f062d865d4d8ec26728caca8e5477cd60b4bb94812ddb6631167
4
+ data.tar.gz: 76f8c566aa4eb7d027490f7d6d70fffd07a45a2944cc7d3d09b357be600e856f
5
5
  SHA512:
6
- metadata.gz: ff27319d80c4ca3c0fc374c43f9deabfc7516a213ac2b7f6adb7b04a268a185044eb99a4324a36511a36ba8cc2bffc48c54dbd356b014d8b80fb0c67966d6a86
7
- data.tar.gz: a5f2845785c5bf531a6a8119f4cda2a512f77d37ad490192c07d3b1907f78487f287ac9f06dc1b0db85b570cd0d00c8dfcbaf6c6a765041bd6ec7d6fe094bc4b
6
+ metadata.gz: cadd9cf60dab6043f285e45d19042de4e34409e71f904bcfe1791e3ed2a3e9619da7b2df5bf036eb2c1895dbc2de849cf421a40c685fff398c9f3add337072c0
7
+ data.tar.gz: a742b7f205341ae1f6e3d3fd5702fa83215f5c5e588f2fdf6d660bce5becd5a7fe89972bc82aa4bc13249235fdf42cf92e916102d3bf8b9223ebc39a4f8d2cd2
@@ -21,19 +21,12 @@ require "chef/knife/cloud/exceptions"
21
21
  require "chef/knife/cloud/service"
22
22
  require "chef/knife/cloud/helpers"
23
23
  require "chef/knife/cloud/vcenter_service_helpers"
24
- require "net/http"
25
24
  require "uri"
26
25
  require "json"
27
26
  require "ostruct"
28
- require "lookup_service_helper"
29
- require "vapi"
30
- require "com/vmware/cis"
31
- require "com/vmware/vcenter"
32
- require "com/vmware/vcenter/vm"
33
- require "sso"
34
- require "base"
27
+ require "vsphere-automation-cis"
28
+ require "vsphere-automation-vcenter"
35
29
  require "set"
36
- require "support/clone_vm"
37
30
 
38
31
  class Chef
39
32
  # The main knife class
@@ -44,43 +37,30 @@ class Chef
44
37
  class VcenterService < Service
45
38
  include VcenterServiceHelpers
46
39
 
47
- attr_reader :vapi_config, :session_svc, :session_id
40
+ attr_reader :api_client, :session_api, :session_id
48
41
  attr_reader :connection_options, :ipaddress
49
42
 
50
43
  def initialize(options = {})
51
44
  super(options)
52
45
 
53
- # Using the information supplied, configure the connection to vCentre
54
- lookup_service_helper = LookupServiceHelper.new(options[:host])
55
-
56
- vapi_urls = lookup_service_helper.find_vapi_urls
57
- vapi_url = vapi_urls.values[0]
58
- Base.log.info(format("Vapi URL: %s", vapi_url)) if options[:vcenter_logs]
59
-
60
- # Create the VAPI config object
61
- ssl_options = {}
62
- ssl_options[:verify] = if options[:verify_ssl]
63
- :peer
64
- else
65
- Base.log.warn("SSL Verification is turned OFF") if options[:vcenter_logs]
66
- :none
67
- end
68
- @vapi_config = VAPI::Bindings::VapiConfig.new(vapi_url, ssl_options)
69
-
70
- # get the SSO url
71
- sso_url = lookup_service_helper.find_sso_url
72
- sso = SSO::Connection.new(sso_url).login(options[:username], options[:password])
73
- token = sso.request_bearer_token
74
- vapi_config.set_security_context(
75
- VAPI::Security.create_saml_bearer_security_context(token.to_s)
76
- )
77
-
78
- # Login and get the session information
79
- @session_svc = Com::Vmware::Cis::Session.new(vapi_config)
80
- @session_id = session_svc.create
81
- vapi_config.set_security_context(
82
- VAPI::Security.create_session_security_context(session_id)
83
- )
46
+ configuration = VSphereAutomation::Configuration.new.tap do |c|
47
+ c.host = options[:host]
48
+ c.username = options[:username]
49
+ c.password = options[:password]
50
+ c.scheme = "https"
51
+ c.verify_ssl = options[:verify_ssl]
52
+ c.verify_ssl_host = options[:verify_ssl]
53
+ end
54
+
55
+ Base.log.warn("SSL Verification is turned OFF") if options[:logs] && !options[:verify_ssl]
56
+
57
+ @api_client = VSphereAutomation::ApiClient.new(configuration)
58
+ api_client.default_headers["Authorization"] = configuration.basic_auth_token
59
+
60
+ session_api = VSphereAutomation::CIS::SessionApi.new(api_client)
61
+ session_id = session_api.create("").value
62
+
63
+ api_client.default_headers["vmware-api-session-id"] = session_id
84
64
 
85
65
  # Set the class properties for the rbvmomi connections
86
66
  @connection_options = {
@@ -96,7 +76,7 @@ class Chef
96
76
  # @param [Object] options to override anything you need to do
97
77
  def create_server(options = {})
98
78
  # Create the vm object
99
- vmobj = Com::Vmware::Vcenter::VM.new(vapi_config)
79
+ vm_api = VSphereAutomation::VCenter::VMApi.new(api_client)
100
80
 
101
81
  # Use the option to determine now a new machine is being created
102
82
  case options[:type]
@@ -128,24 +108,24 @@ class Chef
128
108
  when "create"
129
109
 
130
110
  # Create the placement object
131
- placementspec = Com::Vmware::Vcenter::VM::PlacementSpec.new
132
- placementspec.folder = get_folder(options[:folder])
133
- placementspec.host = get_host(options[:targethost])
134
- placementspec.datastore = get_datastore(options[:datastore])
135
- placementspec.resource_pool = get_resourcepool(options[:resource_pool])
111
+ placement_spec = VSphereAutomation::VCenter::VcenterVMPlacementSpec.new( ###
112
+ folder: get_folder(options[:folder]),
113
+ host: get_host(options[:targethost]).host,
114
+ datastore: get_datastore(options[:datastore]),
115
+ resource_pool: get_resourcepool(options[:resource_pool])
116
+ )
136
117
 
137
118
  # Create the CreateSpec object
138
- createspec = Com::Vmware::Vcenter::VM::CreateSpec.new
139
-
140
- createspec.name = options[:name]
141
- puts "seting the OS"
142
- createspec.guest_OS = Com::Vmware::Vcenter::Vm::GuestOS::UBUNTU_64
143
- puts "setting the placement"
144
- createspec.placement = placementspec
119
+ create_spec = VSphereAutomation::VCenter::VcenterVMCreateSpec.new(
120
+ name: options[:name],
121
+ guest_OS: VSphereAutomation::VCenter::VcenterVmGuestOS::OTHER,
122
+ placement: placement_spec
123
+ )
145
124
 
146
125
  # Create the new machine
147
126
  begin
148
- vm = vmobj.create(createspec)
127
+ create_model = VSphereAutomation::VCenter::VcenterVMCreate.new(spec: create_spec)
128
+ vm = vm_api.create(create_model).value
149
129
  rescue StandardError => e
150
130
  puts e.message
151
131
  end
@@ -155,111 +135,112 @@ class Chef
155
135
  # Get a list of vms from the API
156
136
  #
157
137
  def list_servers
158
- Com::Vmware::Vcenter::VM.new(vapi_config).list
138
+ vms = VSphereAutomation::VCenter::VMApi.new(api_client).list.value
139
+
140
+ # list_resource_command uses .send(:name) syntax, so convert to OpenStruct to keep it compatible
141
+ vms.map { |vmsummary| OpenStruct.new(vmsummary.to_hash) }
159
142
  end
160
143
 
161
144
  # Return a list of the hosts in the vCenter
162
145
  #
163
146
  def list_hosts
164
- Com::Vmware::Vcenter::Host.new(vapi_config).list
147
+ VSphereAutomation::VCenter::HostApi.new(api_client).list.value
165
148
  end
166
149
 
167
150
  # Return a list of the datacenters in the vCenter
168
151
  #
169
152
  def list_datacenters
170
- Com::Vmware::Vcenter::Datacenter.new(vapi_config).list
153
+ VSphereAutomation::VCenter::DatacenterApi.new(api_client).list.value
171
154
  end
172
155
 
173
156
  # Return a list of the clusters in the vCenter
174
157
  #
175
158
  def list_clusters
176
- Com::Vmware::Vcenter::Cluster.new(vapi_config).list
159
+ VSphereAutomation::VCenter::ClusterApi.new(api_client).list.value
177
160
  end
178
161
 
179
162
  # Checks to see if the datacenter exists in the vCenter
180
163
  #
181
164
  # @param [String] name is the name of the datacenter
182
165
  def datacenter_exists?(name)
183
- filter = Com::Vmware::Vcenter::Datacenter::FilterSpec.new(names: Set.new([name]))
184
- dc_obj = Com::Vmware::Vcenter::Datacenter.new(vapi_config)
185
- dc = dc_obj.list(filter)
166
+ dc_api = VSphereAutomation::VCenter::DatacenterApi.new(api_client)
167
+ dcs = dc_api.list({ filter_names: name }).value
186
168
 
187
- raise format("Unable to find data center: %s", name) if dc.empty?
169
+ raise format("Unable to find data center: %s", name) if dcs.empty?
188
170
  end
189
171
 
190
172
  # Gets the folder
191
173
  #
192
174
  # @param [String] name is the folder of the datacenter
193
175
  def get_folder(name)
194
- # Create a filter to ensure that only the named folder is returned
195
- filter = Com::Vmware::Vcenter::Folder::FilterSpec.new(names: Set.new([name]))
196
- # filter.names = name
197
- folder_obj = Com::Vmware::Vcenter::Folder.new(vapi_config)
198
- folder = folder_obj.list(filter)
176
+ folder_api = VSphereAutomation::VCenter::FolderApi.new(api_client)
177
+ folders = folder_api.list({ filter_names: name }).value
178
+
179
+ raise format("Unable to find folder: %s", name) if folders.empty?
199
180
 
200
- folder[0].folder
181
+ folders.first.folder
201
182
  end
202
183
 
203
184
  # Gets the host
204
185
  #
205
186
  # @param [String] name is the host of the datacenter
206
187
  def get_host(name)
207
- host_obj = Com::Vmware::Vcenter::Host.new(vapi_config)
188
+ # create a host object to work with
189
+ host_api = VSphereAutomation::VCenter::HostApi.new(api_client)
208
190
 
209
191
  if name.nil?
210
- host = host_obj.list
192
+ hosts = host_api.list.value
211
193
  else
212
- filter = Com::Vmware::Vcenter::Host::FilterSpec.new(names: Set.new([name]))
213
- host = host_obj.list(filter)
194
+ hosts = host_api.list({ filter_names: name }).value
214
195
  end
215
196
 
216
- host[0].host
197
+ raise format("Unable to find target host: %s", name) if hosts.empty?
198
+
199
+ hosts.first
217
200
  end
218
201
 
219
202
  # Gets the datastore
220
203
  #
221
204
  # @param [String] name is the datastore of the datacenter
222
205
  def get_datastore(name)
223
- datastore_obj = Com::Vmware::Vcenter::Datastore.new(vapi_config)
206
+ ds_api = VSphereAutomation::VCenter::DatastoreApi.new(api_client)
207
+ ds = ds_api.list({ filter_names: name }).value
224
208
 
225
- if name.nil?
226
- datastore = datastore_obj.list
227
- else
228
- filter = Com::Vmware::Vcenter::Datastore::FilterSpec.new(names: Set.new([name]))
229
- datastore = datastore_obj.list(filter)
230
- end
231
-
232
- datastore[0].datastore
209
+ raise format("Unable to find data store: %s", name) if ds.empty?
210
+ ds.first.datastore
233
211
  end
234
212
 
235
213
  # Gets the resource_pool
236
214
  #
237
215
  # @param [String] name is the resource_pool of the datacenter
238
- def get_resource_pool(name)
239
- # Create a resource pool object
240
- rp_obj = Com::Vmware::Vcenter::ResourcePool.new(vapi_config)
216
+ def get_resourcepool(name)
217
+ ### verify
218
+ rp_api = VSphereAutomation::VCenter::ResourcePoolApi.new(api_client)
241
219
 
242
- # If a name has been set then try to find it, otherwise use the first
243
- # resource pool that can be found
244
220
  if name.nil?
245
- resource_pool = rp_obj.list
221
+ # Remove default pool for first pass (<= 1.2.1 behaviour to pick first user-defined pool found)
222
+ resource_pools = rp_api.list.value.delete_if { |pool| pool.name == "Resources" }
223
+ puts "Search of all resource pools found: " + resource_pools.map { |pool| pool.name }.to_s
224
+
225
+ # Revert to default pool, if no user-defined pool found (> 1.2.1 behaviour)
226
+ # (This one might not be found under some circumstances by the statement above)
227
+ return get_resource_pool("Resources") if resource_pools.empty?
246
228
  else
247
- # create a filter to find the named resource pool
248
- filter = Com::Vmware::Vcenter::ResourcePool::FilterSpec.new(names: Set.new([name]))
249
- resource_pool = rp_obj.list(filter)
250
- raise format("Unable to find Resource Pool: %s", name) if resource_pool.nil?
229
+ resource_pools = rp_api.list({ filter_names: name }).value
230
+ puts "Search for resource pools found: " + resource_pools.map { |pool| pool.name }.to_s
251
231
  end
252
232
 
253
- resource_pool[0].resource_pool
233
+ raise format("Unable to find Resource Pool: %s", name) if resource_pools.empty?
234
+
235
+ resource_pools.first.resource_pool
254
236
  end
255
237
 
256
238
  # Gets the server
257
239
  #
258
240
  # @param [String] name is the server of the datacenter
259
241
  def get_server(name)
260
- filter = Com::Vmware::Vcenter::VM::FilterSpec.new(names: Set.new([name]))
261
- vm_obj = Com::Vmware::Vcenter::VM.new(vapi_config)
262
- vm_obj.list(filter)[0]
242
+ vm_api = VSphereAutomation::VCenter::VMApi.new(api_client)
243
+ vm_api.list({ filter_names: name }).value.first
263
244
  end
264
245
 
265
246
  # Deletes the VM
@@ -272,16 +253,16 @@ class Chef
272
253
 
273
254
  ui.confirm("Do you really want to be delete this virtual machine")
274
255
 
275
- vm_obj = Com::Vmware::Vcenter::VM.new(vapi_config)
256
+ vm_api = VSphereAutomation::VCenter::VMApi.new(api_client)
276
257
 
277
258
  # check the power state of the machine, if it is powered on turn it off
278
- if vm.power_state.value == "POWERED_ON"
279
- power = Com::Vmware::Vcenter::Vm::Power.new(vapi_config)
259
+ if vm.power_state == "POWERED_ON"
260
+ power_api = VSphereAutomation::VCenter::VmPowerApi.new(api_client)
280
261
  ui.msg("Shutting down machine")
281
- power.stop(vm.vm)
262
+ power_api.stop(vm.vm)
282
263
  end
283
264
 
284
- vm_obj.delete(vm.vm)
265
+ vm_api.delete(vm.vm)
285
266
  end
286
267
 
287
268
  # Gets some server information
@@ -58,8 +58,7 @@ class Chef
58
58
  #
59
59
  # @param [Object] status takes the number and formats it how you need it to
60
60
  def format_power_status(status)
61
- status_check = status.value
62
- status_color = case status_check
61
+ status_color = case status
63
62
  when "POWERED_OFF"
64
63
  :red
65
64
  when "POWERED_ON"
@@ -68,7 +67,7 @@ class Chef
68
67
  :yellow
69
68
  end
70
69
 
71
- ui.color(status.value, status_color)
70
+ ui.color(status, status_color)
72
71
  end
73
72
  end
74
73
  end
@@ -53,8 +53,7 @@ class Chef
53
53
  # Sets the color for the different status of the machines
54
54
  #
55
55
  def format_power_status(status)
56
- status_check = status.value
57
- status_color = case status_check
56
+ status_color = case status
58
57
  when "POWERED_OFF"
59
58
  :red
60
59
  when "POWERED_ON"
@@ -63,7 +62,7 @@ class Chef
63
62
  :yellow
64
63
  end
65
64
 
66
- ui.color(status.value, status_color)
65
+ ui.color(status, status_color)
67
66
  end
68
67
 
69
68
  # Formats the memory value
@@ -20,5 +20,5 @@
20
20
  # Provisions machines in vCenter
21
21
  module KnifeVcenter
22
22
  # The version of this amazing Gem, you should <3 it.
23
- VERSION = "2.0.1"
23
+ VERSION = "2.0.2"
24
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-vcenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef Partner Engineering
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-28 00:00:00.000000000 Z
11
+ date: 2019-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: knife-cloud
@@ -72,30 +72,30 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '6.6'
75
+ version: '0.1'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '6.6'
82
+ version: '0.1'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '1.7'
89
+ version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '1.7'
96
+ version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: debase
98
+ name: pry
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -109,7 +109,21 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: pry
112
+ name: ruby-debug-ide
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.6.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.6.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rake
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - ">="
@@ -123,19 +137,33 @@ dependencies:
123
137
  - !ruby/object:Gem::Version
124
138
  version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
- name: ruby-debug-ide
140
+ name: rspec
127
141
  requirement: !ruby/object:Gem::Requirement
128
142
  requirements:
129
143
  - - "~>"
130
144
  - !ruby/object:Gem::Version
131
- version: 0.6.0
145
+ version: '3.7'
132
146
  type: :development
133
147
  prerelease: false
134
148
  version_requirements: !ruby/object:Gem::Requirement
135
149
  requirements:
136
150
  - - "~>"
137
151
  - !ruby/object:Gem::Version
138
- version: 0.6.0
152
+ version: '3.7'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-rspec
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.18'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.18'
139
167
  description: Knife plugin to VMware vCenter.
140
168
  email:
141
169
  - partnereng@chef.io
@@ -144,7 +172,6 @@ extensions: []
144
172
  extra_rdoc_files: []
145
173
  files:
146
174
  - LICENSE
147
- - lib/base.rb
148
175
  - lib/chef/knife/cloud/vcenter_service.rb
149
176
  - lib/chef/knife/cloud/vcenter_service_helpers.rb
150
177
  - lib/chef/knife/cloud/vcenter_service_options.rb
@@ -157,8 +184,6 @@ files:
157
184
  - lib/chef/knife/vcenter_vm_list.rb
158
185
  - lib/chef/knife/vcenter_vm_show.rb
159
186
  - lib/knife-vcenter/version.rb
160
- - lib/lookup_service_helper.rb
161
- - lib/sso.rb
162
187
  - lib/support/clone_vm.rb
163
188
  - spec/spec_helper.rb
164
189
  - spec/unit/vcenter_vm_list_spec.rb
@@ -174,7 +199,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
174
199
  requirements:
175
200
  - - ">="
176
201
  - !ruby/object:Gem::Version
177
- version: '0'
202
+ version: '2.3'
178
203
  required_rubygems_version: !ruby/object:Gem::Requirement
179
204
  requirements:
180
205
  - - ">="
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
- #
3
- # Author:: Chef Partner Engineering (<partnereng@chef.io>)
4
- # Copyright:: Copyright (c) 2017-2018 Chef Software, Inc.
5
- # License:: Apache License, Version 2.0
6
- #
7
- # Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- # See the License for the specific language governing permissions and
17
- # limitations under the License.
18
- #
19
-
20
- require "logger"
21
-
22
- # Base module for vcenter knife commands
23
- module Base
24
- attr_accessor :log
25
-
26
- # Creates the @log variable
27
- #
28
- def self.log
29
- @log ||= init_logger
30
- end
31
-
32
- # Set the logger level by default
33
- #
34
- def self.init_logger
35
- log = Logger.new(STDOUT)
36
- log.progname = "Knife VCenter"
37
- log.level = Logger::INFO
38
- log
39
- end
40
- end
@@ -1,457 +0,0 @@
1
- # Copyright 2014-2017 VMware, Inc. All Rights Reserved.
2
- # SPDX-License-Identifier: MIT
3
-
4
- require "savon"
5
- require "nokogiri"
6
- require "base"
7
- # require 'sample/framework/sample_base'
8
-
9
- # Utility class that helps use the lookup service.
10
- class LookupServiceHelper
11
- attr_reader :sample, :wsdl_url, :soap_url
12
- attr_reader :serviceRegistration
13
-
14
- # Constructs a new instance.
15
- # @param [Object] host the associated sample, which provides access
16
- # to the configuration properties of the sample
17
- def initialize(host)
18
- @soap_url = format("https://%s/lookupservice/sdk", host)
19
- @wsdl_url = format("https://%s/lookupservice/wsdl/lookup.wsdl", host)
20
- end
21
-
22
- # Connects to the lookup service.
23
- def connect
24
- rsc = RetrieveServiceContent.new(client).invoke
25
- @serviceRegistration = rsc.get_service_registration
26
- Base.log.info "service registration = #{serviceRegistration}"
27
- end
28
-
29
- # Finds the SSO service URL.
30
- # In a MxN setup where there are more than one PSC nodes;
31
- # This method returns the first SSO service endpoint URL
32
- # as returned by the lookup service.
33
- #
34
- # @return [String] SSO Service endpoint URL.
35
- def find_sso_url
36
- result = find_service_url(product = "com.vmware.cis",
37
- service = "cs.identity",
38
- endpoint = "com.vmware.cis.cs.identity.sso",
39
- protocol = "wsTrust")
40
- raise "SSO URL not found" unless result && !result.empty?
41
-
42
- result.values[0]
43
- end
44
-
45
- # Finds all the vAPI service endpoint URLs.
46
- # In a MxN setup where there are more than one management node;
47
- # this method returns more than one URL
48
- #
49
- # @return [Hash] vapi service endpoint URLs in a dictionary
50
- # where the key is the node_id and the value is the service URL.
51
- def find_vapi_urls
52
- find_service_url(product = "com.vmware.cis",
53
- service = "cs.vapi",
54
- endpoint = "com.vmware.vapi.endpoint",
55
- protocol = "vapi.json.https.public")
56
- end
57
-
58
- # Finds the vapi service endpoint URL of a management node.
59
- #
60
- # @param node_id [String] The UUID of the management node.
61
- # @return [String] vapi service endpoint URL of a management node or
62
- # nil if no vapi endpoint is found.
63
- def find_vapi_url(node_id)
64
- raise "node_id is required" if node_id.nil?
65
-
66
- result = find_vapi_urls
67
- raise "VAPI URLs not found" unless result && !result.empty?
68
-
69
- result[node_id]
70
- end
71
-
72
- # Finds all the vim service endpoint URLs
73
- # In a MxN setup where there are more than one management node;
74
- # this method returns more than one URL
75
- #
76
- # @return [Hash] vim service endpoint URLs in a dictionary where
77
- # the key is the node_id and the value is the service URL.
78
- def find_vim_urls
79
- find_service_url(product = "com.vmware.cis",
80
- service = "vcenterserver",
81
- endpoint = "com.vmware.vim",
82
- protocol = "vmomi")
83
- end
84
-
85
- # Finds the vim service endpoint URL of a management node
86
- #
87
- # @param node_id [String] The UUID of the management node.
88
- # @return [String] vim service endpoint URL of a management node or
89
- # nil if no vim endpoint is found.
90
- def find_vim_url(node_id)
91
- raise "node_id is required" if node_id.nil?
92
-
93
- result = find_vim_urls
94
- raise "VIM URLs not found" unless result && !result.empty?
95
-
96
- result[node_id]
97
- end
98
-
99
- # Finds all the spbm service endpoint URLs
100
- # In a MxN setup where there are more than one management node;
101
- # this method returns more than one URL
102
- #
103
- # @return [Hash] spbm service endpoint URLs in a dictionary where
104
- # the key is the node_id and the value is the service URL.
105
- def find_vim_pbm_urls
106
- find_service_url(product = "com.vmware.vim.sms",
107
- service = "sms",
108
- endpoint = "com.vmware.vim.pbm",
109
- protocol = "https")
110
- end
111
-
112
- # Finds the spbm service endpoint URL of a management node
113
- #
114
- # @param node_id [String] The UUID of the management node.
115
- # @return [String] spbm service endpoint URL of a management node or
116
- # nil if no spbm endpoint is found.
117
- def find_vim_pbm_url(node_id)
118
- raise "node_id is required" if node_id.nil?
119
-
120
- result = find_vim_pbm_urls
121
- raise "PBM URLs not found" unless result && !result.empty?
122
-
123
- result[node_id]
124
- end
125
-
126
- # Get the management node id from the instance name
127
- #
128
- # @param instance_name [String] The instance name of the management node
129
- # @return [String] The UUID of the management node or
130
- # nil is no management node is found by the given instance name
131
- def get_mgmt_node_id(instance_name)
132
- raise "instance_name is required" if instance_name.nil?
133
- result = find_mgmt_nodes()
134
- raise "Management nodes not found" unless result && result.size > 0
135
- result[instance_name]
136
- end
137
-
138
- def get_mgmt_node_instance_name(node_id)
139
- raise "node_id is required" if node_id.nil?
140
-
141
- result = find_mgmt_nodes
142
- raise "Management nodes not found" unless result && !result.empty?
143
-
144
- result.each { |k, v| return k if v == node_id }
145
- nil
146
- end
147
-
148
- # Finds the instance name and UUID of the management node for M1xN1 or
149
- # when the PSC and management services all reside on a single node.
150
- def get_default_mgmt_node
151
- result = find_mgmt_nodes
152
- raise "Management nodes not found" unless result && !result.empty?
153
-
154
- # WHY: raise MultipleManagementNodeException.new if result.size > 1
155
- [result.keys[0], result.values[0]]
156
- end
157
-
158
- # Finds all the management nodes
159
- #
160
- # @return [Hash] management node instance name and node id (UUID) in a dictionary.
161
- def find_mgmt_nodes
162
- # assert self.serviceRegistration is not None
163
- list = List.new(client, "com.vmware.cis", "vcenterserver",
164
- "vmomi", "com.vmware.vim")
165
-
166
- list.invoke
167
- list.get_instance_names
168
- end
169
-
170
- private
171
-
172
- # Finds a service URL with the given attributes.
173
- def find_service_url(product, service, endpoint, protocol)
174
- # assert serviceRegistration is not None
175
- list = List.new(client, product, service, protocol, endpoint)
176
-
177
- list.invoke
178
- list.get_service_endpoints
179
- end
180
-
181
- # Gets or creates the Savon client instance.
182
- def client
183
- @client ||= Savon.client do |globals|
184
- # see: http://savonrb.com/version2/globals.html
185
- globals.wsdl wsdl_url
186
- globals.endpoint soap_url
187
-
188
- globals.strip_namespaces false
189
- globals.env_namespace :S
190
-
191
- # set like this so https connection does not fail
192
- # TODO: find an acceptable solution for production
193
- globals.ssl_verify_mode :none
194
-
195
- # dev/debug settings
196
- # globals.pretty_print_xml ENV['DEBUG_SOAP']
197
- # globals.log ENV['DEBUG_SOAP']
198
- end
199
- end
200
- end
201
-
202
- # @abstract Base class for invocable service calls.
203
- class Invocable
204
- attr_reader :operation, :client, :response
205
-
206
- # Constructs a new instance.
207
- # @param operation [Symbol] the operation name
208
- # @param client [Savon::Client] the client
209
- def initialize(operation, client)
210
- @operation = operation
211
- @client = client
212
- end
213
-
214
- # Invokes the service call represented by this type.
215
- def invoke
216
- request = request_xml.to_s
217
- Base.log.debug(request)
218
- @response = client.call(operation, xml: request)
219
- Base.log.debug(response)
220
- self # for chaining with new
221
- end
222
-
223
- # Builds the request XML content.
224
- def request_xml
225
- builder = Builder::XmlMarkup.new
226
- builder.instruct!(:xml, encoding: "UTF-8")
227
-
228
- builder.tag!("S:Envelope",
229
- "xmlns:S" => "http://schemas.xmlsoap.org/soap/envelope/") do |envelope|
230
- envelope.tag!("S:Body") do |body|
231
- body_xml(body)
232
- end
233
- end
234
- builder.target!
235
- end
236
-
237
- # Builds the body portion of the request XML content.
238
- # Specific service operations must override this method.
239
- def body_xml
240
- raise "abstract method not implemented!"
241
- end
242
-
243
- # Gets the response XML content.
244
- def response_xml
245
- raise "illegal state: response not set yet" if response.nil?
246
-
247
- @response_xml ||= Nokogiri::XML(response.to_xml)
248
- end
249
-
250
- def response_hash
251
- @response_hash ||= response.to_hash
252
- end
253
- end
254
-
255
- # Encapsulates the list operation of the lookup service.
256
- class List < Invocable
257
- # Constructs a new instance.
258
- def initialize(client, product, service, protocol, endpoint)
259
- super(:list, client)
260
-
261
- @product = product
262
- @service = service
263
- @protocol = protocol
264
- @endpoint = endpoint
265
- end
266
-
267
- # <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
268
- # <S:Body>
269
- # <List xmlns="urn:lookup">
270
- # <_this type="LookupServiceRegistration">ServiceRegistration</_this>
271
- # <filterCriteria>
272
- # <serviceType>
273
- # <product>com.vmware.cis</product>
274
- # <type>cs.identity</type>
275
- # </serviceType>
276
- # <endpointType>
277
- # <protocol>wsTrust</protocol>
278
- # <type>com.vmware.cis.cs.identity.sso</type>
279
- # </endpointType>
280
- # </filterCriteria>
281
- # </List>
282
- # </S:Body>
283
- # </S:Envelope>
284
- def body_xml(body)
285
- body.tag!("List", "xmlns" => "urn:lookup") do |list|
286
- # TODO: use the copy that was retrieved on startup?
287
- list.tag!("_this",
288
- "type" => "LookupServiceRegistration") do |this|
289
- this << "ServiceRegistration"
290
- end
291
- list.tag!("filterCriteria") do |criteria|
292
- criteria.tag!("serviceType") do |stype|
293
- stype.tag!("product") do |p|
294
- p << @product
295
- end
296
- stype.tag!("type") do |t|
297
- t << @service
298
- end
299
- end
300
- criteria.tag!("endpointType") do |etype|
301
- etype.tag!("protocol") do |p|
302
- p << @protocol
303
- end
304
- etype.tag!("type") do |t|
305
- t << @endpoint
306
- end
307
- end
308
- end
309
- end
310
- end
311
-
312
- # Gets the service endpoint information from the response.
313
- # Support for MxN.
314
- # @return [Hash] a hash where the key is NodeId and the Value is a Service URL
315
- def get_service_endpoints
316
- result = {}
317
- # <ListResponse xmlns="urn:lookup">
318
- # <returnval>
319
- # <serviceVersion>2.0</serviceVersion>
320
- # <vendorNameResourceKey/>
321
- # <vendorNameDefault/>
322
- # <vendorProductInfoResourceKey/>
323
- # <vendorProductInfoDefault/>
324
- # <serviceEndpoints>
325
- # <url>https://pa-rdinfra3-vm7-dhcp5583.eng.vmware.com/sts/STSService/vsphere.local</url>
326
- # <endpointType>
327
- # <protocol>wsTrust</protocol>
328
- # <type>com.vmware.cis.cs.identity.sso</type>
329
- # </endpointType>
330
- # <sslTrust>
331
- # ...
332
- # </sslTrust>
333
- # </serviceEndpoints>
334
- # <serviceNameResourceKey/>
335
- # <serviceNameDefault/>
336
- # <serviceDescriptionResourceKey/>
337
- # <serviceDescriptionDefault/>
338
- # <ownerId>pa-rdinfra3-vm7-dhcp5583.eng.vmware.com@vsphere.local</ownerId>
339
- # <serviceType>
340
- # <product>com.vmware.cis</product>
341
- # <type>cs.identity</type>
342
- # </serviceType>
343
- # <nodeId/>
344
- # <serviceId>6a8a5058-5d3d-4d42-bb5e-383b91c8732e</serviceId>
345
- # <siteId>default-first-site</siteId>
346
- # </returnval>
347
- # </ListResponse>
348
- Base.log.debug "List: response_hash = #{response_hash}"
349
- return_val = response_hash[:list_response][:returnval]
350
- return_val = [return_val] if return_val.is_a? Hash
351
- return_val.each do |entry|
352
- # FYI: the node_id is sometimes null, so use the service_id in this case
353
- node_id = entry[:node_id] || entry[:service_id]
354
- result[node_id] = entry[:service_endpoints][:url]
355
- end
356
- Base.log.debug "List: result = #{result}"
357
- result
358
- end
359
-
360
- def get_instance_names
361
- result = {}
362
- # <serviceAttributes>
363
- # <key>com.vmware.cis.cm.GroupInternalId</key>
364
- # <value>com.vmware.vim.vcenter</value>
365
- # </serviceAttributes>
366
- # <serviceAttributes>
367
- # <key>com.vmware.cis.cm.ControlScript</key>
368
- # <value>vmware-vpxd.sh</value>
369
- # </serviceAttributes>
370
- # <serviceAttributes>
371
- # <key>com.vmware.cis.cm.HostId</key>
372
- # <value>906477a1-24c6-4d48-9e99-55ef962878f7</value>
373
- # </serviceAttributes>
374
- # <serviceAttributes>
375
- # <key>com.vmware.vim.vcenter.instanceName</key>
376
- # <value>pa-rdinfra3-vm7-dhcp5583.eng.vmware.com</value>
377
- # </serviceAttributes>
378
- Base.log.debug "List: response_hash = #{response_hash}"
379
- return_val = response_hash[:list_response][:returnval]
380
- return_val = [return_val] if return_val.is_a? Hash
381
- return_val.each do |entry|
382
- node_id = entry[:node_id]
383
- # TODO: is it possible there be 0 or 1 attrs? if so, deal with it.
384
- attrs = entry[:service_attributes]
385
- Base.log.debug "List: attrs=#{attrs}"
386
- attrs.each do |attr|
387
- if attr[:key] == "com.vmware.vim.vcenter.instanceName"
388
- result[attr[:value]] = node_id
389
- end
390
- end
391
- end
392
- Base.log.debug "List: result = #{result}"
393
- result
394
- end
395
- end
396
-
397
- # Encapsulates the RetrieveServiceContent operation of the lookup service.
398
- class RetrieveServiceContent < Invocable
399
- # Constructs a new instance.
400
- def initialize(client)
401
- super(:retrieve_service_content, client)
402
- end
403
-
404
- # <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
405
- # <S:Body>
406
- # <RetrieveServiceContent xmlns="urn:lookup">
407
- # <_this type="LookupServiceInstance">ServiceInstance</_this>
408
- # </RetrieveServiceContent>
409
- # </S:Body>
410
- # </S:Envelope>
411
- def body_xml(body)
412
- body.tag!("RetrieveServiceContent", "xmlns" => "urn:lookup") do |rsc|
413
- rsc.tag!("_this", "type" => "LookupServiceInstance") do |this|
414
- this << "ServiceInstance"
415
- end
416
- end
417
- end
418
-
419
- # ...
420
- # <RetrieveServiceContentResponse xmlns="urn:lookup">
421
- # <returnval>
422
- # <lookupService type="LookupLookupService">lookupService</lookupService>
423
- # <serviceRegistration type="LookupServiceRegistration">ServiceRegistration</serviceRegistration>
424
- # <deploymentInformationService type="LookupDeploymentInformationService">deploymentInformationService</deploymentInformationService>
425
- # <l10n type="LookupL10n">l10n</l10n>
426
- # </returnval>
427
- # </RetrieveServiceContentResponse>
428
- # ...
429
- def get_service_registration
430
- Base.log.debug "RetrieveServiceContent: response_hash = #{response_hash}"
431
- return_val = response_hash[:retrieve_service_content_response][:returnval]
432
- result = return_val[:service_registration]
433
- Base.log.debug "RetrieveServiceContent: result = #{result}"
434
- result
435
- end
436
- end
437
-
438
- class MultipleManagementNodeException < RuntimeError
439
- end
440
-
441
- # main: quick self tester
442
- if $PROGRAM_NAME == __FILE__
443
- Base.log.level = Logger::DEBUG if ENV["DEBUG"]
444
- sample = SelfTestSample.new
445
- sample.ls_ip = ARGV[0] || "10.67.245.207"
446
- # MXN: sample.ls_ip = '10.160.42.83'
447
- # MXN: sample.ls_ip = '10.160.35.191'
448
- # MAYBE: sample.main() # for arg parsing
449
- ls_helper = LookupServiceHelper.new(sample)
450
- ls_helper.connect
451
- puts "***************************************"
452
- puts "SSO URL: #{ls_helper.find_sso_url}"
453
- puts "VAPI URL: #{ls_helper.find_vapi_urls}"
454
- puts "VIM URL: #{ls_helper.find_vim_urls}"
455
- puts "PBM URL: #{ls_helper.find_vim_pbm_urls}"
456
- puts "Mgmt Nodes: #{ls_helper.find_mgmt_nodes}"
457
- end
data/lib/sso.rb DELETED
@@ -1,264 +0,0 @@
1
- # Copyright 2014-2017 VMware, Inc. All Rights Reserved.
2
- # SPDX-License-Identifier: MIT
3
-
4
- require "savon"
5
- require "nokogiri"
6
- require "date"
7
- require "securerandom"
8
-
9
- # A little utility library for VMware SSO.
10
- # For now, this is not a general purpose library that covers all
11
- # the interfaces of the SSO service.
12
- # Specifically, the support is limited to the following:
13
- # * request bearer token.
14
- module SSO
15
- # The XML date format.
16
- DATE_FORMAT = "%FT%T.%LZ".freeze
17
-
18
- # The XML namespaces that are required: SOAP, WSDL, et al.
19
- NAMESPACES = {
20
- "xmlns:S" => "http://schemas.xmlsoap.org/soap/envelope/",
21
- "xmlns:wst" => "http://docs.oasis-open.org/ws-sx/ws-trust/200512",
22
- "xmlns:u" => "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd",
23
- "xmlns:x" => "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
24
- }.freeze
25
-
26
- # Provides the connection details for the SSO service.
27
- class Connection
28
- attr_accessor :sso_url, :wsdl_url, :username, :password
29
-
30
- # Creates a new instance.
31
- def initialize(sso_url, wsdl_url = nil)
32
- self.sso_url = sso_url
33
- self.wsdl_url = wsdl_url || "#{sso_url}?wsdl"
34
- end
35
-
36
- # Login with the given credentials.
37
- # Note: this does not invoke a login action, but rather stores the
38
- # credentials for use later.
39
- def login(username, password)
40
- self.username = username
41
- self.password = password
42
- self # enable builder pattern
43
- end
44
-
45
- # Gets (or creates) the Savon client instance.
46
- def client
47
- # construct and init the client proxy
48
- @client ||= Savon.client do |globals|
49
- # see: http://savonrb.com/version2/globals.html
50
- globals.wsdl wsdl_url
51
- globals.endpoint sso_url
52
-
53
- globals.strip_namespaces false
54
- globals.env_namespace :S
55
-
56
- # set like this so https connection does not fail
57
- # TODO: find an acceptable solution for production
58
- globals.ssl_verify_mode :none
59
-
60
- # dev/debug settings
61
- # globals.pretty_print_xml ENV['DEBUG_SOAP']
62
- # globals.log ENV['DEBUG_SOAP']
63
- end
64
- end
65
-
66
- # Invokes the request bearer token operation.
67
- # @return [SamlToken]
68
- def request_bearer_token
69
- rst = RequestSecurityToken.new(client, username, password)
70
- rst.invoke
71
- rst.saml_token
72
- end
73
- end
74
-
75
- # @abstract Base class for invocable service calls.
76
- class SoapInvocable
77
- attr_reader :operation, :client, :response
78
-
79
- # Constructs a new instance.
80
- # @param operation [Symbol] the SOAP operation name (in Symbol form)
81
- # @param client [Savon::Client] the client
82
- def initialize(operation, client)
83
- @operation = operation
84
- @client = client
85
- end
86
-
87
- # Invokes the service call represented by this type.
88
- def invoke
89
- request = request_xml.to_s
90
- puts "request = #{request}" if ENV["DEBUG"]
91
- @response = client.call(operation, xml: request)
92
- puts "response = #{response}" if ENV["DEBUG"]
93
- self # for chaining with new
94
- end
95
-
96
- # Builds the request XML content.
97
- def request_xml
98
- builder = Builder::XmlMarkup.new
99
- builder.instruct!(:xml, encoding: "UTF-8")
100
-
101
- builder.tag!("S:Envelope", NAMESPACES) do |envelope|
102
- if has_header?
103
- envelope.tag!("S:Header") do |header|
104
- header_xml(header)
105
- end
106
- end
107
- envelope.tag!("S:Body") do |body|
108
- body_xml(body)
109
- end
110
- end
111
- builder.target!
112
- end
113
-
114
- def has_header?
115
- true
116
- end
117
-
118
- # Builds the header portion of the SOAP request.
119
- # Specific service operations must override this method.
120
- def header_xml(_header)
121
- raise "abstract method not implemented!"
122
- end
123
-
124
- # Builds the body portion of the SOAP request.
125
- # Specific service operations must override this method.
126
- def body_xml(_body)
127
- raise "abstract method not implemented!"
128
- end
129
-
130
- # Gets the response XML content.
131
- def response_xml
132
- raise "illegal state: response not set yet" if response.nil?
133
-
134
- @response_xml ||= Nokogiri::XML(response.to_xml)
135
- end
136
-
137
- def response_hash
138
- @response_hash ||= response.to_hash
139
- end
140
- end
141
-
142
- # Encapsulates an issue operation that requests a security token
143
- # from the SSO service.
144
- class RequestSecurityToken < SoapInvocable
145
- attr_accessor :request_type, :delegatable
146
-
147
- # Constructs a new instance.
148
- def initialize(client, username, password, hours = 2)
149
- super(:issue, client)
150
-
151
- @username = username
152
- @password = password
153
- @hours = hours
154
-
155
- # TODO: these things should be configurable, so we can get
156
- # non-delegatable tokens, HoK tokens, etc.
157
- @request_type = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue"
158
- @delegatable = true
159
- end
160
-
161
- def now
162
- @now ||= Time.now.utc.to_datetime
163
- end
164
-
165
- def created
166
- @created ||= now.strftime(DATE_FORMAT)
167
- end
168
-
169
- def future
170
- @future ||= now + (2 / 24.0) # days (for DateTime math)
171
- end
172
-
173
- def expires
174
- @expires ||= future.strftime(DATE_FORMAT)
175
- end
176
-
177
- # Builds the header XML for the SOAP request.
178
- def header_xml(header)
179
- id = "uuid-" + SecureRandom.uuid
180
-
181
- # header.tag!("x:Security", "x:mustUnderstand" => "1") do |security|
182
- header.tag!("x:Security") do |security|
183
- security.tag!("u:Timestamp", "u:Id" => "_0") do |timestamp|
184
- timestamp.tag!("u:Created") do |element|
185
- element << created
186
- end
187
- timestamp.tag!("u:Expires") do |element|
188
- element << expires
189
- end
190
- end
191
- security.tag!("x:UsernameToken", "u:Id" => id) do |utoken|
192
- utoken.tag!("x:Username") do |element|
193
- element << @username
194
- end
195
- utoken.tag!("x:Password") do |element|
196
- element << @password
197
- end
198
- end
199
- end
200
- end
201
-
202
- # Builds the body XML for the SOAP request.
203
- def body_xml(body)
204
- body.tag!("wst:RequestSecurityToken") do |rst|
205
- rst.tag!("wst:RequestType") do |element|
206
- element << request_type
207
- end
208
- rst.tag!("wst:Delegatable") do |element|
209
- element << delegatable.to_s
210
- end
211
- # #TODO: we don't seem to need this, but I'm leaving this
212
- # #here for now as a reminder.
213
- # rst.tag!("wst:Lifetime") do |lifetime|
214
- # lifetime.tag!("u:Created") do |element|
215
- # element << created
216
- # end
217
- # lifetime.tag!("u:Expires") do |element|
218
- # element << expires
219
- # end
220
- # end
221
- end
222
- end
223
-
224
- # Gets the saml_token from the SOAP response body.
225
- # @return [SamlToken] the requested SAML token
226
- def saml_token
227
- assertion = response_xml.at_xpath("//saml2:Assertion",
228
- "saml2" => "urn:oasis:names:tc:SAML:2.0:assertion")
229
- SamlToken.new(assertion)
230
- end
231
- end
232
-
233
- # Holds a SAML token.
234
- class SamlToken
235
- attr_reader :xml
236
-
237
- # Creates a new instance.
238
- def initialize(xml)
239
- @xml = xml
240
- end
241
-
242
- # TODO: add some getters for interesting content
243
-
244
- def to_s
245
- esc_token = xml.to_xml(indent: 0, encoding: "UTF-8")
246
- esc_token = esc_token.delete("\n")
247
- esc_token
248
- end
249
- end
250
- end
251
-
252
- # main: quick self tester
253
- if $PROGRAM_NAME == __FILE__
254
- cloudvm_ip = ARGV[0]
255
- cloudvm_ip ||= "10.20.17.0"
256
- # cloudvm_ip ||= "10.67.245.207"
257
- sso_url = "https://#{cloudvm_ip}/sts/STSService/vsphere.local"
258
- wsdl_url = "#{sso_url}?wsdl"
259
- sso = SSO::Connection.new(sso_url, wsdl_url)
260
- # sso.login("administrator@vsphere.local", "Admin!23")
261
- sso.login("root", "vmware")
262
- token = sso.request_bearer_token
263
- puts token.to_s
264
- end