foreman_azure_rm 1.3.1 → 2.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c1c4e6dbdc0dbe85c19fed181beb16d91aac9909
4
- data.tar.gz: 84a125c8cccf9e472805d98b7841b1008d7f095d
2
+ SHA256:
3
+ metadata.gz: 8cdbc28091795bf21377b298699209cc2a0d06365858d117b9468a466fb0ffe2
4
+ data.tar.gz: 938f88f1ac6e6f9d9101ce57d2bf187e5c1196fd4abf68c667ae38db5c3270e2
5
5
  SHA512:
6
- metadata.gz: db1923e2cc13efd600fe2fc3192556491043e656b9a92e3920f4368c0c1d37b53dbdb9f501f89b93dcae541a14c6aac1f95409ad1238bb06ac7f08b4d13caf5b
7
- data.tar.gz: 7efdedb724d265fba4664acab40846fd10fee503cd5d52f3d499568ef89763fc3696dc840370796e6923763836651a883c7242059915cb7bcbf4d6c74f40b0cc
6
+ metadata.gz: c4def716d7fa2719d629c0bb9029a60e079e5578c16a33c9baa624462e3da7cdf634fa8f64070fef86bd4b615f9bccafedb427f073facad2a3e5f021bb74eedc
7
+ data.tar.gz: e2dbb0b84df8d5d7a62fa87486b858c5ee11cd28dcdf072ada26cbd77036942837f92f699e7738f40378cc839d0fde9cfc113d53c846b5af84af17dec14f78f4
data/README.md CHANGED
@@ -1,23 +1,51 @@
1
- # Foreman Azure
1
+ # Foreman AzureRM Plugin
2
2
 
3
3
  ## Description
