foreman_azure_rm 1.1.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 +7 -0
- data/LICENSE +619 -0
- data/README.md +23 -0
- data/Rakefile +47 -0
- data/app/assets/javascripts/foreman_azure_rm/azure_rm_location_callbacks.js +72 -0
- data/app/assets/javascripts/foreman_azure_rm/azure_rm_size_from_location.js +39 -0
- data/app/assets/javascripts/foreman_azure_rm/azure_rm_subnet_from_vnet.js +39 -0
- data/app/controllers/foreman_azure_rm/concerns/hosts_controller_extensions.rb +33 -0
- data/app/models/concerns/fog_extensions/azurerm/compute.rb +246 -0
- data/app/models/concerns/fog_extensions/azurerm/data_disk.rb +24 -0
- data/app/models/concerns/fog_extensions/azurerm/managed_disk.rb +10 -0
- data/app/models/concerns/fog_extensions/azurerm/managed_disks.rb +15 -0
- data/app/models/concerns/fog_extensions/azurerm/network_interface.rb +19 -0
- data/app/models/concerns/fog_extensions/azurerm/network_interfaces.rb +16 -0
- data/app/models/concerns/fog_extensions/azurerm/server.rb +123 -0
- data/app/models/concerns/fog_extensions/azurerm/servers.rb +23 -0
- data/app/models/foreman_azure_rm/azure_rm.rb +310 -0
- data/app/overrides/add_location_size_js.rb +20 -0
- data/app/views/compute_resources/form/_azurerm.html.erb +9 -0
- data/app/views/compute_resources/show/_azurerm.html.erb +0 -0
- data/app/views/compute_resources_vms/form/azurerm/_base.html.erb +207 -0
- data/app/views/compute_resources_vms/form/azurerm/_network.html.erb +23 -0
- data/app/views/compute_resources_vms/form/azurerm/_volume.html.erb +22 -0
- data/app/views/compute_resources_vms/index/_azurerm.html.erb +29 -0
- data/app/views/compute_resources_vms/show/_azurerm.html.erb +14 -0
- data/app/views/images/form/_azurerm.html.erb +6 -0
- data/config/routes.rb +8 -0
- data/lib/foreman_azure_rm.rb +5 -0
- data/lib/foreman_azure_rm/engine.rb +92 -0
- data/lib/foreman_azure_rm/version.rb +3 -0
- data/locale/gemspec.rb +2 -0
- metadata +103 -0
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Foreman Azure
|
2
|
+
|
3
|
+
## Description
|
4
|
+
Plugin to add [Microsoft Azure Resource Manager](http://azure.com/) as a compute resource for [The Foreman](http://theforeman.org/)
|
5
|
+
|
6
|
+
## Features
|
7
|
+
* Managed disks support
|
8
|
+
* Support for most typical IaaS operations
|
9
|
+
* VM creation
|
10
|
+
* Multiple NICs
|
11
|
+
* Multiple data disks, premium or not
|
12
|
+
* Static or dynamic addresses on a per NIC basis
|
13
|
+
* Limited extension support
|
14
|
+
* Microsoft's custom script extension
|
15
|
+
* Puppet Lab's Puppet agent extension for Windows
|
16
|
+
|
17
|
+
## Planned Features
|
18
|
+
* Improved extension support
|
19
|
+
|
20
|
+
## Known Limitations
|
21
|
+
* Most Azure marketplace images (likely all of them) disallow direct root login, which means SSH provisioning
|
22
|
+
with The Foreman has limited functionality. A workaround is to provide a dummy user data template and do all
|
23
|
+
post-provisioning with the custom script extension
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'ForemanAzureRM'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
|
24
|
+
|
25
|
+
Bundler::GemHelper.install_tasks
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
|
29
|
+
Rake::TestTask.new(:test) do |t|
|
30
|
+
t.libs << 'lib'
|
31
|
+
t.libs << 'test'
|
32
|
+
t.pattern = 'test/**/*_test.rb'
|
33
|
+
t.verbose = false
|
34
|
+
end
|
35
|
+
|
36
|
+
task default: :test
|
37
|
+
|
38
|
+
begin
|
39
|
+
require 'rubocop/rake_task'
|
40
|
+
RuboCop::RakeTask.new
|
41
|
+
rescue => _
|
42
|
+
puts 'Rubocop not loaded.'
|
43
|
+
end
|
44
|
+
|
45
|
+
task :default do
|
46
|
+
Rake::Task['rubocop'].execute
|
47
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
/**
|
2
|
+
* Created by tgregory on 3/13/17.
|
3
|
+
*/
|
4
|
+
function azure_rm_storage_accts_from_location() {
|
5
|
+
var imageId = $('#host_compute_attributes_custom_data').val();
|
6
|
+
var storage_accts = $('#azure_rm_storage_acct');
|
7
|
+
var location = $('#azure_rm_location').val();
|
8
|
+
if (typeof tfm == 'undefined') { // earlier than 1.13
|
9
|
+
foreman.tools.showSpinner();
|
10
|
+
} else {
|
11
|
+
tfm.tools.showSpinner();
|
12
|
+
}
|
13
|
+
$.ajax({
|
14
|
+
data: { "image_id": imageId, "location": location },
|
15
|
+
type: "get",
|
16
|
+
url: "/azure_rm/storage_accts",
|
17
|
+
complete: function() {
|
18
|
+
reloadOnAjaxComplete('#azure_rm_storage_acct');
|
19
|
+
if (typeof tfm == 'undefined') { // earlier than 1.13
|
20
|
+
foreman.tools.hideSpinner();
|
21
|
+
} else {
|
22
|
+
tfm.tools.hideSpinner();
|
23
|
+
}
|
24
|
+
},
|
25
|
+
error: function(request, status, error) {
|
26
|
+
console.log(status);
|
27
|
+
console.log(request);
|
28
|
+
console.log(error);
|
29
|
+
},
|
30
|
+
success: function(request_accts) {
|
31
|
+
storage_accts.empty();
|
32
|
+
$.each(request_accts, function() {
|
33
|
+
storage_accts.append($("<option />").val(this).text(this));
|
34
|
+
});
|
35
|
+
}
|
36
|
+
});
|
37
|
+
}
|
38
|
+
|
39
|
+
function azure_rm_vnets_from_location() {
|
40
|
+
var imageId = $('#host_compute_attributes_custom_data').val();
|
41
|
+
var vnets = $('#azure_rm_vnet');
|
42
|
+
var location = $('#azure_rm_location').val();
|
43
|
+
if (typeof tfm == 'undefined') { // earlier than 1.13
|
44
|
+
foreman.tools.showSpinner();
|
45
|
+
} else {
|
46
|
+
tfm.tools.showSpinner();
|
47
|
+
}
|
48
|
+
$.ajax({
|
49
|
+
data: { "image_id": imageId, "location": location },
|
50
|
+
type: "get",
|
51
|
+
url: "/azure_rm/vnets",
|
52
|
+
complete: function() {
|
53
|
+
reloadOnAjaxComplete('#azure_rm_storage_acct');
|
54
|
+
if (typeof tfm == 'undefined') { // earlier than 1.13
|
55
|
+
foreman.tools.hideSpinner();
|
56
|
+
} else {
|
57
|
+
tfm.tools.hideSpinner();
|
58
|
+
}
|
59
|
+
},
|
60
|
+
error: function(request, status, error) {
|
61
|
+
console.log(status);
|
62
|
+
console.log(request);
|
63
|
+
console.log(error);
|
64
|
+
},
|
65
|
+
success: function(request_vnets) {
|
66
|
+
vnets.empty();
|
67
|
+
$.each(request_vnets, function() {
|
68
|
+
vnets.append($("<option />").val(this.id).text(this.name));
|
69
|
+
});
|
70
|
+
}
|
71
|
+
});
|
72
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
/**
|
2
|
+
* Created by tgregory on 3/9/17.
|
3
|
+
*/
|
4
|
+
function azure_rm_get_size_from_location() {
|
5
|
+
var location = $('#azure_rm_location').val();
|
6
|
+
var size_spinner = $('#azure_rm_size_spinner');
|
7
|
+
var sizes = $('#azure_rm_size');
|
8
|
+
var imageId = $('#host_compute_attributes_custom_data').val();
|
9
|
+
if (typeof tfm == 'undefined') { // earlier than 1.13
|
10
|
+
foreman.tools.showSpinner();
|
11
|
+
} else {
|
12
|
+
tfm.tools.showSpinner();
|
13
|
+
}
|
14
|
+
size_spinner.removeClass('hide');
|
15
|
+
$.ajax({
|
16
|
+
data: {"location_string": location, "image_id": imageId},
|
17
|
+
type: 'get',
|
18
|
+
url: '/azure_rm/sizes',
|
19
|
+
complete: function() {
|
20
|
+
reloadOnAjaxComplete('#azure_rm_size');
|
21
|
+
size_spinner.addClass('hide');
|
22
|
+
if (typeof tfm == 'undefined') { // earlier than 1.13
|
23
|
+
foreman.tools.hideSpinner();
|
24
|
+
} else {
|
25
|
+
tfm.tools.hideSpinner();
|
26
|
+
}
|
27
|
+
},
|
28
|
+
error: function(request, status, error) {
|
29
|
+
console.log(request);
|
30
|
+
console.log(error);
|
31
|
+
},
|
32
|
+
success: function(request_sizes) {
|
33
|
+
sizes.empty();
|
34
|
+
$.each(request_sizes, function() {
|
35
|
+
sizes.append($("<option />").val(this).text(this));
|
36
|
+
});
|
37
|
+
}
|
38
|
+
});
|
39
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
//TODO figure out how to refresh modal
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Created by tgregory on 3/10/17.
|
5
|
+
*/
|
6
|
+
function azure_rm_subnet_from_vnet() {
|
7
|
+
var vnet = $('#azure_rm_vnet').val();
|
8
|
+
var imageId = $('#host_compute_attributes_custom_data').val();
|
9
|
+
var subnets = $('#azure_rm_subnet');
|
10
|
+
if (typeof tfm == 'undefined') { // earlier than 1.13
|
11
|
+
foreman.tools.showSpinner();
|
12
|
+
} else {
|
13
|
+
tfm.tools.showSpinner();
|
14
|
+
}
|
15
|
+
$.ajax({
|
16
|
+
data: { "image_id": imageId, "vnet": vnet },
|
17
|
+
type: "get",
|
18
|
+
url: "/azure_rm/subnets",
|
19
|
+
complete: function() {
|
20
|
+
reloadOnAjaxComplete('#azure_rm_subnet');
|
21
|
+
if (typeof tfm == 'undefined') { // earlier than 1.13
|
22
|
+
foreman.tools.hideSpinner();
|
23
|
+
} else {
|
24
|
+
tfm.tools.hideSpinner();
|
25
|
+
}
|
26
|
+
},
|
27
|
+
error: function(request, status, error) {
|
28
|
+
console.log(status);
|
29
|
+
console.log(request);
|
30
|
+
console.log(error);
|
31
|
+
},
|
32
|
+
success: function(request_subnets) {
|
33
|
+
subnets.empty();
|
34
|
+
$.each(request_subnets, function() {
|
35
|
+
subnets.append($("<option />").val(this.id).text(this.name));
|
36
|
+
});
|
37
|
+
}
|
38
|
+
});
|
39
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ForemanAzureRM
|
2
|
+
module Concerns
|
3
|
+
module HostsControllerExtensions
|
4
|
+
|
5
|
+
def sizes
|
6
|
+
if (azure_rm_resource = Image.unscoped.find_by_uuid(params[:image_id])).present?
|
7
|
+
resource = azure_rm_resource.compute_resource
|
8
|
+
render :json => resource.vm_sizes(params[:location_string])
|
9
|
+
else
|
10
|
+
no_sizes = _('The location you selected has no sizes associated with it')
|
11
|
+
render :json => "[\"#{no_sizes}\"]"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def subnets
|
16
|
+
azure_rm_image = Image.unscoped.find_by_uuid(params[:image_id])
|
17
|
+
if azure_rm_image.present?
|
18
|
+
azure_rm_resource = azure_rm_image.compute_resource
|
19
|
+
subnets = azure_rm_resource.subnets(params[:location])
|
20
|
+
if subnets.present?
|
21
|
+
render :json => azure_rm_resource.subnets(params[:location])
|
22
|
+
else
|
23
|
+
no_subnets = _('The selected location has no subnets')
|
24
|
+
render :json => "[\"#{no_subnets}\"]"
|
25
|
+
end
|
26
|
+
else
|
27
|
+
no_compute = _('The selected image has no associated compute resource')
|
28
|
+
render :json => "[\"#{no_compute}\"]"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,246 @@
|
|
1
|
+
module FogExtensions
|
2
|
+
module AzureRM
|
3
|
+
module Compute
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
begin
|
8
|
+
require 'azure_mgmt_compute'
|
9
|
+
require 'azure_mgmt_storage'
|
10
|
+
require 'azure_mgmt_network'
|
11
|
+
require 'azure/storage'
|
12
|
+
rescue LoadError => e
|
13
|
+
retry if require('rubygems')
|
14
|
+
raise e.message
|
15
|
+
end
|
16
|
+
|
17
|
+
options[:environment] = 'AzureCloud' if options[:environment].nil?
|
18
|
+
|
19
|
+
telemetry = "fog-azure-rm/#{Fog::AzureRM::VERSION}"
|
20
|
+
credentials = Fog::Credentials::AzureRM.get_credentials(options[:tenant_id], options[:client_id], options[:client_secret], options[:environment])
|
21
|
+
@compute_mgmt_client = ::Azure::ARM::Compute::ComputeManagementClient.new(credentials, resource_manager_endpoint_url(options[:environment]))
|
22
|
+
@compute_mgmt_client.subscription_id = options[:subscription_id]
|
23
|
+
@compute_mgmt_client.add_user_agent_information(telemetry)
|
24
|
+
@storage_mgmt_client = ::Azure::ARM::Storage::StorageManagementClient.new(credentials, resource_manager_endpoint_url(options[:environment]))
|
25
|
+
@storage_mgmt_client.subscription_id = options[:subscription_id]
|
26
|
+
@storage_mgmt_client.add_user_agent_information(telemetry)
|
27
|
+
# noinspection RubyArgCount
|
28
|
+
@storage_service = Fog::Storage::AzureRM.new(tenant_id: options[:tenant_id], client_id: options[:client_id], client_secret: options[:client_secret], subscription_id: options[:subscription_id], environment: options[:environment])
|
29
|
+
@network_client = ::Azure::ARM::Network::NetworkManagementClient.new(credentials, resource_manager_endpoint_url(options[:environment]))
|
30
|
+
@network_client.subscription_id = options[:subscription_id]
|
31
|
+
@network_client.add_user_agent_information(telemetry)
|
32
|
+
end
|
33
|
+
|
34
|
+
def list_available_sizes(location)
|
35
|
+
sizes = []
|
36
|
+
@compute_mgmt_client.virtual_machine_sizes.list(location).value().each do |vmsize|
|
37
|
+
sizes << vmsize.name
|
38
|
+
end
|
39
|
+
sizes
|
40
|
+
end
|
41
|
+
|
42
|
+
def list_all_vms
|
43
|
+
@compute_mgmt_client.virtual_machines.list_all
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_vm_nic(nic_rg, nic_name)
|
47
|
+
@network_client.network_interfaces.get(nic_rg, nic_name)
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_public_ip(ip_rg, ip_name)
|
51
|
+
@network_client.public_ipaddresses.get(ip_rg, ip_name)
|
52
|
+
end
|
53
|
+
|
54
|
+
def define_managed_storage_profile(vm_name, vhd_path, publisher, offer, sku, version,
|
55
|
+
os_disk_caching, platform, os_disk_size, premium_os_disk,
|
56
|
+
data_disks = nil)
|
57
|
+
storage_profile = Azure::ARM::Compute::Models::StorageProfile.new
|
58
|
+
os_disk = Azure::ARM::Compute::Models::OSDisk.new
|
59
|
+
managed_disk_params = Azure::ARM::Compute::Models::ManagedDiskParameters.new
|
60
|
+
|
61
|
+
# Create OS disk
|
62
|
+
os_disk.name = "#{vm_name}-osdisk"
|
63
|
+
os_disk.os_type = if platform == 'Windows'
|
64
|
+
Azure::ARM::Compute::Models::OperatingSystemTypes::Windows
|
65
|
+
else
|
66
|
+
Azure::ARM::Compute::Models::OperatingSystemTypes::Linux
|
67
|
+
end
|
68
|
+
os_disk.create_option = Azure::ARM::Compute::Models::DiskCreateOptionTypes::FromImage
|
69
|
+
os_disk.caching = if os_disk_caching.present?
|
70
|
+
case os_disk_caching
|
71
|
+
when 'None'
|
72
|
+
Azure::ARM::Compute::Models::CachingTypes::None
|
73
|
+
when 'ReadOnly'
|
74
|
+
Azure::ARM::Compute::Models::CachingTypes::ReadOnly
|
75
|
+
when 'ReadWrite'
|
76
|
+
Azure::ARM::Compute::Models::CachingTypes::ReadWrite
|
77
|
+
else
|
78
|
+
# ARM best practices stipulate RW caching on the OS disk
|
79
|
+
Azure::ARM::Compute::Models::CachingTypes::ReadWrite
|
80
|
+
end
|
81
|
+
end
|
82
|
+
os_disk.disk_size_gb = os_disk_size
|
83
|
+
managed_disk_params.storage_account_type = if premium_os_disk == 'true'
|
84
|
+
Azure::ARM::Compute::Models::StorageAccountTypes::PremiumLRS
|
85
|
+
else
|
86
|
+
Azure::ARM::Compute::Models::StorageAccountTypes::StandardLRS
|
87
|
+
end
|
88
|
+
os_disk.managed_disk = managed_disk_params
|
89
|
+
storage_profile.os_disk = os_disk
|
90
|
+
|
91
|
+
# Create data disks
|
92
|
+
unless data_disks.nil?
|
93
|
+
disks = []
|
94
|
+
disk_count = 0
|
95
|
+
data_disks.each do |_, attrs|
|
96
|
+
managed_data_disk = Azure::ARM::Compute::Models::ManagedDiskParameters.new
|
97
|
+
managed_data_disk.storage_account_type = if attrs[:account_type] == 'true'
|
98
|
+
Azure::ARM::Compute::Models::StorageAccountTypes::PremiumLRS
|
99
|
+
else
|
100
|
+
Azure::ARM::Compute::Models::StorageAccountTypes::StandardLRS
|
101
|
+
end
|
102
|
+
disk = Azure::ARM::Compute::Models::DataDisk.new
|
103
|
+
disk.name = "#{vm_name}-disk#{disk_count}"
|
104
|
+
disk.caching = if attrs[:data_disk_caching].present?
|
105
|
+
case attrs[:data_disk_caching]
|
106
|
+
when 'None'
|
107
|
+
Azure::ARM::Compute::Models::CachingTypes::None
|
108
|
+
when 'ReadOnly'
|
109
|
+
Azure::ARM::Compute::Models::CachingTypes::ReadOnly
|
110
|
+
when 'ReadWrite'
|
111
|
+
Azure::ARM::Compute::Models::CachingTypes::ReadWrite
|
112
|
+
else
|
113
|
+
# ARM best practices stipulate no caching on data disks by default
|
114
|
+
Azure::ARM::Compute::Models::CachingTypes::None
|
115
|
+
end
|
116
|
+
end
|
117
|
+
disk.disk_size_gb = attrs[:disk_size_gb]
|
118
|
+
disk.create_option = Azure::ARM::Compute::Models::DiskCreateOption::Empty
|
119
|
+
disk.lun = disk_count + 1
|
120
|
+
disk.managed_disk = managed_data_disk
|
121
|
+
disk_count += 1
|
122
|
+
disks << disk
|
123
|
+
end
|
124
|
+
storage_profile.data_disks = disks
|
125
|
+
end
|
126
|
+
|
127
|
+
if vhd_path.nil?
|
128
|
+
# We are using a marketplace image
|
129
|
+
storage_profile.image_reference = image_reference(publisher, offer,
|
130
|
+
sku, version)
|
131
|
+
else
|
132
|
+
# We are using a custom managed image
|
133
|
+
image_ref = Azure::ARM::Compute::Models::ImageReference.new
|
134
|
+
image_ref.id = vhd_path
|
135
|
+
storage_profile.image_reference = image_ref
|
136
|
+
end
|
137
|
+
storage_profile
|
138
|
+
end
|
139
|
+
|
140
|
+
def create_vm_extension(vm)
|
141
|
+
if vm[:script_command].present? && vm[:script_uris].present?
|
142
|
+
extension = Azure::ARM::Compute::Models::VirtualMachineExtension.new
|
143
|
+
extension.publisher = 'Microsoft.Azure.Extensions'
|
144
|
+
extension.virtual_machine_extension_type = 'CustomScript'
|
145
|
+
extension.type_handler_version = '2.0'
|
146
|
+
extension.auto_upgrade_minor_version = true
|
147
|
+
extension.location = vm['location'].gsub(/\s+/, '').downcase
|
148
|
+
extension.settings = {
|
149
|
+
'commandToExecute' => vm[:script_command],
|
150
|
+
'fileUris' => vm[:script_uris].split(',')
|
151
|
+
}
|
152
|
+
@compute_mgmt_client.virtual_machine_extensions.create_or_update(vm['resource_group'],
|
153
|
+
vm['name'],
|
154
|
+
'ForemanCustomScript',
|
155
|
+
extension)
|
156
|
+
end
|
157
|
+
if vm[:platform] == 'Windows'
|
158
|
+
if vm[:puppet_master].present?
|
159
|
+
extension = Azure::ARM::Compute::Models::VirtualMachineExtension.new
|
160
|
+
extension.publisher = 'PuppetLabs'
|
161
|
+
extension.virtual_machine_extension_type = 'PuppetEnterpriseAgent'
|
162
|
+
extension.type_handler_version = '3.8'
|
163
|
+
extension.auto_upgrade_minor_version = true
|
164
|
+
extension.location = vm['location'].gsub(/\s+/, '').downcase
|
165
|
+
extension.settings = {
|
166
|
+
'puppet_master_service' => vm[:puppet_master]
|
167
|
+
}
|
168
|
+
@compute_mgmt_client.virtual_machine_extensions.create_or_update(vm['resource_group'],
|
169
|
+
vm['name'],
|
170
|
+
'InstallPuppet',
|
171
|
+
extension)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def create_managed_virtual_machine(vm_hash, async = false)
|
177
|
+
msg = "Creating Virtual Machine #{vm_hash[:name]} in Resource Group #{vm_hash[:resource_group]}."
|
178
|
+
Fog::Logger.debug msg
|
179
|
+
virtual_machine = Azure::ARM::Compute::Models::VirtualMachine.new
|
180
|
+
|
181
|
+
unless vm_hash[:availability_set_id].nil?
|
182
|
+
sub_resource = MsRestAzure::SubResource.new
|
183
|
+
sub_resource.id = vm_hash[:availability_set_id]
|
184
|
+
virtual_machine.availability_set = sub_resource
|
185
|
+
end
|
186
|
+
|
187
|
+
# If image UUID begins with / it is a custom managed image
|
188
|
+
# Otherwise it is a marketplace URN
|
189
|
+
unless vm_hash[:vhd_path].start_with?('/')
|
190
|
+
urn = vm_hash[:vhd_path].split(':')
|
191
|
+
vm_hash[:publisher] = urn[0]
|
192
|
+
vm_hash[:offer] = urn[1]
|
193
|
+
vm_hash[:sku] = urn[2]
|
194
|
+
vm_hash[:version] = urn[3]
|
195
|
+
vm_hash[:vhd_path] = nil
|
196
|
+
end
|
197
|
+
|
198
|
+
string_data = vm_hash[:custom_data]
|
199
|
+
string_data = WHITE_SPACE if string_data.nil?
|
200
|
+
encoded_data = Base64.strict_encode64(string_data)
|
201
|
+
virtual_machine.hardware_profile = define_hardware_profile(vm_hash[:vm_size])
|
202
|
+
virtual_machine.storage_profile = define_managed_storage_profile(vm_hash[:name],
|
203
|
+
vm_hash[:vhd_path],
|
204
|
+
vm_hash[:publisher],
|
205
|
+
vm_hash[:offer],
|
206
|
+
vm_hash[:sku],
|
207
|
+
vm_hash[:version],
|
208
|
+
vm_hash[:os_disk_caching],
|
209
|
+
vm_hash[:platform],
|
210
|
+
vm_hash[:os_disk_size],
|
211
|
+
vm_hash[:premium_os_disk],
|
212
|
+
vm_hash[:data_disks])
|
213
|
+
virtual_machine.os_profile = if vm_hash[:platform].casecmp(WINDOWS).zero?
|
214
|
+
define_windows_os_profile(vm_hash[:name],
|
215
|
+
vm_hash[:username],
|
216
|
+
vm_hash[:password],
|
217
|
+
vm_hash[:provision_vm_agent],
|
218
|
+
vm_hash[:enable_automatic_updates],
|
219
|
+
encoded_data)
|
220
|
+
else
|
221
|
+
define_linux_os_profile(vm_hash[:name],
|
222
|
+
vm_hash[:username],
|
223
|
+
vm_hash[:password],
|
224
|
+
vm_hash[:disable_password_authentication],
|
225
|
+
vm_hash[:ssh_key_path],
|
226
|
+
vm_hash[:ssh_key_data],
|
227
|
+
encoded_data)
|
228
|
+
end
|
229
|
+
virtual_machine.network_profile = define_network_profile(vm_hash[:network_interface_card_ids])
|
230
|
+
virtual_machine.location = vm_hash[:location]
|
231
|
+
|
232
|
+
begin
|
233
|
+
response = if async
|
234
|
+
@compute_mgmt_client.virtual_machines.create_or_update_async(vm_hash[:resource_group], vm_hash[:name], virtual_machine)
|
235
|
+
else
|
236
|
+
@compute_mgmt_client.virtual_machines.create_or_update(vm_hash[:resource_group], vm_hash[:name], virtual_machine)
|
237
|
+
end
|
238
|
+
rescue MsRestAzure::AzureOperationError => e
|
239
|
+
raise_azure_exception(e, msg)
|
240
|
+
end
|
241
|
+
Fog::Logger.debug "Virtual Machine #{vm_hash[:name]} Created Successfully." unless async
|
242
|
+
response
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|