def _agent_config(agent_name, config_dict): """Get agent config parameter from YAML. Args: agent_name: Agent Name config_dict: Dictionary to explore die: Die if true and the result encountered is None Returns: result: result """ # Get result key = 'agents' result = None # Get new result if key in config_dict: configurations = config_dict[key] for configuration in configurations: if 'agent_name' in configuration: if configuration['agent_name'] == agent_name: result = configuration break # Error if not configured if result is None: log_message = ( 'Agent %s not defined in configuration in ' 'agents:%s section') % (key, key) log.log2die(1094, log_message) # Return return result
def agent_cache_directory(self): """Determine the agent_cache_directory. Args: None Returns: value: configured agent_cache_directory """ # Initialize key variables key = 'main' sub_key = 'agent_cache_directory' # Get result value = _key_sub_key(key, sub_key, self.config_dict) # Check if value exists if os.path.isdir(value) is False: log_message = ( 'agent_cache_directory: "%s" ' 'in configuration doesn\'t exist!') % (value) log.log2die(1031, log_message) # Return return value
def start(self): """Start the daemon. Args: None Returns: """ # Check for a pidfile to see if the daemon already runs try: with open(self.pidfile, 'r') as pf_handle: pid = int(pf_handle.read().strip()) except IOError: pid = None if pid: log_message = ( 'PID file: %s already exists. Daemon already running?' '') % (self.pidfile) log.log2die(1062, log_message) # Start the daemon # self.daemonize() # Log success log_message = ('Daemon Started - PID file: %s') % (self.pidfile) log.log2info(1070, log_message) # Run code for daemon self.run()
def move_files(source_dir, target_dir): """Delete files in a directory. Args: source_dir: Directory where files are currently target_dir: Directory where files need to be Returns: Nothing """ # Make sure source directory exists if os.path.exists(source_dir) is False: log_message = ('Directory %s does not exist.') % (source_dir) log.log2die(1011, log_message) # Make sure target directory exists if os.path.exists(target_dir) is False: log_message = ('Directory %s does not exist.') % (target_dir) log.log2die(1012, log_message) source_files = os.listdir(source_dir) for filename in source_files: full_path = ('%s/%s') % (source_dir, filename) shutil.move(full_path, target_dir)
def populate(self, data_in): """Populate data for agent to eventually send to server. Args: data_in: dict of datapoint values from agent timeseries: TimeSeries data if True Returns: None """ # Initialize data data = deepcopy(data_in) # Validate base_type if len(data) != 1 or isinstance(data, defaultdict) is False: log_message = ('Agent data "%s" is invalid') % (data) log.log2die(1025, log_message) # Get a description to use for label value for label in data.keys(): description = self.lang.label_description(label) data[label]['description'] = description break # Add data to appropriate self.data key if data[label]['base_type'] is not None: self.data['timeseries'].update(data) else: self.data['timefixed'].update(data)
def daemonize(self): """Deamonize class. UNIX double fork mechanism. Args: None Returns: None """ # Create a parent process that will manage the child # when the code using this class is done. try: pid = os.fork() if pid > 0: # Exit first parent sys.exit(0) except OSError as err: log_message = ('Daemon fork #1 failed: %s') % (err) log_message = ('%s - PID file: %s') % (log_message, self.pidfile) log.log2die(1060, log_message) # Decouple from parent environment os.chdir('/') os.setsid() os.umask(0) # Do second fork try: pid = os.fork() if pid > 0: # exit from second parent sys.exit(0) except OSError as err: log_message = ('Daemon fork #2 failed: %s') % (err) log_message = ('%s - PID file: %s') % (log_message, self.pidfile) log.log2die(1061, log_message) # Redirect standard file descriptors sys.stdout.flush() sys.stderr.flush() f_handle_si = open(os.devnull, 'r') # f_handle_so = open(os.devnull, 'a+') f_handle_so = open(os.devnull, 'a+') f_handle_se = open(os.devnull, 'a+') os.dup2(f_handle_si.fileno(), sys.stdin.fileno()) # os.dup2(f_handle_so.fileno(), sys.stdout.fileno()) os.dup2(f_handle_so.fileno(), sys.stdout.fileno()) os.dup2(f_handle_se.fileno(), sys.stderr.fileno()) # write pidfile atexit.register(self.delpid) pid = str(os.getpid()) with open(self.pidfile, 'w+') as f_handle: f_handle.write(pid + '\n')
def stop(self): """Stop the daemon. Args: None Returns: """ # Get the pid from the pidfile try: with open(self.pidfile, 'r') as pf_handle: pid = int(pf_handle.read().strip()) except IOError: pid = None if not pid: log_message = ('PID file: %s does not exist. Daemon not running?' '') % (self.pidfile) log.log2warning(1063, log_message) # Not an error in a restart return # Try killing the daemon process try: while 1: if self.lockfile is None: os.kill(pid, signal.SIGTERM) else: time.sleep(0.3) if os.path.exists(self.lockfile) is True: continue else: os.kill(pid, signal.SIGTERM) time.sleep(0.3) except OSError as err: error = str(err.args) if error.find("No such process") > 0: self.delpid() self.dellock() else: log_message = (str(err.args)) log_message = ('%s - PID file: %s') % (log_message, self.pidfile) log.log2die(1068, log_message) except: log_message = ('Unknown daemon "stop" error for PID file: %s' '') % (self.pidfile) log.log2die(1066, log_message) # Log success self.delpid() self.dellock() log_message = ('Daemon Stopped - PID file: %s') % (self.pidfile) log.log2info(1071, log_message)
def purge(self): """Purge data from cache by posting to central server. Args: None Returns: success: "True: if successful """ # Initialize key variables id_agent = self.data['id_agent'] # Add files in cache directory to list only if they match the # cache suffix all_filenames = [ filename for filename in os.listdir(self.cache_dir) if os.path.isfile(os.path.join(self.cache_dir, filename)) ] filenames = [ filename for filename in all_filenames if filename.endswith(self.cache_suffix) ] # Read cache file for filename in filenames: # Only post files for our own UID value if id_agent not in filename: continue # Get the full filepath for the cache file and post filepath = os.path.join(self.cache_dir, filename) with open(filepath, 'r') as f_handle: try: data = json.load(f_handle) except: # Log removal log_message = ( 'Error reading previously cached agent data file %s ' 'for agent %s. May be corrupted.' '') % (filepath, self.name()) log.log2die(1064, log_message) # Post file success = self.post(save=False, data=data) # Delete file if successful if success is True: os.remove(filepath) # Log removal log_message = ('Purging cache file %s after successfully ' 'contacting server %s' '') % (filepath, self.url) log.log2info(1029, log_message)
def _mkdir(directory): """Create a directory if it doesn't already exist. Args: directory: Directory name Returns: None """ # Do work if os.path.exists(directory) is False: os.makedirs(directory, mode=0o775) else: if os.path.isfile(directory) is True: log_message = ('%s is not a directory.' '') % (directory) log.log2die(1043, log_message)
def __init__(self, config): """Method initializing the class. Args: None Returns: None """ # Initialize key variables self.api = API(config) (self._idx_device, self._idx_agent) = self._garnet_device_agent() if self._idx_device is None or self._idx_agent is None: log_message = ('Unable to contact API server.') log.log2die(1050, log_message) else: self._devicename = self._garnet_devicename()
def agents(self): """Get agents. Args: None Returns: result: list of agents """ # Initialize key variables key = 'agents' result = None # Verify data if key not in self.config_dict: log_message = ('No agents configured') log.log2die(1100, log_message) # Process agents result = self.config_dict[key] # Return return result
def read_yaml_files(directories): """Read the contents of all yaml files in a directory. Args: directories: List of directory names with configuration files Returns: config_dict: Dict of yaml read """ # Initialize key variables yaml_found = False yaml_from_file = '' all_yaml_read = '' # Check each directory in sequence for config_directory in directories: # Check if config_directory exists if os.path.isdir(config_directory) is False: log_message = ('Configuration directory "%s" ' 'doesn\'t exist!' % config_directory) log.log2die(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) try: with open(file_path, 'r') as file_handle: yaml_from_file = file_handle.read() except: log_message = ('Error reading file %s. Check permissions, ' 'existence and file syntax.' '') % (file_path) log.log2die(1065, log_message) # 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) log.log2die(1010, log_message) # Return config_dict = yaml.load(all_yaml_read) return config_dict
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 return stdoutdata