Fixes #30393: Virtual machine can refer existing NIC from other resource group (#42562)

pull/43522/head
Yuwei Zhou 6 years ago committed by Yunge Zhu
parent 5149ab1e00
commit 7314aa7298

@ -226,9 +226,11 @@ options:
providing a list of ports. providing a list of ports.
network_interface_names: network_interface_names:
description: description:
- List of existing network interface names to add to the VM. If a network interface name is not provided - List of existing network interface names to add to the VM.
when the VM is created, a default network interface will be created. In order for the module to create - Item can be a str of name or resource id of the network interface.
a network interface, at least one Virtual Network with one Subnet must exist. - Item can also be a dict contains C(resource_group) and C(name) of the network interface.
- If a network interface name is not provided when the VM is created, a default network interface will be created.
- In order for the module to create a new network interface, at least one Virtual Network with one Subnet must exist.
aliases: aliases:
- network_interfaces - network_interfaces
virtual_network_resource_group: virtual_network_resource_group:
@ -239,15 +241,17 @@ options:
virtual_network_name: virtual_network_name:
description: description:
- When creating a virtual machine, if a network interface name is not provided, one will be created. - When creating a virtual machine, if a network interface name is not provided, one will be created.
The new network interface will be assigned to the first virtual network found in the resource group. - The network interface will be assigned to the first virtual network found in the resource group.
Use this parameter to provide a specific virtual network instead. - Use this parameter to provide a specific virtual network instead.
- If the virtual network in in another resource group, specific resource group by C(virtual_network_resource_group).
aliases: aliases:
- virtual_network - virtual_network
subnet_name: subnet_name:
description: description:
- When creating a virtual machine, if a network interface name is not provided, one will be created. - When creating a virtual machine, if a network interface name is not provided, one will be created.
The new network interface will be assigned to the first subnet found in the virtual network. - The new network interface will be assigned to the first subnet found in the virtual network.
Use this parameter to provide a specific subnet instead. - Use this parameter to provide a specific subnet instead.
- If the subnet is in another resource group, specific resource group by C(virtual_network_resource_group).
aliases: aliases:
- subnet - subnet
remove_on_absent: remove_on_absent:
@ -614,7 +618,7 @@ except ImportError:
pass pass
from ansible.module_utils.basic import to_native, to_bytes from ansible.module_utils.basic import to_native, to_bytes
from ansible.module_utils.azure_rm_common import AzureRMModuleBase, azure_id_to_dict, normalize_location_name from ansible.module_utils.azure_rm_common import AzureRMModuleBase, azure_id_to_dict, normalize_location_name, format_resource_id
AZURE_OBJECT_CLASS = 'VirtualMachine' AZURE_OBJECT_CLASS = 'VirtualMachine'
@ -660,7 +664,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
public_ip_allocation_method=dict(type='str', choices=['Dynamic', 'Static', 'Disabled'], default='Static', public_ip_allocation_method=dict(type='str', choices=['Dynamic', 'Static', 'Disabled'], default='Static',
aliases=['public_ip_allocation']), aliases=['public_ip_allocation']),
open_ports=dict(type='list'), open_ports=dict(type='list'),
network_interface_names=dict(type='list', aliases=['network_interfaces']), network_interface_names=dict(type='list', aliases=['network_interfaces'], elements='raw'),
remove_on_absent=dict(type='list', default=['all']), remove_on_absent=dict(type='list', default=['all']),
virtual_network_resource_group=dict(type='str'), virtual_network_resource_group=dict(type='str'),
virtual_network_name=dict(type='str', aliases=['virtual_network']), virtual_network_name=dict(type='str', aliases=['virtual_network']),
@ -753,9 +757,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
)) ))
if self.network_interface_names: if self.network_interface_names:
for name in self.network_interface_names: for nic_name in self.network_interface_names:
nic = self.get_network_interface(name) nic = self.parse_network_interface(nic_name)
network_interfaces.append(nic.id) network_interfaces.append(nic)
if self.ssh_public_keys: if self.ssh_public_keys:
msg = "Parameter error: expecting ssh_public_keys to be a list of type dict where " \ msg = "Parameter error: expecting ssh_public_keys to be a list of type dict where " \
@ -1241,7 +1245,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
# Expand network interfaces to include config properties # Expand network interfaces to include config properties
for interface in vm.network_profile.network_interfaces: for interface in vm.network_profile.network_interfaces:
int_dict = azure_id_to_dict(interface.id) int_dict = azure_id_to_dict(interface.id)
nic = self.get_network_interface(int_dict['networkInterfaces']) nic = self.get_network_interface(int_dict['resourceGroups'], int_dict['networkInterfaces'])
for interface_dict in result['properties']['networkProfile']['networkInterfaces']: for interface_dict in result['properties']['networkProfile']['networkInterfaces']:
if interface_dict['id'] == interface.id: if interface_dict['id'] == interface.id:
nic_dict = self.serialize_obj(nic, 'NetworkInterface') nic_dict = self.serialize_obj(nic, 'NetworkInterface')
@ -1254,7 +1258,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
if config['properties'].get('publicIPAddress'): if config['properties'].get('publicIPAddress'):
pipid_dict = azure_id_to_dict(config['properties']['publicIPAddress']['id']) pipid_dict = azure_id_to_dict(config['properties']['publicIPAddress']['id'])
try: try:
pip = self.network_client.public_ip_addresses.get(self.resource_group, pip = self.network_client.public_ip_addresses.get(pipid_dict['resourceGroups'],
pipid_dict['publicIPAddresses']) pipid_dict['publicIPAddresses'])
except Exception as exc: except Exception as exc:
self.fail("Error fetching public ip {0} - {1}".format(pipid_dict['publicIPAddresses'], self.fail("Error fetching public ip {0} - {1}".format(pipid_dict['publicIPAddresses'],
@ -1341,18 +1345,18 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
self.log('Storing NIC names for deletion.') self.log('Storing NIC names for deletion.')
for interface in vm.network_profile.network_interfaces: for interface in vm.network_profile.network_interfaces:
id_dict = azure_id_to_dict(interface.id) id_dict = azure_id_to_dict(interface.id)
nic_names.append(id_dict['networkInterfaces']) nic_names.append(dict(name=id_dict['networkInterfaces'], resource_group=id_dict['resourceGroups']))
self.log('NIC names to delete {0}'.format(', '.join(nic_names))) self.log('NIC names to delete {0}'.format(str(nic_names)))
self.results['deleted_network_interfaces'] = nic_names self.results['deleted_network_interfaces'] = nic_names
if self.remove_on_absent.intersection(set(['all', 'public_ips'])): if self.remove_on_absent.intersection(set(['all', 'public_ips'])):
# also store each nic's attached public IPs and delete after the NIC is gone # also store each nic's attached public IPs and delete after the NIC is gone
for name in nic_names: for nic_dict in nic_names:
nic = self.get_network_interface(name) nic = self.get_network_interface(nic_dict['resource_group'], nic_dict['name'])
for ipc in nic.ip_configurations: for ipc in nic.ip_configurations:
if ipc.public_ip_address: if ipc.public_ip_address:
pip_dict = azure_id_to_dict(ipc.public_ip_address.id) pip_dict = azure_id_to_dict(ipc.public_ip_address.id)
pip_names.append(pip_dict['publicIPAddresses']) pip_names.append(dict(name=pip_dict['publicIPAddresses'], resource_group=pip_dict['resourceGroups']))
self.log('Public IPs to delete are {0}'.format(', '.join(pip_names))) self.log('Public IPs to delete are {0}'.format(str(pip_names)))
self.results['deleted_public_ips'] = pip_names self.results['deleted_public_ips'] = pip_names
self.log("Deleting virtual machine {0}".format(self.name)) self.log("Deleting virtual machine {0}".format(self.name))
@ -1374,37 +1378,37 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
if self.remove_on_absent.intersection(set(['all', 'network_interfaces'])): if self.remove_on_absent.intersection(set(['all', 'network_interfaces'])):
self.log('Deleting network interfaces') self.log('Deleting network interfaces')
for name in nic_names: for nic_dict in nic_names:
self.delete_nic(name) self.delete_nic(nic_dict['resource_group'], nic_dict['name'])
if self.remove_on_absent.intersection(set(['all', 'public_ips'])): if self.remove_on_absent.intersection(set(['all', 'public_ips'])):
self.log('Deleting public IPs') self.log('Deleting public IPs')
for name in pip_names: for pip_dict in pip_names:
self.delete_pip(name) self.delete_pip(pip_dict['resource_group'], pip_dict['name'])
return True return True
def get_network_interface(self, name): def get_network_interface(self, resource_group, name):
try: try:
nic = self.network_client.network_interfaces.get(self.resource_group, name) nic = self.network_client.network_interfaces.get(resource_group, name)
return nic return nic
except Exception as exc: except Exception as exc:
self.fail("Error fetching network interface {0} - {1}".format(name, str(exc))) self.fail("Error fetching network interface {0} - {1}".format(name, str(exc)))
def delete_nic(self, name): def delete_nic(self, resource_group, name):
self.log("Deleting network interface {0}".format(name)) self.log("Deleting network interface {0}".format(name))
self.results['actions'].append("Deleted network interface {0}".format(name)) self.results['actions'].append("Deleted network interface {0}".format(name))
try: try:
poller = self.network_client.network_interfaces.delete(self.resource_group, name) poller = self.network_client.network_interfaces.delete(resource_group, name)
except Exception as exc: except Exception as exc:
self.fail("Error deleting network interface {0} - {1}".format(name, str(exc))) self.fail("Error deleting network interface {0} - {1}".format(name, str(exc)))
self.get_poller_result(poller) self.get_poller_result(poller)
# Delete doesn't return anything. If we get this far, assume success # Delete doesn't return anything. If we get this far, assume success
return True return True
def delete_pip(self, name): def delete_pip(self, resource_group, name):
self.results['actions'].append("Deleted public IP {0}".format(name)) self.results['actions'].append("Deleted public IP {0}".format(name))
try: try:
poller = self.network_client.public_ip_addresses.delete(self.resource_group, name) poller = self.network_client.public_ip_addresses.delete(resource_group, name)
self.get_poller_result(poller) self.get_poller_result(poller)
except Exception as exc: except Exception as exc:
self.fail("Error deleting {0} - {1}".format(name, str(exc))) self.fail("Error deleting {0} - {1}".format(name, str(exc)))
@ -1692,6 +1696,16 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
self.fail("Error creating network interface {0} - {1}".format(network_interface_name, str(exc))) self.fail("Error creating network interface {0} - {1}".format(network_interface_name, str(exc)))
return new_nic return new_nic
def parse_network_interface(self, nic):
nic = self.parse_resource_to_dict(nic)
if 'name' not in nic:
self.fail("Invalid network interface {0}".format(str(nic)))
return format_resource_id(val=nic['name'],
subscription_id=nic['subscription_id'],
resource_group=nic['resource_group'],
namespace='Microsoft.Network',
types='networkInterfaces')
def main(): def main():
AzureRMVirtualMachine() AzureRMVirtualMachine()

@ -256,23 +256,38 @@
state: absent state: absent
vm_size: Standard_A0 vm_size: Standard_A0
- set_fact:
niclist:
- name: testvm011
resource_group: "{{ resource_group_secondary }}"
- name: testvm012
resource_group: "{{ resource_group_secondary }}"
- name: Create virtual network
azure_rm_virtualnetwork:
resource_group: "{{ resource_group_secondary }}"
name: testvm001
address_prefixes: "10.10.0.0/16"
register: vn
- name: Add subnet
azure_rm_subnet:
resource_group: "{{ resource_group_secondary }}"
name: testvm001
address_prefix: "10.10.0.0/24"
virtual_network: testvm001
- name: Create NICs for dual nic VM - name: Create NICs for dual nic VM
azure_rm_networkinterface: azure_rm_networkinterface:
resource_group: "{{ resource_group }}" resource_group: "{{ item.resource_group }}"
name: "{{ item }}" name: "{{ item.name }}"
virtual_network: testvm001 virtual_network: "{{ vn.state.id }}"
subnet: testvm001 subnet: testvm001
security_group: testvm001 security_group: testvm001
loop: loop: "{{ niclist }}"
- testvm011
- testvm012
- name: Create virtual machine with two NICs - name: Create virtual machine with two NICs
register: output register: output
vars:
niclist:
- testvm011
- testvm012
azure_rm_virtualmachine: azure_rm_virtualmachine:
resource_group: "{{ resource_group }}" resource_group: "{{ resource_group }}"
name: testvm003 name: testvm003
@ -315,10 +330,6 @@
- results.vms[0].admin_username == 'adminuser' - results.vms[0].admin_username == 'adminuser'
- name: Should be idempotent with a dual NICs - name: Should be idempotent with a dual NICs
vars:
niclist:
- testvm011
- testvm012
azure_rm_virtualmachine: azure_rm_virtualmachine:
resource_group: "{{ resource_group }}" resource_group: "{{ resource_group }}"
name: testvm003 name: testvm003

Loading…
Cancel
Save