def estimate_backup_size(self): """Estimate the size of the backup this plugin will generate""" LOG.info("Estimating size of mysqldump backup") estimate_method = self.config['mysqldump']['estimate-method'] if estimate_method.startswith('const:'): try: return parse_size(estimate_method[6:]) except ValueError as exc: raise BackupError(str(exc)) if estimate_method != 'plugin': raise BackupError("Invalid estimate-method '%s'" % estimate_method) try: db_iter = DatabaseIterator(self.client) tbl_iter = MetadataTableIterator(self.client) try: self.client.connect() except Exception as ex: LOG.error("Failed to connect to database") LOG.error("%s", ex) raise BackupError("MySQL Error %s" % ex) try: self.schema.refresh(db_iter=db_iter, tbl_iter=tbl_iter) except MySQLError as exc: LOG.error("Failed to estimate backup size") LOG.error("[%d] %s", *exc.args) raise BackupError("MySQL Error [%d] %s" % exc.args) return float(sum([db.size for db in self.schema.databases])) finally: self.client.disconnect()
class MySQLDumpPlugin(object): """MySQLDump Backup Plugin interface for Holland""" CONFIGSPEC = CONFIGSPEC def __init__(self, name, config, target_directory, dry_run=False): self.name = name self.config = config self.target_directory = target_directory self.dry_run = dry_run self.config.validate_config(self.CONFIGSPEC) # -> ValidationError # Setup a discovery shell to find schema items # This will iterate over items during the estimate # or backup phase, which will call schema.refresh() self.schema = MySQLSchema() config = self.config['mysqldump'] self.schema.add_database_filter(include_glob(*config['databases'])) self.schema.add_database_filter( exclude_glob(*config['exclude-databases'])) self.schema.add_table_filter(include_glob_qualified(*config['tables'])) self.schema.add_table_filter( exclude_glob_qualified(*config['exclude-tables'])) self.schema.add_engine_filter(include_glob(*config['engines'])) self.schema.add_engine_filter(exclude_glob(*config['exclude-engines'])) self.mysql_config = build_mysql_config(self.config['mysql:client']) self.client = connect(self.mysql_config['client']) def estimate_backup_size(self): """Estimate the size of the backup this plugin will generate""" LOG.info("Estimating size of mysqldump backup") estimate_method = self.config['mysqldump']['estimate-method'] if estimate_method.startswith('const:'): try: return parse_size(estimate_method[6:]) except ValueError, exc: raise BackupError(str(exc)) if estimate_method != 'plugin': raise BackupError("Invalid estimate-method '%s'" % estimate_method) try: db_iter = DatabaseIterator(self.client) tbl_iter = MetadataTableIterator(self.client) try: self.client.connect() self.schema.refresh(db_iter=db_iter, tbl_iter=tbl_iter) except MySQLError, exc: LOG.error("Failed to estimate backup size") LOG.error("[%d] %s", *exc.args) raise BackupError("MySQL Error [%d] %s" % exc.args) return float(sum([db.size for db in self.schema.databases]))
def _fast_refresh_schema(self): # determine if we can skip expensive table metadata lookups entirely # and just worry about finding database names # However, with lock-method=auto-detect we must look at table engines # to determine what lock method to use config = self.config['mysqldump'] fast_iterate = config['lock-method'] != 'auto-detect' try: db_iter = DatabaseIterator(self.client) tbl_iter = SimpleTableIterator(self.client, record_engines=True) try: self.client.connect() self.schema.refresh(db_iter=db_iter, tbl_iter=tbl_iter, fast_iterate=fast_iterate) except MySQLError, exc: LOG.debug("MySQLdb error [%d] %s", exc_info=True, *exc.args) raise BackupError("MySQL Error [%d] %s" % exc.args) finally: self.client.disconnect()