knife-azure 1.6.0 → 1.7.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.
- checksums.yaml +4 -4
- data/LICENSE +201 -201
- data/README.md +37 -654
- data/lib/azure/resource_management/ARM_deployment_template.rb +87 -50
- data/lib/azure/resource_management/ARM_interface.rb +236 -516
- data/lib/azure/resource_management/vnet_config.rb +254 -0
- data/lib/azure/resource_management/windows_credentials.rb +109 -61
- data/lib/azure/service_management/ASM_interface.rb +17 -1
- data/lib/azure/service_management/certificate.rb +37 -13
- data/lib/azure/service_management/connection.rb +0 -0
- data/lib/azure/service_management/deploy.rb +0 -0
- data/lib/azure/service_management/disk.rb +0 -0
- data/lib/azure/service_management/host.rb +0 -0
- data/lib/azure/service_management/image.rb +0 -0
- data/lib/azure/service_management/rest.rb +0 -0
- data/lib/azure/service_management/role.rb +0 -0
- data/lib/azure/service_management/utility.rb +0 -0
- data/lib/chef/knife/azure_base.rb +100 -0
- data/lib/chef/knife/azure_image_list.rb +0 -0
- data/lib/chef/knife/azure_server_create.rb +0 -98
- data/lib/chef/knife/azure_server_delete.rb +0 -0
- data/lib/chef/knife/azure_server_list.rb +0 -0
- data/lib/chef/knife/azure_server_show.rb +0 -0
- data/lib/chef/knife/azurerm_base.rb +42 -9
- data/lib/chef/knife/azurerm_server_create.rb +31 -24
- data/lib/chef/knife/azurerm_server_delete.rb +1 -10
- data/lib/chef/knife/azurerm_server_list.rb +5 -1
- data/lib/chef/knife/azurerm_server_show.rb +5 -1
- data/lib/chef/knife/bootstrap/bootstrap_options.rb +12 -18
- data/lib/chef/knife/bootstrap/bootstrapper.rb +34 -15
- data/lib/chef/knife/bootstrap/common_bootstrap_options.rb +21 -24
- data/lib/chef/knife/bootstrap_azure.rb +58 -0
- data/lib/chef/knife/bootstrap_azurerm.rb +40 -50
- data/lib/knife-azure/version.rb +1 -1
- metadata +27 -12
@@ -36,6 +36,45 @@ module Azure::ARM
|
|
36
36
|
hints_json
|
37
37
|
end
|
38
38
|
|
39
|
+
def tcp_ports(tcp_ports, vm_name)
|
40
|
+
tcp_ports = tcp_ports.split(",")
|
41
|
+
sec_grp_json =
|
42
|
+
{
|
43
|
+
"apiVersion" => "[variables('apiVersion')]",
|
44
|
+
"type" => "Microsoft.Network/networkSecurityGroups",
|
45
|
+
"name" => "[variables('secgrpname')]",
|
46
|
+
"location" => "[resourceGroup().location]",
|
47
|
+
"properties" => {
|
48
|
+
"securityRules" => [
|
49
|
+
]
|
50
|
+
}
|
51
|
+
}
|
52
|
+
#Security Rule priority can be set between 100 and 4096
|
53
|
+
rule_no = 300
|
54
|
+
incremental=0
|
55
|
+
for port in tcp_ports
|
56
|
+
rule_no = rule_no + 2
|
57
|
+
sec_grp_json["properties"]["securityRules"].push(
|
58
|
+
{
|
59
|
+
"name" => vm_name + '_rule_' + incremental.to_s,
|
60
|
+
"properties"=> {
|
61
|
+
"description" => "Port Provided by user",
|
62
|
+
"protocol" => "Tcp",
|
63
|
+
"sourcePortRange" => "*",
|
64
|
+
"destinationPortRange" => port,
|
65
|
+
"sourceAddressPrefix" => "*",
|
66
|
+
"destinationAddressPrefix" => "*",
|
67
|
+
"access" => "Allow",
|
68
|
+
"priority" => rule_no,
|
69
|
+
"direction" => "Inbound"
|
70
|
+
}
|
71
|
+
}
|
72
|
+
)
|
73
|
+
incremental=incremental+1
|
74
|
+
end
|
75
|
+
sec_grp_json
|
76
|
+
end
|
77
|
+
|
39
78
|
def create_deployment_template(params)
|
40
79
|
if params[:chef_extension_public_param][:bootstrap_options][:chef_node_name]
|
41
80
|
chef_node_name = "[concat(parameters('chef_node_name'),copyIndex())]"
|
@@ -62,6 +101,7 @@ module Azure::ARM
|
|
62
101
|
# Extension Variables
|
63
102
|
extName = "[concat(variables('vmName'),copyIndex(),'/', variables('vmExtensionName'))]"
|
64
103
|
depExt = "[concat('Microsoft.Compute/virtualMachines/', variables('vmName'), copyIndex())]"
|
104
|
+
|
65
105
|
else
|
66
106
|
# publicIPAddresses Resource Variables
|
67
107
|
publicIPAddressName = "[variables('publicIPAddressName')]"
|
@@ -85,6 +125,11 @@ module Azure::ARM
|
|
85
125
|
depExt = "[concat('Microsoft.Compute/virtualMachines/', variables('vmName'))]"
|
86
126
|
end
|
87
127
|
|
128
|
+
# NetworkSecurityGroups Resource Variables
|
129
|
+
sec_grp_name = "[variables('secgrpname')]"
|
130
|
+
sec_grp = "[concat('Microsoft.Network/networkSecurityGroups/', variables('secgrpname'))]"
|
131
|
+
sec_grp_id = "[resourceId('Microsoft.Network/networkSecurityGroups/', variables('secgrpname'))]"
|
132
|
+
|
88
133
|
resource_ids = {}
|
89
134
|
hint_names = params[:chef_extension_public_param][:hints]
|
90
135
|
|
@@ -176,24 +221,6 @@ module Azure::ARM
|
|
176
221
|
"metadata"=> {
|
177
222
|
"description"=> "Optional Run List to Execute"
|
178
223
|
}
|
179
|
-
},
|
180
|
-
"autoUpdateClient" => {
|
181
|
-
"type" => "string",
|
182
|
-
"metadata" => {
|
183
|
-
"description" => "Optional Flag for auto update"
|
184
|
-
}
|
185
|
-
},
|
186
|
-
"deleteChefConfig" => {
|
187
|
-
"type" => "string",
|
188
|
-
"metadata" => {
|
189
|
-
"description" => "Optional Flag for deleteChefConfig"
|
190
|
-
}
|
191
|
-
},
|
192
|
-
"uninstallChefClient" => {
|
193
|
-
"type" => "string",
|
194
|
-
"metadata" => {
|
195
|
-
"description" => "Optional Flag for uninstallChefClient"
|
196
|
-
}
|
197
224
|
},
|
198
225
|
"chef_node_name" => {
|
199
226
|
"type" => "string",
|
@@ -270,16 +297,15 @@ module Azure::ARM
|
|
270
297
|
"imageOffer"=> "#{params[:azure_image_reference_offer]}",
|
271
298
|
"OSDiskName"=> "#{params[:azure_os_disk_name]}",
|
272
299
|
"nicName"=> "#{params[:azure_vm_name]}",
|
273
|
-
"addressPrefix"=> "10.0.0.0/16",
|
274
300
|
"subnetName"=> "#{params[:azure_vnet_subnet_name]}",
|
275
|
-
"subnetPrefix"=> "10.0.0.0/24",
|
276
301
|
"storageAccountType"=> "#{params[:azure_storage_account_type]}",
|
277
302
|
"publicIPAddressName"=> "#{params[:azure_vm_name]}",
|
278
303
|
"publicIPAddressType"=> "Dynamic",
|
279
304
|
"vmStorageAccountContainerName"=> "#{params[:azure_vm_name]}",
|
280
305
|
"vmName"=> "#{params[:azure_vm_name]}",
|
281
306
|
"vmSize"=> "#{params[:vm_size]}",
|
282
|
-
"virtualNetworkName"=> "#{params[:
|
307
|
+
"virtualNetworkName"=> "#{params[:vnet_config][:virtualNetworkName]}",
|
308
|
+
"secgrpname" => "#{params[:azure_sec_group_name]}",
|
283
309
|
"vnetID"=> "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]",
|
284
310
|
"subnetRef"=> "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
|
285
311
|
"apiVersion"=> "2015-06-15",
|
@@ -319,18 +345,9 @@ module Azure::ARM
|
|
319
345
|
"location"=> "[resourceGroup().location]",
|
320
346
|
"properties"=> {
|
321
347
|
"addressSpace"=> {
|
322
|
-
"addressPrefixes"=> [
|
323
|
-
"[variables('addressPrefix')]"
|
324
|
-
]
|
348
|
+
"addressPrefixes"=> params[:vnet_config][:addressPrefixes]
|
325
349
|
},
|
326
|
-
"subnets"=> [
|
327
|
-
{
|
328
|
-
"name"=> "[variables('subnetName')]",
|
329
|
-
"properties"=> {
|
330
|
-
"addressPrefix"=> "[variables('subnetPrefix')]"
|
331
|
-
}
|
332
|
-
}
|
333
|
-
]
|
350
|
+
"subnets"=> params[:vnet_config][:subnets]
|
334
351
|
}
|
335
352
|
},
|
336
353
|
{
|
@@ -440,6 +457,7 @@ module Azure::ARM
|
|
440
457
|
"publisher" => "#{params[:chef_extension_publisher]}",
|
441
458
|
"type" => "#{params[:chef_extension]}",
|
442
459
|
"typeHandlerVersion" => "#{params[:chef_extension_version]}",
|
460
|
+
"autoUpgradeMinorVersion" => "#{params[:auto_upgrade_minor_version]}",
|
443
461
|
"settings" => {
|
444
462
|
"bootstrap_options" => {
|
445
463
|
"chef_node_name" => chef_node_name,
|
@@ -448,13 +466,9 @@ module Azure::ARM
|
|
448
466
|
"bootstrap_version" => "[parameters('bootstrap_version')]",
|
449
467
|
"node_ssl_verify_mode" => "[parameters('node_ssl_verify_mode')]",
|
450
468
|
"node_verify_api_cert" => "[parameters('node_verify_api_cert')]",
|
451
|
-
"encrypted_data_bag_secret" => "[parameters('encrypted_data_bag_secret')]",
|
452
469
|
"bootstrap_proxy" => "[parameters('bootstrap_proxy')]"
|
453
470
|
},
|
454
471
|
"runlist" => "[parameters('runlist')]",
|
455
|
-
"autoUpdateClient" => "[parameters('autoUpdateClient')]",
|
456
|
-
"deleteChefConfig" => "[parameters('deleteChefConfig')]",
|
457
|
-
"uninstallChefClient" => "[parameters('uninstallChefClient')]",
|
458
472
|
"validation_key_format" => "[parameters('validation_key_format')]",
|
459
473
|
"hints" => hints_json,
|
460
474
|
"client_rb" => "[parameters('client_rb')]",
|
@@ -462,14 +476,46 @@ module Azure::ARM
|
|
462
476
|
},
|
463
477
|
"protectedSettings" => {
|
464
478
|
"validation_key" => "[parameters('validation_key')]",
|
465
|
-
"autoUpgradeMinorVersion" => "#{params[:auto_upgrade_minor_version]}",
|
466
479
|
"client_pem" => "[parameters('client_pem')]",
|
467
|
-
"chef_server_crt" => "[parameters('chef_server_crt')]"
|
480
|
+
"chef_server_crt" => "[parameters('chef_server_crt')]",
|
481
|
+
"encrypted_data_bag_secret" => "[parameters('encrypted_data_bag_secret')]"
|
468
482
|
}
|
469
483
|
}
|
470
484
|
}
|
471
485
|
]
|
472
486
|
}
|
487
|
+
|
488
|
+
if params[:tcp_endpoints]
|
489
|
+
sec_grp_json = tcp_ports(params[:tcp_endpoints], params[:azure_vm_name])
|
490
|
+
template['resources'].insert(1,sec_grp_json)
|
491
|
+
length = template['resources'].length.to_i - 1
|
492
|
+
for i in 0..length do
|
493
|
+
if template['resources'][i]['type'] == "Microsoft.Network/virtualNetworks"
|
494
|
+
template['resources'][i] = template['resources'][i].merge({"dependsOn" => [sec_grp]})
|
495
|
+
end
|
496
|
+
if template['resources'][i]['type'] == "Microsoft.Network/networkInterfaces"
|
497
|
+
template['resources'][i]['properties'] = template['resources'][i]['properties'].merge({"networkSecurityGroup" => {"id" => sec_grp_id}})
|
498
|
+
end
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
if params[:chef_extension_public_param][:extendedLogs] == "true"
|
503
|
+
template['resources'].each do |resource|
|
504
|
+
if resource['type'] == 'Microsoft.Compute/virtualMachines/extensions'
|
505
|
+
resource['properties']['settings']['extendedLogs'] = params[:chef_extension_public_param][:extendedLogs]
|
506
|
+
end
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
if params[:chef_extension_public_param][:chef_service_interval]
|
511
|
+
template['resources'].each do |resource|
|
512
|
+
if resource['type'] == 'Microsoft.Compute/virtualMachines/extensions'
|
513
|
+
resource['properties']['settings']['chef_service_interval'] = params[:chef_extension_public_param][:chef_service_interval]
|
514
|
+
end
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
template
|
473
519
|
end
|
474
520
|
|
475
521
|
def create_deployment_parameters(params, platform)
|
@@ -506,6 +552,9 @@ module Azure::ARM
|
|
506
552
|
"chef_server_crt" => {
|
507
553
|
"value" => "#{params[:chef_extension_private_param][:chef_server_crt]}"
|
508
554
|
},
|
555
|
+
"encrypted_data_bag_secret" => {
|
556
|
+
"value" => "#{params[:chef_extension_private_param][:encrypted_data_bag_secret]}"
|
557
|
+
},
|
509
558
|
"chef_server_url"=> {
|
510
559
|
"value" => "#{params[:chef_extension_public_param][:bootstrap_options][:chef_server_url]}"
|
511
560
|
},
|
@@ -518,24 +567,12 @@ module Azure::ARM
|
|
518
567
|
"node_verify_api_cert" => {
|
519
568
|
"value" => "#{params[:chef_extension_public_param][:bootstrap_options][:node_verify_api_cert]}"
|
520
569
|
},
|
521
|
-
"encrypted_data_bag_secret" => {
|
522
|
-
"value" => "#{params[:chef_extension_public_param][:bootstrap_options][:encrypted_data_bag_secret]}"
|
523
|
-
},
|
524
570
|
"bootstrap_proxy" => {
|
525
571
|
"value" => "#{params[:chef_extension_public_param][:bootstrap_options][:bootstrap_proxy]}"
|
526
572
|
},
|
527
573
|
"runlist" => {
|
528
574
|
"value" => "#{params[:chef_extension_public_param][:runlist]}"
|
529
575
|
},
|
530
|
-
"autoUpdateClient" => {
|
531
|
-
"value" => "#{params[:chef_extension_public_param][:autoUpdateClient]}"
|
532
|
-
},
|
533
|
-
"deleteChefConfig" => {
|
534
|
-
"value" => "#{params[:chef_extension_public_param][:deleteChefConfig]}"
|
535
|
-
},
|
536
|
-
"uninstallChefClient" => {
|
537
|
-
"value" => "#{params[:chef_extension_public_param][:uninstallChefClient]}"
|
538
|
-
},
|
539
576
|
"chef_node_name" => {
|
540
577
|
"value"=> "#{params[:chef_extension_public_param][:bootstrap_options][:chef_node_name]}"
|
541
578
|
},
|
@@ -16,6 +16,7 @@
|
|
16
16
|
require 'azure/azure_interface'
|
17
17
|
require 'azure/resource_management/ARM_base'
|
18
18
|
require 'azure/resource_management/ARM_deployment_template'
|
19
|
+
require 'azure/resource_management/vnet_config'
|
19
20
|
require 'azure_mgmt_resources'
|
20
21
|
require 'azure_mgmt_compute'
|
21
22
|
require 'azure_mgmt_storage'
|
@@ -26,6 +27,7 @@ module Azure
|
|
26
27
|
class ARMInterface < AzureInterface
|
27
28
|
include Azure::ARM::ARMBase
|
28
29
|
include Azure::ARM::ARMDeploymentTemplate
|
30
|
+
include Azure::ARM::VnetConfig
|
29
31
|
|
30
32
|
include Azure::ARM::Resources
|
31
33
|
include Azure::ARM::Resources::Models
|
@@ -88,59 +90,42 @@ module Azure
|
|
88
90
|
end
|
89
91
|
|
90
92
|
def list_servers(resource_group_name = nil)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
93
|
+
if resource_group_name.nil?
|
94
|
+
servers = compute_management_client.virtual_machines.list_all.value
|
95
|
+
else
|
96
|
+
servers = compute_management_client.virtual_machines.list(resource_group_name).value
|
97
|
+
end
|
97
98
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
rows
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
state
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
ui.color(state, :green)
|
115
|
-
else
|
116
|
-
ui.color(state, :yellow)
|
117
|
-
end
|
99
|
+
cols = ['VM Name', 'Resource Group Name', 'Location', 'Provisioning State', 'OS Type']
|
100
|
+
rows = []
|
101
|
+
|
102
|
+
servers.each do |server|
|
103
|
+
rows << server.name.to_s
|
104
|
+
rows << server.id.split('/')[4].downcase
|
105
|
+
rows << server.location.to_s
|
106
|
+
rows << begin
|
107
|
+
state = server.properties.provisioning_state.to_s.downcase
|
108
|
+
case state
|
109
|
+
when 'failed'
|
110
|
+
ui.color(state, :red)
|
111
|
+
when 'succeeded'
|
112
|
+
ui.color(state, :green)
|
113
|
+
else
|
114
|
+
ui.color(state, :yellow)
|
118
115
|
end
|
119
|
-
|
120
|
-
|
121
|
-
display_list(ui, cols, rows)
|
122
|
-
rescue => error
|
123
|
-
if error.class == MsRestAzure::AzureOperationError && error.body
|
124
|
-
if error.body['error']['code']
|
125
|
-
ui.error("#{error.body['error']['message']}")
|
126
|
-
else
|
127
|
-
ui.error(error.body)
|
128
|
-
end
|
129
|
-
else
|
130
|
-
ui.error("#{error.message}")
|
131
|
-
Chef::Log.debug("#{error.backtrace.join("\n")}")
|
132
|
-
end
|
133
|
-
exit
|
116
|
+
end
|
117
|
+
rows << server.properties.storage_profile.os_disk.os_type.to_s
|
134
118
|
end
|
119
|
+
display_list(ui, cols, rows)
|
135
120
|
end
|
136
121
|
|
137
122
|
def delete_server(resource_group_name, vm_name)
|
138
|
-
|
139
|
-
if
|
123
|
+
server = compute_management_client.virtual_machines.get(resource_group_name, vm_name)
|
124
|
+
if server && server.name == vm_name
|
140
125
|
puts "\n\n"
|
141
|
-
msg_pair(ui, 'VM Name',
|
142
|
-
msg_pair(ui, 'VM Size',
|
143
|
-
msg_pair(ui, 'VM OS',
|
126
|
+
msg_pair(ui, 'VM Name', server.name)
|
127
|
+
msg_pair(ui, 'VM Size', server.properties.hardware_profile.vm_size)
|
128
|
+
msg_pair(ui, 'VM OS', server.properties.storage_profile.os_disk.os_type)
|
144
129
|
puts "\n"
|
145
130
|
|
146
131
|
begin
|
@@ -153,9 +138,8 @@ module Azure
|
|
153
138
|
ui.info 'Deleting ..'
|
154
139
|
|
155
140
|
begin
|
156
|
-
|
157
|
-
|
158
|
-
end until promise.value!.body.nil?
|
141
|
+
server_detail = compute_management_client.virtual_machines.delete(resource_group_name, vm_name)
|
142
|
+
end until server_detail.value!.body.nil?
|
159
143
|
|
160
144
|
puts "\n"
|
161
145
|
ui.warn "Deleted server #{vm_name}"
|
@@ -163,90 +147,102 @@ module Azure
|
|
163
147
|
end
|
164
148
|
|
165
149
|
def show_server(name, resource_group)
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
end
|
178
|
-
|
179
|
-
details = Array.new
|
180
|
-
details << ui.color('Server Name', :bold, :cyan)
|
181
|
-
details << server.name
|
182
|
-
|
183
|
-
details << ui.color('Size', :bold, :cyan)
|
184
|
-
details << server.properties.hardware_profile.vm_size
|
150
|
+
server = find_server(resource_group, name)
|
151
|
+
if server
|
152
|
+
network_interface_name = server.properties.network_profile.network_interfaces[0].id.split('/')[-1]
|
153
|
+
network_interface_data = network_resource_client.network_interfaces.get(resource_group, network_interface_name)
|
154
|
+
public_ip_id_data = network_interface_data.properties.ip_configurations[0].properties.public_ipaddress
|
155
|
+
unless public_ip_id_data.nil?
|
156
|
+
public_ip_name = public_ip_id_data.id.split('/')[-1]
|
157
|
+
public_ip_data = network_resource_client.public_ipaddresses.get(resource_group, public_ip_name)
|
158
|
+
else
|
159
|
+
public_ip_data = nil
|
160
|
+
end
|
185
161
|
|
186
|
-
|
187
|
-
|
162
|
+
details = Array.new
|
163
|
+
details << ui.color('Server Name', :bold, :cyan)
|
164
|
+
details << server.name
|
188
165
|
|
189
|
-
|
190
|
-
|
166
|
+
details << ui.color('Size', :bold, :cyan)
|
167
|
+
details << server.properties.hardware_profile.vm_size
|
191
168
|
|
192
|
-
|
193
|
-
|
169
|
+
details << ui.color('Provisioning State', :bold, :cyan)
|
170
|
+
details << server.properties.provisioning_state
|
194
171
|
|
195
|
-
|
196
|
-
|
172
|
+
details << ui.color('Location', :bold, :cyan)
|
173
|
+
details << server.location
|
197
174
|
|
198
|
-
|
199
|
-
|
175
|
+
details << ui.color('Publisher', :bold, :cyan)
|
176
|
+
details << server.properties.storage_profile.image_reference.publisher
|
200
177
|
|
201
|
-
|
202
|
-
|
178
|
+
details << ui.color('Offer', :bold, :cyan)
|
179
|
+
details << server.properties.storage_profile.image_reference.offer
|
203
180
|
|
204
|
-
|
205
|
-
|
181
|
+
details << ui.color('Sku', :bold, :cyan)
|
182
|
+
details << server.properties.storage_profile.image_reference.sku
|
206
183
|
|
207
|
-
|
208
|
-
|
209
|
-
details << public_ip_data.properties.ip_address
|
210
|
-
else
|
211
|
-
details << ' -- '
|
212
|
-
end
|
184
|
+
details << ui.color('Version', :bold, :cyan)
|
185
|
+
details << server.properties.storage_profile.image_reference.version
|
213
186
|
|
214
|
-
|
215
|
-
|
216
|
-
details << public_ip_data.properties.dns_settings.fqdn
|
217
|
-
else
|
218
|
-
details << ' -- '
|
219
|
-
end
|
187
|
+
details << ui.color('OS Type', :bold, :cyan)
|
188
|
+
details << server.properties.storage_profile.os_disk.os_type
|
220
189
|
|
221
|
-
|
190
|
+
details << ui.color('Public IP address', :bold, :cyan)
|
191
|
+
unless public_ip_data.nil?
|
192
|
+
details << public_ip_data.properties.ip_address
|
193
|
+
else
|
194
|
+
details << ' -- '
|
222
195
|
end
|
223
|
-
rescue => error
|
224
|
-
puts "#{error.body["error"]["message"]}"
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
def find_server(resource_group, name)
|
229
|
-
begin
|
230
|
-
promise = compute_management_client.virtual_machines.get(resource_group, name)
|
231
|
-
result = promise.value!
|
232
196
|
|
233
|
-
|
234
|
-
|
197
|
+
details << ui.color('FQDN', :bold, :cyan)
|
198
|
+
unless public_ip_data.nil? or public_ip_data.properties.dns_settings.nil?
|
199
|
+
details << public_ip_data.properties.dns_settings.fqdn
|
235
200
|
else
|
236
|
-
|
201
|
+
details << ' -- '
|
237
202
|
end
|
238
|
-
|
239
|
-
ui.
|
203
|
+
|
204
|
+
puts ui.list(details, :columns_across, 2)
|
240
205
|
end
|
241
|
-
server
|
242
206
|
end
|
243
207
|
|
244
|
-
def
|
245
|
-
|
208
|
+
def find_server(resource_group, name)
|
209
|
+
compute_management_client.virtual_machines.get(resource_group, name)
|
246
210
|
end
|
247
211
|
|
212
|
+
def virtual_machine_exist?(resource_group_name, vm_name)
|
213
|
+
begin
|
214
|
+
compute_management_client.virtual_machines.get(resource_group_name, vm_name)
|
215
|
+
return true
|
216
|
+
rescue MsRestAzure::AzureOperationError => error
|
217
|
+
if error.body
|
218
|
+
err_json = JSON.parse(error.response.body)
|
219
|
+
if err_json['error']['code'] == "ResourceNotFound"
|
220
|
+
return false
|
221
|
+
else
|
222
|
+
raise error
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def security_group_exist?(resource_group_name, security_group_name)
|
229
|
+
begin
|
230
|
+
network_resource_client.network_security_groups.get(resource_group_name, security_group_name)
|
231
|
+
return true
|
232
|
+
rescue MsRestAzure::AzureOperationError => error
|
233
|
+
if error.body
|
234
|
+
err_json = JSON.parse(error.response.body)
|
235
|
+
if err_json['error']['code'] == "ResourceNotFound"
|
236
|
+
return false
|
237
|
+
else
|
238
|
+
raise error
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
248
244
|
def resource_group_exist?(resource_group_name)
|
249
|
-
resource_management_client.resource_groups.check_existence(resource_group_name)
|
245
|
+
resource_management_client.resource_groups.check_existence(resource_group_name)
|
250
246
|
end
|
251
247
|
|
252
248
|
def platform(image_reference)
|
@@ -260,6 +256,69 @@ module Azure
|
|
260
256
|
end
|
261
257
|
end
|
262
258
|
|
259
|
+
def parse_substatus_code(code, index)
|
260
|
+
code.split('/')[index]
|
261
|
+
end
|
262
|
+
|
263
|
+
def fetch_substatus(resource_group_name, virtual_machine_name, chef_extension_name)
|
264
|
+
substatuses = compute_management_client.virtual_machine_extensions.get(
|
265
|
+
resource_group_name,
|
266
|
+
virtual_machine_name,
|
267
|
+
chef_extension_name,
|
268
|
+
'instanceView'
|
269
|
+
).properties.instance_view.substatuses
|
270
|
+
|
271
|
+
return nil if substatuses.nil?
|
272
|
+
|
273
|
+
substatuses.each do |substatus|
|
274
|
+
if parse_substatus_code(substatus.code, 1) == 'Chef Client run logs'
|
275
|
+
return substatus
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
return nil
|
280
|
+
end
|
281
|
+
|
282
|
+
def fetch_chef_client_logs(resource_group_name, virtual_machine_name, chef_extension_name, fetch_process_start_time, fetch_process_wait_timeout = 30)
|
283
|
+
## fetch substatus field which contains the chef-client run logs ##
|
284
|
+
substatus = fetch_substatus(resource_group_name, virtual_machine_name, chef_extension_name)
|
285
|
+
|
286
|
+
unless substatus.nil?
|
287
|
+
## chef-client run logs becomes available ##
|
288
|
+
status = parse_substatus_code(substatus.code, 2)
|
289
|
+
message = substatus.message
|
290
|
+
|
291
|
+
puts "\n\n******** Please find the chef-client run details below ********\n\n"
|
292
|
+
print "----> chef-client run status: "
|
293
|
+
case status
|
294
|
+
when 'succeeded'
|
295
|
+
## chef-client run succeeded ##
|
296
|
+
color = :green
|
297
|
+
when 'failed'
|
298
|
+
## chef-client run failed ##
|
299
|
+
color = :red
|
300
|
+
when 'transitioning'
|
301
|
+
## chef-client run did not complete within maximum timeout of 30 minutes ##
|
302
|
+
## fetch whatever logs available under the chef-client.log file ##
|
303
|
+
color = :yellow
|
304
|
+
end
|
305
|
+
puts "#{ui.color(status, color, :bold)}"
|
306
|
+
puts "----> chef-client run logs: "
|
307
|
+
puts "\n#{message}\n" ## message field of substatus contains the chef-client run logs ##
|
308
|
+
else
|
309
|
+
## unavailability of the substatus field indicates that chef-client run is not completed yet on the server ##
|
310
|
+
fetch_process_wait_time = ((Time.now - fetch_process_start_time) / 60).round
|
311
|
+
if fetch_process_wait_time <= fetch_process_wait_timeout
|
312
|
+
print "#{ui.color('.', :bold)}"
|
313
|
+
sleep 30
|
314
|
+
fetch_chef_client_logs(resource_group_name, virtual_machine_name, chef_extension_name, fetch_process_start_time, fetch_process_wait_timeout)
|
315
|
+
else
|
316
|
+
## wait time exceeded 30 minutes timeout ##
|
317
|
+
ui.error "\nchef-client run logs could not be fetched since fetch process exceeded wait timeout of #{fetch_process_wait_timeout} minutes.\n"
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
263
322
|
def create_server(params = {})
|
264
323
|
platform(params[:azure_image_reference_offer])
|
265
324
|
# resource group creation
|
@@ -273,22 +332,50 @@ module Azure
|
|
273
332
|
Chef::Log.info("Resource Group name is: #{resource_group.name}")
|
274
333
|
Chef::Log.info("Resource Group ID is: #{resource_group.id}")
|
275
334
|
end
|
276
|
-
|
335
|
+
|
277
336
|
# virtual machine creation
|
278
337
|
if virtual_machine_exist?(params[:azure_resource_group_name], params[:azure_vm_name])
|
279
338
|
ui.log("INFO:Virtual Machine #{params[:azure_vm_name]} already exist under the Resource Group #{params[:azure_resource_group_name]}. Exiting for now.")
|
280
339
|
else
|
281
340
|
params[:chef_extension_version] = params[:chef_extension_version].nil? ? get_latest_chef_extension_version(params) : params[:chef_extension_version]
|
282
341
|
params[:vm_size] = get_vm_size(params[:azure_vm_size])
|
342
|
+
params[:vnet_config] = create_vnet_config(
|
343
|
+
params[:azure_resource_group_name],
|
344
|
+
params[:azure_vnet_name],
|
345
|
+
params[:azure_vnet_subnet_name]
|
346
|
+
)
|
347
|
+
if params[:tcp_endpoints]
|
348
|
+
if @platform == 'Windows'
|
349
|
+
params[:tcp_endpoints] = params[:tcp_endpoints] + ",3389"
|
350
|
+
else
|
351
|
+
params[:tcp_endpoints] = params[:tcp_endpoints] + ",22,16001"
|
352
|
+
end
|
353
|
+
random_no = rand(100..1000)
|
354
|
+
params[:azure_sec_group_name] = params[:azure_vm_name] + '_sec_grp_' + random_no.to_s
|
355
|
+
if security_group_exist?(params[:azure_resource_group_name], params[:azure_sec_group_name])
|
356
|
+
random_no = rand(100..1000)
|
357
|
+
params[:azure_sec_group_name] = params[:azure_vm_name] + '_sec_grp_' + random_no.to_s
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
283
361
|
ui.log("Creating Virtual Machine....")
|
284
362
|
deployment = create_virtual_machine_using_template(params)
|
285
363
|
ui.log("Virtual Machine creation successfull.") unless deployment.nil?
|
286
|
-
|
364
|
+
|
287
365
|
unless deployment.nil?
|
288
366
|
ui.log("Deployment name is: #{deployment.name}")
|
289
367
|
ui.log("Deployment ID is: #{deployment.id}")
|
290
368
|
deployment.properties.dependencies.each do |deploy|
|
291
369
|
if deploy.resource_type == "Microsoft.Compute/virtualMachines"
|
370
|
+
if params[:chef_extension_public_param][:extendedLogs] == "true"
|
371
|
+
print "\n\nWaiting for the first chef-client run on virtual machine #{deploy.resource_name}"
|
372
|
+
fetch_chef_client_logs(params[:azure_resource_group_name],
|
373
|
+
deploy.resource_name,
|
374
|
+
params[:chef_extension],
|
375
|
+
Time.now
|
376
|
+
)
|
377
|
+
end
|
378
|
+
|
292
379
|
ui.log("VM Details ...")
|
293
380
|
ui.log("-------------------------------")
|
294
381
|
ui.log("Virtual Machine name is: #{deploy.resource_name}")
|
@@ -300,32 +387,6 @@ module Azure
|
|
300
387
|
end
|
301
388
|
end
|
302
389
|
|
303
|
-
def vm_details(virtual_machine, vm_extension, params)
|
304
|
-
vm_details = OpenStruct.new
|
305
|
-
vm_details.publicipaddress = vm_public_ip(params)
|
306
|
-
|
307
|
-
if @platform == 'Windows'
|
308
|
-
vm_details.rdpport = vm_default_port(params)
|
309
|
-
else
|
310
|
-
vm_details.sshport = vm_default_port(params)
|
311
|
-
end
|
312
|
-
|
313
|
-
vm_details.id = virtual_machine.id
|
314
|
-
vm_details.name = virtual_machine.name
|
315
|
-
vm_details.locationname = params[:azure_service_location].gsub(/[ ]/,'').downcase
|
316
|
-
vm_details.ostype = virtual_machine.properties.storage_profile.os_disk.os_type
|
317
|
-
vm_details.provisioningstate = virtual_machine.properties.provisioning_state
|
318
|
-
vm_details.resources = OpenStruct.new
|
319
|
-
vm_details.resources.id = vm_extension.id
|
320
|
-
vm_details.resources.name = vm_extension.name
|
321
|
-
vm_details.resources.publisher = vm_extension.properties.publisher
|
322
|
-
vm_details.resources.type = vm_extension.properties.type
|
323
|
-
vm_details.resources.type_handler_version = vm_extension.properties.type_handler_version
|
324
|
-
vm_details.resources.provisioning_state = vm_extension.properties.provisioning_state
|
325
|
-
|
326
|
-
vm_details
|
327
|
-
end
|
328
|
-
|
329
390
|
def vm_public_ip(params = {})
|
330
391
|
network_resource_client.public_ipaddresses.get(
|
331
392
|
params[:azure_resource_group_name],
|
@@ -346,11 +407,10 @@ module Azure
|
|
346
407
|
resource_group.location = params[:azure_service_location]
|
347
408
|
|
348
409
|
begin
|
349
|
-
resource_group = resource_management_client.resource_groups.create_or_update(resource_group.name, resource_group)
|
410
|
+
resource_group = resource_management_client.resource_groups.create_or_update(resource_group.name, resource_group)
|
350
411
|
rescue Exception => e
|
351
412
|
Chef::Log.error("Failed to create the Resource Group -- exception being rescued: #{e.to_s}")
|
352
|
-
|
353
|
-
Chef::Log.debug("#{backtrace_message}")
|
413
|
+
common_arm_rescue_block(e)
|
354
414
|
end
|
355
415
|
|
356
416
|
resource_group
|
@@ -372,357 +432,6 @@ module Azure
|
|
372
432
|
deployment
|
373
433
|
end
|
374
434
|
|
375
|
-
def create_virtual_machine(params)
|
376
|
-
os_profile = OSProfile.new
|
377
|
-
os_profile.computer_name = params[:azure_vm_name]
|
378
|
-
os_profile.secrets = []
|
379
|
-
|
380
|
-
if @platform == 'Windows'
|
381
|
-
windows_config = WindowsConfiguration.new
|
382
|
-
windows_config.provision_vmagent = true
|
383
|
-
windows_config.enable_automatic_updates = true
|
384
|
-
|
385
|
-
os_profile.admin_username = params[:winrm_user]
|
386
|
-
os_profile.admin_password = params[:admin_password]
|
387
|
-
os_profile.windows_configuration = windows_config
|
388
|
-
else
|
389
|
-
linux_config = LinuxConfiguration.new
|
390
|
-
linux_config.disable_password_authentication = false
|
391
|
-
|
392
|
-
os_profile.admin_username = params[:ssh_user]
|
393
|
-
os_profile.admin_password = params[:ssh_password]
|
394
|
-
os_profile.linux_configuration = linux_config
|
395
|
-
end
|
396
|
-
|
397
|
-
hardware_profile = HardwareProfile.new
|
398
|
-
hardware_profile.vm_size = get_vm_size(params[:azure_vm_size])
|
399
|
-
|
400
|
-
vm_props = VirtualMachineProperties.new
|
401
|
-
vm_props.os_profile = os_profile
|
402
|
-
vm_props.hardware_profile = hardware_profile
|
403
|
-
vm_props.storage_profile = create_storage_profile(params)
|
404
|
-
vm_props.network_profile = create_network_profile(params)
|
405
|
-
|
406
|
-
vm_params = VirtualMachine.new
|
407
|
-
vm_params.name = params[:azure_vm_name]
|
408
|
-
vm_params.type = 'Microsoft.Compute/virtualMachines'
|
409
|
-
vm_params.properties = vm_props
|
410
|
-
vm_params.location = params[:azure_service_location]
|
411
|
-
|
412
|
-
begin
|
413
|
-
virtual_machine = compute_management_client.virtual_machines.create_or_update(params[:azure_resource_group_name], vm_params.name, vm_params).value!.body
|
414
|
-
rescue Exception => e
|
415
|
-
ui.log("Failed to create the virtual machine, use verbose mode for more details")
|
416
|
-
Chef::Log.error("Failed to create the Virtual Machine -- exception being rescued: #{e.to_s}")
|
417
|
-
backtrace_message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
418
|
-
Chef::Log.debug("#{backtrace_message}")
|
419
|
-
end
|
420
|
-
|
421
|
-
virtual_machine
|
422
|
-
end
|
423
|
-
|
424
|
-
def create_storage_profile(params)
|
425
|
-
ui.log("Creating Storage Account.... \n\n ")
|
426
|
-
storage_account = create_storage_account(
|
427
|
-
params[:azure_storage_account],
|
428
|
-
params[:azure_service_location],
|
429
|
-
params[:azure_storage_account_type],
|
430
|
-
params[:azure_resource_group_name]
|
431
|
-
)
|
432
|
-
|
433
|
-
virtual_hard_disk = get_vhd(
|
434
|
-
params[:azure_storage_account],
|
435
|
-
params[:azure_os_disk_name]
|
436
|
-
)
|
437
|
-
|
438
|
-
ui.log("StorageAccount creation successfull.")
|
439
|
-
storage_profile = StorageProfile.new
|
440
|
-
storage_profile.image_reference = get_image_reference(
|
441
|
-
params[:azure_image_reference_publisher],
|
442
|
-
params[:azure_image_reference_offer],
|
443
|
-
params[:azure_image_reference_sku],
|
444
|
-
params[:azure_image_reference_version]
|
445
|
-
)
|
446
|
-
storage_profile.os_disk = get_os_disk(
|
447
|
-
virtual_hard_disk,
|
448
|
-
params[:azure_os_disk_name],
|
449
|
-
params[:azure_os_disk_caching],
|
450
|
-
params[:azure_os_disk_create_option]
|
451
|
-
)
|
452
|
-
|
453
|
-
storage_profile
|
454
|
-
end
|
455
|
-
|
456
|
-
def create_storage_account(storage_account_name, location, storage_account_type, resource_group_name)
|
457
|
-
storage_props = Azure::ARM::Storage::Models::StorageAccountPropertiesCreateParameters.new
|
458
|
-
storage_props.account_type = storage_account_type
|
459
|
-
|
460
|
-
storage_params = Azure::ARM::Storage::Models::StorageAccountCreateParameters.new
|
461
|
-
storage_params.location = location
|
462
|
-
storage_params.properties = storage_props
|
463
|
-
|
464
|
-
storage = storage_management_client.storage_accounts.create(resource_group_name, storage_account_name, storage_params).value!.body
|
465
|
-
storage
|
466
|
-
end
|
467
|
-
|
468
|
-
def get_vhd(storage_account_name, os_disk_name)
|
469
|
-
virtual_hard_disk = VirtualHardDisk.new
|
470
|
-
virtual_hard_disk.uri = "http://#{storage_account_name}.blob.core.windows.net/vhds/#{os_disk_name}.vhd"
|
471
|
-
virtual_hard_disk
|
472
|
-
end
|
473
|
-
|
474
|
-
def get_image_reference(publisher, offer, sku, version)
|
475
|
-
image_reference = ImageReference.new
|
476
|
-
image_reference.publisher = publisher
|
477
|
-
image_reference.offer = offer
|
478
|
-
image_reference.sku = sku
|
479
|
-
image_reference.version = version
|
480
|
-
image_reference
|
481
|
-
end
|
482
|
-
|
483
|
-
def get_os_disk(virtual_hard_disk, os_disk_name, os_disk_caching, os_disk_create_option)
|
484
|
-
os_disk = OSDisk.new
|
485
|
-
os_disk.name = os_disk_name
|
486
|
-
os_disk.vhd = virtual_hard_disk
|
487
|
-
os_disk.caching = os_disk_caching
|
488
|
-
os_disk.create_option = os_disk_create_option
|
489
|
-
os_disk
|
490
|
-
end
|
491
|
-
|
492
|
-
def vnet_exist?(resource_group_name, vnet_name)
|
493
|
-
begin
|
494
|
-
network_resource_client.virtual_networks.get(resource_group_name, vnet_name).value!.body
|
495
|
-
rescue
|
496
|
-
return false
|
497
|
-
end
|
498
|
-
end
|
499
|
-
|
500
|
-
def subnet_exist?(resource_group_name, vnet_name, subnet_name)
|
501
|
-
begin
|
502
|
-
network_resource_client.subnets.get(resource_group_name, vnet_name, subnet_name).value!.body
|
503
|
-
rescue
|
504
|
-
return false
|
505
|
-
end
|
506
|
-
end
|
507
|
-
|
508
|
-
def create_network_profile(params)
|
509
|
-
if vnet_exist?(params[:azure_resource_group_name], params[:azure_vnet_name])
|
510
|
-
vnet = network_resource_client.virtual_networks.get(params[:azure_resource_group_name], params[:azure_vnet_name]).value!.body
|
511
|
-
Chef::Log.info("Found existing vnet #{vnet.name}...")
|
512
|
-
else
|
513
|
-
ui.log("Creating VirtualNetwork....\n\n")
|
514
|
-
vnet = create_virtual_network(
|
515
|
-
params[:azure_resource_group_name],
|
516
|
-
params[:azure_vnet_name],
|
517
|
-
params[:azure_service_location]
|
518
|
-
)
|
519
|
-
Chef::Log.info("VirtualNetwork creation successfull.")
|
520
|
-
end
|
521
|
-
|
522
|
-
Chef::Log.info("Virtual Network name is: #{vnet.name}")
|
523
|
-
|
524
|
-
Chef::Log.info("Virtual Network ID is: #{vnet.id}")
|
525
|
-
|
526
|
-
if subnet_exist?(params[:azure_resource_group_name], vnet.name, params[:azure_vnet_subnet_name])
|
527
|
-
sbn = network_resource_client.subnets.get(params[:azure_resource_group_name], vnet.name, params[:azure_vnet_subnet_name]).value!.body
|
528
|
-
|
529
|
-
Chef::Log.info("Found subnet #{sbn.name} under virtual network #{vnet.name} ...")
|
530
|
-
|
531
|
-
else
|
532
|
-
ui.log("Creating Subnet....\n\n")
|
533
|
-
sbn = create_subnet(
|
534
|
-
params[:azure_resource_group_name],
|
535
|
-
params[:azure_vnet_subnet_name],
|
536
|
-
vnet
|
537
|
-
)
|
538
|
-
Chef::Log.info("Subnet creation successfull.")
|
539
|
-
end
|
540
|
-
|
541
|
-
Chef::Log.info("Subnet name is: #{sbn.name}")
|
542
|
-
Chef::Log.info("Subnet ID is: #{sbn.id}")
|
543
|
-
|
544
|
-
ui.log("Creating NetworkInterface....\n\n")
|
545
|
-
nic = create_network_interface(
|
546
|
-
params[:azure_resource_group_name],
|
547
|
-
params[:azure_vm_name],
|
548
|
-
params[:azure_service_location],
|
549
|
-
sbn
|
550
|
-
)
|
551
|
-
Chef::Log.info("NetworkInterface creation successfull.")
|
552
|
-
Chef::Log.info("Network Interface name is: #{nic.name}")
|
553
|
-
Chef::Log.info("Network Interface ID is: #{nic.id}")
|
554
|
-
|
555
|
-
network_profile = NetworkProfile.new
|
556
|
-
network_profile.network_interfaces = [nic]
|
557
|
-
network_profile
|
558
|
-
end
|
559
|
-
|
560
|
-
def create_virtual_network(resource_group_name, virtual_network_name, service_location)
|
561
|
-
address_space = AddressSpace.new
|
562
|
-
address_space.address_prefixes = ['10.0.0.0/16']
|
563
|
-
|
564
|
-
vnet_props = VirtualNetworkPropertiesFormat.new
|
565
|
-
vnet_props.address_space = address_space
|
566
|
-
|
567
|
-
vnet_params = VirtualNetwork.new
|
568
|
-
vnet_params.name = virtual_network_name
|
569
|
-
vnet_params.location = service_location
|
570
|
-
vnet_params.properties = vnet_props
|
571
|
-
|
572
|
-
begin
|
573
|
-
vnet = network_resource_client.virtual_networks.create_or_update(resource_group_name, vnet_params.name, vnet_params).value!.body
|
574
|
-
rescue Exception => e
|
575
|
-
Chef::Log.error("Failed to create the Virtual Network -- exception being rescued: #{e.to_s}")
|
576
|
-
backtrace_message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
577
|
-
Chef::Log.debug("#{backtrace_message}")
|
578
|
-
end
|
579
|
-
vnet
|
580
|
-
end
|
581
|
-
|
582
|
-
def create_subnet(resource_group_name, subnet_name, virtual_network)
|
583
|
-
sbn_prop = SubnetPropertiesFormat.new
|
584
|
-
sbn_prop.address_prefix = '10.0.1.0/24'
|
585
|
-
|
586
|
-
sbn_params = Subnet.new
|
587
|
-
sbn_params.name = subnet_name
|
588
|
-
sbn_params.properties = sbn_prop
|
589
|
-
|
590
|
-
begin
|
591
|
-
sbn = network_resource_client.subnets.create_or_update(resource_group_name, virtual_network.name, sbn_params.name, sbn_params).value!.body
|
592
|
-
rescue Exception => e
|
593
|
-
Chef::Log.error("Failed to create the Subnet -- exception being rescued: #{e.to_s}")
|
594
|
-
backtrace_message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
595
|
-
Chef::Log.debug("#{backtrace_message}")
|
596
|
-
end
|
597
|
-
sbn
|
598
|
-
end
|
599
|
-
|
600
|
-
def create_network_interface(resource_group_name, vm_name, service_location, subnet)
|
601
|
-
network_ip_configuration_properties = NetworkInterfaceIPConfigurationPropertiesFormat.new
|
602
|
-
network_ip_configuration_properties.private_ipallocation_method = 'Dynamic'
|
603
|
-
|
604
|
-
network_ip_configuration_properties.public_ipaddress = create_public_ip_config(
|
605
|
-
resource_group_name,
|
606
|
-
vm_name,
|
607
|
-
service_location
|
608
|
-
)
|
609
|
-
|
610
|
-
network_ip_configuration_properties.subnet = subnet
|
611
|
-
|
612
|
-
network_interface_ip_configuration = NetworkInterfaceIPConfiguration.new
|
613
|
-
network_interface_ip_configuration.properties = network_ip_configuration_properties
|
614
|
-
network_interface_ip_configuration.name = vm_name
|
615
|
-
|
616
|
-
network_interface_props_format = NetworkInterfacePropertiesFormat.new
|
617
|
-
network_interface_props_format.ip_configurations = [network_interface_ip_configuration]
|
618
|
-
network_interface_props_format.network_security_group = create_network_security_group(
|
619
|
-
resource_group_name,
|
620
|
-
vm_name,
|
621
|
-
service_location
|
622
|
-
)
|
623
|
-
|
624
|
-
network_interface = NetworkInterface.new
|
625
|
-
network_interface.location = service_location
|
626
|
-
network_interface.name = vm_name
|
627
|
-
network_interface.properties = network_interface_props_format
|
628
|
-
|
629
|
-
begin
|
630
|
-
nic = network_resource_client.network_interfaces.create_or_update(resource_group_name, network_interface.name, network_interface).value!.body
|
631
|
-
rescue Exception => e
|
632
|
-
Chef::Log.error("Failed to create the Network Interface -- exception being rescued: #{e.to_s}")
|
633
|
-
backtrace_message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
634
|
-
Chef::Log.debug("#{backtrace_message}")
|
635
|
-
end
|
636
|
-
|
637
|
-
nic
|
638
|
-
end
|
639
|
-
|
640
|
-
def create_public_ip_config(resource_group_name, vm_name, service_location)
|
641
|
-
public_ip_props = PublicIPAddressPropertiesFormat.new
|
642
|
-
public_ip_props.public_ipallocation_method = 'Dynamic'
|
643
|
-
|
644
|
-
public_ip = PublicIPAddress.new
|
645
|
-
public_ip.name = vm_name
|
646
|
-
public_ip.location = service_location
|
647
|
-
public_ip.properties = public_ip_props
|
648
|
-
|
649
|
-
begin
|
650
|
-
public_ip_address = network_resource_client.public_ipaddresses.create_or_update(
|
651
|
-
resource_group_name,
|
652
|
-
public_ip.name,
|
653
|
-
public_ip
|
654
|
-
).value!.body
|
655
|
-
rescue Exception => e
|
656
|
-
Chef::Log.error("Failed to create the Public IP Address -- exception being rescued: #{e.to_s}")
|
657
|
-
backtrace_message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
658
|
-
Chef::Log.debug("#{backtrace_message}")
|
659
|
-
end
|
660
|
-
|
661
|
-
public_ip_address
|
662
|
-
end
|
663
|
-
|
664
|
-
def create_network_security_group(resource_group_name, vm_name, service_location)
|
665
|
-
network_security_group_prop_format = NetworkSecurityGroupPropertiesFormat.new
|
666
|
-
network_security_group = NetworkSecurityGroup.new
|
667
|
-
network_security_group.name = vm_name
|
668
|
-
network_security_group.location = service_location
|
669
|
-
network_security_group.properties = network_security_group_prop_format
|
670
|
-
|
671
|
-
begin
|
672
|
-
nsg = network_resource_client.network_security_groups.create_or_update(
|
673
|
-
resource_group_name,
|
674
|
-
network_security_group.name,
|
675
|
-
network_security_group
|
676
|
-
).value!.body
|
677
|
-
rescue Exception => e
|
678
|
-
Chef::Log.error("Failed to create the Network Security Group -- exception being rescued: #{e.to_s}")
|
679
|
-
backtrace_message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
680
|
-
Chef::Log.debug("#{backtrace_message}")
|
681
|
-
end
|
682
|
-
|
683
|
-
security_rules = []
|
684
|
-
if @platform == 'Windows'
|
685
|
-
security_rules << add_security_rule('3389', "RDP", 1000, resource_group_name, vm_name, network_security_group)
|
686
|
-
else
|
687
|
-
security_rules << add_security_rule("22", "SSH", 1000, resource_group_name, vm_name, network_security_group)
|
688
|
-
end
|
689
|
-
network_security_group_prop_format.default_security_rules = security_rules
|
690
|
-
|
691
|
-
nsg
|
692
|
-
end
|
693
|
-
|
694
|
-
def add_security_rule(port, description, priority, resource_group_name, vm_name, network_security_group)
|
695
|
-
security_rule_props = SecurityRulePropertiesFormat.new
|
696
|
-
security_rule_props.description = description
|
697
|
-
security_rule_props.destination_port_range = port
|
698
|
-
security_rule_props.protocol = "Tcp"
|
699
|
-
security_rule_props.source_port_range = "*"
|
700
|
-
security_rule_props.source_address_prefix = "*"
|
701
|
-
security_rule_props.destination_address_prefix = "*"
|
702
|
-
security_rule_props.access = "Allow"
|
703
|
-
security_rule_props.priority = priority
|
704
|
-
security_rule_props.direction = "Inbound"
|
705
|
-
|
706
|
-
security_rule = SecurityRule.new
|
707
|
-
security_rule.name = vm_name
|
708
|
-
security_rule.properties = security_rule_props
|
709
|
-
|
710
|
-
begin
|
711
|
-
security_rule = network_resource_client.security_rules.create_or_update(
|
712
|
-
resource_group_name,
|
713
|
-
network_security_group.name,
|
714
|
-
security_rule.name,
|
715
|
-
security_rule
|
716
|
-
).value!.body
|
717
|
-
rescue Exception => e
|
718
|
-
Chef::Log.error("Failed to create the Security Rule -- exception being rescued: #{e.to_s}")
|
719
|
-
backtrace_message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
720
|
-
Chef::Log.debug("#{backtrace_message}")
|
721
|
-
end
|
722
|
-
|
723
|
-
security_rule
|
724
|
-
end
|
725
|
-
|
726
435
|
def create_vm_extension(params)
|
727
436
|
vm_ext_props = VirtualMachineExtensionProperties.new
|
728
437
|
vm_ext_props.publisher = params[:chef_extension_publisher]
|
@@ -731,12 +440,12 @@ module Azure
|
|
731
440
|
vm_ext_props.auto_upgrade_minor_version = false
|
732
441
|
vm_ext_props.settings = params[:chef_extension_public_param]
|
733
442
|
vm_ext_props.protected_settings = params[:chef_extension_private_param]
|
734
|
-
|
443
|
+
|
735
444
|
vm_ext = VirtualMachineExtension.new
|
736
445
|
vm_ext.name = params[:chef_extension]
|
737
446
|
vm_ext.location = params[:azure_service_location]
|
738
447
|
vm_ext.properties = vm_ext_props
|
739
|
-
|
448
|
+
|
740
449
|
begin
|
741
450
|
vm_extension = compute_management_client.virtual_machine_extensions.create_or_update(
|
742
451
|
params[:azure_resource_group_name],
|
@@ -744,22 +453,9 @@ module Azure
|
|
744
453
|
vm_ext.name,
|
745
454
|
vm_ext
|
746
455
|
).value!.body
|
747
|
-
rescue Exception =>
|
456
|
+
rescue Exception => error
|
748
457
|
Chef::Log.error("Failed to create the Virtual Machine Extension -- exception being rescued.")
|
749
|
-
|
750
|
-
if e.class == MsRestAzure::AzureOperationError && e.body
|
751
|
-
if e.body['error']['code'] == 'DeploymentFailed'
|
752
|
-
ui.error("#{error.body['error']['message']}")
|
753
|
-
else
|
754
|
-
ui.error(e.body)
|
755
|
-
end
|
756
|
-
else
|
757
|
-
ui.error("#{error.message}")
|
758
|
-
Chef::Log.debug("#{error.backtrace.join("\n")}")
|
759
|
-
end
|
760
|
-
|
761
|
-
backtrace_message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
|
762
|
-
Chef::Log.debug("#{backtrace_message}")
|
458
|
+
common_arm_rescue_block(error)
|
763
459
|
end
|
764
460
|
|
765
461
|
vm_extension
|
@@ -776,7 +472,7 @@ module Azure
|
|
776
472
|
ext_version = compute_management_client.virtual_machine_extension_images.list_versions(
|
777
473
|
params[:azure_service_location],
|
778
474
|
params[:chef_extension_publisher],
|
779
|
-
params[:chef_extension]).
|
475
|
+
params[:chef_extension]).last.name
|
780
476
|
ext_version_split_values = ext_version.split(".")
|
781
477
|
ext_version = ext_version_split_values[0] + "." + ext_version_split_values[1]
|
782
478
|
ext_version
|
@@ -784,12 +480,36 @@ module Azure
|
|
784
480
|
|
785
481
|
def delete_resource_group(resource_group_name)
|
786
482
|
ui.info 'Resource group deletion takes some time. Please wait ...'
|
483
|
+
|
787
484
|
begin
|
788
|
-
|
789
|
-
|
790
|
-
end until promise.value!.body.nil?
|
485
|
+
server = resource_management_client.resource_groups.delete(resource_group_name)
|
486
|
+
end until server.value!.body.nil?
|
791
487
|
puts "\n"
|
792
488
|
end
|
489
|
+
|
490
|
+
def common_arm_rescue_block(error)
|
491
|
+
if error.class == MsRestAzure::AzureOperationError && error.body
|
492
|
+
err_json = JSON.parse(error.response.body)
|
493
|
+
err_details = err_json["error"]["details"] if err_json["error"]
|
494
|
+
if err_details
|
495
|
+
err_details.each do |err|
|
496
|
+
ui.error(JSON.parse(err["message"])["error"]["message"])
|
497
|
+
end
|
498
|
+
else
|
499
|
+
ui.error(err_json["error"]["message"])
|
500
|
+
end
|
501
|
+
Chef::Log.debug(error.response.body)
|
502
|
+
else
|
503
|
+
begin
|
504
|
+
JSON.parse(error.message)
|
505
|
+
Chef::Log.debug("#{error.message}")
|
506
|
+
rescue JSON::ParserError => e
|
507
|
+
ui.error("#{error.message}")
|
508
|
+
end
|
509
|
+
ui.error("Something went wrong. Please use -VV option for more details.")
|
510
|
+
Chef::Log.debug("#{error.backtrace.join("\n")}")
|
511
|
+
end
|
512
|
+
end
|
793
513
|
end
|
794
514
|
end
|
795
515
|
end
|