mpetrive-rh

Untitled

Apr 17th, 2018
275
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2. #
  3. # Copyright (c) 2016 Matt Davis, <mdavis@ansible.com>
  4. # Chris Houseknecht, <house@redhat.com>
  5. #
  6. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
  7.  
  8. from __future__ import absolute_import, division, print_function
  9. __metaclass__ = type
  10.  
  11.  
  12. ANSIBLE_METADATA = {'metadata_version': '1.1',
  13. 'status': ['preview'],
  14. 'supported_by': 'certified'}
  15.  
  16. import base64
  17. import random
  18. import re
  19.  
  20. try:
  21. from msrestazure.azure_exceptions import CloudError
  22. from msrestazure.tools import parse_resource_id
  23. except ImportError:
  24. # This is handled in azure_rm_common
  25. pass
  26.  
  27. #MP
  28. from ansible.utils.display import Display
  29.  
  30. from ansible.module_utils.basic import to_native, to_bytes
  31. from ansible.module_utils.azure_rm_common import AzureRMModuleBase, azure_id_to_dict
  32.  
  33.  
  34. AZURE_OBJECT_CLASS = 'VirtualMachine'
  35.  
  36. AZURE_ENUM_MODULES = ['azure.mgmt.compute.models']
  37.  
  38.  
  39. def extract_names_from_blob_uri(blob_uri, storage_suffix):
  40. # HACK: ditch this once python SDK supports get by URI
  41. m = re.match(r'^https://(?P<accountname>[^.]+)\.blob\.{0}/'
  42. r'(?P<containername>[^/]+)/(?P<blobname>.+)$'.format(storage_suffix), blob_uri)
  43. if not m:
  44. raise Exception("unable to parse blob uri '%s'" % blob_uri)
  45. extracted_names = m.groupdict()
  46. return extracted_names
  47.  
  48.  
  49. class AzureRMVirtualMachine(AzureRMModuleBase):
  50.  
  51. def __init__(self):
  52.  
  53. self.module_arg_spec = dict(
  54. resource_group=dict(type='str', required=True),
  55. name=dict(type='str', required=True),
  56. custom_data=dict(type='str'),
  57. state=dict(choices=['present', 'absent'], default='present', type='str'),
  58. location=dict(type='str'),
  59. short_hostname=dict(type='str'),
  60. vm_size=dict(type='str'),
  61. admin_username=dict(type='str'),
  62. admin_password=dict(type='str', no_log=True),
  63. ssh_password_enabled=dict(type='bool', default=True),
  64. ssh_public_keys=dict(type='list'),
  65. image=dict(type='raw'),
  66. availability_set=dict(type='str'),
  67. storage_account_name=dict(type='str', aliases=['storage_account']),
  68. storage_container_name=dict(type='str', aliases=['storage_container'], default='vhds'),
  69. storage_blob_name=dict(type='str', aliases=['storage_blob']),
  70. os_disk_caching=dict(type='str', aliases=['disk_caching'], choices=['ReadOnly', 'ReadWrite'],
  71. default='ReadOnly'),
  72. managed_disk_type=dict(type='str', choices=['Standard_LRS', 'Premium_LRS']),
  73. os_type=dict(type='str', choices=['Linux', 'Windows'], default='Linux'),
  74. public_ip_allocation_method=dict(type='str', choices=['Dynamic', 'Static', 'Disabled'], default='Static',
  75. aliases=['public_ip_allocation']),
  76. open_ports=dict(type='list'),
  77. network_interface_names=dict(type='list', aliases=['network_interfaces']),
  78. remove_on_absent=dict(type='list', default=['all']),
  79. virtual_network_resource_group=dict(type='str'),
  80. virtual_network_name=dict(type='str', aliases=['virtual_network']),
  81. subnet_name=dict(type='str', aliases=['subnet']),
  82. allocated=dict(type='bool', default=True),
  83. restarted=dict(type='bool', default=False),
  84. started=dict(type='bool', default=True),
  85. data_disks=dict(type='list'),
  86. plan=dict(type='dict')
  87. )
  88.  
  89. self.resource_group = None
  90. self.name = None
  91. self.custom_data = None
  92. self.state = None
  93. self.location = None
  94. self.short_hostname = None
  95. self.vm_size = None
  96. self.admin_username = None
  97. self.admin_password = None
  98. self.ssh_password_enabled = None
  99. self.ssh_public_keys = None
  100. self.image = None
  101. self.availability_set = None
  102. self.storage_account_name = None
  103. self.storage_container_name = None
  104. self.storage_blob_name = None
  105. self.os_type = None
  106. self.os_disk_caching = None
  107. self.managed_disk_type = None
  108. self.network_interface_names = None
  109. self.remove_on_absent = set()
  110. self.tags = None
  111. self.force = None
  112. self.public_ip_allocation_method = None
  113. self.open_ports = None
  114. self.virtual_network_resource_group = None
  115. self.virtual_network_name = None
  116. self.subnet_name = None
  117. self.allocated = None
  118. self.restarted = None
  119. self.started = None
  120. self.differences = None
  121. self.data_disks = None
  122. self.plan = None
  123.  
  124. self.results = dict(
  125. changed=False,
  126. actions=[],
  127. powerstate_change=None,
  128. ansible_facts=dict(azure_vm=None)
  129. )
  130.  
  131. super(AzureRMVirtualMachine, self).__init__(derived_arg_spec=self.module_arg_spec,
  132. supports_check_mode=True)
  133.  
  134. def exec_module(self, **kwargs):
  135.  
  136. display = Display(4)
  137.  
  138. for key in list(self.module_arg_spec.keys()) + ['tags']:
  139. setattr(self, key, kwargs[key])
  140.  
  141. # make sure options are lower case
  142. self.remove_on_absent = set([resource.lower() for resource in self.remove_on_absent])
  143.  
  144. display.v(u"test")
  145. display.v("test")
  146. display.vv(u"first hello world")
  147. display.vvvv(u"first four hello world")
  148.  
  149. changed = False
  150. powerstate_change = None
  151. results = dict()
  152. vm = None
  153. network_interfaces = []
  154. requested_vhd_uri = None
  155. data_disk_requested_vhd_uri = None
  156. disable_ssh_password = None
  157. vm_dict = None
  158. image_reference = None
  159. custom_image = False
  160.  
  161. resource_group = self.get_resource_group(self.resource_group)
  162. if not self.location:
  163. # Set default location
  164. self.location = resource_group.location
  165.  
  166. if self.state == 'present':
  167. # Verify parameters and resolve any defaults
  168.  
  169. if self.vm_size and not self.vm_size_is_valid():
  170. self.fail("Parameter error: vm_size {0} is not valid for your subscription and location.".format(
  171. self.vm_size
  172. ))
  173.  
  174. if self.network_interface_names:
  175. for name in self.network_interface_names:
  176. nic = self.get_network_interface(name)
  177. network_interfaces.append(nic.id)
  178.  
  179. if self.ssh_public_keys:
  180. msg = "Parameter error: expecting ssh_public_keys to be a list of type dict where " \
  181. "each dict contains keys: path, key_data."
  182. for key in self.ssh_public_keys:
  183. if not isinstance(key, dict):
  184. self.fail(msg)
  185. if not key.get('path') or not key.get('key_data'):
  186. self.fail(msg)
  187.  
  188. if self.image and isinstance(self.image, dict):
  189. if all(key in self.image for key in ('publisher', 'offer', 'sku', 'version')):
  190. marketplace_image = self.get_marketplace_image_version()
  191. if self.image['version'] == 'latest':
  192. self.image['version'] = marketplace_image.name
  193. self.log("Using image version {0}".format(self.image['version']))
  194.  
  195. image_reference = self.compute_models.ImageReference(
  196. publisher=self.image['publisher'],
  197. offer=self.image['offer'],
  198. sku=self.image['sku'],
  199. version=self.image['version']
  200. )
  201. elif self.image.get('name'):
  202. custom_image = True
  203. image_reference = self.get_custom_image_reference(
  204. self.image.get('name'),
  205. self.image.get('resource_group'))
  206. else:
  207. self.fail("parameter error: expecting image to contain [publisher, offer, sku, version] or [name, resource_group]")
  208. elif self.image and isinstance(self.image, str):
  209. custom_image = True
  210. image_reference = self.get_custom_image_reference(self.image)
  211. elif self.image:
  212. self.fail("parameter error: expecting image to be a string or dict not {0}".format(type(self.image).__name__))
  213.  
  214. if self.plan:
  215. if not self.plan.get('name') or not self.plan.get('product') or not self.plan.get('publisher'):
  216. self.fail("parameter error: plan must include name, product, and publisher")
  217.  
  218. if not self.storage_blob_name and not self.managed_disk_type:
  219. self.storage_blob_name = self.name + '.vhd'
  220. elif self.managed_disk_type:
  221. self.storage_blob_name = self.name
  222.  
  223. if self.storage_account_name and not self.managed_disk_type:
  224. properties = self.get_storage_account(self.storage_account_name)
  225.  
  226. requested_vhd_uri = '{0}{1}/{2}'.format(properties.primary_endpoints.blob,
  227. self.storage_container_name,
  228. self.storage_blob_name)
  229.  
  230. disable_ssh_password = not self.ssh_password_enabled
  231.  
  232. try:
  233. self.log("Fetching virtual machine {0}".format(self.name))
  234. vm = self.compute_client.virtual_machines.get(self.resource_group, self.name, expand='instanceview')
  235. self.check_provisioning_state(vm, self.state)
  236. vm_dict = self.serialize_vm(vm)
  237.  
  238. if self.state == 'present':
  239. differences = []
  240. current_nics = []
  241. results = vm_dict
  242.  
  243. # Try to determine if the VM needs to be updated
  244. if self.network_interface_names:
  245. for nic in vm_dict['properties']['networkProfile']['networkInterfaces']:
  246. current_nics.append(nic['id'])
  247.  
  248. if set(current_nics) != set(network_interfaces):
  249. self.log('CHANGED: virtual machine {0} - network interfaces are different.'.format(self.name))
  250. differences.append('Network Interfaces')
  251. updated_nics = [dict(id=id) for id in network_interfaces]
  252. vm_dict['properties']['networkProfile']['networkInterfaces'] = updated_nics
  253. changed = True
  254.  
  255. if self.os_disk_caching and \
  256. self.os_disk_caching != vm_dict['properties']['storageProfile']['osDisk']['caching']:
  257. self.log('CHANGED: virtual machine {0} - OS disk caching'.format(self.name))
  258. differences.append('OS Disk caching')
  259. changed = True
  260. vm_dict['properties']['storageProfile']['osDisk']['caching'] = self.os_disk_caching
  261.  
  262. update_tags, vm_dict['tags'] = self.update_tags(vm_dict.get('tags', dict()))
  263. if update_tags:
  264. differences.append('Tags')
  265. changed = True
  266.  
  267. if self.short_hostname and self.short_hostname != vm_dict['properties']['osProfile']['computerName']:
  268. self.log('CHANGED: virtual machine {0} - short hostname'.format(self.name))
  269. differences.append('Short Hostname')
  270. changed = True
  271. vm_dict['properties']['osProfile']['computerName'] = self.short_hostname
  272.  
  273. if self.started and vm_dict['powerstate'] not in ['starting', 'running'] and self.allocated:
  274. self.log("CHANGED: virtual machine {0} not running and requested state 'running'".format(self.name))
  275. changed = True
  276. powerstate_change = 'poweron'
  277. elif self.state == 'present' and vm_dict['powerstate'] == 'running' and self.restarted:
  278. self.log("CHANGED: virtual machine {0} {1} and requested state 'restarted'"
  279. .format(self.name, vm_dict['powerstate']))
  280. changed = True
  281. powerstate_change = 'restarted'
  282. elif self.state == 'present' and not self.allocated and vm_dict['powerstate'] not in ['deallocated', 'deallocating']:
  283. self.log("CHANGED: virtual machine {0} {1} and requested state 'deallocated'"
  284. .format(self.name, vm_dict['powerstate']))
  285. changed = True
  286. powerstate_change = 'deallocated'
  287. elif not self.started and vm_dict['powerstate'] == 'running':
  288. self.log("CHANGED: virtual machine {0} running and requested state 'stopped'".format(self.name))
  289. changed = True
  290. powerstate_change = 'poweroff'
  291.  
  292. self.differences = differences
  293.  
  294. elif self.state == 'absent':
  295. self.log("CHANGED: virtual machine {0} exists and requested state is 'absent'".format(self.name))
  296. results = dict()
  297. changed = True
  298.  
  299. except CloudError:
  300. self.log('Virtual machine {0} does not exist'.format(self.name))
  301. if self.state == 'present':
  302. self.log("CHANGED: virtual machine {0} does not exist but state is 'present'.".format(self.name))
  303. changed = True
  304.  
  305. self.results['changed'] = changed
  306. self.results['ansible_facts']['azure_vm'] = results
  307. self.results['powerstate_change'] = powerstate_change
  308. display.vv("outside hello world")
  309. display.vvvv("four outside hello world")
  310.  
  311. if self.check_mode:
  312. return self.results
  313.  
  314. if changed:
  315. if self.state == 'present':
  316. default_storage_account = None
  317. if not vm:
  318. # Create the VM
  319. self.log("Create virtual machine {0}".format(self.name))
  320. self.results['actions'].append('Created VM {0}'.format(self.name))
  321.  
  322. # Validate parameters
  323. if not self.admin_username:
  324. self.fail("Parameter error: admin_username required when creating a virtual machine.")
  325.  
  326. if self.os_type == 'Linux':
  327. if disable_ssh_password and not self.ssh_public_keys:
  328. self.fail("Parameter error: ssh_public_keys required when disabling SSH password.")
  329.  
  330. if not image_reference:
  331. self.fail("Parameter error: an image is required when creating a virtual machine.")
  332.  
  333. availability_set_resource = None
  334. if self.availability_set:
  335. parsed_availability_set = parse_resource_id(self.availability_set)
  336. availability_set = self.get_availability_set(parsed_availability_set.get('resource_group', self.resource_group),
  337. parsed_availability_set.get('name'))
  338. availability_set_resource = self.compute_models.SubResource(availability_set.id)
  339.  
  340. # Get defaults
  341. if not self.network_interface_names:
  342. default_nic = self.create_default_nic()
  343. self.log("network interface:")
  344. self.log(self.serialize_obj(default_nic, 'NetworkInterface'), pretty_print=True)
  345. network_interfaces = [default_nic.id]
  346.  
  347. # os disk
  348. if not self.storage_account_name and not self.managed_disk_type:
  349. storage_account = self.create_default_storage_account()
  350. self.log("storage account:")
  351. self.log(self.serialize_obj(storage_account, 'StorageAccount'), pretty_print=True)
  352. requested_vhd_uri = 'https://{0}.blob.{1}/{2}/{3}'.format(
  353. storage_account.name,
  354. self._cloud_environment.suffixes.storage_endpoint,
  355. self.storage_container_name,
  356. self.storage_blob_name)
  357. default_storage_account = storage_account # store for use by data disks if necessary
  358.  
  359. if not self.short_hostname:
  360. self.short_hostname = self.name
  361.  
  362. nics = [self.compute_models.NetworkInterfaceReference(id=id) for id in network_interfaces]
  363.  
  364. # os disk
  365. if self.managed_disk_type:
  366. vhd = None
  367. managed_disk = self.compute_models.ManagedDiskParameters(storage_account_type=self.managed_disk_type)
  368. elif custom_image:
  369. vhd = None
  370. managed_disk = None
  371. else:
  372. vhd = self.compute_models.VirtualHardDisk(uri=requested_vhd_uri)
  373. managed_disk = None
  374.  
  375. plan = None
  376. if self.plan:
  377. plan = self.compute_models.Plan(name=self.plan.get('name'), product=self.plan.get('product'),
  378. publisher=self.plan.get('publisher'),
  379. promotion_code=self.plan.get('promotion_code'))
  380.  
  381. vm_resource = self.compute_models.VirtualMachine(
  382. self.location,
  383. tags=self.tags,
  384. os_profile=self.compute_models.OSProfile(
  385. admin_username=self.admin_username,
  386. computer_name=self.short_hostname,
  387. ),
  388. hardware_profile=self.compute_models.HardwareProfile(
  389. vm_size=self.vm_size
  390. ),
  391. storage_profile=self.compute_models.StorageProfile(
  392. os_disk=self.compute_models.OSDisk(
  393. name=self.storage_blob_name,
  394. vhd=vhd,
  395. managed_disk=managed_disk,
  396. create_option=self.compute_models.DiskCreateOptionTypes.from_image,
  397. caching=self.os_disk_caching,
  398. ),
  399. image_reference=image_reference,
  400. ),
  401. network_profile=self.compute_models.NetworkProfile(
  402. network_interfaces=nics
  403. ),
  404. availability_set=availability_set_resource,
  405. plan=plan
  406. )
  407.  
  408. if self.admin_password:
  409. vm_resource.os_profile.admin_password = self.admin_password
  410.  
  411. if self.custom_data:
  412. # Azure SDK (erroneously?) wants native string type for this
  413. vm_resource.os_profile.custom_data = to_native(base64.b64encode(to_bytes(self.custom_data)))
  414.  
  415. if self.os_type == 'Linux':
  416. vm_resource.os_profile.linux_configuration = self.compute_models.LinuxConfiguration(
  417. disable_password_authentication=disable_ssh_password
  418. )
  419. if self.ssh_public_keys:
  420. ssh_config = self.compute_models.SshConfiguration()
  421. ssh_config.public_keys = \
  422. [self.compute_models.SshPublicKey(path=key['path'], key_data=key['key_data']) for key in self.ssh_public_keys]
  423. vm_resource.os_profile.linux_configuration.ssh = ssh_config
  424.  
  425. # data disk
  426. if self.data_disks:
  427. data_disks = []
  428. count = 0
  429.  
  430. for data_disk in self.data_disks:
  431. if not data_disk.get('managed_disk_type'):
  432. if not data_disk.get('storage_blob_name'):
  433. data_disk['storage_blob_name'] = self.name + '-data-' + str(count) + '.vhd'
  434. count += 1
  435.  
  436. if data_disk.get('storage_account_name'):
  437. data_disk_storage_account = self.get_storage_account(data_disk['storage_account_name'])
  438. else:
  439. if(not default_storage_account):
  440. data_disk_storage_account = self.create_default_storage_account()
  441. self.log("data disk storage account:")
  442. self.log(self.serialize_obj(data_disk_storage_account, 'StorageAccount'), pretty_print=True)
  443. default_storage_account = data_disk_storage_account # store for use by future data disks if necessary
  444. else:
  445. data_disk_storage_account = default_storage_account
  446.  
  447. if not data_disk.get('storage_container_name'):
  448. data_disk['storage_container_name'] = 'vhds'
  449.  
  450. data_disk_requested_vhd_uri = 'https://{0}.blob.{1}/{2}/{3}'.format(
  451. data_disk_storage_account.name,
  452. self._cloud_environment.suffixes.storage_endpoint,
  453. data_disk['storage_container_name'],
  454. data_disk['storage_blob_name']
  455. )
  456.  
  457. if not data_disk.get('managed_disk_type'):
  458. data_disk_managed_disk = None
  459. disk_name = data_disk['storage_blob_name']
  460. data_disk_vhd = self.compute_models.VirtualHardDisk(uri=data_disk_requested_vhd_uri)
  461. else:
  462. data_disk_vhd = None
  463. data_disk_managed_disk = self.compute_models.ManagedDiskParameters(storage_account_type=data_disk['managed_disk_type'])
  464. disk_name = self.name + "-datadisk-" + str(count)
  465. count += 1
  466.  
  467. data_disk['caching'] = data_disk.get(
  468. 'caching', 'ReadOnly'
  469. )
  470.  
  471. data_disks.append(self.compute_models.DataDisk(
  472. lun=data_disk['lun'],
  473. name=disk_name,
  474. vhd=data_disk_vhd,
  475. caching=data_disk['caching'],
  476. create_option=self.compute_models.DiskCreateOptionTypes.empty,
  477. disk_size_gb=data_disk['disk_size_gb'],
  478. managed_disk=data_disk_managed_disk,
  479. ))
  480.  
  481. vm_resource.storage_profile.data_disks = data_disks
  482.  
  483. self.log("Create virtual machine with parameters:")
  484. self.create_or_update_vm(vm_resource)
  485.  
  486. elif self.differences and len(self.differences) > 0:
  487. # Update the VM based on detected config differences
  488.  
  489. self.log("Update virtual machine {0}".format(self.name))
  490. self.results['actions'].append('Updated VM {0}'.format(self.name))
  491.  
  492. nics = [self.compute_models.NetworkInterfaceReference(id=interface['id'])
  493. for interface in vm_dict['properties']['networkProfile']['networkInterfaces']]
  494.  
  495. # os disk
  496. #display.vv("hello world")
  497. #display.vvvv("four hello world")
  498. #display.vv(vm_dict['properties']['storageProfile']['osDisk'])
  499. if not vm_dict['properties']['storageProfile']['osDisk'].get('managedDisk'):
  500. managed_disk = None
  501. vhd = self.compute_models.VirtualHardDisk(uri=vm_dict['properties']['storageProfile']['osDisk']['vhd']['uri'])
  502. else:
  503. vhd = None
  504. managed_disk = self.compute_models.ManagedDiskParameters(
  505. storage_account_type=vm_dict['properties']['storageProfile']['osDisk']['managedDisk']['storageAccountType']
  506. #storage_account_type="Standard_LRS"
  507. )
  508.  
  509. availability_set_resource = None
  510. try:
  511. availability_set_resource = self.compute_models.SubResource(vm_dict['properties']['availabilitySet']['id'])
  512. except Exception:
  513. # pass if the availability set is not set
  514. pass
  515.  
  516. if vm_dict['properties']['storageProfile']['imageReference'].get('publisher'):
  517. vm_resource = self.compute_models.VirtualMachine(
  518. vm_dict['location'],
  519. os_profile=self.compute_models.OSProfile(
  520. admin_username=vm_dict['properties']['osProfile']['adminUsername'],
  521. computer_name=vm_dict['properties']['osProfile']['computerName']
  522. ),
  523. hardware_profile=self.compute_models.HardwareProfile(
  524. vm_size=vm_dict['properties']['hardwareProfile']['vmSize']
  525. ),
  526. storage_profile=self.compute_models.StorageProfile(
  527. os_disk=self.compute_models.OSDisk(
  528. name=vm_dict['properties']['storageProfile']['osDisk']['name'],
  529. vhd=vhd,
  530. managed_disk=managed_disk,
  531. create_option=vm_dict['properties']['storageProfile']['osDisk']['createOption'],
  532. os_type=vm_dict['properties']['storageProfile']['osDisk']['osType'],
  533. caching=vm_dict['properties']['storageProfile']['osDisk']['caching'],
  534. ),
  535. image_reference=self.compute_models.ImageReference(
  536. publisher=vm_dict['properties']['storageProfile']['imageReference']['publisher'],
  537. offer=vm_dict['properties']['storageProfile']['imageReference']['offer'],
  538. sku=vm_dict['properties']['storageProfile']['imageReference']['sku'],
  539. version=vm_dict['properties']['storageProfile']['imageReference']['version']
  540. ),
  541. ),
  542. availability_set=availability_set_resource,
  543. network_profile=self.compute_models.NetworkProfile(
  544. network_interfaces=nics
  545. ),
  546. )
  547. else:
  548. vm_resource = self.compute_models.VirtualMachine(
  549. vm_dict['location'],
  550. os_profile=self.compute_models.OSProfile(
  551. admin_username=vm_dict['properties']['osProfile']['adminUsername'],
  552. computer_name=vm_dict['properties']['osProfile']['computerName']
  553. ),
  554. hardware_profile=self.compute_models.HardwareProfile(
  555. vm_size=vm_dict['properties']['hardwareProfile']['vmSize']
  556. ),
  557. storage_profile=self.compute_models.StorageProfile(
  558. os_disk=self.compute_models.OSDisk(
  559. name=vm_dict['properties']['storageProfile']['osDisk']['name'],
  560. vhd=vhd,
  561. managed_disk=managed_disk,
  562. create_option=vm_dict['properties']['storageProfile']['osDisk']['createOption'],
  563. os_type=vm_dict['properties']['storageProfile']['osDisk']['osType'],
  564. caching=vm_dict['properties']['storageProfile']['osDisk']['caching'],
  565. ),
  566. image_reference=self.get_custom_image_reference(
  567. name=self.image,
  568. #name=vm_dict['properties']['storageProfile']['imageReference']['name'],
  569. resource_group=self.resource_group
  570. #resource_group=vm_dict['resource_group']
  571. ),
  572. ),
  573. availability_set=availability_set_resource,
  574. network_profile=self.compute_models.NetworkProfile(
  575. network_interfaces=nics
  576. ),
  577. )
  578.  
  579. if vm_dict.get('tags'):
  580. vm_resource.tags = vm_dict['tags']
  581.  
  582. # Add custom_data, if provided
  583. if vm_dict['properties']['osProfile'].get('customData'):
  584. custom_data = vm_dict['properties']['osProfile']['customData']
  585. # Azure SDK (erroneously?) wants native string type for this
  586. vm_resource.os_profile.custom_data = to_native(base64.b64encode(to_bytes(custom_data)))
  587.  
  588. # Add admin password, if one provided
  589. if vm_dict['properties']['osProfile'].get('adminPassword'):
  590. vm_resource.os_profile.admin_password = vm_dict['properties']['osProfile']['adminPassword']
  591.  
  592. # Add linux configuration, if applicable
  593. linux_config = vm_dict['properties']['osProfile'].get('linuxConfiguration')
  594. if linux_config:
  595. ssh_config = linux_config.get('ssh', None)
  596. vm_resource.os_profile.linux_configuration = self.compute_models.LinuxConfiguration(
  597. disable_password_authentication=linux_config.get('disablePasswordAuthentication', False)
  598. )
  599. if ssh_config:
  600. public_keys = ssh_config.get('publicKeys')
  601. if public_keys:
  602. vm_resource.os_profile.linux_configuration.ssh = self.compute_models.SshConfiguration(public_keys=[])
  603. for key in public_keys:
  604. vm_resource.os_profile.linux_configuration.ssh.public_keys.append(
  605. self.compute_models.SshPublicKey(path=key['path'], key_data=key['keyData'])
  606. )
  607.  
  608. # data disk
  609. if vm_dict['properties']['storageProfile'].get('dataDisks'):
  610. data_disks = []
  611.  
  612. for data_disk in vm_dict['properties']['storageProfile']['dataDisks']:
  613. if data_disk.get('managedDisk'):
  614. managed_disk_type = data_disk['managedDisk']['storageAccountType']
  615. data_disk_managed_disk = self.compute_models.ManagedDiskParameters(storage_account_type=managed_disk_type)
  616. data_disk_vhd = None
  617. else:
  618. data_disk_vhd = data_disk['vhd']['uri']
  619. data_disk_managed_disk = None
  620.  
  621. data_disks.append(self.compute_models.DataDisk(
  622. lun=int(data_disk['lun']),
  623. name=data_disk.get('name'),
  624. vhd=data_disk_vhd,
  625. caching=data_disk.get('caching'),
  626. create_option=data_disk.get('createOption'),
  627. disk_size_gb=int(data_disk['diskSizeGB']),
  628. managed_disk=data_disk_managed_disk,
  629. ))
  630. vm_resource.storage_profile.data_disks = data_disks
  631.  
  632. self.log("Update virtual machine with parameters:")
  633. self.create_or_update_vm(vm_resource)
  634.  
  635. # Make sure we leave the machine in requested power state
  636. if (powerstate_change == 'poweron' and
  637. self.results['ansible_facts']['azure_vm']['powerstate'] != 'running'):
  638. # Attempt to power on the machine
  639. self.power_on_vm()
  640.  
  641. elif (powerstate_change == 'poweroff' and
  642. self.results['ansible_facts']['azure_vm']['powerstate'] == 'running'):
  643. # Attempt to power off the machine
  644. self.power_off_vm()
  645.  
  646. elif powerstate_change == 'restarted':
  647. self.restart_vm()
  648.  
  649. elif powerstate_change == 'deallocated':
  650. self.deallocate_vm()
  651.  
  652. self.results['ansible_facts']['azure_vm'] = self.serialize_vm(self.get_vm())
  653.  
  654. elif self.state == 'absent':
  655. # delete the VM
  656. self.log("Delete virtual machine {0}".format(self.name))
  657. self.results['ansible_facts']['azure_vm'] = None
  658. self.delete_vm(vm)
  659.  
  660. # until we sort out how we want to do this globally
  661. del self.results['actions']
  662.  
  663. return self.results
  664.  
  665. def get_vm(self):
  666. '''
  667. Get the VM with expanded instanceView
  668.  
  669. :return: VirtualMachine object
  670. '''
  671. try:
  672. vm = self.compute_client.virtual_machines.get(self.resource_group, self.name, expand='instanceview')
  673. return vm
  674. except Exception as exc:
  675. self.fail("Error getting virtual machine {0} - {1}".format(self.name, str(exc)))
  676.  
  677. def serialize_vm(self, vm):
  678. '''
  679. Convert a VirtualMachine object to dict.
  680.  
  681. :param vm: VirtualMachine object
  682. :return: dict
  683. '''
  684.  
  685. result = self.serialize_obj(vm, AZURE_OBJECT_CLASS, enum_modules=AZURE_ENUM_MODULES)
  686. result['id'] = vm.id
  687. result['name'] = vm.name
  688. result['type'] = vm.type
  689. result['location'] = vm.location
  690. result['tags'] = vm.tags
  691.  
  692. result['powerstate'] = dict()
  693. if vm.instance_view:
  694. result['powerstate'] = next((s.code.replace('PowerState/', '')
  695. for s in vm.instance_view.statuses if s.code.startswith('PowerState')), None)
  696.  
  697. # Expand network interfaces to include config properties
  698. for interface in vm.network_profile.network_interfaces:
  699. int_dict = azure_id_to_dict(interface.id)
  700. nic = self.get_network_interface(int_dict['networkInterfaces'])
  701. for interface_dict in result['properties']['networkProfile']['networkInterfaces']:
  702. if interface_dict['id'] == interface.id:
  703. nic_dict = self.serialize_obj(nic, 'NetworkInterface')
  704. interface_dict['name'] = int_dict['networkInterfaces']
  705. interface_dict['properties'] = nic_dict['properties']
  706.  
  707. # Expand public IPs to include config properties
  708. for interface in result['properties']['networkProfile']['networkInterfaces']:
  709. for config in interface['properties']['ipConfigurations']:
  710. if config['properties'].get('publicIPAddress'):
  711. pipid_dict = azure_id_to_dict(config['properties']['publicIPAddress']['id'])
  712. try:
  713. pip = self.network_client.public_ip_addresses.get(self.resource_group,
  714. pipid_dict['publicIPAddresses'])
  715. except Exception as exc:
  716. self.fail("Error fetching public ip {0} - {1}".format(pipid_dict['publicIPAddresses'],
  717. str(exc)))
  718. pip_dict = self.serialize_obj(pip, 'PublicIPAddress')
  719. config['properties']['publicIPAddress']['name'] = pipid_dict['publicIPAddresses']
  720. config['properties']['publicIPAddress']['properties'] = pip_dict['properties']
  721.  
  722. self.log(result, pretty_print=True)
  723. if self.state != 'absent' and not result['powerstate']:
  724. self.fail("Failed to determine PowerState of virtual machine {0}".format(self.name))
  725. return result
  726.  
  727. def power_off_vm(self):
  728. self.log("Powered off virtual machine {0}".format(self.name))
  729. self.results['actions'].append("Powered off virtual machine {0}".format(self.name))
  730. try:
  731. poller = self.compute_client.virtual_machines.power_off(self.resource_group, self.name)
  732. self.get_poller_result(poller)
  733. except Exception as exc:
  734. self.fail("Error powering off virtual machine {0} - {1}".format(self.name, str(exc)))
  735. return True
  736.  
  737. def power_on_vm(self):
  738. self.results['actions'].append("Powered on virtual machine {0}".format(self.name))
  739. self.log("Power on virtual machine {0}".format(self.name))
  740. try:
  741. poller = self.compute_client.virtual_machines.start(self.resource_group, self.name)
  742. self.get_poller_result(poller)
  743. except Exception as exc:
  744. self.fail("Error powering on virtual machine {0} - {1}".format(self.name, str(exc)))
  745. return True
  746.  
  747. def restart_vm(self):
  748. self.results['actions'].append("Restarted virtual machine {0}".format(self.name))
  749. self.log("Restart virtual machine {0}".format(self.name))
  750. try:
  751. poller = self.compute_client.virtual_machines.restart(self.resource_group, self.name)
  752. self.get_poller_result(poller)
  753. except Exception as exc:
  754. self.fail("Error restarting virtual machine {0} - {1}".format(self.name, str(exc)))
  755. return True
  756.  
  757. def deallocate_vm(self):
  758. self.results['actions'].append("Deallocated virtual machine {0}".format(self.name))
  759. self.log("Deallocate virtual machine {0}".format(self.name))
  760. try:
  761. poller = self.compute_client.virtual_machines.deallocate(self.resource_group, self.name)
  762. self.get_poller_result(poller)
  763. except Exception as exc:
  764. self.fail("Error deallocating virtual machine {0} - {1}".format(self.name, str(exc)))
  765. return True
  766.  
  767. def delete_vm(self, vm):
  768. vhd_uris = []
  769. managed_disk_ids = []
  770. nic_names = []
  771. pip_names = []
  772.  
  773. if self.remove_on_absent.intersection(set(['all', 'virtual_storage'])):
  774. # store the attached vhd info so we can nuke it after the VM is gone
  775. if(vm.storage_profile.os_disk.managed_disk):
  776. self.log('Storing managed disk ID for deletion')
  777. managed_disk_ids.append(vm.storage_profile.os_disk.managed_disk.id)
  778. elif(vm.storage_profile.os_disk.vhd):
  779. self.log('Storing VHD URI for deletion')
  780. vhd_uris.append(vm.storage_profile.os_disk.vhd.uri)
  781.  
  782. data_disks = vm.storage_profile.data_disks
  783. for data_disk in data_disks:
  784. if(data_disk.vhd):
  785. vhd_uris.append(data_disk.vhd.uri)
  786. elif(data_disk.managed_disk):
  787. managed_disk_ids.append(data_disk.managed_disk.id)
  788.  
  789. # FUTURE enable diff mode, move these there...
  790. self.log("VHD URIs to delete: {0}".format(', '.join(vhd_uris)))
  791. self.results['deleted_vhd_uris'] = vhd_uris
  792. self.log("Managed disk IDs to delete: {0}".format(', '.join(managed_disk_ids)))
  793. self.results['deleted_managed_disk_ids'] = managed_disk_ids
  794.  
  795. if self.remove_on_absent.intersection(set(['all', 'network_interfaces'])):
  796. # store the attached nic info so we can nuke them after the VM is gone
  797. self.log('Storing NIC names for deletion.')
  798. for interface in vm.network_profile.network_interfaces:
  799. id_dict = azure_id_to_dict(interface.id)
  800. nic_names.append(id_dict['networkInterfaces'])
  801. self.log('NIC names to delete {0}'.format(', '.join(nic_names)))
  802. self.results['deleted_network_interfaces'] = nic_names
  803. if self.remove_on_absent.intersection(set(['all', 'public_ips'])):
  804. # also store each nic's attached public IPs and delete after the NIC is gone
  805. for name in nic_names:
  806. nic = self.get_network_interface(name)
  807. for ipc in nic.ip_configurations:
  808. if ipc.public_ip_address:
  809. pip_dict = azure_id_to_dict(ipc.public_ip_address.id)
  810. pip_names.append(pip_dict['publicIPAddresses'])
  811. self.log('Public IPs to delete are {0}'.format(', '.join(pip_names)))
  812. self.results['deleted_public_ips'] = pip_names
  813.  
  814. self.log("Deleting virtual machine {0}".format(self.name))
  815. self.results['actions'].append("Deleted virtual machine {0}".format(self.name))
  816. try:
  817. poller = self.compute_client.virtual_machines.delete(self.resource_group, self.name)
  818. # wait for the poller to finish
  819. self.get_poller_result(poller)
  820. except Exception as exc:
  821. self.fail("Error deleting virtual machine {0} - {1}".format(self.name, str(exc)))
  822.  
  823. # TODO: parallelize nic, vhd, and public ip deletions with begin_deleting
  824. # TODO: best-effort to keep deleting other linked resources if we encounter an error
  825. if self.remove_on_absent.intersection(set(['all', 'virtual_storage'])):
  826. self.log('Deleting VHDs')
  827. self.delete_vm_storage(vhd_uris)
  828. self.log('Deleting managed disks')
  829. self.delete_managed_disks(managed_disk_ids)
  830.  
  831. if self.remove_on_absent.intersection(set(['all', 'network_interfaces'])):
  832. self.log('Deleting network interfaces')
  833. for name in nic_names:
  834. self.delete_nic(name)
  835.  
  836. if self.remove_on_absent.intersection(set(['all', 'public_ips'])):
  837. self.log('Deleting public IPs')
  838. for name in pip_names:
  839. self.delete_pip(name)
  840. return True
  841.  
  842. def get_network_interface(self, name):
  843. try:
  844. nic = self.network_client.network_interfaces.get(self.resource_group, name)
  845. return nic
  846. except Exception as exc:
  847. self.fail("Error fetching network interface {0} - {1}".format(name, str(exc)))
  848.  
  849. def delete_nic(self, name):
  850. self.log("Deleting network interface {0}".format(name))
  851. self.results['actions'].append("Deleted network interface {0}".format(name))
  852. try:
  853. poller = self.network_client.network_interfaces.delete(self.resource_group, name)
  854. except Exception as exc:
  855. self.fail("Error deleting network interface {0} - {1}".format(name, str(exc)))
  856. self.get_poller_result(poller)
  857. # Delete doesn't return anything. If we get this far, assume success
  858. return True
  859.  
  860. def delete_pip(self, name):
  861. self.results['actions'].append("Deleted public IP {0}".format(name))
  862. try:
  863. poller = self.network_client.public_ip_addresses.delete(self.resource_group, name)
  864. self.get_poller_result(poller)
  865. except Exception as exc:
  866. self.fail("Error deleting {0} - {1}".format(name, str(exc)))
  867. # Delete returns nada. If we get here, assume that all is well.
  868. return True
  869.  
  870. def delete_managed_disks(self, managed_disk_ids):
  871. for mdi in managed_disk_ids:
  872. try:
  873. poller = self.rm_client.resources.delete_by_id(mdi, '2017-03-30')
  874. self.get_poller_result(poller)
  875. except Exception as exc:
  876. self.fail("Error deleting managed disk {0} - {1}".format(mdi, str(exc)))
  877.  
  878. def delete_vm_storage(self, vhd_uris):
  879. # FUTURE: figure out a cloud_env indepdendent way to delete these
  880. for uri in vhd_uris:
  881. self.log("Extracting info from blob uri '{0}'".format(uri))
  882. try:
  883. blob_parts = extract_names_from_blob_uri(uri, self._cloud_environment.suffixes.storage_endpoint)
  884. except Exception as exc:
  885. self.fail("Error parsing blob URI {0}".format(str(exc)))
  886. storage_account_name = blob_parts['accountname']
  887. container_name = blob_parts['containername']
  888. blob_name = blob_parts['blobname']
  889.  
  890. blob_client = self.get_blob_client(self.resource_group, storage_account_name)
  891.  
  892. self.log("Delete blob {0}:{1}".format(container_name, blob_name))
  893. self.results['actions'].append("Deleted blob {0}:{1}".format(container_name, blob_name))
  894. try:
  895. blob_client.delete_blob(container_name, blob_name)
  896. except Exception as exc:
  897. self.fail("Error deleting blob {0}:{1} - {2}".format(container_name, blob_name, str(exc)))
  898.  
  899. def get_marketplace_image_version(self):
  900. try:
  901. versions = self.compute_client.virtual_machine_images.list(self.location,
  902. self.image['publisher'],
  903. self.image['offer'],
  904. self.image['sku'])
  905. except Exception as exc:
  906. self.fail("Error fetching image {0} {1} {2} - {3}".format(self.image['publisher'],
  907. self.image['offer'],
  908. self.image['sku'],
  909. str(exc)))
  910. if versions and len(versions) > 0:
  911. if self.image['version'] == 'latest':
  912. return versions[len(versions) - 1]
  913. for version in versions:
  914. if version.name == self.image['version']:
  915. return version
  916.  
  917. self.fail("Error could not find image {0} {1} {2} {3}".format(self.image['publisher'],
  918. self.image['offer'],
  919. self.image['sku'],
  920. self.image['version']))
  921.  
  922. def get_custom_image_reference(self, name, resource_group=None):
  923. try:
  924. if resource_group:
  925. vm_images = self.compute_client.images.list_by_resource_group(resource_group)
  926. else:
  927. vm_images = self.compute_client.images.list()
  928. except Exception as exc:
  929. self.fail("Error fetching custom images from subscription - {0}".format(str(exc)))
  930.  
  931. for vm_image in vm_images:
  932. if vm_image.name == name:
  933. self.log("Using custom image id {0}".format(vm_image.id))
  934. return self.compute_models.ImageReference(id=vm_image.id)
  935.  
  936. self.fail("Error could not find image with name {0}".format(name))
  937.  
  938. def get_availability_set(self, resource_group, name):
  939. try:
  940. return self.compute_client.availability_sets.get(resource_group, name)
  941. except Exception as exc:
  942. self.fail("Error fetching availability set {0} - {1}".format(name, str(exc)))
  943.  
  944. def get_storage_account(self, name):
  945. try:
  946. account = self.storage_client.storage_accounts.get_properties(self.resource_group,
  947. name)
  948. return account
  949. except Exception as exc:
  950. self.fail("Error fetching storage account {0} - {1}".format(name, str(exc)))
  951.  
  952. def create_or_update_vm(self, params):
  953. try:
  954. poller = self.compute_client.virtual_machines.create_or_update(self.resource_group, self.name, params)
  955. self.get_poller_result(poller)
  956. except Exception as exc:
  957. self.fail("Error creating or updating virtual machine {0} - {1}".format(self.name, str(exc)))
  958.  
  959. def vm_size_is_valid(self):
  960. '''
  961. Validate self.vm_size against the list of virtual machine sizes available for the account and location.
  962.  
  963. :return: boolean
  964. '''
  965. try:
  966. sizes = self.compute_client.virtual_machine_sizes.list(self.location)
  967. except Exception as exc:
  968. self.fail("Error retrieving available machine sizes - {0}".format(str(exc)))
  969. for size in sizes:
  970. if size.name == self.vm_size:
  971. return True
  972. return False
  973.  
  974. def create_default_storage_account(self):
  975. '''
  976. Create a default storage account <vm name>XXXX, where XXXX is a random number. If <vm name>XXXX exists, use it.
  977. Otherwise, create one.
  978.  
  979. :return: storage account object
  980. '''
  981. account = None
  982. valid_name = False
  983.  
  984. # Attempt to find a valid storage account name
  985. storage_account_name_base = re.sub('[^a-zA-Z0-9]', '', self.name[:20].lower())
  986. for i in range(0, 5):
  987. rand = random.randrange(1000, 9999)
  988. storage_account_name = storage_account_name_base + str(rand)
  989. if self.check_storage_account_name(storage_account_name):
  990. valid_name = True
  991. break
  992.  
  993. if not valid_name:
  994. self.fail("Failed to create a unique storage account name for {0}. Try using a different VM name."
  995. .format(self.name))
  996.  
  997. try:
  998. account = self.storage_client.storage_accounts.get_properties(self.resource_group, storage_account_name)
  999. except CloudError:
  1000. pass
  1001.  
  1002. if account:
  1003. self.log("Storage account {0} found.".format(storage_account_name))
  1004. self.check_provisioning_state(account)
  1005. return account
  1006. sku = self.storage_models.Sku(self.storage_models.SkuName.standard_lrs)
  1007. sku.tier = self.storage_models.SkuTier.standard
  1008. kind = self.storage_models.Kind.storage
  1009. parameters = self.storage_models.StorageAccountCreateParameters(sku, kind, self.location)
  1010. self.log("Creating storage account {0} in location {1}".format(storage_account_name, self.location))
  1011. self.results['actions'].append("Created storage account {0}".format(storage_account_name))
  1012. try:
  1013. poller = self.storage_client.storage_accounts.create(self.resource_group, storage_account_name, parameters)
  1014. self.get_poller_result(poller)
  1015. except Exception as exc:
  1016. self.fail("Failed to create storage account: {0} - {1}".format(storage_account_name, str(exc)))
  1017. return self.get_storage_account(storage_account_name)
  1018.  
  1019. def check_storage_account_name(self, name):
  1020. self.log("Checking storage account name availability for {0}".format(name))
  1021. try:
  1022. response = self.storage_client.storage_accounts.check_name_availability(name)
  1023. if response.reason == 'AccountNameInvalid':
  1024. raise Exception("Invalid default storage account name: {0}".format(name))
  1025. except Exception as exc:
  1026. self.fail("Error checking storage account name availability for {0} - {1}".format(name, str(exc)))
  1027.  
  1028. return response.name_available
  1029.  
  1030. def create_default_nic(self):
  1031. '''
  1032. Create a default Network Interface <vm name>01. Requires an existing virtual network
  1033. with one subnet. If NIC <vm name>01 exists, use it. Otherwise, create one.
  1034.  
  1035. :return: NIC object
  1036. '''
  1037.  
  1038. network_interface_name = self.name + '01'
  1039. nic = None
  1040.  
  1041. self.log("Create default NIC {0}".format(network_interface_name))
  1042. self.log("Check to see if NIC {0} exists".format(network_interface_name))
  1043. try:
  1044. nic = self.network_client.network_interfaces.get(self.resource_group, network_interface_name)
  1045. except CloudError:
  1046. pass
  1047.  
  1048. if nic:
  1049. self.log("NIC {0} found.".format(network_interface_name))
  1050. self.check_provisioning_state(nic)
  1051. return nic
  1052.  
  1053. self.log("NIC {0} does not exist.".format(network_interface_name))
  1054.  
  1055. virtual_network_resource_group = None
  1056. if self.virtual_network_resource_group:
  1057. virtual_network_resource_group = self.virtual_network_resource_group
  1058. else:
  1059. virtual_network_resource_group = self.resource_group
  1060.  
  1061. if self.virtual_network_name:
  1062. try:
  1063. self.network_client.virtual_networks.list(virtual_network_resource_group, self.virtual_network_name)
  1064. virtual_network_name = self.virtual_network_name
  1065. except CloudError as exc:
  1066. self.fail("Error: fetching virtual network {0} - {1}".format(self.virtual_network_name, str(exc)))
  1067.  
  1068. else:
  1069. # Find a virtual network
  1070. no_vnets_msg = "Error: unable to find virtual network in resource group {0}. A virtual network " \
  1071. "with at least one subnet must exist in order to create a NIC for the virtual " \
  1072. "machine.".format(virtual_network_resource_group)
  1073.  
  1074. virtual_network_name = None
  1075. try:
  1076. vnets = self.network_client.virtual_networks.list(virtual_network_resource_group)
  1077. except CloudError:
  1078. self.log('cloud error!')
  1079. self.fail(no_vnets_msg)
  1080.  
  1081. for vnet in vnets:
  1082. virtual_network_name = vnet.name
  1083. self.log('vnet name: {0}'.format(vnet.name))
  1084. break
  1085.  
  1086. if not virtual_network_name:
  1087. self.fail(no_vnets_msg)
  1088.  
  1089. if self.subnet_name:
  1090. try:
  1091. subnet = self.network_client.subnets.get(virtual_network_resource_group, virtual_network_name, self.subnet_name)
  1092. subnet_id = subnet.id
  1093. except Exception as exc:
  1094. self.fail("Error: fetching subnet {0} - {1}".format(self.subnet_name, str(exc)))
  1095. else:
  1096. no_subnets_msg = "Error: unable to find a subnet in virtual network {0}. A virtual network " \
  1097. "with at least one subnet must exist in order to create a NIC for the virtual " \
  1098. "machine.".format(virtual_network_name)
  1099.  
  1100. subnet_id = None
  1101. try:
  1102. subnets = self.network_client.subnets.list(virtual_network_resource_group, virtual_network_name)
  1103. except CloudError:
  1104. self.fail(no_subnets_msg)
  1105.  
  1106. for subnet in subnets:
  1107. subnet_id = subnet.id
  1108. self.log('subnet id: {0}'.format(subnet_id))
  1109. break
  1110.  
  1111. if not subnet_id:
  1112. self.fail(no_subnets_msg)
  1113.  
  1114. pip = None
  1115. if self.public_ip_allocation_method != 'Disabled':
  1116. self.results['actions'].append('Created default public IP {0}'.format(self.name + '01'))
  1117. pip_info = self.create_default_pip(self.resource_group, self.location, self.name + '01', self.public_ip_allocation_method)
  1118. pip = self.network_models.PublicIPAddress(id=pip_info.id, location=pip_info.location, resource_guid=pip_info.resource_guid)
  1119.  
  1120. self.results['actions'].append('Created default security group {0}'.format(self.name + '01'))
  1121. group = self.create_default_securitygroup(self.resource_group, self.location, self.name + '01', self.os_type,
  1122. self.open_ports)
  1123.  
  1124. parameters = self.network_models.NetworkInterface(
  1125. location=self.location,
  1126. ip_configurations=[
  1127. self.network_models.NetworkInterfaceIPConfiguration(
  1128. private_ip_allocation_method='Dynamic',
  1129. )
  1130. ]
  1131. )
  1132. parameters.ip_configurations[0].subnet = self.network_models.Subnet(id=subnet_id)
  1133. parameters.ip_configurations[0].name = 'default'
  1134. parameters.network_security_group = self.network_models.NetworkSecurityGroup(id=group.id,
  1135. location=group.location,
  1136. resource_guid=group.resource_guid)
  1137. parameters.ip_configurations[0].public_ip_address = pip
  1138.  
  1139. self.log("Creating NIC {0}".format(network_interface_name))
  1140. self.log(self.serialize_obj(parameters, 'NetworkInterface'), pretty_print=True)
  1141. self.results['actions'].append("Created NIC {0}".format(network_interface_name))
  1142. try:
  1143. poller = self.network_client.network_interfaces.create_or_update(self.resource_group,
  1144. network_interface_name,
  1145. parameters)
  1146. new_nic = self.get_poller_result(poller)
  1147. except Exception as exc:
  1148. self.fail("Error creating network interface {0} - {1}".format(network_interface_name, str(exc)))
  1149. return new_nic
  1150.  
  1151.  
  1152. def main():
  1153. AzureRMVirtualMachine()
  1154.  
  1155.  
  1156. if __name__ == '__main__':
  1157. main()
Add Comment
Please, Sign In to add comment