4
- Plugin to add [Microsoft Azure Resource Manager](http://azure.com/) as a compute resource for [The Foreman](http://theforeman.org/)
4
+ ```foreman_azure_rm``` adds [Microsoft Azure Resource Manager](http://azure.com/) as a compute resource for The Foreman
5
+
6
+ * Website: [TheForeman.org](http://theforeman.org)
7
+ * Support: [Foreman support](http://theforeman.org/support.html)
5
8
 
6
9
  ## Features
7
- * Managed disks support
8
10
  * Support for most typical IaaS operations
9
11
  * VM creation
10
- * Multiple NICs
11
- * Multiple data disks, premium or not
12
+ * Provisions using Finish and User data templates from Foreman
13
+ * Supports cloud-config provisioning
14
+ * Currently supports single NIC
15
+ * Currently supports single default OS Disk
16
+ * Currently supports only provisioning of Linux platforms
17
+ * Provisioning using [Public Images](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cli-ps-findimage)
12
18
  * Static or dynamic addresses on a per NIC basis
13
19
  * Limited extension support
14
20
  * Microsoft's custom script extension
15
21
  * Puppet Lab's Puppet agent extension for Windows
22
+
23
+ ## Configuration
24
+ Go to **Infrastructure > Compute Resources** and click on "New Compute Resource".
25
+
26
+ Choose the **AzureRM provider**, and fill in all the fields. You need a Subscription ID, Tenant ID, Client ID and a Client Secret which you can generate from your [Microsoft Azure subscription](https://docs.bmc.com/docs/cloudlifecyclemanagement/46/setting-up-a-tenant-id-client-id-and-client-secret-for-azure-resource-manager-provisioning-669202145.html#SettingupaTenantID,ClientID,andClientSecretforAzureResourceManagerprovisioning-SetupTenantIDPrereqPrerequisites)
27
+
28
+ That's it. You're now ready to create and manage Azure resources in your new AzureRM compute resource. You should see something like this in the Compute Resource page:
29
+
30
+
31
+ ![](https://i.imgur.com/9J7tPJa.png)
32
+
33
+
34
+ ![](https://i.imgur.com/eFHucdb.png)
35
+
36
+
37
+ ![](https://i.imgur.com/RTBlMeE.png)
38
+
16
39
 
17
40
  ## Planned Features
41
+ * Multiple NICs support
42
+ * Support to add multiple data disks (standard or premium)
43
+ * Provision using custom images
44
+ * Provision using shared image galleries
18
45
  * Improved extension support
19
46
 
20
47
  ## 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
48
+ * Unable to provision using Windows Images
49
+
50
+ ## Links
51
+ * [Issue tracker](https://projects.theforeman.org/projects/azurerm)
@@ -5,9 +5,9 @@ module ForemanAzureRM
5
5
  def sizes
6
6
  if (azure_rm_resource = Image.unscoped.find_by_uuid(params[:image_id])).present?
7
7
  resource = azure_rm_resource.compute_resource
8
- render :json => resource.vm_sizes(params[:location_string]).map { |size| size.name }
8
+ render :json => resource.vm_sizes(params[:region_string]).map { |size| size.name }
9
9
  else
10
- no_sizes = _('The location you selected has no sizes associated with it')
10
+ no_sizes = _('The region you selected has no sizes associated with it')
11
11
  render :json => "[\"#{no_sizes}\"]"
12
12
  end
13
13
  end
@@ -16,11 +16,11 @@ module ForemanAzureRM
16
16
  azure_rm_image = Image.unscoped.find_by_uuid(params[:image_id])
17
17
  if azure_rm_image.present?
18
18
  azure_rm_resource = azure_rm_image.compute_resource
19
- subnets = azure_rm_resource.subnets(params[:location])
19
+ subnets = azure_rm_resource.subnets(params[:region])
20
20
  if subnets.present?
21
- render :json => azure_rm_resource.subnets(params[:location])
21
+ render :json => subnets
22
22
  else
23
- no_subnets = _('The selected location has no subnets')
23
+ no_subnets = _('The selected region has no subnets')
24
24
  render :json => "[\"#{no_subnets}\"]"
25
25
  end
26
26
  else
@@ -30,4 +30,4 @@ module ForemanAzureRM
30
30
  end
31
31
  end
32
32
  end
33
- end
33
+ end
@@ -0,0 +1,216 @@
1
+ # This concern has the methods to be called inside azure_rm.rb
2
+ module ForemanAzureRM
3
+ module VMExtensions
4
+ module ManagedVM
5
+ extend ActiveSupport::Concern
6
+
7
+ def define_managed_storage_profile(vm_name, vhd_path, publisher, offer, sku, version,
8
+ os_disk_caching, platform, premium_os_disk)
9
+ storage_profile = ComputeModels::StorageProfile.new
10
+ os_disk = ComputeModels::OSDisk.new
11
+ managed_disk_params = ComputeModels::ManagedDiskParameters.new
12
+
13
+ # Create OS disk
14
+ os_disk.name = "#{vm_name}-osdisk"
15
+ os_disk.os_type = platform
16
+ os_disk.create_option = ComputeModels::DiskCreateOptionTypes::FromImage
17
+ os_disk.caching = if os_disk_caching.present?
18
+ case os_disk_caching
19
+ when 'None'
20
+ ComputeModels::CachingTypes::None
21
+ when 'ReadOnly'
22
+ ComputeModels::CachingTypes::ReadOnly
23
+ when 'ReadWrite'
24
+ ComputeModels::CachingTypes::ReadWrite
25
+ else
26
+ # ARM best practices stipulate RW caching on the OS disk
27
+ ComputeModels::CachingTypes::ReadWrite
28
+ end
29
+ end
30
+ managed_disk_params.storage_account_type = if premium_os_disk == 'true'
31
+ ComputeModels::StorageAccountTypes::PremiumLRS
32
+ else
33
+ ComputeModels::StorageAccountTypes::StandardLRS
34
+ end
35
+ os_disk.managed_disk = managed_disk_params
36
+ storage_profile.os_disk = os_disk
37
+
38
+ # Currently eliminating data disk creation since capability does not exist.
39
+
40
+ if vhd_path.nil?
41
+ # We are using a marketplace image
42
+ storage_profile.image_reference = image_reference(publisher, offer,
43
+ sku, version)
44
+ else
45
+ # We are using a custom managed image
46
+ image_ref = ComputeModels::ImageReference.new
47
+ image_ref.id = vhd_path
48
+ storage_profile.image_reference = image_ref
49
+ end
50
+ storage_profile
51
+ end
52
+
53
+ def image_reference(publisher, offer, sku, version)
54
+ image_reference = ComputeModels::ImageReference.new
55
+ image_reference.publisher = publisher
56
+ image_reference.offer = offer
57
+ image_reference.sku = sku
58
+ image_reference.version = version
59
+ image_reference
60
+ end
61
+
62
+ def define_network_profile(network_interface_card_ids)
63
+ network_interface_cards = []
64
+ network_interface_card_ids.each_with_index do |id, index|
65
+ nic = ComputeModels::NetworkInterfaceReference.new
66
+ nic.id = id
67
+ nic.primary = true
68
+ network_interface_cards << nic
69
+ end
70
+ network_profile = ComputeModels::NetworkProfile.new
71
+ network_profile.network_interfaces = network_interface_cards
72
+ network_profile
73
+ end
74
+
75
+ def create_nics(args = {})
76
+ nics = []
77
+ formatted_region = args[:azure_vm][:location].gsub(/\s+/, '').downcase
78
+ args[:interfaces_attributes].each do |nic, attrs|
79
+ attrs[:pubip_alloc] = attrs[:bridge]
80
+ attrs[:privip_alloc] = (attrs[:name] == 'false') ? false : true
81
+ pip_alloc = case attrs[:pubip_alloc]
82
+ when 'Static'
83
+ NetworkModels::IPAllocationMethod::Static
84
+ when 'Dynamic'
85
+ NetworkModels::IPAllocationMethod::Dynamic
86
+ when 'None'
87
+ nil
88
+ end
89
+ priv_ip_alloc = if attrs[:priv_ip_alloc]
90
+ NetworkModels::IPAllocationMethod::Static
91
+ else
92
+ NetworkModels::IPAllocationMethod::Dynamic
93
+ end
94
+ if pip_alloc.present?
95
+ public_ip_params = NetworkModels::PublicIPAddress.new.tap do |ip|
96
+ ip.location = formatted_region
97
+ ip.public_ipallocation_method = pip_alloc
98
+ end
99
+ pip = sdk.create_or_update_pip(args[:azure_vm][:resource_group],
100
+ "#{args[:azure_vm][:vm_name]}-pip#{nic}",
101
+ public_ip_params)
102
+ end
103
+ new_nic = sdk.create_or_update_nic(
104
+ args[:azure_vm][:resource_group],
105
+ "#{args[:azure_vm][:vm_name]}-nic#{nic}",
106
+ NetworkModels::NetworkInterface.new.tap do |interface|
107
+ interface.location = formatted_region
108
+ interface.ip_configurations = [
109
+ NetworkModels::NetworkInterfaceIPConfiguration.new.tap do |nic_conf|
110
+ nic_conf.name = "#{args[:azure_vm][:vm_name]}-nic#{nic}"
111
+ nic_conf.private_ipallocation_method = priv_ip_alloc
112
+ nic_conf.subnet = subnets(args[:azure_vm][:location]).select{ |subnet| subnet.id == attrs[:network] }.first
113
+ nic_conf.public_ipaddress = pip.present? ? pip : nil
114
+ end
115
+ ]
116
+ end
117
+ )
118
+ nics << new_nic
119
+ end
120
+ nics
121
+ end
122
+
123
+ def create_managed_virtual_machine(vm_hash)
124
+ custom_data = vm_hash[:custom_data]
125
+ msg = "Creating Virtual Machine #{vm_hash[:name]} in Resource Group #{vm_hash[:resource_group]}."
126
+ logger.debug msg
127
+ vm_create_params = ComputeModels::VirtualMachine.new.tap do |vm|
128
+ vm.location = vm_hash[:location]
129
+ unless vm_hash[:availability_set_id].nil?
130
+ sub_resource = MsRestAzure::SubResource.new
131
+ sub_resource.id = vm_hash[:availability_set_id]
132
+ vm.availability_set = sub_resource
133
+ end
134
+ # If image UUID begins with / it is a custom managed image
135
+ # Otherwise it is a marketplace URN
136
+ unless vm_hash[:vhd_path].start_with?('/')
137
+ urn = vm_hash[:vhd_path].split(':')
138
+ vm_hash[:publisher] = urn[0]
139
+ vm_hash[:offer] = urn[1]
140
+ vm_hash[:sku] = urn[2]
141
+ vm_hash[:version] = urn[3]
142
+ vm_hash[:vhd_path] = nil
143
+ end
144
+
145
+ vm.os_profile = ComputeModels::OSProfile.new.tap do |os_profile|
146
+ os_profile.computer_name = vm_hash[:name]
147
+ os_profile.admin_username = vm_hash[:username]
148
+ os_profile.admin_password = vm_hash[:password]
149
+
150
+ # Adding the ssh-key support for authentication
151
+ os_profile.linux_configuration = ComputeModels::LinuxConfiguration.new.tap do |linux|
152
+ linux.disable_password_authentication = vm_hash[:disable_password_authentication]
153
+ linux.ssh = ComputeModels::SshConfiguration.new.tap do |ssh_config|
154
+ ssh_config.public_keys = [
155
+ ComputeModels::SshPublicKey.new.tap do |foreman_key|
156
+ foreman_key.key_data = key_pair.public
157
+ foreman_key.path = "/home/#{vm_hash[:username]}/.ssh/authorized_keys"
158
+ end
159
+ ]
160
+ if vm_hash[:ssh_key_data].present?
161
+ key_data = vm_hash[:ssh_key_data]
162
+ pub_key = ComputeModels::SshPublicKey.new
163
+ pub_key.key_data = key_data
164
+ pub_key.path = "/home/#{vm_hash[:username]}/.ssh/authorized_keys"
165
+ ssh_config.public_keys << pub_key
166
+ end
167
+ end
168
+ end
169
+ # added custom_data here so that azure's vm gets this
170
+ os_profile.custom_data = Base64.strict_encode64(custom_data) unless vm_hash[:custom_data].nil?
171
+ end
172
+ vm.storage_profile = define_managed_storage_profile(
173
+ vm_hash[:name],
174
+ vm_hash[:vhd_path],
175
+ vm_hash[:publisher],
176
+ vm_hash[:offer],
177
+ vm_hash[:sku],
178
+ vm_hash[:version],
179
+ vm_hash[:os_disk_caching],
180
+ vm_hash[:platform],
181
+ vm_hash[:premium_os_disk],
182
+ )
183
+ vm.hardware_profile = ComputeModels::HardwareProfile.new.tap do |hw_profile|
184
+ hw_profile.vm_size = vm_hash[:vm_size]
185
+ end
186
+ vm.network_profile = define_network_profile(vm_hash[:network_interface_card_ids])
187
+ end
188
+
189
+ response = sdk.create_or_update_vm(vm_hash[:resource_group], vm_hash[:name], vm_create_params)
190
+ logger.debug "Virtual Machine #{vm_hash[:name]} Created Successfully."
191
+ response
192
+ end
193
+
194
+ def create_vm_extension(args = {})
195
+ if args[:azure_vm][:script_command].present? || args[:azure_vm][:script_uris].present?
196
+ extension = ComputeModels::VirtualMachineExtension.new
197
+ if args[:azure_vm][:platform] == 'Linux'
198
+ extension.publisher = 'Microsoft.Azure.Extensions'
199
+ extension.virtual_machine_extension_type = 'CustomScript'
200
+ extension.type_handler_version = '2.0'
201
+ end
202
+ extension.auto_upgrade_minor_version = true
203
+ extension.location = args[:azure_vm][:location].gsub(/\s+/, '').downcase
204
+ extension.settings = {
205
+ 'commandToExecute' => args[:azure_vm][:script_command],
206
+ 'fileUris' => args[:azure_vm][:script_uris].split(',')
207
+ }
208
+ sdk.create_or_update_vm_extensions(args[:azure_vm][:resource_group],
209
+ args[:azure_vm][:vm_name],
210
+ 'ForemanCustomScript',
211
+ extension)
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end
@@ -1,11 +1,25 @@
1
+ # This Model contains code modified as per azure-sdk
2
+ # and removed dependencies from fog-azure-rm.
3
+ #
4
+ require 'base64'
5
+
1
6
  module ForemanAzureRM
2
7
  class AzureRM < ComputeResource
8
+
9
+ include VMExtensions::ManagedVM
3
10
  alias_attribute :sub_id, :user
4
11
  alias_attribute :secret_key, :password
5
12
  alias_attribute :app_ident, :url
6
13
  alias_attribute :tenant, :uuid
7
14
 
8
- before_create :test_connection
15
+ validates :user, :presence => true
16
+ validates :password, :presence => true
17
+ validates :url, :presence => true
18
+ validates :uuid, :presence => true
19
+
20
+ has_one :key_pair, :foreign_key => :compute_resource_id, :dependent => :destroy
21
+
22
+ before_create :test_connection, :setup_key_pair
9
23
 
10
24
  class VMContainer
11
25
  attr_accessor :virtualmachines
@@ -19,6 +33,10 @@ module ForemanAzureRM
19
33
  end
20
34
  end
21
35
 
36
+ def sdk
37
+ @sdk ||= ForemanAzureRM::AzureSDKAdapter.new(tenant, app_ident, secret_key, sub_id)
38
+ end
39
+
22
40
  def to_label
23
41
  "#{name} (#{provider_friendly_name})"
24
42
  end
@@ -35,8 +53,9 @@ module ForemanAzureRM
35
53
  [:image]
36
54
  end
37
55
 
38
- def locations
56
+ def regions
39
57
  [
58
+ 'West Europe',
40
59
  'Central US',
41
60
  'South Central US',
42
61
  'North Central US',
@@ -48,34 +67,41 @@ module ForemanAzureRM
48
67
  ]
49
68
  end
50
69
 
51
- def resource_groups
52
- rgs = rg_client.list_resource_groups
53
- rg_names = []
54
- rgs.each do |rg|
55
- rg_names << rg.name
56
- end
57
- rg_names
58
- end
59
-
60
- def available_resource_groups
61
- rg_client.list_resource_groups
62
- end
63
-
64
- def storage_accts(location = nil)
65
- stripped_location = location.gsub(/\s+/, '').downcase
70
+ def storage_accts(region = nil)
71
+ stripped_region = region.gsub(/\s+/, '').downcase
66
72
  acct_names = []
67
- if location.nil?
68
- storage_client.list_storage_accounts.each do |acct|
73
+ if region.nil?
74
+ sdk.get_storage_accts.each do |acct|
69
75
  acct_names << acct.name
70
76
  end
71
77
  else
72
- (storage_client.list_storage_accounts.select { |acct| acct.location == stripped_location }).each do |acct|
78
+ (sdk.get_storage_accts.select { |acct| acct.region == stripped_region }).each do |acct|
73
79
  acct_names << acct.name
74
80
  end
75
81
  end
76
82
  acct_names
77
83
  end
78
84
 
85
+ def resource_groups
86
+ sdk.rgs
87
+ end
88
+
89
+ def test_connection(options = {})
90
+ sdk.rgs.each do |rg|
91
+ puts "#{rg}"
92
+ end
93
+ super(options)
94
+ end
95
+
96
+ def new_vm(attr = {})
97
+ AzureRMCompute.new(sdk: sdk)
98
+ end
99
+
100
+ def stop
101
+ power_off
102
+ deallocate
103
+ end
104
+
79
105
  def provided_attributes
80
106
  super.merge({ :ip => :provisioning_ip_address })
81
107
  end
@@ -98,226 +124,144 @@ module ForemanAzureRM
98
124
  subnets
99
125
  end
100
126
 
101
- # TODO Delete this
102
- def networks
103
- subnets
104
- end
105
-
106
- def virtual_networks(location = nil)
107
- if location.nil?
108
- azure_network_service.virtual_networks
127
+ def virtual_networks(region = nil)
128
+ if region.nil?
129
+ sdk.vnets
109
130
  else
110
- stripped_location = location.gsub(/\s+/, '').downcase
111
- azure_network_service.virtual_networks.select { |vnet| vnet.location == stripped_location }
131
+ stripped_region = region.gsub(/\s+/, '').downcase
132
+ sdk.vnets.select { |vnet| vnet.location == stripped_region }
112
133
  end
113
134
  end
114
135
 
115
- def subnets(location = nil)
116
- vnets = virtual_networks(location)
136
+ def subnets(region = nil)
137
+ stripped_region = region.gsub(/\s+/, '').downcase
138
+ vnets = virtual_networks(stripped_region)
117
139
  subnets = []
118
140
  vnets.each do |vnet|
119
- subnets.concat(azure_network_service.subnets(resource_group: vnet.resource_group,
120
- virtual_network_name: vnet.name).all)
141
+ subnets.concat(sdk.subnets(vnet.resource_group, vnet.name))
121
142
  end
122
143
  subnets
123
144
  end
124
145
 
125
- def test_connection(options = {})
126
- rg_client.resource_groups.each do |rg|
127
- puts "#{rg.name}"
128
- end
129
- super(options)
146
+ def new_interface(attr = {})
147
+ # WIP
148
+ # calls nic_cards method in adapter
149
+ # causes compute profiles issue
150
+ # NetworkModels::NetworkInterface.new
130
151
  end
131
152
 
132
- def new_interface(attr = {})
133
- azure_network_service.network_interfaces.new(attr)
153
+ def vm_sizes(region)
154
+ sdk.list_vm_sizes(region)
134
155
  end
135
156
 
136
- def new_volume(attr = {})
137
- client.managed_disks.new(attr)
157
+ def vm_instance_defaults
158
+ ActiveSupport::HashWithIndifferentAccess.new
138
159
  end
139
160
 
140
161
  def vms
141
162
  container = VMContainer.new
142
- rg_client.resource_groups.each do |rg|
143
- client.servers(resource_group: rg.name).each do |vm|
144
- container.virtualmachines << vm
163
+ # Load all vms
164
+ resource_groups.each do |rg|
165
+ sdk.list_vms(rg).each do |vm|
166
+ container.virtualmachines << AzureRMCompute.new(azure_vm: vm, sdk:sdk)
145
167
  end
146
168
  end
147
169
  container
148
170
  end
149
171
 
150
- def vm_sizes(location)
151
- client.list_available_sizes(location)
172
+ def setup_key_pair
173
+ require 'sshkey'
174
+ name = "foreman-#{id}#{Foreman.uuid}"
175
+ key = ::SSHKey.generate
176
+ build_key_pair :name => name, :secret => key.private_key, :public => key.ssh_public_key
152
177
  end
153
178
 
154
179
  def find_vm_by_uuid(uuid)
155
- # TODO: Find a better way to handle this than loading and sorting through
156
- # all VMs, which also requires that names be globally unique, instead of
157
- # unique within a resource group
158
180
  vm = vms.all.find { |vm| vm.name == uuid }
159
181
  raise ActiveRecord::RecordNotFound unless vm.present?
160
182
  vm
161
183
  end
162
184
 
163
- def create_nics(args = {})
164
- nics = []
165
- formatted_location = args[:location].gsub(/\s+/, '').downcase
166
- args[:interfaces_attributes].each do |nic, attrs|
167
- attrs[:pubip_alloc] = attrs[:bridge]
168
- attrs[:privip_alloc] = (attrs[:name] == 'false') ? false : true
169
- pip_alloc = case attrs[:pubip_alloc]
170
- when 'Static'
171
- Fog::ARM::Network::Models::IPAllocationMethod::Static
172
- when 'Dynamic'
173
- Fog::ARM::Network::Models::IPAllocationMethod::Dynamic
174
- when 'None'
175
- nil
176
- end
177
- priv_ip_alloc = if attrs[:priv_ip_alloc]
178
- Fog::ARM::Network::Models::IPAllocationMethod::Static
179
- else
180
- Fog::ARM::Network::Models::IPAllocationMethod::Dynamic
181
- end
182
- if pip_alloc.present?
183
- pip = azure_network_service.public_ips.create(
184
- name: "#{args[:vm_name]}-pip#{nic}",
185
- resource_group: args[:resource_group],
186
- location: formatted_location,
187
- public_ip_allocation_method: pip_alloc
188
- )
189
- end
190
- new_nic = azure_network_service.network_interfaces.create(
191
- name: "#{args[:vm_name]}-nic#{nic}",
192
- resource_group: args[:resource_group],
193
- location: formatted_location,
194
- subnet_id: attrs[:network],
195
- public_ip_address_id: pip.present? ? pip.id : nil,
196
- ip_configuration_name: 'ForemanIPConfiguration',
197
- private_ip_allocation_method: priv_ip_alloc
198
- )
199
- nics << new_nic
200
- end
201
- nics
185
+ # user data support
186
+ def user_data_supported?
187
+ true
202
188
  end
203
189
 
204
- # Preferred behavior is to utilize Fog but Fog Azure RM
205
- # does not currently support creating managed VMs
206
190
  def create_vm(args = {})
207
- args[:vm_name] = args[:name].split('.')[0]
208
- nics = create_nics(args)
209
- if args[:ssh_key_data].present?
191
+ args[:azure_vm][:vm_name] = args[:name].split('.')[0]
192
+ nics = create_nics(args)
193
+ if args[:azure_vm][:password].present? && !args[:azure_vm][:ssh_key_data].present?
194
+ sudoers_cmd = "$echo #{args[:azure_vm][:password]} | sudo -S echo '\"#{args[:azure_vm][:username]}\" ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/waagent"
195
+ if args[:azure_vm][:script_command].present?
196
+ # to run the script_cmd given through form
197
+ # as username
198
+ args[:azure_vm][:script_command] = sudoers_cmd + " ; su - \"#{args[:azure_vm][:username]}\" -c \"#{args[:azure_vm][:script_command]}\""
199
+ else
200
+ args[:azure_vm][:script_command] = sudoers_cmd
201
+ end
202
+ disable_password_auth = false
203
+ elsif args[:azure_vm][:ssh_key_data].present? && !args[:azure_vm][:password].present?
210
204
  disable_password_auth = true
211
- ssh_key_path = "/home/#{args[:username]}/.ssh/authorized_keys"
212
205
  else
213
206
  disable_password_auth = false
214
- ssh_key_path = nil
215
207
  end
216
- vm = client.create_managed_virtual_machine(
217
- name: args[:vm_name],
218
- location: args[:location],
219
- resource_group: args[:resource_group],
220
- vm_size: args[:vm_size],
221
- username: args[:username],
222
- password: args[:password],
223
- ssh_key_data: args[:ssh_key_data],
224
- ssh_key_path: ssh_key_path,
225
- disable_password_authentication: disable_password_auth,
226
- network_interface_card_ids: nics.map(&:id),
227
- platform: args[:platform],
228
- vhd_path: args[:image_id],
229
- os_disk_caching: args[:os_disk_caching],
230
- data_disks: args[:volumes_attributes],
231
- os_disk_size: args[:os_disk_size],
232
- premium_os_disk: args[:premium_os_disk],
208
+ vm = create_managed_virtual_machine(
209
+ name: args[:azure_vm][:vm_name],
210
+ location: args[:azure_vm][:location],
211
+ resource_group: args[:azure_vm][:resource_group],
212
+ vm_size: args[:azure_vm][:vm_size],
213
+ username: args[:azure_vm][:username],
214
+ password: args[:azure_vm][:password],
215
+ ssh_key_data: args[:azure_vm][:ssh_key_data],
216
+ disable_password_authentication: disable_password_auth,
217
+ network_interface_card_ids: nics.map(&:id),
218
+ platform: args[:azure_vm][:platform],
219
+ vhd_path: args[:image_id],
220
+ os_disk_caching: args[:azure_vm][:os_disk_caching],
221
+ premium_os_disk: args[:azure_vm][:premium_os_disk],
222
+ custom_data: args[:user_data],
223
+ script_command: args[:azure_vm][:script_command],
224
+ script_uris: args[:azure_vm][:script_uris],
233
225
  )
234
- vm_hash = Fog::Compute::AzureRM::Server.parse(vm)
235
- vm_hash[:password] = args[:password]
236
- vm_hash[:platform] = args[:platform]
237
- vm_hash[:puppet_master] = args[:puppet_master]
238
- vm_hash[:script_command] = args[:script_command]
239
- vm_hash[:script_uris] = args[:script_uris]
240
- client.create_vm_extension(vm_hash)
241
- client.servers.new vm_hash
242
- # fog-azure-rm raises all ARM errors as RuntimeError
243
- rescue Fog::Errors::Error, RuntimeError => e
226
+ create_vm_extension(args)
227
+ # return the vm object using azure_vm
228
+ return_vm = AzureRMCompute.new(azure_vm: vm, sdk: sdk)
229
+ rescue RuntimeError => e
244
230
  Foreman::Logging.exception('Unhandled Azure RM error', e)
245
231
  destroy_vm vm.id if vm
246
232
  raise e
247
233
  end
248
234
 
249
235
  def destroy_vm(uuid)
236
+ #vm.azure_vm because that's the azure object and vm is the wrapper
250
237
  vm = find_vm_by_uuid(uuid)
251
- raw_model = client.get_virtual_machine(vm.resource_group, vm.name)
252
- os_disk_name = raw_model.storage_profile.os_disk.name
253
- data_disks = raw_model.storage_profile.data_disks
238
+ vm_name = vm.name
239
+ rg_name = vm.azure_vm.resource_group
240
+ os_disk = vm.azure_vm.storage_profile.os_disk
241
+ data_disks = vm.azure_vm.storage_profile.data_disks
254
242
  nic_ids = vm.network_interface_card_ids
255
- # In ARM things must be deleted in order
256
- vm.destroy
257
- nic_ids.each do |id|
258
- nic = azure_network_service.network_interfaces.get(id.split('/')[4],
259
- id.split('/')[-1])
260
- ip_id = nic.public_ip_address_id
261
- nic.destroy
262
- if ip_id.present?
263
- azure_network_service.public_ips.get(ip_id.split('/')[4],
264
- ip_id.split('/')[-1]).destroy
243
+
244
+ sdk.delete_vm(rg_name, vm_name)
245
+
246
+ nic_ids.each do |nic_id|
247
+ nic = sdk.vm_nic(rg_name, nic_id.split('/')[-1])
248
+ if nic.present?
249
+ public_ip = nic.ip_configurations.first.public_ipaddress
250
+ sdk.delete_nic(rg_name, nic_id.split('/')[-1])
251
+ if public_ip.present?
252
+ ip_id = public_ip.id
253
+ sdk.delete_pip(rg_name, ip_id.split('/')[-1])
254
+ end
265
255
  end
266
256
  end
267
- client.managed_disks.get(vm.resource_group, os_disk_name).destroy
268
- data_disks.each do |disk|
269
- client.managed_disks.get(vm.resource_group, disk.name).destroy
257
+ if os_disk.present?
258
+ sdk.delete_disk(rg_name, os_disk.name)
270
259
  end
271
260
 
261
+ true
272
262
  rescue ActiveRecord::RecordNotFound
273
- # If the VM does not exist, we don't really care.
263
+ logger.info "Could not find the selected vm."
274
264
  true
275
265
  end
276
-
277
- protected
278
-
279
- def client
280
- @client ||= Fog::Compute.new(
281
- :provider => 'AzureRM',
282
- :tenant_id => tenant,
283
- :client_id => app_ident,
284
- :client_secret => secret_key,
285
- :subscription_id => sub_id,
286
- :environment => 'AzureCloud'
287
- )
288
- end
289
-
290
- def rg_client
291
- # noinspection RubyArgCount
292
- @rg_client ||= Fog::Resources::AzureRM.new(
293
- tenant_id: tenant,
294
- client_id: app_ident,
295
- client_secret: secret_key,
296
- subscription_id: sub_id,
297
- :environment => 'AzureCloud'
298
- )
299
- end
300
-
301
- def storage_client
302
- @storage_client ||= Fog::Storage.new(
303
- :provider => 'AzureRM',
304
- :tenant_id => tenant,
305
- :client_id => app_ident,
306
- :client_secret => secret_key,
307
- :subscription_id => sub_id,
308
- :environment => 'AzureCloud'
309
- )
310
- end
311
-
312
- def azure_network_service
313
- # noinspection RubyArgCount
314
- @azure_network_service ||= Fog::Network::AzureRM.new(
315
- :tenant_id => tenant,
316
- :client_id => app_ident,
317
- :client_secret => secret_key,
318
- :subscription_id => sub_id,
319
- :environment => 'AzureCloud'
320
- )
321
- end
322
266
  end
323
- end
267
+ end