import os
import sys
from xml.dom import minidom
import pmm_config
import pmmcli_config
import pmm_dump_formatter
import pmm_api_xml_protocols
import subproc
import encodings.idna
from xml.parsers.expat import ExpatError

mswindows = (sys.platform == "win32")

pmm_ras_error_codes = {111: "Dump already exists in repository",
                       112: "Dump objects do not match with restore process owner",
                       113: "Unable to decrypt backup by specified key",
                       116: "Global server security settings prohibits restore from unsigned or modified backups. You can not restore from it, except your service provider explicitly allow it",
                       121: "Permission denied error",
                       122: "FTP password does not match",
                       123: "FTP bad login",
                       124: "FTP host resolve error",
                       125: "FTP connection error",
                       126: "FTP network error",
                       127: "FTP dump file does not exists",
                       151: "Dump does not exist in repository",
                       152: "The file you are trying to upload is not a valid backup file",
                       153: "Dump already exists",
                       154: "Dump could not be extracted because of result path is too long"}

# Unknown error codes should be translated to error code = 199
pmm_ras_unknown_error_code = 199

converter_premature_eof_error_message = "The file you are trying to upload is not a valid backup file. \
Probably, it is a part of multivolume backup created from Plesk 8 or earlier, or it is simply broken."

class RepositoryAccessService:
    def _get_pmmras_command(self):
        cmd = subproc.CmdLine(pmm_config.pmm_ras())
        if pmmcli_config.get().force_debug_log() == 1:
            cmd.arg('--verbose')
            cmd.arg('--debug')
        return cmd
        
