Example #1
0
    def contactable(self):
        """Check if device is contactable.

        Args:
            device_id: Device ID

        Returns:
            contactable: True if a contactable

        """
        # Define key variables
        contactable = False

        # Try to reach device
        try:
            # If we can poll the SNMP sysObjectID,
            # then the device is contactable
            if self.sysobjectid(connectivity_check=True) is not None:
                contactable = True

        except Exception as unused_exception_error:
            # Not contactable
            contactable = False

        except:
            # Log a message
            log_message = ('Unexpected SNMP error for device %s') % (
                self.snmp_params['snmp_hostname'])
            jm_general.logit(1008, log_message, True)

        # Return
        return contactable
Example #2
0
def do_test(cli_args, config):
    """Process 'test' CLI option.

    Args:
        connectivity_check: Set if testing for connectivity

    Returns:
        None

    """
    # Show host information
    validate = snmp_manager.Validate(cli_args.host, config.snmp_auth())
    snmp_params = validate.credentials()

    if bool(snmp_params) is True:
        print('\nValid credentials found:\n')
        print(yaml.dump(snmp_params, default_flow_style=False))
        print('\n')

        # Get SNMP data
        status = snmp_info.Query(snmp_params)
        data = status.everything()

        # Pring result as YAML
        yaml_string = jm_general.dict2yaml(data)
        print(yaml_string)
    else:
        # Error, host problems
        log_message = (
            'Uncontactable host %s or no valid SNMP '
            'credentials found for it.') % (cli_args.host)
        jm_general.logit(1006, log_message)
Example #3
0
def do_test(cli_args, config):
    """Process 'test' CLI option.

    Args:
        connectivity_check: Set if testing for connectivity

    Returns:
        None

    """
    # Show host information
    validate = snmp_manager.Validate(cli_args.host, config.snmp_auth())
    snmp_params = validate.credentials()

    if bool(snmp_params) is True:
        print('\nValid credentials found:\n')
        print(yaml.dump(snmp_params, default_flow_style=False))
        print('\n')

        # Get SNMP data
        status = snmp_info.Query(snmp_params)
        data = status.everything()

        # Pring result as YAML
        yaml_string = jm_general.dict2yaml(data)
        print(yaml_string)
    else:
        # Error, host problems
        log_message = ('Uncontactable host %s or no valid SNMP '
                       'credentials found for it.') % (cli_args.host)
        jm_general.logit(1006, log_message)
Example #4
0
    def contactable(self):
        """Check if device is contactable.

        Args:
            device_id: Device ID

        Returns:
            contactable: True if a contactable

        """
        # Define key variables
        contactable = False

        # Try to reach device
        try:
            # If we can poll the SNMP sysObjectID,
            # then the device is contactable
            if self.sysobjectid(connectivity_check=True) is not None:
                contactable = True

        except Exception as unused_exception_error:
            # Not contactable
            contactable = False

        except:
            # Log a message
            log_message = ('Unexpected SNMP error for device %s') % (
                self.snmp_params['snmp_hostname'])
            jm_general.logit(1008, log_message, True)

        # Return
        return contactable
Example #5
0
    def __init__(self, config, host, ifindices=None):
        """Initialize class.

        Args:
            config: Configuration file object
            host: Hostname to process
            ifindices: List of ifindices to process

        Returns:
            data_dict: Dict of summary data

        """
        # Initialize key variables
        self.ports = {}
        yaml_file = config.snmp_device_file(host)

        # Fail if yaml file doesn't exist
        if os.path.isfile(yaml_file) is False:
            log_message = (
                'YAML file %s for host %s doesn\'t exist! '
                'Try polling devices first.') % (yaml_file, host)
            jm_general.logit(1017, log_message)

        # Read file
        with open(yaml_file, 'r') as file_handle:
            yaml_from_file = file_handle.read()
        yaml_data = yaml.load(yaml_from_file)

        #####################################################################
        #
        # Jordan: You need to add code here to process Juniper devices
        # Create a method / function to populate the ethernet interfaces
        # with vlan data from their type 53 interfaces (if they exist)
        # Then pass the resulting modified yaml_data dictionary to the loop
        # below
        #
        #####################################################################

        # Create dict for layer1 Ethernet data
        for key, metadata in yaml_data['layer1'].items():
            # Only process if key is found in ifindices
            if ifindices is not None:
                if int(key) not in ifindices:
                    continue

            # Process metadata
            if _is_ethernet(metadata) is True:
                # Update vlan to universal infoset metadata value
                metadata['jm_vlan'] = _vlan(yaml_data, key)

                # Update duplex to universal infoset metadata value
                metadata['jm_duplex'] = _duplex(metadata)

                # Update ports
                self.ports[int(key)] = metadata

        # Get system
        self.system = yaml_data['system']
