Пример #1
0
    def download_software(self, requested_software_version: str) -> None:
        """ Download software """

        major = requested_software_version.split(".")[0]
        minor = requested_software_version.split(".")[1]
        patch = requested_software_version.split(".")[2]

        requested_software_version_dependencies = [f"{major}.0.0"]
        if minor != "0":
            requested_software_version_dependencies.append(
                f"{major}.{minor}.0")
        if patch != "0":
            requested_software_version_dependencies.append(
                f"{major}.{minor}.{patch}")

        netcat.LOGGER.info(
            "Detected software version dependencies: {}",
            " -> ".join(requested_software_version_dependencies))

        # Download latest software list
        netcat.LOGGER.info("Refreshing available software versions")
        available_software_versions = self.send_command(
            "request system software check", timeout=120)
        if server_error := netcat.find_regex_sl(available_software_versions,
                                                r"(Server error)"):
            raise netcat.CustomException(f"Received: '{server_error}'")
Пример #2
0
    def get_site_id(self) -> str:
        """ Detect site ID """

        if site_id := netcat.find_regex_sl(
                self.send_command("show routing protocol bgp summary"),
                r"^ +router id: +\d+\.(\d+)\.\d+\.\d+$"):
            netcat.LOGGER.info(f"Detected Site ID: {site_id}")
            return site_id
Пример #3
0
def display_resource_availability_history(device_name: str, resource: str,
                                          resource_name: str,
                                          cisco_command: str, cisco_regex: str,
                                          pa_regex: str,
                                          pa_command: str) -> str:
    """ Display resource history for given device name and resource """

    # Time process execution
    start_time = time.monotonic()

    timestamp_list = [
        _.get("snapshot_timestamp") for _ in db.get_command_status_list()
        if type(_) is dict
    ]

    device_data_list = db.get_device_data_list__c(device_name,
                                                  [pa_command, cisco_command])

    availability_history = []

    for timestamp in timestamp_list:

        device_data: Optional[Dict[str, Any]] = next(
            (_ for _ in device_data_list
             if _.get("snapshot_timestamp") == timestamp), None)

        if device_data is None:
            availability_history.append({
                "uuid": uuid.uuid1(),
                "snapshot_timestamp": timestamp
            })
            continue

        if device_data.get("device_type") == "cisco_router":
            if status := netcat.find_regex_sl(
                    netcat.get_command_output(device_data, cisco_command),
                    cisco_regex):
                availability_history.append({
                    "uuid": uuid.uuid1(),
                    "snapshot_timestamp": timestamp,
                    "status": status
                })
                continue

        elif device_data.get("device_type") == "paloalto":
            if status := netcat.find_regex_sl(
                    netcat.get_command_output(device_data, pa_command),
                    pa_regex):
                availability_history.append({
                    "uuid": uuid.uuid1(),
                    "snapshot_timestamp": timestamp,
                    "status": status
                })
                continue
Пример #4
0
    def get_site_id(self) -> str:
        """ Detect site ID """

        netcat.LOGGER.info("Detecting Site ID")

        # We do it for routers only, makes little sense to do for other devices
        if self.type == "cisco_router":
            if site_id := netcat.find_regex_sl(
                    self.send_command("show ip bgp summary"),
                    r"^BGP router identifier \d+\.(\d+).\d+.\d+,.*$"):
                netcat.LOGGER.info(f"Detected Site ID: {site_id}")
                return site_id
Пример #5
0
    def get_inet_gw(self) -> str:
        """ Detect Internet default gateway """

        netcat.LOGGER.info("Detecting Internet default gateway IP address")

        if inet_gw := netcat.find_regex_sl(
                self.send_config_command(
                    "show network virtual-router VR_GLOBAL routing-table ip static-route SR_DEFAULT nexthop"
                ), r"^.+ (\d+\.\d+\.\d+.\d+)$"):
            netcat.LOGGER.info(
                f"Detected Internet default IP address: {inet_gw}")
            return inet_gw
Пример #6
0
    def get_inet_gw(self) -> str:
        """ Detect Internet default gateway """

        netcat.LOGGER.info("Detecting Internet default gateway IP address")

        # We do it for routers only, makes little sense to do for other devices
        if self.type == "cisco_router":

            if inet_gw := netcat.find_regex_sl(
                    self.send_command(
                        "show running-config | include 0.0.0.0 0.0.0.0"),
                    r"^ip route (?:vrf INTERNET )?0\.0\.0\.0 0\.0\.0\.0 (\d+\.\d+\.\d+\.\d+) .*$"
            ):
                netcat.LOGGER.info(
                    "Detected Internet default gateway IP address: {}",
                    inet_gw)
                return inet_gw
Пример #7
0
    def clear_commit_in_progress(self) -> None:
        """ Check if there is any commit in progress and wait till finishes or time out after 3 minutes"""

        netcat.LOGGER.info("Checking for any other commit in progress")

        for _ in range(6):
            if netcat.find_regex_sl(
                    self.send_command("show jobs processed"),
                    r"(^[^ ]+ [^ ]+ +[^ ]+ +\d+ +Commit +ACT .*$)"):
                netcat.LOGGER.warning(
                    "Another commit in progress, will wait 30s and recheck")
                time.sleep(30)
                continue
            break

        else:
            raise netcat.CustomException(
                "Another commit in progress takes over 3 minutes")

        netcat.LOGGER.info("No other commit in progress")
Пример #8
0
    def upgrade_software(self, requested_software_version: str) -> None:
        """ Upgrade software """

        # Make up to three attempts to install software
        for _ in range(3):
            for _ in range(30):
                command_output = self.send_command(
                    f"request system software install version {requested_software_version}"
                )
                if netcat.find_regex_sl(command_output, r"(Server error)"):
                    if netcat.find_regex_sl(command_output,
                                            r"(install is in progress)"):
                        netcat.LOGGER.info(
                            "Another installation in progress, waiting...")
                        time.sleep(10)
                        continue
                    if netcat.find_regex_sl(
                            command_output,
                            r"(pending jobs in the commit task queue)"):
                        netcat.LOGGER.info(
                            "Pending jobs in commit task queue, waiting...")
                        time.sleep(10)
                        continue
                    if netcat.find_regex_sl(command_output,
                                            r"(commit is in progress)"):
                        netcat.LOGGER.info("Commit is in progress, waiting...")
                        time.sleep(10)
                        continue
                    raise netcat.CustomException(
                        f"Received: '{netcat.find_regex_sl(command_output, r'(Server error)')}'"
                    )
                break
            else:
                raise netcat.CustomException(
                    "Another installation in progress for over 5 minutes")

            job_id = netcat.find_regex_sl(
                command_output,
                r"^Software install job enqueued with jobid (\d+)\.\s+.*$")

            netcat.LOGGER.info(
                f"Installation of software version {requested_software_version} started with job id '{job_id}'"
            )

            time.sleep(5)

            while ((
                    command_output :=
                    self.send_command(f"show jobs id {job_id}")
            ) and netcat.find_regex_sl(
                    command_output,
                    rf"^\d\S+\s+\S+\s+(?:\S+\s+)?\d+\s+SWInstall\s+(\S+)\s+\S+\s+\S+\s*$"
            ) in {"ACT", "QUEUED"}):

                installation_progress = netcat.find_regex_sl(
                    command_output,
                    rf"^\d\S+\s+\S+\s+\S+\s+\d+\s+SWInstall\s+\S+\s+\S+\s+(\S+)\s*$"
                )

                netcat.LOGGER.info(
                    f"Installing software version {requested_software_version}, progress {installation_progress}"
                )
                time.sleep(5)

            if netcat.find_regex_sl(
                    command_output,
                    rf"^\d\S+\s+\S+\s+\S+\s+\d+\s+SWInstall\s+FIN\s+(\S+)\s+\S+\s*$"
            ) == "OK":
                netcat.LOGGER.info(
                    f"Installation of software version {requested_software_version} completed"
                )
                break

            netcat.LOGGER.warning(
                f"Installation of version {requested_software_version} failed, will retry up to three times..."
            )
            print("***", command_output, "***")
