foreman_azure_rm 2.0.0.pre1 → 2.0.1

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
2
  SHA256:
3
- metadata.gz: 8cdbc28091795bf21377b298699209cc2a0d06365858d117b9468a466fb0ffe2
4
- data.tar.gz: 938f88f1ac6e6f9d9101ce57d2bf187e5c1196fd4abf68c667ae38db5c3270e2
3
+ metadata.gz: 3a507325a26003d06dcc112040e5915d39306b9681ec21253e618da875846e56
4
+ data.tar.gz: 771298a3fc115f85b24d90198ba53a5a093e85661d4aa4da958c6a01ea437b3e
5
5
  SHA512:
6
- metadata.gz: c4def716d7fa2719d629c0bb9029a60e079e5578c16a33c9baa624462e3da7cdf634fa8f64070fef86bd4b615f9bccafedb427f073facad2a3e5f021bb74eedc
7
- data.tar.gz: e2dbb0b84df8d5d7a62fa87486b858c5ee11cd28dcdf072ada26cbd77036942837f92f699e7738f40378cc839d0fde9cfc113d53c846b5af84af17dec14f78f4
6
+ metadata.gz: f29267ea139f9e9fb18697dc828d33ea30c0d5fcd433b21be427ec93912d5113b4278fbfd6ffb9282d2ad05f5d3142047b11e4b912afdb3bb5e454019599c968
7
+ data.tar.gz: 5603751a843f247708743e8e639b27575080ac2c709c2efbd77c591805d14713c8c3a5995610c9162f6b6c7c2d23a6f7f015204dab0641e34079c0a49a9ae69c
@@ -3,6 +3,15 @@ module ForemanAzureRM
3
3
  module ComputeResourcesControllerExtensions
4
4
  include Api::Version2
5
5
  include Foreman::Controller::Parameters::ComputeResource
6
+ extend ::Apipie::DSL::Concern
7
+ update_api(:create, :update) do
8
+ param :compute_resource, Hash do
9
+ # Not adding :tenant as already specified in core.
10
+ param :app_ident, String, :desc => N_("Client ID for AzureRM")
11
+ param :secret_key, String, :desc => N_("Client Secret for AzureRM")
12
+ param :sub_id, String, :desc => N_("Subscription ID for AzureRM")
13
+ end
14
+ end
6
15
 
7
16
  def available_resource_groups
8
17
  compute_resource = ComputeResource.find_by_id(params[:id])
@@ -1,11 +1,12 @@
1
1
  module ForemanAzureRM
2
2
  module Concerns
3
3
  module HostsControllerExtensions
4
+ extend ActiveSupport::Concern
4
5
 
5
6
  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[:region_string]).map { |size| size.name }
7
+ azure_rm_resource = ComputeResource.unscoped.find_by_id(params[:compute_resource_id])
8
+ if azure_rm_resource.present?
9
+ render :json => azure_rm_resource.vm_sizes.map { |size| size.name }
9
10
  else
10
11
  no_sizes = _('The region you selected has no sizes associated with it')
11
12
  render :json => "[\"#{no_sizes}\"]"
@@ -13,10 +14,9 @@ module ForemanAzureRM
13
14
  end
14
15
 
15
16
  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[:region])
17
+ azure_rm_resource = ComputeResource.unscoped.find_by_id(params[:compute_resource_id])
18
+ if azure_rm_resource.present?
19
+ subnets = azure_rm_resource.subnets
20
20
  if subnets.present?
21
21
  render :json => subnets
22
22
  else
@@ -35,7 +35,7 @@ module ForemanAzureRM
35
35
  os_disk.managed_disk = managed_disk_params
36
36
  storage_profile.os_disk = os_disk
37
37
 
38
- # Currently eliminating data disk creation since capability does not exist.
38
+ # TODO - disk creation for volume capability
39
39
 
40
40
  if vhd_path.nil?
41
41
  # We are using a marketplace image
@@ -72,45 +72,44 @@ module ForemanAzureRM
72
72
  network_profile
73
73
  end
74
74
 
75
- def create_nics(args = {})
75
+ def create_nics(region, args = {})
76
76
  nics = []
77
- formatted_region = args[:azure_vm][:location].gsub(/\s+/, '').downcase
78
77
  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?
78
+ private_ip = (attrs[:private_ip] == 'false') ? false : true
79
+ priv_ip_alloc = if private_ip
80
+ NetworkModels::IPAllocationMethod::Static
81
+ else
82
+ NetworkModels::IPAllocationMethod::Dynamic
83
+ end
84
+ pub_ip_alloc = case attrs[:public_ip]
85
+ when 'Static'
86
+ NetworkModels::IPAllocationMethod::Static
87
+ when 'Dynamic'
88
+ NetworkModels::IPAllocationMethod::Dynamic
89
+ when 'None'
90
+ nil
91
+ end
92
+ if pub_ip_alloc.present?
95
93
  public_ip_params = NetworkModels::PublicIPAddress.new.tap do |ip|
96
- ip.location = formatted_region
97
- ip.public_ipallocation_method = pip_alloc
94
+ ip.location = region
95
+ ip.public_ipallocation_method = pub_ip_alloc
98
96
  end