Example #6
0
    def test_logit(self):
        """Testing method / function logit."""
        # Try logging with exit
        log_message = self.random_string
        with self.assertRaises(SystemExit):
            testimport.logit(1000, log_message, True)

        # Try logging with noexit
        result = testimport.logit(1000, log_message, False)
        self.assertEqual(result, None)
Example #7
0
def _process_error(
        connectivity_check=False, session_error_status=None,
        session_error_index=None, get=False,
        log_message=None):
    """Process errors received.

    Args:
        connectivity_check:
                Set if testing for connectivity. Some session
                errors are ignored so that a null result is returned
        session_error_status: Error status
        session_error_index: Error index
        get: True if formatting the results of an SNMP get

    Returns:
        results:

    """
    # Initialize key variables
    results = {}

    # Timeout contacting device
    # (Timeout as OID requested does not exist, not because the
    # device is uncontactable)
    # The device must be checked for connectivity before hand. If it
    # can connect but some additional OID is unavailable, then this is
    # invoked. This is used to determine whether a device has 64 bit
    # IFMIB octet counters
    if connectivity_check is False:
        if (session_error_status == 0) and (
                session_error_index == -24):

            # Return blank results
            return results

    if connectivity_check is True:
        # Bad SNMP authentication during authentication check
        if (session_error_status == 0) and (
                session_error_index == -4):
            # Return blank results
            return results

        # Device completely off the air (SNMP timeout)
        if (session_error_status == 0) and (
                session_error_index == 0):
            # Return blank results
            return results

    # Otherwise Fail
    if get is True:
        action_taken = 'SNMPget'
    else:
        action_taken = 'SNMPwalk'
    log_message = ('%s - %s') % (action_taken, log_message)
    jm_general.logit(1003, log_message, True)
Example #8
0
def _process_error(connectivity_check=False,
                   session_error_status=None,
                   session_error_index=None,
                   get=False,
                   log_message=None):
    """Process errors received.

    Args:
        connectivity_check: True if we were just testing connectivity
        session_error_status: Error status
        session_error_index: Error index
        get: True if formatting the results of an SNMP get

    Returns:
        results:

    """
    # Initialize key variables
    results = {}

    # Timeout contacting device
    # (Timeout as OID requested does not exist, not because the
    # device is uncontactable)
    # The device must be checked for connectivity before hand. If it
    # can connect but some additional OID is unavailable, then this is
    # invoked. This is used to determine whether a device has 64 bit
    # IFMIB octet counters
    if connectivity_check is False:
        if (session_error_status == 0) and (session_error_index == -24):

            # Return blank results
            return results

    if connectivity_check is True:
        # Bad SNMP authentication during authentication check
        if (session_error_status == 0) and (session_error_index == -4):
            # Return blank results
            return results

        # Device completely off the air (SNMP timeout)
        if (session_error_status == 0) and (session_error_index == 0):
            # Return blank results
            return results

    # Otherwise Fail
    if get is True:
        action_taken = 'SNMPget'
    else:
        action_taken = 'SNMPwalk'
    log_message = ('%s - %s') % (action_taken, log_message)
    jm_general.logit(1003, log_message, True)
Example #9
0
    def run(self):
        """Update the database using threads."""
        while True:
            # Get the data_dict
            data_dict = self.queue.get()
            host = data_dict['host']
            config = data_dict['config']
            verbose = data_dict['verbose']
            temp_dir = data_dict['temp_dir']

            # Show host information
            validate = snmp_manager.Validate(host, config.snmp_auth())
            snmp_params = validate.credentials()
            snmp_object = snmp_manager.Interact(snmp_params)

            # Verbose output
            if verbose is True:
                output = ('Processing on: host %s') % (host)
                print(output)

            # Skip invalid, and uncontactable hosts
            if bool(snmp_params) is False:
                if verbose is True:
                    log_message = (
                        'Uncontactable host %s or no valid SNMP '
                        'credentials found for it.') % (host)
                    jm_general.logit(1019, log_message, False)
                continue

            # Process if valid
            if bool(snmp_params) is True:
                # Get data
                status = snmp_info.Query(snmp_object)
                data = status.everything()
                yaml_string = jm_general.dict2yaml(data)

                # Dump data
                temp_file = ('%s/%s.yaml') % (temp_dir, host)
                with open(temp_file, 'w') as file_handle:
                    file_handle.write(yaml_string)

                # Verbose output
                if verbose is True:
                    output = ('Completed run: host %s') % (host)
                    print(output)

            # Signals to queue job is done
            self.queue.task_done()
Example #10
0
    def __init__(self, config, host, ifindices=None):
        """Initialize class.

        Args:
            config: Configuration file object
            host: Hostname to process
            ifindices: List of ifindices to process

        Returns:
            data_dict: Dict of summary data

        """
        # Initialize key variables
        self.ports = {}
        yaml_file = config.snmp_device_file(host)

        # Fail if yaml file doesn't exist
        if os.path.isfile(yaml_file) is False:
            log_message = ('YAML file %s for host %s doesn\'t exist! '
                           'Try polling devices first.') % (yaml_file, host)
            jm_general.logit(1017, log_message)

        # Read file
        with open(yaml_file, 'r') as file_handle:
            yaml_from_file = file_handle.read()
        yaml_data = yaml.load(yaml_from_file)

        # Create dict for layer1 Ethernet data
        for key, metadata in yaml_data['layer1'].items():
            # Only process if key is found in ifindices
            if ifindices is not None:
                if int(key) not in ifindices:
                    continue

            # Process metadata
            if _is_ethernet(metadata) is True:
                # Update vlan to universal infoset metadata value
                metadata['jm_vlan'] = _vlan(yaml_data, key)

                # Update duplex to universal infoset metadata value
                metadata['jm_duplex'] = _duplex(metadata)

                # Update ports
                self.ports[int(key)] = metadata

        # Get system
        self.system = yaml_data['system']
Example #11
0
    def run(self):
        """Update the database using threads."""
        while True:
            # Get the data_dict
            data_dict = self.queue.get()
            host = data_dict['host']
            config = data_dict['config']
            verbose = data_dict['verbose']
            temp_dir = data_dict['temp_dir']

            # Show host information
            validate = snmp_manager.Validate(host, config.snmp_auth())
            snmp_params = validate.credentials()

            # Verbose output
            if verbose is True:
                output = ('Processing on: host %s') % (host)
                print(output)

            # Skip invalid, and uncontactable hosts
            if bool(snmp_params) is False:
                if verbose is True:
                    log_message = ('Uncontactable host %s or no valid SNMP '
                                   'credentials found for it.') % (host)
                    jm_general.logit(1019, log_message, False)
                continue

            # Process if valid
            if bool(snmp_params) is True:
                # Get data
                status = snmp_info.Query(snmp_params)
                data = status.everything()
                yaml_string = jm_general.dict2yaml(data)

                # Dump data
                temp_file = ('%s/%s.yaml') % (temp_dir, host)
                with open(temp_file, 'w') as file_handle:
                    file_handle.write(yaml_string)

                # Verbose output
                if verbose is True:
                    output = ('Completed run: host %s') % (host)
                    print(output)

            # Signals to queue job is done
            self.queue.task_done()
Example #12
0
    def __init__(self, snmp_parameters):
        """Function for intializing the class."""
        # Initialize key variables
        self.snmp_params = {}

        # Assign variables
        self.snmp_params = snmp_parameters

        # Fail if snmp_parameters dictionary is empty
        if snmp_parameters['snmp_version'] is None:
            log_message = ('SNMP version is "None". Non existent host? - %s'
                           '') % (snmp_parameters['snmp_hostname'])
            jm_general.logit(1004, log_message, True)

        # Fail if snmp_parameters dictionary is empty
        if not snmp_parameters:
            log_message = ('SNMP parameters provided are blank. '
                           'Non existent host?')
            jm_general.logit(1005, log_message, True)
Example #13
0
    def __init__(self, snmp_parameters):
        """Function for intializing the class."""
        # Initialize key variables
        self.snmp_params = {}

        # Assign variables
        self.snmp_params = snmp_parameters

        # Fail if snmp_parameters dictionary is empty
        if snmp_parameters['snmp_version'] is None:
            log_message = (
                'SNMP version is "None". Non existent host? - %s'
                '') % (snmp_parameters['snmp_hostname'])
            jm_general.logit(1004, log_message, True)

        # Fail if snmp_parameters dictionary is empty
        if not snmp_parameters:
            log_message = ('SNMP parameters provided are blank. '
                           'Non existent host?')
            jm_general.logit(1005, log_message, True)
