knife-vcenter 2.0.1 → 2.0.2

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 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