Submit
Path:
~
/
/
opt
/
psa
/
admin
/
plib
/
modules
/
site-import
/
backend
/
lib
/
python
/
parallels
/
plesk
/
source
/
plesk
/
pmm_agent
/
File Content:
unix.py
import json import os import posixpath import textwrap import parallels from parallels.core import MigrationError from parallels.core.logging import get_logger from parallels.core.runners.base import BaseRunner from parallels.core.runners.entities import ExecutionOptions from parallels.core.utils import migrator_utils from parallels.core.utils.common import is_empty_list, safe_format from parallels.core.utils.json_utils import encode_json from parallels.core.utils.common.sql_utils import format_sql_results_for_log from parallels.core.utils.common.string_utils import safe_utf8_decode from parallels.core.utils.pmm.agent import DumpAll, DumpSelected from parallels.core.utils.pmm.utils import convert_sql_query_for_perl from parallels.plesk.source.legacy.pmm_agent import UnixPmmMigrationAgent from parallels.plesk.source.plesk import messages from parallels.plesk.source.plesk.capability_dump.model.factory import create_plesk_capability_model from parallels.plesk.source.plesk.capability_dump.xml_converter import CapabilityXMLConverter from parallels.plesk.source.plesk.pmm_agent.hosting_description import HostingDescriptionAgent from parallels.plesk.source.plesk.shallow_dump.model.factory import create_plesk_shallow_model from parallels.plesk.source.plesk.shallow_dump.xml_converter import ShallowXMLConverter logger = get_logger(__name__) class PleskXPmmMigrationAgent(UnixPmmMigrationAgent): """Migration agent for Plesk panel and Expand. 'self.max_plesk_version' specifies maximum version of source Plesk panel that is supported by the agent. """ def __init__(self, global_context, server, migrator_pmm_dir, settings): source_plesk_version = server.plesk_version if source_plesk_version < (17, 0): self.max_plesk_version = {'MAJOR': 12, 'MINOR': 5, 'PATCH': 30} else: self.max_plesk_version = {'MAJOR': 17, 'MINOR': 0, 'PATCH': 17} self.remote_log_filename = 'dump.log' super(PleskXPmmMigrationAgent, self).__init__(global_context, server, migrator_pmm_dir, settings) @property def common_pmm_dir(self): source_plesk_version = self._source_server.plesk_version if source_plesk_version < (17, 0): shared_dir = 'plesk_12_5_pmm_shared' else: shared_dir = 'plesk_17_0_pmm_shared' return migrator_utils.get_package_extras_file_path(parallels.plesk.source.legacy, shared_dir) def execute_sql(self, query, query_args=None, log_output=True): """Execute SQL query on panel database Returns list of rows, each row is a dictionary. :type query: str|unicode :type query_args: list|dict :rtype: list[dict] :type log_output: bool """ with logger.debug_level_context(messages.EXECUTE_SQL_QUERY): logger.fdebug(messages.EXECUTE_SQL_QUERY_QUERY, query=query) command = u"""cd {path}; {perl} ExecutePleskSQL.pl""" query_template, query_template_params = convert_sql_query_for_perl(query, query_args) stdin_content = encode_json(dict( query=query_template, query_args=query_template_params )) with self._source_server.runner() as runner: assert isinstance(runner, BaseRunner) arguments = { 'perl': self._perl_bin, 'path': self.agent_dir, } execution_result = runner.execute_command( command, arguments, ExecutionOptions( stdin_content=stdin_content, log_output=False, ignore_exit_code=True ) ) try: result = json.loads(safe_utf8_decode(execution_result.stdout)) except Exception: logger.exception() raise MigrationError( safe_format( messages.FAILED_TO_EXECUTE_SQL_QUERY_PARSE_JSON, exit_code=execution_result.exit_code, stdout=execution_result.stdout, stderr=execution_result.stderr, query=query ) ) if result.get('status') != 'ok': raise MigrationError(safe_format( messages.FAILED_TO_EXECUTE_SQL_QUERY, reason=result['message'] )) else: rowset = self._convert_rowset_int_values_to_str(result['rowset']) logger.fdebug(messages.EXECUTE_SQL_QUERY_RESULTS, result=format_sql_results_for_log(rowset)) return rowset def _deploy(self): agent_dir = super(PleskXPmmMigrationAgent, self)._deploy() self._patch_template(agent_dir, self.max_plesk_version) return agent_dir def _run(self, local_data_filename, local_log_filename, selection=DumpAll()): """Run migration agent on a source panel and download the results. Execute the agent which puts results into XML dump file. Download dump XML file and log file to specified locations: - dump_xml_filename - local filename to put dump XML to - dump_log_filename - local filename to put dump log to Raise MigrationError in case of any failure. """ logger.info(messages.LOG_CREATE_SOURCE_PANEL_MIGRATION_DUMP) self.local_log_filename = local_log_filename source_plesk_version = self._source_server.plesk_version if source_plesk_version < (17, 0): logger.debug(messages.LOG_RUN_MIGRATION_AGENT) self._make_dump(selection) self._download_dump(local_data_filename) else: HostingDescriptionAgent(self).create_dump(local_data_filename, selection) def _run_shallow(self, local_data_filename): logger.info(messages.LOG_CREATE_SOURCE_PANEL_MIGRATION_SHALLOW_DUMP) shallow_model = create_plesk_shallow_model( self, self._source_server.plesk_version ) ShallowXMLConverter(shallow_model).write_xml(local_data_filename) def _run_capability(self, local_data_filename, local_log_filename, selection=DumpAll()): logger.info(messages.LOG_CREATE_SOURCE_PANEL_MIGRATION_CAPABILITY_DUMP) self.local_log_filename = local_log_filename source_plesk_version = self._source_server.plesk_version if source_plesk_version < (12, 0): logger.debug(messages.LOG_RUN_MIGRATION_AGENT) self._make_capability_dump(selection) self._download_agent_file('dump.xml', local_data_filename) else: capability_model = create_plesk_capability_model( self, self._source_server.plesk_version, selection ) CapabilityXMLConverter(capability_model).write_xml(local_data_filename) def _patch_template(self, agent_dir, max_plesk_version): """Fill in maximum supported Plesk version.""" command = ( u""" sed "s/@@MAJOR_VERSION@@/{MAJOR}/; s/@@MINOR_VERSION@@/{MINOR}/; s/@@PATCH_VERSION@@/{PATCH}/;" \\ ./PleskMaxVersion.pm.in > ./PleskMaxVersion.pm""".format( **max_plesk_version ) ) self._run_agent_command( u"cd {path}; %s" % textwrap.dedent(command), {'path': agent_dir}) def _make_dump(self, selection=DumpAll()): """Run the agent and create migration dump. Download agent log file even in case, if the agent has failed. """ logger.debug(messages.LOG_RUN_MIGRATION_AGENT) command = u"""cd {path}; {perl} {script} %s > {log} 2>&1""" selection_options, selection_args = self._get_selection_cli_options(selection) cli_options = [ '--configuration-only', # dump admin info to get admin descriptions of resellers, clients and subscriptions '--admin-info', '--server', '-v', '5' ] + selection_options if not self.global_context.migrator.with_server_configuration(self.global_context.options): cli_options.append('--skip-extra-server-settings') cli_args = { 'perl': self._perl_bin, 'path': self.agent_dir, 'script': self.settings.agent_script_name, 'log': self.remote_log_filename, } cli_args.update(selection_args) try: self._run_agent_command(command % (" ".join(cli_options)), cli_args) finally: self._download_agent_file( self.remote_log_filename, self.local_log_filename ) logger.fdebug(messages.LOG_CONFIGURATION_DUMP_LOG_FILE, filename=self.local_log_filename) def _make_capability_dump(self, selection=DumpAll()): """Run the agent and create capability dump. Download agent log file even in case, if the agent has failed. """ logger.debug(messages.LOG_RUN_MIGRATION_AGENT) command = u"""cd {path}; {perl} {script} %s > {log} 2>&1""" selection_options, selection_args = self._get_selection_cli_options(selection) cli_options = ['--capability-only', '-v', '5'] + selection_options cli_args = { 'perl': self._perl_bin, 'path': self.agent_dir, 'script': self.settings.agent_script_name, 'log': self.remote_log_filename, } cli_args.update(selection_args) try: self._run_agent_command(command % (" ".join(cli_options)), cli_args) finally: self._download_agent_file( self.remote_log_filename, self.local_log_filename ) logger.fdebug(messages.LOG_CAPABILITY_DUMP_LOG_FILE, filename=self.local_log_filename) @staticmethod def _get_selection_cli_options(selection): selection_cli_options = [] selection_cli_args = {} if isinstance(selection, DumpAll): selection_cli_options.append('--dump-all') elif isinstance(selection, DumpSelected): if not is_empty_list(selection.domains): selection_cli_options.append('--dump-domains={domains}') selection_cli_args['domains'] = ",".join(selection.domains) if not is_empty_list(selection.clients): selection_cli_options.append('--dump-clients={clients}') selection_cli_args['clients'] = ",".join(selection.clients) if not is_empty_list(selection.resellers): selection_cli_options.append('--dump-resellers={resellers}') selection_cli_args['resellers'] = ",".join(selection.resellers) return selection_cli_options, selection_cli_args def _download_dump(self, local_data_filename): logger.debug(messages.LOG_DOWNLOAD_DUMP_XML, local_data_filename) remote_dump_file = 'migration_dump.tar' dump_directories = ['clients', 'domains', 'resellers', '.discovered'] with self._source_server.runner() as runner: assert isinstance(runner, BaseRunner) runner.remove_file(posixpath.join(self.agent_dir, remote_dump_file)) command = u"tar rf {dumpfile} backup_info*" args = dict( agent_dir=self.agent_dir, dumpfile=remote_dump_file ) i = 0 for directory in dump_directories: if runner.file_exists(posixpath.join(self.agent_dir, directory)): command += ' {dir%i}' % i args['dir%i' % i] = directory i += 1 runner.execute_command('cd {agent_dir}; ' + command, args) self._download_agent_file(remote_dump_file, local_data_filename) def _download_agent_file(self, remote_file, local_file): """Download a file from agent directory on source server.""" try: with self._source_server.runner() as runner: logger.debug(messages.LOG_DOWNLOAD_FILE_TO, local_file) runner.get_file(os.path.join(self.agent_dir, remote_file), local_file) except Exception as e: logger.exception() logger.error(messages.ERROR_DOWNLOADING_FILE, e) def _run_agent_command(self, command, arguments): """Run a command on the source server.""" try: with self._source_server.runner() as runner: assert isinstance(runner, BaseRunner) runner.execute_command(textwrap.dedent(command), arguments) except Exception as e: logger.exception() raise MigrationError( safe_format(messages.ERROR_RUNNING_COMMAND, reason=e) ) @staticmethod def _convert_rowset_int_values_to_str(rowset): """Convert integer values in rowset to strings. Old DBI::mysql libraries return MySQL integer values as strings, new DBI::mysql libraries return integer MySQL values as integers. We don't want to keep this difference in mind for code which uses execute MySQL query feature of PMM agent. So convert all integers to strings. :type rowset: list[dict] :rtype: list[dict] """ rowset_fixed = [] for row in rowset: row_fixed = {} for column_name, value in row.items(): if isinstance(value, int): value = str(value) row_fixed[column_name] = value rowset_fixed.append(row_fixed) return rowset_fixed
Edit
Rename
Chmod
Delete
FILE
FOLDER
INFO
Name
Size
Permission
Action
__pycache__
---
0770
__init__.py
0 bytes
0644
hosting_description.py
20011 bytes
0644
unix.py
13809 bytes
0644
utils.py
2002 bytes
0644
windows.py
20238 bytes
0644
N4ST4R_ID | Naxtarrr