Example #14
0
    def web_directory(self):
        """Determine the web_directory.

        Args:
            None

        Returns:
            value: configured web_directory

        """
        # Get parameter
        value = self.config_dict['web_directory']

        # Check if value exists
        if os.path.isdir(value) is False:
            log_message = ('web_directory: "%s" '
                           'in configuration doesn\'t exist!') % (value)
            jm_general.logit(1016, log_message)

        # Return
        return value
Example #15
0
    def web_directory(self):
        """Determine the web_directory.

        Args:
            None

        Returns:
            value: configured web_directory

        """
        # Get parameter
        value = self.config_dict['web_directory']

        # Check if value exists
        if os.path.isdir(value) is False:
            log_message = (
                'web_directory: "%s" '
                'in configuration doesn\'t exist!') % (value)
            jm_general.logit(1016, log_message)

        # Return
        return value
Example #16
0
    def __init__(self, config_directory):
        """Function for intializing the class."""
        # Initialize key variables
        yaml_found = False
        yaml_from_file = ''
        all_yaml_read = ''

        # Check if config_directory exists
        if os.path.isdir(config_directory) is False:
            log_message = (
                'Configuration directory "%s" '
                'doesn\'t exist!' % config_directory)
            jm_general.logit(1009, log_message)

        # Cycle through list of files in directory
        for filename in os.listdir(config_directory):
            # Examine all the '.yaml' files in directory
            if filename.endswith('.yaml'):
                # YAML files found
                yaml_found = True

                # Read file and add to string
                file_path = ('%s/%s') % (config_directory, filename)
                with open(file_path, 'r') as file_handle:
                    yaml_from_file = file_handle.read()

                # Append yaml from file to all yaml previously read
                all_yaml_read = ('%s\n%s') % (all_yaml_read, yaml_from_file)

        # Verify YAML files found in directory
        if yaml_found is False:
            log_message = (
                'No files found in directory "%s" with ".yaml" '
                'extension.') % (config_directory)
            jm_general.logit(1010, log_message)

        # Return
        self.config_dict = yaml.load(all_yaml_read)
Example #17
0
    def db_modify(self, sql_statement, error_code, data_list=False):
        """Do a database modification.

        Args:
            sql_statement: SQL statement
            error_code: Error number to use if one occurs
            data_list: If not False, then the SQL statement is referring
                to a bulk update using a list of tuples contained in
                data_list.

        Returns:
            query_results: Query results

        """
        # Make sure this is a UPDATE, INSERT or REPLACE statement
        first_word = sql_statement.split()[0]
        if ((first_word.lower() != 'update') and
                (first_word.lower() != 'delete') and
                (first_word.lower() != 'insert') and
                (first_word.lower() != 'replace')):

            log_message = ('db_modify function can only do '
                           'INSERT, UPDATE, DELETE or REPLACE: '
                           'SQL statement %s') % (sql_statement)
            jm_general.logit(error_code, log_message)

        # Open database connection. Prepare cursor
        cursor = self.database.cursor()

        try:
            # If a list is provided, then do an executemany
            if data_list:
                # Execute the SQL command
                cursor.executemany(sql_statement, data_list)
            else:
                # Execute the SQL command
                cursor.execute(sql_statement)

            # Commit  change
            self.database.commit()

        except Exception as exception_error:
            self.database.rollback()
            log_message = (
                'Unable to modify database. '
                'SQL statement: \"%s\" Error: \"%s\"') % (
                    sql_statement, exception_error)
            jm_general.logit(error_code, log_message)
        except:
            self.database.rollback()
            log_message = ('Unexpected exception. SQL statement: \"%s\"') % (
                sql_statement)
            jm_general.logit(error_code, log_message)

        # disconnect from server
        self.database.close()
