def _decode(packet): """Decode the data structure used with XML-RPC into a CommandResult. Since the result sets are merged into a single list of dictionaries, we separate them into result sets using the keys for the dictionaries. """ _LOGGER.debug("Decode packet: %s", packet) version, fabric_uuid, ttl, error, rsets = packet if version != FORMAT_VERSION: raise TypeError("XML-RPC packet format version was %d, expected %d", version, FORMAT_VERSION) result = CommandResult(error, uuid=fabric_uuid, ttl=ttl) if len(rsets) > 0: for rset in rsets: # If the result set contain at least one row, use that to # deduce the types for the columns. If not, assume it is # all strings. if len(rset['rows']) > 0: types = [type(val) for val in rset['rows'][0]] else: types = [str] * len(rset['info']['names']) # Create the result set and add the rows from the packet. rs = ResultSet(names=rset['info']['names'], types=types) for row in rset['rows']: rs.append_row(row) result.append_result(rs) return result
def _decode(packet): """Decode the data structure used with XML-RPC into a CommandResult. Since the result sets are merged into a single list of dictionaries, we separate them into result sets using the keys for the dictionaries. """ _LOGGER.debug("Decode packet: %s", packet) version, fabric_uuid, ttl, error, rsets = packet if version != FORMAT_VERSION: raise TypeError("XML-RPC packet format version was %d, expected %d", version, FORMAT_VERSION) result = CommandResult(error, uuid=fabric_uuid, ttl=ttl) if len(rsets) > 0: for rset in rsets: # If the result set contain at least one row, use that to # deduce the types for the columns. If not, assume it is # all strings. if len(rset['rows']) > 0: types = [ type(val) for val in rset['rows'][0] ] else: types = [ str ] * len(rset['info']['names']) # Create the result set and add the rows from the packet. rs = ResultSet(names=rset['info']['names'], types=types) for row in rset['rows']: rs.append_row(row) result.append_result(rs) return result
def execute(self, event, locks, *args, **kwargs): """Trigger the execution of an event. :param event: Event's identification. :type event: String :param args: Event's non-keyworded arguments. :param kwargs: Event's keyworded arguments. :return: :class:`CommandResult` instance with UUID of the procedures that were triggered. """ lockable_objects = set() for lock in locks.split(","): lockable_objects.add(lock.strip()) rset = ResultSet(names=['uuid'], types=[str]) # Trigger the event and add the UUID of all procedures queued # to the result. for proc in _events.trigger(event, lockable_objects, *args, **kwargs): rset.append_row([str(proc.uuid)]) return CommandResult(None, results=rset)
def execute(self, group_id=None): """Return information on existing group(s). :param group_id: None if one wants to list the existing groups or group's id if one wants information on a group. :return: List with {"group_id" : group_id, "failure_detector": ON/OFF, "description" : description}. """ if group_id is None: gids = _server.Group.groups() else: gids = [group_id] _LOGGER.debug("Group IDs: %s", gids) # Fetch all the groups before building the result set since an # exception can be thrown and there is little point in trying # to build a result set before all groups can be fetched. groups = [ _retrieve_group(gid) for gid in gids ] rset = ResultSet( names=('group_id', 'description', 'failure_detector', 'master_uuid'), types=(str, str, str, str) ) for group in groups: rset.append_row([ group.group_id, # group_id group.description, # description "ACTIVE" if group.status else "INACTIVE", # failure_detector group.master, # master_uuid ]) return CommandResult(None, results=rset)
def execute(self, proc_uuids=None): """Wait until a set of procedures uniquely identified by their uuids finish their execution. However, before starting waiting, the function checks if the procedures exist. If one of the procedures is not found, the following exception is raised :class:`~mysql.fabric.errors.ProcedureError`. :param proc_uuids: Iterable with procedures' UUIDs. """ if proc_uuids is None: raise _errors.ProcedureError("Please, specify which procedure(s) you will be waiting for.") procedures = [] for proc_uuid in proc_uuids: proc_uuid = _uuid.UUID(proc_uuid.strip()) procedure = _executor.Executor().get_procedure(proc_uuid) if not procedure: raise _errors.ProcedureError("Procedure (%s) was not found." % (proc_uuid,)) procedures.append(procedure) command_results = CommandResult(error=None) for procedure in procedures: command_result = ProcedureCommand.wait_for_procedures([procedure], True) if command_result.error is None: for result in command_result.results: command_results.append_result(result) else: result = ResultSet(names=["uuid", "error"], types=[str, str]) result.append_row([str(procedure.uuid), str(command_result.error)]) command_results.append_result(result) return command_results
def search(provider_id, generic_filters, meta_filters, skip_store): """Return information on existing machine(s). """ provider = _retrieve_provider(provider_id) if not skip_store: if generic_filters or meta_filters: raise ConfigurationError( "Filters are only supported when the 'skip_store' option " "is set.") machines = Machine.machines(provider.provider_id) else: generic_filters, meta_filters = \ _preprocess_filters(generic_filters, meta_filters) manager = provider.get_provider_machine() if issubclass(manager, AbstractDatabaseManager): meta_filters = {} manager = _retrieve_database_manager(provider_id) elif issubclass(manager, AbstractMachineManager): manager = _retrieve_machine_manager(provider_id) machines = manager.search(generic_filters, meta_filters) rset = ResultSet(names=('uuid', 'provider_id', 'av_zone', 'addresses'), types=(str, str, str, str)) for machine in machines: row = (str(machine.uuid), machine.provider_id, machine.av_zone, machine.addresses) rset.append_row(row) return CommandResult(None, results=rset)
def setUp(self): # Create a simplistic result set names = ["foo", "bar"] types = [int, float] self.result = ResultSet(names=names, types=types) self.names = names self.types = types
def execute(self, protocol=None): """Return a list with all the available Fabric Servers. :return: List with existing Fabric Servers. :rtype: ["host:port", ...] """ service = _services.ServiceManager() rset = ResultSet(names=('host', 'port'), types=(str, int)) for _, address in service.address(protocol).items(): rset.append_row(address.split(":")) return CommandResult(None, results=rset)
def execute(self, address, timeout=None): """Return server's UUID. :param address: Server's address. :param timeout: Time in seconds after which an error is reported if the UUID is not retrieved. :return: UUID. """ rset = ResultSet(names=['uuid'], types=[str]) rset.append_row([_lookup_uuid(address, timeout)]) return CommandResult(None, results=rset)
def execute(self, protocol=None): """Return a list with all the available Fabric Servers. :return: List with existing Fabric Servers. :rtype: ["host:port", ...] """ service = _services.ServiceManager() rset = ResultSet(names=('host', 'port'),types=(str, int)) for _, address in service.address(protocol).items(): rset.append_row(address.split(":")) return CommandResult(None, results=rset)
def get_cmd_info_result(self, cmd_result): """Create the information result set from a CommandResult :param cmd_result: Instance of CommandResult :return: A ResultSet instance :rtype: ResultSet """ info_result = ResultSet(('fabric_uuid', 'ttl', 'message'), (str, int, str)) info_result.append_row((cmd_result.uuid, cmd_result.ttl, cmd_result.error)) return info_result
def get_cmd_info_result(self, cmd_result): """Create the information result set from a CommandResult :param cmd_result: Instance of CommandResult :return: A ResultSet instance :rtype: ResultSet """ info_result = ResultSet(('fabric_uuid', 'ttl', 'message'), (str, int, str)) info_result.append_row( (cmd_result.uuid, cmd_result.ttl, cmd_result.error)) return info_result
def execute(self): """The method returns all the shard mapping definitions. :return: A list of shard mapping definitions An Empty List if no shard mapping definition is found. """ rset = ResultSet( names=('mapping_id', 'type_name', 'global_group_id'), types=(int, str, str), ) for row in ShardMapping.list_shard_mapping_defn(): rset.append_row(row) return CommandResult(None, results=rset)
def execute(self, group_id, server_id=None, status=None, mode=None): """Return information on existing server(s) in a group. :param group_id: Group's id. :param uuid: None if one wants to list the existing servers in a group or server's id if one wants information on a server in a group. :server_id type: Servers's UUID or HOST:PORT. :param status: Server's status one is searching for. :param mode: Server's mode one is searching for. :return: Information on servers. :rtype: List with [uuid, address, status, mode, weight] """ # Determine the set of servers to iterate through. group = _retrieve_group(group_id) if server_id is None: servers = [server for server in group.servers()] else: servers = [_retrieve_server(server_id, group_id)] # Determine the set of status to check upon. if status is None: status = _server.MySQLServer.SERVER_STATUS else: status = [_retrieve_server_status(status)] # Determine the set of modes to check upon. if mode is None: mode = _server.MySQLServer.SERVER_MODE else: mode = [_retrieve_server_mode(mode)] # Create result set. rset = ResultSet( names=('server_uuid', 'address', 'status', 'mode', 'weight', 'connections'), types=(str, str, str, str, float, int), ) for server in servers: if server.status in status and server.mode in mode: rset.append_row([ str(server.uuid), server.address, server.status, server.mode, server.weight, server.connections ]) return CommandResult(None, results=rset)
def execute(self, connector_version=None, patterns=""): """Return information about all servers. :param connector_version: The connectors version of the data. :param patterns: group pattern. """ rset = ResultSet( names=('group_id', 'primary', 'secondary', 'spare', 'faulty'), types=(str, int, int, int, int) ) for row in _server.MySQLServer.dump_health(connector_version): rset.append_row(row) return CommandResult(None, results=rset)
def execute(self, connector_version=None, patterns=""): """Return information about all servers. :param connector_version: The connectors version of the data. :param patterns: group pattern. """ rset = ResultSet( names=('server_uuid', 'group_id', 'host', 'port', 'mode', 'status', 'weight'), types=(str, str, str, int, int, int, float) ) for row in _server.MySQLServer.dump_servers(connector_version, patterns): rset.append_row(row) return CommandResult(None, results=rset)
def execute(self): """A remote command that returns None. """ rset = ResultSet(names=['foo'], types=[int]) rset.append_row([2L**32]) return CommandResult(None, results=rset)
def execute(self, connector_version=None, patterns=""): """Return information about the index for all mappings matching any of the patterns provided. :param connector_version: The connectors version of the data. :param patterns: group pattern. """ rset = ResultSet( names=('lower_bound', 'mapping_id', 'shard_id', 'group_id'), types=(str, int, int, str), ) for row in Shards.dump_shard_indexes(connector_version, patterns): rset.append_row(row) return CommandResult(None, results=rset)
def execute(self, connector_version=None, patterns=""): """Return information about all shard mappings matching any of the provided patterns. :param connector_version: The connectors version of the data. :param patterns: shard mapping pattern. """ rset = ResultSet( names=('mapping_id', 'type_name', 'global_group_id'), types=(int, str, str), ) for row in ShardMapping.dump_shard_maps(connector_version, patterns): rset.append_row(row) return CommandResult(None, results=rset)
def execute(self): """Statistics on the Fabric node. It returns information on the Fabric node, specifically a list with the following fileds: node identification, how long it is running, when it was started. """ fabric = FabricNode() node_id = fabric.uuid node_startup = fabric.startup node_uptime = _utils.get_time() - node_startup rset = ResultSet(names=('node_id', 'node_uptime', 'node_startup'), types=(str, str, str)) rset.append_row([node_id, node_uptime, node_startup]) return CommandResult(None, results=rset)
def execute(self, connector_version=None, patterns=""): """Return information about all tables belonging to mappings matching any of the provided patterns. :param connector_version: The connectors version of the data. :param patterns: shard mapping pattern. """ rset = ResultSet( names=('schema_name', 'table_name', 'column_name', 'mapping_id'), types=(str, str, str, int), ) for row in ShardMapping.dump_shard_tables(connector_version, patterns): rset.append_row(row) return CommandResult(None, results=rset)
def execute(self, connector_version=None, patterns=""): """Return information about all tables belonging to mappings matching any of the provided patterns. :param connector_version: The connectors version of the data. :param patterns: shard mapping pattern. """ rset = ResultSet( names=('schema_name', 'table_name', 'column_name', 'mapping_id', 'range_check'), types=(str, str, str, int, int), ) for row in ShardMapping.dump_shard_tables(connector_version, patterns): rset.append_row(row) return CommandResult(None, results=rset)
def execute(self): """Statistics on the Fabric node. It returns information on the Fabric node, specifically a list with the following fileds: node identification, how long it is running, when it was started. """ fabric = FabricNode() node_id = fabric.uuid node_startup = fabric.startup node_uptime = _utils.get_time() - node_startup rset = ResultSet( names=('node_id', 'node_uptime', 'node_startup'), types=( str, str, str)) rset.append_row([node_id, node_uptime, node_startup]) return CommandResult(None, results=rset)
def execute(self, group_id=None): """Statistics on a Group. It returns how many promotions and demotions were executed within a group. Specifically, a list with the following fields are returned: group_id, number of promotions, number of demotions. :param group_id: Group one wants to retrieve information on. """ rset = ResultSet( names=('group_id', 'call_count', 'call_abort'), types=(str, long, long), ) for row in MySQLHandler.group_view(group_id): rset.append_row(row) return CommandResult(None, results=rset)
def execute(self, procedure_name=None): """Statistics on the Fabric node. It returns information on procedures that match the %procedure_name% pattern. The information is returned is a list in which each member of the list is also a list with the following fields: procedure name, number of successful calls, number of unsuccessful calls. :param procedure_name: Procedure one wants to retrieve information on. """ rset = ResultSet( names=('proc_name', 'call_count', 'call_abort'), types=(str, long, long), ) for row in MySQLHandler.procedure_view(procedure_name): rset.append_row(row) return CommandResult(None, results=rset)
def execute(self, connector_version=None, patterns=""): """Return all the sharding information about the tables passed as patterns. If no patterns are provided, dump sharding information about all tables. :param connector_version: The connectors version of the data. :param patterns: shard table pattern. """ rset = ResultSet( names=('schema_name', 'table_name', 'column_name', 'lower_bound', 'shard_id', 'type_name', 'group_id', 'global_group'), types=(str, str, str, str, int, str, str, str), ) for row in ShardMapping.dump_sharding_info(connector_version, patterns): rset.append_row(row) return CommandResult(None, results=rset)
def execute(self, event, locks=None, args=None, kwargs=None): """Trigger the execution of an event. :param event: Event's identification. :type event: String :param args: Event's non-keyworded arguments. :param kwargs: Event's keyworded arguments. :return: :class:`CommandResult` instance with UUID of the procedures that were triggered. """ # Prepare lockable objects. lockable_objects = None if locks: lockable_objects = set() for lock in locks: lockable_objects.add(lock.strip()) # Prepare list arguments. param_args = [] if args is not None: param_args = args # Prepare key word arguments. param_kwargs = {} if kwargs is not None: param_kwargs = kv_to_dict(kwargs) # Define the result set format. rset = ResultSet(names=['uuid'], types=[str]) _LOGGER.debug("Triggering event (%s) with arguments: %s, %s.", event, param_args, param_kwargs) # Trigger the event and add the UUID of all procedures queued # to the result. procedures = _events.trigger(event, lockable_objects, *param_args, **param_kwargs) for procedure in procedures: rset.append_row([str(procedure.uuid)]) return CommandResult(None, results=rset)
def execute(self): """Get last fd number and max_open_files, return them. """ try: ### Getting max open files f = open("/proc/%d/limits" % os.getpid()) max_open_files = int(re.search("Max open files\s+(\d+)\s", f.read()).group(1)) f.close() ### Getting newest fd. max_fd = os.open("/dev/null", 0) os.close(max_fd) except Exception as error: _LOGGER.warning("Can't get current and/or max fd (%s).", str(error)) return CommandResult(str(error)) _LOGGER.info("OpenFDs are %d/%d.", max_fd, max_open_files) rset = ResultSet(names=('current', 'max'),types=(int, int)) rset.append_row((max_fd, max_open_files)) return CommandResult(None, results=rset)
def execute(self, provider_id=None): """Return information on existing provider(s). :param provider_id: None if one wants to list the existing providers or provider's id if one wants information on a provider. """ rset = ResultSet( names=('provider_id', 'type', 'username', 'url', 'tenant', 'default_image', 'default_flavor', 'extra'), types=(str, str, str, str, str, str, str, str) ) if provider_id is None: for prv in Provider.providers(): rset.append_row(( prv.provider_id, prv.provider_type, prv.username, prv.url, prv.tenant, prv.default_image, prv.default_flavor, prv.extra )) else: prv = _retrieve_provider(provider_id) rset.append_row(( prv.provider_id, prv.provider_type, prv.username, prv.url, prv.tenant, prv.default_image, prv.default_flavor, prv.extra )) return CommandResult(None, results=rset)
def execute(self, event, locks=None, args=None, kwargs=None): """Trigger the execution of an event. :param event: Event's identification. :type event: String :param args: Event's non-keyworded arguments. :param kwargs: Event's keyworded arguments. :return: :class:`CommandResult` instance with UUID of the procedures that were triggered. """ # Prepare lockable objects. lockable_objects = None if locks: lockable_objects = set() for lock in locks: lockable_objects.add(lock.strip()) # Prepare list arguments. param_args = [] if args is not None: param_args = args # Prepare key word arguments. param_kwargs = {} if kwargs is not None: param_kwargs = kv_to_dict(kwargs) # Define the result set format. rset = ResultSet(names=["uuid"], types=[str]) _LOGGER.debug("Triggering event (%s) with arguments: %s, %s.", event, param_args, param_kwargs) # Trigger the event and add the UUID of all procedures queued # to the result. procedures = _events.trigger(event, lockable_objects, *param_args, **param_kwargs) for procedure in procedures: rset.append_row([str(procedure.uuid)]) return CommandResult(None, results=rset)
def execute(self, provider_id, generic_filters=None, meta_filters=None, skip_store=False): """Return information on existing machine(s). :param provider_id: Provider's Id. :param generic_filters: Filter returned machines by some properites but metadata properties. :param meta_filters: Filter returned machines by metadata properties. :param skip_store: Proceed anyway if there is no information on the machine in the state store. Default is False. """ rset = ResultSet(names=('uuid', 'provider_id', 'av_zone', 'addresses'), types=(str, str, str, str)) if not skip_store: if generic_filters or meta_filters: raise _errors.ConfigurationError( "Filters are only supported when the 'skip_store' option " "is set.") provider = _retrieve_provider(provider_id) for mc in Machine.machines(provider.provider_id): rset.append_row( (str(mc.uuid), mc.provider_id, mc.av_zone, mc.addresses)) else: generic_filters, meta_filters = \ _preprocess_filters(generic_filters, meta_filters) manager = _retrieve_manager(provider_id) for mc in manager.search_machines(generic_filters, meta_filters): rset.append_row( (str(mc.uuid), mc.provider_id, mc.av_zone, mc.addresses)) return CommandResult(None, results=rset)
def execute(self, proc_uuids=None): """Wait until a set of procedures uniquely identified by their uuids finish their execution. However, before starting waiting, the function checks if the procedures exist. If one of the procedures is not found, the following exception is raised :class:`~mysql.fabric.errors.ProcedureError`. :param proc_uuids: Iterable with procedures' UUIDs. """ if proc_uuids is None: raise _errors.ProcedureError( "Please, specify which procedure(s) you will be waiting for.") procedures = [] for proc_uuid in proc_uuids: proc_uuid = _uuid.UUID(proc_uuid.strip()) procedure = _executor.Executor().get_procedure(proc_uuid) if not procedure: raise _errors.ProcedureError("Procedure (%s) was not found." % (proc_uuid, )) procedures.append(procedure) command_results = CommandResult(error=None) for procedure in procedures: command_result = ProcedureCommand.wait_for_procedures([ procedure, ], True) if command_result.error is None: for result in command_result.results: command_results.append_result(result) else: result = ResultSet(names=['uuid', 'error'], types=[str, str]) result.append_row( [str(procedure.uuid), str(command_result.error)]) command_results.append_result(result) return command_results
def test_remote_command(self): """Create a remote command and fire it. """ # Configure a local command. from __main__ import xmlrpc_next_port params = { 'protocol.xmlrpc': { 'address': 'localhost:{0}'.format(xmlrpc_next_port), 'user': '', 'password': '', }, } config = _config.Config(None, params) local_cmd = NewRemoteCommand() local_cmd.setup_client(_xmlrpc.MyClient(), None, config) # Dispatch request through local command to remote command. rs = ResultSet(names=["foo"], types=[str]) rs.append_row(["executed"]) self.assertEqual(str(local_cmd.dispatch()), str(CommandResult(None, results=rs))) self.assertEqual(local_cmd.execution, None)
def search(provider_id, generic_filters, meta_filters, skip_store): """Return information on existing machine(s). """ provider = _retrieve_provider(provider_id) if not skip_store: if generic_filters or meta_filters: raise ConfigurationError( "Filters are only supported when the 'skip_store' option " "is set." ) machines = Machine.machines(provider.provider_id) else: generic_filters, meta_filters = \ _preprocess_filters(generic_filters, meta_filters) manager = provider.get_provider_machine() if issubclass(manager, AbstractDatabaseManager): meta_filters = {} manager = _retrieve_database_manager(provider_id) elif issubclass(manager, AbstractMachineManager): manager = _retrieve_machine_manager(provider_id) machines = manager.search(generic_filters, meta_filters) rset = ResultSet( names=('uuid', 'provider_id', 'av_zone', 'addresses'), types=(str, str, str, str) ) for machine in machines: row = ( str(machine.uuid), machine.provider_id, machine.av_zone, machine.addresses ) rset.append_row(row) return CommandResult(None, results=rset)
def execute(self, group_id, timeout=None): """Check if any server within a group has failed. :param group_id: Group's id. :param group_id: Timeout value after which a server is considered unreachable. If None is provided, it assumes the default value in the configuration file. """ group = _server.Group.fetch(group_id) if not group: raise _errors.GroupError("Group (%s) does not exist." % (group_id, )) info = ResultSet( names=[ 'uuid', 'is_alive', 'status', 'is_not_running', 'is_not_configured', 'io_not_running', 'sql_not_running', 'io_error', 'sql_error' ], types=[str, bool, str] + [bool] * 4 + [str, str] ) issues = ResultSet(names=['issue'], types=[str]) try: timeout = float(timeout) except (TypeError, ValueError): pass for server in group.servers(): alive = False is_master = (group.master == server.uuid) status = server.status why_slave_issues = {} # These are used when server is not contactable. why_slave_issues = { 'is_not_running': False, 'is_not_configured': False, 'io_not_running': False, 'sql_not_running': False, 'io_error': False, 'sql_error': False, } try: alive = server.is_alive(timeout or DEFAULT_UNREACHABLE_TIMEOUT) if alive and not is_master: server.connect() slave_issues, why_slave_issues = \ _replication.check_slave_issues(server) str_master_uuid = _replication.slave_has_master(server) if (group.master is None or str(group.master) != \ str_master_uuid) and not slave_issues: issues.append_row([ "Group has master (%s) but server is connected " \ "to master (%s)." % \ (group.master, str_master_uuid) ]) except _errors.DatabaseError: alive = False info.append_row([ server.uuid, alive, status, why_slave_issues['is_not_running'], why_slave_issues['is_not_configured'], why_slave_issues['io_not_running'], why_slave_issues['sql_not_running'], why_slave_issues['io_error'], why_slave_issues['sql_error'], ]) return CommandResult(None, results=[info, issues])
class TestResultSet(unittest.TestCase): "Test result set." def setUp(self): # Create a simplistic result set names = ["foo", "bar"] types = [int, float] self.result = ResultSet(names=names, types=types) self.names = names self.types = types def test_definition(self): "Check that the types and number of columns are correct." self.assertEqual(len(self.result.columns), 2) for no, name in enumerate(self.names): self.assertEqual(self.result.columns[no].name, name) for no, typ in enumerate(self.types): self.assertEqual(self.result.columns[no].type, typ) def test_append_row(self): "Check append_row function" self.assertEqual(self.result.rowcount, 0) self.result.append_row((1, 2)) self.assertEqual(self.result.rowcount, 1) self.result.append_row([5.0, 3.2]) self.assertEqual(self.result.rowcount, 2) self.result.append_row(['50', '2.25']) # Test that we can iterate the rows and get the expected # rows. Also check that the value returned matches the # expected type. expected = [ (1, 2.0), # Second element in tuple converted to float above (5, 3.2), # First element in tuple converted to int above (50, 2.25), # Both elements converted from string ] for row, ref in zip(self.result, expected): self.assertEqual(row, ref) for no, col in enumerate(row): # assertIsInstance is in Python 2.7, but not Python 2.6 self.assertTrue( isinstance(col, self.result.columns[no].type), "Expected type '%s', was '%s'" % (self.result.columns[no].type.__name__, type(col).__name__)) def test_indexing(self): "Check indexing the result set." # Just for precaution, the result set should be empty at start. self.assertEqual(self.result.rowcount, 0) # This should fail and raise an exception self.assertRaises(IndexError, (lambda x: self.result[x]), 0) # Check that indexing works and return the row added. self.result.append_row((1, 2.0)) self.assertEqual(self.result[0], (1, 2.0)) def test_failures(self): "Test that the result set class throw errors at the right times." self.assertRaises(_errors.CommandResultError, self.result.append_row, [1, 2.0, 5]) self.assertRaises(_errors.CommandResultError, self.result.append_row, [1]) self.assertRaises(_errors.CommandResultError, self.result.append_row, []) self.assertRaises(ValueError, self.result.append_row, [1, 'ERROR']) self.assertRaises(ValueError, self.result.append_row, ['ERROR', 2.0])
class TestCommandResult(unittest.TestCase): "Test command result" def setUp(self): self.names = ["foo", "bar"] self.types = [int, float] self.rset = ResultSet(names=self.names, types=self.types) self.rset.append_row((1, 2.0)) self.rset.append_row((2, 4.0)) def test_basic(self): result = CommandResult(None) self.assertEqual(result.error, None) self.assertEqual(len(result.results), 0) result.append_result(self.rset) self.assertEqual(len(result.results), 1) # Check that indexing works and return the result set added. self.assertEqual(result.results[0], self.rset) # Check that passing something that is not a result set will # raise an error. self.assertRaises(_errors.CommandResultError, result.append_result, []) result = CommandResult("Not working") self.assertEqual(result.error, "Not working") self.assertRaises(_errors.CommandResultError, result.append_result, self.rset) def test_xmlrpc_execute(self): "Test XML-RPC encoding and decoding functions." cmd = _xmlrpc._CommandExecuteAndEncode(NewRemoteCommand()) result1 = CommandResult(None) result1.append_result(self.rset) packet = cmd() self.assertEqual( packet, [ _xmlrpc.FORMAT_VERSION, str(FABRIC_UUID), utils.TTL, '', # No error [ # One result set with one row { 'info': { 'names': ['foo'] }, 'rows': [ ("executed", ), ] } ] ]) result2 = _xmlrpc._decode(packet) def test_xmlrpc_encoding(self): "Test the XML-RPC encoder and decoder." results = [ CommandResult(None), ] for result in results: self.assertEqual(str(result), str(_xmlrpc._decode(_xmlrpc._encode(result))))
def setUp(self): self.names = ["foo", "bar"] self.types = [int, float] self.rset = ResultSet(names=self.names, types=self.types) self.rset.append_row((1, 2.0)) self.rset.append_row((2, 4.0))
def execute(self, group_id): """Check if any server within a group has failed. :param group_id: Group's id. """ group = _server.Group.fetch(group_id) if not group: raise _errors.GroupError("Group (%s) does not exist." % (group_id, )) info = ResultSet( names=[ 'uuid', 'is_alive', 'status', 'is_not_running', 'is_not_configured', 'io_not_running', 'sql_not_running', 'io_error', 'sql_error', 'gtid_executed' ], types=[str, bool, str] + [bool] * 4 + [str, str, str] ) issues = ResultSet(names=['issue'], types=[str]) for server in group.servers(): alive = False is_master = (group.master == server.uuid) status = server.status why_slave_issues = {} # These are used when server is not contactable. why_slave_issues = { 'is_not_running': False, 'is_not_configured': False, 'io_not_running': False, 'sql_not_running': False, 'io_error': False, 'sql_error': False, } try: # TODO: CHECK WHETHER WE SHOULD USE IS_ALIVE OR NOT. if server.is_alive: server.connect() alive = True if not is_master: slave_issues, why_slave_issues = \ _replication.check_slave_issues(server) str_master_uuid = _replication.slave_has_master(server) if (group.master is None or str(group.master) != \ str_master_uuid) and not slave_issues: issues.append_row([ "Group has master (%s) but server is connected " \ "to master (%s)." % \ (group.master, str_master_uuid) ]) gtid_executed= server.get_gtid_status()[0].GTID_EXECUTED else: status = _server.MySQLServer.FAULTY gtid_executed= "UNKNOWN" except _errors.DatabaseError: status = _server.MySQLServer.FAULTY gtid_executed= "UNKNOWN" info.append_row([ server.uuid, alive, status, why_slave_issues['is_not_running'], why_slave_issues['is_not_configured'], why_slave_issues['io_not_running'], why_slave_issues['sql_not_running'], why_slave_issues['io_error'], why_slave_issues['sql_error'], ' '.join(gtid_executed.splitlines()), ]) return CommandResult(None, results=[info, issues])
def execute(self): """Method that is remotely executed. """ rs = ResultSet(names=["foo"], types=[str]) rs.append_row(["executed"]) return CommandResult(None, rs)