From 6fb05137adb92c7567bdae449a2a35165c74b564 Mon Sep 17 00:00:00 2001 From: Gonza Rafuls Date: Mon, 17 May 2021 18:28:46 +0200 Subject: [PATCH] feat: added modify switch conf With this tool we can now change the switch settings for each host interface to move into a specific vlan. Running the tool without `--change` will only check that the values are already correctly set, otherwise it will attempt to make those changes effective on the switch. Change-Id: Ib0b01ca75a83c588169aefef85653d4ed185b684 --- README.md | 10 +++ quads/tools/modify_switch_conf.py | 145 ++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 quads/tools/modify_switch_conf.py diff --git a/README.md b/README.md index 93b86ee4c..d9833cf46 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ QUADS automates the future scheduling, end-to-end provisioning and delivery of b * [Using the QUADS JSON API](#using-the-quads-json-api) * [Additional Tools and Commands](#additional-tools-and-commands) * [Verify or Correct Cloud and Host Network Switch Settings](#verify-or-correct-cloud-and-host-network-switch-settings) + * [Modify or check a specific Host Network Switch Settings](#modify-or-check-a-specific-host-network-switch-settings) * [Modifying Cloud-level Attributes](#modifying-cloud-level-attributes) * [Looking into the Future](#looking-into-the-future) * [Dry Run for Pending Actions](#dry-run-for-pending-actions) @@ -886,6 +887,15 @@ Resource properly removed /opt/quads/quads/tools/verify_switchconf.py --host host01.example.com ``` +### Modify or check a specific Host Network Switch Settings +* With the `modify_switch_conf.py` tool you can set up each individual network interface to a specific vlan id. +* Passing the `--change` argument will make the changes effective in the switch. Not passing this will only verify the configuration is set to the desired. + +``` +/opt/quads/quads/tools/modify_switch_conf.py --host host01.example.com --nic1 1400 --nic2 1401 --nic3 1400 --nic4 1402 --nic5 1400 +``` +* All `--nic*` arguments are optional so this can be also done individually for all nics. + ### Modifying Cloud-level Attributes * You can re-define or change any aspects of an already-defined cloud starting in `1.1.4` with the `--mod-cloud` command. * This can be done a per-parameter or combined basis: diff --git a/quads/tools/modify_switch_conf.py b/quads/tools/modify_switch_conf.py new file mode 100644 index 000000000..127c482cd --- /dev/null +++ b/quads/tools/modify_switch_conf.py @@ -0,0 +1,145 @@ +#!/usr/bin/python3 + +import argparse +import logging + +from quads.config import conf +from quads.model import Host +from quads.tools.juniper_set_port import juniper_set_port +from quads.tools.ssh_helper import SSHHelper + +logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO, format="%(levelname)s - %(message)s") + + +def verify(_host_name, change=False, nic1=None, nic2=None, nic3=None, nic4=None, nic5=None): + _nics = {"em1": nic1, "em2": nic2, "em3": nic3, "em4": nic4, "em5": nic5} + _host_obj = Host.objects(name=_host_name).first() + if not _host_obj: + logger.error(f"Hostname not found.") + return + + logger.info(f"Host: {_host_obj.name}") + if _host_obj.interfaces: + interfaces = sorted(_host_obj.interfaces, key=lambda k: k["name"]) + for i, interface in enumerate(interfaces): + vlan = _nics.get(interface.name) + if vlan: + ssh_helper = SSHHelper(interface.ip_address, conf["junos_username"]) + + try: + _, old_vlan_out = ssh_helper.run_cmd( + "show configuration interfaces %s" % interface.switch_port + ) + old_vlan = old_vlan_out[0].split(";")[0].split()[1] + if old_vlan.startswith("QinQ"): + old_vlan = old_vlan[7:] + except IndexError: + old_vlan = 0 + + try: + _, vlan_member_out = ssh_helper.run_cmd( + "show configuration vlans | display set | match %s.0" + % interface.switch_port + ) + vlan_member = vlan_member_out[0].split()[2][4:].strip(",") + except IndexError: + logger.warning( + "Could not determine the previous VLAN member for %s, switch %s, switch port %s " + % ( + interface.name, + interface.ip_address, + interface.switch_port, + ) + ) + vlan_member = 0 + + ssh_helper.disconnect() + + if int(old_vlan) != int(vlan): + logger.warning( + "Interface %s not using QinQ_vl%s", interface.switch_port, vlan + ) + + if int(vlan_member) != int(vlan): + logger.warning( + "Interface %s appears to be a member of VLAN %s, should be %s", + interface.switch_port, + vlan_member, + vlan, + ) + + if change: + logger.info(f"Change requested for {interface.name}") + success = juniper_set_port( + interface.ip_address, + interface.switch_port, + vlan_member, + vlan, + ) + + if success: + logger.info("Successfully updated switch settings.") + else: + logger.error( + f"There was something wrong updating switch for {interface.name}" + ) + else: + logger.info(f"Interface {interface.name} is already configured for vlan{vlan}") + else: + logger.error( + f"The host has no interfaces defined" + ) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Verify switch configs for a cloud or host") + parser.add_argument( + "--host", + dest="host", + type=str, + default=None, + help="Host name to verify switch configuration for.", + required=True, + ) + parser.add_argument( + "--nic1", + dest="nic1", + type=str, + default=None, + help="Nic 1 (EM1).", + ) + parser.add_argument( + "--nic2", + dest="nic2", + type=str, + default=None, + help="Nic 2 (EM2).", + ) + parser.add_argument( + "--nic3", + dest="nic3", + type=str, + default=None, + help="Nic 3 (EM3).", + ) + parser.add_argument( + "--nic4", + dest="nic4", + type=str, + default=None, + help="Nic 4 (EM4).", + ) + parser.add_argument( + "--nic5", + dest="nic5", + type=str, + default=None, + help="Nic 5 (EM5).", + ) + parser.add_argument( + "--change", dest="change", action="store_true", help="Commit changes on switch." + ) + + args = parser.parse_args() + verify(args.host, args.change, args.nic1, args.nic2, args.nic3, args.nic4, args.nic5)