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.
- checksums.yaml +4 -4
- data/lib/azure/custom_errors.rb +1 -1
- data/lib/azure/resource_management/ARM_deployment_template.rb +5 -5
- data/lib/azure/resource_management/ARM_interface.rb +4 -6
- data/lib/azure/resource_management/windows_credentials.rb +2 -2
- data/lib/chef/knife/azurerm_server_create.rb +1 -1
- data/lib/chef/knife/bootstrap/bootstrapper.rb +5 -10
- data/lib/chef/knife/helpers/azurerm_base.rb +4 -4
- data/lib/knife-azure/version.rb +1 -1
- metadata +30 -43
- data/lib/azure/service_management/ASM_interface.rb +0 -310
- data/lib/azure/service_management/ag.rb +0 -99
- data/lib/azure/service_management/certificate.rb +0 -235
- data/lib/azure/service_management/connection.rb +0 -102
- data/lib/azure/service_management/deploy.rb +0 -221
- data/lib/azure/service_management/disk.rb +0 -68
- data/lib/azure/service_management/host.rb +0 -184
- data/lib/azure/service_management/image.rb +0 -94
- data/lib/azure/service_management/loadbalancer.rb +0 -78
- data/lib/azure/service_management/rest.rb +0 -126
- data/lib/azure/service_management/role.rb +0 -717
- data/lib/azure/service_management/storageaccount.rb +0 -127
- data/lib/azure/service_management/utility.rb +0 -40
- data/lib/azure/service_management/vnet.rb +0 -134
- data/lib/chef/knife/azure_ag_create.rb +0 -73
- data/lib/chef/knife/azure_ag_list.rb +0 -35
- data/lib/chef/knife/azure_image_list.rb +0 -56
- data/lib/chef/knife/azure_internal-lb_create.rb +0 -74
- data/lib/chef/knife/azure_internal-lb_list.rb +0 -35
- data/lib/chef/knife/azure_server_create.rb +0 -531
- data/lib/chef/knife/azure_server_delete.rb +0 -136
- data/lib/chef/knife/azure_server_list.rb +0 -38
- data/lib/chef/knife/azure_server_show.rb +0 -41
- data/lib/chef/knife/azure_vnet_create.rb +0 -74
- data/lib/chef/knife/azure_vnet_list.rb +0 -35
- data/lib/chef/knife/bootstrap_azure.rb +0 -191
- data/lib/chef/knife/helpers/azure_base.rb +0 -392
@@ -1,717 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Barry Davis (barryd@jetstreamsoftware.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 "securerandom" unless defined?(SecureRandom)
|
20
|
-
require_relative "utility"
|
21
|
-
|
22
|
-
module Azure
|
23
|
-
class Roles
|
24
|
-
include AzureUtility
|
25
|
-
attr_accessor :connection, :roles
|
26
|
-
def initialize(connection)
|
27
|
-
@connection = connection
|
28
|
-
@roles = nil
|
29
|
-
end
|
30
|
-
|
31
|
-
# do not use this unless you want a list of all roles(vms) in your subscription
|
32
|
-
def all
|
33
|
-
@roles = []
|
34
|
-
@connection.deploys.all.each do |deploy|
|
35
|
-
deploy.roles.each do |role|
|
36
|
-
@roles << role
|
37
|
-
end
|
38
|
-
end
|
39
|
-
@roles
|
40
|
-
end
|
41
|
-
|
42
|
-
def find_roles_within_hostedservice(hostedservicename)
|
43
|
-
host = @connection.hosts.find(hostedservicename)
|
44
|
-
host ? host.roles : nil # nil says invalid hosted service
|
45
|
-
end
|
46
|
-
|
47
|
-
def find_in_hosted_service(role_name, hostedservicename)
|
48
|
-
host = @connection.hosts.find(hostedservicename)
|
49
|
-
return nil if host.nil?
|
50
|
-
|
51
|
-
host.find_role(role_name)
|
52
|
-
end
|
53
|
-
|
54
|
-
def find(role_name, params = nil)
|
55
|
-
if params && params[:azure_dns_name]
|
56
|
-
return find_in_hosted_service(role_name, params[:azure_dns_name])
|
57
|
-
end
|
58
|
-
|
59
|
-
all if @roles.nil?
|
60
|
-
|
61
|
-
# TODO: - optimize this lookup
|
62
|
-
@roles.each do |role|
|
63
|
-
return role if role.name == role_name
|
64
|
-
end
|
65
|
-
nil
|
66
|
-
end
|
67
|
-
|
68
|
-
def alone_on_hostedservice(found_role)
|
69
|
-
roles = find_roles_within_hostedservice(found_role.hostedservicename)
|
70
|
-
return false if roles && roles.length > 1
|
71
|
-
|
72
|
-
true
|
73
|
-
end
|
74
|
-
|
75
|
-
def exists?(name)
|
76
|
-
find(name) != nil
|
77
|
-
end
|
78
|
-
|
79
|
-
def delete(params)
|
80
|
-
role = find(params[:name])
|
81
|
-
unless role.nil?
|
82
|
-
roleXML = nil
|
83
|
-
roleXML = @connection.query_azure("hostedservices/#{role.hostedservicename}", "get", "", "embed-detail=true")
|
84
|
-
osdisk = roleXML.css(roleXML, "OSVirtualHardDisk")
|
85
|
-
disk_name = xml_content(osdisk, "DiskName")
|
86
|
-
storage_account_name = xml_content(osdisk, "MediaLink").gsub("http://", "").gsub(/.blob(.*)$/, "")
|
87
|
-
|
88
|
-
if !params[:preserve_azure_os_disk] && !params[:preserve_azure_vhd] && !params[:wait]
|
89
|
-
# default compmedia = true. So, it deletes role and associated resources
|
90
|
-
check_and_delete_role_and_resources(params, role)
|
91
|
-
else
|
92
|
-
# compmedia = false. So, it deletes only role and not associated resources
|
93
|
-
check_and_delete_role_and_resources(params, role, compmedia = false)
|
94
|
-
check_and_delete_disks(params, disk_name)
|
95
|
-
check_and_delete_service(params)
|
96
|
-
end
|
97
|
-
check_and_delete_storage(params, disk_name, storage_account_name)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def check_and_delete_role_and_resources(params, role, compmedia = true)
|
102
|
-
if alone_on_hostedservice(role)
|
103
|
-
if !params[:preserve_azure_dns_name] && compmedia
|
104
|
-
servicecall = "hostedservices/#{role.hostedservicename}"
|
105
|
-
else
|
106
|
-
servicecall = "hostedservices/#{role.hostedservicename}/deployments/#{role.deployname}"
|
107
|
-
end
|
108
|
-
else
|
109
|
-
servicecall = "hostedservices/#{role.hostedservicename}/deployments" \
|
110
|
-
"/#{role.deployname}/roles/#{role.name}"
|
111
|
-
end
|
112
|
-
if compmedia
|
113
|
-
@connection.query_azure(servicecall, "delete", "", "comp=media", wait = params[:wait])
|
114
|
-
else
|
115
|
-
@connection.query_azure(servicecall, "delete")
|
116
|
-
end
|
117
|
-
|
118
|
-
# delete role from local cache as well.
|
119
|
-
@connection.hosts.find(role.hostedservicename).delete_role(role)
|
120
|
-
@roles.delete(role) if @roles
|
121
|
-
end
|
122
|
-
|
123
|
-
def check_and_delete_disks(params, disk_name)
|
124
|
-
servicecall = "disks/#{disk_name}"
|
125
|
-
unless params[:preserve_azure_os_disk]
|
126
|
-
# OS Disk can only be deleted if it is detached from the VM.
|
127
|
-
# So Iteratively check for disk detachment from the VM while waiting for 5 minutes ,
|
128
|
-
# exit otherwise after 12 attempts.
|
129
|
-
for attempt in 0..12
|
130
|
-
break if @connection.query_azure(servicecall, "get").search("AttachedTo").text == ""
|
131
|
-
|
132
|
-
attempt == 12 ? (puts "The associated disk could not be deleted due to time out.") : (sleep 25)
|
133
|
-
end
|
134
|
-
if params[:preserve_azure_vhd]
|
135
|
-
@connection.query_azure(servicecall, "delete")
|
136
|
-
else
|
137
|
-
@connection.query_azure(servicecall, "delete", "", "comp=media", wait = params[:wait])
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def check_and_delete_service(params)
|
143
|
-
unless params[:preserve_azure_dns_name]
|
144
|
-
unless params[:azure_dns_name].nil?
|
145
|
-
roles_using_same_service = find_roles_within_hostedservice(params[:azure_dns_name])
|
146
|
-
if roles_using_same_service.size <= 1
|
147
|
-
servicecall = "hostedservices/" + params[:azure_dns_name]
|
148
|
-
@connection.query_azure(servicecall, "delete")
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def check_and_delete_storage(params, disk_name, storage_account_name)
|
155
|
-
if params[:delete_azure_storage_account]
|
156
|
-
# Iteratively check for disk deletion
|
157
|
-
for attempt in 0..12
|
158
|
-
break unless @connection.query_azure("disks").search("Name").text.include?(disk_name)
|
159
|
-
|
160
|
-
attempt == 12 ? (puts "The associated disk could not be deleted due to time out.") : (sleep 25)
|
161
|
-
end
|
162
|
-
begin
|
163
|
-
@connection.query_azure("storageservices/#{storage_account_name}", "delete")
|
164
|
-
rescue Exception => ex
|
165
|
-
ui.warn(ex.message.to_s)
|
166
|
-
ui.warn(ex.backtrace.join("\n").to_s)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
def update(name, params)
|
172
|
-
role = Role.new(@connection)
|
173
|
-
roleExtensionXml = role.setup_extension(params)
|
174
|
-
role.update(name, params, roleExtensionXml)
|
175
|
-
end
|
176
|
-
|
177
|
-
private :check_and_delete_role_and_resources, :check_and_delete_disks, :check_and_delete_service, :check_and_delete_storage
|
178
|
-
end
|
179
|
-
|
180
|
-
class Role
|
181
|
-
include AzureUtility
|
182
|
-
attr_accessor :connection, :name, :status, :size, :ipaddress, :publicipaddress
|
183
|
-
attr_accessor :sshport, :hostedservicename, :deployname, :thumbprint
|
184
|
-
attr_accessor :winrmport
|
185
|
-
attr_accessor :hostname, :tcpports, :udpports
|
186
|
-
attr_accessor :role_xml, :os_type, :os_version
|
187
|
-
|
188
|
-
TCP_ENDPOINTS_MAPPING = { "3389" => "Remote Desktop",
|
189
|
-
"5986" => "PowerShell",
|
190
|
-
"22" => "SSH",
|
191
|
-
"21" => "FTP",
|
192
|
-
"25" => "SMTP",
|
193
|
-
"53" => "DNS",
|
194
|
-
"80" => "HTTP",
|
195
|
-
"110" => "POP3",
|
196
|
-
"143" => "IMAP",
|
197
|
-
"389" => "LDAP",
|
198
|
-
"443" => "HTTPs",
|
199
|
-
"587" => "SMTPS",
|
200
|
-
"995" => "POP3S",
|
201
|
-
"993" => "IMAPS",
|
202
|
-
"1433" => "MSSQL",
|
203
|
-
"3306" => "MySQL" }.freeze
|
204
|
-
|
205
|
-
def initialize(connection)
|
206
|
-
@connection = connection
|
207
|
-
end
|
208
|
-
|
209
|
-
def parse(roleXML, hostedservicename, deployname)
|
210
|
-
@name = xml_content(roleXML, "RoleName")
|
211
|
-
@status = xml_content(roleXML, "InstanceStatus")
|
212
|
-
@size = xml_content(roleXML, "InstanceSize")
|
213
|
-
@ipaddress = xml_content(roleXML, "IpAddress")
|
214
|
-
@hostname = xml_content(roleXML, "HostName")
|
215
|
-
@hostedservicename = hostedservicename
|
216
|
-
@deployname = deployname
|
217
|
-
@thumbprint = fetch_thumbprint
|
218
|
-
@tcpports = []
|
219
|
-
@udpports = []
|
220
|
-
|
221
|
-
endpoints = roleXML.css("InstanceEndpoint")
|
222
|
-
@publicipaddress = xml_content(endpoints[0], "Vip") unless endpoints.empty?
|
223
|
-
endpoints.each do |endpoint|
|
224
|
-
if xml_content(endpoint, "Name").casecmp("ssh").zero?
|
225
|
-
@sshport = xml_content(endpoint, "PublicPort")
|
226
|
-
elsif xml_content(endpoint, "Name").casecmp("winrm").zero?
|
227
|
-
@winrmport = xml_content(endpoint, "PublicPort")
|
228
|
-
else
|
229
|
-
hash = {}
|
230
|
-
hash["Name"] = xml_content(endpoint, "Name")
|
231
|
-
hash["Vip"] = xml_content(endpoint, "Vip")
|
232
|
-
hash["PublicPort"] = xml_content(endpoint, "PublicPort")
|
233
|
-
hash["LocalPort"] = xml_content(endpoint, "LocalPort")
|
234
|
-
|
235
|
-
if xml_content(endpoint, "Protocol") == "tcp"
|
236
|
-
@tcpports << hash
|
237
|
-
else # == 'udp'
|
238
|
-
@udpports << hash
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
def parse_role_list_xml(roleListXML)
|
245
|
-
@role_xml = roleListXML
|
246
|
-
os_disk_xml = roleListXML.css("OSVirtualHardDisk")
|
247
|
-
@os_type = xml_content(os_disk_xml, "OS")
|
248
|
-
@os_version = xml_content(os_disk_xml, "SourceImageName")
|
249
|
-
end
|
250
|
-
|
251
|
-
# Expects endpoint_param_string to be in the form {localport}:{publicport}:{lb_set_name}:{lb_probe_path}
|
252
|
-
# Only localport is mandatory.
|
253
|
-
def parse_endpoint_from_params(protocol, _azure_vm_name, endpoint_param_string)
|
254
|
-
fields = endpoint_param_string.split(":").map(&:strip)
|
255
|
-
hash = {}
|
256
|
-
hash["LocalPort"] = fields[0]
|
257
|
-
hash["Port"] = fields[1] || fields[0]
|
258
|
-
hash["LoadBalancerName"] = fields[2] if fields[2] != "EXTERNAL" # TODO: hackity hack.. Shouldn't use magic words.
|
259
|
-
hash["LoadBalancedEndpointSetName"] = fields[3]
|
260
|
-
hash["Protocol"] = protocol
|
261
|
-
if TCP_ENDPOINTS_MAPPING.include?(hash["Port"]) && protocol == "TCP"
|
262
|
-
hash["Name"] = TCP_ENDPOINTS_MAPPING[hash["Port"]]
|
263
|
-
else
|
264
|
-
hash["Name"] = "#{protocol}Endpoint_chef_#{fields[0]}"
|
265
|
-
end
|
266
|
-
if fields[2]
|
267
|
-
hash["LoadBalancerProbe"] = {}
|
268
|
-
hash["LoadBalancerProbe"]["Path"] = fields[4]
|
269
|
-
hash["LoadBalancerProbe"]["Port"] = fields[0]
|
270
|
-
hash["LoadBalancerProbe"]["Protocol"] = fields[4] ? "HTTP" : protocol
|
271
|
-
end
|
272
|
-
hash
|
273
|
-
end
|
274
|
-
|
275
|
-
def find_deploy(params)
|
276
|
-
@connection.hosts.find(params[:azure_dns_name]).deploys[0] # TODO: this relies on the 'production only' bug.
|
277
|
-
end
|
278
|
-
|
279
|
-
def add_endpoints_to_xml(xml, endpoints, params)
|
280
|
-
existing_endpoints = find_deploy(params).input_endpoints
|
281
|
-
|
282
|
-
endpoints.each do |ep|
|
283
|
-
if existing_endpoints
|
284
|
-
existing_endpoints.each do |eep|
|
285
|
-
ep = eep if eep["LoadBalancedEndpointSetName"] && ep["LoadBalancedEndpointSetName"] && (eep["LoadBalancedEndpointSetName"] == ep["LoadBalancedEndpointSetName"])
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
if ep["Port"] == params[:port] && ep["Protocol"].casecmp("tcp").zero?
|
290
|
-
puts("Skipping tcp-endpoints: #{ep["LocalPort"]} because this port is already in use by ssh/winrm endpoint in current VM.")
|
291
|
-
next
|
292
|
-
end
|
293
|
-
|
294
|
-
xml.InputEndpoint do
|
295
|
-
xml.LoadBalancedEndpointSetName ep["LoadBalancedEndpointSetName"] if ep["LoadBalancedEndpointSetName"]
|
296
|
-
xml.LocalPort ep["LocalPort"]
|
297
|
-
xml.Name ep["Name"]
|
298
|
-
xml.Port ep["Port"]
|
299
|
-
if ep["LoadBalancerProbe"]
|
300
|
-
xml.LoadBalancerProbe do
|
301
|
-
xml.Path ep["LoadBalancerProbe"]["Path"] if ep["LoadBalancerProbe"]["Path"]
|
302
|
-
xml.Port ep["LoadBalancerProbe"]["Port"]
|
303
|
-
xml.Protocol ep["LoadBalancerProbe"]["Protocol"]
|
304
|
-
xml.IntervalInSeconds ep["LoadBalancerProbe"]["IntervalInSeconds"] if ep["LoadBalancerProbe"]["IntervalInSeconds"]
|
305
|
-
xml.TimeoutInSeconds ep["LoadBalancerProbe"]["TimeoutInSeconds"] if ep["LoadBalancerProbe"]["TimeoutInSeconds"]
|
306
|
-
end
|
307
|
-
end
|
308
|
-
xml.Protocol ep["Protocol"]
|
309
|
-
xml.EnableDirectServerReturn ep["EnableDirectServerReturn"] if ep["EnableDirectServerReturn"]
|
310
|
-
xml.LoadBalancerName ep["LoadBalancerName"] if ep["LoadBalancerName"]
|
311
|
-
xml.IdleTimeoutInMinutes ep["IdleTimeoutInMinutes"] if ep["IdleTimeoutInMinutes"]
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
def fetch_thumbprint
|
317
|
-
query_result = connection.query_azure("hostedservices/#{@hostedservicename}/deployments/#{@hostedservicename}/roles/#{@name}")
|
318
|
-
query_result.at_css("DefaultWinRmCertificateThumbprint").nil? ? "" : query_result.at_css("DefaultWinRmCertificateThumbprint").text
|
319
|
-
end
|
320
|
-
|
321
|
-
def setup(params)
|
322
|
-
azure_user_domain_name = params[:azure_user_domain_name] || params[:azure_domain_name]
|
323
|
-
builder = Nokogiri::XML::Builder.new do |xml|
|
324
|
-
xml.PersistentVMRole(
|
325
|
-
"xmlns" => "http://schemas.microsoft.com/windowsazure",
|
326
|
-
"xmlns:i" => "http://www.w3.org/2001/XMLSchema-instance"
|
327
|
-
) do
|
328
|
-
xml.RoleName { xml.text params[:azure_vm_name] }
|
329
|
-
xml.OsVersion("i:nil" => "true")
|
330
|
-
xml.RoleType "PersistentVMRole"
|
331
|
-
|
332
|
-
xml.ConfigurationSets do
|
333
|
-
if params[:os_type] == "Linux"
|
334
|
-
xml.ConfigurationSet("i:type" => "LinuxProvisioningConfigurationSet") do
|
335
|
-
xml.ConfigurationSetType "LinuxProvisioningConfiguration"
|
336
|
-
xml.HostName params[:azure_vm_name]
|
337
|
-
xml.UserName params[:connection_user]
|
338
|
-
if params[:ssh_identity_file].nil?
|
339
|
-
xml.UserPassword params[:connection_password]
|
340
|
-
xml.DisableSshPasswordAuthentication "false"
|
341
|
-
else
|
342
|
-
xml.DisableSshPasswordAuthentication "true"
|
343
|
-
xml.SSH do
|
344
|
-
xml.PublicKeys do
|
345
|
-
xml.PublicKey do
|
346
|
-
xml.Fingerprint params[:fingerprint].to_s.upcase
|
347
|
-
xml.Path "/home/" + params[:connection_user] + "/.ssh/authorized_keys"
|
348
|
-
end
|
349
|
-
end
|
350
|
-
end
|
351
|
-
end
|
352
|
-
end
|
353
|
-
elsif params[:os_type] == "Windows"
|
354
|
-
xml.ConfigurationSet("i:type" => "WindowsProvisioningConfigurationSet") do
|
355
|
-
xml.ConfigurationSetType "WindowsProvisioningConfiguration"
|
356
|
-
xml.ComputerName params[:azure_vm_name]
|
357
|
-
xml.AdminPassword params[:admin_password]
|
358
|
-
xml.ResetPasswordOnFirstLogon "false"
|
359
|
-
xml.EnableAutomaticUpdates "false"
|
360
|
-
if params[:azure_domain_name]
|
361
|
-
xml.DomainJoin do
|
362
|
-
xml.Credentials do
|
363
|
-
xml.Domain azure_user_domain_name
|
364
|
-
xml.Username params[:azure_domain_user]
|
365
|
-
xml.Password params[:azure_domain_passwd]
|
366
|
-
end
|
367
|
-
xml.JoinDomain params[:azure_domain_name]
|
368
|
-
xml.MachineObjectOU params[:azure_domain_ou_dn] if params[:azure_domain_ou_dn]
|
369
|
-
end
|
370
|
-
end
|
371
|
-
if params[:connection_protocol].casecmp("winrm").zero?
|
372
|
-
if params[:ssl_cert_fingerprint]
|
373
|
-
xml.StoredCertificateSettings do
|
374
|
-
xml.CertificateSetting do
|
375
|
-
xml.StoreLocation "LocalMachine"
|
376
|
-
xml.StoreName "My"
|
377
|
-
xml.Thumbprint params[:ssl_cert_fingerprint]
|
378
|
-
end
|
379
|
-
end
|
380
|
-
end
|
381
|
-
xml.WinRM do
|
382
|
-
xml.Listeners do
|
383
|
-
if params[:winrm_ssl] || params[:ssl_cert_fingerprint]
|
384
|
-
xml.Listener do
|
385
|
-
xml.CertificateThumbprint params[:ssl_cert_fingerprint] if params[:ssl_cert_fingerprint]
|
386
|
-
xml.Protocol "Https"
|
387
|
-
end
|
388
|
-
else
|
389
|
-
xml.Listener do
|
390
|
-
xml.Protocol "Http"
|
391
|
-
end
|
392
|
-
end
|
393
|
-
end
|
394
|
-
end
|
395
|
-
end
|
396
|
-
xml.AdminUsername params[:connection_user]
|
397
|
-
if params[:connection_protocol].casecmp("winrm").zero? && (params[:winrm_max_timeout] || params[:winrm_max_memory_per_shell])
|
398
|
-
xml.AdditionalUnattendContent do
|
399
|
-
xml.Passes do
|
400
|
-
xml.UnattendPass do
|
401
|
-
xml.PassName "oobeSystem"
|
402
|
-
xml.Components do
|
403
|
-
xml.UnattendComponent do
|
404
|
-
xml.ComponentName "Microsoft-Windows-Shell-Setup"
|
405
|
-
xml.ComponentSettings do
|
406
|
-
xml.ComponentSetting do
|
407
|
-
xml.SettingName "AutoLogon"
|
408
|
-
xml.Content Base64.encode64(
|
409
|
-
Nokogiri::XML::Builder.new do |auto_logon_xml|
|
410
|
-
auto_logon_xml.AutoLogon do
|
411
|
-
auto_logon_xml.Username params[:connection_user]
|
412
|
-
auto_logon_xml.Password do
|
413
|
-
auto_logon_xml.Value params[:admin_password]
|
414
|
-
auto_logon_xml.PlainText true
|
415
|
-
end
|
416
|
-
auto_logon_xml.LogonCount 1
|
417
|
-
auto_logon_xml.Enabled true
|
418
|
-
end
|
419
|
-
end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION)
|
420
|
-
).strip
|
421
|
-
end
|
422
|
-
xml.ComponentSetting do
|
423
|
-
xml.SettingName "FirstLogonCommands"
|
424
|
-
xml.Content Base64.encode64(
|
425
|
-
Nokogiri::XML::Builder.new do |first_logon_xml|
|
426
|
-
first_logon_xml.FirstLogonCommands do
|
427
|
-
if params[:winrm_max_timeout]
|
428
|
-
first_logon_xml.SynchronousCommand("wcm:action" => "add") do
|
429
|
-
first_logon_xml.Order 1
|
430
|
-
first_logon_xml.CommandLine "cmd.exe /c winrm set winrm/config @{MaxTimeoutms=\"#{params[:winrm_max_timeout]}\"}"
|
431
|
-
first_logon_xml.Description "Bump WinRM max timeout to #{params[:winrm_max_timeout]} milliseconds"
|
432
|
-
end
|
433
|
-
end
|
434
|
-
|
435
|
-
if params[:winrm_max_memory_per_shell]
|
436
|
-
first_logon_xml.SynchronousCommand("wcm:action" => "add") do
|
437
|
-
first_logon_xml.Order 2
|
438
|
-
first_logon_xml.CommandLine "cmd.exe /c winrm set winrm/config/winrs @{MaxMemoryPerShellMB=\"#{params[:winrm_max_memory_per_shell]}\"}"
|
439
|
-
first_logon_xml.Description "Bump WinRM max memory per shell to #{params[:winrm_max_memory_per_shell]} MB"
|
440
|
-
end
|
441
|
-
end
|
442
|
-
end
|
443
|
-
end.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION)
|
444
|
-
).strip
|
445
|
-
end
|
446
|
-
end
|
447
|
-
end
|
448
|
-
end
|
449
|
-
end
|
450
|
-
end
|
451
|
-
end
|
452
|
-
end
|
453
|
-
end
|
454
|
-
end
|
455
|
-
|
456
|
-
xml.ConfigurationSet("i:type" => "NetworkConfigurationSet") do
|
457
|
-
xml.ConfigurationSetType "NetworkConfiguration"
|
458
|
-
xml.InputEndpoints do
|
459
|
-
# 1. connection_protocol = 'winrm' for windows => Set winrm port
|
460
|
-
# 2. connection_protocol = 'ssh' for windows and linux => Set ssh port
|
461
|
-
# 3. connection_protocol = 'cloud-api' for windows and linux => Set no port
|
462
|
-
if (params[:os_type] == "Windows") && params[:connection_protocol].casecmp("winrm").zero?
|
463
|
-
xml.InputEndpoint do
|
464
|
-
if params[:winrm_ssl]
|
465
|
-
xml.LocalPort "5986"
|
466
|
-
else
|
467
|
-
xml.LocalPort "5985"
|
468
|
-
end
|
469
|
-
xml.Name "WinRM"
|
470
|
-
xml.Port params[:port]
|
471
|
-
xml.Protocol "TCP"
|
472
|
-
end
|
473
|
-
elsif params[:connection_protocol].casecmp("ssh").zero?
|
474
|
-
xml.InputEndpoint do
|
475
|
-
xml.LocalPort "22"
|
476
|
-
xml.Name "SSH"
|
477
|
-
xml.Port params[:port]
|
478
|
-
xml.Protocol "TCP"
|
479
|
-
end
|
480
|
-
end
|
481
|
-
all_endpoints = []
|
482
|
-
|
483
|
-
if params[:tcp_endpoints]
|
484
|
-
params[:tcp_endpoints].split(",").map(&:strip).each do |endpoint|
|
485
|
-
all_endpoints << parse_endpoint_from_params("TCP", params[:azure_vm_name], endpoint)
|
486
|
-
end
|
487
|
-
end
|
488
|
-
if params[:udp_endpoints]
|
489
|
-
params[:udp_endpoints].split(",").map(&:strip).each do |endpoint|
|
490
|
-
all_endpoints << parse_endpoint_from_params("UDP", params[:azure_vm_name], endpoint)
|
491
|
-
end
|
492
|
-
end
|
493
|
-
add_endpoints_to_xml(xml, all_endpoints, params) if all_endpoints.any?
|
494
|
-
end
|
495
|
-
if params[:azure_subnet_name]
|
496
|
-
xml.SubnetNames do
|
497
|
-
xml.SubnetName params[:azure_subnet_name]
|
498
|
-
end
|
499
|
-
end
|
500
|
-
end
|
501
|
-
end
|
502
|
-
|
503
|
-
# Azure resource extension support
|
504
|
-
if params[:connection_protocol] == "cloud-api"
|
505
|
-
xml.ResourceExtensionReferences do
|
506
|
-
xml.ResourceExtensionReference do
|
507
|
-
xml.ReferenceName params[:chef_extension]
|
508
|
-
xml.Publisher params[:chef_extension_publisher]
|
509
|
-
xml.Name params[:chef_extension]
|
510
|
-
xml.Version params[:chef_extension_version]
|
511
|
-
xml.ResourceExtensionParameterValues do
|
512
|
-
if params[:chef_extension_public_param]
|
513
|
-
xml.ResourceExtensionParameterValue do
|
514
|
-
xml.Key "PublicParams"
|
515
|
-
xml.Value Base64.encode64(params[:chef_extension_public_param].to_json)
|
516
|
-
xml.Type "Public"
|
517
|
-
end
|
518
|
-
end
|
519
|
-
if params[:chef_extension_private_param]
|
520
|
-
xml.ResourceExtensionParameterValue do
|
521
|
-
xml.Key "PrivateParams"
|
522
|
-
xml.Value Base64.encode64(params[:chef_extension_private_param].to_json)
|
523
|
-
xml.Type "Private"
|
524
|
-
end
|
525
|
-
end
|
526
|
-
end
|
527
|
-
xml.State "Enable"
|
528
|
-
end
|
529
|
-
end
|
530
|
-
end
|
531
|
-
|
532
|
-
if params[:azure_availability_set]
|
533
|
-
xml.AvailabilitySetName params[:azure_availability_set]
|
534
|
-
end
|
535
|
-
|
536
|
-
xml.VMImageName params[:azure_source_image] if params[:is_vm_image]
|
537
|
-
|
538
|
-
xml.Label Base64.encode64(params[:azure_vm_name]).strip
|
539
|
-
|
540
|
-
# OSVirtualHardDisk not required in case azure_source_image is a VMImage
|
541
|
-
unless params[:is_vm_image]
|
542
|
-
xml.OSVirtualHardDisk do
|
543
|
-
disk_name = params[:azure_os_disk_name] || "disk_" + SecureRandom.uuid
|
544
|
-
xml.DiskName disk_name
|
545
|
-
domain_suffix = params[:azure_api_host_name] ? params[:azure_api_host_name].scan(/core.*/)[0] : ""
|
546
|
-
xml.MediaLink "http://" + params[:azure_storage_account] + ".blob." + domain_suffix + "/vhds/" + disk_name + ".vhd"
|
547
|
-
xml.SourceImageName params[:azure_source_image]
|
548
|
-
end
|
549
|
-
end
|
550
|
-
|
551
|
-
xml.RoleSize params[:azure_vm_size]
|
552
|
-
xml.ProvisionGuestAgent true if params[:connection_protocol] == "cloud-api"
|
553
|
-
end
|
554
|
-
end
|
555
|
-
builder.doc
|
556
|
-
end
|
557
|
-
|
558
|
-
def create(params, roleXML)
|
559
|
-
servicecall = "hostedservices/#{params[:azure_dns_name]}/deployments" \
|
560
|
-
"/#{params["deploy_name"]}/roles"
|
561
|
-
@connection.query_azure(servicecall, "post", roleXML.to_xml)
|
562
|
-
end
|
563
|
-
|
564
|
-
def setup_extension(params)
|
565
|
-
## add Chef Extension config in role_xml retrieved from the server
|
566
|
-
puts "Adding Chef Extension config in server role..."
|
567
|
-
role_xml = update_role_xml_for_extension(params[:role_xml], params)
|
568
|
-
|
569
|
-
## role_xml can't be used for update as it has additional tags like
|
570
|
-
## role_name, osversion etc. which update API does not support, also the
|
571
|
-
## xml is the child of parent node 'Deployment' in XML, so instead of
|
572
|
-
## modifying the role_xml to fit for our requirements, we create
|
573
|
-
## new XML (with Chef Extension config and other pre-existing VM config)
|
574
|
-
## using the required values of the updated role_xml
|
575
|
-
builder = Nokogiri::XML::Builder.new do |xml|
|
576
|
-
xml.PersistentVMRole(
|
577
|
-
"xmlns" => "http://schemas.microsoft.com/windowsazure",
|
578
|
-
"xmlns:i" => "http://www.w3.org/2001/XMLSchema-instance"
|
579
|
-
) do
|
580
|
-
xml.ConfigurationSets role_xml.at_css("ConfigurationSets").children unless role_xml.at_css("ConfigurationSets").nil?
|
581
|
-
xml.ResourceExtensionReferences role_xml.at_css("ResourceExtensionReferences").children unless role_xml.at_css("ResourceExtensionReferences").nil?
|
582
|
-
xml.AvailabilitySetName role_xml.at_css("AvailabilitySetName").children unless role_xml.at_css("AvailabilitySetName").nil?
|
583
|
-
xml.DataVirtualHardDisks role_xml.at_css("DataVirtualHardDisks").children unless role_xml.at_css("DataVirtualHardDisks").nil?
|
584
|
-
xml.OSVirtualHardDisk role_xml.at_css("OSVirtualHardDisk").children unless role_xml.at_css("OSVirtualHardDisk").nil?
|
585
|
-
xml.RoleSize role_xml.at_css("RoleSize").children unless role_xml.at_css("RoleSize").nil?
|
586
|
-
xml.ProvisionGuestAgent role_xml.at_css("ProvisionGuestAgent").children unless role_xml.at_css("ProvisionGuestAgent").nil?
|
587
|
-
end
|
588
|
-
end
|
589
|
-
|
590
|
-
builder.doc.to_xml.gsub("<\;", "<").gsub(">\;", ">")
|
591
|
-
end
|
592
|
-
|
593
|
-
def update_role_xml_for_extension(roleXML, params)
|
594
|
-
## check if 'ResourceExtensionReferences' node already exist in the XML,
|
595
|
-
## if no add it, else retrieve the object of the existing node
|
596
|
-
add_resource_extension_references = roleXML.at_css("ResourceExtensionReferences").nil?
|
597
|
-
|
598
|
-
if add_resource_extension_references
|
599
|
-
resource_extension_references = Nokogiri::XML::Node.new("ResourceExtensionReferences", roleXML)
|
600
|
-
else
|
601
|
-
resource_extension_references = roleXML.css("ResourceExtensionReferences")
|
602
|
-
end
|
603
|
-
|
604
|
-
## check if Azure Chef Extension is already installed on the given server,
|
605
|
-
## if no than install it, else raise error saying that the extension is
|
606
|
-
## already installed
|
607
|
-
ext = nil
|
608
|
-
unless add_resource_extension_references
|
609
|
-
unless resource_extension_references.at_css("ReferenceName").nil?
|
610
|
-
resource_extension_references.css("ReferenceName").each { |node| ext = node if node.content == params[:chef_extension] }
|
611
|
-
end
|
612
|
-
end
|
613
|
-
|
614
|
-
add_resource_extension_reference = ext.nil?
|
615
|
-
|
616
|
-
## create Azure Chef Extension config and add it in the role_xml
|
617
|
-
if add_resource_extension_reference
|
618
|
-
resource_extension_reference = Nokogiri::XML::Node.new("ResourceExtensionReference", roleXML)
|
619
|
-
|
620
|
-
reference_name = Nokogiri::XML::Node.new("ReferenceName", roleXML)
|
621
|
-
reference_name.content = params[:chef_extension]
|
622
|
-
resource_extension_reference.add_child(reference_name)
|
623
|
-
|
624
|
-
publisher = Nokogiri::XML::Node.new("Publisher", roleXML)
|
625
|
-
publisher.content = params[:chef_extension_publisher]
|
626
|
-
resource_extension_reference.add_child(publisher)
|
627
|
-
|
628
|
-
name = Nokogiri::XML::Node.new("Name", roleXML)
|
629
|
-
name.content = params[:chef_extension]
|
630
|
-
resource_extension_reference.add_child(name)
|
631
|
-
|
632
|
-
version = Nokogiri::XML::Node.new("Version", roleXML)
|
633
|
-
version.content = params[:chef_extension_version]
|
634
|
-
resource_extension_reference.add_child(version)
|
635
|
-
|
636
|
-
resource_extension_parameter_values = Nokogiri::XML::Node.new("ResourceExtensionParameterValues", roleXML)
|
637
|
-
if params[:chef_extension_public_param]
|
638
|
-
resource_extension_parameter_value = Nokogiri::XML::Node.new("ResourceExtensionParameterValue", roleXML)
|
639
|
-
|
640
|
-
key = Nokogiri::XML::Node.new("Key", roleXML)
|
641
|
-
key.content = "PublicParams"
|
642
|
-
resource_extension_parameter_value.add_child(key)
|
643
|
-
|
644
|
-
value = Nokogiri::XML::Node.new("Value", roleXML)
|
645
|
-
value.content = Base64.encode64(params[:chef_extension_public_param].to_json)
|
646
|
-
resource_extension_parameter_value.add_child(value)
|
647
|
-
|
648
|
-
type = Nokogiri::XML::Node.new("Type", roleXML)
|
649
|
-
type.content = "Public"
|
650
|
-
resource_extension_parameter_value.add_child(type)
|
651
|
-
|
652
|
-
resource_extension_parameter_values.add_child(resource_extension_parameter_value)
|
653
|
-
end
|
654
|
-
|
655
|
-
if params[:chef_extension_private_param]
|
656
|
-
resource_extension_parameter_value = Nokogiri::XML::Node.new("ResourceExtensionParameterValue", roleXML)
|
657
|
-
|
658
|
-
key = Nokogiri::XML::Node.new("Key", roleXML)
|
659
|
-
key.content = "PrivateParams"
|
660
|
-
resource_extension_parameter_value.add_child(key)
|
661
|
-
|
662
|
-
value = Nokogiri::XML::Node.new("Value", roleXML)
|
663
|
-
value.content = Base64.encode64(params[:chef_extension_private_param].to_json)
|
664
|
-
resource_extension_parameter_value.add_child(value)
|
665
|
-
|
666
|
-
type = Nokogiri::XML::Node.new("Type", roleXML)
|
667
|
-
type.content = "Private"
|
668
|
-
resource_extension_parameter_value.add_child(type)
|
669
|
-
|
670
|
-
resource_extension_parameter_values.add_child(resource_extension_parameter_value)
|
671
|
-
end
|
672
|
-
|
673
|
-
resource_extension_reference.add_child(resource_extension_parameter_values)
|
674
|
-
|
675
|
-
state = Nokogiri::XML::Node.new("State", roleXML)
|
676
|
-
state.content = "enable"
|
677
|
-
resource_extension_reference.add_child(state)
|
678
|
-
|
679
|
-
if add_resource_extension_references
|
680
|
-
resource_extension_references.add_child(resource_extension_reference)
|
681
|
-
else
|
682
|
-
resource_extension_references.last.add_child(resource_extension_reference)
|
683
|
-
end
|
684
|
-
|
685
|
-
roleXML.add_child(resource_extension_references) if add_resource_extension_references
|
686
|
-
|
687
|
-
add_provision_guest_agent = roleXML.at_css("ProvisionGuestAgent").nil?
|
688
|
-
|
689
|
-
if add_provision_guest_agent
|
690
|
-
provision_guest_agent = Nokogiri::XML::Node.new("ProvisionGuestAgent", roleXML)
|
691
|
-
provision_guest_agent.content = true
|
692
|
-
else
|
693
|
-
provision_guest_agent = roleXML.css("ProvisionGuestAgent")
|
694
|
-
provision_guest_agent.first.content = true
|
695
|
-
end
|
696
|
-
|
697
|
-
roleXML.add_child(provision_guest_agent) if add_provision_guest_agent
|
698
|
-
else ## raise error as Chef Extension is already installed on the server
|
699
|
-
raise "Chef Extension is already installed on the server #{params[:azure_vm_name]}."
|
700
|
-
end
|
701
|
-
|
702
|
-
roleXML
|
703
|
-
end
|
704
|
-
|
705
|
-
def update(name, params, roleXML)
|
706
|
-
puts "Updating server role..."
|
707
|
-
servicecall = "hostedservices/#{params[:azure_dns_name]}" \
|
708
|
-
"/deployments/#{params[:deploy_name]}/roles/#{name}"
|
709
|
-
ret_val = @connection.query_azure(servicecall, "put", roleXML, "", true, true, "application/xml")
|
710
|
-
error_code, error_message = error_from_response_xml(ret_val)
|
711
|
-
unless error_code.empty?
|
712
|
-
Chef::Log.debug(ret_val.to_s)
|
713
|
-
raise "Unable to update role:" + error_code + " : " + error_message
|
714
|
-
end
|
715
|
-
end
|
716
|
-
end
|
717
|
-
end
|