Example #18
0
    def __init__(self, config_directory):
        """Function for intializing the class."""
        # Initialize key variables
        yaml_found = False
        yaml_from_file = ''
        all_yaml_read = ''

        # Check if config_directory exists
        if os.path.isdir(config_directory) is False:
            log_message = ('Configuration directory "%s" '
                           'doesn\'t exist!' % config_directory)
            jm_general.logit(1009, log_message)

        # Cycle through list of files in directory
        for filename in os.listdir(config_directory):
            # Examine all the '.yaml' files in directory
            if filename.endswith('.yaml'):
                # YAML files found
                yaml_found = True

                # Read file and add to string
                file_path = ('%s/%s') % (config_directory, filename)
                with open(file_path, 'r') as file_handle:
                    yaml_from_file = file_handle.read()

                # Append yaml from file to all yaml previously read
                all_yaml_read = ('%s\n%s') % (all_yaml_read, yaml_from_file)

        # Verify YAML files found in directory
        if yaml_found is False:
            log_message = ('No files found in directory "%s" with ".yaml" '
                           'extension.') % (config_directory)
            jm_general.logit(1010, log_message)

        # Return
        self.config_dict = yaml.load(all_yaml_read)
Example #19
0
    def db_query(self, sql_statement, error_code):
        """Do a database query.

        Args:
            sql_statement: SQL statement
            error_code: Error number to use if one occurs

        Returns:
            query_results: Query results

        """
        # Make sure this is a SELECT statement
        first_word = sql_statement.split()[0]
        if first_word.lower() != 'select':
            log_message = ('db_query function can only do SELECT: '
                           'SQL statement %s') % (sql_statement)
            jm_general.logit(error_code, log_message)

        # Open database connection. Prepare cursor
        cursor = self.database.cursor()

        try:
            # Execute the SQL command
            cursor.execute(sql_statement)
            query_results = cursor.fetchall()

        except Exception as exception_error:
            log_message = (
                'Unable to fetch data from database. '
                'SQL statement: \"%s\" Error: \"%s\"') % (
                    sql_statement, exception_error)
            jm_general.logit(error_code, log_message)
        except:
            log_message = ('Unexpected exception. SQL statement: \"%s\"') % (
                sql_statement)
            jm_general.logit(error_code, log_message)

        # Disconnect from server
        self.database.close()

        return query_results
Example #20
0
def make(config, verbose=False):
    """Process 'pagemaker' CLI option.

    Args:
        config: Configuration object
        verbose: Verbose output if True

    Returns:
        None

    """
    # Initialize key variables
    threads_in_pool = 10
    device_file_found = False

    # Create directory if needed
    perm_dir = config.web_directory()
    temp_dir = tempfile.mkdtemp()

    # Delete all files in temporary directory
    jm_general.delete_files(temp_dir)

    # Spawn a pool of threads, and pass them queue instance
    for unused_var in range(threads_in_pool):
        update_thread = PageMaker(THREAD_QUEUE)
        update_thread.daemon = True
        update_thread.start()

    # Get host data and write to file
    for host in config.hosts():
        # Skip if device file not found
        if os.path.isfile(config.snmp_device_file(host)) is False:
            log_message = (
                'No YAML device file for host %s found in %s. '
                'Run toolbox.py with the "poll" option first.'
                '') % (host, config.snmp_directory())
            jm_general.logit(1018, log_message, False)
            continue
        else:
            device_file_found = True

        ####################################################################
        #
        # Define variables that will be required for the database update
        # We have to initialize the dict during every loop to prevent
        # data corruption
        #
        ####################################################################
        data_dict = {}
        data_dict['host'] = host
        data_dict['config'] = config
        data_dict['verbose'] = verbose
        data_dict['temp_dir'] = temp_dir
        THREAD_QUEUE.put(data_dict)

    # Do the rest if device_file_found
    if device_file_found is True:
        # Wait on the queue until everything has been processed
        THREAD_QUEUE.join()

        # PYTHON BUG. Join can occur while threads are still shutting down.
        # This can create spurious "Exception in thread (most likely raised
        # during interpreter shutdown)" errors.
        # The "time.sleep(1)" adds a delay to make sure things really terminate
        # properly. This seems to be an issue on virtual machines in Dev only
        time.sleep(1)

        # Create index file
        write_file = ('%s/index.html') % (temp_dir)
        index_html = _index_html(config)
        with open(write_file, 'w') as file_handle:
            file_handle.write(index_html)

        # Cleanup, move temporary files to clean permanent directory.
        # Delete temporary directory
        if os.path.isdir(perm_dir):
            jm_general.delete_files(perm_dir)
        else:
            os.makedirs(perm_dir, 0o755)
        jm_general.move_files(temp_dir, perm_dir)

    # Clean up
    os.rmdir(temp_dir)
