def on_HostInitResponse(self, message): if bus.cnf.state == ScalarizrState.RUNNING: self._logger.info("Ignoring 'HostInitResponse' message, cause state is '%s'", bus.cnf.state) return bus.initialization_op = operation(name='Initialization') try: self._define_initialization(message) bus.fire("host_init_response", message) hostup_msg = self.new_message(Messages.HOST_UP, broadcast=True) bus.fire("before_host_up", hostup_msg) if bus.scalr_version >= (2, 2, 3): self.send_message(Messages.BEFORE_HOST_UP, broadcast=True, wait_subhandler=True) self.send_message(hostup_msg) bus.cnf.state = ScalarizrState.RUNNING bus.fire("host_up") except: with bus.initialization_op as op: if not op.finished: with op.phase('Scalarizr routines'): with op.step('Scalarizr routines'): op.error() raise with bus.initialization_op as op: op.ok()
def execute_scripts(self, scripts): if not scripts: return if scripts[0].event_name: phase = "Executing %d %s script(s)" % (len(scripts), scripts[0].event_name) else: phase = 'Executing %d script(s)' % (len(scripts), ) self._logger.info(phase) if self._cnf.state != szrconfig.ScalarizrState.INITIALIZING: # Define operation op = operation(name=self._op_exec_scripts, phases=[{ 'name': phase, 'steps': ["Execute '%s'" % script.name for script in scripts if not script.asynchronous] }]) op.define() else: op = bus.initialization_op with op.phase(phase): for script in scripts: step_title = self._step_exec_tpl % (script.name, 'async' if script.asynchronous else 'sync') with op.step(step_title): self._execute_one_script(script)
def execute_scripts(self, scripts): if not scripts: return # read logs_dir_prefix ini = bus.cnf.rawini try: logs_dir = ini.get(self.name, 'logs_dir') if not os.path.exists(logs_dir): os.makedirs(logs_dir) except ConfigParser.Error: pass if scripts[0].event_name: phase = "Executing %d %s script(s)" % (len(scripts), scripts[0].event_name) else: phase = 'Executing %d script(s)' % (len(scripts), ) self._logger.info(phase) if self._cnf.state != szrconfig.ScalarizrState.INITIALIZING: # Define operation op = operation(name=self._op_exec_scripts, phases=[{ 'name': phase, 'steps': ["Execute '%s'" % script.name for script in scripts if not script.asynchronous] }]) op.define() else: op = bus.initialization_op with op.phase(phase): for script in scripts: step_title = self._step_exec_tpl % (script.name, 'async' if script.asynchronous else 'sync') with op.step(step_title): self._execute_one_script(script)
def on_HostInitResponse(self, message): if bus.cnf.state == ScalarizrState.RUNNING: self._logger.info( "Ignoring 'HostInitResponse' message, cause state is '%s'", bus.cnf.state) return self._check_control_ports() bus.initialization_op = operation(name='Initialization') try: self._define_initialization(message) bus.fire("host_init_response", message) hostup_msg = self.new_message(Messages.HOST_UP, broadcast=True) bus.fire("before_host_up", hostup_msg) if bus.scalr_version >= (2, 2, 3): self.send_message(Messages.BEFORE_HOST_UP, broadcast=True, wait_subhandler=True) self.send_message(hostup_msg) bus.cnf.state = ScalarizrState.RUNNING bus.fire("host_up") except: with bus.initialization_op as op: if not op.finished: with op.phase('Scalarizr routines'): with op.step('Scalarizr routines'): op.error() raise with bus.initialization_op as op: op.ok()
def on_Deploy(self, message, define_operation=True, raise_exc=False): msg_body = dicts.encode(message.body, encoding='ascii') try: if define_operation: op = operation(name='Deploy') op.phases = self._get_phase_definition(message) op.define() else: op = bus.initialization_op with op.phase(self._phase_deploy): assert 'deploy_task_id' in msg_body, 'deploy task is undefined' assert 'source' in msg_body, 'source is undefined' assert 'type' in msg_body['source'], 'source type is undefined' assert 'remote_path' in msg_body and msg_body['remote_path'], 'remote path is undefined' assert 'body' in msg_body['pre_deploy_routines'] if 'pre_deploy_routines' in msg_body else True assert 'body' in msg_body['post_deploy_routines'] if 'post_deploy_routines' in msg_body else True self._log_hdlr.deploy_task_id = msg_body['deploy_task_id'] self._logger.addHandler(self._log_hdlr) src_type = msg_body['source'].pop('type') src = Source.from_type(src_type, **msg_body['source']) if msg_body.get('pre_deploy_routines') and msg_body['pre_deploy_routines'].get('body'): with op.step(self._step_execute_pre_deploy_script): self._exec_script(name='PreDeploy', **msg_body['pre_deploy_routines']) with op.step(self._step_update_from_scm): src.update(msg_body['remote_path']) if msg_body.get('post_deploy_routines') and msg_body['post_deploy_routines'].get('body'): with op.step(self._step_execute_post_deploy_script): self._exec_script(name='PostDeploy', **msg_body['post_deploy_routines']) self.send_message( Messages.DEPLOY_RESULT, dict( status='ok', deploy_task_id=msg_body['deploy_task_id'] ) ) if define_operation: op.ok() except (Exception, BaseException), e: self._logger.exception(e) self.send_message( Messages.DEPLOY_RESULT, dict( status='error', last_error=str(e), deploy_task_id=msg_body['deploy_task_id'] ) ) if raise_exc: raise
def on_Deploy(self, message, define_operation=True): msg_body = dicts.encode(message.body, encoding='ascii') try: if define_operation: op = operation(name='Deploy') op.phases = self._get_phase_definition(message) op.define() else: op = bus.initialization_op with op.phase(self._phase_deploy): assert 'deploy_task_id' in msg_body, 'deploy task is undefined' assert 'source' in msg_body, 'source is undefined' assert 'type' in msg_body['source'], 'source type is undefined' assert 'remote_path' in msg_body and msg_body[ 'remote_path'], 'remote path is undefined' assert 'body' in msg_body[ 'pre_deploy_routines'] if 'pre_deploy_routines' in msg_body else True assert 'body' in msg_body[ 'post_deploy_routines'] if 'post_deploy_routines' in msg_body else True self._log_hdlr.deploy_task_id = msg_body['deploy_task_id'] self._logger.addHandler(self._log_hdlr) src_type = msg_body['source'].pop('type') src = Source.from_type(src_type, **msg_body['source']) if msg_body.get('pre_deploy_routines') and msg_body[ 'pre_deploy_routines'].get('body'): with op.step(self._step_execute_pre_deploy_script): self._exec_script(name='PreDeploy', **msg_body['pre_deploy_routines']) with op.step(self._step_update_from_scm): src.update(msg_body['remote_path']) if msg_body.get('post_deploy_routines') and msg_body[ 'post_deploy_routines'].get('body'): with op.step(self._step_execute_post_deploy_script): self._exec_script(name='PostDeploy', **msg_body['post_deploy_routines']) self.send_message( Messages.DEPLOY_RESULT, dict(status='ok', deploy_task_id=msg_body['deploy_task_id'])) if define_operation: op.ok() except (Exception, BaseException), e: self._logger.exception(e) self.send_message( Messages.DEPLOY_RESULT, dict(status='error', last_error=str(e), deploy_task_id=msg_body['deploy_task_id']))
class StorageAPI(object): error_messages = { 'empty': "'%s' can't be blank", 'invalid': "'%s' is invalid, '%s' expected" } @rpc.service_method def create(self, volume=None, mkfs=False, mount=False, fstab=False, async=False): ''' :type volume: dict :param volume: Volume configuration object :type mkfs: bool :param mkfs: Whether create filesystem on volume device. Error will be raised if existed filesystem detected. :type mount: bool :param mount: Whether mount volume device. Non blank `mpoint` in volume configuration required :type fstab: bool :param fstab: Whether add device to /etc/fstab :type async: bool :param async: Execute method in separate thread and report status with Operation/Steps mechanism :rtype: dict|string ''' self._check_invalid(volume, 'volume', dict) def do_create(): vol = storage2.volume(volume) vol.ensure(mkfs=mkfs, mount=mount, fstab=fstab) return dict(vol) if async: txt = 'Create volume' op = handlers.operation(name=txt) def block(): op.define() with op.phase(txt): with op.step(txt): data = do_create() op.ok(data=data) threading.Thread(target=block).start() return op.id else: return do_create()
class RedisAPI(object): _cnf = None _queryenv = None def __init__(self): self._cnf = bus.cnf self._queryenv = bus.queryenv_service ini = self._cnf.rawini self._role_name = ini.get(config.SECT_GENERAL, config.OPT_ROLE_NAME) @rpc.service_method def launch_processes(self, num=None, ports=None, passwords=None, async=False): if ports and passwords and len(ports) != len(passwords): raise AssertionError('Number of ports must be equal to number of passwords') if num and ports and num != len(ports): raise AssertionError('When ports range is passed its length must be equal to num parameter') if not self.is_replication_master: if not passwords or not ports: raise AssertionError('ports and passwords are required to launch processes on redis slave') available_ports = self.available_ports if num > len(available_ports): raise AssertionError('Cannot launch %s new processes: Ports available: %s' % (num, str(available_ports))) if ports: for port in ports: if port not in available_ports: raise AssertionError('Cannot launch Redis process on port %s: Already running' % port) else: ports = available_ports[:num] if async: txt = 'Launch Redis processes' op = handlers.operation(name=txt) def block(): op.define() with op.phase(txt): with op.step(txt): result = self._launch(ports, passwords, op) op.ok(data=dict(ports=result[0], passwords=result[1])) threading.Thread(target=block).start() return op.id else: result = self._launch(ports, passwords) return dict(ports=result[0], passwords=result[1])
class MySQLAPI(object): """ @xxx: reporting is an anal pain """ error_messages = { 'empty': "'%s' can't be blank", 'invalid': "'%s' is invalid, '%s' expected" } def __init__(self): self._mysql_init = mysql_svc.MysqlInitScript() @rpc.service_method def grow_volume(self, volume, growth, async=False): self._check_invalid(volume, 'volume', dict) self._check_empty(volume.get('id'), 'volume.id') def do_grow(): vol = storage2.volume(volume) self._mysql_init.stop('Growing data volume') try: growed_vol = vol.grow(**growth) __mysql__['volume'] = dict(growed_vol) return dict(growed_vol) finally: self._mysql_init.start() if async: txt = 'Grow MySQL/Percona data volume' op = handlers.operation(name=txt) def block(): op.define() with op.phase(txt): with op.step(txt): data = do_grow() op.ok(data=data) threading.Thread(target=block).start() return op.id else: return do_grow()
def on_DbMsr_CreateDataBundle(self, message): try: op = operation(name=self._op_data_bundle, phases=[{ 'name': self._phase_data_bundle, 'steps': [self._step_create_data_bundle] }]) op.define() with op.phase(self._phase_data_bundle): with op.step(self._step_create_data_bundle): bus.fire('before_postgresql_data_bundle') snap = self._create_snapshot() used_size = int( system2( ('df', '-P', '--block-size=M', STORAGE_PATH))[0].split('\n')[1].split()[2][:-1]) bus.fire('postgresql_data_bundle', snapshot_id=snap.id) # Notify scalr msg_data = { 'db_type': BEHAVIOUR, 'status': 'ok', 'used_size': '%.3f' % (float(used_size) / 1000, ), BEHAVIOUR: { OPT_SNAPSHOT_CNF: dict(snap) } } self.send_message( DbMsrMessages.DBMSR_CREATE_DATA_BUNDLE_RESULT, msg_data) op.ok() except (Exception, BaseException), e: LOG.exception(e) # Notify Scalr about error self.send_message( DbMsrMessages.DBMSR_CREATE_DATA_BUNDLE_RESULT, dict(db_type=BEHAVIOUR, status='error', last_error=str(e)))
def on_DbMsr_CreateBackup(self, message): try: op = operation(name=self._op_backup, phases=[{ 'name': self._phase_backup, 'steps': [self._step_copy_database_file, self._step_upload_to_cloud_storage] }]) op.define() with op.phase(self._phase_backup): with op.step(self._step_copy_database_file): # Flush redis data on disk before creating backup LOG.info("Dumping Redis data on disk") self.redis_instances.save_all() dbs = [r.db_path for r in self.redis_instances] with op.step(self._step_upload_to_cloud_storage): cloud_storage_path = self._platform.scalrfs.backups(BEHAVIOUR) LOG.info("Uploading backup to cloud storage (%s)", cloud_storage_path) transfer = LargeTransfer(dbs, cloud_storage_path) result = transfer.run() result = handlers.transfer_result_to_backup_result(result) op.ok(data=result) # Notify Scalr self.send_message(DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict( db_type = BEHAVIOUR, status = 'ok', backup_parts = result )) except (Exception, BaseException), e: LOG.exception(e) # Notify Scalr about error self.send_message(DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict( db_type = BEHAVIOUR, status = 'error', last_error = str(e) ))
def execute_scripts(self, scripts): if not scripts: return # read logs_dir_prefix ini = bus.cnf.rawini try: logs_dir = ini.get(self.name, 'logs_dir') if not os.path.exists(logs_dir): os.makedirs(logs_dir) except ConfigParser.Error: pass if scripts[0].event_name: phase = "Executing %d %s script(s)" % (len(scripts), scripts[0].event_name) else: phase = 'Executing %d script(s)' % (len(scripts), ) self._logger.info(phase) if self._cnf.state != szrconfig.ScalarizrState.INITIALIZING: # Define operation op = operation(name=self._op_exec_scripts, phases=[{ 'name': phase, 'steps': [ "Execute '%s'" % script.name for script in scripts if not script.asynchronous ] }]) op.define() else: op = bus.initialization_op with op.phase(phase): for script in scripts: step_title = self._step_exec_tpl % ( script.name, 'async' if script.asynchronous else 'sync') with op.step(step_title): self._execute_one_script(script)
def on_DbMsr_CreateDataBundle(self, message): try: op = operation(name=self._op_data_bundle, phases=[{ 'name': self._phase_data_bundle, 'steps': [self._step_create_data_bundle] }]) op.define() with op.phase(self._phase_data_bundle): with op.step(self._step_create_data_bundle): bus.fire('before_%s_data_bundle' % BEHAVIOUR) # Creating snapshot snap = self._create_snapshot() used_size = int(system2(('df', '-P', '--block-size=M', self._storage_path))[0].split('\n')[1].split()[2][:-1]) bus.fire('%s_data_bundle' % BEHAVIOUR, snapshot_id=snap.id) # Notify scalr msg_data = dict( db_type = BEHAVIOUR, used_size = '%.3f' % (float(used_size) / 1000,), status = 'ok' ) msg_data[BEHAVIOUR] = {'snapshot_config': dict(snap)} self.send_message(DbMsrMessages.DBMSR_CREATE_DATA_BUNDLE_RESULT, msg_data) op.ok() except (Exception, BaseException), e: LOG.exception(e) # Notify Scalr about error self.send_message(DbMsrMessages.DBMSR_CREATE_DATA_BUNDLE_RESULT, dict( db_type = BEHAVIOUR, status ='error', last_error = str(e) ))
def on_DbMsr_CreateDataBundle(self, message): try: op = operation(name=self._op_data_bundle, phases=[{ 'name': self._phase_data_bundle, 'steps': [self._step_create_data_bundle] }]) op.define() with op.phase(self._phase_data_bundle): with op.step(self._step_create_data_bundle): bus.fire('before_postgresql_data_bundle') snap = self._create_snapshot() used_size = int(system2(('df', '-P', '--block-size=M', STORAGE_PATH))[0].split('\n')[1].split()[2][:-1]) bus.fire('postgresql_data_bundle', snapshot_id=snap.id) # Notify scalr msg_data = { 'db_type': BEHAVIOUR, 'status': 'ok', 'used_size' : '%.3f' % (float(used_size) / 1000,), BEHAVIOUR: {OPT_SNAPSHOT_CNF: dict(snap)} } self.send_message(DbMsrMessages.DBMSR_CREATE_DATA_BUNDLE_RESULT, msg_data) op.ok() except (Exception, BaseException), e: LOG.exception(e) # Notify Scalr about error self.send_message(DbMsrMessages.DBMSR_CREATE_DATA_BUNDLE_RESULT, dict( db_type = BEHAVIOUR, status ='error', last_error = str(e) ))
with op.step(txt): result = self._launch(ports, passwords, op) op.ok(data=dict(ports=result[0], passwords=result[1])) threading.Thread(target=block).start() return op.id else: result = self._launch(ports, passwords) return dict(ports=result[0], passwords=result[1]) @rpc.service_method def shutdown_processes(self, ports, remove_data=False, async=False): if async: txt = "Shutdown Redis processes" op = handlers.operation(name=txt) def block(): op.define() with op.phase(txt): with op.step(txt): self._shutdown(ports, remove_data, op) op.ok() threading.Thread(target=block).start() return op.id else: return self._shutdown(ports, remove_data) @rpc.service_method def list_processes(self):
def on_DbMsr_CreateBackup(self, message): tmpdir = backup_path = None try: op = operation(name=self._op_backup, phases=[{ 'name': self._phase_backup, 'steps': [self._step_copy_database_file, self._step_upload_to_cloud_storage] }]) op.define() with op.phase(self._phase_backup): with op.step(self._step_copy_database_file): # Flush redis data on disk before creating backup LOG.info("Dumping Redis data on disk") self.redis_instances.save_all() # Dump all databases LOG.info("Dumping all databases") tmpdir = tempfile.mkdtemp() # Defining archive name and path backup_filename = time.strftime('%Y-%m-%d-%H:%M:%S')+'.tar.gz' backup_path = os.path.join('/tmp', backup_filename) dbs = [r.db_path for r in self.redis_instances] # Creating archive backup = tarfile.open(backup_path, 'w:gz') for src_path in dbs: fname = os.path.basename(src_path) dump_path = os.path.join(tmpdir, fname) if not os.path.exists(src_path): LOG.info('%s DB file %s does not exist. Nothing to backup.' % (BEHAVIOUR, src_path)) else: shutil.copyfile(src_path, dump_path) backup.add(dump_path, fname) backup.close() # Creating list of full paths to archive chunks if os.path.getsize(backup_path) > BACKUP_CHUNK_SIZE: parts = [os.path.join(tmpdir, file) for file in split(backup_path, backup_filename, BACKUP_CHUNK_SIZE , tmpdir)] else: parts = [backup_path] sizes = [os.path.getsize(file) for file in parts] with op.step(self._step_upload_to_cloud_storage): cloud_storage_path = self._platform.scalrfs.backups(BEHAVIOUR) LOG.info("Uploading backup to cloud storage (%s)", cloud_storage_path) trn = transfer.Transfer() cloud_files = trn.upload(parts, cloud_storage_path) LOG.info("%s backup uploaded to cloud storage under %s/%s" % (BEHAVIOUR, cloud_storage_path, backup_filename)) result = list(dict(path=path, size=size) for path, size in zip(cloud_files, sizes)) op.ok(data=result) # Notify Scalr self.send_message(DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict( db_type = BEHAVIOUR, status = 'ok', backup_parts = result )) except (Exception, BaseException), e: LOG.exception(e) # Notify Scalr about error self.send_message(DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict( db_type = BEHAVIOUR, status = 'error', last_error = str(e) ))
def on_DbMsr_CreateBackup(self, message): #TODO: Think how to move the most part of it into Postgresql class # Retrieve password for scalr pg user tmpdir = backup_path = None try: # Get databases list psql = PSQL(user=self.postgresql.root_user.name) databases = psql.list_pg_databases() if 'template0' in databases: databases.remove('template0') op = operation(name=self._op_backup, phases=[{ 'name': self._phase_backup }]) op.define() with op.phase(self._phase_backup): if not os.path.exists(self._tmp_path): os.makedirs(self._tmp_path) # Defining archive name and path backup_filename = time.strftime('%Y-%m-%d-%H:%M:%S')+'.tar.gz' backup_path = os.path.join(self._tmp_path, backup_filename) # Creating archive backup = tarfile.open(backup_path, 'w:gz') # Dump all databases LOG.info("Dumping all databases") tmpdir = tempfile.mkdtemp(dir=self._tmp_path) chown_r(tmpdir, self.postgresql.root_user.name) def _single_backup(db_name): dump_path = tmpdir + os.sep + db_name + '.sql' pg_args = '%s %s --no-privileges -f %s' % (PG_DUMP, db_name, dump_path) su_args = [SU_EXEC, '-', self.postgresql.root_user.name, '-c', pg_args] err = system2(su_args)[1] if err: raise HandlerError('Error while dumping database %s: %s' % (db_name, err)) backup.add(dump_path, os.path.basename(dump_path)) make_backup_steps(databases, op, _single_backup) backup.close() with op.step(self._step_upload_to_cloud_storage): # Creating list of full paths to archive chunks #if os.path.getsize(backup_path) > __postgresql__['pgdump_chunk_size']: # parts = [os.path.join(tmpdir, file) for file in split(backup_path, backup_filename, __postgresql__['pgdump_chunk_size'], tmpdir)] #else: # parts = [backup_path] #sizes = [os.path.getsize(file) for file in parts] cloud_storage_path = self._platform.scalrfs.backups(BEHAVIOUR) LOG.info("Uploading backup to cloud storage (%s)", cloud_storage_path) trn = LargeTransfer(backup_path, cloud_storage_path) manifest = trn.run() LOG.info("Postgresql backup uploaded to cloud storage under %s/%s", cloud_storage_path, backup_filename) result = list(dict(path=os.path.join(cloud_storage_path, c[0]), size=c[2]) for c in manifest['files'][0]['chunks']) op.ok(data=result) # Notify Scalr self.send_message(DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict( db_type = BEHAVIOUR, status = 'ok', backup_parts = result )) except (Exception, BaseException), e: LOG.exception(e) # Notify Scalr about error self.send_message(DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict( db_type = BEHAVIOUR, status = 'error', last_error = str(e) ))
with op.step(txt): result = self._launch(ports, passwords, op) op.ok(data=dict(ports=result[0], passwords=result[1])) threading.Thread(target=block).start() return op.id else: result = self._launch(ports, passwords) return dict(ports=result[0], passwords=result[1]) @rpc.service_method def shutdown_processes(self, ports, remove_data=False, async=False): if async: txt = 'Shutdown Redis processes' op = handlers.operation(name=txt) def block(): op.define() with op.phase(txt): with op.step(txt): self._shutdown(ports, remove_data, op) op.ok() threading.Thread(target=block).start() return op.id else: return self._shutdown(ports, remove_data) @rpc.service_method def list_processes(self): return self.get_running_processes()
def on_DbMsr_CreateBackup(self, message): #TODO: Think how to move the most part of it into Postgresql class # Retrieve password for scalr pg user tmpdir = backup_path = None try: # Get databases list psql = PSQL(user=self.postgresql.root_user.name) databases = psql.list_pg_databases() if 'template0' in databases: databases.remove('template0') op = operation(name=self._op_backup, phases=[{ 'name': self._phase_backup }]) op.define() with op.phase(self._phase_backup): if not os.path.exists(self._tmp_path): os.makedirs(self._tmp_path) # Defining archive name and path backup_filename = time.strftime( '%Y-%m-%d-%H:%M:%S') + '.tar.gz' backup_path = os.path.join(self._tmp_path, backup_filename) # Creating archive backup = tarfile.open(backup_path, 'w:gz') # Dump all databases LOG.info("Dumping all databases") tmpdir = tempfile.mkdtemp(dir=self._tmp_path) chown_r(tmpdir, self.postgresql.root_user.name) def _single_backup(db_name): dump_path = tmpdir + os.sep + db_name + '.sql' pg_args = '%s %s --no-privileges -f %s' % ( PG_DUMP, db_name, dump_path) su_args = [ SU_EXEC, '-', self.postgresql.root_user.name, '-c', pg_args ] err = system2(su_args)[1] if err: raise HandlerError( 'Error while dumping database %s: %s' % (db_name, err)) backup.add(dump_path, os.path.basename(dump_path)) make_backup_steps(databases, op, _single_backup) backup.close() with op.step(self._step_upload_to_cloud_storage): # Creating list of full paths to archive chunks if os.path.getsize( backup_path) > __postgresql__['pgdump_chunk_size']: parts = [ os.path.join(tmpdir, file) for file in split( backup_path, backup_filename, __postgresql__['pgdump_chunk_size'], tmpdir) ] else: parts = [backup_path] sizes = [os.path.getsize(file) for file in parts] cloud_storage_path = self._platform.scalrfs.backups( BEHAVIOUR) LOG.info("Uploading backup to cloud storage (%s)", cloud_storage_path) trn = transfer.Transfer() cloud_files = trn.upload(parts, cloud_storage_path) LOG.info( "Postgresql backup uploaded to cloud storage under %s/%s", cloud_storage_path, backup_filename) result = list( dict(path=path, size=size) for path, size in zip(cloud_files, sizes)) op.ok(data=result) # Notify Scalr self.send_message( DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict(db_type=BEHAVIOUR, status='ok', backup_parts=result)) except (Exception, BaseException), e: LOG.exception(e) # Notify Scalr about error self.send_message( DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict(db_type=BEHAVIOUR, status='error', last_error=str(e)))
def on_DbMsr_CreateBackup(self, message): LOG.debug("on_DbMsr_CreateBackup") ''' bak = backup.backup( type='mysqldump', file_per_database=True, tmpdir=__mysql__['tmp_dir'], cloudfsdir=self._platform.scalrfs.backups(__mysql__['behavior']), chunk_size=__mysql__['mysqldump_chunk_size']) restore = None try: op = operation(name=self._op_backup, phases=[{ 'name': self._phase_backup, 'steps': [self._phase_backup] }]) op.define() with op.phase(self._phase_backup): with op.step(self._phase_backup): restore = bak.run() #- type: mysqldump #- files: # - size: 1234567 # - path: s3://farm-2121-44/backups/mysql/20120314.tar.gz.part0 # - size: 3524567 # - path: s3://farm-2121-44/backups/mysql/20120314.tar.gz.part1 #result = list(dict(path=path, size=size) for path, size in zip(cloud_files, sizes)) op.ok(data=restore.files) # Notify Scalr self.send_message(DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict( db_type = __mysql__['behavior'], status = 'ok', backup_parts = restore.files )) except: exc = sys.exc_info()[1] LOG.exception(exc) # Notify Scalr about error self.send_message(DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict( db_type = __mysql__['behavior'], status = 'error', last_error = str(exc) )) ''' tmp_basedir = __mysql__['tmp_dir'] if not os.path.exists(tmp_basedir): os.makedirs(tmp_basedir) # Retrieve password for scalr mysql user backup_path = None tmpdir = None try: # Get databases list databases = self.root_client.list_databases() op = operation(name=self._op_backup, phases=[{ 'name': self._phase_backup }]) op.define() with op.phase(self._phase_backup): # Dump all databases LOG.info("Dumping all databases") tmpdir = tempfile.mkdtemp(dir=tmp_basedir) backup_filename = 'mysql-backup-%s.tar.gz' % time.strftime('%Y-%m-%d-%H:%M:%S') backup_path = os.path.join(tmpdir, backup_filename) # Creating archive backup = tarfile.open(backup_path, 'w:gz') mysqldump = mysql_svc.MySQLDump(root_user=__mysql__['root_user'], root_password=__mysql__['root_password']) dump_options = __mysql__['mysqldump_options'].split(' ') def _single_backup(db_name): dump_path = os.path.join(tmpdir, db_name + '.sql') mysqldump.create(db_name, dump_path, dump_options) backup.add(dump_path, os.path.basename(dump_path)) make_backup_steps(databases, op, _single_backup) backup.close() with op.step(self._step_upload_to_cloud_storage): # Creating list of full paths to archive chunks if os.path.getsize(backup_path) > __mysql__['mysqldump_chunk_size']: parts = [os.path.join(tmpdir, file) for file in filetool.split(backup_path, backup_filename, __mysql__['mysqldump_chunk_size'] , tmpdir)] else: parts = [backup_path] sizes = [os.path.getsize(file) for file in parts] cloud_storage_path = self._platform.scalrfs.backups('mysql') LOG.info("Uploading backup to cloud storage (%s)", cloud_storage_path) trn = transfer.Transfer() cloud_files = trn.upload(parts, cloud_storage_path) LOG.info("Mysql backup uploaded to cloud storage under %s/%s", cloud_storage_path, backup_filename) result = list(dict(path=path, size=size) for path, size in zip(cloud_files, sizes)) op.ok(data=result) # Notify Scalr self.send_message(DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict( db_type = __mysql__['behavior'], status = 'ok', backup_parts = result )) except (Exception, BaseException), e: LOG.exception(e) # Notify Scalr about error self.send_message(DbMsrMessages.DBMSR_CREATE_BACKUP_RESULT, dict( db_type = __mysql__['behavior'], status = 'error', last_error = str(e) ))
def on_DbMsr_CreateDataBundle(self, message): LOG.debug("on_DbMsr_CreateDataBundle") try: op = operation(name=self._op_data_bundle, phases=[{ 'name': self._phase_data_bundle, 'steps': [self._step_create_data_bundle] }]) op.define() with op.phase(self._phase_data_bundle): with op.step(self._step_create_data_bundle): bus.fire('before_mysql_data_bundle') backup_info = message.body.get(__mysql__['behavior'], {}) compat_prior_backup_restore = 'backup' not in backup_info if compat_prior_backup_restore: bak = backup.backup( type='snap_mysql', volume=__mysql__['volume']) else: bak = backup.backup(backup_info['backup']) restore = bak.run() ''' # Creating snapshot snap, log_file, log_pos = self._create_snapshot(ROOT_USER, self.root_password, tags=self.mysql_tags) used_size = firstmatched(lambda r: r.mpoint == STORAGE_PATH, filetool.df()).used bus.fire('mysql_data_bundle', snapshot_id=snap.id) ''' # Notify scalr msg_data = { 'db_type': __mysql__['behavior'], 'status': 'ok', __mysql__['behavior']: {} } if compat_prior_backup_restore: msg_data[__mysql__['behavior']].update({ 'snapshot_config': dict(restore.snapshot), 'log_file': restore.log_file, 'log_pos': restore.log_pos, }) else: msg_data[__mysql__['behavior']].update({ 'restore': dict(restore) }) self.send_message(DbMsrMessages.DBMSR_CREATE_DATA_BUNDLE_RESULT, msg_data) op.ok() except (Exception, BaseException), e: LOG.exception(e) # Notify Scalr about error self.send_message(DbMsrMessages.DBMSR_CREATE_DATA_BUNDLE_RESULT, dict( db_type = __mysql__['behavior'], status ='error', last_error = str(e) ))