Example #1
0
  def uninstall(self, unique_id, configs=None):
    """uninstall the service.  If the deployer has not started a service with
    `unique_id` this will raise a DeploymentError.  This considers one config:
    'additional_directories': a list of directories to remove in addition to those provided in the constructor plus
     the install path. This will update the directories to remove but does not override it
    :param unique_id:
    :param configs:
    :return:
    """
    # the following is necessay to set the configs for this function as the combination of the
    # default configurations and the parameter with the parameter superceding the defaults but
    # not modifying the defaults
    if configs is None:
      configs = {}
    tmp = self.default_configs.copy()
    tmp.update(configs)
    configs = tmp

    if unique_id in self.processes:
      hostname = self.processes[unique_id].hostname
    else:
      logger.error("Can't uninstall {0}: process not known".format(unique_id))
      raise DeploymentError("Can't uninstall {0}: process not known".format(unique_id))

    install_path = self.processes[unique_id].install_path
    directories_to_remove = self.default_configs.get('directories_to_clean', [])
    directories_to_remove.extend(configs.get('additional_directories', []))
    if install_path not in directories_to_remove:
      directories_to_remove.append(install_path)
    with get_ssh_client(hostname, username=runtime.get_username(), password=runtime.get_password()) as ssh:
      for directory_to_remove in directories_to_remove:
        log_output(better_exec_command(ssh, "rm -rf {0}".format(directory_to_remove),
                                       "Failed to remove {0}".format(directory_to_remove)))
Example #2
0
    def stop(self, unique_id, configs=None):
        """Stop the service.  If the deployer has not started a service with`unique_id` the deployer will raise an Exception
    There are two configs that will be considered:
    'terminate_only': if this config is passed in then this method is the same as terminate(unique_id) (this is also the
    behavior if stop_command is None and not overridden)
    'stop_command': overrides the default stop_command

    :param unique_id:
    :param configs:
    :return:
    """
        # the following is necessay to set the configs for this function as the combination of the
        # default configurations and the parameter with the parameter superceding the defaults but
        # not modifying the defaults
        if configs is None:
            configs = {}
        tmp = self.default_configs.copy()
        tmp.update(configs)
        configs = tmp

        logger.debug("stopping " + unique_id)

        if unique_id in self.processes:
            hostname = self.processes[unique_id].hostname
        else:
            logger.error("Can't stop {0}: process not known".format(unique_id))
            raise DeploymentError(
                "Can't stop {0}: process not known".format(unique_id))

        if configs.get('terminate_only', False):
            self.terminate(unique_id, configs)
        else:
            stop_command = configs.get(
                'stop_command') or self.default_configs.get('stop_command')
            env = configs.get("env", {})
            if stop_command is not None:
                install_path = self.processes[unique_id].install_path
                with get_ssh_client(hostname,
                                    username=runtime.get_username(),
                                    password=runtime.get_password()) as ssh:
                    log_output(
                        exec_with_env(
                            ssh,
                            "cd {0}; {1}".format(install_path, stop_command),
                            msg="Failed to stop {0}".format(unique_id),
                            env=env))
            else:
                self.terminate(unique_id, configs)

        if 'delay' in configs:
            time.sleep(configs['delay'])
Example #3
0
  def stop(self, unique_id, configs=None):
    """Stop the service.  If the deployer has not started a service with`unique_id` the deployer will raise an Exception
    There are two configs that will be considered:
    'terminate_only': if this config is passed in then this method is the same as terminate(unique_id) (this is also the
    behavior if stop_command is None and not overridden)
    'stop_command': overrides the default stop_command

    :param unique_id:
    :param configs:
    :return:
    """
    # the following is necessay to set the configs for this function as the combination of the
    # default configurations and the parameter with the parameter superceding the defaults but
    # not modifying the defaults
    if configs is None:
      configs = {}
    tmp = self.default_configs.copy()
    tmp.update(configs)
    configs = tmp

    logger.debug("stopping " + unique_id)

    if unique_id in self.processes:
      hostname = self.processes[unique_id].hostname
    else:
      logger.error("Can't stop {0}: process not known".format(unique_id))
      raise DeploymentError("Can't stop {0}: process not known".format(unique_id))

    if configs.get('terminate_only', False):
      self.terminate(unique_id, configs)
    else:
      stop_command = configs.get('stop_command') or self.default_configs.get('stop_command')
      env = configs.get("env", {})
      if stop_command is not None:
        install_path = self.processes[unique_id].install_path
        with get_ssh_client(hostname, username=runtime.get_username(), password=runtime.get_password()) as ssh:
          log_output(exec_with_env(ssh, "cd {0}; {1}".format(install_path, stop_command),
                                         msg="Failed to stop {0}".format(unique_id), env=env))
      else:
        self.terminate(unique_id, configs)

    if 'delay' in configs:
      time.sleep(configs['delay'])