99
- pip = sdk.create_or_update_pip(args[:azure_vm][:resource_group],
100
- "#{args[:azure_vm][:vm_name]}-pip#{nic}",
97
+
98
+ pip = sdk.create_or_update_pip(args[:resource_group],
99
+ "#{args[:vm_name]}-pip#{nic}",
101
100
  public_ip_params)
102
101
  end
103
102
  new_nic = sdk.create_or_update_nic(
104
- args[:azure_vm][:resource_group],
105
- "#{args[:azure_vm][:vm_name]}-nic#{nic}",
103
+ args[:resource_group],
104
+ "#{args[:vm_name]}-nic#{nic}",
106
105
  NetworkModels::NetworkInterface.new.tap do |interface|
107
- interface.location = formatted_region
106
+ interface.location = region
108
107
  interface.ip_configurations = [
109
108
  NetworkModels::NetworkInterfaceIPConfiguration.new.tap do |nic_conf|
110
- nic_conf.name = "#{args[:azure_vm][:vm_name]}-nic#{nic}"
109
+ nic_conf.name = "#{args[:vm_name]}-nic#{nic}"
111
110
  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
111
+ nic_conf.subnet = subnets.select{ |subnet| subnet.id == attrs[:network] }.first
112
+ nic_conf.public_ipaddress = pip
114
113
  end
115
114
  ]
116
115
  end
@@ -120,7 +119,7 @@ module ForemanAzureRM
120
119
  nics
121
120
  end
122
121
 
123
- def create_managed_virtual_machine(vm_hash)
122
+ def initialize_vm(vm_hash)
124
123
  custom_data = vm_hash[:custom_data]
125
124
  msg = "Creating Virtual Machine #{vm_hash[:name]} in Resource Group #{vm_hash[:resource_group]}."
126
125
  logger.debug msg
@@ -183,30 +182,34 @@ module ForemanAzureRM
183
182
  vm.hardware_profile = ComputeModels::HardwareProfile.new.tap do |hw_profile|
184
183
  hw_profile.vm_size = vm_hash[:vm_size]
185
184
  end
186
- vm.network_profile = define_network_profile(vm_hash[:network_interface_card_ids])
187
185
  end
188
186
 
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
187
+ vm_create_params
188
+ end
189
+
190
+ def create_managed_virtual_machine(vm_hash)
191
+ vm_params = initialize_vm(vm_hash)
192
+ vm_params.network_profile = define_network_profile(vm_hash[:network_interface_card_ids])
193
+ sdk.create_or_update_vm(vm_hash[:resource_group], vm_hash[:name], vm_params)
192
194
  end
193
195
 
194
- def create_vm_extension(args = {})
195
- if args[:azure_vm][:script_command].present? || args[:azure_vm][:script_uris].present?
196
+ def create_vm_extension(region, args = {})
197
+ if args[:script_command].present? || args[:script_uris].present?
198
+ args[:script_uris] ||= args[:script_uris].to_s
196
199
  extension = ComputeModels::VirtualMachineExtension.new
197
- if args[:azure_vm][:platform] == 'Linux'
200
+ if args[:platform] == 'Linux'
198
201
  extension.publisher = 'Microsoft.Azure.Extensions'
199
202
  extension.virtual_machine_extension_type = 'CustomScript'
200
203
  extension.type_handler_version = '2.0'
201
204
  end
202
205
  extension.auto_upgrade_minor_version = true
203
- extension.location = args[:azure_vm][:location].gsub(/\s+/, '').downcase
206
+ extension.location = region
204
207
  extension.settings = {
205
- 'commandToExecute' => args[:azure_vm][:script_command],
206
- 'fileUris' => args[:azure_vm][:script_uris].split(',')
208
+ 'commandToExecute' => args[:script_command],
209
+ 'fileUris' => args[:script_uris].split(',')
207
210
  }
208
- sdk.create_or_update_vm_extensions(args[:azure_vm][:resource_group],
209
- args[:azure_vm][:vm_name],
211
+ sdk.create_or_update_vm_extensions(args[:resource_group],
212
+ args[:vm_name],
210
213
  'ForemanCustomScript',
211
214
  extension)
212
215
  end
@@ -1,6 +1,6 @@
1
1
  # This Model contains code modified as per azure-sdk
2
2
  # and removed dependencies from fog-azure-rm.
3
- #
3
+
4
4
  require 'base64'
5
5
 
6
6
  module ForemanAzureRM
@@ -9,13 +9,10 @@ module ForemanAzureRM
9
9
  include VMExtensions::ManagedVM
10
10
  alias_attribute :sub_id, :user
11
11
  alias_attribute :secret_key, :password
12
- alias_attribute :app_ident, :url
12
+ alias_attribute :region, :url
13
13
  alias_attribute :tenant, :uuid
14
14
 
15
- validates :user, :presence => true
16
- validates :password, :presence => true
17
- validates :url, :presence => true
18
- validates :uuid, :presence => true
15
+ validates :user, :password, :url, :uuid, :app_ident, :presence => true
19
16
 
20
17
  has_one :key_pair, :foreign_key => :compute_resource_id, :dependent => :destroy
21
18
 
@@ -23,6 +20,7 @@ module ForemanAzureRM
23
20
 
24
21
  class VMContainer
25
22
  attr_accessor :virtualmachines
23
+ delegate :each, to: :virtualmachines
26
24
 
27
25
  def initialize
28
26
  @virtualmachines = []
@@ -33,6 +31,14 @@ module ForemanAzureRM
33
31
  end
34
32
  end
35
33
 
34
+ def app_ident
35
+ attrs[:app_ident]
36
+ end
37
+
38
+ def app_ident=(name)
39
+ attrs[:app_ident] = name
40
+ end
41
+
36
42
  def sdk
37
43
  @sdk ||= ForemanAzureRM::AzureSDKAdapter.new(tenant, app_ident, secret_key, sub_id)
38
44
  end
@@ -45,7 +51,7 @@ module ForemanAzureRM
45
51
  ComputeResource.model_name
46
52
  end
47
53
 
48
- def provider_friendly_name
54
+ def self.provider_friendly_name
49
55
  'Azure Resource Manager'
50
56
  end
51
57
 
@@ -55,33 +61,18 @@ module ForemanAzureRM
55
61
 
56
62
  def regions
57
63
  [
58
- 'West Europe',
59
- 'Central US',
60
- 'South Central US',
61
- 'North Central US',
62
- 'West Central US',
63
- 'East US',
64
- 'East US 2',
65
- 'West US',
66
- 'West US 2'
64
+ ['West Europe', 'westeurope'],
65
+ ['Central US', 'centralus'],
66
+ ['South Central US', 'southcentralus'],
67
+ ['North Central US', 'northcentralus'],
68
+ ['West Central US', 'westcentralus'],
69
+ ['East US', 'eastus'],
70
+ ['East US 2', 'eastus2'],
71
+ ['West US', 'westus'],
72
+ ['West US 2', 'westus2']
67
73
  ]
68
74
  end
69
75
 
70
- def storage_accts(region = nil)
71
- stripped_region = region.gsub(/\s+/, '').downcase
72
- acct_names = []
73
- if region.nil?
74
- sdk.get_storage_accts.each do |acct|
75
- acct_names << acct.name
76
- end
77
- else
78
- (sdk.get_storage_accts.select { |acct| acct.region == stripped_region }).each do |acct|
79
- acct_names << acct.name
80
- end
81
- end
82
- acct_names
83
- end
84
-
85
76
  def resource_groups
86
77
  sdk.rgs
87
78
  end
@@ -93,25 +84,39 @@ module ForemanAzureRM
93
84
  super(options)
94
85
  end
95
86
 
96
- def new_vm(attr = {})
97
- AzureRMCompute.new(sdk: sdk)
98
- end
99
-
100
- def stop
101
- power_off
102
- deallocate
87
+ def new_vm(args = {})
88
+ return AzureRMCompute.new(sdk: sdk) if args.empty? || args[:image_id].nil?
89
+ opts = vm_instance_defaults.merge(args.to_h).deep_symbolize_keys
90
+ # convert rails nested_attributes into a plain hash
91
+ nested_args = opts.delete(:interfaces_attributes)
92
+ opts[:interfaces] = nested_attributes_for(:interfaces, nested_args) if nested_args
93
+
94
+ opts.reject! { |k, v| v.nil? }
95
+
96
+ raw_vm = initialize_vm(location: region,
97
+ resource_group: opts[:resource_group],
98
+ vm_size: opts[:vm_size],
99
+ username: opts[:username],
100
+ password: opts[:password],
101
+ platform: opts[:platform],
102
+ ssh_key_data: opts[:ssh_key_data],
103
+ os_disk_caching: opts[:os_disk_caching],
104
+ vhd_path: opts[:image_id],
105
+ premium_os_disk: opts[:premium_os_disk]
106
+ )
107
+ if opts[:interfaces].present?
108
+ ifaces = []
109
+ opts[:interfaces].each_with_index do |iface_attrs, i|
110
+ ifaces << new_interface(iface_attrs)
111
+ end
112
+ end
113
+ AzureRMCompute.new(azure_vm: raw_vm ,sdk: sdk, resource_group: opts[:resource_group], nics: ifaces)
103
114
  end
104
115
 
105
116
  def provided_attributes
106
117
  super.merge({ :ip => :provisioning_ip_address })
107
118
  end
108
119
 
109
- def host_interfaces_attrs(host)
110
- host.interfaces.select(&:physical?).each.with_index.reduce({}) do |hash, (nic, index)|
111
- hash.merge(index.to_s => nic.compute_attributes.merge(ip: nic.ip, ip6: nic.ip6))
112
- end
113
- end
114
-
115
120
  def available_vnets(attr = {})
116
121
  virtual_networks
117
122
  end
@@ -120,22 +125,12 @@ module ForemanAzureRM
120
125
  subnets
121
126
  end
122
127
 
123
- def available_subnets
124
- subnets
125
- end
126
-
127
- def virtual_networks(region = nil)
128
- if region.nil?
129
- sdk.vnets
130
- else
131
- stripped_region = region.gsub(/\s+/, '').downcase
132
- sdk.vnets.select { |vnet| vnet.location == stripped_region }
133
- end
128
+ def virtual_networks
129
+ @virtual_networks ||= sdk.vnets.select { |vnet| vnet.location == region }
134
130
  end
135
131
 
136
- def subnets(region = nil)
137
- stripped_region = region.gsub(/\s+/, '').downcase
138
- vnets = virtual_networks(stripped_region)
132
+ def subnets
133
+ vnets = virtual_networks
139
134
  subnets = []
140
135
  vnets.each do |vnet|
141
136
  subnets.concat(sdk.subnets(vnet.resource_group, vnet.name))
@@ -143,28 +138,46 @@ module ForemanAzureRM
143
138
  subnets
144
139
  end
145
140
 
146
- def new_interface(attr = {})
147
- # WIP
148
- # calls nic_cards method in adapter
149
- # causes compute profiles issue
150
- # NetworkModels::NetworkInterface.new
141
+ alias_method :available_subnets, :subnets
142
+
143
+ def new_interface(attrs = {})
144
+ args = { :network => "", :public_ip => "", :private_ip => false, 'persisted?' => false }.merge(attrs.to_h)
145
+ OpenStruct.new(args)
146
+ end
147
+
148
+ def editable_network_interfaces?
149
+ true
151
150
  end
152
151
 
153
- def vm_sizes(region)
152
+ def vm_sizes
154
153
  sdk.list_vm_sizes(region)
155
154
  end
156
155
 
156
+ def associated_host(vm)
157
+ associate_by("ip", [vm.public_ip_address, vm.private_ip_address])
158
+ end
159
+
157
160
  def vm_instance_defaults
158
- ActiveSupport::HashWithIndifferentAccess.new
161
+ super.deep_merge(
162
+ interfaces: [new_interface]
163
+ )
164
+ end
165
+
166
+ def vm_nics(vm)
167
+ ifaces = []
168
+ vm.network_profile.network_interfaces.each do |nic|
169
+ nic_rg = (split_nic_id = nic.id.split('/'))[4]
170
+ nic_name = split_nic_id[-1]
171
+ ifaces << sdk.vm_nic(nic_rg, nic_name)
172
+ end
173
+ ifaces
159
174
  end
160
175
 
161
- def vms
176
+ def vms(attrs = {})
162
177
  container = VMContainer.new
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)
167
- end
178
+ # Load all vms of the region
179
+ sdk.list_vms(region).each do |vm|
180
+ container.virtualmachines << AzureRMCompute.new(azure_vm: vm, sdk:sdk, nics: vm_nics(vm))
168
181
  end
169
182
  container
170
183
  end
@@ -188,44 +201,46 @@ module ForemanAzureRM
188
201
  end
189
202
 
190
203
  def create_vm(args = {})
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]}\""
204
+ args = args.to_h.deep_symbolize_keys
205
+ args[:vm_name] = args[:name].split('.')[0]
206
+ nics = create_nics(region, args)
207
+ if args[:password].present? && !args[:ssh_key_data].present?
208
+ sudoers_cmd = "$echo #{args[:password]} | sudo -S echo '\"#{args[:username]}\" ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/waagent"
209
+ if args[:script_command].present?
210
+ # to run the script_cmd given through form as username
211
+ args[:script_command] = sudoers_cmd + " ; su - \"#{args[:username]}\" -c \"#{args[:script_command]}\""
199
212
  else
