From 781dd9c45966e703ff22f31364cca610d18c9d4a Mon Sep 17 00:00:00 2001 From: Tim Rupp Date: Sun, 25 Sep 2016 13:30:27 -0700 Subject: [PATCH] Distinguish between untagged and tagged vlans We were incorrectly making VLANS always be untagged when they could be either tagged or untagged. This change corrects the arguments to the vlan module to allow for specifying either untagged or tagged interfaces. The arguments are mutually exclusive --- .../modules/extras/network/f5/bigip_vlan.py | 117 +++++++++++++----- 1 file changed, 87 insertions(+), 30 deletions(-) diff --git a/lib/ansible/modules/extras/network/f5/bigip_vlan.py b/lib/ansible/modules/extras/network/f5/bigip_vlan.py index 1fe6947eb4..4e13d2508c 100644 --- a/lib/ansible/modules/extras/network/f5/bigip_vlan.py +++ b/lib/ansible/modules/extras/network/f5/bigip_vlan.py @@ -27,11 +27,21 @@ options: description: description: - The description to give to the VLAN. - interfaces: + tagged_interfaces: description: - - Specifies a list of tagged or untagged interfaces and trunks that you - want to configure for the VLAN. Use tagged interfaces or trunks when + - Specifies a list of tagged interfaces and trunks that you want to + configure for the VLAN. Use tagged interfaces or trunks when you want to assign a single interface or trunk to multiple VLANs. + required: false + aliases: + - tagged_interface + untagged_interfaces: + description: + - Specifies a list of untagged interfaces and trunks that you want to + configure for the VLAN. + required: false + aliases: + - untagged_interface name: description: - The VLAN to manage. If the special VLAN C(ALL) is specified with @@ -85,8 +95,7 @@ EXAMPLES = ''' - name: Add VLAN 2345 as tagged to interface 1.1 bigip_vlan: - interfaces: - - 1.1 + tagged_interface: 1.1 name: "net1" password: "secret" server: "lb.mydomain.com" @@ -94,6 +103,19 @@ EXAMPLES = ''' user: "admin" validate_certs: "no" delegate_to: localhost + +- name: Add VLAN 1234 as tagged to interfaces 1.1 and 1.2 + bigip_vlan: + tagged_interfaces: + - 1.1 + - 1.2 + name: "net1" + password: "secret" + server: "lb.mydomain.com" + tag: "1234" + user: "admin" + validate_certs: "no" + delegate_to: localhost ''' RETURN = ''' @@ -148,14 +170,10 @@ class BigIpVlan(object): port=kwargs['server_port']) def present(self): - changed = False - if self.exists(): - changed = self.update() + return self.update() else: - changed = self.create() - - return changed + return self.create() def absent(self): changed = False @@ -188,7 +206,17 @@ class BigIpVlan(object): if hasattr(r, 'description'): p['description'] = str(r.description) if len(ifcs) is not 0: - p['interfaces'] = list(set([str(x.name) for x in ifcs])) + untagged = [] + tagged = [] + for x in ifcs: + if hasattr(x, 'tagged'): + tagged.append(str(x.name)) + elif hasattr(x, 'untagged'): + untagged.append(str(x.name)) + if untagged: + p['untagged_interfaces'] = list(set(untagged)) + if tagged: + p['tagged_interfaces'] = list(set(tagged)) p['name'] = name return p @@ -198,14 +226,16 @@ class BigIpVlan(object): check_mode = self.params['check_mode'] description = self.params['description'] name = self.params['name'] - interfaces = self.params['interfaces'] + untagged_interfaces = self.params['untagged_interfaces'] + tagged_interfaces = self.params['tagged_interfaces'] partition = self.params['partition'] tag = self.params['tag'] if tag is not None: params['tag'] = tag - if interfaces is not None: + if untagged_interfaces is not None or tagged_interfaces is not None: + tmp = [] ifcs = self.api.tm.net.interfaces.get_collection() ifcs = [str(x.name) for x in ifcs] @@ -215,12 +245,23 @@ class BigIpVlan(object): ) pinterfaces = [] + if untagged_interfaces: + interfaces = untagged_interfaces + elif tagged_interfaces: + interfaces = tagged_interfaces + for ifc in interfaces: ifc = str(ifc) if ifc in ifcs: pinterfaces.append(ifc) - if pinterfaces: - params['interfaces'] = pinterfaces + + if tagged_interfaces: + tmp = [dict(name=x, tagged=True) for x in pinterfaces] + elif untagged_interfaces: + tmp = [dict(name=x, untagged=True) for x in pinterfaces] + + if tmp: + params['interfaces'] = tmp if description is not None: params['description'] = self.params['description'] @@ -250,9 +291,10 @@ class BigIpVlan(object): name = self.params['name'] tag = self.params['tag'] partition = self.params['partition'] - interfaces = self.params['interfaces'] + tagged_interfaces = self.params['tagged_interfaces'] + untagged_interfaces = self.params['untagged_interfaces'] - if interfaces is not None: + if untagged_interfaces is not None or tagged_interfaces is not None: ifcs = self.api.tm.net.interfaces.get_collection() ifcs = [str(x.name) for x in ifcs] @@ -261,24 +303,35 @@ class BigIpVlan(object): 'No interfaces were found' ) + pinterfaces = [] + if untagged_interfaces: + interfaces = untagged_interfaces + elif tagged_interfaces: + interfaces = tagged_interfaces + for ifc in interfaces: ifc = str(ifc) if ifc in ifcs: - try: - pinterfaces.append(ifc) - except UnboundLocalError: - pinterfaces = [] - pinterfaces.append(ifc) + pinterfaces.append(ifc) else: raise F5ModuleError( 'The specified interface "%s" was not found' % (ifc) ) - if 'interfaces' in current: - if pinterfaces != current['interfaces']: - params['interfaces'] = pinterfaces - else: - params['interfaces'] = pinterfaces + if tagged_interfaces: + tmp = [dict(name=x, tagged=True) for x in pinterfaces] + if 'tagged_interfaces' in current: + if pinterfaces != current['tagged_interfaces']: + params['interfaces'] = tmp + else: + params['interfaces'] = tmp + elif untagged_interfaces: + tmp = [dict(name=x, untagged=True) for x in pinterfaces] + if 'untagged_interfaces' in current: + if pinterfaces != current['untagged_interfaces']: + params['interfaces'] = tmp + else: + params['interfaces'] = tmp if description is not None: if 'description' in current: @@ -361,7 +414,8 @@ def main(): meta_args = dict( description=dict(required=False, default=None), - interfaces=dict(required=False, default=None, type='list'), + tagged_interfaces=dict(required=False, default=None, type='list', aliases=['tagged_interface']), + untagged_interfaces=dict(required=False, default=None, type='list', aliases=['untagged_interface']), name=dict(required=True), tag=dict(required=False, default=None, type='int') ) @@ -369,7 +423,10 @@ def main(): module = AnsibleModule( argument_spec=argument_spec, - supports_check_mode=True + supports_check_mode=True, + mutually_exclusive=[ + ['tagged_interfaces', 'untagged_interfaces'] + ] ) try: