def configure_raid(self, device_id): _g_logger.info("Configuring RAID on " + str(device_id)) if self.args.formatVolume: exe = self.conf.get_script_location("configureRaid") else: exe = self.conf.get_script_location("assembleRaid") if self.args.raidLevel.upper() == "NONE": raise plugin_exceptions.AgentPluginParameterBadValueException( "mount_volume", "raidLevel", "When using multiple volumes you must specify a RAID level") try: raid_level = str(int(self.args.raidLevel[4:])) except: raise plugin_exceptions.AgentPluginParameterBadValueException( "mount_volume", "raidLevel", "Invalid RAID level") cmd = [exe, raid_level, device_id] for d in self.args.devices: cmd.append(d) _g_logger.debug("Running the raid configuration command %s" % str(cmd)) (stdout, stderr, rc) = plugin_utils.run_command(self.conf, cmd) _g_logger.debug("configure raid results: %d stdout=%s stderr=%s" % (rc, str(stdout), str(stderr))) if rc != 0: _g_logger.error( "Failed to run raid configuration: stdout=%s\nstderr=%s" % (str(stdout), str(stderr))) raise exceptions.AgentExecutableException(cmd, rc, stdout, stderr)
def _is_legal(proposed_name): if len(proposed_name) > 255: raise plugin_exceptions.AgentPluginParameterBadValueException( "rename", "serverName", "less than 255") regex = ("^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)" "*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$") allowed = re.compile(regex) if allowed is None: raise plugin_exceptions.AgentPluginParameterBadValueException( "rename", "serverName", "a legal hostname")
def _do_http_download(self): exe_file = self.conf.get_temp_file("fetch_exe_file") timeout = self.args.connect_timeout u_req = urllib.request.Request(self.args.url) u_req.add_header("Content-Type", "application/x-www-form-urlencoded") u_req.add_header("Connection", "Keep-Alive") u_req.add_header("Cache-Control", "no-cache") response = urllib.request.urlopen(u_req, timeout=timeout) if response.code != 200: raise plugin_exceptions.AgentPluginParameterBadValueException( self.name, "url", expected_values="The url %s was invalid" % self.args.url) sha256 = hashlib.sha256() data = response.read(1024) with open(exe_file, "wb") as fptr: while data: sha256.update(data) fptr.write(data) data = response.read(1024) actual_checksum = sha256.hexdigest() if self.args.checksum and actual_checksum != self.args.checksum: raise plugin_exceptions.AgentPluginOperationException( "The checksum did not match") return exe_file, True
def _validate_arguments(self): # validate that all of the required arguments were sent for arg in self.protocol_arguments: h, mandatory, t, default = self.protocol_arguments[arg] if mandatory and arg not in self.arguments: raise plugin_exceptions.AgentPluginParameterNotSentException( self.name, arg) setattr(self.args, arg, default) # validate that nothing extra was sent for arg in self.arguments: if arg not in self.protocol_arguments: dcm_logger.log_to_dcm_console_unknown_job_parameter( job_name=self.name, parameter_name=arg) else: h, mandatory, t, default = self.protocol_arguments[arg] a = self.arguments[arg] if a is not None: try: a = t(a) except Exception as ex: _g_logger.exception(str(ex)) raise plugin_exceptions.AgentPluginParameterBadValueException( self.name, "Parameter %s has an invalid value %s" % (arg, a)) setattr(self.args, arg, a)
def run(self): _g_logger.info("Running configuration management of type " + self.args.configType) if self.args.configType.upper() == "CHEF": (stdout, stderr, rc) = self.configure_server_with_chef() elif self.args.configType.upper() == "PUPPET": (stdout, stderr, rc) = self.configure_server_with_puppet() else: raise plugin_exceptions.AgentPluginParameterBadValueException( "configType", "CHEF or PUPPET") if stderr: dcm_logger.log_to_dcm_console_configuration_management_error( stderr=stderr) if stdout: dcm_logger.log_to_dcm_console_configuration_management_output( stdout=stdout) if rc != 0: return plugin_base.PluginReply(rc, message=stderr) else: return plugin_base.PluginReply(rc, reply_type="string", reply_object=stdout)
def _normalize_device(self): if self.conf.cloud_type != CLOUD_TYPES.CloudStack and\ self.conf.cloud_type != CLOUD_TYPES.CloudStack3: return self.args.devices[:] modified_device_list = [] for target_device in self.args.devices: if target_device not in _cloud_stack_map: raise plugin_exceptions.AgentPluginParameterBadValueException( "mount_volume", "raidLevel", "When using cloud stack the device must be one of: %s" % str(list(_cloud_stack_map.keys()))) modified_device_list.append(_cloud_stack_map[target_device]) return modified_device_list
def run(self): _scheme_map = {'http': self._do_http_download, 'https': self._do_http_download, 'file': self._do_file} url_parts = urllib.parse.urlparse(self.args.url) if url_parts.scheme not in list(_scheme_map.keys()): # for now we are only accepting http. in the future we will # switch on scheme to decide what cloud storage protocol module # to use raise plugin_exceptions.AgentPluginParameterBadValueException( "url", url_parts.scheme, expected_values=str(list(_scheme_map.keys()))) func = _scheme_map[url_parts.scheme] try: exe_file, cleanup = func() except BaseException as ex: if type(ex) == plugin_exceptions.AgentPluginOperationException: raise return plugin_base.PluginReply( 1, error_message="Failed to download the URL %s: %s" % (self.args.url, str(ex))) try: os.chmod(exe_file, 0o755) command_list = [] if self.args.runUnderSudo: command_list.append(self.conf.system_sudo) if self.args.inpython: command_list.append(sys.executable) command_list.append(exe_file) if self.args.arguments: command_list.extend(self.args.arguments) _g_logger.debug("FetchRunScript is running the command %s" % str(command_list)) (stdout, stderr, rc) = plugin_utils.run_command( self.conf, command_list) _g_logger.debug("Command %s: stdout %s. stderr: %s" % (str(command_list), stdout, stderr)) return plugin_base.PluginReply( rc, message=stdout, error_message=stderr, reply_type="void") finally: if exe_file and cleanup and os.path.exists(exe_file): os.remove(exe_file)
def __init__(self, conf, request_id, items_map, name, arguments): """If the plugin overrides the constructor it must call super on the parent constructor and pass in the same values it was passed. :param conf: The DCM agent configuration object. This can be used as a way to discover information about the agent deployment. As an example conf.platform_name will tell the plugin the linux distribution name (eg: ubuntu). :param request_id: This is the request ID for this specific request of the command. This will be different every time. The plugin will rarely need this information. :param items_map: This is an opaque structure that is threaded through the module. Plugins should only use this when calling super() :param name: The name of this command. This will match cls.command_name :param arguments: The arguments that DCM passed into this command. after the parent constructor is called these arguments will be attributes of the self.args object. """ logname = __name__ + "." + name log = logging.getLogger(logname) self.logger = logging.LoggerAdapter(log, {'job_id': request_id}) self.job_id = request_id self.name = name self.conf = conf self.items_map = items_map self.arguments = arguments self.args = _ArgHolder() try: self._validate_arguments() except plugin_exceptions.AgentPluginParameterBadValueException: raise except Exception as ex: raise plugin_exceptions.AgentPluginParameterBadValueException( self.name, "general", str(ex))