Example #4
0
    def uninstall(self, unique_id, configs=None):
        """uninstall the service.  If the deployer has not started a service with
    `unique_id` this will raise a DeploymentError.  This considers one config:
    'additional_directories': a list of directories to remove in addition to those provided in the constructor plus
     the install path. This will update the directories to remove but does not override it
    :param unique_id:
    :param configs:
    :return:
    """
        # the following is necessay to set the configs for this function as the combination of the
        # default configurations and the parameter with the parameter superceding the defaults but
        # not modifying the defaults
        if configs is None:
            configs = {}
        tmp = self.default_configs.copy()
        tmp.update(configs)
        configs = tmp

        if unique_id in self.processes:
            hostname = self.processes[unique_id].hostname
        else:
            logger.error(
                "Can't uninstall {0}: process not known".format(unique_id))
            raise DeploymentError(
                "Can't uninstall {0}: process not known".format(unique_id))

        install_path = self.processes[unique_id].install_path
        directories_to_remove = self.default_configs.get(
            'directories_to_clean', [])
        directories_to_remove.extend(configs.get('additional_directories', []))
        if install_path not in directories_to_remove:
            directories_to_remove.append(install_path)
        with get_ssh_client(hostname,
                            username=runtime.get_username(),
                            password=runtime.get_password()) as ssh:
            for directory_to_remove in directories_to_remove:
                log_output(
                    better_exec_command(
                        ssh, "rm -rf {0}".format(directory_to_remove),
                        "Failed to remove {0}".format(directory_to_remove)))