200
- args[:azure_vm][:script_command] = sudoers_cmd
213
+ args[:script_command] = sudoers_cmd
201
214
  end
202
215
  disable_password_auth = false
203
- elsif args[:azure_vm][:ssh_key_data].present? && !args[:azure_vm][:password].present?
216
+ elsif args[:ssh_key_data].present? && !args[:password].present?
204
217
  disable_password_auth = true
205
218
  else
206
219
  disable_password_auth = false
207
220
  end
221
+
208
222
  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],
223
+ name: args[:vm_name],
224
+ location: region,
225
+ resource_group: args[:resource_group],
226
+ vm_size: args[:vm_size],
227
+ username: args[:username],
228
+ password: args[:password],
229
+ ssh_key_data: args[:ssh_key_data],
216
230
  disable_password_authentication: disable_password_auth,
217
231
  network_interface_card_ids: nics.map(&:id),
218
- platform: args[:azure_vm][:platform],
232
+ platform: args[:platform],
219
233
  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],
234
+ os_disk_caching: args[:os_disk_caching],
235
+ premium_os_disk: args[:premium_os_disk],
222
236
  custom_data: args[:user_data],
223
- script_command: args[:azure_vm][:script_command],
224
- script_uris: args[:azure_vm][:script_uris],
237
+ script_command: args[:script_command],
238
+ script_uris: args[:script_uris],
225
239
  )