class LocalRepositoryAccessService(RepositoryAccessService):
    def __init__(self, dumps_storage_credentials):
        self.__dumps_storage_credentials_formatter = pmm_dump_formatter.DumpsStorageCredentialsFormatter(dumps_storage_credentials)

    def _pmmras_get_dump_list(self, type, guid, id, name):
        pmmras_dump_list = None
        # get pmmras_dump_list as XML string from pmmras
        # call pmm_ras, passing type, guid, id, name
        password = self.__dumps_storage_credentials_formatter.get_password()
        os.environ['DUMP_STORAGE_PASSWD'] = str(password)
        cmd = self._get_pmmras_command()
        cmd.arg('--get-dump-list')
        if type:
            type_arg = '--type=' + type
            cmd.arg(type_arg)
        if guid:
            guid_arg = '--guid=' + guid
            cmd.arg(guid_arg)
        if id:
            id_arg = '--id=' + id
            cmd.arg(id_arg)
        if name:
            idna = name.find('xn--') >= 0
            name_arg = ''
            if idna:
                name_arg = '--name=' + name
            else:
                domain_names_parts = name.split('.')
                idna_name = ''
                for part in domain_names_parts:
                    if idna_name != '':
                        idna_name = idna_name + '.'
                    if part != '':
                        idna_name = idna_name + encodings.idna.ToASCII(part)
                name_arg = '--name=' + idna_name
            cmd.arg(name_arg)
        session_path_arg = '--session-path=' + pmm_config.pmm_logs_directory()
        cmd.arg(session_path_arg)
        errcode = 0
        message = u''
        try:
            proc = cmd.spawn()
            pmmras_dump_list = proc.stdout.encode('utf-8')
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            pmmras_dump_list = x.subprocess.stdout
            message =  u"pmm-ras error (Error code = " + unicode(errcode) + "):"  \
                     + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                     + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"

        dump_list = pmm_api_xml_protocols.DumpList.factory()
        if pmmras_dump_list:
            try:
                dump_list.build(minidom.parseString(pmmras_dump_list).childNodes[0])
            except ExpatError:
                message = message + u"Unable to parse DumpList: ExpatError"
        
        return dump_list, None, message

    def _pmmras_get_dump_status(self, dump_storage, dump_file):
        pmmras_dump_status = None
        # get pmmras_dump_status as XML string from pmmras
        # call pmm_ras, passing secure dump file specification
        password = self.__dumps_storage_credentials_formatter.get_password()
        os.environ['DUMP_STORAGE_PASSWD'] = str(password)
        cmd = self._get_pmmras_command()
        cmd.arg('--get-dump-info')
        dump_storage_arg = '--dump-storage=' + dump_storage
        cmd.arg(dump_storage_arg)
        dump_file_specification_arg = '--dump-file-specification=' + dump_file
        cmd.arg(dump_file_specification_arg)
        cmd.arg('--check-sign')
        session_path_arg = '--session-path=' + pmm_config.pmm_logs_directory()
        cmd.arg(session_path_arg)
        errcode = 0
        message = u''
        try:
            proc = cmd.spawn()
            pmmras_dump_status = proc.stdout.encode('utf-8')
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            if errcode in pmm_ras_error_codes.keys():
                message = pmm_ras_error_codes[errcode]
            else:
                # try get pmmras_dump_status from utility output
                pmmras_dump_status = x.subprocess.stdout
                message =  u"pmm-ras error (Error code = " + unicode(errcode) + "):"  \
                         + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                         + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"
                errcode = pmm_ras_unknown_error_code
        
        dump_result = None
        if pmmras_dump_status:
            dump_result = pmm_api_xml_protocols.Dump.factory()
            try:
                dump_result.build(minidom.parseString(pmmras_dump_status).childNodes[0])
            except ExpatError:
                message = message + u"Unable to parse Dump element: ExpatError"
        
        return dump_result, errcode, message

    def _pmmras_delete_dump(self, dump_storage, dump_file):
        # deletes dump
        # call pmm_ras, passing secure dump file specification
        password = self.__dumps_storage_credentials_formatter.get_password()
        os.environ['DUMP_STORAGE_PASSWD'] = str(password)
        cmd = self._get_pmmras_command()
        cmd.arg('--delete-dump')
        dump_storage_arg = '--dump-storage=' + dump_storage
        cmd.arg(dump_storage_arg)
        dump_file_specification_arg = '--dump-specification=' + dump_file
        cmd.arg(dump_file_specification_arg)
        session_path_arg = '--session-path=' + pmm_config.pmm_logs_directory()
        cmd.arg(session_path_arg)
        errcode = 0
        message = u''
        try:
            proc = cmd.spawn()
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            if errcode in pmm_ras_error_codes.keys():
                message = pmm_ras_error_codes[errcode]
            else:
                message =  u"pmm-ras error (Error code = " + unicode(errcode) + "):"  \
                         + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                         + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"
                errcode = pmm_ras_unknown_error_code
        
        return errcode, message

    def _pmmras_convert_local_dump(self, dump_storage, dump_file):
        cmd = self._get_pmmras_command()
        cmd.arg('--convert-local-dump')
        dump_storage_arg = '--dump-storage=' + dump_storage
        cmd.arg(dump_storage_arg)
        dump_specification_arg = '--dump-specification=' + dump_file
        cmd.arg(dump_specification_arg)
        session_path_arg = '--session-path=' + pmm_config.pmm_logs_directory()
        cmd.arg(session_path_arg)
        errcode = 0
        message = u''
        try:
            proc = cmd.spawn()
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            if errcode in pmm_ras_error_codes.keys():
                message = pmm_ras_error_codes[errcode]
            else:
                message =  u"pmm-ras error (Error code = " + unicode(errcode) + "):"  \
                         + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                         + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"
                errcode = pmm_ras_unknown_error_code
        
        return errcode, message
        

    # the 'getDumpList' method returns XML-element-class instances autogenerated from 'pmm_api_xml_protocols.xsd'
    def getDumpList(self,object_specification):
        dump_list, errcode, message = self._pmmras_get_dump_list(object_specification.get_type(),object_specification.get_guid(),object_specification.get_id(),object_specification.get_name())
        return dump_list, errcode, message

    # the 'getDumpStatus' method returns XML-element-class instances autogenerated from 'pmm_api_xml_protocols.xsd'
    def getDumpStatus(self,dump_specification):
        dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(dump_specification)
        dump_file = dump_specification_formatter.get_name_of_xml_file()
        dump_storage = dump_specification_formatter.get_dumps_storage_credentials_formatter().getDumpStorage()
        dump_status, errcode, message = self._pmmras_get_dump_status(dump_storage, dump_file)
        return dump_status, errcode, message

    # the 'deleteDump' method returns error code and error message 
    def deleteDump(self,dump_specification):
        dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(dump_specification)
        dump_file = dump_specification_formatter.get_name_of_xml_file()
        dump_storage = dump_specification_formatter.get_dumps_storage_credentials_formatter().getDumpStorage()
        errcode, message = self._pmmras_delete_dump(dump_storage, dump_file)
        return errcode, message
        
    def convert_local_dump(self,dump_specification):
        dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(dump_specification)
        dump_storage = dump_specification_formatter.get_dumps_storage_credentials_formatter().getDumpStorage()
        dump_file = dump_specification_formatter.get_name_of_xml_file()
        errcode, message = self._pmmras_convert_local_dump(dump_storage, dump_file)
        return errcode, message
        

