def check_file_validity(self): """Check whether the a given file exists, is readable and is a file. Args: None Returns: None """ # Initialize key variables file_ = self.tailed_file # Check if exists if os.path.exists(file_) is False: log_message = 'File {} does not exist.'.format(file_) log.log2die(1018, log_message) # Check if file if os.path.isfile(file_) is False: log_message = '{} is not a file.'.format(file_) log.log2die(1035, log_message) # Check if readable if not os.access(file_, os.R_OK): log_message = 'File {} is not readable.'.format(file_) log.log2die(1036, log_message)
def __init__(self, snmp_parameters): """Intialize the class. Args: snmp_parameters: Dict of SNMP parameters to use Returns: None """ # Initialize key 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? - {}' ''.format(snmp_parameters['snmp_hostname'])) log.log2die(1004, log_message) # Fail if snmp_parameters dictionary is empty if bool(snmp_parameters) is False: log_message = ('SNMP parameters provided are blank. ' 'Non existent host?') log.log2die(1005, log_message)
def systemd_daemon(agent_name, action=None): """Manage systemd daemon for agent. Args: agent_name: Name of agent action: Action to occur Returns: None """ # Initialize key variables executable = '/bin/systemctl' options = ['start', 'stop', 'restart'] fixed_action = action.lower() # Check user is root running_username = getpass.getuser() if running_username != 'root': log_message = 'You can only run this command as the \'root\' user.' log.log2die(1133, log_message) # Check if agent exists if systemd_exists(agent_name) is False: log_message = 'systemd not configured for daemon {}'.format(agent_name) log.log2die(1026, log_message) # Process request if fixed_action in options: command = '{} {} {}.service'.format(executable, fixed_action, agent_name) run_script(command) else: log_message = ('Invalid action "{}" for systemd daemon {}' ''.format(action, agent_name)) log.log2die(1126, log_message)
def query(self, oid_to_get, get=False, connectivity_check=False, normalized=False, context_name=''): """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 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 context_name: Set the contextName used for SNMPv3 messages. The default contextName is the empty string "". Overrides the defContext token in the snmp.conf file. Returns: Dictionary of tuples (OID, value) """ # Initialize variables return_results = {} session_error_string = None non_repeaters = 0 max_repetitions = 25 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) log.log2die(1020, log_message) # 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, contextName=context_name) else: (session_error_string, session_error_status, session_error_index, var_binds) = \ snmp_object.bulkCmd( authentication_object, transport_object, non_repeaters, max_repetitions, oid_to_get, contextName=context_name) # Do something here except Exception as exception_error: if connectivity_check is False: # Check for errors and print out results log_message = ('Error occurred during SNMPget on host ' 'OID {} from {} for context "{}": ({})' ''.format(oid_to_get, snmp_params['snmp_hostname'], context_name, exception_error)) log.log2die(1023, log_message) else: var_binds = {} except: log_message = ('Unexpected error') log.log2die(1002, log_message) # 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
def __init__(self, config, hostname): """Initialize class. Args: config: Configuration file object hostname: Hostname 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 = {} self.hostname = hostname yaml_file = config.topology_device_file(self.hostname) # 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, self.hostname) log.log2die(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(): # Skip non Ethernet ports if 'jm_ethernet' not in metadata: continue # Process metadata if bool(metadata['jm_ethernet']) is True: # Update ports self.ports[int(ifindex)] = metadata # Get system self.system = yaml_data['system']
def run_script(cli_string, shell=False, die=True): """Run the cli_string UNIX CLI command and record output. Args: cli_string: Command to run on the CLI die: Die if command runs with an error Returns: None """ # Initialize key variables encoding = locale.getdefaultlocale()[1] header_returncode = ('[Return Code]') header_stdout = ('[Output]') header_stderr = ('[Error Message]') header_bad_cmd = ('[ERROR: Bad Command]') log_message = '' # Create the subprocess object if shell is False: do_command_list = list(cli_string.split(' ')) process = subprocess.Popen(do_command_list, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) else: process = subprocess.Popen(cli_string, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdoutdata, stderrdata = process.communicate() returncode = process.returncode # Crash if the return code is not 0 if die is True: if returncode != 0: # Print the Return Code header, Return Code, STDOUT header string2print = ('%s %s %s %s') % (header_bad_cmd, cli_string, header_returncode, returncode) log_message = ('%s%s') % (log_message, string2print) # Print the STDERR string2print = ('%s') % (header_stderr) log_message = ('%s %s') % (log_message, string2print) for line in stderrdata.decode(encoding).split('\n'): string2print = ('%s') % (line) log_message = ('%s %s') % (log_message, string2print) # Print the STDOUT string2print = ('%s') % (header_stdout) log_message = ('%s %s') % (log_message, string2print) for line in stdoutdata.decode(encoding).split('\n'): string2print = ('%s') % (line) log_message = ('%s %s') % (log_message, string2print) # All done log.log2die(1074, log_message) # Return data = { 'stdout': stdoutdata.decode(), 'stderr': stderrdata.decode(), 'returncode': returncode } return data
def query(self, oid_to_get, get=False, check_reachability=False, check_existence=False, normalized=False, context_name=''): """Do an SNMP query. Args: oid_to_get: OID to walk get: Flag determining whether to do a GET or WALK check_reachability: Set if testing for connectivity. Some session errors are ignored so that a null result is returned check_existence: Set if checking for the existence of the OID 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 context_name: Set the contextName used for SNMPv3 messages. The default contextName is the empty string "". Overrides the defContext token in the snmp.conf file. Returns: Dictionary of tuples (OID, value) """ # Initialize variables snmp_params = self._snmp_params _contactable = True exists = True results = [] # Check if OID is valid if _oid_valid_format(oid_to_get) is False: log_message = ('OID {} has an invalid format'.format(oid_to_get)) log.log2die(1020, log_message) # Create SNMP session session = _Session(snmp_params, context_name=context_name).session # Create failure log message try_log_message = ('Error occurred during SNMP query on host ' 'OID {} from {} for context "{}"' ''.format(oid_to_get, snmp_params['snmp_hostname'], context_name)) # Fill the results object by getting OID data try: # Get the data if get is True: results = [session.get(oid_to_get)] else: results = session.bulkwalk(oid_to_get, non_repeaters=0, max_repetitions=25) # Crash on error, return blank results if doing certain types of # connectivity checks except exceptions.EasySNMPConnectionError as exception_error: (_contactable, exists) = _process_error(try_log_message, exception_error, check_reachability, check_existence) except exceptions.EasySNMPTimeoutError as exception_error: (_contactable, exists) = _process_error(try_log_message, exception_error, check_reachability, check_existence) except exceptions.EasySNMPUnknownObjectIDError as exception_error: (_contactable, exists) = _process_error(try_log_message, exception_error, check_reachability, check_existence) except exceptions.EasySNMPNoSuchNameError as exception_error: (_contactable, exists) = _process_error(try_log_message, exception_error, check_reachability, check_existence) except exceptions.EasySNMPNoSuchObjectError as exception_error: (_contactable, exists) = _process_error(try_log_message, exception_error, check_reachability, check_existence) except exceptions.EasySNMPNoSuchInstanceError as exception_error: (_contactable, exists) = _process_error(try_log_message, exception_error, check_reachability, check_existence) except exceptions.EasySNMPUndeterminedTypeError as exception_error: (_contactable, exists) = _process_error(try_log_message, exception_error, check_reachability, check_existence) except SystemError as exception_error: (_contactable, exists) = _process_error(try_log_message, exception_error, check_reachability, check_existence, system_error=True) except: log_message = ('Unexpected error') log.log2die(1002, log_message) # Format results values = _format_results(results, normalized=normalized) # Return return (_contactable, exists, values)