1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
|
#!/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': 'certified'}
DOCUMENTATION = r'''
---
module: ucs_vsans
short_description: Configures VSANs on Cisco UCS Manager
description:
- Configures VSANs on Cisco UCS Manager.
extends_documentation_fragment: cisco.ucs.ucs
options:
state:
description:
- If C(present), will verify VSANs are present and will create if needed.
- If C(absent), will verify VSANs are absent and will delete if needed.
choices: [present, absent]
default: present
name:
description:
- The name assigned to the VSAN.
- 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 VSAN is created.
required: yes
vsan_id:
description:
- The unique identifier assigned to the VSAN.
- The ID can be a string between '1' and '4078', or between '4080' and '4093'. '4079' is a reserved VSAN ID.
- In addition, if you plan to use FC end-host mode, the range between '3840' to '4079' is also a reserved VSAN ID range.
- Optional if state is absent.
required: yes
vlan_id:
description:
- The unique string identifier assigned to the VLAN used for Fibre Channel connections.
- Note that Cisco UCS Manager uses VLAN '4048'. See the UCS Manager configuration guide if you want to assign '4048' to a VLAN.
- Optional if state is absent.
required: yes
fc_zoning:
description:
- Fibre Channel zoning configuration for the Cisco UCS domain.
- "Fibre Channel zoning can be set to one of the following values:"
- "disabled — The upstream switch handles Fibre Channel zoning, or Fibre Channel zoning is not implemented for the Cisco UCS domain."
- "enabled — Cisco UCS Manager configures and controls Fibre Channel zoning for the Cisco UCS domain."
- If you enable Fibre Channel zoning, do not configure the upstream switch with any VSANs that are being used for Fibre Channel zoning.
choices: [disabled, enabled]
default: disabled
fabric:
description:
- "The fabric configuration of the VSAN. This can be one of the following:"
- "common - The VSAN maps to the same VSAN ID in all available fabrics."
- "A - The VSAN maps to the a VSAN ID that exists only in fabric A."
- "B - The VSAN maps to the a VSAN ID that exists only in fabric B."
choices: [common, A, B]
default: common
requirements:
- ucsmsdk
author:
- David Soper (@dsoper2)
- John McDonough (@movinalot)
- CiscoUcs (@CiscoUcs)
version_added: '2.5'
'''
EXAMPLES = r'''
- name: Configure VSAN
cisco.ucs.ucs_vsans:
hostname: 172.16.143.150
username: admin
password: password
name: vsan110
fabric: common
vsan_id: '110'
vlan_id: '110'
- name: Remove VSAN
cisco.ucs.ucs_vsans:
hostname: 172.16.143.150
username: admin
password: password
name: vsan110
state: absent
'''
RETURN = r'''
#
'''
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.cisco.ucs.plugins.module_utils.ucs import UCSModule, ucs_argument_spec
def main():
argument_spec = ucs_argument_spec
argument_spec.update(
name=dict(type='str'),
vsan_id=dict(type='str'),
vlan_id=dict(type='str'),
fc_zoning=dict(type='str', default='disabled', choices=['disabled', 'enabled']),
fabric=dict(type='str', default='common', choices=['common', 'A', 'B']),
state=dict(type='str', default='present', choices=['present', 'absent']),
vsan_list=dict(type='list'),
)
# Note that use of vsan_list is an experimental feature which allows multiple resource updates with a single UCSM connection.
# Support for vsan_list may change or be removed once persistent UCS connections are supported.
# Either vsan_list or name/vsan_id/vlan_id is required (user can specify either a list or single resource).
module = AnsibleModule(
argument_spec,
supports_check_mode=True,
required_one_of=[
['vsan_list', 'name']
],
mutually_exclusive=[
['vsan_list', 'name']
],
)
ucs = UCSModule(module)
err = False
from ucsmsdk.mometa.fabric.FabricVsan import FabricVsan
changed = False
try:
# Only documented use is a single resource, but to also support experimental
# feature allowing multiple updates all params are converted to a vsan_list below.
if module.params['vsan_list']:
# directly use the list (single resource and list are mutually exclusive
vsan_list = module.params['vsan_list']
else:
# single resource specified, create list from the current params
vsan_list = [module.params]
for vsan in vsan_list:
mo_exists = False
props_match = False
# set default params. Done here to set values for lists which can't be done in the argument_spec
if not vsan.get('fc_zoning'):
vsan['fc_zoning'] = 'disabled'
if not vsan.get('fabric'):
vsan['fabric'] = 'common'
# dn is fabric/san/net-<name> for common vsans or fabric/san/[A or B]/net-<name> for A or B
dn_base = 'fabric/san'
if vsan['fabric'] != 'common':
dn_base += '/' + vsan['fabric']
dn = dn_base + '/net-' + vsan['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=vsan['vsan_id'])
kwargs['fcoe_vlan'] = vsan['vlan_id']
kwargs['zoning_state'] = vsan['fc_zoning']
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 = FabricVsan(
parent_mo_or_dn=dn_base,
name=vsan['name'],
id=vsan['vsan_id'],
fcoe_vlan=vsan['vlan_id'],
zoning_state=vsan['fc_zoning'],
)
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()
|