示例#1
0
class IsmCopyProfile():

    CRYPTPASS = "******"
    # Receiving args
    module = AnsibleModule(argument_spec=dict(
        config=dict(type="str", required=True),
        ism_source_profile_name=dict(type="str", required=True),
        ism_profile_name=dict(typer="str", required=True),
        ism_profile_data=dict(type="dict", required=False)))

    def __init__(self):
        self.__present()

    def __present(self):
        # Instance of common class
        self.common = IsmCommon(self.module)

        # check for blank("") and None
        self.common.required_param_check(self.module.params["config"],
                                         "config")
        self.common.required_param_check(
            self.module.params["ism_source_profile_name"],
            "ism_source_profile_name")
        self.common.required_param_check(
            self.module.params["ism_profile_name"], "ism_profile_name")

        try:

            # Pre-process
            self.common.preProcess(self.module.params,
                                   NodeCheck=False,
                                   noHost=True)
            self.module.params['config'] = self.common.covert_unicode(
                self.module.params['config'])
            self.module.params[
                'ism_source_profile_name'] = self.common.covert_unicode(
                    self.module.params['ism_source_profile_name'])
            self.module.params[
                'ism_profile_name'] = self.common.covert_unicode(
                    self.module.params['ism_profile_name'])

            if self.module.params['ism_profile_data']:
                self.common.covertUnicodeHashDict(
                    self.module.params['ism_profile_data'])

            # Check profile
            check_profile_result = \
                self.__checkProfile(self.module.params['ism_source_profile_name'],
                                    self.module.params['ism_profile_name'])

            # Get profile
            get_profile_result = self.__getProfile(check_profile_result)

            # Copy profile
            self.__copyProfile(get_profile_result)

            self.module.exit_json(changed=True, ism_copy_profile="Success")

        except Exception as e:
            self.module.log(str(e))
            self.module.log(traceback.format_exc())
            self.module.fail_json(msg=str(e))
        finally:
            self.common.ismLogout()

    def __checkProfile(self, source, dest):
        profile_id = None

        # source and dest profile name are same
        if source == dest:
            msg = "ism_source_profile_name and ism_profile_name have duplicate values: {0}".\
                  format(source)
            self.module.log(msg)
            self.module.fail_json(msg=msg)

        # Get REST URL
        rest_url = self.common.getRestUrl(self.common.PROFILE_LIST_REST_URL)

        # REST API execution
        json_data = self.common.execRest(rest_url, self.common.GET,
                                         self.common.RESPONSE_CODE_200)

        for profile in json_data['IsmBody']['ProfileList']:

            if profile['ProfileName'] == dest:
                # already copied
                self.module.exit_json(changed=False,
                                      ism_copy_profile="Success")

            elif profile['ProfileName'] == source:
                profile_id = profile['ProfileId']

        # Profile not found
        if not profile_id:
            msg = "profile not found: {0}".format(source)
            self.module.log(msg)
            self.module.fail_json(msg=msg)

        return profile_id

    def __getProfile(self, profile_id):
        # Get REST URL
        rest_url = self.common.getRestUrl(
            self.common.PROFILE_LIST_REST_URL,
            "/" + profile_id + "?passwordkey=" + self.CRYPTPASS)
        # REST API execution
        json_data = self.common.execRest(rest_url, self.common.GET,
                                         self.common.RESPONSE_CODE_200)

        source_info = json_data['IsmBody']

        # delete create profile REST-API not supported keys
        not_supported_keys = [
            'ProfileId', 'PathName', 'AssignedNodeId', 'Status',
            'InternalStatus', 'VerifyStatus', 'HistoryList', 'VerifyList',
            'TimeStampInfo'
        ]

        for not_supported_key in not_supported_keys:
            if not_supported_key in source_info:
                del source_info[not_supported_key]

        # add information
        if self.module.params['ism_profile_data']:
            dict_data = source_info['ProfileData']
            dict_set = dict(self.module.params['ism_profile_data'])
            source_info['ProfileData'] = self.common.mergeDicts(
                dict_data, dict_set)

        source_info['ProfileName'] = self.module.params['ism_profile_name']
        source_info['OneTimePasswordKey'] = self.CRYPTPASS

        all_data = {"IsmBody": source_info}
        return all_data

    def __copyProfile(self, body):
        # Get REST URL
        rest_url = self.common.getRestUrl(self.common.PROFILE_LIST_REST_URL)

        # REST API execution
        param_str = "\'" + self.common.singleEscape(json.dumps(body)) + "\'"
        self.common.execRest(rest_url, self.common.POST,
                             self.common.RESPONSE_CODE_201, param_str)