class FtpRepositoryAccessService(RepositoryAccessService):
    def __init__(self, dumps_storage_credentials):
        self.__dumps_storage_credentials_formatter = pmm_dump_formatter.DumpsStorageCredentialsFormatter(dumps_storage_credentials)

    # for the case of migration functionality to PMM RAS
    def _pmmras_export_dump_as_file(self, dump_file_name, dump_storage_credentials_formatter, password):
        # dump_storage_credentials_formatter is a target DumpsStorageCredentialsFormatter
        if not mswindows:
            raise Exception("pmm-ras --export_dump_as_file is supported for Windows only!")
        
        os.environ['DUMP_STORAGE_PASSWD'] = str(password)
        cmd = self._get_pmmras_command()
        cmd.arg('--export-dump-as-file')
        
        if dump_storage_credentials_formatter.get_use_passive_ftp_mode() == 'true':
            cmd.arg('--use-ftp-passive-mode')
        
        # dump specification is a filename relative for local dumps storage
        dump_specification_arg = '--dump-specification=' + dump_file_name
        cmd.arg(dump_specification_arg)
        dump_file_specification_arg = '--dump-file-specification=' + dump_storage_credentials_formatter.getFileDumpStorage()
        cmd.arg(dump_file_specification_arg)
        session_path_arg = '--session-path=' + pmm_config.pmm_logs_directory()
        cmd.arg(session_path_arg)
        
        errcode = 0
        message = u''
        filename = None
        try:
            proc = cmd.spawn()
            filename = proc.stdout.strip()
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            if errcode in pmm_ras_error_codes.keys():
                if errcode == 111:
                    filename = x.subprocess.stdout.strip()
                message = pmm_ras_error_codes[errcode]
            else:
                message =  u"pmm-ras error (Error code = " + unicode(errcode) + "):"  \
                         + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                         + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"
                errcode = pmm_ras_unknown_error_code
        
        return errcode, message, filename

    # download to local repository is supported only. so far pmm-ras does not need to know repository password
    def _pmmras_import_file_as_dump(self, dump_file, dumps_storage, guid,type, ignore_content_list_sign):
        # call pmm_ras, passing secure_source_dump_file_specification,source_password,secure_dump_storage
        password = self.__dumps_storage_credentials_formatter.get_password()
        os.environ['DUMP_STORAGE_PASSWD'] = str(password)
        cmd = self._get_pmmras_command()
        cmd.arg('--import-file-as-dump')
        
        if self.__dumps_storage_credentials_formatter.get_use_passive_ftp_mode() == 'true':
            cmd.arg('--use-ftp-passive-mode')
        
        
        dump_file_specification_arg = '--dump-file-specification=' + dump_file
        cmd.arg(dump_file_specification_arg)
        dump_storage_arg = '--dump-storage=' + dumps_storage
        cmd.arg(dump_storage_arg)
        guid_arg = '--guid=' + guid
        cmd.arg(guid_arg)
        type_arg = '--type=' + type
        cmd.arg(type_arg)
        session_path_arg = '--session-path=' + pmm_config.pmm_logs_directory()
        cmd.arg(session_path_arg)
        cmd.arg('--check-sign')
        if ignore_content_list_sign == 'true':
            cmd.arg('--force')
        errcode = 0
        message = u''
        filename = None
        try:
            proc = cmd.spawn()
            filenames = proc.stdout.splitlines()
            if len(filenames) > 1:
                filename = filenames[-1].strip()
            else:
                filename = filenames[0].strip()
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            if errcode in pmm_ras_error_codes.keys():
                if errcode == 111 or errcode == 116:
                    filename = x.subprocess.stdout.strip()
                elif errcode == 154:
                    pass
                message = pmm_ras_error_codes[errcode]
            else:
                message =  u"pmm-ras error (Error code = " + unicode(errcode) + "):"  \
                         + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                         + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"
                errcode = pmm_ras_unknown_error_code
        
        return errcode, message, filename
    

    def _pmmras_export_file_as_file(self, destination_dump, destination_dumps_storage_password):
        source_dump = self.__dumps_storage_credentials_formatter.getFileDumpStorage()
        source__dumps_storage_password = self.__dumps_storage_credentials_formatter.get_password()
        os.environ['DUMP_STORAGE_PASSWD_SRC'] = str(source__dumps_storage_password)
        os.environ['DUMP_STORAGE_PASSWD_DST'] = str(destination_dumps_storage_password)
        cmd = self._get_pmmras_command()
        cmd.arg('--export-file-as-file')
        
        if self.__dumps_storage_credentials_formatter.get_use_passive_ftp_mode() == 'true':
            cmd.arg('--use-ftp-passive-mode')
        
        file_from_arg = '--file-from=' + source_dump
        cmd.arg(file_from_arg)
        file_to_arg = '--file-to=' + destination_dump
        cmd.arg(file_to_arg)
        session_path_arg = '--session-path=' + pmm_config.pmm_logs_directory()
        cmd.arg(session_path_arg)
        errcode = 0
        message = u''
        try:
            proc = cmd.spawn()
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            if errcode in pmm_ras_error_codes.keys():
                message = pmm_ras_error_codes[errcode]
            else:
                message =  u"pmm-ras error (Error code = " + unicode(errcode) + "):"  \
                         + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                         + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"
                errcode = pmm_ras_unknown_error_code
        
        return errcode, message

    def _pmmras_get_ftp_dump_list(self):
        password = self.__dumps_storage_credentials_formatter.get_password()
        secure_dumps_storage = self.__dumps_storage_credentials_formatter.getDumpStorage()
        os.environ['DUMP_STORAGE_PASSWD'] = str(password)
        pmmras_dump_list = None
        cmd = self._get_pmmras_command()
        cmd.arg('--get-ftp-dump-list')
        
        if self.__dumps_storage_credentials_formatter.get_use_passive_ftp_mode() == 'true':
            cmd.arg('--use-ftp-passive-mode')
        
        cmd.arg('--no-default-mask')
        
        dump_storage_arg = '--dump-storage=' + secure_dumps_storage
        cmd.arg(dump_storage_arg)
        session_path_arg = '--session-path=' + pmm_config.pmm_logs_directory()
        cmd.arg(session_path_arg)
        errcode = 0
        message = u''
        try:
            proc = cmd.spawn()
            pmmras_dump_list = proc.stdout.encode('utf-8')
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            if errcode in pmm_ras_error_codes.keys():
                message = pmm_ras_error_codes[errcode]
            else:
                # try get pmmras_dump_list from utility output
                pmmras_dump_list = x.subprocess.stdout
                message =  u"pmm-ras error (Error code = " + unicode(errcode) + "):"  \
                         + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                         + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"
                errcode = pmm_ras_unknown_error_code
        
        dump_list = pmm_api_xml_protocols.DumpList.factory()
        if pmmras_dump_list:
            try:
                dump_list.build(minidom.parseString(pmmras_dump_list).childNodes[0])
            except ExpatError:
                message = message + u"\nUnable to parse DumpList: ExpatError"
        
        return dump_list, None, message

    def _pmmras_get_dump_status(self,dump_storage,dump_file):
        # get pmmras_dump_status as XML string from pmmras
        # call pmm_ras, passing secure dump file specification
        password = self.__dumps_storage_credentials_formatter.get_password()
        os.environ['DUMP_STORAGE_PASSWD'] = str(password)
        pmmras_dump_status = None
        cmd = self._get_pmmras_command()
        cmd.arg('--get-ftp-dump-info')
        
        if self.__dumps_storage_credentials_formatter.get_use_passive_ftp_mode() == 'true':
            cmd.arg('--use-ftp-passive-mode')
        
        dump_storage_arg = '--dump-storage=' + dump_storage
        cmd.arg(dump_storage_arg)
        dump_file_specification_arg = '--dump-file-specification=' + dump_file
        cmd.arg(dump_file_specification_arg)
        session_path_arg = '--session-path=' + pmm_config.pmm_logs_directory()
        cmd.arg(session_path_arg)
        errcode = 0
        message = u''
        try:
            proc = cmd.spawn()
            pmmras_dump_status = proc.stdout.encode('utf-8')
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            if errcode in pmm_ras_error_codes.keys():
                message = pmm_ras_error_codes[errcode]
            else:
                # try get pmmras_dump_status from utility output
                pmmras_dump_status = x.subprocess.stdout
                message =  u"pmm-ras error (Error code = " + unicode(errcode) + "):"  \
                         + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                         + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"
                errcode = pmm_ras_unknown_error_code
        
        dump_result = None
        if pmmras_dump_status:
            dump_result = pmm_api_xml_protocols.Dump.factory()
            try:
                dump_result.build(minidom.parseString(pmmras_dump_status).childNodes[0])
            except ExpatError:
                message = message + u"\nUnable to parse Dump element: ExpatError"
        
        return dump_result, errcode, message

    def _pmmras_delete_dump(self, dump_storage, dump_file):
        # deletes dump
        password = self.__dumps_storage_credentials_formatter.get_password()
        os.environ['DUMP_STORAGE_PASSWD'] = str(password)
        cmd = self._get_pmmras_command()
        cmd.arg('--delete-exported-dump')
        
        if self.__dumps_storage_credentials_formatter.get_use_passive_ftp_mode() == 'true':
            cmd.arg('--use-ftp-passive-mode')
        
        dump_storage_arg = '--dump-storage=' + dump_storage
        cmd.arg(dump_storage_arg)
        dump_file_specification_arg = '--dump-file-specification=' + dump_file
        cmd.arg(dump_file_specification_arg)
        session_path_arg = '--session-path=' + pmm_config.pmm_logs_directory()
        cmd.arg(session_path_arg)
        errcode = 0
        message = u''
        try:
            proc = cmd.spawn()
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            if errcode in pmm_ras_error_codes.keys():
                message = pmm_ras_error_codes[errcode]
            else:
                message =  u"pmm-ras error (Error code = " + unicode(errcode) + "):"  \
                         + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                         + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"
                errcode = pmm_ras_unknown_error_code
        
        return errcode, message

    # the 'import_file_as_dump' method returns errcode, message
    # pmm-ras supports only 'local' storage-type in destination_dump_specification
    def import_file_as_dump(self,source_dump_specification,destination_dump_specification,guid,type):
        source_dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(source_dump_specification)
        destination_dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(destination_dump_specification)
        dump_file = source_dump_specification_formatter.get_destination_file()
        dumps_storage = destination_dump_specification_formatter.get_dumps_storage_credentials_formatter().getDumpStorage()
        ignore_backup_sign = destination_dump_specification.get_dumps_storage_credentials_formatter().get_ignore_backup_sign()
        errcode, message, filename = self._pmmras_import_file_as_dump(dump_file, dumps_storage, guid,
                                                                      type, ignore_backup_sign)
        return errcode, message, filename

    # the 'export_dump_as_file' method returns errcode, message
    def export_dump_as_file(self,source_dump_specification,destination_dump_specification):
        source_dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(source_dump_specification)
        dump_file_name = source_dump_specification_formatter.get_name_of_xml_file()
        destination_dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(destination_dump_specification)
        dumps_storage_credentials_formatter = destination_dump_specification_formatter.get_dumps_storage_credentials_formatter()
        destination_dumps_storage_password = dumps_storage_credentials_formatter.get_password()
        errcode, message, filename = self._pmmras_export_dump_as_file(dump_file_name,dumps_storage_credentials_formatter,destination_dumps_storage_password)
        return errcode, message, filename

    # the 'export_file_as_file' method returns errcode, message
    def export_file_as_file(self,destination_dump_specification):
        destination_dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(destination_dump_specification)
        destination_dump = destination_dump_specification_formatter.get_destination_file()
        destination_dumps_storage_password = destination_dump_specification_formatter.get_dumps_storage_credentials_formatter().get_password()
        errcode, message = self._pmmras_export_file_as_file(destination_dump, destination_dumps_storage_password)
        return errcode, message

    # the 'getDumpList' method returns XML-element-class instances autogenerated from 'pmm_api_xml_protocols.xsd'
    def getDumpList(self,object_specification):
        # object specification is ignored for ftp dumps, pmm-ras shows all dump files
        dump_list, errcode, message = self._pmmras_get_ftp_dump_list()
        return dump_list, errcode, message

    # the 'getDumpStatus' method returns XML-element-class instances autogenerated from 'pmm_api_xml_protocols.xsd'
    def getDumpStatus(self,dump_specification):
        dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(dump_specification)
        dump_storage_credentials_formatter = dump_specification_formatter.get_dumps_storage_credentials_formatter()
        dump_storage = dump_storage_credentials_formatter.getDumpStorage()
        dump_file = dump_storage_credentials_formatter.get_file_name()
        dump_status, errcode, message = self._pmmras_get_dump_status(dump_storage,dump_file)
        return dump_status, errcode, message

    # the 'deleteDump' method returns error code and error message 
    def deleteDump(self,dump_specification):
        dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(dump_specification)
        dump_storage_credentials_formatter = dump_specification_formatter.get_dumps_storage_credentials_formatter()
        dump_file = dump_storage_credentials_formatter.get_file_name()
        dump_storage = dump_storage_credentials_formatter.getDumpStorage()
        errcode, message = self._pmmras_delete_dump(dump_storage, dump_file)
        return errcode, message

