knife-azure 3.0.6 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/azure/custom_errors.rb +1 -1
  3. data/lib/azure/resource_management/ARM_deployment_template.rb +5 -5
  4. data/lib/azure/resource_management/ARM_interface.rb +4 -6
  5. data/lib/azure/resource_management/windows_credentials.rb +2 -2
  6. data/lib/chef/knife/azurerm_server_create.rb +1 -1
  7. data/lib/chef/knife/bootstrap/bootstrapper.rb +5 -10
  8. data/lib/chef/knife/helpers/azurerm_base.rb +4 -4
  9. data/lib/knife-azure/version.rb +1 -1
  10. metadata +30 -43
  11. data/lib/azure/service_management/ASM_interface.rb +0 -310
  12. data/lib/azure/service_management/ag.rb +0 -99
  13. data/lib/azure/service_management/certificate.rb +0 -235
  14. data/lib/azure/service_management/connection.rb +0 -102
  15. data/lib/azure/service_management/deploy.rb +0 -221
  16. data/lib/azure/service_management/disk.rb +0 -68
  17. data/lib/azure/service_management/host.rb +0 -184
  18. data/lib/azure/service_management/image.rb +0 -94
  19. data/lib/azure/service_management/loadbalancer.rb +0 -78
  20. data/lib/azure/service_management/rest.rb +0 -126
  21. data/lib/azure/service_management/role.rb +0 -717
  22. data/lib/azure/service_management/storageaccount.rb +0 -127
  23. data/lib/azure/service_management/utility.rb +0 -40
  24. data/lib/azure/service_management/vnet.rb +0 -134
  25. data/lib/chef/knife/azure_ag_create.rb +0 -73
  26. data/lib/chef/knife/azure_ag_list.rb +0 -35
  27. data/lib/chef/knife/azure_image_list.rb +0 -56
  28. data/lib/chef/knife/azure_internal-lb_create.rb +0 -74
  29. data/lib/chef/knife/azure_internal-lb_list.rb +0 -35
  30. data/lib/chef/knife/azure_server_create.rb +0 -531
  31. data/lib/chef/knife/azure_server_delete.rb +0 -136
  32. data/lib/chef/knife/azure_server_list.rb +0 -38
  33. data/lib/chef/knife/azure_server_show.rb +0 -41
  34. data/lib/chef/knife/azure_vnet_create.rb +0 -74
  35. data/lib/chef/knife/azure_vnet_list.rb +0 -35
  36. data/lib/chef/knife/bootstrap_azure.rb +0 -191
  37. data/lib/chef/knife/helpers/azure_base.rb +0 -392