示例#2
0
class IsmBackup():
    PEXPECT_VERSION = "4.7.0"
    PEXPECT_VERSION_MSG = 'The pexpect >= 4.7.0 python module is required'
    PXSSH_DEBUG = False
    PXSSH_CONNECT_TIMEOUT = 60
    PXSSH_MSG_HEADER = "SSH connection error: {0}"
    PXSSH_OPTION = {
        "ConnectTimeout": PXSSH_CONNECT_TIMEOUT,
        "StrictHostKeyChecking": "no",
        "UserKnownHostsFile": "/dev/null"
    }

    PORT_SSH = 22

    FTP_CONNECT_TIMEOUT = 60
    FTP_MSG_CONNECT_HEADER = "FTP connection error: {0}"
    FTP_MSG_OPERATION_HEADER = "FTP operation error: {0}"

    RE_CONNECT_ERROR = re.compile(r'^could not set shell prompt')
    RE_START_BACKUP = re.compile(r'^Start backup process\? \[y/n\]: ',
                                 re.MULTILINE)
    RE_ERROR = re.compile(r'^(ERROR:\d+:.+)$', re.MULTILINE)
    RE_OUTPUT_FILE = re.compile(r'^Output file: (ism.+\.gz)', re.MULTILINE)

    FTP_DIR = "/Administrator/ftp/"

    module = AnsibleModule(argument_spec=dict(
        config=dict(type="str", required=True),
        hostname=dict(type="str", required=True),
        dest_dir=dict(type="str", required=True),
        timeout=dict(type="int", default=0, required=False)))

    def __init__(self):
        self.__present()

    def __present(self):
        self.common = IsmCommon(self.module)

        # check for blank("") and None
        self.common.required_param_check(self.module.params["config"],
                                         "config")
        self.common.required_param_check(self.module.params["hostname"],
                                         "hostname")
        self.common.required_param_check(self.module.params["dest_dir"],
                                         "dest_dir")

        # check pexpect installed and its version
        if not HAS_PEXPECT:
            self.module.fail_json(msg=self.PEXPECT_VERSION_MSG)
        if not self.common.checkLibraryVersion(pexpect.__version__, "4.7.0"):
            self.module.fail_json(msg=self.PEXPECT_VERSION_MSG)

        try:
            self.common.preProcess(
                self.module.params,
                usableEssential=True,
                NodeCheck=False,
                paramListNotBlank=["timeout"
                                   ],  # don't convert None to blank("")
                doIsmLogin=False)
            # convert to unicode
            self.module.params['config'] = self.common.covert_unicode(
                self.module.params['config'])
            self.module.params['hostname'] = self.common.covert_unicode(
                self.module.params['hostname'])
            self.module.params['dest_dir'] = self.common.covert_unicode(
                self.module.params['dest_dir'])

            self.dest_dir = self.module.params["dest_dir"]

            self.timeout = self.module.params["timeout"]
            if not (self.timeout) or self.timeout <= 0:  # less than or equal 0
                self.timeout = None  # no timeout

            config_json = self.common.ism_config_json

            self.ism_ip = config_json["ip"]
            self.ism_user_name = config_json["credentials"]["userName"]
            self.ism_password = config_json["credentials"]["password"]

            self.ism_password = self.common.decryptIsmPassword(
                self.ism_password, self.ism_ip)

            filename = self.__backup()
            dest_file = os.path.join(self.dest_dir, filename)

            self.__download(dest_file, filename)

            self.module.exit_json(changed=True, ism_backup_file=dest_file)

        except Exception as e:
            self.module.log(traceback.format_exc())
            self.module.fail_json(msg=str(e))

    def __backup(self):
        ssh = None

        try:
            ssh = pxssh.pxssh(options=self.PXSSH_OPTION)

            if self.PXSSH_DEBUG:
                # pxssh stdout for debug
                ssh.logfile = sys.stdout

            try:
                ssh.login(self.ism_ip,
                          username=self.ism_user_name,
                          password=self.ism_password,
                          login_timeout=self.PXSSH_CONNECT_TIMEOUT,
                          port=self.PORT_SSH)
            except pexpect.ExceptionPexpect as e:
                msg = str(e)
                if self.RE_CONNECT_ERROR.match(msg):
                    # connection error
                    msg = self.PXSSH_MSG_HEADER.format(
                        "Failed to connect host")
                else:
                    msg = self.PXSSH_MSG_HEADER.format(msg)
                self.module.log(msg)
                self.module.log(traceback.format_exc())
                self.module.fail_json(msg=msg)

            ssh.sendline("ismadm system backup")

            # waiting backup size estimation
            index = ssh.expect(
                [self.RE_START_BACKUP, self.RE_ERROR, ssh.PROMPT],
                timeout=self.timeout)

            if index == 1:
                # error message
                msg = ssh.match.group(1).rstrip()
                self.module.log(msg)
                self.module.fail_json(msg=msg)
            elif index == 2:
                # not ISM server
                msg = "backup failed: not ISM server"
                self.module.log(msg)
                self.module.log("output={0}".format(ssh.before))
                self.module.fail_json(msg=msg)

            # start backup
            ssh.sendline("y")

            # waiting backup complete
            ssh.expect(ssh.PROMPT, timeout=self.timeout)

            output = ssh.before

            match = self.RE_ERROR.search(output)
            if match:
                # error message
                msg = match.group(1).rstrip()
                self.module.log(msg)
                self.module.fail_json(msg=msg)

            match = self.RE_OUTPUT_FILE.search(output)
            if not match:
                # Output file not found
                msg = "missing backup file info"
                self.module.log(msg)
                self.module.log("output={0}".format(output))
                self.module.fail_json(msg=msg)

            filename = match.group(1)

            return filename

        except pexpect.TIMEOUT:
            msg = "waiting for backup timeout: {0}s".format(self.timeout)
            self.module.log(msg)
            self.module.log(traceback.format_exc())
            self.module.fail_json(msg=msg)
        finally:
            # close
            if ssh:
                try:
                    ssh.close()
                except Exception:
                    # ignore error
                    self.module.log(traceback.format_exc())

    def __download(self, dest_file, ftp_file):
        ftp = None
        file_deleted = False
        try:
            try:
                ftp = FTP(self.ism_ip, self.ism_user_name, self.ism_password,
                          self.FTP_CONNECT_TIMEOUT)
            except Exception as e:
                msg = self.FTP_MSG_CONNECT_HEADER.format(e)
                self.module.log(msg)
                self.module.log(traceback.format_exc())
                self.module.fail_json(msg=msg)

            with open(dest_file, 'wb') as f:
                try:
                    ftp.retrbinary('RETR ' + self.FTP_DIR + ftp_file, f.write)
                    ftp.delete(self.FTP_DIR + ftp_file)
                    file_deleted = True
                except Exception as e:
                    msg = self.FTP_MSG_OPERATION_HEADER.format(e)
                    self.module.log(msg)
                    self.module.log(traceback.format_exc())
                    self.module.fail_json(msg=msg)

        except Exception as e:
            self.module.log(traceback.format_exc())
            self.module.fail_json(msg=str(e))
        finally:
            # FTP logout
            if ftp:
                try:
                    if not file_deleted:
                        # delete file
                        ftp.delete(self.FTP_DIR + ftp_file)
                    ftp.quit()
                except Exception:
                    # ignore error
                    self.module.log(traceback.format_exc())