226
- create_vm_extension(args)
240
+ logger.debug "Virtual Machine #{args[:vm_name]} Created Successfully."
241
+ create_vm_extension(region, args)
227
242
  # return the vm object using azure_vm
228
- return_vm = AzureRMCompute.new(azure_vm: vm, sdk: sdk)
243
+ AzureRMCompute.new(azure_vm: vm, sdk: sdk, resource_group: args[:resource_group], nics: vm_nics(vm))
229
244
  rescue RuntimeError => e
230
245
  Foreman::Logging.exception('Unhandled Azure RM error', e)
231
246
  destroy_vm vm.id if vm
@@ -233,15 +248,13 @@ module ForemanAzureRM
233
248
  end
234
249
 
235
250
  def destroy_vm(uuid)
236
- #vm.azure_vm because that's the azure object and vm is the wrapper
237
251
  vm = find_vm_by_uuid(uuid)
238
- vm_name = vm.name
239
- rg_name = vm.azure_vm.resource_group
252
+ rg_name = vm.resource_group
240
253
  os_disk = vm.azure_vm.storage_profile.os_disk
241
254
  data_disks = vm.azure_vm.storage_profile.data_disks
242
255
  nic_ids = vm.network_interface_card_ids
243
256
 
244
- sdk.delete_vm(rg_name, vm_name)
257
+ sdk.delete_vm(rg_name, vm.name)
245
258
 
246
259
  nic_ids.each do |nic_id|
247
260
  nic = sdk.vm_nic(rg_name, nic_id.split('/')[-1])
@@ -2,12 +2,29 @@ module ForemanAzureRM
2
2
  class AzureRMCompute
3
3
  attr_accessor :sdk
4
4
  attr_accessor :azure_vm
5
+ attr_accessor :resource_group
6
+ attr_accessor :nics
7
+ attr_accessor :image_id
5
8
 
6
9
  delegate :name, to: :azure_vm, allow_nil: true
7
10
 
8
- def initialize(azure_vm: ComputeModels::VirtualMachine.new, sdk: sdk)
11
+ def initialize(azure_vm: ComputeModels::VirtualMachine.new,
12
+ sdk: sdk,
13
+ resource_group: azure_vm.resource_group,
14
+ nics: [])
15
+
9
16
  @azure_vm = azure_vm
10
17
  @sdk = sdk
18
+ @resource_group ||= resource_group
19
+ @nics ||= nics
20
+ @azure_vm.hardware_profile ||= ComputeModels::HardwareProfile.new
21
+ @azure_vm.os_profile ||= ComputeModels::OSProfile.new
22
+ @azure_vm.os_profile.linux_configuration ||= ComputeModels::LinuxConfiguration.new
23
+ @azure_vm.os_profile.linux_configuration.ssh ||= ComputeModels::SshConfiguration.new
24
+ @azure_vm.os_profile.linux_configuration.ssh.public_keys ||= [ComputeModels::SshPublicKey.new]
25
+ @azure_vm.storage_profile ||= ComputeModels::StorageProfile.new
26
+ @azure_vm.storage_profile.os_disk ||= ComputeModels::OSDisk.new
27
+ @azure_vm.storage_profile.os_disk.managed_disk ||= ComputeModels::ManagedDiskParameters.new
11
28
  end
