knife-vcenter 1.0.0

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.
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+ require 'rubocop/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+ RuboCop::RakeTask.new(:style)
8
+
9
+ begin
10
+ require 'github_changelog_generator/task'
11
+
12
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
13
+ config.future_release = KnifeVcenter::VERSION
14
+ config.issues = true
15
+ end
16
+ rescue LoadError
17
+ puts 'github_changelog_generator is not available. gem install github_changelog_generator to generate changelogs'
18
+ end
19
+
20
+ task default: [ :spec, :style ]
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'knife-vcenter/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'knife-vcenter'
10
+ spec.version = KnifeVcenter::VERSION
11
+ spec.authors = ['Chef Partner Engineering']
12
+ spec.email = ['partnereng@chef.io']
13
+ spec.summary = 'Knife plugin to VMware vCenter.'
14
+ spec.description = spec.summary
15
+ spec.homepage = 'https://github.com/chef/knife-vcenter'
16
+ spec.license = 'Apache 2.0'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0")
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_dependency 'chef', '~> 12'
24
+ spec.add_dependency 'knife-cloud', '~> 1.2'
25
+ spec.add_dependency 'rb-readline', '~> 0.5'
26
+ spec.add_dependency 'rbvmomi', '~> 1.11'
27
+ spec.add_dependency 'savon', '~> 2.11'
28
+ spec.add_dependency 'vsphere-automation-sdk', '~> 2.5'
29
+
30
+ spec.add_development_dependency 'bundler', '~> 1.7'
31
+ spec.add_development_dependency 'debase'
32
+ spec.add_development_dependency 'github_changelog_generator'
33
+ spec.add_development_dependency 'pry'
34
+ spec.add_development_dependency 'rake', '~> 10.0'
35
+ spec.add_development_dependency 'rubocop', '~> 0.35'
36
+ spec.add_development_dependency 'ruby-debug-ide', '~> 0.6.0'
37
+
38
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Author:: Chef Partner Engineering (<partnereng@chef.io>)
4
+ # Copyright:: Copyright (c) 2017 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
+ module Base
23
+ attr_accessor :log
24
+
25
+ def self.log
26
+ @log ||= init_logger
27
+ end
28
+
29
+ def self.init_logger
30
+ log = Logger.new(STDOUT)
31
+ log.progname = 'Knife VCenter'
32
+ log.level = Logger::INFO
33
+ log
34
+ end
35
+ end
@@ -0,0 +1,256 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Author:: Chef Partner Engineering (<partnereng@chef.io>)
4
+ # Copyright:: Copyright (c) 2017 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 'chef/knife/cloud/exceptions'
21
+ require 'chef/knife/cloud/service'
22
+ require 'chef/knife/cloud/helpers'
23
+ require 'chef/knife/cloud/vcenter_service_helpers'
24
+ require 'net/http'
25
+ require 'uri'
26
+ require 'json'
27
+ 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'
35
+ require 'set'
36
+ require 'support/clone_vm'
37
+
38
+ class Chef
39
+ class Knife
40
+ class Cloud
41
+ class VcenterService < Service
42
+ include VcenterServiceHelpers
43
+
44
+ attr_reader :vapi_config, :session_svc, :session_id
45
+ attr_reader :connection_options, :ipaddress
46
+
47
+ def initialize(options={})
48
+ super(options)
49
+
50
+ # Using the information supplied, configure the connection to vCentre
51
+ lookup_service_helper = LookupServiceHelper.new(options[:host])
52
+
53
+ vapi_urls = lookup_service_helper.find_vapi_urls()
54
+ vapi_url = vapi_urls.values[0]
55
+ Base.log.info(format('Vapi URL: %s', vapi_url)) if options[:vcenter_logs]
56
+
57
+ # Create the VAPI config object
58
+ ssl_options = {}
59
+ ssl_options[:verify] = if options[:verify_ssl]
60
+ :peer
61
+ else
62
+ Base.log.warn('SSL Verification is turned OFF') if options[:vcenter_logs]
63
+ :none
64
+ end
65
+ @vapi_config = VAPI::Bindings::VapiConfig.new(vapi_url, ssl_options)
66
+
67
+ # get the SSO url
68
+ sso_url = lookup_service_helper.find_sso_url()
69
+ sso = SSO::Connection.new(sso_url).login(options[:username], options[:password])
70
+ token = sso.request_bearer_token()
71
+ vapi_config.set_security_context(
72
+ VAPI::Security.create_saml_bearer_security_context(token.to_s)
73
+ )
74
+
75
+ # Login and get the session information
76
+ @session_svc = Com::Vmware::Cis::Session.new(vapi_config)
77
+ @session_id = session_svc.create()
78
+ vapi_config.set_security_context(
79
+ VAPI::Security.create_session_security_context(session_id)
80
+ )
81
+
82
+ # Set the class properties for the rbvmomi connections
83
+ @connection_options = {
84
+ user: options[:username],
85
+ password: options[:password],
86
+ insecure: options[:verify_ssl] ? false : true,
87
+ host: options[:host],
88
+ }
89
+ end
90
+
91
+ def create_server(options={})
92
+
93
+ # Create the vm object
94
+ vmobj = Com::Vmware::Vcenter::VM.new(vapi_config)
95
+
96
+ # Use the option to determine now a new machine is being created
97
+ case options[:type]
98
+ when "clone"
99
+
100
+ # Some of ht eoptions need to be the ID of the component in VMWAre
101
+ # Update these using the REST API so that they can be passed to the support library
102
+ options[:targethost] = get_host(options[:targethost])
103
+
104
+ # Configure the folder option as a has with the name an the id
105
+ options[:folder] = {
106
+ name: options[:folder],
107
+ id: get_folder(options[:folder])
108
+ } unless options[:folder].nil?
109
+
110
+ # Clone the machine using the support library
111
+ clone_obj = Support::CloneVm.new(connection_options, options)
112
+ @ipaddress = clone_obj.clone()
113
+
114
+ # return an object from the restapi
115
+ return get_server(options[:name])
116
+
117
+ when "create"
118
+
119
+ # Create the placement object
120
+ placementspec = Com::Vmware::Vcenter::VM::PlacementSpec.new()
121
+ placementspec.folder = get_folder(options[:folder])
122
+ placementspec.host = get_host(options[:targethost])
123
+ placementspec.datastore = get_datastore(options[:datastore])
124
+ placementspec.resource_pool = get_resourcepool(options[:resource_pool])
125
+
126
+ # Create the CreateSpec object
127
+ createspec = Com::Vmware::Vcenter::VM::CreateSpec.new()
128
+
129
+ createspec.name = options[:name]#
130
+ puts "seting the OS"
131
+ createspec.guest_OS = Com::Vmware::Vcenter::Vm::GuestOS::UBUNTU_64
132
+ puts "setting the placement"
133
+ createspec.placement = placementspec
134
+
135
+ # Create the new machine
136
+ begin
137
+ vm = vmobj.create(createspec)
138
+ rescue => e
139
+ puts e.message
140
+ end
141
+ end
142
+ end
143
+
144
+ def list_servers
145
+ # get a list of vms from the API
146
+ Com::Vmware::Vcenter::VM.new(vapi_config).list()
147
+ end
148
+
149
+ def list_hosts
150
+ # return a list of the hosts in the vcenter
151
+ Com::Vmware::Vcenter::Host.new(vapi_config).list()
152
+ end
153
+
154
+ def list_datacenters
155
+ Com::Vmware::Vcenter::Datacenter.new(vapi_config).list()
156
+ end
157
+
158
+ def list_clusters
159
+ Com::Vmware::Vcenter::Cluster.new(vapi_config).list()
160
+ end
161
+
162
+ def get_folder(name)
163
+ # Create a filter to ensure that only the named folder is returned
164
+ filter = Com::Vmware::Vcenter::Folder::FilterSpec.new({names: Set.new([name])})
165
+ # filter.names = name
166
+ folder_obj = Com::Vmware::Vcenter::Folder.new(vapi_config)
167
+ folder = folder_obj.list(filter)
168
+
169
+ folder[0].folder
170
+ end
171
+
172
+ def get_host(name)
173
+ filter = Com::Vmware::Vcenter::Host::FilterSpec.new({names: Set.new([name])})
174
+ host_obj = Com::Vmware::Vcenter::Host.new(vapi_config)
175
+ host = host_obj.list(filter)
176
+ host[0].host
177
+ end
178
+
179
+ def get_datastore(name)
180
+ filter = Com::Vmware::Vcenter::Datastore::FilterSpec.new({names: Set.new([name])})
181
+ datastore_obj = Com::Vmware::Vcenter::Datastore.new(vapi_config)
182
+ datastore = datastore_obj.list(filter)
183
+ datastore[0].datastore
184
+ end
185
+
186
+ def get_resourcepool(name)
187
+ filter = Com::Vmware::Vcenter::ResourcePool::FilterSpec.new({names: Set.new([name])})
188
+ resource_pool_obj = Com::Vmware::Vcenter::ResourcePool.new(vapi_config)
189
+ resource_pool = resource_pool_obj.list(filter)
190
+ resource_pool[0].resource_pool
191
+ end
192
+
193
+ def get_server(name)
194
+ filter = Com::Vmware::Vcenter::VM::FilterSpec.new({names: Set.new([name])})
195
+ vm_obj = Com::Vmware::Vcenter::VM.new(vapi_config)
196
+ vm_obj.list(filter)[0]
197
+ end
198
+
199
+ def delete_vm(name)
200
+ vm = get_server(name)
201
+ server_summary(vm)
202
+ ui.msg('')
203
+
204
+ ui.confirm('Do you really want to be delete this virtual machine')
205
+
206
+ vm_obj = Com::Vmware::Vcenter::VM.new(vapi_config)
207
+
208
+ # check the power state of the machine, if it is powered on turn it off
209
+ if vm.power_state.value == "POWERED_ON"
210
+ power = Com::Vmware::Vcenter::Vm::Power.new(vapi_config)
211
+ ui.msg('Shutting down machine')
212
+ power.stop(vm.vm)
213
+ end
214
+
215
+ vm_obj.delete(vm.vm)
216
+ end
217
+
218
+ def server_summary(server, _coloumns_with_inf=nil)
219
+ msg_pair('ID', server.vm)
220
+ msg_pair('Name', server.name)
221
+ msg_pair('Power State', server.power_state)
222
+ end
223
+
224
+ =begin
225
+ def bootstrap_common_params(bootstrap)
226
+ bootstrap.config[:run_list] = config[:run_list]
227
+ bootstrap.config[:environment] = get_config(:environment)
228
+ bootstrap.config[:first_boot_attributes] = get_config(:first_boot_attributes)
229
+ bootstrap.config[:chef_node_name] = get_config(:chef_node_name)
230
+ bootstrap.config[:node_ssl_verify_mode] = get_config(:node_ssl_verify_mode)
231
+ bootstrap
232
+ end
233
+
234
+ def bootstrap_for_node
235
+ Chef::Knife::Bootstrap.load_deps
236
+ bootstrap = Chef::Knife::Bootstrap.new
237
+ bootstrap.name_args = [config[:fqdn]]
238
+ bootstrap.config[:ssh_user] = get_config(:ssh_user)
239
+ bootstrap.config[:ssh_password] = get_config(:ssh_password)
240
+ bootstrap.config[:ssh_port] = get_config(:ssh_port)
241
+ bootstrap.config[:identity_file] = get_config(:identity_file)
242
+ bootstrap.config[:use_sudo] = true unless get_config(:ssh_user) == 'root'
243
+ bootstrap.config[:use_sudo_password] = true unless get_config(:ssh_user) == 'root'
244
+ bootstrap.config[:log_level] = get_config(:log_level)
245
+ bootstrap_common_params(bootstrap)
246
+ end
247
+ =end
248
+ private
249
+
250
+ def cleanup
251
+ session_svc.delete() unless session_id.nil?
252
+ end
253
+ end
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Author:: Chef Partner Engineering (<partnereng@chef.io>)
4
+ # Copyright:: Copyright (c) 2017 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 'chef/knife/cloud/helpers'
21
+
22
+ class Chef
23
+ class Knife
24
+ class Cloud
25
+ module VcenterServiceHelpers
26
+ include Chef::Knife::Cloud::Helpers
27
+
28
+ def create_service_instance
29
+ Chef::Knife::Cloud::VcenterService.new(username: locate_config_value(:vcenter_username),
30
+ password: locate_config_value(:vcenter_password),
31
+ host: locate_config_value(:vcenter_host),
32
+ verify_ssl: verify_ssl?)
33
+ end
34
+
35
+ def verify_ssl?
36
+ !locate_config_value(:vcenter_disable_ssl_verify)
37
+ end
38
+
39
+ def validate!
40
+ check_for_missing_config_values!(:vcenter_username, :vcenter_password, :vcenter_host)
41
+ end
42
+
43
+ # rubocop:disable Style/GuardClause
44
+ def check_for_missing_config_values!(*keys)
45
+ missing = keys.select { |x| locate_config_value(x).nil? }
46
+
47
+ unless missing.empty?
48
+ ui.error(format("The following required parameters are missing: %s", missing.join(', ')))
49
+ exit(1)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Author:: Chef Partner Engineering (<partnereng@chef.io>)
4
+ # Copyright:: Copyright (c) 2017 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
+ class Chef
21
+ class Knife
22
+ class Cloud
23
+ # rubocop:disable Style/AlignParameters
24
+ # runodop:disable Metrics/BlockLength
25
+ module VcenterServiceOptions
26
+ def self.included(includer)
27
+ includer.class_eval do
28
+ option :vcenter_username,
29
+ long: '--vcenter-username USERNAME',
30
+ description: 'Username to use to connect to the VCenter API'
31
+
32
+ option :vcenter_password,
33
+ long: '--vcenter-password PASSWORD',
34
+ description: 'Password associated with the specified user'
35
+
36
+ option :vcenter_host,
37
+ long: '--vcenter-host HOST',
38
+ description: 'Host to target for operations'
39
+
40
+ option :vcenter_disable_ssl_verify,
41
+ long: '--vcenter-disable-ssl-verify',
42
+ description: 'Skip any SSL verification for the API',
43
+ boolean: true,
44
+ default: false
45
+
46
+ option :vcenter_logs,
47
+ long: '--vcenter-logs',
48
+ description: 'Whether or not to display logs from VCenter SDK. Default: false',
49
+ boolean: true,
50
+ default: false
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end