Пример #9
0
        netcat.LOGGER.info(
            "Detected software version dependencies: {}",
            " -> ".join(requested_software_version_dependencies))

        # Download latest software list
        netcat.LOGGER.info("Refreshing available software versions")
        available_software_versions = self.send_command(
            "request system software check", timeout=120)
        if server_error := netcat.find_regex_sl(available_software_versions,
                                                r"(Server error)"):
            raise netcat.CustomException(f"Received: '{server_error}'")

        # Download all the software versions from dependency list
        for software_version_dependency in requested_software_version_dependencies:
            if netcat.find_regex_sl(
                    available_software_versions,
                    rf"^{software_version_dependency}\s+\S+\s+\S+\s+\S+\s+(\S+)\s*$"
            ) == "yes":
                netcat.LOGGER.info(
                    f"Software version {software_version_dependency} already downloaded"
                )
                continue

            # Make up to three attempts to download software
            for _ in range(3):
                netcat.LOGGER.info(
                    f"Attempting to download software version: {software_version_dependency}"
                )

                # Wait up to five minutes in case any other download is in progress
                for _ in range(30):
                    command_output = self.send_command(
Пример #10
0
def find_broken_links_per_device(
        device_data: Dict[str, Any]) -> List[Dict[str, Any]]:
    """ Search for any link that is down (but not admin down) on Cisco routers and Palo Alto firewalls """

    # Time process execution
    start_time = time.monotonic()

    # Setup logger to show process name
    if os.getpid() != netcat.MAIN_PROCESS_PID:
        netcat.bind_logger("SUB_PROC")

    broken_links = []

    if device_data.get("device_type") == "cisco_router":

        # Look for any broken link
        for interface_name, interface_ip_address in netcat.find_regex_ml(
                netcat.get_command_output(device_data,
                                          "show ip interface brief"),
                rf"^([^\s]*(?:Ethernet|Tunnel)\S+)\s+(\S+)\s+\S+\s+\S+\s+(?:up|down)\s+down\s*$"
        ):

            broken_link = {
                "uuid": uuid.uuid1(),
                "device_name": device_data.get("device_name"),
                "device_type": device_data.get("device_type"),
                "interface_name": interface_name,
                "interface_name_encoded": interface_name.replace("/", "_"),
                "interface_ip_address": interface_ip_address,
            }

            # Search for latest device_info structure that has broken link in UP state and record its timestamp
            device_data_list = db.get_device_data_list__c(
                device_data.get("device_name", ""),
                command_list=["show ip interface brief"])

            for device_data in device_data_list:
                regex_interface_name = interface_name.replace("/",
                                                              "\\/").replace(
                                                                  ".", "\.")
                if netcat.find_regex_sl(
                        netcat.get_command_output(device_data,
                                                  "show ip interface brief"),
                        rf"(^[^\s]*{regex_interface_name}\s+\S+\s+\S+\s+\S+\s+up\s+up\s*$)",
                        hint=interface_name,
                        optional=False):
                    broken_link["snapshot_timestamp"] = device_data.get(
                        "snapshot_timestamp")
                    break

            broken_links.append(broken_link)

    elif device_data.get("device_type") == "paloalto":

        # Skip device if its not in active ha state
        if netcat.find_regex_sl(
                netcat.get_command_output(device_data,
                                          "show high-availability all"),
                r"\s+State: (\S+) .*$") not in {
                    "active", "active-primary", "active-secondary", ""
                }:
            return []

        # Look for any broken link
        for interface_name, interface_mac_address in netcat.find_regex_ml(
                netcat.get_command_output(device_data, "show interface all"),
                r"^((?:ethernet|ae)\S+)\s+\d+\s+ukn\/ukn\/down\S+\s+(\S+)\s*$"
        ):

            broken_link = {
                "uuid": uuid.uuid1(),
                "device_name": device_data.get("device_name"),
                "device_type": device_data.get("device_type"),
                "interface_name": interface_name,
                "interface_name_encoded": interface_name.replace("/", "_"),
                "interface_ip_address": "N/A",
                "interface_mac_address": interface_mac_address,
            }

            # Search for latest device_info structure that has broken BGP session in UP state and record its timestamp
            device_data_list = db.get_device_data_list__c(
                device_data.get("device_name", ""),
                command_list=["show interface all"])

            for device_data in device_data_list:
                regex_interface_name = interface_name.replace("/",
                                                              "\\/").replace(
                                                                  ".", "\.")
                if netcat.find_regex_ml(
                        netcat.get_command_output(device_data,
                                                  "show interface all"),
                        rf"(^{regex_interface_name}\s+\S+\s+\S+\/up\s+\S+\s*$)",
                        hint=interface_name,
                        optional=False):
                    broken_link["snapshot_timestamp"] = device_data.get(
                        "snapshot_timestamp")
                    break

            broken_links.append(broken_link)

    else:
        netcat.LOGGER.warning(
            f"{netcat.fn()}: Unknown device data type value '{device_data.get('type')}'"
        )

    # Time process execution
    end_time = time.monotonic()

    netcat.LOGGER.debug(
        f"Created broken links list of {len(broken_links)} links in {end_time - start_time:.2f}s"
    )

    return broken_links
Пример #11
0
def find_broken_bgp_sessions_per_device(
        device_data: Dict[str, Any]) -> List[Dict[str, Any]]:
    """ Search for broken BGP sessions on Cisco routers and Palo Alto firewalls """

    # Time process execution
    start_time = time.monotonic()

    # Setup logger to show process name
    if os.getpid() != netcat.MAIN_PROCESS_PID:
        netcat.bind_logger("SUB_PROC")

    broken_bgp_sessions = []

    if device_data.get("device_type") == "cisco_router":

        # Look for any broken BGP sessions
        for bgp_session_peer_ip, bgp_session_peer_asn in netcat.find_regex_ml(
                netcat.get_command_output(device_data, "show ip bgp summary"),
                r"^(\S+)\s+\d\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\S+\s+(?:Idle|Active)$"
        ):

            broken_bgp_session = {
                "uuid": uuid.uuid1(),
                "device_name": device_data.get("device_name"),
                "device_type": device_data.get("device_type"),
                "peer_ip": bgp_session_peer_ip,
                "peer_asn": bgp_session_peer_asn,
            }

            # Search for latest device_data document that has broken BGP session in UP state and record its timestamp
            device_data_list = db.get_device_data_list__c(
                device_data.get("device_name", ""),
                command_list=["show ip bgp summary"])

            for device_data in device_data_list:
                if netcat.find_regex_ml(
                        netcat.get_command_output(device_data,
                                                  "show ip bgp summary"),
                        rf"(^{bgp_session_peer_ip}\s+\d\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\S+\s+\d+$)",
                        hint=bgp_session_peer_ip,
                        optional=False):
                    broken_bgp_session["snapshot_timestamp"] = device_data.get(
                        "snapshot_timestamp")
                    break

            broken_bgp_sessions.append(broken_bgp_session)

    elif device_data.get("device_type") == "paloalto":

        # Skip device if its not in active ha state
        if netcat.find_regex_sl(
                netcat.get_command_output(device_data,
                                          "show high-availability all"),
                r"\s+State: (\S+) .*$") not in {
                    "active", "active-primary", "active-secondary", ""
                }:
            return []

        # Look for any broken BGP sessions
        for bgp_session_peer_asn, bgp_session_peer_ip in netcat.find_regex_ml(
                netcat.get_command_output(device_data,
                                          "show routing protocol bgp summary"),
                r"^\s+peer \S+\s+ AS (\d+), (?:Connect|Active), IP (\S+)$"):

            broken_bgp_session = {
                "uuid": uuid.uuid1(),
                "device_name": device_data.get("device_name"),
                "device_type": device_data.get("device_type"),
                "peer_ip": bgp_session_peer_ip,
                "peer_asn": bgp_session_peer_asn,
            }

            # Search for latest device_data structure that has broken BGP session in UP state and record its timestamp
            device_data_list = db.get_device_data_list__c(
                device_data.get("device_name", ""),
                command_list=[
                    "show routing protocol bgp summary",
                    "show high-availability all"
                ])

            for device_data in device_data_list:
                if netcat.find_regex_sl(
                        netcat.get_command_output(
                            device_data, "show routing protocol bgp summary"),
                        rf"(^\s+peer \S+\s+ AS \d+, Established, IP {bgp_session_peer_ip})$",
                        hint=bgp_session_peer_ip,
                        optional=False):
                    broken_bgp_session["snapshot_timestamp"] = device_data.get(
                        "snapshot_timestamp")
                    break

            broken_bgp_sessions.append(broken_bgp_session)

    else:
        netcat.LOGGER.warning(
            f"{netcat.fn()}: Unknown device data type value '{device_data.get('type')}'"
        )

    # Time process execution
    end_time = time.monotonic()

    netcat.LOGGER.debug(
        f"Created broken bgp session list of {len(broken_bgp_sessions)} sessions in {end_time - start_time:.2f}s"
    )

    return broken_bgp_sessions