knife-azure 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +275 -0
- data/lib/azure/certificate.rb +87 -0
- data/lib/azure/connection.rb +3 -1
- data/lib/azure/deploy.rb +72 -28
- data/lib/azure/host.rb +97 -18
- data/lib/azure/image.rb +21 -15
- data/lib/azure/rest.rb +9 -18
- data/lib/azure/role.rb +165 -48
- data/lib/azure/storageaccount.rb +39 -18
- data/lib/chef/knife/azure_base.rb +69 -9
- data/lib/chef/knife/azure_image_list.rb +14 -13
- data/lib/chef/knife/azure_server_create.rb +271 -108
- data/lib/chef/knife/azure_server_delete.rb +55 -13
- data/lib/chef/knife/azure_server_list.rb +9 -16
- data/lib/knife-azure/version.rb +1 -1
- metadata +119 -207
- data/README.rdoc +0 -252
data/lib/azure/host.rb
CHANGED
@@ -21,30 +21,69 @@ class Azure
|
|
21
21
|
def initialize(connection)
|
22
22
|
@connection=connection
|
23
23
|
end
|
24
|
+
|
25
|
+
# force_load should be true when there is something in local cache and we want to reload
|
26
|
+
# first call is always load.
|
27
|
+
def load(force_load = false)
|
28
|
+
if not @hosted_services || force_load
|
29
|
+
@hosted_services = begin
|
30
|
+
hosted_services = Hash.new
|
31
|
+
responseXML = @connection.query_azure('hostedservices')
|
32
|
+
servicesXML = responseXML.css('HostedServices HostedService')
|
33
|
+
servicesXML.each do |serviceXML|
|
34
|
+
host = Host.new(@connection).parse(serviceXML)
|
35
|
+
hosted_services[host.name] = host
|
36
|
+
end
|
37
|
+
hosted_services
|
38
|
+
end
|
39
|
+
end
|
40
|
+
@hosted_services
|
41
|
+
end
|
42
|
+
|
24
43
|
def all
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
44
|
+
self.load.values
|
45
|
+
end
|
46
|
+
|
47
|
+
# first look up local cache if we have already loaded list.
|
48
|
+
def exists?(name)
|
49
|
+
return @hosted_services.key?(name) if @hosted_services
|
50
|
+
self.exists_on_cloud?(name)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Look up on cloud and not local cache
|
54
|
+
def exists_on_cloud?(name)
|
55
|
+
ret_val = @connection.query_azure("hostedservices/#{name}")
|
56
|
+
if ret_val.nil? || ret_val.css('Error Code').length > 0
|
57
|
+
Chef::Log.warn 'Unable to find hosted(cloud) service:' + ret_val.at_css('Error Code').content + ' : ' + ret_val.at_css('Error Message').content if ret_val
|
58
|
+
false
|
59
|
+
else
|
60
|
+
true
|
31
61
|
end
|
32
|
-
hosted_services
|
33
62
|
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
63
|
+
|
64
|
+
# first look up local cache if we have already loaded list.
|
65
|
+
def find(name)
|
66
|
+
return @hosted_services[name] if @hosted_services && @hosted_services.key?(name)
|
67
|
+
self.fetch_from_cloud(name)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Look up hosted service on cloud and not local cache
|
71
|
+
def fetch_from_cloud(name)
|
72
|
+
ret_val = @connection.query_azure("hostedservices/#{name}")
|
73
|
+
if ret_val.nil? || ret_val.css('Error Code').length > 0
|
74
|
+
Chef::Log.warn 'Unable to find hosted(cloud) service:' + ret_val.at_css('Error Code').content + ' : ' + ret_val.at_css('Error Message').content if ret_val
|
75
|
+
nil
|
76
|
+
else
|
77
|
+
Host.new(@connection).parse(ret_val)
|
39
78
|
end
|
40
|
-
hostExists
|
41
79
|
end
|
80
|
+
|
42
81
|
def create(params)
|
43
82
|
host = Host.new(@connection)
|
44
83
|
host.create(params)
|
45
84
|
end
|
46
85
|
def delete(name)
|
47
|
-
if self.exists
|
86
|
+
if self.exists?(name)
|
48
87
|
servicecall = "hostedservices/" + name
|
49
88
|
@connection.query_azure(servicecall, "delete")
|
50
89
|
end
|
@@ -58,8 +97,11 @@ class Azure
|
|
58
97
|
attr_accessor :connection, :name, :url, :label
|
59
98
|
attr_accessor :dateCreated, :description, :location
|
60
99
|
attr_accessor :dateModified, :status
|
100
|
+
|
61
101
|
def initialize(connection)
|
62
102
|
@connection = connection
|
103
|
+
@deploys_loaded = false
|
104
|
+
@deploys = Hash.new
|
63
105
|
end
|
64
106
|
def parse(serviceXML)
|
65
107
|
@name = xml_content(serviceXML, 'ServiceName')
|
@@ -75,10 +117,10 @@ class Azure
|
|
75
117
|
def create(params)
|
76
118
|
builder = Nokogiri::XML::Builder.new do |xml|
|
77
119
|
xml.CreateHostedService('xmlns'=>'http://schemas.microsoft.com/windowsazure') {
|
78
|
-
xml.ServiceName params[:
|
79
|
-
xml.Label Base64.encode64(params[:
|
80
|
-
xml.Description
|
81
|
-
xml.Location params[:
|
120
|
+
xml.ServiceName params[:azure_dns_name]
|
121
|
+
xml.Label Base64.encode64(params[:azure_dns_name])
|
122
|
+
xml.Description 'Explicitly created hosted service'
|
123
|
+
xml.Location params[:azure_service_location] || 'West US'
|
82
124
|
}
|
83
125
|
end
|
84
126
|
@connection.query_azure("hostedservices", "post", builder.to_xml)
|
@@ -86,5 +128,42 @@ class Azure
|
|
86
128
|
def details
|
87
129
|
response = @connection.query_azure('hostedservices/' + @name + '?embed-detail=true')
|
88
130
|
end
|
131
|
+
|
132
|
+
# Deployments within this hostedservice
|
133
|
+
def add_deploy(deploy)
|
134
|
+
@deploys[deploy.name] = deploy
|
135
|
+
end
|
136
|
+
|
137
|
+
def delete_role(role)
|
138
|
+
deploys.each { |d| d.delete_role_if_present(role) }
|
139
|
+
end
|
140
|
+
|
141
|
+
def deploys
|
142
|
+
# check if we have deploys loaded, else load.
|
143
|
+
if (@deploys.length == 0) && !@deploys_loaded
|
144
|
+
deploy = Deploy.new(@connection)
|
145
|
+
deploy.retrieve(@name)
|
146
|
+
@deploys[deploy.name] = deploy
|
147
|
+
@deploys_loaded = true
|
148
|
+
end
|
149
|
+
@deploys.values
|
150
|
+
end
|
151
|
+
|
152
|
+
def roles
|
153
|
+
roles = []
|
154
|
+
deploys.each do |deploy|
|
155
|
+
roles.concat(deploy.roles) if deploy.roles
|
156
|
+
end
|
157
|
+
roles
|
158
|
+
end
|
159
|
+
|
160
|
+
def find_role(role_name, deploy_name = nil)
|
161
|
+
return @deploys[deploy_name].find_role(role_name) if deploy_name && deploys
|
162
|
+
# else lookup all deploys within hostedservice
|
163
|
+
deploys.each do |deploy|
|
164
|
+
role = deploy.find_role(role_name)
|
165
|
+
return role if role
|
166
|
+
end
|
167
|
+
end
|
89
168
|
end
|
90
169
|
end
|
data/lib/azure/image.rb
CHANGED
@@ -21,23 +21,29 @@ class Azure
|
|
21
21
|
def initialize(connection)
|
22
22
|
@connection=connection
|
23
23
|
end
|
24
|
-
def
|
25
|
-
images
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
def load
|
25
|
+
@images ||= begin
|
26
|
+
images = Hash.new
|
27
|
+
response = @connection.query_azure('images')
|
28
|
+
osimages = response.css('OSImage')
|
29
|
+
osimages.each do |image|
|
30
|
+
item = Image.new(image)
|
31
|
+
images[item.name] = item
|
32
|
+
end
|
33
|
+
images
|
31
34
|
end
|
32
|
-
images
|
33
35
|
end
|
34
|
-
|
35
|
-
|
36
|
-
self.
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
|
37
|
+
def all
|
38
|
+
self.load.values
|
39
|
+
end
|
40
|
+
|
41
|
+
def exists?(name)
|
42
|
+
self.all.key?(name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def find(name)
|
46
|
+
self.load[name]
|
41
47
|
end
|
42
48
|
end
|
43
49
|
end
|
data/lib/azure/rest.rb
CHANGED
@@ -24,23 +24,10 @@ module AzureAPI
|
|
24
24
|
class Rest
|
25
25
|
def initialize(params)
|
26
26
|
@subscription_id = params[:azure_subscription_id]
|
27
|
-
@pem_file =
|
28
|
-
@host_name = params[:
|
27
|
+
@pem_file = params[:azure_mgmt_cert]
|
28
|
+
@host_name = params[:azure_api_host_name]
|
29
29
|
@verify_ssl = params[:verify_ssl_cert]
|
30
30
|
end
|
31
|
-
def find_pem(name)
|
32
|
-
config_dir = Chef::Knife.chef_config_dir
|
33
|
-
if File.exist? name
|
34
|
-
pem_file = name
|
35
|
-
elsif config_dir && File.exist?(File.join(config_dir, name))
|
36
|
-
pem_file = File.join(config_dir, name)
|
37
|
-
elsif File.exist?(File.join(ENV['HOME'], '.chef', name))
|
38
|
-
pem_file = File.join(ENV['HOME'], '.chef', name)
|
39
|
-
else
|
40
|
-
raise 'Unable to find certificate pem file - ' + name
|
41
|
-
end
|
42
|
-
pem_file
|
43
|
-
end
|
44
31
|
def query_azure(service_name, verb = 'get', body = '')
|
45
32
|
request_url = "https://#{@host_name}/#{@subscription_id}/services/#{service_name}"
|
46
33
|
print '.'
|
@@ -69,8 +56,12 @@ module AzureAPI
|
|
69
56
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
70
57
|
end
|
71
58
|
http.use_ssl = true
|
72
|
-
|
73
|
-
|
59
|
+
begin
|
60
|
+
http.cert = OpenSSL::X509::Certificate.new(@pem_file)
|
61
|
+
rescue OpenSSL::X509::CertificateError => err
|
62
|
+
raise "Invalid Azure Certificate pem file. Error: #{err}"
|
63
|
+
end
|
64
|
+
http.key = OpenSSL::PKey::RSA.new(@pem_file)
|
74
65
|
http
|
75
66
|
end
|
76
67
|
def request_setup(uri, verb, body)
|
@@ -95,7 +86,7 @@ module AzureAPI
|
|
95
86
|
puts response.code
|
96
87
|
puts "=== response.inspect ==="
|
97
88
|
puts response.inspect
|
98
|
-
puts "=== all of the headers ==="
|
89
|
+
puts "=== all of the headers ==="
|
99
90
|
puts response.each_header { |h, j| puts h.inspect + ' : ' + j.inspect}
|
100
91
|
end
|
101
92
|
end
|
data/lib/azure/role.rb
CHANGED
@@ -15,14 +15,16 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
|
-
|
18
|
+
require 'securerandom'
|
19
19
|
class Azure
|
20
20
|
class Roles
|
21
|
+
include AzureUtility
|
21
22
|
attr_accessor :connection, :roles
|
22
23
|
def initialize(connection)
|
23
24
|
@connection = connection
|
24
25
|
@roles = nil
|
25
26
|
end
|
27
|
+
# do not use this unless you want a list of all roles(vms) in your subscription
|
26
28
|
def all
|
27
29
|
@roles = Array.new
|
28
30
|
@connection.deploys.all.each do |deploy|
|
@@ -32,51 +34,121 @@ class Azure
|
|
32
34
|
end
|
33
35
|
@roles
|
34
36
|
end
|
35
|
-
|
36
|
-
|
37
|
-
|
37
|
+
|
38
|
+
def find_roles_within_hostedservice(hostedservicename)
|
39
|
+
host = @connection.hosts.find(hostedservicename)
|
40
|
+
(host) ? host.roles : nil # nil says invalid hosted service
|
41
|
+
end
|
42
|
+
|
43
|
+
def find_in_hosted_service(role_name, hostedservicename)
|
44
|
+
host = @connection.hosts.find(hostedservicename)
|
45
|
+
return nil if host.nil?
|
46
|
+
host.find_role(role_name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def find(role_name, params= nil)
|
50
|
+
if params && params[:azure_dns_name]
|
51
|
+
return find_in_hosted_service(role_name, params[:azure_dns_name])
|
38
52
|
end
|
53
|
+
|
54
|
+
all if @roles == nil
|
55
|
+
|
56
|
+
# TODO - optimize this lookup
|
39
57
|
@roles.each do |role|
|
40
|
-
if(role.name ==
|
41
|
-
return role
|
58
|
+
if(role.name == role_name)
|
59
|
+
return role
|
42
60
|
end
|
43
61
|
end
|
44
|
-
nil
|
62
|
+
nil
|
45
63
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
role.hostedservicename == found_role.hostedservicename)
|
52
|
-
return false;
|
53
|
-
end
|
64
|
+
|
65
|
+
def alone_on_hostedservice(found_role)
|
66
|
+
roles = find_roles_within_hostedservice(found_role.hostedservicename)
|
67
|
+
if roles && roles.length > 1
|
68
|
+
return false
|
54
69
|
end
|
55
|
-
true
|
70
|
+
return true
|
56
71
|
end
|
57
|
-
|
72
|
+
|
73
|
+
def exists?(name)
|
58
74
|
find(name) != nil
|
59
75
|
end
|
60
|
-
|
76
|
+
|
77
|
+
def delete(name, params)
|
61
78
|
role = find(name)
|
62
79
|
if role != nil
|
63
|
-
if
|
80
|
+
if alone_on_hostedservice(role)
|
64
81
|
servicecall = "hostedservices/#{role.hostedservicename}/deployments" +
|
65
82
|
"/#{role.deployname}"
|
66
83
|
else
|
67
84
|
servicecall = "hostedservices/#{role.hostedservicename}/deployments" +
|
68
85
|
"/#{role.deployname}/roles/#{role.name}"
|
69
86
|
end
|
70
|
-
|
87
|
+
|
88
|
+
roleXML = nil
|
89
|
+
|
90
|
+
unless params[:preserve_azure_os_disk]
|
91
|
+
roleXML = @connection.query_azure(servicecall, "get")
|
92
|
+
end
|
93
|
+
|
94
|
+
@connection.query_azure(servicecall, "delete")
|
95
|
+
# delete role from local cache as well.
|
96
|
+
@connection.hosts.find(role.hostedservicename).delete_role(role)
|
97
|
+
@roles.delete(role) if @roles
|
98
|
+
|
99
|
+
unless params[:preserve_azure_dns_name]
|
100
|
+
unless params[:azure_dns_name].nil?
|
101
|
+
roles_using_same_service = find_roles_within_hostedservice(params[:azure_dns_name])
|
102
|
+
if roles_using_same_service.size <= 1
|
103
|
+
servicecall = "hostedservices/" + params[:azure_dns_name]
|
104
|
+
@connection.query_azure(servicecall, "delete")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
unless params[:preserve_azure_os_disk]
|
110
|
+
osdisk = roleXML.css(roleXML, 'OSVirtualHardDisk')
|
111
|
+
disk_name = xml_content(osdisk, 'DiskName')
|
112
|
+
servicecall = "disks/#{disk_name}"
|
113
|
+
storage_account = @connection.query_azure(servicecall, "get")
|
114
|
+
|
115
|
+
# OS Disk can only be deleted if it is detached from the VM.
|
116
|
+
# So Iteratively check for disk detachment from the VM while waiting for 5 minutes ,
|
117
|
+
# exit otherwise after 12 attempts.
|
118
|
+
for attempt in 0..12
|
119
|
+
break if @connection.query_azure(servicecall, "get").search("AttachedTo").text == ""
|
120
|
+
if attempt == 12 then puts "The associated disk could not be deleted due to time out." else sleep 25 end
|
121
|
+
end
|
122
|
+
@connection.query_azure(servicecall, "delete")
|
123
|
+
|
124
|
+
if params[:delete_azure_storage_account]
|
125
|
+
storage_account_name = xml_content(storage_account, "MediaLink")
|
126
|
+
storage_account_name = storage_account_name.gsub("http://", "").gsub(/.blob(.*)$/, "")
|
127
|
+
|
128
|
+
begin
|
129
|
+
@connection.query_azure("storageservices/#{storage_account_name}", "delete")
|
130
|
+
rescue Exception => ex
|
131
|
+
ui.warn("#{ex.message}")
|
132
|
+
ui.warn("#{ex.backtrace.join("\n")}")
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
|
71
140
|
end
|
72
|
-
#@connection.disks.clear_unattached
|
73
141
|
end
|
142
|
+
|
74
143
|
end
|
144
|
+
|
75
145
|
class Role
|
76
146
|
include AzureUtility
|
77
|
-
attr_accessor :connection, :name, :status, :size, :ipaddress
|
78
|
-
attr_accessor :sshport, :
|
147
|
+
attr_accessor :connection, :name, :status, :size, :ipaddress, :publicipaddress
|
148
|
+
attr_accessor :sshport, :hostedservicename, :deployname
|
149
|
+
attr_accessor :winrmport
|
79
150
|
attr_accessor :hostname, :tcpports, :udpports
|
151
|
+
|
80
152
|
def initialize(connection)
|
81
153
|
@connection = connection
|
82
154
|
end
|
@@ -90,11 +162,14 @@ class Azure
|
|
90
162
|
@deployname = deployname
|
91
163
|
@tcpports = Array.new
|
92
164
|
@udpports = Array.new
|
165
|
+
|
93
166
|
endpoints = roleXML.css('InstanceEndpoint')
|
167
|
+
@publicipaddress = xml_content(endpoints[0], 'Vip') if !endpoints.empty?
|
94
168
|
endpoints.each do |endpoint|
|
95
169
|
if xml_content(endpoint, 'Name').downcase == 'ssh'
|
96
170
|
@sshport = xml_content(endpoint, 'PublicPort')
|
97
|
-
|
171
|
+
elsif xml_content(endpoint, 'Name').downcase == 'winrm'
|
172
|
+
@winrmport = xml_content(endpoint, 'PublicPort')
|
98
173
|
else
|
99
174
|
hash = Hash.new
|
100
175
|
hash['Name'] = xml_content(endpoint, 'Name')
|
@@ -115,34 +190,72 @@ class Azure
|
|
115
190
|
'xmlns'=>'http://schemas.microsoft.com/windowsazure',
|
116
191
|
'xmlns:i'=>'http://www.w3.org/2001/XMLSchema-instance'
|
117
192
|
) {
|
118
|
-
xml.RoleName {xml.text params[:
|
193
|
+
xml.RoleName {xml.text params[:azure_vm_name]}
|
119
194
|
xml.OsVersion('i:nil' => 'true')
|
120
195
|
xml.RoleType 'PersistentVMRole'
|
121
196
|
xml.ConfigurationSets {
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
197
|
+
if params[:os_type] == 'Linux'
|
198
|
+
|
199
|
+
xml.ConfigurationSet('i:type' => 'LinuxProvisioningConfigurationSet') {
|
200
|
+
xml.ConfigurationSetType 'LinuxProvisioningConfiguration'
|
201
|
+
xml.HostName params[:azure_vm_name]
|
202
|
+
xml.UserName params[:ssh_user]
|
203
|
+
unless params[:identity_file].nil?
|
204
|
+
xml.DisableSshPasswordAuthentication 'true'
|
205
|
+
xml.SSH {
|
206
|
+
xml.PublicKeys {
|
207
|
+
xml.PublicKey {
|
208
|
+
xml.Fingerprint params[:fingerprint]
|
209
|
+
xml.Path '/home/' + params[:ssh_user] + '/.ssh/authorized_keys'
|
210
|
+
}
|
211
|
+
}
|
212
|
+
}
|
213
|
+
else
|
214
|
+
xml.UserPassword params[:ssh_password]
|
215
|
+
xml.DisableSshPasswordAuthentication 'false'
|
216
|
+
end
|
217
|
+
}
|
218
|
+
elsif params[:os_type] == 'Windows'
|
219
|
+
xml.ConfigurationSet('i:type' => 'WindowsProvisioningConfigurationSet') {
|
220
|
+
xml.ConfigurationSetType 'WindowsProvisioningConfiguration'
|
221
|
+
xml.ComputerName params[:azure_vm_name]
|
222
|
+
xml.AdminPassword params[:admin_password]
|
223
|
+
xml.ResetPasswordOnFirstLogon 'false'
|
224
|
+
xml.EnableAutomaticUpdates 'false'
|
225
|
+
|
226
|
+
}
|
227
|
+
end
|
228
|
+
|
129
229
|
xml.ConfigurationSet('i:type' => 'NetworkConfigurationSet') {
|
130
230
|
xml.ConfigurationSetType 'NetworkConfiguration'
|
131
231
|
xml.InputEndpoints {
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
232
|
+
if params[:bootstrap_proto].downcase == 'ssh'
|
233
|
+
xml.InputEndpoint {
|
234
|
+
xml.LocalPort '22'
|
235
|
+
xml.Name 'SSH'
|
236
|
+
xml.Port params[:port]
|
237
|
+
xml.Protocol 'TCP'
|
238
|
+
}
|
239
|
+
elsif params[:bootstrap_proto].downcase == 'winrm' and params[:os_type] == 'Windows'
|
240
|
+
xml.InputEndpoint {
|
241
|
+
xml.LocalPort '5985'
|
242
|
+
xml.Name 'WinRM'
|
243
|
+
xml.Port params[:port]
|
244
|
+
xml.Protocol 'TCP'
|
245
|
+
}
|
246
|
+
end
|
247
|
+
|
137
248
|
if params[:tcp_endpoints]
|
138
249
|
params[:tcp_endpoints].split(',').each do |endpoint|
|
139
250
|
ports = endpoint.split(':')
|
140
251
|
xml.InputEndpoint {
|
141
252
|
xml.LocalPort ports[0]
|
142
|
-
xml.Name 'tcpport_' + ports[0] + '_' + params[:
|
253
|
+
xml.Name 'tcpport_' + ports[0] + '_' + params[:azure_vm_name]
|
143
254
|
if ports.length > 1
|
144
255
|
xml.Port ports[1]
|
145
|
-
|
256
|
+
else
|
257
|
+
xml.Port ports[0]
|
258
|
+
end
|
146
259
|
xml.Protocol 'TCP'
|
147
260
|
}
|
148
261
|
end
|
@@ -152,10 +265,12 @@ class Azure
|
|
152
265
|
ports = endpoint.split(':')
|
153
266
|
xml.InputEndpoint {
|
154
267
|
xml.LocalPort ports[0]
|
155
|
-
xml.Name 'udpport_' + ports[0] + '_' + params[:
|
268
|
+
xml.Name 'udpport_' + ports[0] + '_' + params[:azure_vm_name]
|
156
269
|
if ports.length > 1
|
157
270
|
xml.Port ports[1]
|
158
|
-
|
271
|
+
else
|
272
|
+
xml.Port ports[0]
|
273
|
+
end
|
159
274
|
xml.Protocol 'UDP'
|
160
275
|
}
|
161
276
|
end
|
@@ -163,20 +278,22 @@ class Azure
|
|
163
278
|
}
|
164
279
|
}
|
165
280
|
}
|
166
|
-
xml.Label Base64.encode64(params[:
|
281
|
+
xml.Label Base64.encode64(params[:azure_vm_name]).strip
|
167
282
|
xml.OSVirtualHardDisk {
|
168
|
-
|
169
|
-
xml.
|
283
|
+
disk_name = params[:azure_os_disk_name] || "disk_" + SecureRandom.uuid
|
284
|
+
xml.DiskName disk_name
|
285
|
+
xml.MediaLink 'http://' + params[:azure_storage_account] + '.blob.core.windows.net/vhds/' + disk_name + '.vhd'
|
286
|
+
xml.SourceImageName params[:azure_source_image]
|
170
287
|
}
|
171
|
-
xml.RoleSize params[:
|
288
|
+
xml.RoleSize params[:azure_vm_size]
|
172
289
|
}
|
173
|
-
end
|
290
|
+
end
|
174
291
|
builder.doc
|
175
292
|
end
|
176
293
|
def create(params, roleXML)
|
177
|
-
servicecall = "hostedservices/#{params[:
|
294
|
+
servicecall = "hostedservices/#{params[:azure_dns_name]}/deployments" +
|
178
295
|
"/#{params['deploy_name']}/roles"
|
179
|
-
@connection.query_azure(servicecall, "post", roleXML.to_xml)
|
296
|
+
@connection.query_azure(servicecall, "post", roleXML.to_xml)
|
180
297
|
end
|
181
298
|
end
|
182
299
|
end
|