Example #5
0
  def install(self, unique_id, configs=None):
    """
    Copies the executable to the remote machine under install path. Inspects the configs for the possible keys
    'hostname': the host to install on
    'install_path': the location on the remote host
    'executable': the executable to copy
    'no_copy': if this config is passed in and true then this method will not copy the executable assuming that it is
    already installed
    'post_install_cmds': an optional list of commands that should be executed on the remote machine after the
     executable has been installed. If no_copy is set to true, then the post install commands will not be run.

    If the unique_id is already installed on a different host, this will perform the cleanup action first.
    If either 'install_path' or 'executable' are provided the new value will become the default.

    :param unique_id:
    :param configs:
    :return:
    """

    # the following is necessay to set the configs for this function as the combination of the
    # default configurations and the parameter with the parameter superceding the defaults but
    # not modifying the defaults
    if configs is None:
      configs = {}
    tmp = self.default_configs.copy()
    tmp.update(configs)
    configs = tmp

    hostname = None
    is_tarfile = False
    is_zipfile = False
    if unique_id in self.processes and  'hostname' in configs:
        self.uninstall(unique_id, configs)
        hostname = configs['hostname']
    elif 'hostname' in configs:
      hostname = configs['hostname']
    elif unique_id not in self.processes:
      # we have not installed this unique_id before and no hostname is provided in the configs so raise an error
      raise DeploymentError("hostname was not provided for unique_id: " + unique_id)

    env = configs.get("env", {})
    install_path = configs.get('install_path') or self.default_configs.get('install_path')
    pid_file = configs.get('pid_file') or self.default_configs.get('pid_file')
    if install_path is None:
      logger.error("install_path was not provided for unique_id: " + unique_id)
      raise DeploymentError("install_path was not provided for unique_id: " + unique_id)
    if not configs.get('no_copy', False):
      with get_ssh_client(hostname, username=runtime.get_username(), password=runtime.get_password()) as ssh:
        log_output(better_exec_command(ssh, "mkdir -p {0}".format(install_path),
                                       "Failed to create path {0}".format(install_path)))
        log_output(better_exec_command(ssh, "chmod 755 {0}".format(install_path),
                                       "Failed to make path {0} writeable".format(install_path)))
        executable = configs.get('executable') or self.default_configs.get('executable')
        if executable is None:
          logger.error("executable was not provided for unique_id: " + unique_id)
          raise DeploymentError("executable was not provided for unique_id: " + unique_id)

        #if the executable is in remote location copy to local machine
        copy_from_remote_location = False;

        if (":" in executable):
          copy_from_remote_location = True

          if ("http" not in executable):
            remote_location_server = executable.split(":")[0]
            remote_file_path = executable.split(":")[1] 
            remote_file_name = os.path.basename(remote_file_path)

            local_temp_file_name = os.path.join(configs.get("tmp_dir","/tmp"),remote_file_name)
          
            if not os.path.exists(local_temp_file_name):
              with get_sftp_client(remote_location_server,username=runtime.get_username(), password=runtime.get_password()) as ftp:
                try:
                  ftp.get(remote_file_path, local_temp_file_name)
                  executable = local_temp_file_name
                except:
                  raise DeploymentError("Unable to load file from remote server " + executable)
          #use urllib for http copy
          else:    
              remote_file_name = executable.split("/")[-1]
              local_temp_file_name = os.path.join(configs.get("tmp_dir","/tmp"),remote_file_name)
              if not os.path.exists(local_temp_file_name):
                try:
                  urllib.urlretrieve (executable, local_temp_file_name)
                except:
                  raise DeploymentError("Unable to load file from remote server " + executable)
              executable = local_temp_file_name    

        try:                     
          exec_name = os.path.basename(executable)
          install_location = os.path.join(install_path, exec_name)
          with get_sftp_client(hostname, username=runtime.get_username(), password=runtime.get_password()) as ftp:
            ftp.put(executable, install_location)
        except:
            raise DeploymentError("Unable to copy executable to install_location:" + install_location)
        finally:
          #Track if its a tarfile or zipfile before deleting it in case the copy to remote location fails
          is_tarfile = tarfile.is_tarfile(executable)
          is_zipfile = zipfile.is_zipfile(executable)
          if (copy_from_remote_location and not configs.get('cache',False)):
            os.remove(executable)       

        # only supports tar and zip (because those modules are provided by Python's standard library)
        if configs.get('extract', False) or self.default_configs.get('extract', False):
          if is_tarfile:
            log_output(better_exec_command(ssh, "tar -xf {0} -C {1}".format(install_location, install_path),
                                           "Failed to extract tarfile {0}".format(exec_name)))
          elif is_zipfile:
            log_output(better_exec_command(ssh, "unzip -o {0} -d {1}".format(install_location, install_path),
                                           "Failed to extract zipfile {0}".format(exec_name)))
          else:
            logger.error(executable + " is not a supported filetype for extracting")
            raise DeploymentError(executable + " is not a supported filetype for extracting")
        post_install_cmds = configs.get('post_install_cmds', False) or self.default_configs.get('post_install_cmds', [])
        for cmd in post_install_cmds:
          relative_cmd = "cd {0}; {1}".format(install_path, cmd)
          log_output(exec_with_env(ssh, relative_cmd,
                                         msg="Failed to execute post install command: {0}".format(relative_cmd), env=env))
    self.processes[unique_id] = Process(unique_id, self.service_name, hostname, install_path)
    self.processes[unique_id].pid_file = pid_file