Example #21
0
    def __init__(self, config, host, ifindices=None):
        """Initialize class.

        Args:
            config: Configuration file object
            host: Hostname to process
            ifindices: List of ifindices to process

        Returns:
            data_dict: Dict of summary data

        Summary:

            IF-MIB

            A significant portion of this code relies on ifIndex
            IF-MIB::ifStackStatus information. This is stored under the
            'system' key of the device YAML files.

            According to the official IF-MIB file. ifStackStatus is a
            "table containing information on the relationships
            between the multiple sub-layers of network interfaces.  In
            particular, it contains information on which sub-layers run
            'on top of' which other sub-layers, where each sub-layer
            corresponds to a conceptual row in the ifTable.  For
            example, when the sub-layer with ifIndex value x runs over
            the sub-layer with ifIndex value y, then this table
            contains:

              ifStackStatus.x.y=active

            For each ifIndex value, I, which identifies an active
            interface, there are always at least two instantiated rows
            in this table associated with I.  For one of these rows, I
            is the value of ifStackHigherLayer; for the other, I is the
            value of ifStackLowerLayer.  (If I is not involved in
            multiplexing, then these are the only two rows associated
            with I.)

            For example, two rows exist even for an interface which has
            no others stacked on top or below it:

              ifStackStatus.0.x=active
              ifStackStatus.x.0=active"

            In the case of Juniper equipment, VLAN information is only
            visible on subinterfaces of the main interface. For example
            interface ge-0/0/0 won't have VLAN information assigned to it
            directly.

            When a VLAN is assigned to this interface, a subinterface
            ge-0/0/0.0 is automatically created with a non-Ethernet ifType.
            VLAN related OIDs are only maintained for this new subinterface
            only. This makes determining an interface's VLAN based on
            Ethernet ifType more difficult. ifStackStatus maps the ifIndex of
            the primary interface (ge-0/0/0) to the ifIndex of the secondary
            interface (ge-0/0/0.0) which manages higher level protocols and
            data structures such as VLANs and LLDP.

            The primary interface is referred to as the
            ifStackLowerLayer and the secondary subinterface is referred to
            as the ifStackHigherLayer.

            =================================================================

            Layer1 Keys

            The following Layer1 keys are presented by the ethernet_data
            method due to this instantiation:

            jm_nativevlan: A vendor agnostic Native VLAN
            jm_vlan: A list of vendor agnostic VLANs
            jm_trunk: A vendor agnostic flag of "True" if the port is a Trunk
            jm_duplex: A vendor agnostic status code for the duplex setting

        """
        # Initialize key variables
        self.ports = {}
        yaml_file = config.snmp_device_file(host)

        # Fail if yaml file doesn't exist
        if os.path.isfile(yaml_file) is False:
            log_message = (
                'YAML file %s for host %s doesn\'t exist! '
                'Try polling devices first.') % (yaml_file, host)
            jm_general.logit(1017, log_message)

        # Read file
        with open(yaml_file, 'r') as file_handle:
            yaml_from_file = file_handle.read()
        yaml_data = yaml.load(yaml_from_file)

        # Create dict for layer1 Ethernet data
        for ifindex, metadata in yaml_data['layer1'].items():
            # Only process if ifIndex is found in ifindices
            if ifindices is not None:
                if int(ifindex) not in ifindices:
                    continue

            # Process metadata
            if _is_ethernet(metadata) is True:
                # Get the ifIndex of the lower layer interface
                ifstacklowerlayer = ifindex

                #############################################################
                #
                # This stuff relies on ifstacklowerlayer / ifstackhigherlayer
                #
                #############################################################
                # Determine the ifIndex for any existing higher
                # layer subinterfaces whose data could be used
                # for upper layer2 features such as VLANs and
                # LAG trunking
                higherlayers = yaml_data[
                    'system']['IF-MIB']['ifStackStatus'][ifindex]

                # Update vlan to universal infoset metadata value
                for higherlayer in higherlayers:
                    # All numeric keys in YAML need to be strings. Prepare
                    # for key checking.
                    ifstackhigherlayer = str(higherlayer)

                    # This is an Ethernet port with no higher level
                    # interfaces. Use lower level ifIndex
                    if ifstackhigherlayer == '0':
                        metadata['jm_vlan'] = _vlan(
                            yaml_data, ifstacklowerlayer)

                        metadata['jm_nativevlan'] = _nativevlan(
                            yaml_data, ifstacklowerlayer)

                        metadata['jm_trunk'] = _trunk(
                            yaml_data, ifstacklowerlayer)
                    else:
                        # Assign native VLAN to higer layer
                        metadata['jm_nativevlan'] = _nativevlan(
                            yaml_data, ifstackhigherlayer)

                        # Update trunk status to universal metadata value
                        metadata['jm_trunk'] = _trunk(
                            yaml_data, ifstackhigherlayer)

                        # This is an Ethernet port with a single higher level
                        # interface
                        if len(higherlayers) == 1:
                            metadata['jm_vlan'] = _vlan(
                                yaml_data, ifstackhigherlayer)
                        # This is an Ethernet port with multiple higher level
                        # interfaces
                        else:
                            metadata['jm_vlan'].extend(
                                _vlan(yaml_data, ifstackhigherlayer))

                #############################################################
                #
                # This stuff relies on ifindex
                #
                #############################################################

                # Update duplex to universal infoset metadata value
                metadata['jm_duplex'] = _duplex(metadata)

                # Update ports
                self.ports[int(ifindex)] = metadata

        # Get system
        self.system = yaml_data['system']