12
29
 
13
30
  def id
@@ -18,10 +35,6 @@ module ForemanAzureRM
18
35
  !!identity && !!id
19
36
  end
20
37
 
21
- def vm_size
22
- @azure_vm.hardware_profile.vm_size
23
- end
24
-
25
38
  def wait_for(_timeout = 0, _interval = 0, &block)
26
39
  instance_eval(&block)
27
40
  return true
@@ -35,46 +48,60 @@ module ForemanAzureRM
35
48
  vm_status
36
49
  end
37
50
 
51
+ def start
52
+ sdk.start_vm(@azure_vm.resource_group, name)
53
+ true
54
+ end
55
+
56
+ def stop
57
+ sdk.stop_vm(@azure_vm.resource_group, name)
58
+ true
59
+ end
60
+
38
61
  def vm_status
39
62
  sdk.check_vm_status(@azure_vm.resource_group, name)
40
63
  end
41
64
 
42
65
  def network_interface_card_ids
66
+ return nil unless @azure_vm.network_profile
43
67
  nics = @azure_vm.network_profile.network_interfaces
44
68
  nics.map(&:id)
45
69
  end
46
70
 
47
71
  def provisioning_ip_address
72
+ public_ip_address || private_ip_address
73
+ end
74
+
75
+ def public_ip_address
48
76
  interfaces.each do |nic|
49
77
  nic.ip_configurations.each do |configuration|
50
78
  next unless configuration.primary
51
- if configuration.public_ipaddress.present?
52
- ip_id = configuration.public_ipaddress.id
53
- ip_rg = ip_id.split('/')[4]
54
- ip_name = ip_id.split('/')[-1]
55
- public_ip = sdk.public_ip(ip_rg, ip_name)
56
- return public_ip.ip_address
57
- else
58
- return configuration.private_ipaddress
59
- end
79
+ return nil if configuration.public_ipaddress.blank?
80
+ ip_id = configuration.public_ipaddress.id
81
+ ip_rg = ip_id.split('/')[4]
82
+ ip_name = ip_id.split('/')[-1]
83
+ public_ip = sdk.public_ip(ip_rg, ip_name)
84
+ return public_ip.ip_address
60
85
  end
61
- end
86
+ end
62
87
  end
63
88
 
64
- def interfaces
65
- interfaces = []
66
- unless network_interface_card_ids.nil?
67
- network_interface_card_ids.each do |nic_id|
68
- nic_rg = nic_id.split('/')[4]
69
- nic_name = nic_id.split('/')[-1]
70
- interfaces << sdk.vm_nic(nic_rg, nic_name)
89
+ def private_ip_address
90
+ interfaces.each do |nic|
91
+ nic.ip_configurations.each do |configuration|
92
+ next unless configuration.primary
93
+ if configuration.private_ipaddress.present?
94
+ return private_ip_address = configuration.private_ipaddress
95
+ end
71
96
  end
72
97
  end
73
- interfaces
74
98
  end
75
99
 
76
- def interfaces=(setifaces)
77
- @azure_vm.network_profile.network_interfaces = setifaces
100
+ def interfaces
101
+ nics
102
+ end
103
+
104
+ def interfaces_attributes=(attrs)
78
105
  end
79
106
 
80
107
  def ip_addresses
@@ -89,7 +116,45 @@ module ForemanAzureRM
89
116
  @azure_vm.name = setuuid
90
117
  end
91
118
 
92
- def image_id
119
+ # Following properties are for AzureRM
120
+ # These are not part of Foreman's interface
121
+
122
+ def vm_size
123
+ @azure_vm.hardware_profile.vm_size
124
+ end
125
+
126
+ def platform
127
+ @azure_vm.storage_profile.os_disk.os_type
128
+ end
129
+
130
+ def username
131
+ @azure_vm.os_profile.admin_username
132
+ end
133
+
134
+ def password
135
+ @azure_vm.os_profile.admin_password
136
+ end
137
+
138
+ def ssh_key_data
139
+ # since you can only give one additional
140
+ # sshkey through foreman's UI
141
+ sshkey = @azure_vm.os_profile.linux_configuration.ssh.public_keys[1]
142
+ return unless sshkey.present?
143
+ sshkey.key_data
144
+ end
145
+
146
+ def premium_os_disk
147
+ @azure_vm.storage_profile.os_disk.managed_disk.storage_account_type
148
+ end
149
+
150
+ def os_disk_caching
151
+ @azure_vm.storage_profile.os_disk.caching
152
+ end
153
+
154
+ def script_command
155
+ end
156
+
157
+ def script_uris
93
158
  end
94
159
  end
95
160
  end
@@ -1 +1 @@
1
- attributes :user, :uuid
1
+ attributes :tenant, :app_ident, :sub_id, :secret_key, :region
@@ -1,8 +1,10 @@
1
- <%= text_f f, :url, :label => _('Client ID'), :required => true %>
1
+ <%= text_f f, :app_ident, :label => _('Client ID'), :required => true %>
2
2
  <%= password_f f, :password, :label => _('Client Secret'), :keep_value => true, :required => true %>
3
3
  <%= text_f f, :user, :label => _('Subscription ID'), :required => true %>
4
4
  <%= text_f f, :uuid, :label => _('Tenant ID'), :required => true %>
5
5
 
6
+ <%= selectable_f(f, :url, f.object.regions, {}, {:label => _('Azure Region'), :required => true }) %>
7
+
6
8
  <div class="col-md-offset-2">
7
9
  <%= test_connection_button_f(f, true) %>