@@ -1,74 +0,0 @@
1
- #
2
- # Author:: Aiman Alsari (aiman.alsari@gmail.com)
3
- # Copyright:: Copyright (c) Chef Software Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require_relative "helpers/azure_base"
20
-
21
- class Chef
22
- class Knife
23
- class AzureInternalLbCreate < Knife
24
- include Knife::AzureBase
25
-
26
- banner "knife azure internal lb create (options)"
27
-
28
- option :azure_load_balancer,
29
- short: "-n NAME",
30
- long: "--azure-load-balancer NAME",
31
- description: "Required. Specifies new load balancer name."
32
-
33
- option :azure_lb_static_vip,
34
- long: "--azure-lb-static-vip VIP",
35
- description: "Optional. The Virtual IP that will be used for the load balancer."
36
-
37
- option :azure_subnet_name,
38
- long: "--azure-subnet-name SUBNET_NAME",
39
- description: "Required if static VIP is set. Specifies the subnet name "\
40
- "the load balancer is located in."
41
-
42
- option :azure_dns_name,
43
- long: "--azure-dns-name DNS_NAME",
44
- description: "The DNS prefix name that will be used to add this load balancer to. This must be an existing service/deployment."
45
-
46
- def run
47
- $stdout.sync = true
48
-
49
- Chef::Log.info("validating...")
50
- validate_asm_keys!(:azure_load_balancer)
51
-
52
- params = {
53
- azure_load_balancer: config[:azure_load_balancer],
54
- azure_lb_static_vip: config[:azure_lb_static_vip],
55
- azure_subnet_name: config[:azure_subnet_name],
56
- azure_dns_name: config[:azure_dns_name],
57
- }
58
-
59
- rsp = service.create_internal_lb(params)
60
- print "\n"
61
- if rsp.at_css("Status").nil?
62
- if rsp.at_css("Code").nil? || rsp.at_css("Message").nil?
63
- puts "Unknown Error. try -VV"
64
- else
65
- puts "#{rsp.at_css("Code").content}: "\
66
- "#{rsp.at_css("Message").content}"
67
- end
68
- else
69
- puts "Creation status: #{rsp.at_css("Status").content}"
70
- end
71
- end
72
- end
73
- end
74
- end
@@ -1,35 +0,0 @@
1
- #
2
- # Author:: Aiman Alsari (aiman.alsari@gmail.com)
3
- # Copyright:: Copyright (c) Chef Software Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require_relative "helpers/azure_base"
20
-
21
- class Chef
22
- class Knife
23
- class AzureInternalLbList < Knife
24
- include Knife::AzureBase
25
-
26
- banner "knife azure internal lb list (options)"
27
-
28
- def run
29
- $stdout.sync = true
30
- validate_asm_keys!
31
- service.list_internal_lb
32
- end
33
- end
34
- end
35
- end
@@ -1,531 +0,0 @@
1
- #
2
- # Author:: Barry Davis (barryd@jetstreamsoftware.com)
3
- # Author:: Adam Jacob (<adam@chef.io>)
4
- # Author:: Seth Chisamore (<schisamo@chef.io>)
5
- # Copyright:: Copyright (c) Chef Software Inc.
6
- # License:: Apache License, Version 2.0
7
- #
8
- # Licensed under the Apache License, Version 2.0 (the "License");
9
- # you may not use this file except in compliance with the License.
10
- # You may obtain a copy of the License at
11
- #
12
- # http://www.apache.org/licenses/LICENSE-2.0
13
- #
14
- # Unless required by applicable law or agreed to in writing, software
15
- # distributed under the License is distributed on an "AS IS" BASIS,
16
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
- # See the License for the specific language governing permissions and
18
- # limitations under the License.
19
- #
20
-
21
- require_relative "helpers/azure_base"
22
- require "chef/knife/bootstrap"
23
- require "chef/knife/bootstrap/client_builder"
24
- require_relative "bootstrap/common_bootstrap_options"
25
- require_relative "bootstrap/bootstrapper"
26
-
27
- class Chef
28
- class Knife
29
- class AzureServerCreate < Knife::Bootstrap
30
- include Knife::AzureBase
31
- include Knife::Bootstrap::CommonBootstrapOptions
32
- include Knife::Bootstrap::Bootstrapper
33
-
34
- deps do
35
- require "securerandom" unless defined?(SecureRandom)
36
- require "readline"
37
- require "chef/json_compat"
38
- require "chef/knife/bootstrap"
39
- require "chef/knife/core/windows_bootstrap_context"
40
- Chef::Knife::Bootstrap.load_deps
41
- end
42
-
43
- banner "knife azure server create (options)"
44
-
45
- SUPPORTED_CONNECTION_PROTOCOLS = %w{ssh winrm cloud-api}.freeze
46
-
47
- attr_accessor :initial_sleep_delay
48
-
49
- option :azure_affinity_group,
50
- short: "-a GROUP",
51
- long: "--azure-affinity-group GROUP",
52
- description: "Required if not using a Service Location. Specifies Affinity Group the VM should belong to."
53
-
54
- option :azure_dns_name,
55
- short: "-d DNS_NAME",
56
- long: "--azure-dns-name DNS_NAME",
57
- description: "The DNS prefix name that can be used to access the cloud service which is unique within Windows Azure. Default is 'azure-dns-any_random_text'(e.g: azure-dns-be9b0f6f-7dda-456f-b2bf-4e28a3bc0add).
58
- If you want to add new VM to an existing service/deployment, specify an exiting dns-name,
59
- along with --azure-connect-to-existing-dns option.
60
- Otherwise a new deployment is created. For example, if the DNS of cloud service is MyService you could access the cloud service
61
- by calling: http://DNS_NAME.cloudapp.net"
62
-
63
- option :azure_source_image,
64
- short: "-I IMAGE",
65
- long: "--azure-source-image IMAGE",
66
- description: "Required. Specifies the name of the disk image to use to create the virtual machine.
67
- Do a \"knife azure image list\" to see a list of available images."
68
-
69
- option :udp_endpoints,
70
- short: "-u PORT_LIST",
71
- long: "--udp-endpoints PORT_LIST",
72
- description: "Comma-separated list of UDP local and public ports to open e.g. '80:80,433:5000'"
73
-
74
- option :azure_connect_to_existing_dns,
75
- short: "-c",
76
- long: "--azure-connect-to-existing-dns",
77
- boolean: true,
78
- default: false,
79
- description: "Set this flag to add the new VM to an existing deployment/service. Must give the name of the existing
80
- DNS correctly in the --dns-name option"
81
-
82
- option :azure_network_name,
83
- long: "--azure-network-name NETWORK_NAME",
84
- description: "Optional. Specifies the network of virtual machine"
85
-
86
- option :azure_subnet_name,
87
- long: "--azure-subnet-name SUBNET_NAME",
88
- description: "Optional. Specifies the subnet of virtual machine"
89
-
90
- option :azure_vm_startup_timeout,
91
- long: "--azure-vm-startup-timeout TIMEOUT",
92
- description: "The number of minutes that knife-azure will wait for the virtual machine to reach the 'provisioning' state. Default is 10.",
93
- default: 10
94
-
95
- option :azure_vm_ready_timeout,
96
- long: "--azure-vm-ready-timeout TIMEOUT",
97
- description: "The number of minutes that knife-azure will wait for the virtual machine state to transition from 'provisioning' to 'ready'. Default is 15.",
98
- default: 15
99
-
100
- option :auth_timeout,
101
- long: "--windows-auth-timeout MINUTES",
102
- description: "The maximum time in minutes to wait to for authentication over the transport to the node to succeed. The default value is 25 minutes.",
103
- default: 25
104
-
105
- option :identity_file_passphrase,
106
- long: "--identity-file-passphrase PASSWORD",
107
- description: "SSH key passphrase. Optional, specify if passphrase for identity-file exists"
108
-
109
- option :winrm_max_timeout,
110
- long: "--winrm-max-timeout MINUTES",
111
- description: "Set winrm maximum command timeout in minutes, useful for long bootstraps"
112
-
113
- option :winrm_max_memory_per_shell,
114
- long: "--winrm-max-memory-per-shell",
115
- description: "Set winrm max memory per shell in MB"
116
-
117
- option :azure_domain_name,
118
- long: "--azure-domain-name DOMAIN_NAME",
119
- description: 'Optional. Specifies the domain name to join. If the domains name is not specified, --azure-domain-user must specify the user principal name (UPN) format (user@fully-qualified-DNS-domain) or the fully-qualified-DNS-domain\\username format'
120
-
121
- option :azure_domain_ou_dn,
122
- long: "--azure-domain-ou-dn DOMAIN_OU_DN",
123
- description: "Optional. Specifies the (LDAP) X 500-distinguished name of the organizational unit (OU) in which the computer account is created. This account is in Active Directory on a domain controller in the domain to which the computer is being joined. Example: OU=HR,dc=opscode,dc=com"
124
-
125
- option :azure_domain_user,
126
- long: "--azure-domain-user DOMAIN_USER_NAME",
127
- description: 'Optional. Specifies the username who has access to join the domain.
128
- Supported format: username(if domain is already specified in --azure-domain-name option),
129
- fully-qualified-DNS-domain\username, user@fully-qualified-DNS-domain'
130
-
131
- option :azure_domain_passwd,
132
- long: "--azure-domain-passwd DOMAIN_PASSWD",
133
- description: "Optional. Specifies the password for domain user who has access to join the domain."
134
-
135
- # Overriding this option to provide "cloud-api" in SUPPORTED_CONNECTION_PROTOCOLS
136
- option :connection_protocol,
137
- short: "-o PROTOCOL",
138
- long: "--connection-protocol PROTOCOL",
139
- description: "The protocol to use to connect to the target node.",
140
- in: SUPPORTED_CONNECTION_PROTOCOLS
141
-
142
- # run() would be executing from parent class
143
- # Chef::Knife::Bootstrap, defined in core.
144
- # Required methods have been overridden here
145
- #### run() execution begins ####
146
-
147
- def plugin_setup!; end
148
-
149
- def validate_name_args!; end
150
-
151
- # Ensure a valid protocol is provided for target host connection
152
- #
153
- # The method call will cause the program to exit(1) if:
154
- # * Conflicting protocols are given via the target URI and the --protocol option
155
- # * The protocol is not a supported protocol
156
- #
157
- # @note we are overriding this method here to consider "cloud-api" as valid protocol
158
- #
159
- # @return [TrueClass] If options are valid.
160
- def validate_protocol!
161
- from_cli = config[:connection_protocol]
162
- if from_cli && connection_protocol != from_cli
163
- # Hanging indent to align with the ERROR: prefix
164
- ui.error <<~EOM
165
- The URL '#{host_descriptor}' indicates protocol is '#{connection_protocol}'
166
- while the --protocol flag specifies '#{from_cli}'. Please include
167
- only one or the other.
168
- EOM
169
- exit 1
170
- end
171
-
172
- unless SUPPORTED_CONNECTION_PROTOCOLS.include?(connection_protocol)
173
- ui.error <<~EOM
174
- Unsupported protocol '#{connection_protocol}'.
175
-
176
- Supported protocols are: #{SUPPORTED_CONNECTION_PROTOCOLS.join(" ")}
177
- EOM
178
- exit 1
179
- end
180
- true
181
- end
182
-
183
- def plugin_validate_options!
184
- Chef::Log.info("Validating...")
185
- validate_asm_keys!(:azure_source_image)
186
- validate_params!
187
- end
188
-
189
- def plugin_create_instance!
190
- Chef::Log.info("Creating...")
191
- set_defaults
192
- server_def = create_server_def
193
- vm_details = service.create_server(server_def)
194
-
195
- wait_until_virtual_machine_ready
196
-
197
- config[:connection_port] = server_def[:port]
198
- config[:connection_protocol] = server_def[:connection_protocol]
199
- config[:chef_node_name] = config[:chef_node_name] || server_name
200
- rescue => error
201
- ui.error("Something went wrong. Please use -VV option for more details.")
202
- Chef::Log.debug(error.backtrace.join("\n").to_s)
203
- exit 1
204
- end
205
-
206
- def server_name
207
- @server_name ||= if @server.nil?
208
- nil
209
- elsif !@server.hostedservicename.nil?
210
- @server.hostedservicename + ".cloudapp.net"
211
- else
212
- @server.ipaddress
213
- end
214
- end
215
-
216
- alias host_descriptor server_name
217
-
218
- def plugin_finalize
219
- if config[:connection_protocol] == "cloud-api" && config[:extended_logs]
220
- print "\nWaiting for the first chef-client run"
221
- fetch_chef_client_logs(Time.now, 30)
222
- end
223
- msg_server_summary(@server)
224
- end
225
-
226
- #### run() execution ends ####
227
-
228
- def wait_until_virtual_machine_ready(retry_interval_in_seconds = 30)
229
- vm_status = nil
230
- begin
231
- azure_vm_startup_timeout = config[:azure_vm_startup_timeout].to_i
232
- azure_vm_ready_timeout = config[:azure_vm_ready_timeout].to_i
233
- vm_status = wait_for_virtual_machine_state(:vm_status_provisioning, azure_vm_startup_timeout, retry_interval_in_seconds)
234
- if vm_status != :vm_status_ready
235
- begin
236
- wait_for_virtual_machine_state(:vm_status_ready, azure_vm_ready_timeout, retry_interval_in_seconds)
237
- rescue Chef::Exceptions::CommandTimeout => e
238
- ui.warn("\n#{e.message}")
239
- ui.warn("Ignoring failure to reach 'ready' with bootstrap.")
240
- end
241
- end
242
-
243
- msg_server_summary(@server)
244
-
245
- if config[:connection_protocol] == "cloud-api"
246
- extension_status = wait_for_resource_extension_state(:wagent_provisioning, 5, retry_interval_in_seconds)
247
-
248
- if extension_status != :extension_installing
249
- extension_status = wait_for_resource_extension_state(:extension_installing, 5, retry_interval_in_seconds)
250
- end
251
-
252
- if extension_status != :extension_provisioning
253
- extension_status = wait_for_resource_extension_state(:extension_provisioning, 10, retry_interval_in_seconds)
254
- end
255
-
256
- if extension_status != :extension_ready
257
- wait_for_resource_extension_state(:extension_ready, 5, retry_interval_in_seconds)
258
- end
259
- end
260
- rescue Exception => e
261
- Chef::Log.error("#{e}")
262
- raise "Verify connectivity to Azure and subscription resource limit compliance (e.g. maximum CPU core limits) and try again."
263
- end
264
- end
265
-
266
- def wait_for_virtual_machine_state(vm_status_goal, total_wait_time_in_minutes, retry_interval_in_seconds)
267
- vm_status_ordering = { vm_status_not_detected: 0, vm_status_provisioning: 1, vm_status_ready: 2 }
268
- vm_status_description = { vm_status_not_detected: "any", vm_status_provisioning: "provisioning", vm_status_ready: "ready" }
269
-
270
- print ui.color("\nWaiting for virtual machine to reach status '#{vm_status_description[vm_status_goal]}'\n", :magenta)
271
-
272
- total_wait_time_in_seconds = total_wait_time_in_minutes * 60
273
- max_polling_attempts = total_wait_time_in_seconds / retry_interval_in_seconds
274
- polling_attempts = 0
275
-
276
- wait_start_time = Time.now
277
-
278
- begin
279
- vm_status = get_virtual_machine_status
280
- vm_ready = vm_status_ordering[vm_status] >= vm_status_ordering[vm_status_goal]
281
- print "."
282
- sleep retry_interval_in_seconds unless vm_ready
283
- polling_attempts += 1
284
- end until vm_ready || polling_attempts >= max_polling_attempts
285
-
286
- unless vm_ready
287
- raise Chef::Exceptions::CommandTimeout, "Virtual machine state '#{vm_status_description[vm_status_goal]}' not reached after #{total_wait_time_in_minutes} minutes."
288
- end
289
-
290
- elapsed_time_in_minutes = ((Time.now - wait_start_time) / 60).round(2)
291
- print ui.color("\nvm state '#{vm_status_description[vm_status_goal]}' reached after #{elapsed_time_in_minutes} minutes.\n", :cyan)
292
- vm_status
293
- end
294
-
295
- def wait_for_resource_extension_state(extension_status_goal, total_wait_time_in_minutes, retry_interval_in_seconds)
296
- extension_status_ordering = { extension_status_not_detected: 0, wagent_provisioning: 1, extension_installing: 2, extension_provisioning: 3, extension_ready: 4 }
297
-
298
- status_description = { extension_status_not_detected: "any", wagent_provisioning: "wagent provisioning", extension_installing: "installing", extension_provisioning: "provisioning", extension_ready: "ready" }
299
-
300
- print ui.color("\nWaiting for Resource Extension to reach status '#{status_description[extension_status_goal]}'\n", :magenta)
301
-
302
- max_polling_attempts = (total_wait_time_in_minutes * 60) / retry_interval_in_seconds
303
- polling_attempts = 0
304
-
305
- wait_start_time = Time.now
306
-
307
- begin
308
- extension_status = get_extension_status
309
- extension_ready = extension_status_ordering[extension_status[:status]] >= extension_status_ordering[extension_status_goal]
310
- print "."
311
- sleep retry_interval_in_seconds unless extension_ready
312
- polling_attempts += 1
313
- end until extension_ready || polling_attempts >= max_polling_attempts
314
-
315
- unless extension_ready
316
- raise Chef::Exceptions::CommandTimeout, "Resource extension state '#{status_description[extension_status_goal]}' not reached after #{total_wait_time_in_minutes} minutes. #{extension_status[:message]}"
317
- end
318
-
319
- elapsed_time_in_minutes = ((Time.now - wait_start_time) / 60).round(2)
320
- print ui.color("\nResource extension state '#{status_description[extension_status_goal]}' reached after #{elapsed_time_in_minutes} minutes.\n", :cyan)
321
-
322
- extension_status[:status]
323
- end
324
-
325
- def get_virtual_machine_status
326
- @server = service.get_role_server(config[:azure_dns_name], config[:azure_vm_name])
327
- if @server.nil?
328
- :vm_status_not_detected
329
- else
330
- Chef::Log.debug("Role status is #{@server.status}")
331
- case @server.status.to_s
332
- when "ReadyRole"
333
- :vm_status_ready
334
- when "Provisioning"
335
- :vm_status_provisioning
336
- else
337
- :vm_status_not_detected
338
- end
339
- end
340
- end
341
-
342
- def get_extension_status
343
- deployment_name = service.deployment_name(config[:azure_dns_name])
344
- deployment = service.deployment("hostedservices/#{config[:azure_dns_name]}/deployments/#{deployment_name}")
345
- extension_status = {}
346
-
347
- if deployment.at_css("Deployment Name") != nil
348
- role_list_xml = deployment.css("RoleInstanceList RoleInstance")
349
- role_list_xml.each do |role|
350
- if role.at_css("RoleName").text == config[:azure_vm_name]
351
- lnx_waagent_fail_msg = "Failed to deserialize the status reported by the Guest Agent"
352
- waagent_status_msg = role.at_css("GuestAgentStatus FormattedMessage Message").text
353
- if role.at_css("GuestAgentStatus Status").text == "Ready"
354
- extn_status = role.at_css("ResourceExtensionStatusList Status").text
355
- Chef::Log.debug("Resource extension status is #{extn_status}")
356
- if extn_status == "Installing"
357
- extension_status[:status] = :extension_installing
358
- extension_status[:message] = role.at_css("ResourceExtensionStatusList FormattedMessage Message").text
359
- elsif extn_status == "NotReady"
360
- extension_status[:status] = :extension_provisioning
361
- extension_status[:message] = role.at_css("ResourceExtensionStatusList FormattedMessage Message").text
362
- elsif extn_status == "Ready"
363
- extension_status[:status] = :extension_ready
364
- extension_status[:message] = role.at_css("ResourceExtensionStatusList FormattedMessage Message").text
365
- else
366
- extension_status[:status] = :extension_status_not_detected
367
- end
368
- # This fix is for linux waagent issue: api unable to deserialize the waagent status.
369
- elsif (role.at_css("GuestAgentStatus Status").text == "NotReady") && (waagent_status_msg == lnx_waagent_fail_msg)
370
- extension_status[:status] = :extension_ready
371
- else
372
- extension_status[:status] = :wagent_provisioning
373
- extension_status[:message] = role.at_css("GuestAgentStatus Message").text
374
- end
375
- else
376
- extension_status[:status] = :extension_status_not_detected
377
- end
378
- end
379
- else
380
- extension_status[:status] = :extension_status_not_detected
381
- end
382
- extension_status
383
- end
384
-
385
- def create_server_def
386
- server_def = {
387
- azure_storage_account: config[:azure_storage_account],
388
- azure_api_host_name: config[:azure_api_host_name],
389
- azure_dns_name: config[:azure_dns_name],
390
- azure_vm_name: config[:azure_vm_name],
391
- azure_service_location: config[:azure_service_location],
392
- azure_os_disk_name: config[:azure_os_disk_name],
393
- azure_source_image: config[:azure_source_image],
394
- azure_vm_size: config[:azure_vm_size],
395
- tcp_endpoints: config[:tcp_endpoints],
396
- udp_endpoints: config[:udp_endpoints],
397
- connection_protocol: config[:connection_protocol],
398
- azure_connect_to_existing_dns: config[:azure_connect_to_existing_dns],
399
- connection_user: config[:connection_user],
400
- azure_availability_set: config[:azure_availability_set],
401
- azure_affinity_group: config[:azure_affinity_group],
402
- azure_network_name: config[:azure_network_name],
403
- azure_subnet_name: config[:azure_subnet_name],
404
- ssl_cert_fingerprint: config[:thumbprint],
405
- cert_path: config[:cert_path],
406
- cert_password: config[:cert_passphrase],
407
- winrm_ssl: config[:winrm_ssl],
408
- winrm_max_timeout: config[:winrm_max_timeout].to_i * 60 * 1000, # converting minutes to milliseconds
409
- winrm_max_memory_per_shell: config[:winrm_max_memory_per_shell],
410
- }
411
-
412
- if config[:connection_protocol] == "cloud-api"
413
- server_def[:chef_extension] = get_chef_extension_name
414
- server_def[:chef_extension_publisher] = get_chef_extension_publisher
415
- server_def[:chef_extension_version] = get_chef_extension_version
416
- server_def[:chef_extension_public_param] = get_chef_extension_public_params
417
- server_def[:chef_extension_private_param] = get_chef_extension_private_params
418
- else
419
- if is_image_windows?
420
- # We can specify the AdminUsername after API version 2013-03-01. However, in this API version,
421
- # the AdminUsername is a required parameter.
422
- # Also, the user name cannot be Administrator, Admin, Admin1 etc, for enhanced security (provided by Azure)
423
- if config[:connection_user].nil? || config[:connection_user].downcase =~ /admin*/
424
- ui.error("Connection User is compulsory parameter and it cannot be named 'admin*'")
425
- exit 1
426
- # take cares of when user name contains domain
427
- # azure add role api doesn't support '\\' in user name
428
- elsif config[:connection_user].split('\\').length.eql?(2)
429
- server_def[:connection_user] = config[:connection_user].split('\\')[1]
430
- end
431
- else
432
- unless config[:connection_user]
433
- ui.error("Connection User is compulsory parameter")
434
- exit 1
435
- end
436
- unless config[:connection_password] || config[:ssh_identity_file]
437
- ui.error("Specify either SSH Key or SSH Password")
438
- exit 1
439
- end
440
- end
441
- end
442
-
443
- if is_image_windows?
444
- server_def[:os_type] = "Windows"
445
- server_def[:admin_password] = config[:connection_password]
446
- server_def[:connection_protocol] = config[:connection_protocol] || "winrm"
447
- else
448
- server_def[:os_type] = "Linux"
449
- server_def[:connection_protocol] = config[:connection_protocol].nil? || config[:connection_protocol] == "winrm" ? "ssh" : config[:connection_protocol]
450
- server_def[:connection_user] = config[:connection_user]
451
- server_def[:connection_password] = config[:connection_password]
452
- server_def[:ssh_identity_file] = config[:ssh_identity_file]
453
- server_def[:identity_file_passphrase] = config[:identity_file_passphrase]
454
- end
455
-
456
- azure_connect_to_existing_dns = config[:azure_connect_to_existing_dns]
457
- if is_image_windows? && server_def[:connection_protocol] == "winrm"
458
- port = config[:connection_port] || "5985"
459
- port = config[:connection_port] || Random.rand(64000) + 1000 if azure_connect_to_existing_dns
460
- elsif server_def[:connection_protocol] == "ssh"
461
- port = config[:connection_port] || "22"
462
- port = config[:connection_port] || Random.rand(64000) + 1000 if azure_connect_to_existing_dns
463
- end
464
-
465
- server_def[:port] = port
466
-
467
- server_def[:is_vm_image] = service.vm_image?(config[:azure_source_image])
468
- server_def[:azure_domain_name] = config[:azure_domain_name] if config[:azure_domain_name]
469
-
470
- if config[:azure_domain_user]
471
- # extract domain name since it should be part of username
472
- case config[:azure_domain_user]
473
- when /(\S+)\\(.+)/ # format - fully-qualified-DNS-domain\username
474
- server_def[:azure_domain_name] = $1 if config[:azure_domain_name].nil?
475
- server_def[:azure_user_domain_name] = $1
476
- server_def[:azure_domain_user] = $2
477
- when /(.+)@(\S+)/ # format - user@fully-qualified-DNS-domain
478
- server_def[:azure_domain_name] = $2 if config[:azure_domain_name].nil?
479
- server_def[:azure_user_domain_name] = $2
480
- server_def[:azure_domain_user] = $1
481
- else
482
- if config[:azure_domain_name].nil?
483
- ui.error('--azure-domain-name should be specified if --azure-domain-user is not in one of the following formats: fully-qualified-DNS-domain\username, user@fully-qualified-DNS-domain')
484
- exit 1
485
- end
486
- server_def[:azure_domain_user] = config[:azure_domain_user]
487
- end
488
- end
489
- server_def[:azure_domain_passwd] = config[:azure_domain_passwd]
490
- server_def[:azure_domain_ou_dn] = config[:azure_domain_ou_dn]
491
-
492
- server_def
493
- end
494
-
495
- private
496
-
497
- def set_defaults
498
- set_configs
499
- end
500
-
501
- def set_configs
502
- unless config[:connection_user].nil?
503
- config[:connection_user] = config[:connection_user]
504
- end
505
-
506
- unless config[:connection_password].nil?
507
- config[:connection_password] = config[:connection_password]
508
- end
509
-
510
- config[:azure_dns_name] = get_dns_name(config[:azure_dns_name])
511
- config[:azure_vm_name] = config[:azure_dns_name] unless config[:azure_vm_name]
512
- config[:chef_node_name] = config[:azure_vm_name] unless config[:chef_node_name]
513
- end
514
-
515
- # This is related to Windows VM's specifically and computer name
516
- # length limits for legacy computer accounts
517
- MAX_VM_NAME_CHARACTERS = 15
518
-
519
- # generate a random dns_name if azure_dns_name is empty
520
- def get_dns_name(azure_dns_name, prefix = "az-")
521
- return azure_dns_name unless azure_dns_name.nil?
522
-
523
- if config[:azure_vm_name].nil?
524
- (prefix + SecureRandom.hex((MAX_VM_NAME_CHARACTERS - prefix.length) / 2))
525
- else
526
- config[:azure_vm_name]
527
- end
528
- end
529
- end
530
- end
531
- end