Example #22
0
    def query(
            self, oid_to_get, get=False, connectivity_check=False,
            normalized=False):
        """Do an SNMP query.

        Args:
            oid_to_get: OID to walk
            get: Flag determining whether to do a GET or WALK
            normalized: If True, then return results as a dict keyed by
                only the last node of an OID, otherwise return results
                keyed by the entire OID string. Normalization is useful
                when trying to create multidimensional dicts where the
                primary key is a universal value such as IF-MIB::ifIndex
                or BRIDGE-MIB::dot1dBasePort
            connectivity_check:
                Set if testing for connectivity. Some session
                errors are ignored so that a null result is returned

        Returns:
            Dictionary of tuples (OID, value)

        """
        # Initialize variables
        return_results = {}
        snmp_params = self.snmp_params

        # Check if OID is valid
        valid_format = oid_valid_format(oid_to_get)
        if valid_format is False:
            log_message = ('OID %s has an invalid format') % (oid_to_get)
            jm_general.logit(1000, log_message, True)

        # Create the object
        snmp_object = cmdgen.CommandGenerator()

        # Setup Transport object
        transport_object = cmdgen.UdpTransportTarget(
            (snmp_params['snmp_hostname'], snmp_params['snmp_port']))

        # Create the auth object
        authentication_object = _get_auth_object(snmp_params)

        # Fill the results object by getting OID data
        try:
            # Get the data
            if get is True:
                (session_error_string, session_error_status,
                 session_error_index, var_binds) = \
                    snmp_object.getCmd(
                        authentication_object, transport_object, oid_to_get)
            else:
                (session_error_string, session_error_status,
                 session_error_index, var_binds) = \
                    snmp_object.nextCmd(
                        authentication_object, transport_object, oid_to_get)

        # Do something here
        except Exception as exception_error:
            # Check for errors and print out results
            log_message = (
                'Error occurred during SNMPget on host '
                'OID %s from %s: (%s)') % (oid_to_get,
                                           snmp_params['snmp_hostname'],
                                           exception_error)
            jm_general.logit(1001, log_message, True)
        except:
            log_message = ('Unexpected error')
            jm_general.logit(1002, log_message, True)

        # Crash on error, return blank results if doing certain types of
        # connectivity checks
        if session_error_string:
            log_message = (
                'Error occurred for OID %s on host %s: '
                '(%s) ErrorNum: %s, ErrorInd: '
                '%s') % (oid_to_get,
                         snmp_params['snmp_hostname'],
                         session_error_string,
                         session_error_status, session_error_index)

            return _process_error(
                connectivity_check=connectivity_check,
                session_error_status=session_error_status,
                session_error_index=session_error_index,
                get=get,
                log_message=log_message)

        # Format results
        return_results = _format_results(
            normalized=normalized, get=get, var_binds=var_binds)

        # Return
        return return_results