class Pre9BackupConverterAccessService:
    def __init__(self, dumps_storage_credentials):
        self.__dumps_storage_credentials_formatter = pmm_dump_formatter.DumpsStorageCredentialsFormatter(dumps_storage_credentials)

    def _get_filename(self, output):
        filenames = output.split("Created dump:")
        if len(filenames) > 1:
            return filenames[-1].strip()
        else:
            return u''

    def _import_file_as_dump(self, dump_file, dumps_storage):
        cmd = subproc.CmdLine(pmm_config.pre9backup_converter())
        if mswindows:
            source_arg = '--source=' + dump_file
            cmd.arg(source_arg)
            
            destination_arg = '--destination=' + dumps_storage
            cmd.arg(destination_arg)
        else:
            cmd.arg('convert')
            
            directory_arg = '--directory=' + dumps_storage
            cmd.arg(directory_arg)
            
            dump_file_arg = dump_file
            cmd.arg(dump_file_arg)
        
        errcode = 0
        message = u''
        filename = u''
        try:
            proc = cmd.spawn()
            filename = self._get_filename(proc.stdout)
            if filename == u'':
                errcode = 1
                message = u"pre9-backup-convert error: empty result filename returned from utility"
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            if not mswindows and errcode == 1 and x.subprocess.stderr.startswith("Runtime error: Premature EOF without final boundary"):
                errcode = 152
                message = converter_premature_eof_error_message
            else:
                message =  u"pre9-backup-convert error (Error code = " + unicode(errcode) + "):"  \
                         + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                         + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"
        
        return errcode, message, filename

    # the 'import_file_as_dump' method returns errcode, message
    # pmm-ras supports only 'local' storage-type in destination_dump_specification
    def import_file_as_dump(self,source_dump_specification,destination_dump_specification):
        source_dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(source_dump_specification)
        destination_dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(destination_dump_specification)
        dump_file = source_dump_specification_formatter.get_destination_file()
        dumps_storage = destination_dump_specification_formatter.get_dumps_storage_credentials_formatter().getDumpStorage()
        errcode, message, filename = self._import_file_as_dump(dump_file,dumps_storage)
        return errcode, message, filename


