Repository URL to install this package:
|
Version:
6.0.0 ▾
|
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2021, Simon Dodsley (simon@purestorage.com)
# 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: purefb_lag
version_added: '1.7.0'
short_description: Manage FlashBlade Link Aggregation Groups
description:
- Maintain FlashBlade Link Aggregation Groups
author:
- Pure Storage Ansible Team (@sdodsley) <pure-ansible-team@purestorage.com>
options:
name:
description:
- Name of the Link Aggregation Group
type: str
default: uplink
state:
description:
- Define whether the LAG should be added or deleted
default: present
choices: [ absent, present ]
type: str
ports:
description:
- Name of network ports assigned to the LAG
- Format should be CHx.ETHy, where CHx is the chassis number and
ETHy is the ethernet port number.
- Matched port pairs from each Fabric Module in the Chassis will
be used.
- To modify required ports for a LAG specify only the ports required
by the LAG. Any ports currently used by the LAG not specified will be
disconnected from the LAG.
type: list
elements: str
extends_documentation_fragment:
- purestorage.flashblade.purestorage.fb
"""
EXAMPLES = r"""
- name: Add LAG
purefb_lag:
name: lag2
ports:
- ch1.eth2
fb_url: 10.10.10.2
api_token: T-68618f31-0c9e-4e57-aa44-5306a2cf10e3
- name: Upate LAG
purefb_lag:
name: lag2
ports:
- ch1.eth2
- ch1.eth4
fb_url: 10.10.10.2
api_token: T-68618f31-0c9e-4e57-aa44-5306a2cf10e3
- name: Delete LAG
purefb_lag:
name: lag2
state: absent
fb_url: 10.10.10.2
api_token: T-68618f31-0c9e-4e57-aa44-5306a2cf10e3
"""
RETURN = r"""
lag:
description: A dictionary describing the LAG.
type: dict
returned: success
contains:
lag_speed:
description: Combined speed of all ports in the LAG in Gb/s
type: str
port_speed:
description: Configured speed of each port in the LAG in Gb/s
type: str
mac_address:
description: Unique MAC address assigned to the LAG
type: str
status:
description: Health status of the LAG.
type: str
"""
HAS_PURESTORAGE = True
try:
from pypureclient import flashblade
except ImportError:
HAS_PURESTORAGE = False
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.purestorage.flashblade.plugins.module_utils.purefb import (
get_system,
purefb_argument_spec,
)
MIN_REQUIRED_API_VERSION = "2.0"
def delete_lag(module, blade):
"""Delete Link Aggregation Group"""
changed = True
if not module.check_mode:
res = blade.delete_link_aggregation_groups(names=[module.params["name"]])
if res.status_code != 200:
module.fail_json(
msg="Failed to delete LAG {0}. Error: {1}".format(
module.params["name"], res.errors[0].message
)
)
module.exit_json(changed=changed)
def update_lag(module, blade):
"""Update Link Aggregation Group"""
changed = False
used_ports = []
current_ports = []
lagfact = []
current_lag = list(
blade.get_link_aggregation_groups(names=[module.params["name"]]).items
)[0]
for port in range(0, len(current_lag.ports)):
used_ports.append(current_lag.ports[port].name)
for lag_port in range(0, len(module.params["ports"]), 2):
if (
not (
module.params["ports"][lag_port].split(".")[0].upper()
+ ".FM1."
+ module.params["ports"][lag_port].split(".")[1].upper()
)
in used_ports
):
current_lags = list(blade.get_link_aggregation_groups().items)
for lag in range(0, len(current_lags)):
for port in range(0, len(current_lags[lag].ports)):
current_ports.append(current_lags[lag].ports[port].name)
for current_lag_port in range(0, len(current_ports)):
if (
module.params["ports"][lag_port].split(".")[0].upper()
+ ".FM1."
+ module.params["ports"][lag_port].split(".")[1].upper()
) in current_ports:
module.fail_json(
msg="Selected port {0} is currently in use by another LAG.".format(
module.params["ports"][lag_port].upper()
)
)
new_ports = []
for port in range(0, len(module.params["ports"])):
new_ports.append(
module.params["ports"][port].split(".")[0].upper()
+ ".FM1."
+ module.params["ports"][port].split(".")[1].upper()
)
new_ports.append(
module.params["ports"][port].split(".")[0].upper()
+ ".FM2."
+ module.params["ports"][port].split(".")[1].upper()
)
ports = []
for final_port in range(0, len(new_ports)):
ports.append(flashblade.FixedReference(name=new_ports[final_port]))
link_aggregation_group = flashblade.Linkaggregationgroup(ports=ports)
if sorted(used_ports) != sorted(new_ports):
changed = True
if not module.check_mode:
res = blade.patch_link_aggregation_groups(
names=[module.params["name"]],
link_aggregation_group=link_aggregation_group,
)
if res.status_code != 200:
module.fail_json(
msg="Failed to update LAG {0}. Error: {1}".format(
module.params["name"],
res.errors[0].message,
)
)
else:
response = list(res.items)[0]
lagfact = {
"mac_address": response.mac_address,
"port_speed": str(response.port_speed / 1000000000) + "Gb/s",
"lag_speed": str(response.lag_speed / 1000000000) + "Gb/s",
"status": response.status,
}
module.exit_json(changed=changed, lag=lagfact)
def create_lag(module, blade):
"""Create Link Aggregation Group"""
changed = True
used_ports = []
lagfact = []
current_lags = list(blade.get_link_aggregation_groups().items)
for lag in range(0, len(current_lags)):
for port in range(0, len(current_lags[lag].ports)):
used_ports.append(current_lags[lag].ports[port].name)
for lag_port in range(0, len(module.params["ports"])):
if (
module.params["ports"][lag_port].split(".")[0].upper()
+ ".FM1."
+ module.params["ports"][0].split(".")[1].upper()
) in used_ports:
module.fail_json(
msg="Selected port {0} is currently in use by another LAG.".format(
module.params["ports"][lag_port].upper()
)
)
new_ports = []
for new_port in range(0, len(module.params["ports"])):
new_ports.append(
module.params["ports"][new_port].split(".")[0].upper()
+ ".FM1."
+ module.params["ports"][new_port].split(".")[1].upper()
)
new_ports.append(
module.params["ports"][new_port].split(".")[0].upper()
+ ".FM2."
+ module.params["ports"][new_port].split(".")[1].upper()
)
ports = []
for final_port in range(0, len(new_ports)):
ports.append(flashblade.FixedReference(name=new_ports[final_port]))
link_aggregation_group = flashblade.LinkAggregationGroup(ports=ports)
if not module.check_mode:
res = blade.post_link_aggregation_groups(
names=[module.params["name"]], link_aggregation_group=link_aggregation_group
)
if res.status_code != 200:
module.fail_json(
msg="Failed to create LAG {0}. Error: {1}".format(
module.params["name"],
res.errors[0].message,
)
)
else:
response = list(res.items)[0]
lagfact = {
"mac_address": response.mac_address,
"port_speed": str(response.port_speed / 1000000000) + "Gb/s",
"lag_speed": str(response.lag_speed / 1000000000) + "Gb/s",
"status": response.status,
}
module.exit_json(changed=changed, lag=lagfact)
def main():
argument_spec = purefb_argument_spec()
argument_spec.update(
dict(
state=dict(type="str", default="present", choices=["absent", "present"]),
name=dict(type="str", default="uplink"),
ports=dict(type="list", elements="str"),
)
)
required_if = [["state", "present", ["ports"]]]
module = AnsibleModule(
argument_spec, required_if=required_if, supports_check_mode=True
)
if not HAS_PURESTORAGE:
module.fail_json(msg="py-pure-client sdk is required for this module")
blade = get_system(module)
api_version = list(blade.get_versions().items)
if MIN_REQUIRED_API_VERSION not in api_version:
module.fail_json(
msg="FlashBlade REST version not supported. "
"Minimum version required: {0}".format(MIN_REQUIRED_API_VERSION)
)
state = module.params["state"]
exists = bool(
blade.get_link_aggregation_groups(names=[module.params["name"]]).status_code
== 200
)
if module.params["ports"]:
# Remove duplicates
module.params["ports"] = list(dict.fromkeys(module.params["ports"]))
if not exists and state == "present":
create_lag(module, blade)
elif exists and state == "present":
update_lag(module, blade)
elif exists and state == "absent":
if module.params["name"].lower() == "uplink":
module.fail_json(
msg="Preconfigured Link Aggregation Group cannot be deleted"
)
else:
delete_lag(module, blade)
module.exit_json(changed=False)
if __name__ == "__main__":
main()