knife-azure 3.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +8 -12
- data/lib/azure/resource_management/windows_credentials.rb +7 -8
- data/lib/chef/knife/azurerm_server_create.rb +2 -2
- data/lib/chef/knife/azurerm_server_delete.rb +1 -1
- data/lib/chef/knife/bootstrap/bootstrapper.rb +10 -11
- data/lib/chef/knife/bootstrap_azurerm.rb +1 -1
- data/lib/chef/knife/helpers/azurerm_base.rb +17 -19
- 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 -125
- 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 -394
@@ -1,94 +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
|
-
module Azure
|
20
|
-
class Images
|
21
|
-
def initialize(connection)
|
22
|
-
@connection = connection
|
23
|
-
end
|
24
|
-
|
25
|
-
def load
|
26
|
-
@images ||= begin
|
27
|
-
osimages = get_images("OSImage") # get OSImages
|
28
|
-
vmimages = get_images("VMImage") # get VMImages
|
29
|
-
|
30
|
-
all_images = osimages.merge(vmimages)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def all
|
35
|
-
load.values
|
36
|
-
end
|
37
|
-
|
38
|
-
# img_type = OSImages or VMImage
|
39
|
-
def get_images(img_type)
|
40
|
-
images = {}
|
41
|
-
|
42
|
-
if img_type == "OSImage"
|
43
|
-
response = @connection.query_azure("images")
|
44
|
-
elsif img_type == "VMImage"
|
45
|
-
response = @connection.query_azure("vmimages")
|
46
|
-
end
|
47
|
-
|
48
|
-
unless response.to_s.empty?
|
49
|
-
osimages = response.css(img_type)
|
50
|
-
|
51
|
-
osimages.each do |image|
|
52
|
-
item = Image.new(image)
|
53
|
-
images[item.name] = item
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
images
|
58
|
-
end
|
59
|
-
|
60
|
-
def is_os_image(image_name)
|
61
|
-
os_images = get_images("OSImage").values
|
62
|
-
os_images.detect { |img| img.name == image_name } ? true : false
|
63
|
-
end
|
64
|
-
|
65
|
-
def is_vm_image(image_name)
|
66
|
-
vm_images = get_images("VMImage").values
|
67
|
-
vm_images.detect { |img| img.name == image_name } ? true : false
|
68
|
-
end
|
69
|
-
|
70
|
-
def exists?(name)
|
71
|
-
all.detect { |img| img.name == name } ? true : false
|
72
|
-
end
|
73
|
-
|
74
|
-
def find(name)
|
75
|
-
load[name]
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
module Azure
|
81
|
-
class Image
|
82
|
-
attr_accessor :category, :label
|
83
|
-
attr_accessor :name, :os, :eula, :description, :location
|
84
|
-
def initialize(image)
|
85
|
-
@category = image.at_css("Category").content
|
86
|
-
@label = image.at_css("Label").content
|
87
|
-
@name = image.at_css("Name").content
|
88
|
-
@os = image.at_css("OS").content
|
89
|
-
@location = image.at_css("Location").content.gsub(";", ", ") if image.at_css("Location")
|
90
|
-
@eula = image.at_css("Eula").content if image.at_css("Eula")
|
91
|
-
@description = image.at_css("Description").content if image.at_css("Description")
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
@@ -1,78 +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
|
-
module Azure
|
20
|
-
class Loadbalancer
|
21
|
-
include AzureUtility
|
22
|
-
attr_accessor :name, :service, :subnet, :vip
|
23
|
-
|
24
|
-
def initialize(connection)
|
25
|
-
@connection = connection
|
26
|
-
end
|
27
|
-
|
28
|
-
def load
|
29
|
-
@lbs ||= begin
|
30
|
-
@lbs = {}
|
31
|
-
@connection.deploys.all.each do |deploy|
|
32
|
-
@lbs.merge!(deploy.loadbalancers)
|
33
|
-
end
|
34
|
-
@lbs
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def all
|
39
|
-
load.values
|
40
|
-
end
|
41
|
-
|
42
|
-
def exists?(name)
|
43
|
-
load.key?(name)
|
44
|
-
end
|
45
|
-
|
46
|
-
def find(name)
|
47
|
-
load[name]
|
48
|
-
end
|
49
|
-
|
50
|
-
def parse(lbXML, hostedservicename)
|
51
|
-
@name = xml_content(lbXML, "Name")
|
52
|
-
ip_configXML = lbXML.css("FrontendIpConfiguration")
|
53
|
-
@subnet = xml_content(ip_configXML, "SubnetName")
|
54
|
-
@vip = xml_content(ip_configXML, "StaticVirtualNetworkIPAddress")
|
55
|
-
@service = hostedservicename
|
56
|
-
self
|
57
|
-
end
|
58
|
-
|
59
|
-
def create(params)
|
60
|
-
if params[:azure_lb_static_vip] && !params[:azure_subnet_name]
|
61
|
-
Chef::Log.fatal "Unable to create Loadbalancer, :azure_subnet_name needs to be set if :azure_lb_static_vip is set"
|
62
|
-
end
|
63
|
-
builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
|
64
|
-
xml.LoadBalancer(xmlns: "http://schemas.microsoft.com/windowsazure") do
|
65
|
-
xml.Name params[:azure_load_balancer]
|
66
|
-
xml.FrontendIpConfiguration do
|
67
|
-
xml.Type "Private"
|
68
|
-
xml.SubnetName params[:azure_subnet_name] if params[:azure_subnet_name]
|
69
|
-
xml.StaticVirtualNetworkIPAddress params[:azure_lb_static_vip] if params[:azure_lb_static_vip]
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
deploy_name = @connection.deploys.get_deploy_name_for_hostedservice(params[:azure_dns_name])
|
74
|
-
servicecall = "hostedservices/#{params[:azure_dns_name]}/deployments/#{deploy_name}/loadbalancers"
|
75
|
-
@connection.query_azure(servicecall, "post", builder.doc.to_xml)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,125 +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 "net/https"
|
20
|
-
require "uri"
|
21
|
-
require "nokogiri"
|
22
|
-
|
23
|
-
module AzureAPI
|
24
|
-
|
25
|
-
class Rest
|
26
|
-
def initialize(params)
|
27
|
-
@subscription_id = params[:azure_subscription_id]
|
28
|
-
@pem_file = params[:azure_mgmt_cert]
|
29
|
-
@host_name = params[:azure_api_host_name]
|
30
|
-
@verify_ssl = params[:verify_ssl_cert]
|
31
|
-
end
|
32
|
-
|
33
|
-
def query_azure(service_name,
|
34
|
-
verb = "get",
|
35
|
-
body = "",
|
36
|
-
params = "",
|
37
|
-
services = true,
|
38
|
-
content_type = nil)
|
39
|
-
svc_str = services ? "/services" : ""
|
40
|
-
uri = URI.parse("#{@host_name}/#{@subscription_id}#{svc_str}/#{service_name}")
|
41
|
-
scheme = !uri.scheme ? "https://" : ""
|
42
|
-
request_url = "#{scheme}#{@host_name}/#{@subscription_id}#{svc_str}/#{service_name}"
|
43
|
-
print "."
|
44
|
-
response = http_query(request_url, verb, body, params, content_type)
|
45
|
-
if response.code.to_i == 307
|
46
|
-
Chef::Log.debug "Redirect to #{response["Location"]}"
|
47
|
-
response = http_query(response["Location"], verb, body, params, content_type)
|
48
|
-
end
|
49
|
-
@last_request_id = response["x-ms-request-id"]
|
50
|
-
response
|
51
|
-
end
|
52
|
-
|
53
|
-
def http_query(request_url, verb, body, params, content_type = nil)
|
54
|
-
uri = URI.parse(request_url)
|
55
|
-
uri.query = params
|
56
|
-
http = http_setup(uri)
|
57
|
-
request = request_setup(uri, verb, body, content_type)
|
58
|
-
response = http.request(request)
|
59
|
-
@last_request_id = response["x-ms-request-id"]
|
60
|
-
response
|
61
|
-
end
|
62
|
-
|
63
|
-
def query_for_completion
|
64
|
-
uri = URI.parse("#{@host_name}/#{@subscription_id}/operations/#{@last_request_id}")
|
65
|
-
scheme = !uri.scheme ? "https://" : ""
|
66
|
-
request_url = "#{scheme}#{@host_name}/#{@subscription_id}/operations/#{@last_request_id}"
|
67
|
-
response = http_query(request_url, "get", "", "")
|
68
|
-
if response.code.to_i == 307
|
69
|
-
Chef::Log.debug "Redirect to #{response["Location"]}"
|
70
|
-
response = http_query(response["Location"], "get", "", "")
|
71
|
-
end
|
72
|
-
response
|
73
|
-
end
|
74
|
-
|
75
|
-
def http_setup(uri)
|
76
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
77
|
-
store = OpenSSL::X509::Store.new
|
78
|
-
store.set_default_paths
|
79
|
-
http.cert_store = store
|
80
|
-
if @verify_ssl
|
81
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
82
|
-
else
|
83
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
84
|
-
end
|
85
|
-
http.use_ssl = true
|
86
|
-
begin
|
87
|
-
http.cert = OpenSSL::X509::Certificate.new(@pem_file)
|
88
|
-
rescue OpenSSL::X509::CertificateError => err
|
89
|
-
raise "Invalid Azure Certificate pem file. Error: #{err}"
|
90
|
-
end
|
91
|
-
http.key = OpenSSL::PKey::RSA.new(@pem_file)
|
92
|
-
http
|
93
|
-
end
|
94
|
-
|
95
|
-
def request_setup(uri, verb, body, content_type)
|
96
|
-
if verb == "get"
|
97
|
-
request = Net::HTTP::Get.new(uri.request_uri)
|
98
|
-
elsif verb == "post"
|
99
|
-
request = Net::HTTP::Post.new(uri.request_uri)
|
100
|
-
elsif verb == "delete"
|
101
|
-
request = Net::HTTP::Delete.new(uri.request_uri)
|
102
|
-
elsif verb == "put"
|
103
|
-
request = Net::HTTP::Put.new(uri.request_uri)
|
104
|
-
end
|
105
|
-
text = verb == "put" && content_type.nil?
|
106
|
-
request["x-ms-version"] = "2014-05-01"
|
107
|
-
request["content-type"] = text ? "text/plain" : "application/xml"
|
108
|
-
request["accept"] = "application/xml"
|
109
|
-
request["accept-charset"] = "utf-8"
|
110
|
-
request.body = body
|
111
|
-
request
|
112
|
-
end
|
113
|
-
|
114
|
-
def showResponse(response)
|
115
|
-
puts "=== response body ==="
|
116
|
-
puts response.body
|
117
|
-
puts "=== response.code ==="
|
118
|
-
puts response.code
|
119
|
-
puts "=== response.inspect ==="
|
120
|
-
puts response.inspect
|
121
|
-
puts "=== all of the headers ==="
|
122
|
-
puts response.each_header { |h, j| puts h.inspect + " : " + j.inspect }
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
@@ -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"
|
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
|