class Pre8BackupConverter:
    def __init__(self):
        if mswindows:
            raise Exception("Pre8BackupConverter is only used for Unix!")

    def convert(self, source_dump_specification_formatter):
        source_dump_specification_object = source_dump_specification_formatter.buildXml()
        source_dumps_storage_credentials = source_dump_specification_object.get_dumps_storage_credentials()
        source_dumps_storage_credentials.set_file_name( source_dumps_storage_credentials.get_file_name() + '-psa8')
        destination_dump_specification_formatter = pmm_dump_formatter.DumpSpecificationFormatter(source_dump_specification_object)
        
        cmd = subproc.CmdLine(pmm_config.backup_convert())
        cmd.arg('convert')
        
        cmd.arg('-o')
        cmd.arg(destination_dump_specification_formatter.get_destination_file())
        cmd.arg(source_dump_specification_formatter.get_destination_file())
        
        errcode = 0
        message = u''
        filename = u''
        try:
            proc = cmd.spawn()
            if not os.path.isfile(destination_dump_specification_formatter.get_destination_file()):
                errcode = 1
                message = u"pre8-backup-convert error: dump '" + destination_dump_specification_formatter.get_destination_file() + "' is not created"
        except subproc.NonzeroExitException, x:
            errcode = x.exitcode
            if not mswindows and errcode == 1 and x.subprocess.stderr.startswith("Runtime error: Premature EOF without final boundary"):
                errcode = 152
                message = converter_premature_eof_error_message
            else:
                message =  u"pre8-backup-convert error (Error code = " + unicode(errcode) + "):"  \
                         + u"\n== STDOUT ====================\n" + x.subprocess.stdout + u"\n==============================\n" \
                         + u"== STDERR ====================\n" + x.subprocess.stderr + u"\n==============================\n"
        
        return errcode, message, destination_dump_specification_formatter