8
10
  </div>
@@ -2,16 +2,17 @@
2
2
  os ||= nil
3
3
  images = possible_images(compute_resource, arch, os)
4
4
  resource_groups = compute_resource.resource_groups
5
+ compute_resource_id = compute_resource.id
5
6
  %>
6
7
 
7
- <script>
8
+ <script >
8
9
  function azure_rm_region_callback() {
9
10
  azure_rm_get_size_from_region();
10
11
  azure_rm_subnets_from_region();
11
12
  }
12
13
 
13
14
  function azure_rm_get_size_from_region() {
14
- var region = $('#azure_rm_region').val();
15
+ var compute_resource = <%=compute_resource_id%>;
15
16
  var size_spinner = $('#azure_rm_size_spinner');
16
17
  var sizes = $('#azure_rm_size');
17
18
  var imageId = $('#azure_rm_image_id').val();
@@ -22,7 +23,7 @@
22
23
  }
23
24
  size_spinner.removeClass('hide');
24
25
  $.ajax({
25
- data: {"region_string": region, "image_id": imageId},
26
+ data: {"image_id": imageId, "compute_resource_id": compute_resource},
26
27
  type: 'get',
27
28
  url: '/azure_rm/sizes',
28
29
  complete: function () {
@@ -50,14 +51,14 @@
50
51
  function azure_rm_subnets_from_region() {
51
52
  var imageId = $('#azure_rm_image_id').val();
52
53
  var subnets = $('#azure_rm_subnet');
53
- var region = $('#azure_rm_region').val();
54
+ var compute_resource = <%=compute_resource_id%>;
54
55
  if (typeof tfm == 'undefined') { // earlier than 1.13
55
56
  foreman.tools.showSpinner();
56
57
  } else {
57
58
  tfm.tools.showSpinner();
58
59
  }
59
60
  $.ajax({
60
- data: {"image_id": imageId, "region": region},
61
+ data: {"image_id": imageId, "compute_resource_id": compute_resource},
61
62
  type: 'get',
62
63
  url: '/azure_rm/subnets',
63
64
  complete: function () {
@@ -84,109 +85,102 @@
84
85
  }
85
86
  </script>
86
87
 
87
- <% #This view has been modified and wraps the properties of azure_vm
88
- # using fields_for rails method.
88
+ <% # This view has been modified and refers to the properties wrapper class %>
89
+
90
+ <%= selectable_f f, :resource_group, resource_groups,
91
+ { :include_blank => true },
92
+ {
93
+ :disabled => resource_groups.empty?,
94
+ :label => _('Resource Group'),
95
+ :required => true,
96
+ :id => 'azure_rm_rg',
97
+ :help_inline => spinner_button_f(f, _('Reload Images, Sizes, vNets'),
98
+ 'azure_rm_region_callback();',
99
+ {
100
+ :id => 'load_subnets_btn',
101
+ :spinner_id => 'load_subnets_indicator',
102
+ :class => 'btn-success',
103
+ :spinner_class => 'spinner-inverse'
104
+ })
105
+ }
89
106
  %>
90
107
 
91
- <%= f.fields_for :azure_vm do |vm_f| %>
108
+ <%= selectable_f f, :vm_size, compute_resource.vm_sizes.map { |size| size.name },
109
+ {},
110
+ {
111
+ :label => _('VM Size'),
112
+ :required => true,
113
+ :id => 'azure_rm_size'
114
+ }
115
+ %>
92
116
 
93
- <%= selectable_f vm_f, :location, compute_resource.regions,
94
- { :include_blank => _('Please select an Azure region') },
117
+ <%= selectable_f f, :platform, %w(Linux Windows),
118
+ {},
95
119
  {
96
- :label => _('Azure Region'),
97
- :required => true,
98
- :id => 'azure_rm_region',
99
- :label_size => "col-md-2",
100
- :onchange => 'azure_rm_region_callback();',
101
- :help_inline => spinner_button_f(f, _('Reload Images, Sizes, vNets'),
102
- 'azure_rm_region_callback();',
103
- {
104
- :id => 'load_subnets_btn',
105
- :spinner_id => 'load_subnets_indicator',
106
- :class => 'btn-success',
107
- :spinner_class => 'spinner-inverse'
108
- })
120
+ :label => _('Platform'),
121
+ :required => true
109
122
  }
110
- %>
123
+ %>
111
124
 
112
- <%= selectable_f vm_f, :resource_group, resource_groups,
113
- { :include_blank => true },
114
- {
115
- :disabled => resource_groups.empty?,
116
- :label => _('Resource Group'),
117
- :required => true,
118
- :id => 'azure_rm_rg'
119
- }
120
- %>
125
+ <%= text_f f, :username,
126
+ {
127
+ :label => _('Username'),
128
+ :required => true
129
+ }
130
+ %>
121
131
 
122
- <%= selectable_f vm_f, :vm_size, [],
123
- { :include_blank => _('Please first select an Azure region') },
124
- {
125
- :label => _('VM Size'),
126
- :required => true,
127
- :id => 'azure_rm_size'
128
- }
129
- %>
132
+ <%= password_f f, :password,
133
+ {
134
+ :label => _('Password'),
135
+ :required => true,
136
+ :placeholder => "********",
137
+ :value => f.object.password
130
138
 
131
- <%= selectable_f vm_f, :platform, %w(Linux Windows),
132
- {},
133
- {
134
- :label => _('Platform'),
135
- :required => true
136
- }
137
- %>
139
+ }
140
+ %>
138
141
 
139
- <%= text_f vm_f, :username,
140
- {
141
- :label => _('Username'),
142
- :required => true
143
- }
144
- %>
142
+ <%= textarea_f f, :ssh_key_data,
143
+ {
144
+ :label => _('SSH Key')
145
+ }
146
+ %>
145
147
 
146
- <%= password_f vm_f, :password,
147
- {
148
- :label => _('Password'),
149
- :required => true,
150
- :placeholder => "********"
151
- }
152
- %>
148
+ <%= checkbox_f f, :premium_os_disk,
149
+ { :checked => f.object.premium_os_disk == "Premium_LRS",
150
+ :label => _('Premium OS Disk'),
151
+ :label_size => "col-md-2"
152
+ },
153
+ 'true',
154
+ 'false'
155
+ %>
153
156
 
154
- <%= textarea_f vm_f, :ssh_key_data,
157
+ <%= selectable_f f, :os_disk_caching, %w(None ReadOnly ReadWrite),
158
+ {},
155
159
  {
156
- :label => _('SSH Key')
160
+ :label => _('OS Disk Caching'),
161
+ :required => true,
162
+ :class => "col-md-2"
157
163
  }
158
- %>
164
+ %>
159
165
 
160
- <%= checkbox_f vm_f, :premium_os_disk,
161
- {
162
- :label => _('Premium OS Disk'), :label_size => "col-md-2"
163
- },
164
- 'true',
165
- 'false'
166
- %>
166
+ <%= text_f f, :script_command,
167
+ {
168
+ :label => _('Custom Script Command'),
169
+ :help_inline => _("To perform commands as root, prefix it with 'sudo'.")
170
+ }
171
+ %>
167
172
 
168
- <%= selectable_f vm_f, :os_disk_caching, %w(None ReadOnly ReadWrite),
169
- {},
170
- {
171
- :label => _('OS Disk Caching'),
172
- :required => true,
173
- :class => "col-md-2"
174
- }
175
- %>
173
+ <%= text_f f, :script_uris,
174
+ {
175
+ :label => _('Comma seperated file URIs')
176
+ }
177
+ %>
176
178
 
177
- <%= text_f vm_f, :script_command,
178
- {
179
- :label => _('Custom Script Command'),
180
- :help_inline => _("To perform commands as root, prefix it with 'sudo'.")
181
- }
182
- %>
179
+ <% checked = params[:host] && params[:host][:compute_attributes] && params[:host][:compute_attributes][:start] || '1'
180
+ %>
183
181
 
184
- <%= text_f vm_f, :script_uris,
185
- {
186
- :label => _('Comma seperated file URIs')
187
- }
188
- %>
189
- <% end %>
182
+ <%= checkbox_f f, :start, { :checked => (checked == '1'), :help_inline => _("Power ON this machine upon creation"), :label => _('Start'), :label_size => "col-md-2" } if new_vm && controller_name != "compute_attributes"
183
+ %>
190
184
 
191
185
  <div id="image_selection">
192
186
  <%= select_f f, :image_id, images, :uuid, :name,
@@ -1,5 +1,8 @@
1
- <%= selectable_f f, :network, [],
2
- { :include_blank => _('Please first select an image and an Azure region')},
1
+ <% nat = compute_resource.subnets.collect { |s| [ "#{s.id.split('/')[8]}-#{s.name} #{s.address_prefix}", s.id ] } %>
2
+
3
+ <%= selectable_f f, :network, options_for_select(nat,
4
+ :selected => f.object.network),
5
+ { :include_blank => _('Select') },
3
6
  {
4
7
  :label => _('Azure Subnet'),
5
8
  :required => true,
@@ -8,16 +11,21 @@
8
11
  }
9
12
  %>
10
13
 
11
- <%= selectable_f f, :bridge, ['None', 'Dynamic', 'Static'],
14
+ <%= selectable_f f, :public_ip, options_for_select(['None', 'Dynamic', 'Static'],
15
+ :selected => f.object.public_ip),
12
16
  {},
13
17
  {
14
- :label => _("Public IP"),
15
- :label_size => "col-md-2"
18
+ :label => _("Public IP"),
19
+ :label_size => "col-md-2"
16
20
  }
17
21
  %>
18
22
 
19
- <%= checkbox_f f, :name,
20
- { :label => _("Static Private IP"), :label_size => "col-md-2" },
21
- 'true',
22
- 'false'
23
- %>
23
+ <%= checkbox_f f, :private_ip,
24
+ {
25
+ :label => _("Static Private IP"),
26
+ :label_size => "col-md-2"
27
+ },
28
+ 'true',
29
+ 'false'
30
+
31
+ %>
@@ -6,14 +6,14 @@
6
6
  <th><%= _('Resource Group') %></th>
7
7
  <th><%= _('Region') %></th>
8
8
  <th><%= _('State') %></th>
9
- <th></th>
9
+ <th><%= _('Actions') %></th>
10
10
  </tr>
11
11
  </thead>
12
12
  <% @vms.each do |vm| %>
13
13
  <tr>
14
14
  <td><%= link_to_if_authorized vm.name, hash_for_compute_resource_vm_path(:compute_resource_id => @compute_resource, :id => vm.identity).merge(:auth_object => @compute_resource, :authorizer => :authorizer) %></td>
15
15
  <td><%= vm.vm_size %></td>
16
- <td><%= vm.azure_vm.resource_group %></td>
16
+ <td><%= vm.resource_group %></td>
17
17
  <td><%= vm.azure_vm.location %></td>
18
18
  <td> <span <%= vm_power_class(vm.ready?) %>> <%= vm_state(vm) %> </span> </td>
19
19
  <td>
@@ -2,5 +2,5 @@
2
2
  :help_inline => _("The user that will be used to SSH into the VM for completion")
3
3
  %>
4
4
  <%= password_f f, :password, :help_inline => _("Password to authenticate with - used for SSH finish step.") %>
5
- <%= image_field(f, :label => _("Managed Image ID or Marketplace URN")) %>
5
+ <%= image_field(f, :label => _("Marketplace Image URN"), :help_inline => _("Marketplace URN (e.g. OpenLogic:CentOS:7.5:latest)")) %>
6
6
  <%= checkbox_f f, :user_data, :help_inline => _("Does this image support user data input?") %>
@@ -1,5 +1,17 @@
1
1
  require 'foreman_azure_rm/engine.rb'
2
+ require 'azure_mgmt_resources'
3
+ require 'azure_mgmt_network'
4
+ require 'azure_mgmt_storage'
5
+ require 'azure_mgmt_compute'
2
6
 
3
7
  module ForemanAzureRM
8
+ Storage = Azure::Storage::Profiles::Latest::Mgmt
9
+ Network = Azure::Network::Profiles::Latest::Mgmt
10
+ Compute = Azure::Compute::Profiles::Latest::Mgmt
11
+ Resources = Azure::Resources::Profiles::Latest::Mgmt
4
12
 
13
+ StorageModels = Storage::Models
14
+ NetworkModels = Network::Models
15
+ ComputeModels = Compute::Models
16
+ ResourceModels = Resources::Models
5
17
  end
@@ -1,14 +1,4 @@
1
1
  module ForemanAzureRM
2
- Storage = Azure::Storage::Profiles::Latest::Mgmt
3
- Network = Azure::Network::Profiles::Latest::Mgmt
4
- Compute = Azure::Compute::Profiles::Latest::Mgmt
5
- Resources = Azure::Resources::Profiles::Latest::Mgmt
6
-
7
- StorageModels = Storage::Models
8
- NetworkModels = Network::Models
9
- ComputeModels = Compute::Models
10
- ResourceModels = Resources::Models
11
-
12
2
  class AzureSDKAdapter
13
3
  def initialize(tenant, app_ident, secret_key, sub_id)
14
4
  @tenant = tenant
@@ -56,8 +46,8 @@ module ForemanAzureRM
56
46
  network_client.virtual_networks.list_all
57
47
  end
58
48
 
59
- def subnets(resource_group, vnet_name)
60
- network_client.subnets.list(resource_group, vnet_name)
49
+ def subnets(rg_name, vnet_name)
50
+ network_client.subnets.list(rg_name, vnet_name)
61
51
  end
62
52
 
63
53
  def public_ip(rg_name, pip_name)
@@ -68,14 +58,19 @@ module ForemanAzureRM
68
58
  network_client.network_interfaces.get(rg_name, nic_name)
69
59
  end
70
60
 
61
+ def get_vm_extension(rg_name, vm_name, vm_extension_name)
62
+ compute_client.virtual_machine_extensions.get(rg_name, vm_name, vm_extension_name)
63
+ end
64
+
71
65
  def list_vm_sizes(region)
66
+ return [] unless region.present?
72
67
  stripped_region = region.gsub(/\s+/, '').downcase
73
68
  compute_client.virtual_machine_sizes.list(stripped_region).value()
74
69
  end
75
70
 
76
- def list_vms(rg_name)
71
+ def list_vms(region)
77
72
  # List all VMs in a resource group
78
- virtual_machines = compute_client.virtual_machines.list(rg_name)
73
+ virtual_machines = compute_client.virtual_machines.list_by_location(region)
79
74
  end
80
75
 
81
76
  def get_vm(rg_name, vm_name)
@@ -137,5 +132,14 @@ module ForemanAzureRM
137
132
  end
138
133
  vm_status
139
134
  end
135
+
136
+ def start_vm(rg_name, vm_name)
137
+ compute_client.virtual_machines.start(rg_name, vm_name)
138
+ end
139
+
140
+ def stop_vm(rg_name, vm_name)
141
+ compute_client.virtual_machines.power_off(rg_name, vm_name)
142
+ compute_client.virtual_machines.deallocate(rg_name, vm_name)
143
+ end
140
144
  end
141
145
  end
@@ -4,13 +4,19 @@ module ForemanAzureRM
4
4
 
5
5
  #autoloading all files inside lib dir
6
6
  config.autoload_paths += Dir["#{config.root}/lib"]
7
- config.autoload_paths += Dir["#{config.root}/app/models/concerns"]
7
+ config.autoload_paths += Dir["#{config.root}/app/models/concerns/foreman_azure_rm/vm_extensions/"]
8
8
 
9
9
  initializer 'foreman_azure_rm.register_plugin', :before => :finisher_hook do
10
10
  Foreman::Plugin.register :foreman_azure_rm do
11
11
  requires_foreman '>= 1.17'
12
12
  compute_resource ForemanAzureRM::AzureRM
13
- parameter_filter ComputeResource, :azure_vm, :tenant, :app_ident, :secret_key, :sub_id
13
+ parameter_filter ComputeResource, :azure_vm, :tenant, :app_ident, :secret_key, :sub_id, :region
14
+ end
15
+ end
16
+
17
+ initializer "foreman_azure_rm.add_rabl_view_path" do
18
+ Rabl.configure do |config|
19
+ config.view_paths << ForemanAzureRM::Engine.root.join('app', 'views')
14
20
  end
15
21
  end
16
22
 
@@ -1,3 +1,3 @@
1
1
  module ForemanAzureRM
2
- VERSION = '2.0.0.pre1'.freeze
2
+ VERSION = '2.0.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_azure_rm
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre1
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aditi Puntambekar
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-08-21 00:00:00.000000000 Z
13
+ date: 2019-10-31 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: deface
@@ -169,9 +169,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
169
169
  version: '0'
170
170
  required_rubygems_version: !ruby/object:Gem::Requirement
171
171
  requirements:
172
- - - ">"
172
+ - - ">="
173
173
  - !ruby/object:Gem::Version
174
- version: 1.3.1
174
+ version: '0'
175
175
  requirements: []
176
176
  rubyforge_project:
177
177
  rubygems_version: 2.7.6