new module vmware_dvswitch_pvlans (#48855)
This commit is contained in:
parent
b67719ba1d
commit
1b9b0b85c4
3 changed files with 667 additions and 0 deletions
533
lib/ansible/modules/cloud/vmware/vmware_dvswitch_pvlans.py
Normal file
533
lib/ansible/modules/cloud/vmware/vmware_dvswitch_pvlans.py
Normal file
|
@ -0,0 +1,533 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de>
|
||||
#
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'
|
||||
}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: vmware_dvswitch_pvlans
|
||||
short_description: Manage Private VLAN configuration of a Distributed Switch
|
||||
description:
|
||||
- This module can be used to configure Private VLANs (PVLANs) on a Distributed Switch.
|
||||
version_added: 2.8
|
||||
author:
|
||||
- Christian Kotte (@ckotte)
|
||||
notes:
|
||||
- Tested on vSphere 6.5 and 6.7
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- PyVmomi
|
||||
options:
|
||||
switch:
|
||||
description:
|
||||
- The name of the Distributed Switch.
|
||||
type: str
|
||||
required: True
|
||||
aliases: ['dvswitch']
|
||||
primary_pvlans:
|
||||
description:
|
||||
- A list of VLAN IDs that should be configured as Primary PVLANs.
|
||||
- If C(primary_pvlans) isn't specified, all PVLANs will be deleted if present.
|
||||
- Each member of the list requires primary_pvlan_id (int) set.
|
||||
- The secondary promiscuous PVLAN will be created automatically.
|
||||
- If C(secondary_pvlans) isn't specified, the primary PVLANs and each secondary promiscuous PVLAN will be created.
|
||||
- Please see examples for more information.
|
||||
type: list
|
||||
default: []
|
||||
secondary_pvlans:
|
||||
description:
|
||||
- A list of VLAN IDs that should be configured as Secondary PVLANs.
|
||||
- 'C(primary_pvlans) need to be specified to create any Secodary PVLAN.'
|
||||
- If C(primary_pvlans) isn't specified, all PVLANs will be deleted if present.
|
||||
- Each member of the list requires primary_pvlan_id (int), secondary_pvlan_id (int), and pvlan_type (str) to be set.
|
||||
- The type of the secondary PVLAN can be isolated or community. The secondary promiscuous PVLAN will be created automatically.
|
||||
- Please see examples for more information.
|
||||
type: list
|
||||
default: []
|
||||
extends_documentation_fragment: vmware.documentation
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Create PVLANs on a Distributed Switch
|
||||
vmware_dvswitch_pvlans:
|
||||
hostname: '{{ inventory_hostname }}'
|
||||
username: '{{ vcenter_username }}'
|
||||
password: '{{ vcenter_password }}'
|
||||
switch: dvSwitch
|
||||
primary_pvlans:
|
||||
- primary_pvlan_id: 1
|
||||
- primary_pvlan_id: 4
|
||||
secondary_pvlans:
|
||||
- primary_pvlan_id: 1
|
||||
secondary_pvlan_id: 2
|
||||
pvlan_type: isolated
|
||||
- primary_pvlan_id: 1
|
||||
secondary_pvlan_id: 3
|
||||
pvlan_type: community
|
||||
- primary_pvlan_id: 4
|
||||
secondary_pvlan_id: 5
|
||||
pvlan_type: community
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Create primary PVLAN and secondary promiscuous PVLAN on a Distributed Switch
|
||||
vmware_dvswitch_pvlans:
|
||||
hostname: '{{ inventory_hostname }}'
|
||||
username: '{{ vcenter_username }}'
|
||||
password: '{{ vcenter_password }}'
|
||||
switch: dvSwitch
|
||||
primary_pvlans:
|
||||
- primary_pvlan_id: 1
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Remove all PVLANs from a Distributed Switch
|
||||
vmware_dvswitch_pvlans:
|
||||
hostname: '{{ inventory_hostname }}'
|
||||
username: '{{ vcenter_username }}'
|
||||
password: '{{ vcenter_password }}'
|
||||
switch: dvSwitch
|
||||
primary_pvlans: []
|
||||
secondary_pvlans: []
|
||||
delegate_to: localhost
|
||||
'''
|
||||
|
||||
RETURN = """
|
||||
result:
|
||||
description: information about performed operation
|
||||
returned: always
|
||||
type: string
|
||||
sample: {
|
||||
"changed": true,
|
||||
"dvswitch": "dvSwitch",
|
||||
"private_vlans": [
|
||||
{
|
||||
"primary_pvlan_id": 1,
|
||||
"pvlan_type": "promiscuous",
|
||||
"secondary_pvlan_id": 1
|
||||
},
|
||||
{
|
||||
"primary_pvlan_id": 1,
|
||||
"pvlan_type": "isolated",
|
||||
"secondary_pvlan_id": 2
|
||||
},
|
||||
{
|
||||
"primary_pvlan_id": 1,
|
||||
"pvlan_type": "community",
|
||||
"secondary_pvlan_id": 3
|
||||
}
|
||||
],
|
||||
"private_vlans_previous": [],
|
||||
"result": "All private VLANs added"
|
||||
}
|
||||
"""
|
||||
|
||||
try:
|
||||
from pyVmomi import vim
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.vmware import (
|
||||
PyVmomi, TaskError, find_dvs_by_name, vmware_argument_spec, wait_for_task
|
||||
)
|
||||
|
||||
|
||||
class VMwareDvSwitchPvlans(PyVmomi):
|
||||
"""Class to manage Private VLANs on a Distributed Virtual Switch"""
|
||||
|
||||
def __init__(self, module):
|
||||
super(VMwareDvSwitchPvlans, self).__init__(module)
|
||||
self.switch_name = self.module.params['switch']
|
||||
if self.module.params['primary_pvlans']:
|
||||
self.primary_pvlans = self.module.params['primary_pvlans']
|
||||
if self.module.params['secondary_pvlans']:
|
||||
self.secondary_pvlans = self.module.params['secondary_pvlans']
|
||||
else:
|
||||
self.secondary_pvlans = None
|
||||
self.do_pvlan_sanity_checks()
|
||||
else:
|
||||
self.primary_pvlans = None
|
||||
self.secondary_pvlans = None
|
||||
self.dvs = find_dvs_by_name(self.content, self.switch_name)
|
||||
if self.dvs is None:
|
||||
self.module.fail_json(msg="Failed to find DVS %s" % self.switch_name)
|
||||
|
||||
def do_pvlan_sanity_checks(self):
|
||||
"""Do sanity checks for primary and secondary PVLANs"""
|
||||
# Check if primary PVLANs are unique
|
||||
for primary_vlan in self.primary_pvlans:
|
||||
count = 0
|
||||
primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan)
|
||||
for primary_vlan_2 in self.primary_pvlans:
|
||||
primary_pvlan_id_2 = self.get_primary_pvlan_option(primary_vlan_2)
|
||||
if primary_pvlan_id == primary_pvlan_id_2:
|
||||
count += 1
|
||||
if count > 1:
|
||||
self.module.fail_json(
|
||||
msg="The primary PVLAN ID '%s' must be unique!" % primary_pvlan_id
|
||||
)
|
||||
if self.secondary_pvlans:
|
||||
# Check if secondary PVLANs are unique
|
||||
for secondary_pvlan in self.secondary_pvlans:
|
||||
count = 0
|
||||
result = self.get_secondary_pvlan_options(secondary_pvlan)
|
||||
for secondary_pvlan_2 in self.secondary_pvlans:
|
||||
result_2 = self.get_secondary_pvlan_options(secondary_pvlan_2)
|
||||
if result[0] == result_2[0]:
|
||||
count += 1
|
||||
if count > 1:
|
||||
self.module.fail_json(
|
||||
msg="The secondary PVLAN ID '%s' must be unique!" % result[0]
|
||||
)
|
||||
# Check if secondary PVLANs are already used as primary PVLANs
|
||||
for primary_vlan in self.primary_pvlans:
|
||||
primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan)
|
||||
for secondary_pvlan in self.secondary_pvlans:
|
||||
result = self.get_secondary_pvlan_options(secondary_pvlan)
|
||||
if primary_pvlan_id == result[0]:
|
||||
self.module.fail_json(
|
||||
msg="The secondary PVLAN ID '%s' is already used as a primary PVLAN!" %
|
||||
result[0]
|
||||
)
|
||||
# Check if a primary PVLAN is present for every secondary PVLANs
|
||||
for secondary_pvlan in self.secondary_pvlans:
|
||||
primary_pvlan_found = False
|
||||
result = self.get_secondary_pvlan_options(secondary_pvlan)
|
||||
for primary_vlan in self.primary_pvlans:
|
||||
primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan)
|
||||
if result[1] == primary_pvlan_id:
|
||||
primary_pvlan_found = True
|
||||
break
|
||||
if not primary_pvlan_found:
|
||||
self.module.fail_json(
|
||||
msg="The primary PVLAN ID '%s' isn't defined for the secondary PVLAN ID '%s'!" %
|
||||
(result[1], result[0])
|
||||
)
|
||||
|
||||
def ensure(self):
|
||||
"""Manage Private VLANs"""
|
||||
changed = False
|
||||
results = dict(changed=changed)
|
||||
results['dvswitch'] = self.switch_name
|
||||
changed_list_add = []
|
||||
changed_list_remove = []
|
||||
|
||||
config_spec = vim.dvs.VmwareDistributedVirtualSwitch.ConfigSpec()
|
||||
# Use the same version in the new spec; The version will be increased by one by the API automatically
|
||||
config_spec.configVersion = self.dvs.config.configVersion
|
||||
|
||||
# Check Private VLANs
|
||||
results['private_vlans'] = None
|
||||
if self.primary_pvlans:
|
||||
desired_pvlan_list = []
|
||||
for primary_vlan in self.primary_pvlans:
|
||||
primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan)
|
||||
temp_pvlan = dict()
|
||||
temp_pvlan['primary_pvlan_id'] = primary_pvlan_id
|
||||
temp_pvlan['secondary_pvlan_id'] = primary_pvlan_id
|
||||
temp_pvlan['pvlan_type'] = 'promiscuous'
|
||||
desired_pvlan_list.append(temp_pvlan)
|
||||
if self.secondary_pvlans:
|
||||
for secondary_pvlan in self.secondary_pvlans:
|
||||
(secondary_pvlan_id,
|
||||
secondary_vlan_primary_vlan_id,
|
||||
pvlan_type) = self.get_secondary_pvlan_options(secondary_pvlan)
|
||||
temp_pvlan = dict()
|
||||
temp_pvlan['primary_pvlan_id'] = secondary_vlan_primary_vlan_id
|
||||
temp_pvlan['secondary_pvlan_id'] = secondary_pvlan_id
|
||||
temp_pvlan['pvlan_type'] = pvlan_type
|
||||
desired_pvlan_list.append(temp_pvlan)
|
||||
results['private_vlans'] = desired_pvlan_list
|
||||
if self.dvs.config.pvlanConfig:
|
||||
pvlan_spec_list = []
|
||||
# Check if desired PVLANs are configured
|
||||
for primary_vlan in self.primary_pvlans:
|
||||
primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan)
|
||||
promiscuous_found = other_found = False
|
||||
for pvlan_object in self.dvs.config.pvlanConfig:
|
||||
if pvlan_object.primaryVlanId == primary_pvlan_id and pvlan_object.pvlanType == 'promiscuous':
|
||||
promiscuous_found = True
|
||||
break
|
||||
if not promiscuous_found:
|
||||
changed = True
|
||||
changed_list_add.append('promiscuous (%s, %s)' % (primary_pvlan_id, primary_pvlan_id))
|
||||
pvlan_spec_list.append(
|
||||
self.create_pvlan_config_spec(
|
||||
operation='add',
|
||||
primary_pvlan_id=primary_pvlan_id,
|
||||
secondary_pvlan_id=primary_pvlan_id,
|
||||
pvlan_type='promiscuous'
|
||||
)
|
||||
)
|
||||
if self.secondary_pvlans:
|
||||
for secondary_pvlan in self.secondary_pvlans:
|
||||
(secondary_pvlan_id,
|
||||
secondary_vlan_primary_vlan_id,
|
||||
pvlan_type) = self.get_secondary_pvlan_options(secondary_pvlan)
|
||||
if primary_pvlan_id == secondary_vlan_primary_vlan_id:
|
||||
for pvlan_object_2 in self.dvs.config.pvlanConfig:
|
||||
if (pvlan_object_2.primaryVlanId == secondary_vlan_primary_vlan_id
|
||||
and pvlan_object_2.secondaryVlanId == secondary_pvlan_id
|
||||
and pvlan_object_2.pvlanType == pvlan_type):
|
||||
other_found = True
|
||||
break
|
||||
if not other_found:
|
||||
changed = True
|
||||
changed_list_add.append(
|
||||
'%s (%s, %s)' % (pvlan_type, primary_pvlan_id, secondary_pvlan_id)
|
||||
)
|
||||
pvlan_spec_list.append(
|
||||
self.create_pvlan_config_spec(
|
||||
operation='add',
|
||||
primary_pvlan_id=primary_pvlan_id,
|
||||
secondary_pvlan_id=secondary_pvlan_id,
|
||||
pvlan_type=pvlan_type
|
||||
)
|
||||
)
|
||||
# Check if a PVLAN needs to be removed
|
||||
for pvlan_object in self.dvs.config.pvlanConfig:
|
||||
promiscuous_found = other_found = False
|
||||
if (pvlan_object.primaryVlanId == pvlan_object.secondaryVlanId
|
||||
and pvlan_object.pvlanType == 'promiscuous'):
|
||||
for primary_vlan in self.primary_pvlans:
|
||||
primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan)
|
||||
if pvlan_object.primaryVlanId == primary_pvlan_id and pvlan_object.pvlanType == 'promiscuous':
|
||||
promiscuous_found = True
|
||||
break
|
||||
if not promiscuous_found:
|
||||
changed = True
|
||||
changed_list_remove.append(
|
||||
'promiscuous (%s, %s)' % (pvlan_object.primaryVlanId, pvlan_object.secondaryVlanId)
|
||||
)
|
||||
pvlan_spec_list.append(
|
||||
self.create_pvlan_config_spec(
|
||||
operation='remove',
|
||||
primary_pvlan_id=pvlan_object.primaryVlanId,
|
||||
secondary_pvlan_id=pvlan_object.secondaryVlanId,
|
||||
pvlan_type='promiscuous'
|
||||
)
|
||||
)
|
||||
elif self.secondary_pvlans:
|
||||
for secondary_pvlan in self.secondary_pvlans:
|
||||
(secondary_pvlan_id,
|
||||
secondary_vlan_primary_vlan_id,
|
||||
pvlan_type) = self.get_secondary_pvlan_options(secondary_pvlan)
|
||||
if (pvlan_object.primaryVlanId == secondary_vlan_primary_vlan_id
|
||||
and pvlan_object.secondaryVlanId == secondary_pvlan_id
|
||||
and pvlan_object.pvlanType == pvlan_type):
|
||||
other_found = True
|
||||
break
|
||||
if not other_found:
|
||||
changed = True
|
||||
changed_list_remove.append(
|
||||
'%s (%s, %s)' % (
|
||||
pvlan_object.pvlanType, pvlan_object.primaryVlanId, pvlan_object.secondaryVlanId
|
||||
)
|
||||
)
|
||||
pvlan_spec_list.append(
|
||||
self.create_pvlan_config_spec(
|
||||
operation='remove',
|
||||
primary_pvlan_id=pvlan_object.primaryVlanId,
|
||||
secondary_pvlan_id=pvlan_object.secondaryVlanId,
|
||||
pvlan_type=pvlan_object.pvlanType
|
||||
)
|
||||
)
|
||||
else:
|
||||
changed = True
|
||||
changed_list_remove.append(
|
||||
'%s (%s, %s)' % (
|
||||
pvlan_object.pvlanType, pvlan_object.primaryVlanId, pvlan_object.secondaryVlanId
|
||||
)
|
||||
)
|
||||
pvlan_spec_list.append(
|
||||
self.create_pvlan_config_spec(
|
||||
operation='remove',
|
||||
primary_pvlan_id=pvlan_object.primaryVlanId,
|
||||
secondary_pvlan_id=pvlan_object.secondaryVlanId,
|
||||
pvlan_type=pvlan_object.pvlanType
|
||||
)
|
||||
)
|
||||
else:
|
||||
changed = True
|
||||
changed_list_add.append('All private VLANs')
|
||||
pvlan_spec_list = []
|
||||
for primary_vlan in self.primary_pvlans:
|
||||
# the first secondary VLAN's type is always promiscuous
|
||||
primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan)
|
||||
pvlan_spec_list.append(
|
||||
self.create_pvlan_config_spec(
|
||||
operation='add',
|
||||
primary_pvlan_id=primary_pvlan_id,
|
||||
secondary_pvlan_id=primary_pvlan_id,
|
||||
pvlan_type='promiscuous'
|
||||
)
|
||||
)
|
||||
if self.secondary_pvlans:
|
||||
for secondary_pvlan in self.secondary_pvlans:
|
||||
(secondary_pvlan_id,
|
||||
secondary_vlan_primary_vlan_id,
|
||||
pvlan_type) = self.get_secondary_pvlan_options(secondary_pvlan)
|
||||
if primary_pvlan_id == secondary_vlan_primary_vlan_id:
|
||||
pvlan_spec_list.append(
|
||||
self.create_pvlan_config_spec(
|
||||
operation='add',
|
||||
primary_pvlan_id=primary_pvlan_id,
|
||||
secondary_pvlan_id=secondary_pvlan_id,
|
||||
pvlan_type=pvlan_type
|
||||
)
|
||||
)
|
||||
else:
|
||||
# Remove PVLAN configuration if present
|
||||
if self.dvs.config.pvlanConfig:
|
||||
changed = True
|
||||
changed_list_remove.append('All private VLANs')
|
||||
pvlan_spec_list = []
|
||||
for pvlan_object in self.dvs.config.pvlanConfig:
|
||||
pvlan_spec_list.append(
|
||||
self.create_pvlan_config_spec(
|
||||
operation='remove',
|
||||
primary_pvlan_id=pvlan_object.primaryVlanId,
|
||||
secondary_pvlan_id=pvlan_object.secondaryVlanId,
|
||||
pvlan_type=pvlan_object.pvlanType
|
||||
)
|
||||
)
|
||||
|
||||
if changed:
|
||||
message_add = message_remove = None
|
||||
if changed_list_add:
|
||||
message_add = self.build_change_message('add', changed_list_add)
|
||||
if changed_list_remove:
|
||||
message_remove = self.build_change_message('remove', changed_list_remove)
|
||||
if message_add and message_remove:
|
||||
message = message_add + '. ' + message_remove + '.'
|
||||
elif message_add:
|
||||
message = message_add
|
||||
elif message_remove:
|
||||
message = message_remove
|
||||
current_pvlan_list = []
|
||||
for pvlan_object in self.dvs.config.pvlanConfig:
|
||||
temp_pvlan = dict()
|
||||
temp_pvlan['primary_pvlan_id'] = pvlan_object.primaryVlanId
|
||||
temp_pvlan['secondary_pvlan_id'] = pvlan_object.secondaryVlanId
|
||||
temp_pvlan['pvlan_type'] = pvlan_object.pvlanType
|
||||
current_pvlan_list.append(temp_pvlan)
|
||||
results['private_vlans_previous'] = current_pvlan_list
|
||||
config_spec.pvlanConfigSpec = pvlan_spec_list
|
||||
if not self.module.check_mode:
|
||||
try:
|
||||
task = self.dvs.ReconfigureDvs_Task(config_spec)
|
||||
wait_for_task(task)
|
||||
except TaskError as invalid_argument:
|
||||
self.module.fail_json(
|
||||
msg="Failed to update DVS : %s" % to_native(invalid_argument)
|
||||
)
|
||||
else:
|
||||
message = "PVLANs already configured properly"
|
||||
results['changed'] = changed
|
||||
results['result'] = message
|
||||
|
||||
self.module.exit_json(**results)
|
||||
|
||||
def get_primary_pvlan_option(self, primary_vlan):
|
||||
"""Get Primary PVLAN option"""
|
||||
primary_pvlan_id = primary_vlan.get('primary_pvlan_id', None)
|
||||
if primary_pvlan_id is None:
|
||||
self.module.fail_json(
|
||||
msg="Please specify primary_pvlan_id in primary_pvlans options as it's a required parameter"
|
||||
)
|
||||
if primary_pvlan_id in (0, 4095):
|
||||
self.module.fail_json(msg="The VLAN IDs of 0 and 4095 are reserved and cannot be used as a primary PVLAN.")
|
||||
return primary_pvlan_id
|
||||
|
||||
def get_secondary_pvlan_options(self, secondary_pvlan):
|
||||
"""Get Secondary PVLAN option"""
|
||||
secondary_pvlan_id = secondary_pvlan.get('secondary_pvlan_id', None)
|
||||
if secondary_pvlan_id is None:
|
||||
self.module.fail_json(
|
||||
msg="Please specify secondary_pvlan_id in secondary_pvlans options as it's a required parameter"
|
||||
)
|
||||
primary_pvlan_id = secondary_pvlan.get('primary_pvlan_id', None)
|
||||
if primary_pvlan_id is None:
|
||||
self.module.fail_json(
|
||||
msg="Please specify primary_pvlan_id in secondary_pvlans options as it's a required parameter"
|
||||
)
|
||||
if secondary_pvlan_id in (0, 4095) or primary_pvlan_id in (0, 4095):
|
||||
self.module.fail_json(
|
||||
msg="The VLAN IDs of 0 and 4095 are reserved and cannot be used as a primary or secondary PVLAN."
|
||||
)
|
||||
pvlan_type = secondary_pvlan.get('pvlan_type', None)
|
||||
supported_pvlan_types = ['isolated', 'community']
|
||||
if pvlan_type is None:
|
||||
self.module.fail_json(msg="Please specify pvlan_type in secondary_pvlans options as it's a required parameter")
|
||||
elif pvlan_type not in supported_pvlan_types:
|
||||
self.module.fail_json(msg="The specified PVLAN type '%s' isn't supported!" % pvlan_type)
|
||||
return secondary_pvlan_id, primary_pvlan_id, pvlan_type
|
||||
|
||||
@staticmethod
|
||||
def create_pvlan_config_spec(operation, primary_pvlan_id, secondary_pvlan_id, pvlan_type):
|
||||
"""
|
||||
Create PVLAN config spec
|
||||
operation: add, edit, or remove
|
||||
Returns: PVLAN config spec
|
||||
"""
|
||||
pvlan_spec = vim.dvs.VmwareDistributedVirtualSwitch.PvlanConfigSpec()
|
||||
pvlan_spec.operation = operation
|
||||
pvlan_spec.pvlanEntry = vim.dvs.VmwareDistributedVirtualSwitch.PvlanMapEntry()
|
||||
pvlan_spec.pvlanEntry.primaryVlanId = primary_pvlan_id
|
||||
pvlan_spec.pvlanEntry.secondaryVlanId = secondary_pvlan_id
|
||||
pvlan_spec.pvlanEntry.pvlanType = pvlan_type
|
||||
return pvlan_spec
|
||||
|
||||
def build_change_message(self, operation, changed_list):
|
||||
"""Build the changed message"""
|
||||
if operation == 'add':
|
||||
changed_operation = 'added'
|
||||
elif operation == 'remove':
|
||||
changed_operation = 'removed'
|
||||
if self.module.check_mode:
|
||||
changed_suffix = ' would be %s' % changed_operation
|
||||
else:
|
||||
changed_suffix = ' %s' % changed_operation
|
||||
if len(changed_list) > 2:
|
||||
message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1])
|
||||
elif len(changed_list) == 2:
|
||||
message = ' and '.join(changed_list)
|
||||
elif len(changed_list) == 1:
|
||||
message = changed_list[0]
|
||||
message += changed_suffix
|
||||
return message
|
||||
|
||||
|
||||
def main():
|
||||
"""Main"""
|
||||
argument_spec = vmware_argument_spec()
|
||||
argument_spec.update(
|
||||
dict(
|
||||
switch=dict(required=True, aliases=['dvswitch']),
|
||||
primary_pvlans=dict(type='list', default=list(), required=False),
|
||||
secondary_pvlans=dict(type='list', default=list(), required=False),
|
||||
)
|
||||
)
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=argument_spec,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
vmware_dvswitch_pvlans = VMwareDvSwitchPvlans(module)
|
||||
vmware_dvswitch_pvlans.ensure()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
2
test/integration/targets/vmware_dvswitch_pvlans/aliases
Normal file
2
test/integration/targets/vmware_dvswitch_pvlans/aliases
Normal file
|
@ -0,0 +1,2 @@
|
|||
cloud/vcenter
|
||||
unsupported
|
132
test/integration/targets/vmware_dvswitch_pvlans/tasks/main.yml
Normal file
132
test/integration/targets/vmware_dvswitch_pvlans/tasks/main.yml
Normal file
|
@ -0,0 +1,132 @@
|
|||
# Test code for the vmware_dvswitch_pvlans module.
|
||||
# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
- name: store the vcenter container ip
|
||||
set_fact:
|
||||
vcsim: "{{ lookup('env', 'vcenter_host') }}"
|
||||
|
||||
- debug: var=vcsim
|
||||
|
||||
- name: Wait for Flask controller to come up online
|
||||
wait_for:
|
||||
host: "{{ vcsim }}"
|
||||
port: 5000
|
||||
state: started
|
||||
|
||||
- name: kill vcsim
|
||||
uri:
|
||||
url: http://{{ vcsim }}:5000/killall
|
||||
|
||||
- name: start vcsim
|
||||
uri:
|
||||
url: http://{{ vcsim }}:5000/spawn?cluster=2
|
||||
register: vcsim_instance
|
||||
|
||||
- name: Wait for vcsim server to come up online
|
||||
wait_for:
|
||||
host: "{{ vcsim }}"
|
||||
port: 443
|
||||
state: started
|
||||
|
||||
- name: get a list of Datacenter from vcsim
|
||||
uri:
|
||||
url: http://{{ vcsim }}:5000/govc_find?filter=DC
|
||||
register: datacenters
|
||||
|
||||
- debug: var=vcsim_instance
|
||||
- debug: var=datacenters
|
||||
|
||||
# Testcase 0001: Add Distributed vSwitch
|
||||
- name: add distributed vSwitch
|
||||
vmware_dvswitch:
|
||||
validate_certs: False
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
datacenter_name: "{{ item | basename }}"
|
||||
state: present
|
||||
switch_name: dvswitch_0001
|
||||
mtu: 9000
|
||||
uplink_quantity: 2
|
||||
discovery_proto: lldp
|
||||
discovery_operation: both
|
||||
register: dvs_result_0001
|
||||
with_items:
|
||||
- "{{ datacenters['json'] }}"
|
||||
|
||||
- name: ensure distributed vswitch is present
|
||||
assert:
|
||||
that:
|
||||
- "{{ dvs_result_0001.changed == true }}"
|
||||
|
||||
- name: get a list of distributed vswitch from vcsim after adding
|
||||
uri:
|
||||
url: http://{{ vcsim }}:5000/govc_find?filter=DVS
|
||||
register: new_dvs_0001
|
||||
|
||||
- debug:
|
||||
msg: "{{ item | basename }}"
|
||||
with_items: "{{ new_dvs_0001['json'] }}"
|
||||
|
||||
- set_fact: new_dvs_name="{% for dvs in new_dvs_0001['json'] %} {{ True if (dvs | basename) == 'dvswitch_0001' else False }}{% endfor %}"
|
||||
|
||||
- debug: var=new_dvs_name
|
||||
- assert:
|
||||
that:
|
||||
- "{{ 'True' in new_dvs_name }}"
|
||||
|
||||
- name: Configure PVLANs in check mode
|
||||
vmware_dvswitch_pvlans:
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
switch: dvswitch_0001
|
||||
primary_pvlans:
|
||||
- primary_pvlan_id: 1
|
||||
- primary_pvlan_id: 4
|
||||
secondary_pvlans:
|
||||
- primary_pvlan_id: 1
|
||||
secondary_pvlan_id: 2
|
||||
pvlan_type: isolated
|
||||
- primary_pvlan_id: 1
|
||||
secondary_pvlan_id: 3
|
||||
pvlan_type: community
|
||||
- primary_pvlan_id: 4
|
||||
secondary_pvlan_id: 5
|
||||
pvlan_type: community
|
||||
validate_certs: no
|
||||
register: pvlans_result_check_mode
|
||||
check_mode: yes
|
||||
|
||||
- name: ensure pvlans were configured
|
||||
assert:
|
||||
that:
|
||||
- pvlans_result_check_mode.changed
|
||||
|
||||
- name: Configure PVLANs
|
||||
vmware_dvswitch_pvlans:
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
switch: dvswitch_0001
|
||||
primary_pvlans:
|
||||
- primary_pvlan_id: 1
|
||||
- primary_pvlan_id: 4
|
||||
secondary_pvlans:
|
||||
- primary_pvlan_id: 1
|
||||
secondary_pvlan_id: 2
|
||||
pvlan_type: isolated
|
||||
- primary_pvlan_id: 1
|
||||
secondary_pvlan_id: 3
|
||||
pvlan_type: community
|
||||
- primary_pvlan_id: 4
|
||||
secondary_pvlan_id: 5
|
||||
pvlan_type: community
|
||||
validate_certs: no
|
||||
register: pvlans_result
|
||||
|
||||
- name: ensure pvlans were configured
|
||||
assert:
|
||||
that:
|
||||
- pvlans_result.changed
|
Loading…
Reference in a new issue