forked from ansible/ansible
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ucs vlans and integration tests (ansible#35071)
* UCS VLANs module and integration tests * UCS VLANs and integration tests
- Loading branch information
Showing
3 changed files
with
311 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
|
||
# 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 = r''' | ||
--- | ||
module: ucs_vlans | ||
short_description: Configures VLANs on Cisco UCS Manager | ||
description: | ||
- Configures VLANs on Cisco UCS Manager. | ||
- Examples can be used with the UCS Platform Emulator U(https://communities.cisco.com/ucspe). | ||
extends_documentation_fragment: ucs | ||
options: | ||
state: | ||
description: | ||
- If C(present), will verify VLANs are present and will create if needed. | ||
- If C(absent), will verify VLANs are absent and will delete if needed. | ||
choices: [present, absent] | ||
default: present | ||
name: | ||
description: | ||
- The name assigned to the VLAN. | ||
- The VLAN name is case sensitive. | ||
- This name can be between 1 and 32 alphanumeric characters. | ||
- "You cannot use spaces or any special characters other than - (hyphen), \"_\" (underscore), : (colon), and . (period)." | ||
- You cannot change this name after the VLAN is created. | ||
required: yes | ||
multicast_policy: | ||
description: | ||
- The multicast policy associated with this VLAN. | ||
- This option is only valid if the Sharing Type field is set to None or Primary. | ||
default: '' | ||
fabric: | ||
description: | ||
- "The fabric configuration of the VLAN. This can be one of the following:" | ||
- "common - The VLAN applies to both fabrics and uses the same configuration parameters in both cases." | ||
- "A — The VLAN only applies to fabric A." | ||
- "B — The VLAN only applies to fabric B." | ||
- For upstream disjoint L2 networks, Cisco recommends that you choose common to create VLANs that apply to both fabrics. | ||
choices: [common, A, B] | ||
default: common | ||
id: | ||
description: | ||
- The unique string identifier assigned to the VLAN. | ||
- A VLAN ID can be between '1' and '3967', or between '4048' and '4093'. | ||
- You cannot create VLANs with IDs from 4030 to 4047. This range of VLAN IDs is reserved. | ||
- The VLAN IDs you specify must also be supported on the switch that you are using. | ||
- VLANs in the LAN cloud and FCoE VLANs in the SAN cloud must have different IDs. | ||
- Optional if state is absent. | ||
required: yes | ||
sharing: | ||
description: | ||
- The Sharing Type field. | ||
- "Whether this VLAN is subdivided into private or secondary VLANs. This can be one of the following:" | ||
- "none - This VLAN does not have any secondary or private VLANs. This is a regular VLAN." | ||
- "primary - This VLAN can have one or more secondary VLANs, as shown in the Secondary VLANs area. This VLAN is a primary VLAN in the private VLAN domain." | ||
- "isolated - This is a private VLAN associated with a primary VLAN. This VLAN is an Isolated VLAN." | ||
- "community - This VLAN can communicate with other ports on the same community VLAN as well as the promiscuous port. This VLAN is a Community VLAN." | ||
choices: [none, primary, isolated, community] | ||
default: none | ||
native: | ||
description: | ||
- Designates the VLAN as a native VLAN. | ||
choices: ['no', 'yes'] | ||
default: 'no' | ||
requirements: | ||
- ucsmsdk | ||
author: | ||
- David Soper (@dsoper2) | ||
- CiscoUcs (@CiscoUcs) | ||
version_added: '2.5' | ||
''' | ||
|
||
EXAMPLES = r''' | ||
- name: Configure VLAN | ||
ucs_vlans: | ||
hostname: 172.16.143.150 | ||
username: admin | ||
password: password | ||
name: vlan2 | ||
id: '2' | ||
native: 'yes' | ||
- name: Remove VLAN | ||
ucs_vlans: | ||
hostname: 172.16.143.150 | ||
username: admin | ||
password: password | ||
name: vlan2 | ||
state: absent | ||
''' | ||
|
||
RETURN = r''' | ||
# | ||
''' | ||
|
||
from ansible.module_utils.basic import AnsibleModule | ||
from ansible.module_utils.remote_management.ucs import UCSModule, ucs_argument_spec | ||
|
||
|
||
def main(): | ||
argument_spec = ucs_argument_spec | ||
argument_spec.update( | ||
name=dict(type='str', required=True), | ||
multicast_policy=dict(type='str', default=''), | ||
fabric=dict(type='str', default='common', choices=['common', 'A', 'B']), | ||
id=dict(type='str'), | ||
sharing=dict(type='str', default='none', choices=['none', 'primary', 'isolated', 'community']), | ||
native=dict(type='str', default='no', choices=['yes', 'no']), | ||
state=dict(type='str', default='present', choices=['present', 'absent']), | ||
) | ||
|
||
module = AnsibleModule( | ||
argument_spec, | ||
supports_check_mode=True, | ||
required_if=[ | ||
['state', 'present', ['id']], | ||
], | ||
) | ||
ucs = UCSModule(module) | ||
|
||
err = False | ||
|
||
# UCSModule creation above verifies ucsmsdk is present and exits on failure, so additional imports are done below. | ||
from ucsmsdk.mometa.fabric.FabricVlan import FabricVlan | ||
|
||
changed = False | ||
try: | ||
mo_exists = False | ||
props_match = False | ||
# dn is fabric/lan/net-<name> for common vlans or fabric/lan/[A or B]/net-<name> for A or B | ||
dn_base = 'fabric/lan' | ||
if module.params['fabric'] != 'common': | ||
dn_base += '/' + module.params['fabric'] | ||
dn = dn_base + '/net-' + module.params['name'] | ||
|
||
mo = ucs.login_handle.query_dn(dn) | ||
if mo: | ||
mo_exists = True | ||
|
||
if module.params['state'] == 'absent': | ||
# mo must exist but all properties do not have to match | ||
if mo_exists: | ||
if not module.check_mode: | ||
ucs.login_handle.remove_mo(mo) | ||
ucs.login_handle.commit() | ||
changed = True | ||
else: | ||
if mo_exists: | ||
# check top-level mo props | ||
kwargs = dict(id=module.params['id']) | ||
kwargs['default_net'] = module.params['native'] | ||
kwargs['sharing'] = module.params['sharing'] | ||
kwargs['mcast_policy_name'] = module.params['multicast_policy'] | ||
if (mo.check_prop_match(**kwargs)): | ||
props_match = True | ||
|
||
if not props_match: | ||
if not module.check_mode: | ||
# create if mo does not already exist | ||
mo = FabricVlan( | ||
parent_mo_or_dn=dn_base, | ||
name=module.params['name'], | ||
id=module.params['id'], | ||
default_net=module.params['native'], | ||
sharing=module.params['sharing'], | ||
mcast_policy_name=module.params['multicast_policy'], | ||
) | ||
|
||
ucs.login_handle.add_mo(mo, True) | ||
ucs.login_handle.commit() | ||
changed = True | ||
|
||
except Exception as e: | ||
err = True | ||
ucs.result['msg'] = "setup error: %s " % str(e) | ||
|
||
ucs.result['changed'] = changed | ||
if err: | ||
module.fail_json(**ucs.result) | ||
module.exit_json(**ucs.result) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Not enabled, but can be used with the UCS Platform Emulator or UCS hardware. | ||
# Example integration_config.yml: | ||
# --- | ||
# ucs_hostname: 172.16.143.136 | ||
# ucs_username: admin | ||
# ucs_password: password |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# Test code for the UCS modules | ||
# Copyright 2017, David Soper (@dsoper2) | ||
|
||
- name: Test that we have a UCS host, UCS username, and UCS password | ||
fail: | ||
msg: 'Please define the following variables: ucs_hostname, ucs_username and ucs_password.' | ||
when: ucs_hostname is not defined or ucs_username is not defined or ucs_password is not defined | ||
vars: | ||
login_info: &login_info | ||
hostname: "{{ ucs_hostname }}" | ||
username: "{{ ucs_username }}" | ||
password: "{{ ucs_password }}" | ||
|
||
# Setup (clean environment) | ||
- name: VLANs absent | ||
ucs_vlans: &vlans_absent | ||
<<: *login_info | ||
name: vlan2 | ||
state: absent | ||
|
||
# Test present (check_mode) | ||
- name: VLANs present (check_mode) | ||
ucs_vlans: &vlans_present | ||
<<: *login_info | ||
name: vlan2 | ||
id: '2' | ||
native: 'yes' | ||
check_mode: yes | ||
register: cm_vlans_present | ||
|
||
# Present (normal mode) | ||
- name: VLANs present (normal mode) | ||
ucs_vlans: *vlans_present | ||
register: nm_vlans_present | ||
|
||
# Test present again (idempotent) | ||
- name: VLANs present again (check_mode) | ||
ucs_vlans: *vlans_present | ||
check_mode: yes | ||
register: cm_vlans_present_again | ||
|
||
# Present again (normal mode) | ||
- name: VLANs present again (normal mode) | ||
ucs_vlans: *vlans_present | ||
register: nm_vlans_present_again | ||
|
||
# Verfiy present | ||
- name: Verify VLANs present results | ||
assert: | ||
that: | ||
- cm_vlans_present.changed == nm_vlans_present.changed == true | ||
- cm_vlans_present_again.changed == nm_vlans_present_again.changed == false | ||
|
||
# Test change (check_mode) | ||
- name: VLANs VLAN change (check_mode) | ||
ucs_vlans: &vlans_change | ||
<<: *vlans_present | ||
id: '20' | ||
check_mode: yes | ||
register: cm_vlans_vlan_change | ||
|
||
# Change (normal mode) | ||
- name: VLANs VLAN change (normal mode) | ||
ucs_vlans: *vlans_change | ||
register: nm_vlans_vlan_change | ||
|
||
# Test change again (idempotent) | ||
- name: VLANs VLAN change again (check_mode) | ||
ucs_vlans: *vlans_change | ||
check_mode: yes | ||
register: cm_vlans_vlan_change_again | ||
|
||
# Change again (normal mode) | ||
- name: VLANs VLAN change again (normal mode) | ||
ucs_vlans: *vlans_change | ||
register: nm_vlans_vlan_change_again | ||
|
||
# Verfiy change | ||
- name: Verify VLANs change results | ||
assert: | ||
that: | ||
- cm_vlans_vlan_change.changed == nm_vlans_vlan_change.changed == true | ||
- cm_vlans_vlan_change_again.changed == nm_vlans_vlan_change_again.changed == false | ||
|
||
# Teardown (clean environment) | ||
- name: VLANs absent (check_mode) | ||
ucs_vlans: *vlans_absent | ||
check_mode: yes | ||
register: cm_vlans_absent | ||
|
||
# Absent (normal mode) | ||
- name: VLANs absent (normal mode) | ||
ucs_vlans: *vlans_absent | ||
register: nm_vlans_absent | ||
|
||
# Test absent again (idempotent) | ||
- name: VLANs absent again (check_mode) | ||
ucs_vlans: *vlans_absent | ||
check_mode: yes | ||
register: cm_vlans_absent_again | ||
|
||
# Absent again (normal mode) | ||
- name: VLANs absent again (normal mode) | ||
ucs_vlans: *vlans_absent | ||
register: nm_vlans_absent_again | ||
|
||
# Verfiy absent | ||
- name: Verify VLANs absent results | ||
assert: | ||
that: | ||
- cm_vlans_absent.changed == nm_vlans_absent.changed == true | ||
- cm_vlans_absent_again.changed == nm_vlans_absent_again.changed == false |