Example #6
0
    def install(self, unique_id, configs=None):
        """
    Copies the executable to the remote machine under install path. Inspects the configs for the possible keys
    'hostname': the host to install on
    'install_path': the location on the remote host
    'executable': the executable to copy
    'no_copy': if this config is passed in and true then this method will not copy the executable assuming that it is
    already installed
    'post_install_cmds': an optional list of commands that should be executed on the remote machine after the
     executable has been installed. If no_copy is set to true, then the post install commands will not be run.

    If the unique_id is already installed on a different host, this will perform the cleanup action first.
    If either 'install_path' or 'executable' are provided the new value will become the default.

    :param unique_id:
    :param configs:
    :return:
    """

        # the following is necessay to set the configs for this function as the combination of the
        # default configurations and the parameter with the parameter superceding the defaults but
        # not modifying the defaults
        if configs is None:
            configs = {}
        tmp = self.default_configs.copy()
        tmp.update(configs)
        configs = tmp

        hostname = None
        is_tarfile = False
        is_zipfile = False
        if unique_id in self.processes and 'hostname' in configs:
            self.uninstall(unique_id, configs)
            hostname = configs['hostname']
        elif 'hostname' in configs:
            hostname = configs['hostname']
        elif unique_id not in self.processes:
            # we have not installed this unique_id before and no hostname is provided in the configs so raise an error
            raise DeploymentError("hostname was not provided for unique_id: " +
                                  unique_id)

        env = configs.get("env", {})
        install_path = configs.get('install_path') or self.default_configs.get(
            'install_path')
        pid_file = configs.get('pid_file') or self.default_configs.get(
            'pid_file')
        if install_path is None:
            logger.error("install_path was not provided for unique_id: " +
                         unique_id)
            raise DeploymentError(
                "install_path was not provided for unique_id: " + unique_id)
        if not configs.get('no_copy', False):
            with get_ssh_client(hostname,
                                username=runtime.get_username(),
                                password=runtime.get_password()) as ssh:
                log_output(
                    better_exec_command(
                        ssh, "mkdir -p {0}".format(install_path),
                        "Failed to create path {0}".format(install_path)))
                log_output(
                    better_exec_command(
                        ssh, "chmod 755 {0}".format(install_path),
                        "Failed to make path {0} writeable".format(
                            install_path)))
                executable = configs.get(
                    'executable') or self.default_configs.get('executable')
                if executable is None:
                    logger.error(
                        "executable was not provided for unique_id: " +
                        unique_id)
                    raise DeploymentError(
                        "executable was not provided for unique_id: " +
                        unique_id)

                #if the executable is in remote location copy to local machine
                copy_from_remote_location = False

                if (":" in executable):
                    copy_from_remote_location = True

                    if ("http" not in executable):
                        remote_location_server = executable.split(":")[0]
                        remote_file_path = executable.split(":")[1]
                        remote_file_name = os.path.basename(remote_file_path)

                        local_temp_file_name = os.path.join(
                            configs.get("tmp_dir", "/tmp"), remote_file_name)

                        if not os.path.exists(local_temp_file_name):
                            with get_sftp_client(
                                    remote_location_server,
                                    username=runtime.get_username(),
                                    password=runtime.get_password()) as ftp:
                                try:
                                    ftp.get(remote_file_path,
                                            local_temp_file_name)
                                    executable = local_temp_file_name
                                except:
                                    raise DeploymentError(
                                        "Unable to load file from remote server "
                                        + executable)
                    #use urllib for http copy
                    else:
                        remote_file_name = executable.split("/")[-1]
                        local_temp_file_name = os.path.join(
                            configs.get("tmp_dir", "/tmp"), remote_file_name)
                        if not os.path.exists(local_temp_file_name):
                            try:
                                urllib.urlretrieve(executable,
                                                   local_temp_file_name)
                            except:
                                raise DeploymentError(
                                    "Unable to load file from remote server " +
                                    executable)
                        executable = local_temp_file_name

                try:
                    exec_name = os.path.basename(executable)
                    install_location = os.path.join(install_path, exec_name)
                    with get_sftp_client(
                            hostname,
                            username=runtime.get_username(),
                            password=runtime.get_password()) as ftp:
                        ftp.put(executable, install_location)
                except:
                    raise DeploymentError(
                        "Unable to copy executable to install_location:" +
                        install_location)
                finally:
                    #Track if its a tarfile or zipfile before deleting it in case the copy to remote location fails
                    is_tarfile = tarfile.is_tarfile(executable)
                    is_zipfile = zipfile.is_zipfile(executable)
                    if (copy_from_remote_location
                            and not configs.get('cache', False)):
                        os.remove(executable)

                # only supports tar and zip (because those modules are provided by Python's standard library)
                if configs.get('extract', False) or self.default_configs.get(
                        'extract', False):
                    if is_tarfile:
                        log_output(
                            better_exec_command(
                                ssh, "tar -xf {0} -C {1}".format(
                                    install_location, install_path),
                                "Failed to extract tarfile {0}".format(
                                    exec_name)))
                    elif is_zipfile:
                        log_output(
                            better_exec_command(
                                ssh, "unzip -o {0} -d {1}".format(
                                    install_location, install_path),
                                "Failed to extract zipfile {0}".format(
                                    exec_name)))
                    else:
                        logger.error(
                            executable +
                            " is not a supported filetype for extracting")
                        raise DeploymentError(
                            executable +
                            " is not a supported filetype for extracting")
                post_install_cmds = configs.get(
                    'post_install_cmds', False) or self.default_configs.get(
                        'post_install_cmds', [])
                for cmd in post_install_cmds:
                    relative_cmd = "cd {0}; {1}".format(install_path, cmd)
                    log_output(
                        exec_with_env(
                            ssh,
                            relative_cmd,
                            msg="Failed to execute post install command: {0}".
                            format(relative_cmd),
                            env=env))
        self.processes[unique_id] = Process(unique_id, self.service_name,
                                            hostname, install_path)
        self.processes[unique_id].pid_file = pid_file