Example #23
0
def make(config, verbose=False):
    """Process 'pagemaker' CLI option.

    Args:
        config: Configuration object
        verbose: Verbose output if True

    Returns:
        None

    """
    # Initialize key variables
    threads_in_pool = 10
    device_file_found = False

    # Create directory if needed
    perm_dir = config.web_directory()
    temp_dir = tempfile.mkdtemp()

    # Delete all files in temporary directory
    jm_general.delete_files(temp_dir)

    # Spawn a pool of threads, and pass them queue instance
    for unused_var in range(threads_in_pool):
        update_thread = PageMaker(THREAD_QUEUE)
        update_thread.daemon = True
        update_thread.start()

    # Get host data and write to file
    for host in config.hosts():
        # Skip if device file not found
        if os.path.isfile(config.snmp_device_file(host)) is False:
            log_message = (
                'No YAML device file for host %s found in %s. '
                'Run toolbox.py with the "poll" option first.'
                '') % (host, config.snmp_directory())
            jm_general.logit(1018, log_message, False)
            continue
        else:
            device_file_found = True

        ####################################################################
        #
        # Define variables that will be required for the database update
        # We have to initialize the dict during every loop to prevent
        # data corruption
        #
        ####################################################################
        data_dict = {}
        data_dict['host'] = host
        data_dict['config'] = config
        data_dict['verbose'] = verbose
        data_dict['temp_dir'] = temp_dir
        THREAD_QUEUE.put(data_dict)

    # Do the rest if device_file_found
    if device_file_found is True:
        # Wait on the queue until everything has been processed
        THREAD_QUEUE.join()

        # PYTHON BUG. Join can occur while threads are still shutting down.
        # This can create spurious "Exception in thread (most likely raised
        # during interpreter shutdown)" errors.
        # The "time.sleep(1)" adds a delay to make sure things really terminate
        # properly. This seems to be an issue on virtual machines in Dev only
        time.sleep(1)

        # Create index file
        write_file = ('%s/index.html') % (temp_dir)
        index_html = _index_html(config)
        with open(write_file, 'w') as file_handle:
            file_handle.write(index_html)

        # Cleanup, move temporary files to clean permanent directory.
        # Delete temporary directory
        if os.path.isdir(perm_dir):
            jm_general.delete_files(perm_dir)
        else:
            os.makedirs(perm_dir, 0o755)
        jm_general.move_files(temp_dir, perm_dir)

    # Clean up
    os.rmdir(temp_dir)
Example #24
0
    def query(self,
              oid_to_get,
              get=False,
              connectivity_check=False,
              normalized=False):
        """Do an SNMP query.

        Args:
            oid_to_get: OID to walk
            get: Flag determining whether to do a GET or WALK
            connectivity_check:
                Set if testing for connectivity. Some session
                errors are ignored so that a null result is returned

        Returns:
            Dictionary of tuples (OID, value)

        """
        # Initialize variables
        return_results = {}
        snmp_params = self.snmp_params

        # Check if OID is valid
        valid_format = oid_valid_format(oid_to_get)
        if valid_format is False:
            log_message = ('OID %s has an invalid format') % (oid_to_get)
            jm_general.logit(1000, log_message, True)

        # Create the object
        snmp_object = cmdgen.CommandGenerator()

        # Setup Transport object
        transport_object = cmdgen.UdpTransportTarget(
            (snmp_params['snmp_hostname'], snmp_params['snmp_port']))

        # Create the auth object
        authentication_object = _get_auth_object(snmp_params)

        # Fill the results object by getting OID data
        try:
            # Get the data
            if get is True:
                (session_error_string, session_error_status,
                 session_error_index, var_binds) = \
                    snmp_object.getCmd(
                        authentication_object, transport_object, oid_to_get)
            else:
                (session_error_string, session_error_status,
                 session_error_index, var_binds) = \
                    snmp_object.nextCmd(
                        authentication_object, transport_object, oid_to_get)

        # Do something here
        except Exception as exception_error:
            # Check for errors and print out results
            log_message = ('Error occurred during SNMPget on host '
                           'OID %s from %s: (%s)') % (
                               oid_to_get, snmp_params['snmp_hostname'],
                               exception_error)
            jm_general.logit(1001, log_message, True)
        except:
            log_message = ('Unexpected error')
            jm_general.logit(1002, log_message, True)

        # Crash on error, return blank results if doing certain types of
        # connectivity checks
        if session_error_string:
            log_message = ('Error occurred for OID %s on host %s: '
                           '(%s) ErrorNum: %s, ErrorInd: '
                           '%s') % (oid_to_get, snmp_params['snmp_hostname'],
                                    session_error_string, session_error_status,
                                    session_error_index)

            return _process_error(connectivity_check=connectivity_check,
                                  session_error_status=session_error_status,
                                  session_error_index=session_error_index,
                                  get=get,
                                  log_message=log_message)

        # Format results
        return_results = _format_results(normalized=normalized,
                                         get=get,
                                         var_binds=var_binds)

        # Return
        return return_results