def _add_shard_range_check(shard_mapping_id, shard_type): """Add the shard ranges in the metadata tables of the shards :param shard_mapping_id: The shard mapping ID of the shards for which the metadata needs to be added. :param shard_type: The datatype of the sharding definition. """ shard_list = SHARDING_SPECIFICATION_HANDLER[shard_type].list(shard_mapping_id) for shard in shard_list: group_id = Shards.fetch(shard.shard_id).group_id #The metadata has to be created before adding the ranges because #the global group might have still not replicated the schema to the #shard group. If the replication has still not happened, adding #the bounds will throw an error. SHARD_METADATA.create_shard_meta_data(group_id) spec_handler = SHARDING_SPECIFICATION_HANDLER[shard_type] upper_bound = spec_handler.get_upper_bound( shard.lower_bound, shard_mapping_id, shard_type ) SHARD_METADATA.insert_shard_meta_data(shard.shard_id, shard.lower_bound, upper_bound, group_id)
def _remove_shard(shard_id, update_only=False): """Remove the RANGE specification mapping represented by the current RANGE shard specification object. :param shard_id: The shard ID of the shard that needs to be removed. :param update_only: Only update the state store and skip adding range checks. :return: True if the remove succeeded False if the query failed :raises: ShardingError if the shard id is not found, : ShardingError if the shard is not disabled. """ range_sharding_specification, shard, _, _ = \ verify_and_fetch_shard(shard_id) if shard.state == "ENABLED": raise _errors.ShardingError(SHARD_NOT_DISABLED) #Stop the replication of the shard group with the global #group. Also clear the references of the master and the #slave group from the current group. #NOTE: When we do the stopping of the shard group #replication in shard remove we are actually just clearing #the references, since a shard cannot be removed unless #it is disabled and when it is disabled the replication is #stopped but the references are not cleared. if not update_only: #The Group ID needs to be fetched before the sharding #information is removed. group_id = Shards.fetch(shard.shard_id).group_id _stop_shard_group_replication(shard_id, True) range_sharding_specification.remove() shard.remove() if not update_only: SHARD_METADATA.drop_shard_meta_data(group_id) _LOGGER.debug("Removed Shard (%s).", shard_id)
def _undo_remove_shard(shard_id, update_only=False): """Recreate the shard metadata. :param shard_id: The ID of the shard that was being removed. :param update_only: Only update the state store and skip adding range checks. """ if update_only: return group_id = Shards.fetch(shard_id).group_id try: SHARD_METADATA.create_shard_meta_data(group_id) except _errors.DatabaseError as error: #If the create fails, do not insert the metadata. return spec_handler = SHARDING_SPECIFICATION_HANDLER[shard_type] upper_bound = spec_handler.get_upper_bound( shard.lower_bound, shard_mapping_id, shard_type ) SHARD_METADATA.insert_shard_meta_data(shard.shard_id, shard.lower_bound, upper_bound, group_id)
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. """ return Shards.dump_shard_indexes(connector_version, patterns)
def _lookup(lookup_arg, key, hint): """Given a table name and a key return the servers of the Group where the shard of this table can be found :param lookup_arg: table name for "LOCAL" lookups Shard Mapping ID for "GLOBAL" lookups. :param key: The key value that needs to be looked up :param hint: A hint indicates if the query is LOCAL or GLOBAL :return: The servers of the Group that contains the range in which the key belongs. """ VALID_HINTS = ('LOCAL', 'GLOBAL') hint = hint.upper() if hint not in VALID_HINTS: raise _errors.ShardingError(INVALID_SHARDING_HINT) group = None #Perform the lookup for the group contaning the lookup data. if hint == "GLOBAL": #Fetch the shard mapping object. In the case of GLOBAL lookups #the shard mapping ID is passed directly. In the case of "LOCAL" #lookups it is the table name that is passed. shard_mapping = ShardMapping.fetch_by_id(lookup_arg) if shard_mapping is None: raise _errors.ShardingError( SHARD_MAPPING_NOT_FOUND % (lookup_arg, ) ) #GLOBAL lookups. There can be only one global group, hence using #shard_mapping[0] is safe. group = Group.fetch(shard_mapping[0].global_group) else: shard_mapping = ShardMapping.fetch(lookup_arg) if shard_mapping is None: raise _errors.ShardingError(TABLE_NAME_NOT_FOUND % (lookup_arg, )) sharding_specification =\ SHARDING_SPECIFICATION_HANDLER[shard_mapping.type_name].\ lookup(key, shard_mapping.shard_mapping_id, shard_mapping.type_name) if sharding_specification is None: raise _errors.ShardingError(INVALID_SHARDING_KEY % (key, )) shard = Shards.fetch(str(sharding_specification.shard_id)) if shard.state == "DISABLED": raise _errors.ShardingError(SHARD_NOT_ENABLED) #group cannot be None since there is a foreign key on the group_id. #An exception will be thrown nevertheless. group = Group.fetch(shard.group_id) if group is None: raise _errors.ShardingError(SHARD_LOCATION_NOT_FOUND) ret = [] #An empty list will be returned if the registered group has not #servers. for server in group.servers(): ret.append([str(server.uuid), server.address, group.master == server.uuid]) return ret
def verify_and_fetch_shard(shard_id): """Find out if the shard_id exists and return the sharding specification for it. If it does not exist throw an exception. :param shard_id: The ID for the shard whose specification needs to be fetched. :return: The sharding specification class representing the shard ID. :raises: ShardingError if the shard ID is not found. """ #Here the underlying sharding specification might be a RANGE #or a HASH. The type of sharding specification is obtained from the #shard mapping. range_sharding_spec = RangeShardingSpecification.fetch(shard_id) if range_sharding_spec is None: raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id, )) #Fetch the shard mappings and use them to find the type of sharding #scheme. shard_mappings = ShardMapping.fetch_by_id( range_sharding_spec.shard_mapping_id ) if shard_mappings is None: raise _errors.ShardingError( SHARD_MAPPING_NOT_FOUND % ( range_sharding_spec.shard_mapping_id, ) ) #Fetch the shard mapping definition. There is only one shard mapping #definition associated with all of the shard mappings. shard_mapping_defn = ShardMapping.fetch_shard_mapping_defn( range_sharding_spec.shard_mapping_id ) if shard_mapping_defn is None: raise _errors.ShardingError( SHARD_MAPPING_DEFN_NOT_FOUND % ( range_sharding_spec.shard_mapping_id, ) ) shard = Shards.fetch(shard_id) if shard is None: raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id, )) #Both of the shard_mappings retrieved will be of the same sharding #type. Hence it is safe to use one of them to retireve the sharding type. if shard_mappings[0].type_name == "HASH": return HashShardingSpecification.fetch(shard_id), \ shard, shard_mappings, shard_mapping_defn else: return range_sharding_spec, shard, shard_mappings, shard_mapping_defn
def _undo_add_shard_range_check(shard_mapping_id, shard_type): """Remove the shard ranges in the metadata tables of the shards :param shard_mapping_id: The shard mapping ID of the shards for which the metadata needs to be added. :param shard_type: The datatype of the sharding definition. """ shard_list = SHARDING_SPECIFICATION_HANDLER[shard_type].list(shard_mapping_id) for shard in shard_list: group_id = Shards.fetch(shard.shard_id).group_id SHARD_METADATA.delete_shard_meta_data(group_id, shard.shard_id) SHARD_METADATA.drop_shard_meta_data(group_id)
def _undo_add_shard_range_check(shard_mapping_id, shard_type): """Remove the shard ranges in the metadata tables of the shards :param shard_mapping_id: The shard mapping ID of the shards for which the metadata needs to be added. :param shard_type: The datatype of the sharding definition. """ shard_list = SHARDING_SPECIFICATION_HANDLER[shard_type].list( shard_mapping_id) for shard in shard_list: group_id = Shards.fetch(shard.shard_id).group_id SHARD_METADATA.delete_shard_meta_data(group_id, shard.shard_id) SHARD_METADATA.drop_shard_meta_data(group_id)
def _lookup(lookup_arg, key, hint): """Given a table name and a key return the servers of the Group where the shard of this table can be found :param lookup_arg: table name for "LOCAL" lookups Shard Mapping ID for "GLOBAL" lookups. :param key: The key value that needs to be looked up :param hint: A hint indicates if the query is LOCAL or GLOBAL :return: The servers of the Group that contains the range in which the key belongs. """ VALID_HINTS = ('LOCAL', 'GLOBAL') hint = hint.upper() if hint not in VALID_HINTS: raise _errors.ShardingError(INVALID_SHARDING_HINT) group = None #Perform the lookup for the group contaning the lookup data. if hint == "GLOBAL": #Fetch the shard mapping object. In the case of GLOBAL lookups #the shard mapping ID is passed directly. In the case of "LOCAL" #lookups it is the table name that is passed. shard_mapping = ShardMapping.fetch_by_id(lookup_arg) if shard_mapping is None: raise _errors.ShardingError(SHARD_MAPPING_NOT_FOUND % (lookup_arg, )) #GLOBAL lookups. There can be only one global group, hence using #shard_mapping[0] is safe. group_id = shard_mapping[0].global_group else: shard_mapping = ShardMapping.fetch(lookup_arg) if shard_mapping is None: raise _errors.ShardingError(TABLE_NAME_NOT_FOUND % (lookup_arg, )) sharding_specification = \ SHARDING_SPECIFICATION_HANDLER[shard_mapping.type_name].\ lookup(key, shard_mapping.shard_mapping_id, shard_mapping.type_name) if sharding_specification is None: raise _errors.ShardingError(INVALID_SHARDING_KEY % (key, )) shard = Shards.fetch(str(sharding_specification.shard_id)) if shard.state == "DISABLED": raise _errors.ShardingError(SHARD_NOT_ENABLED) #group cannot be None since there is a foreign key on the group_id. #An exception will be thrown nevertheless. group_id = shard.group_id return ServerLookups().execute(group_id=group_id)
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 verify_and_fetch_shard(shard_id): """Find out if the shard_id exists and return the sharding specification for it. If it does not exist throw an exception. :param shard_id: The ID for the shard whose specification needs to be fetched. :return: The sharding specification class representing the shard ID. :raises: ShardingError if the shard ID is not found. """ #Here the underlying sharding specification might be a RANGE #or a HASH. The type of sharding specification is obtained from the #shard mapping. range_sharding_spec = RangeShardingSpecification.fetch(shard_id) if range_sharding_spec is None: raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id, )) #Fetch the shard mappings and use them to find the type of sharding #scheme. shard_mappings = ShardMapping.fetch_by_id( range_sharding_spec.shard_mapping_id) if shard_mappings is None: raise _errors.ShardingError(SHARD_MAPPING_NOT_FOUND % (range_sharding_spec.shard_mapping_id, )) #Fetch the shard mapping definition. There is only one shard mapping #definition associated with all of the shard mappings. shard_mapping_defn = ShardMapping.fetch_shard_mapping_defn( range_sharding_spec.shard_mapping_id) if shard_mapping_defn is None: raise _errors.ShardingError(SHARD_MAPPING_DEFN_NOT_FOUND % (range_sharding_spec.shard_mapping_id, )) shard = Shards.fetch(shard_id) if shard is None: raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id, )) #Both of the shard_mappings retrieved will be of the same sharding #type. Hence it is safe to use one of them to retireve the sharding type. if shard_mappings[0].type_name == "HASH": return HashShardingSpecification.fetch(shard_id), \ shard, shard_mappings, shard_mapping_defn else: return range_sharding_spec, shard, shard_mappings, shard_mapping_defn
def _undo_remove_shard(shard_id, update_only=False): """Recreate the shard metadata. :param shard_id: The ID of the shard that was being removed. :param update_only: Only update the state store and skip adding range checks. """ if update_only: return group_id = Shards.fetch(shard_id).group_id try: SHARD_METADATA.create_shard_meta_data(group_id) except _errors.DatabaseError as error: #If the create fails, do not insert the metadata. return spec_handler = SHARDING_SPECIFICATION_HANDLER[shard_type] upper_bound = spec_handler.get_upper_bound(shard.lower_bound, shard_mapping_id, shard_type) SHARD_METADATA.insert_shard_meta_data(shard.shard_id, shard.lower_bound, upper_bound, group_id)
def _add_shard_range_check(shard_mapping_id, shard_type): """Add the shard ranges in the metadata tables of the shards :param shard_mapping_id: The shard mapping ID of the shards for which the metadata needs to be added. :param shard_type: The datatype of the sharding definition. """ shard_list = SHARDING_SPECIFICATION_HANDLER[shard_type].list( shard_mapping_id) for shard in shard_list: group_id = Shards.fetch(shard.shard_id).group_id #The metadata has to be created before adding the ranges because #the global group might have still not replicated the schema to the #shard group. If the replication has still not happened, adding #the bounds will throw an error. SHARD_METADATA.create_shard_meta_data(group_id) spec_handler = SHARDING_SPECIFICATION_HANDLER[shard_type] upper_bound = spec_handler.get_upper_bound(shard.lower_bound, shard_mapping_id, shard_type) SHARD_METADATA.insert_shard_meta_data(shard.shard_id, shard.lower_bound, upper_bound, group_id)
def setUp(self): self.manager, self.proxy = tests.utils.setup_xmlrpc() self.__options_1 = { "uuid": _uuid.UUID("{aa75b12b-98d1-414c-96af-9e9d4b179678}"), "address": MySQLInstances().get_address(0), "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } uuid_server1 = MySQLServer.discover_uuid(self.__options_1["address"]) self.__options_1["uuid"] = _uuid.UUID(uuid_server1) self.__server_1 = MySQLServer(**self.__options_1) MySQLServer.add(self.__server_1) self.__group_1 = Group("GROUPID1", "First description.") Group.add(self.__group_1) self.__group_1.add_server(self.__server_1) tests.utils.configure_decoupled_master(self.__group_1, self.__server_1) self.__options_2 = { "uuid": _uuid.UUID("{aa45b12b-98d1-414c-96af-9e9d4b179678}"), "address": MySQLInstances().get_address(1), "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } uuid_server2 = MySQLServer.discover_uuid(self.__options_2["address"]) self.__options_2["uuid"] = _uuid.UUID(uuid_server2) self.__server_2 = MySQLServer(**self.__options_2) MySQLServer.add(self.__server_2) self.__server_2.connect() self.__server_2.exec_stmt("DROP DATABASE IF EXISTS db1") self.__server_2.exec_stmt("CREATE DATABASE db1") self.__server_2.exec_stmt("CREATE TABLE db1.t1" "(userID INT, name VARCHAR(30))") for i in range(1, 501): self.__server_2.exec_stmt("INSERT INTO db1.t1 " "VALUES(%s, 'TEST %s')" % (i, i)) self.__group_2 = Group("GROUPID2", "Second description.") Group.add(self.__group_2) self.__group_2.add_server(self.__server_2) tests.utils.configure_decoupled_master(self.__group_2, self.__server_2) self.__options_3 = { "uuid": _uuid.UUID("{bb75b12b-98d1-414c-96af-9e9d4b179678}"), "address": MySQLInstances().get_address(2), "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } uuid_server3 = MySQLServer.discover_uuid(self.__options_3["address"]) self.__options_3["uuid"] = _uuid.UUID(uuid_server3) self.__server_3 = MySQLServer(**self.__options_3) MySQLServer.add(self.__server_3) self.__server_3.connect() self.__server_3.exec_stmt("DROP DATABASE IF EXISTS db1") self.__server_3.exec_stmt("CREATE DATABASE db1") self.__server_3.exec_stmt("CREATE TABLE db1.t1" "(userID INT, name VARCHAR(30))") for i in range(1, 501): self.__server_3.exec_stmt("INSERT INTO db1.t1 " "VALUES(%s, 'TEST %s')" % (i, i)) self.__group_3 = Group("GROUPID3", "Third description.") Group.add(self.__group_3) self.__group_3.add_server(self.__server_3) tests.utils.configure_decoupled_master(self.__group_3, self.__server_3) self.__options_4 = { "uuid": _uuid.UUID("{bb45b12b-98d1-414c-96af-9e9d4b179678}"), "address": MySQLInstances().get_address(3), "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } uuid_server4 = MySQLServer.discover_uuid(self.__options_4["address"]) self.__options_4["uuid"] = _uuid.UUID(uuid_server4) self.__server_4 = MySQLServer(**self.__options_4) MySQLServer.add(self.__server_4) self.__server_4.connect() self.__server_4.exec_stmt("DROP DATABASE IF EXISTS db1") self.__server_4.exec_stmt("CREATE DATABASE db1") self.__server_4.exec_stmt("CREATE TABLE db1.t1" "(userID INT, name VARCHAR(30))") for i in range(1, 501): self.__server_4.exec_stmt("INSERT INTO db1.t1 " "VALUES(%s, 'TEST %s')" % (i, i)) self.__group_4 = Group("GROUPID4", "Fourth description.") Group.add(self.__group_4) self.__group_4.add_server(self.__server_4) tests.utils.configure_decoupled_master(self.__group_4, self.__server_4) self.__options_5 = { "uuid": _uuid.UUID("{cc75b12b-98d1-414c-96af-9e9d4b179678}"), "address": MySQLInstances().get_address(4), "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } uuid_server5 = MySQLServer.discover_uuid(self.__options_5["address"]) self.__options_5["uuid"] = _uuid.UUID(uuid_server5) self.__server_5 = MySQLServer(**self.__options_5) MySQLServer.add(self.__server_5) self.__server_5.connect() self.__server_5.exec_stmt("DROP DATABASE IF EXISTS db1") self.__server_5.exec_stmt("CREATE DATABASE db1") self.__server_5.exec_stmt("CREATE TABLE db1.t1" "(userID INT, name VARCHAR(30))") for i in range(1, 501): self.__server_5.exec_stmt("INSERT INTO db1.t1 " "VALUES(%s, 'TEST %s')" % (i, i)) self.__group_5 = Group("GROUPID5", "Fifth description.") Group.add(self.__group_5) self.__group_5.add_server(self.__server_5) tests.utils.configure_decoupled_master(self.__group_5, self.__server_5) self.__options_6 = { "uuid": _uuid.UUID("{cc45b12b-98d1-414c-96af-9e9d4b179678}"), "address": MySQLInstances().get_address(5), "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } uuid_server6 = MySQLServer.discover_uuid(self.__options_6["address"]) self.__options_6["uuid"] = _uuid.UUID(uuid_server6) self.__server_6 = MySQLServer(**self.__options_6) MySQLServer.add(self.__server_6) self.__server_6.connect() self.__server_6.exec_stmt("DROP DATABASE IF EXISTS db1") self.__server_6.exec_stmt("CREATE DATABASE db1") self.__server_6.exec_stmt("CREATE TABLE db1.t1" "(userID INT, name VARCHAR(30))") for i in range(1, 501): self.__server_6.exec_stmt("INSERT INTO db1.t1 " "VALUES(%s, 'TEST %s')" % (i, i)) self.__group_6 = Group("GROUPID6", "Sixth description.") Group.add(self.__group_6) self.__group_6.add_server(self.__server_6) tests.utils.configure_decoupled_master(self.__group_6, self.__server_6) self.__shard_mapping_list = ShardMapping.list_shard_mapping_defn() self.assertEquals(self.__shard_mapping_list, []) self.__shard_mapping_id_1 = ShardMapping.define("HASH", "GROUPID1") self.__shard_mapping_1 = ShardMapping.add(self.__shard_mapping_id_1, "db1.t1", "userID") self.__shard_1 = Shards.add("GROUPID2") self.__shard_2 = Shards.add("GROUPID3") self.__shard_3 = Shards.add("GROUPID4") self.__shard_4 = Shards.add("GROUPID5") self.__shard_5 = Shards.add("GROUPID6") self.__hash_sharding_specification_1 = HashShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, self.__shard_1.shard_id) self.__hash_sharding_specification_2 = HashShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, self.__shard_2.shard_id) self.__hash_sharding_specification_3 = HashShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, self.__shard_3.shard_id) self.__hash_sharding_specification_4 = HashShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, self.__shard_4.shard_id) self.__hash_sharding_specification_5 = HashShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, self.__shard_5.shard_id)
def _add_shard(shard_mapping_id, groupid_lb_list, state, update_only=False): """Add the RANGE shard specification. This represents a single instance of a shard specification that maps a key RANGE to a server. :param shard_mapping_id: The unique identification for a shard mapping. :param groupid_lb_list: The list of group_id, lower_bounds pairs in the format, group_id/lower_bound, group_id/lower_bound... . :param state: Indicates whether a given shard is ENABLED or DISABLED :param update_only: Only update the state store and skip adding range checks. :return: True if the add succeeded. False otherwise. :raises: ShardingError If the group on which the shard is being created does not exist, If the shard_mapping_id is not found, If adding the shard definition fails, If the state of the shard is an invalid value, If the range definition is invalid. """ shard_mapping = ShardMapping.fetch_shard_mapping_defn(shard_mapping_id) if shard_mapping is None: raise _errors.ShardingError(SHARD_MAPPING_NOT_FOUND % \ (shard_mapping_id, )) schema_type = shard_mapping[1] if len(RangeShardingSpecification.list(shard_mapping_id)) != 0: raise _errors.ShardingError(SHARDS_ALREADY_EXIST) group_id_list, lower_bound_list = \ _utils.get_group_lower_bound_list(groupid_lb_list) if (len(group_id_list) != len(lower_bound_list)) and\ schema_type == "RANGE": raise _errors.ShardingError(LOWER_BOUND_GROUP_ID_COUNT_MISMATCH) if len(lower_bound_list) != 0 and schema_type == "HASH": raise _errors.ShardingError(LOWER_BOUND_AUTO_GENERATED) if schema_type in Shards.VALID_RANGE_SHARDING_TYPES: for lower_bound in lower_bound_list: if not SHARDING_DATATYPE_HANDLER[schema_type].\ is_valid_lower_bound(lower_bound): raise _errors.ShardingError( INVALID_LOWER_BOUND_VALUE % (lower_bound, )) state = state.upper() if state not in Shards.VALID_SHARD_STATES: raise _errors.ShardingError(INVALID_SHARD_STATE % (state, )) for index, group_id in enumerate(group_id_list): shard = Shards.add(group_id, state) shard_id = shard.shard_id if schema_type == "HASH": HashShardingSpecification.add( shard_mapping_id, shard_id ) _LOGGER.debug( "Added Shard (map id = %s, id = %s).", shard_mapping_id, shard_id ) else: range_sharding_specification = \ SHARDING_SPECIFICATION_HANDLER[schema_type].add( shard_mapping_id, lower_bound_list[index], shard_id ) _LOGGER.debug( "Added Shard (map id = %s, lower bound = %s, id = %s).", range_sharding_specification.shard_mapping_id, range_sharding_specification.lower_bound, range_sharding_specification.shard_id ) if not update_only: #If the shard is added in a DISABLED state do not setup replication #with the primary of the global group. Basically setup replication only #if the shard is ENABLED. if state == "ENABLED": _setup_shard_group_replication(shard_id) if not update_only: #Add the shard limits into the metadata present in each of the shards. _events.trigger_within_procedure( ADD_SHARD_RANGE_CHECK, shard_mapping_id, schema_type )
def setUp(self): """Configure the existing environment """ self.manager, self.proxy = tests.utils.setup_xmlrpc() self.__options_1 = { "uuid": _uuid.UUID("{bb75b12b-98d1-414c-96af-9e9d4b179678}"), "address": "server_1.mysql.com:3060", "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } self.__server_1 = MySQLServer(**self.__options_1) MySQLServer.add(self.__server_1) self.__options_2 = { "uuid": _uuid.UUID("{aa75a12a-98d1-414c-96af-9e9d4b179678}"), "address": "server_2.mysql.com:3060", "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } self.__server_2 = MySQLServer(**self.__options_2) MySQLServer.add(self.__server_2) self.__group_1 = Group("GROUPID1", "First description.") Group.add(self.__group_1) self.__group_1.add_server(self.__server_1) self.__group_1.add_server(self.__server_2) self.__options_3 = { "uuid": _uuid.UUID("{cc75b12b-98d1-414c-96af-9e9d4b179678}"), "address": MySQLInstances().get_address(0), "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } uuid_server3 = MySQLServer.discover_uuid(self.__options_3["address"]) self.__options_3["uuid"] = _uuid.UUID(uuid_server3) self.__server_3 = MySQLServer(**self.__options_3) MySQLServer.add(self.__server_3) self.__options_4 = { "uuid": _uuid.UUID("{dd75a12a-98d1-414c-96af-9e9d4b179678}"), "address": "server_4.mysql.com:3060", "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } self.__server_4 = MySQLServer(**self.__options_4) MySQLServer.add(self.__server_4) self.__group_2 = Group("GROUPID2", "Second description.") Group.add(self.__group_2) self.__group_2.add_server(self.__server_3) self.__group_2.add_server(self.__server_4) tests.utils.configure_decoupled_master(self.__group_2, self.__server_3) self.__options_5 = { "uuid": _uuid.UUID("{ee75b12b-98d1-414c-96af-9e9d4b179678}"), "address": MySQLInstances().get_address(2), "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } uuid_server5 = MySQLServer.discover_uuid(self.__options_5["address"]) self.__options_5["uuid"] = _uuid.UUID(uuid_server5) self.__server_5 = MySQLServer(**self.__options_5) MySQLServer.add(self.__server_5) self.__options_6 = { "uuid": _uuid.UUID("{ff75a12a-98d1-414c-96af-9e9d4b179678}"), "address": "server_6.mysql.com:3060", "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } self.__server_6 = MySQLServer(**self.__options_6) MySQLServer.add(self.__server_6) self.__group_3 = Group("GROUPID3", "Third description.") Group.add(self.__group_3) self.__group_3.add_server(self.__server_5) self.__group_3.add_server(self.__server_6) tests.utils.configure_decoupled_master(self.__group_3, self.__server_5) self.__options_1_host, self.__options_1_port = \ server_utils.split_host_port(self.__options_1["address"], 13001) self.__options_2_host, self.__options_2_port = \ server_utils.split_host_port(self.__options_2["address"], 13001) self.__options_3_host, self.__options_3_port = \ server_utils.split_host_port(self.__options_3["address"], 13001) self.__options_4_host, self.__options_4_port = \ server_utils.split_host_port(self.__options_4["address"], 13001) self.__options_5_host, self.__options_5_port = \ server_utils.split_host_port(self.__options_5["address"], 13001) self.__options_6_host, self.__options_6_port = \ server_utils.split_host_port(self.__options_6["address"], 13001) group_4 = Group("GROUPID4", "4TH description.") Group.add(group_4) group_5 = Group("GROUPID5", "5TH description.") Group.add(group_5) group_6 = Group("GROUPID6", "6TH description.") Group.add(group_6) group_7 = Group("GROUPID7", "7TH description.") Group.add(group_7) group_8 = Group("GROUPID8", "8TH description.") Group.add(group_8) group_9 = Group("GROUPID9", "9TH description.") Group.add(group_9) group_10 = Group("GROUPID10", "10TH description.") Group.add(group_10) group_11 = Group("GROUPID11", "11TH description.") Group.add(group_11) group_12 = Group("GROUPID12", "12TH description.") Group.add(group_12) group_13 = Group("GROUPID13", "13TH description.") Group.add(group_13) group_14 = Group("GROUPID14", "14TH description.") Group.add(group_14) self.__shard_mapping_list = ShardMapping.list_shard_mapping_defn() self.assertEquals(self.__shard_mapping_list, []) self.__shard_mapping_id_1 = ShardMapping.define("RANGE", "GROUPID10") self.__shard_mapping_id_2 = ShardMapping.define("RANGE", "GROUPID11") self.__shard_mapping_id_3 = ShardMapping.define("RANGE", "GROUPID12") #Test with sharding type values in lower case self.__shard_mapping_id_4 = ShardMapping.define("range", "GROUPID13") self.__shard_mapping_id_5 = ShardMapping.define("range", "GROUPID14") self.__shard_mapping_1 = \ ShardMapping.add(self.__shard_mapping_id_1, "db1.t1", "userID1") self.__shard_mapping_2 = \ ShardMapping.add(self.__shard_mapping_id_2, "db2.t2", "userID2") self.__shard_mapping_3 = \ ShardMapping.add(self.__shard_mapping_id_3, "db3.t3", "userID3") self.__shard_mapping_4 = \ ShardMapping.add(self.__shard_mapping_id_4, "db4.t4", "userID4") self.__shard_mapping_5 = \ ShardMapping.add(self.__shard_mapping_id_5, "prune_db.prune_table", "userID") self.__shard_id_1 = Shards.add("GROUPID1", "ENABLED") self.__shard_id_2 = Shards.add("GROUPID10", "ENABLED") self.__shard_id_3 = Shards.add("GROUPID11", "DISABLED") self.__shard_id_4 = Shards.add("GROUPID4", "ENABLED") self.__shard_id_5 = Shards.add("GROUPID5", "ENABLED") self.__shard_id_6 = Shards.add("GROUPID6", "ENABLED") self.__shard_id_7 = Shards.add("GROUPID7", "ENABLED") self.__shard_id_8 = Shards.add("GROUPID8", "ENABLED") self.__shard_id_9 = Shards.add("GROUPID9", "ENABLED") self.__shard_id_10 = Shards.add("GROUPID2", "ENABLED") self.__shard_id_11 = Shards.add("GROUPID3", "ENABLED") self.__range_sharding_specification_1 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 0, self.__shard_id_1.shard_id) self.__range_sharding_specification_2 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 1001, self.__shard_id_2.shard_id) self.__range_sharding_specification_3 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 2001, self.__shard_id_3.shard_id) self.__range_sharding_specification_4 = RangeShardingSpecification.add( self.__shard_mapping_2.shard_mapping_id, 3001, self.__shard_id_4.shard_id) self.__range_sharding_specification_5 = RangeShardingSpecification.add( self.__shard_mapping_2.shard_mapping_id, 4001, self.__shard_id_5.shard_id) self.__range_sharding_specification_6 = RangeShardingSpecification.add( self.__shard_mapping_3.shard_mapping_id, 6001, self.__shard_id_6.shard_id) self.__range_sharding_specification_7 = RangeShardingSpecification.add( self.__shard_mapping_3.shard_mapping_id, 7001, self.__shard_id_7.shard_id) self.__range_sharding_specification_8 = RangeShardingSpecification.add( self.__shard_mapping_4.shard_mapping_id, 8001, self.__shard_id_8.shard_id) self.__range_sharding_specification_9 = RangeShardingSpecification.add( self.__shard_mapping_4.shard_mapping_id, 10001, self.__shard_id_9.shard_id) self.__range_sharding_specification_10 = RangeShardingSpecification.add( self.__shard_mapping_5.shard_mapping_id, 100, self.__shard_id_10.shard_id) self.__range_sharding_specification_11 = RangeShardingSpecification.add( self.__shard_mapping_5.shard_mapping_id, 201, self.__shard_id_11.shard_id) READ_ONLY = MySQLServer.get_mode_idx(MySQLServer.READ_ONLY) READ_WRITE = MySQLServer.get_mode_idx(MySQLServer.READ_WRITE) SECONDARY = MySQLServer.get_status_idx(MySQLServer.SECONDARY) PRIMARY = MySQLServer.get_status_idx(MySQLServer.PRIMARY) self.__setofservers = tests.utils.make_servers_result( [[ str(self.__server_1.uuid), 'GROUPID1', self.__options_1_host, self.__options_1_port, READ_ONLY, SECONDARY, 1.0 ], [ str(self.__server_2.uuid), 'GROUPID1', self.__options_2_host, self.__options_2_port, READ_ONLY, SECONDARY, 1.0 ], [ str(self.__server_3.uuid), 'GROUPID2', self.__options_3_host, self.__options_3_port, READ_WRITE, PRIMARY, 1.0 ], [ str(self.__server_4.uuid), 'GROUPID2', self.__options_4_host, self.__options_4_port, READ_ONLY, SECONDARY, 1.0 ], [ str(self.__server_5.uuid), 'GROUPID3', self.__options_5_host, self.__options_5_port, READ_WRITE, PRIMARY, 1.0 ], [ str(self.__server_6.uuid), 'GROUPID3', self.__options_6_host, self.__options_6_port, READ_ONLY, SECONDARY, 1.0 ]]) self.__setofservers_1 = tests.utils.make_servers_result( [[ str(self.__server_1.uuid), 'GROUPID1', self.__options_1_host, self.__options_1_port, READ_ONLY, SECONDARY, 1.0 ], [ str(self.__server_2.uuid), 'GROUPID1', self.__options_2_host, self.__options_2_port, READ_ONLY, SECONDARY, 1.0 ]]) self.__setofservers_2 = tests.utils.make_servers_result( [[ str(self.__server_1.uuid), 'GROUPID1', self.__options_1_host, self.__options_1_port, READ_ONLY, SECONDARY, 1.0 ], [ str(self.__server_2.uuid), 'GROUPID1', self.__options_2_host, self.__options_2_port, READ_ONLY, SECONDARY, 1.0 ], [ str(self.__server_3.uuid), 'GROUPID2', self.__options_3_host, self.__options_3_port, READ_WRITE, PRIMARY, 1.0 ], [ str(self.__server_4.uuid), 'GROUPID2', self.__options_4_host, self.__options_4_port, READ_ONLY, SECONDARY, 1.0 ]]) self.__setofservers_3 = tests.utils.make_servers_result( [[ str(self.__server_1.uuid), 'GROUPID1', self.__options_1_host, self.__options_1_port, READ_ONLY, SECONDARY, 1.0 ], [ str(self.__server_2.uuid), 'GROUPID1', self.__options_2_host, self.__options_2_port, READ_ONLY, SECONDARY, 1.0 ], [ str(self.__server_3.uuid), 'GROUPID2', self.__options_3_host, self.__options_3_port, READ_WRITE, PRIMARY, 1.0 ], [ str(self.__server_4.uuid), 'GROUPID2', self.__options_4_host, self.__options_4_port, READ_ONLY, SECONDARY, 1.0 ], [ str(self.__server_5.uuid), 'GROUPID3', self.__options_5_host, self.__options_5_port, READ_WRITE, PRIMARY, 1.0 ], [ str(self.__server_6.uuid), 'GROUPID3', self.__options_6_host, self.__options_6_port, READ_ONLY, SECONDARY, 1.0 ]]) self.__setoftables = tests.utils.make_tables_result( [['db1', 't1', 'userID1', '1'], ['db2', 't2', 'userID2', '2'], ['db3', 't3', 'userID3', '3'], ['db4', 't4', 'userID4', '4'], ['prune_db', 'prune_table', 'userID', '5']]) self.__setoftables_1 = tests.utils.make_tables_result( [['db1', 't1', 'userID1', '1']]) self.__setoftables_2 = tests.utils.make_tables_result( [['db1', 't1', 'userID1', '1'], ['db2', 't2', 'userID2', '2']]) self.__setoftables_3 = tests.utils.make_tables_result( [['db1', 't1', 'userID1', '1'], ['db2', 't2', 'userID2', '2'], ['db3', 't3', 'userID3', '3']]) self.__setofshardmaps = tests.utils.make_mapping_result( [['1', 'RANGE', 'GROUPID10'], ['2', 'RANGE', 'GROUPID11'], ['3', 'RANGE', 'GROUPID12'], ['4', 'RANGE', 'GROUPID13'], ['5', 'RANGE', 'GROUPID14']]) self.__setofshardmaps_1 = tests.utils.make_mapping_result( [['1', 'RANGE', 'GROUPID10']]) self.__setofshardmaps_2 = tests.utils.make_mapping_result( [['1', 'RANGE', 'GROUPID10'], ['2', 'RANGE', 'GROUPID11']]) self.__setofshardmaps_3 = tests.utils.make_mapping_result( [['1', 'RANGE', 'GROUPID10'], ['2', 'RANGE', 'GROUPID11'], ['3', 'RANGE', 'GROUPID12']]) self.__setofshardindexes = tests.utils.make_index_result( [['0', '1', '1', 'GROUPID1'], ['1001', '1', '2', 'GROUPID10'], ['3001', '2', '4', 'GROUPID4'], ['4001', '2', '5', 'GROUPID5'], ['6001', '3', '6', 'GROUPID6'], ['7001', '3', '7', 'GROUPID7'], ['8001', '4', '8', 'GROUPID8'], ['10001', '4', '9', 'GROUPID9'], ['100', '5', '10', 'GROUPID2'], ['201', '5', '11', 'GROUPID3']]) self.__setofshardindexes_1 = tests.utils.make_index_result( [['0', '1', '1', 'GROUPID1'], ['1001', '1', '2', 'GROUPID10']]) self.__setofshardindexes_3 = tests.utils.make_index_result( [['0', '1', '1', 'GROUPID1'], ['1001', '1', '2', 'GROUPID10'], ['3001', '2', '4', 'GROUPID4'], ['4001', '2', '5', 'GROUPID5'], ['6001', '3', '6', 'GROUPID6'], ['7001', '3', '7', 'GROUPID7']]) self.__setofshardindexes_5 = tests.utils.make_index_result( [['0', '1', '1', 'GROUPID1'], ['1001', '1', '2', 'GROUPID10'], ['3001', '2', '4', 'GROUPID4'], ['4001', '2', '5', 'GROUPID5'], ['6001', '3', '6', 'GROUPID6'], ['7001', '3', '7', 'GROUPID7'], ['8001', '4', '8', 'GROUPID8'], ['10001', '4', '9', 'GROUPID9'], ['100', '5', '10', 'GROUPID2'], ['201', '5', '11', 'GROUPID3']]) self.__shardinginformation_1 = tests.utils.make_info_result( [[ 'db1', 't1', 'userID1', '0', '1', 'RANGE', 'GROUPID1', 'GROUPID10' ], [ 'db1', 't1', 'userID1', '1001', '2', 'RANGE', 'GROUPID10', 'GROUPID10' ]]) self.__shardinginformation_2 = tests.utils.make_info_result( [[ 'db1', 't1', 'userID1', '0', '1', 'RANGE', 'GROUPID1', 'GROUPID10' ], [ 'db1', 't1', 'userID1', '1001', '2', 'RANGE', 'GROUPID10', 'GROUPID10' ], [ 'db2', 't2', 'userID2', '3001', '4', 'RANGE', 'GROUPID4', 'GROUPID11' ], [ 'db2', 't2', 'userID2', '4001', '5', 'RANGE', 'GROUPID5', 'GROUPID11' ]]) self.__shardinginformation_3 = tests.utils.make_info_result( [[ 'db1', 't1', 'userID1', '0', '1', 'RANGE', 'GROUPID1', 'GROUPID10' ], [ 'db1', 't1', 'userID1', '1001', '2', 'RANGE', 'GROUPID10', 'GROUPID10' ], [ 'db2', 't2', 'userID2', '3001', '4', 'RANGE', 'GROUPID4', 'GROUPID11' ], [ 'db2', 't2', 'userID2', '4001', '5', 'RANGE', 'GROUPID5', 'GROUPID11' ], [ 'db3', 't3', 'userID3', '6001', '6', 'RANGE', 'GROUPID6', 'GROUPID12' ], [ 'db3', 't3', 'userID3', '7001', '7', 'RANGE', 'GROUPID7', 'GROUPID12' ]])
def setUp(self): """Configure the existing environment """ self.__options_1 = { "uuid" : _uuid.UUID("{bb75b12b-98d1-414c-96af-9e9d4b179678}"), "address" : "server_1.mysql.com:3060", } self.__server_1 = MySQLServer(**self.__options_1) MySQLServer.add(self.__server_1) self.__options_2 = { "uuid" : _uuid.UUID("{aa75a12a-98d1-414c-96af-9e9d4b179678}"), "address" : "server_2.mysql.com:3060", } self.__server_2 = MySQLServer(**self.__options_2) MySQLServer.add(self.__server_2) self.__group_1 = Group("GROUPID1", "First description.") Group.add(self.__group_1) self.__group_1.add_server(self.__server_1) self.__group_1.add_server(self.__server_2) self.__options_3 = { "uuid" : _uuid.UUID("{cc75b12b-98d1-414c-96af-9e9d4b179678}"), "address" : MySQLInstances().get_address(0), "user" : MySQLInstances().user, "passwd" : MySQLInstances().passwd, } uuid_server3 = MySQLServer.discover_uuid(self.__options_3["address"]) self.__options_3["uuid"] = _uuid.UUID(uuid_server3) self.__server_3 = MySQLServer(**self.__options_3) MySQLServer.add(self.__server_3) self.__server_3.connect() self.__server_3.exec_stmt("DROP DATABASE IF EXISTS prune_db") self.__server_3.exec_stmt("CREATE DATABASE prune_db") self.__server_3.exec_stmt("CREATE TABLE prune_db.prune_table" "(userID INT, name VARCHAR(30))") self.__server_3.exec_stmt("INSERT INTO prune_db.prune_table " "VALUES(101, 'TEST 1')") self.__server_3.exec_stmt("INSERT INTO prune_db.prune_table " "VALUES(202, 'TEST 2')") self.__options_4 = { "uuid" : _uuid.UUID("{dd75a12a-98d1-414c-96af-9e9d4b179678}"), "address" : "server_4.mysql.com:3060", } self.__server_4 = MySQLServer(**self.__options_4) MySQLServer.add(self.__server_4) self.__group_2 = Group("GROUPID2", "Second description.") Group.add(self.__group_2) self.__group_2.add_server(self.__server_3) self.__group_2.add_server(self.__server_4) tests.utils.configure_decoupled_master(self.__group_2, self.__server_3) self.__options_5 = { "uuid" : _uuid.UUID("{ee75b12b-98d1-414c-96af-9e9d4b179678}"), "address" : MySQLInstances().get_address(2), "user" : MySQLInstances().user, "passwd" : MySQLInstances().passwd, } uuid_server5 = MySQLServer.discover_uuid(self.__options_5["address"]) self.__options_5["uuid"] = _uuid.UUID(uuid_server5) self.__server_5 = MySQLServer(**self.__options_5) MySQLServer.add(self.__server_5) self.__server_5.connect() self.__server_5.exec_stmt("DROP DATABASE IF EXISTS prune_db") self.__server_5.exec_stmt("CREATE DATABASE prune_db") self.__server_5.exec_stmt("CREATE TABLE prune_db.prune_table" "(userID INT, name VARCHAR(30))") self.__server_5.exec_stmt("INSERT INTO prune_db.prune_table " "VALUES(101, 'TEST 1')") self.__server_5.exec_stmt("INSERT INTO prune_db.prune_table " "VALUES(202, 'TEST 2')") self.__options_6 = { "uuid" : _uuid.UUID("{ff75a12a-98d1-414c-96af-9e9d4b179678}"), "address" : "server_6.mysql.com:3060", } self.__server_6 = MySQLServer(**self.__options_6) MySQLServer.add(self.__server_6) self.__group_3 = Group("GROUPID3", "Third description.") Group.add(self.__group_3) self.__group_3.add_server(self.__server_5) self.__group_3.add_server(self.__server_6) tests.utils.configure_decoupled_master(self.__group_3, self.__server_5) group_4 = Group("GROUPID4", "4TH description.") Group.add(group_4) group_5 = Group("GROUPID5", "5TH description.") Group.add(group_5) group_6 = Group("GROUPID6", "6TH description.") Group.add(group_6) group_7 = Group("GROUPID7", "7TH description.") Group.add(group_7) group_8 = Group("GROUPID8", "8TH description.") Group.add(group_8) group_9 = Group("GROUPID9", "9TH description.") Group.add(group_9) group_10 = Group("GROUPID10", "10TH description.") Group.add(group_10) group_11 = Group("GROUPID11", "11TH description.") Group.add(group_11) group_12 = Group("GROUPID12", "12TH description.") Group.add(group_12) group_13 = Group("GROUPID13", "13TH description.") Group.add(group_13) group_14 = Group("GROUPID14", "14TH description.") Group.add(group_14) self.__shard_mapping_list = ShardMapping.list_shard_mapping_defn() self.assertEquals( self.__shard_mapping_list, []) self.__shard_mapping_id_1 = ShardMapping.define("RANGE", "GROUPID10") self.__shard_mapping_id_2 = ShardMapping.define("RANGE", "GROUPID11") self.__shard_mapping_id_3 = ShardMapping.define("RANGE", "GROUPID12") #Test with sharding type values in lower case self.__shard_mapping_id_4 = ShardMapping.define("range", "GROUPID13") self.__shard_mapping_id_5 = ShardMapping.define("range", "GROUPID14") self.__shard_mapping_1 = \ ShardMapping.add(self.__shard_mapping_id_1, "db1.t1", "userID1") self.__shard_mapping_2 = \ ShardMapping.add(self.__shard_mapping_id_2, "db2.t2", "userID2") self.__shard_mapping_3 = \ ShardMapping.add(self.__shard_mapping_id_3, "db3.t3", "userID3") self.__shard_mapping_4 = \ ShardMapping.add(self.__shard_mapping_id_4, "db4.t4", "userID4") self.__shard_mapping_5 = \ ShardMapping.add(self.__shard_mapping_id_5, "prune_db.prune_table", "userID") self.__shard_id_1 = Shards.add("GROUPID1") self.__shard_id_2 = Shards.add("GROUPID10") self.__shard_id_3 = Shards.add("GROUPID11") self.__shard_id_4 = Shards.add("GROUPID4") self.__shard_id_5 = Shards.add("GROUPID5") self.__shard_id_6 = Shards.add("GROUPID6") self.__shard_id_7 = Shards.add("GROUPID7") self.__shard_id_8 = Shards.add("GROUPID8") self.__shard_id_9 = Shards.add("GROUPID9") self.__shard_id_10 = Shards.add("GROUPID2") self.__shard_id_11 = Shards.add("GROUPID3") self.__range_sharding_specification_1 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 0, self.__shard_id_1.shard_id ) self.__range_sharding_specification_2 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 1001, self.__shard_id_2.shard_id ) self.__range_sharding_specification_3 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 2001, self.__shard_id_3.shard_id ) self.__range_sharding_specification_4 = RangeShardingSpecification.add( self.__shard_mapping_2.shard_mapping_id, 3001, self.__shard_id_4.shard_id ) self.__range_sharding_specification_5 = RangeShardingSpecification.add( self.__shard_mapping_2.shard_mapping_id, 4001, self.__shard_id_5.shard_id ) self.__range_sharding_specification_6 = RangeShardingSpecification.add( self.__shard_mapping_3.shard_mapping_id, 6001, self.__shard_id_6.shard_id ) self.__range_sharding_specification_7 = RangeShardingSpecification.add( self.__shard_mapping_3.shard_mapping_id, 7001, self.__shard_id_7.shard_id ) self.__range_sharding_specification_8 = RangeShardingSpecification.add( self.__shard_mapping_4.shard_mapping_id, 8001, self.__shard_id_8.shard_id ) self.__range_sharding_specification_9 = RangeShardingSpecification.add( self.__shard_mapping_4.shard_mapping_id, 10001, self.__shard_id_9.shard_id ) self.__range_sharding_specification_10 = RangeShardingSpecification.add( self.__shard_mapping_5.shard_mapping_id, 100, self.__shard_id_10.shard_id) self.__range_sharding_specification_11 = RangeShardingSpecification.add( self.__shard_mapping_5.shard_mapping_id, 201, self.__shard_id_11.shard_id)
def _setup_shard_switch_split(shard_id, source_group_id, destination_group_id, split_value, prune_limit, cmd, update_only): """Setup the moved shard to map to the new group. :param shard_id: The shard ID of the shard that needs to be moved. :param source_group_id: The group_id of the source shard. :param destn_group_id: The ID of the group to which the shard needs to be moved. :param split_value: Indicates the value at which the range for the particular shard will be split. Will be set only for shard split operations. :param prune_limit: The number of DELETEs that should be done in one batch. :param cmd: Indicates the type of re-sharding operation. :update_only: Only update the state store and skip provisioning. """ #Fetch the Range sharding specification. range_sharding_spec, source_shard, shard_mappings, shard_mapping_defn = \ _services_sharding.verify_and_fetch_shard(shard_id) #Disable the old shard source_shard.disable() #Remove the old shard. range_sharding_spec.remove() source_shard.remove() destination_group = Group.fetch(destination_group_id) if destination_group is None: raise _errors.ShardingError(_services_sharding.SHARD_GROUP_NOT_FOUND % (destination_group_id, )) destn_group_master = MySQLServer.fetch(destination_group.master) if destn_group_master is None: raise _errors.ShardingError( _services_sharding.SHARD_GROUP_MASTER_NOT_FOUND) destn_group_master.connect() #Make the destination group as read only to disable updates until the #connectors update their caches, thus avoiding inconsistency. destn_group_master.read_only = True #Add the new shards. Generate new shard IDs for the shard being #split and also for the shard that is created as a result of the split. new_shard_1 = Shards.add(source_shard.group_id, "DISABLED") new_shard_2 = Shards.add(destination_group_id, "DISABLED") #Both of the shard mappings associated with this shard_id should #be of the same sharding type. Hence it is safe to use one of the #shard mappings. if shard_mappings[0].type_name == "HASH": #In the case of a split involving a HASH sharding scheme, #the shard that is split gets a new shard_id, while the split #gets the new computed lower_bound and also a new shard id. #NOTE: How the shard that is split retains its lower_bound. HashShardingSpecification.add_hash_split( range_sharding_spec.shard_mapping_id, new_shard_1.shard_id, range_sharding_spec.lower_bound) HashShardingSpecification.add_hash_split( range_sharding_spec.shard_mapping_id, new_shard_2.shard_id, split_value) else: #Add the new ranges. Note that the shard being split retains #its lower_bound, while the new shard gets the computed, #lower_bound. RangeShardingSpecification.add(range_sharding_spec.shard_mapping_id, range_sharding_spec.lower_bound, new_shard_1.shard_id) RangeShardingSpecification.add(range_sharding_spec.shard_mapping_id, split_value, new_shard_2.shard_id) #The sleep ensures that the connector have refreshed their caches with the #new shards that have been added as a result of the split. time.sleep(_utils.TTL) #The source shard group master would have been marked as read only #during the sync. Remove the read_only flag. source_group = Group.fetch(source_group_id) if source_group is None: raise _errors.ShardingError(_services_sharding.SHARD_GROUP_NOT_FOUND % (source_group_id, )) source_group_master = MySQLServer.fetch(source_group.master) if source_group_master is None: raise _errors.ShardingError( _services_sharding.SHARD_GROUP_MASTER_NOT_FOUND) source_group_master.connect() #Kill all the existing connections on the servers source_group.kill_connections_on_servers() #Allow connections on the source group master source_group_master.read_only = False #Allow connections on the destination group master destn_group_master.read_only = False #Setup replication for the new group from the global server _group_replication.setup_group_replication \ (shard_mapping_defn[2], destination_group_id) #Enable the split shards new_shard_1.enable() new_shard_2.enable() #Trigger changing the mappings for the shard that was copied if not update_only: _events.trigger_within_procedure(PRUNE_SHARDS, new_shard_1.shard_id, new_shard_2.shard_id, prune_limit)
def _check_shard_information(shard_id, destn_group_id, mysqldump_binary, mysqlclient_binary, split_value, config_file, prune_limit, cmd, update_only): """Verify the sharding information before starting a re-sharding operation. :param shard_id: The destination shard ID. :param destn_group_id: The Destination group ID. :param mysqldump_binary: The path to the mysqldump binary. :param mysqlclient_binary: The path to the mysqlclient binary. :param split_value: The point at which the sharding definition should be split. :param config_file: The complete path to the fabric configuration file. :param prune_limit: The number of DELETEs that should be done in one batch. :param cmd: Indicates if it is a split or a move being executed. :param update_only: If the operation is a update only operation. """ if not _services_utils.is_valid_binary(mysqldump_binary): raise _errors.ShardingError( _services_sharding.MYSQLDUMP_NOT_FOUND % mysqldump_binary) if not _services_utils.is_valid_binary(mysqlclient_binary): raise _errors.ShardingError( _services_sharding.MYSQLCLIENT_NOT_FOUND % mysqlclient_binary) if cmd == "SPLIT": range_sharding_spec, _, shard_mappings, _ = \ _services_sharding.verify_and_fetch_shard(shard_id) upper_bound = \ SHARDING_SPECIFICATION_HANDLER[shard_mappings[0].type_name].\ get_upper_bound( range_sharding_spec.lower_bound, range_sharding_spec.shard_mapping_id, shard_mappings[0].type_name ) #If the underlying sharding scheme is a HASH. When a shard is split, #all the tables that are part of the shard, have the same sharding #scheme. All the shard mappings associated with this shard_id will be #of the same sharding type. Hence it is safe to use one of the shard #mappings. if shard_mappings[0].type_name == "HASH": if split_value is not None: raise _errors.ShardingError( _services_sharding.NO_LOWER_BOUND_FOR_HASH_SHARDING ) if upper_bound is None: #While splitting a range, retrieve the next upper bound and #find the mid-point, in the case where the next upper_bound #is unavailable pick the maximum value in the set of values in #the shard. upper_bound = HashShardingSpecification.fetch_max_key(shard_id) #Calculate the split value. split_value = \ SHARDING_DATATYPE_HANDLER[shard_mappings[0].type_name].\ split_value( range_sharding_spec.lower_bound, upper_bound ) elif split_value is not None: if not (SHARDING_DATATYPE_HANDLER[shard_mappings[0].type_name].\ is_valid_split_value( split_value, range_sharding_spec.lower_bound, upper_bound ) ): raise _errors.ShardingError( _services_sharding.INVALID_LOWER_BOUND_VALUE % (split_value, ) ) elif split_value is None: raise _errors.ShardingError( _services_sharding.SPLIT_VALUE_NOT_DEFINED ) #Ensure that the group does not already contain a shard. if Shards.lookup_shard_id(destn_group_id) is not None: raise _errors.ShardingError( _services_sharding.SHARD_MOVE_DESTINATION_NOT_EMPTY % (destn_group_id, ) ) #Fetch the group information for the source shard that #needs to be moved. source_shard = Shards.fetch(shard_id) if source_shard is None: raise _errors.ShardingError( _services_sharding.SHARD_NOT_FOUND % (shard_id, )) #Fetch the group_id and the group that hosts the source shard. source_group_id = source_shard.group_id destn_group = Group.fetch(destn_group_id) if destn_group is None: raise _errors.ShardingError( _services_sharding.SHARD_GROUP_NOT_FOUND % (destn_group_id, )) if not update_only: _events.trigger_within_procedure( BACKUP_SOURCE_SHARD, shard_id, source_group_id, destn_group_id, mysqldump_binary, mysqlclient_binary, split_value, config_file, prune_limit, cmd, update_only ) else: _events.trigger_within_procedure( SETUP_RESHARDING_SWITCH, shard_id, source_group_id, destn_group_id, split_value, prune_limit, cmd, update_only )
def _add_shard(shard_mapping_id, groupid_lb_list, state): """Add the RANGE shard specification. This represents a single instance of a shard specification that maps a key RANGE to a server. :param shard_mapping_id: The unique identification for a shard mapping. :param groupid_lb_list: The list of group_id, lower_bounds pairs in the format, group_id/lower_bound, group_id/lower_bound... . :param state: Indicates whether a given shard is ENABLED or DISABLED :return: True if the add succeeded. False otherwise. :raises: ShardingError If the group on which the shard is being created does not exist, If the shard_mapping_id is not found, If adding the shard definition fails, If the state of the shard is an invalid value, If the range definition is invalid. """ shard_mapping = ShardMapping.fetch_shard_mapping_defn(shard_mapping_id) if shard_mapping is None: raise _errors.ShardingError(SHARD_MAPPING_NOT_FOUND % \ (shard_mapping_id, )) schema_type = shard_mapping[1] if len(RangeShardingSpecification.list(shard_mapping_id)) != 0: raise _errors.ShardingError(SHARDS_ALREADY_EXIST) group_id_list, lower_bound_list = \ _utils.get_group_lower_bound_list(groupid_lb_list) if (len(group_id_list) != len(lower_bound_list)) and\ schema_type == "RANGE": raise _errors.ShardingError(LOWER_BOUND_GROUP_ID_COUNT_MISMATCH) if len(lower_bound_list) != 0 and schema_type == "HASH": raise _errors.ShardingError(LOWER_BOUND_AUTO_GENERATED) if schema_type in Shards.VALID_RANGE_SHARDING_TYPES: for lower_bound in lower_bound_list: if not SHARDING_DATATYPE_HANDLER[schema_type].\ is_valid_lower_bound(lower_bound): raise _errors.ShardingError(INVALID_LOWER_BOUND_VALUE % (lower_bound, )) state = state.upper() if state not in Shards.VALID_SHARD_STATES: raise _errors.ShardingError(INVALID_SHARD_STATE % (state, )) for index, group_id in enumerate(group_id_list): shard = Shards.add(group_id, state) shard_id = shard.shard_id if schema_type == "HASH": HashShardingSpecification.add(shard_mapping_id, shard_id) _LOGGER.debug("Added Shard (map id = %s, id = %s).", shard_mapping_id, shard_id) else: range_sharding_specification = \ SHARDING_SPECIFICATION_HANDLER[schema_type].add( shard_mapping_id, lower_bound_list[index], shard_id ) _LOGGER.debug( "Added Shard (map id = %s, lower bound = %s, id = %s).", range_sharding_specification.shard_mapping_id, range_sharding_specification.lower_bound, range_sharding_specification.shard_id) #If the shard is added in a DISABLED state do not setup replication #with the primary of the global group. Basically setup replication only #if the shard is ENABLED. if state == "ENABLED": _setup_shard_group_replication(shard_id)
def setUp(self): """Configure the existing environment """ self.manager, self.proxy = tests.utils.setup_xmlrpc() self.__options_1 = { "uuid" : _uuid.UUID("{bb75b12b-98d1-414c-96af-9e9d4b179678}"), "address" : "server_1.mysql.com:3060", } self.__server_1 = MySQLServer(**self.__options_1) MySQLServer.add(self.__server_1) self.__options_2 = { "uuid" : _uuid.UUID("{aa75a12a-98d1-414c-96af-9e9d4b179678}"), "address" : "server_2.mysql.com:3060", } self.__server_2 = MySQLServer(**self.__options_2) MySQLServer.add(self.__server_2) self.__group_1 = Group("GROUPID1", "First description.") Group.add(self.__group_1) self.__group_1.add_server(self.__server_1) self.__group_1.add_server(self.__server_2) self.__options_3 = { "uuid" : _uuid.UUID("{cc75b12b-98d1-414c-96af-9e9d4b179678}"), "address" : MySQLInstances().get_address(0), "user" : MySQLInstances().user, "passwd" : MySQLInstances().passwd, } uuid_server3 = MySQLServer.discover_uuid(self.__options_3["address"]) self.__options_3["uuid"] = _uuid.UUID(uuid_server3) self.__server_3 = MySQLServer(**self.__options_3) MySQLServer.add(self.__server_3) self.__options_4 = { "uuid" : _uuid.UUID("{dd75a12a-98d1-414c-96af-9e9d4b179678}"), "address" : "server_4.mysql.com:3060", } self.__server_4 = MySQLServer(**self.__options_4) MySQLServer.add(self.__server_4) self.__group_2 = Group("GROUPID2", "Second description.") Group.add(self.__group_2) self.__group_2.add_server(self.__server_3) self.__group_2.add_server(self.__server_4) tests.utils.configure_decoupled_master(self.__group_2, self.__server_3) self.__options_5 = { "uuid" : _uuid.UUID("{ee75b12b-98d1-414c-96af-9e9d4b179678}"), "address" : MySQLInstances().get_address(2), "user" : MySQLInstances().user, "passwd" : MySQLInstances().passwd, } uuid_server5 = MySQLServer.discover_uuid(self.__options_5["address"]) self.__options_5["uuid"] = _uuid.UUID(uuid_server5) self.__server_5 = MySQLServer(**self.__options_5) MySQLServer.add(self.__server_5) self.__options_6 = { "uuid" : _uuid.UUID("{ff75a12a-98d1-414c-96af-9e9d4b179678}"), "address" : "server_6.mysql.com:3060", } self.__server_6 = MySQLServer(**self.__options_6) MySQLServer.add(self.__server_6) self.__group_3 = Group("GROUPID3", "Third description.") Group.add(self.__group_3) self.__group_3.add_server(self.__server_5) self.__group_3.add_server(self.__server_6) tests.utils.configure_decoupled_master(self.__group_3, self.__server_5) self.__options_1_host, self.__options_1_port = \ server_utils.split_host_port(self.__options_1["address"], 13001) self.__options_2_host, self.__options_2_port = \ server_utils.split_host_port(self.__options_2["address"], 13001) self.__options_3_host, self.__options_3_port = \ server_utils.split_host_port(self.__options_3["address"], 13001) self.__options_4_host, self.__options_4_port = \ server_utils.split_host_port(self.__options_4["address"], 13001) self.__options_5_host, self.__options_5_port = \ server_utils.split_host_port(self.__options_5["address"], 13001) self.__options_6_host, self.__options_6_port = \ server_utils.split_host_port(self.__options_6["address"], 13001) group_4 = Group("GROUPID4", "4TH description.") Group.add(group_4) group_5 = Group("GROUPID5", "5TH description.") Group.add(group_5) group_6 = Group("GROUPID6", "6TH description.") Group.add(group_6) group_7 = Group("GROUPID7", "7TH description.") Group.add(group_7) group_8 = Group("GROUPID8", "8TH description.") Group.add(group_8) group_9 = Group("GROUPID9", "9TH description.") Group.add(group_9) group_10 = Group("GROUPID10", "10TH description.") Group.add(group_10) group_11 = Group("GROUPID11", "11TH description.") Group.add(group_11) group_12 = Group("GROUPID12", "12TH description.") Group.add(group_12) group_13 = Group("GROUPID13", "13TH description.") Group.add(group_13) group_14 = Group("GROUPID14", "14TH description.") Group.add(group_14) self.__shard_mapping_list = ShardMapping.list_shard_mapping_defn() self.assertEquals( self.__shard_mapping_list, []) self.__shard_mapping_id_1 = ShardMapping.define("RANGE", "GROUPID10") self.__shard_mapping_id_2 = ShardMapping.define("RANGE", "GROUPID11") self.__shard_mapping_id_3 = ShardMapping.define("RANGE", "GROUPID12") #Test with sharding type values in lower case self.__shard_mapping_id_4 = ShardMapping.define("range", "GROUPID13") self.__shard_mapping_id_5 = ShardMapping.define("range", "GROUPID14") self.__shard_mapping_1 = \ ShardMapping.add(self.__shard_mapping_id_1, "db1.t1", "userID1") self.__shard_mapping_2 = \ ShardMapping.add(self.__shard_mapping_id_2, "db2.t2", "userID2") self.__shard_mapping_3 = \ ShardMapping.add(self.__shard_mapping_id_3, "db3.t3", "userID3") self.__shard_mapping_4 = \ ShardMapping.add(self.__shard_mapping_id_4, "db4.t4", "userID4") self.__shard_mapping_5 = \ ShardMapping.add(self.__shard_mapping_id_5, "prune_db.prune_table", "userID") self.__shard_id_1 = Shards.add("GROUPID1", "ENABLED") self.__shard_id_2 = Shards.add("GROUPID10", "ENABLED") self.__shard_id_3 = Shards.add("GROUPID11", "DISABLED") self.__shard_id_4 = Shards.add("GROUPID4", "ENABLED") self.__shard_id_5 = Shards.add("GROUPID5", "ENABLED") self.__shard_id_6 = Shards.add("GROUPID6", "ENABLED") self.__shard_id_7 = Shards.add("GROUPID7", "ENABLED") self.__shard_id_8 = Shards.add("GROUPID8", "ENABLED") self.__shard_id_9 = Shards.add("GROUPID9", "ENABLED") self.__shard_id_10 = Shards.add("GROUPID2", "ENABLED") self.__shard_id_11 = Shards.add("GROUPID3", "ENABLED") self.__range_sharding_specification_1 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 0, self.__shard_id_1.shard_id ) self.__range_sharding_specification_2 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 1001, self.__shard_id_2.shard_id ) self.__range_sharding_specification_3 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 2001, self.__shard_id_3.shard_id ) self.__range_sharding_specification_4 = RangeShardingSpecification.add( self.__shard_mapping_2.shard_mapping_id, 3001, self.__shard_id_4.shard_id ) self.__range_sharding_specification_5 = RangeShardingSpecification.add( self.__shard_mapping_2.shard_mapping_id, 4001, self.__shard_id_5.shard_id ) self.__range_sharding_specification_6 = RangeShardingSpecification.add( self.__shard_mapping_3.shard_mapping_id, 6001, self.__shard_id_6.shard_id ) self.__range_sharding_specification_7 = RangeShardingSpecification.add( self.__shard_mapping_3.shard_mapping_id, 7001, self.__shard_id_7.shard_id ) self.__range_sharding_specification_8 = RangeShardingSpecification.add( self.__shard_mapping_4.shard_mapping_id, 8001, self.__shard_id_8.shard_id ) self.__range_sharding_specification_9 = RangeShardingSpecification.add( self.__shard_mapping_4.shard_mapping_id, 10001, self.__shard_id_9.shard_id ) self.__range_sharding_specification_10 = RangeShardingSpecification.add( self.__shard_mapping_5.shard_mapping_id, 100, self.__shard_id_10.shard_id) self.__range_sharding_specification_11 = RangeShardingSpecification.add( self.__shard_mapping_5.shard_mapping_id, 201, self.__shard_id_11.shard_id) READ_ONLY = MySQLServer.get_mode_idx(MySQLServer.READ_ONLY) READ_WRITE = MySQLServer.get_mode_idx(MySQLServer.READ_WRITE) SECONDARY = MySQLServer.get_status_idx(MySQLServer.SECONDARY) PRIMARY = MySQLServer.get_status_idx(MySQLServer.PRIMARY) self.__setofservers = [0, 0, 0, [[str(self.__server_1.uuid), 'GROUPID1', self.__options_1_host, self.__options_1_port, READ_ONLY, SECONDARY, 1.0], [str(self.__server_2.uuid), 'GROUPID1', self.__options_2_host, self.__options_2_port, READ_ONLY, SECONDARY, 1.0], [str(self.__server_3.uuid), 'GROUPID2', self.__options_3_host, self.__options_3_port, READ_WRITE, PRIMARY, 1.0], [str(self.__server_4.uuid), 'GROUPID2', self.__options_4_host, self.__options_4_port, READ_ONLY, SECONDARY, 1.0], [str(self.__server_5.uuid), 'GROUPID3', self.__options_5_host, self.__options_5_port, READ_WRITE, PRIMARY, 1.0], [str(self.__server_6.uuid), 'GROUPID3', self.__options_6_host, self.__options_6_port, READ_ONLY, SECONDARY, 1.0]]] self.__setofservers_1 = [0, 0, 0, [[str(self.__server_1.uuid), 'GROUPID1', self.__options_1_host, self.__options_1_port, READ_ONLY, SECONDARY, 1.0], [str(self.__server_2.uuid), 'GROUPID1', self.__options_2_host, self.__options_2_port, READ_ONLY, SECONDARY, 1.0]]] self.__setofservers_2 = [0, 0, 0, [[str(self.__server_1.uuid), 'GROUPID1', self.__options_1_host, self.__options_1_port, READ_ONLY, SECONDARY, 1.0], [str(self.__server_2.uuid), 'GROUPID1', self.__options_2_host, self.__options_2_port, READ_ONLY, SECONDARY, 1.0], [str(self.__server_3.uuid), 'GROUPID2', self.__options_3_host, self.__options_3_port, READ_WRITE, PRIMARY, 1.0], [str(self.__server_4.uuid), 'GROUPID2', self.__options_4_host, self.__options_4_port, READ_ONLY, SECONDARY, 1.0]]] self.__setofservers_3 = [0, 0, 0, [[str(self.__server_1.uuid), 'GROUPID1', self.__options_1_host, self.__options_1_port, READ_ONLY, SECONDARY, 1.0], [str(self.__server_2.uuid), 'GROUPID1', self.__options_2_host, self.__options_2_port, READ_ONLY, SECONDARY, 1.0], [str(self.__server_3.uuid), 'GROUPID2', self.__options_3_host, self.__options_3_port, READ_WRITE, PRIMARY, 1.0], [str(self.__server_4.uuid), 'GROUPID2', self.__options_4_host, self.__options_4_port, READ_ONLY, SECONDARY, 1.0], [str(self.__server_5.uuid), 'GROUPID3', self.__options_5_host, self.__options_5_port, READ_WRITE, PRIMARY, 1.0], [str(self.__server_6.uuid), 'GROUPID3', self.__options_6_host, self.__options_6_port, READ_ONLY, SECONDARY, 1.0]]] self.__setoftables = [0, 0, 0, [['db1', 't1', 'userID1', '1'], ['db2', 't2', 'userID2', '2'], ['db3', 't3', 'userID3', '3'], ['db4', 't4', 'userID4', '4'], ['prune_db', 'prune_table', 'userID', '5']]] self.__setoftables_1 = [0, 0, 0, [['db1', 't1', 'userID1', '1']]] self.__setoftables_2 = [0, 0, 0, [['db1', 't1', 'userID1', '1'], ['db2', 't2', 'userID2', '2']]] self.__setoftables_3 = [0, 0, 0, [['db1', 't1', 'userID1', '1'], ['db2', 't2', 'userID2', '2'], ['db3', 't3', 'userID3', '3']]] self.__setofshardmaps = [0, 0, 0, [['1', 'RANGE', 'GROUPID10'], ['2', 'RANGE', 'GROUPID11'], ['3', 'RANGE', 'GROUPID12'], ['4', 'RANGE', 'GROUPID13'], ['5', 'RANGE', 'GROUPID14']]] self.__setofshardmaps_1 = [0, 0, 0, [['1', 'RANGE', 'GROUPID10']]] self.__setofshardmaps_2 = [0, 0, 0, [['1', 'RANGE', 'GROUPID10'], ['2', 'RANGE', 'GROUPID11']]] self.__setofshardmaps_3 = [0, 0, 0, [['1', 'RANGE', 'GROUPID10'], ['2', 'RANGE', 'GROUPID11'], ['3', 'RANGE', 'GROUPID12']]] self.__setofshardindexes = [0, 0, 0, [['0', '1', '1', 'GROUPID1'], ['1001', '1', '2', 'GROUPID10'], ['3001', '2', '4', 'GROUPID4'], ['4001', '2', '5', 'GROUPID5'], ['6001', '3', '6', 'GROUPID6'], ['7001', '3', '7', 'GROUPID7'], ['8001', '4', '8', 'GROUPID8'], ['10001', '4', '9', 'GROUPID9'], ['100', '5', '10', 'GROUPID2'], ['201', '5', '11', 'GROUPID3']]] self.__setofshardindexes_1 = [0, 0, 0, [['0', '1', '1', 'GROUPID1'], ['1001', '1', '2', 'GROUPID10']]] self.__setofshardindexes_3 = [0, 0, 0, [['0', '1', '1', 'GROUPID1'], ['1001', '1', '2', 'GROUPID10'], ['3001', '2', '4', 'GROUPID4'], ['4001', '2', '5', 'GROUPID5'], ['6001', '3', '6', 'GROUPID6'], ['7001', '3', '7', 'GROUPID7']]] self.__setofshardindexes_5 = [0, 0, 0, [['0', '1', '1', 'GROUPID1'], ['1001', '1', '2', 'GROUPID10'], ['3001', '2', '4', 'GROUPID4'], ['4001', '2', '5', 'GROUPID5'], ['6001', '3', '6', 'GROUPID6'], ['7001', '3', '7', 'GROUPID7'], ['8001', '4', '8', 'GROUPID8'], ['10001', '4', '9', 'GROUPID9'], ['100', '5', '10', 'GROUPID2'], ['201', '5', '11', 'GROUPID3']]] self.__shardinginformation_1 = [0, 0, 0, [['db1', 't1', 'userID1', '0', '1', 'RANGE', 'GROUPID1', 'GROUPID10'], ['db1', 't1', 'userID1', '1001', '2', 'RANGE', 'GROUPID10', 'GROUPID10']]] self.__shardinginformation_2 = [0, 0, 0, [['db1', 't1', 'userID1', '0', '1', 'RANGE', 'GROUPID1', 'GROUPID10'], ['db1', 't1', 'userID1', '1001', '2', 'RANGE', 'GROUPID10', 'GROUPID10'], ['db2', 't2', 'userID2', '3001', '4', 'RANGE', 'GROUPID4', 'GROUPID11'], ['db2', 't2', 'userID2', '4001', '5', 'RANGE', 'GROUPID5', 'GROUPID11']]] self.__shardinginformation_3 = [0, 0, 0, [['db1', 't1', 'userID1', '0', '1', 'RANGE', 'GROUPID1', 'GROUPID10'], ['db1', 't1', 'userID1', '1001', '2', 'RANGE', 'GROUPID10', 'GROUPID10'], ['db2', 't2', 'userID2', '3001', '4','RANGE', 'GROUPID4', 'GROUPID11'], ['db2', 't2', 'userID2', '4001', '5', 'RANGE', 'GROUPID5', 'GROUPID11'], ['db3', 't3', 'userID3', '6001', '6', 'RANGE', 'GROUPID6', 'GROUPID12'], ['db3', 't3', 'userID3', '7001', '7', 'RANGE', 'GROUPID7', 'GROUPID12']]]
def setUp(self): """Configure the existing environment """ self.__options_1 = { "uuid": _uuid.UUID("{bb75b12b-98d1-414c-96af-9e9d4b179678}"), "address": "server_1.mysql.com:3060", "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } self.__server_1 = MySQLServer(**self.__options_1) MySQLServer.add(self.__server_1) self.__options_2 = { "uuid": _uuid.UUID("{aa75a12a-98d1-414c-96af-9e9d4b179678}"), "address": "server_2.mysql.com:3060", "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } self.__server_2 = MySQLServer(**self.__options_2) MySQLServer.add(self.__server_2) self.__group_1 = Group("GROUPID1", "First description.") Group.add(self.__group_1) self.__group_1.add_server(self.__server_1) self.__group_1.add_server(self.__server_2) self.__options_3 = { "uuid": _uuid.UUID("{cc75b12b-98d1-414c-96af-9e9d4b179678}"), "address": MySQLInstances().get_address(0), "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } uuid_server3 = MySQLServer.discover_uuid(self.__options_3["address"]) self.__options_3["uuid"] = _uuid.UUID(uuid_server3) self.__server_3 = MySQLServer(**self.__options_3) MySQLServer.add(self.__server_3) self.__server_3.connect() self.__server_3.exec_stmt("DROP DATABASE IF EXISTS prune_db") self.__server_3.exec_stmt("CREATE DATABASE prune_db") self.__server_3.exec_stmt("CREATE TABLE prune_db.prune_table" "(userID INT, name VARCHAR(30))") self.__server_3.exec_stmt("INSERT INTO prune_db.prune_table " "VALUES(101, 'TEST 1')") self.__server_3.exec_stmt("INSERT INTO prune_db.prune_table " "VALUES(202, 'TEST 2')") self.__options_4 = { "uuid": _uuid.UUID("{dd75a12a-98d1-414c-96af-9e9d4b179678}"), "address": "server_4.mysql.com:3060", "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } self.__server_4 = MySQLServer(**self.__options_4) MySQLServer.add(self.__server_4) self.__group_2 = Group("GROUPID2", "Second description.") Group.add(self.__group_2) self.__group_2.add_server(self.__server_3) self.__group_2.add_server(self.__server_4) tests.utils.configure_decoupled_master(self.__group_2, self.__server_3) self.__options_5 = { "uuid": _uuid.UUID("{ee75b12b-98d1-414c-96af-9e9d4b179678}"), "address": MySQLInstances().get_address(2), "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } uuid_server5 = MySQLServer.discover_uuid(self.__options_5["address"]) self.__options_5["uuid"] = _uuid.UUID(uuid_server5) self.__server_5 = MySQLServer(**self.__options_5) MySQLServer.add(self.__server_5) self.__server_5.connect() self.__server_5.exec_stmt("DROP DATABASE IF EXISTS prune_db") self.__server_5.exec_stmt("CREATE DATABASE prune_db") self.__server_5.exec_stmt("CREATE TABLE prune_db.prune_table" "(userID INT, name VARCHAR(30))") self.__server_5.exec_stmt("INSERT INTO prune_db.prune_table " "VALUES(101, 'TEST 1')") self.__server_5.exec_stmt("INSERT INTO prune_db.prune_table " "VALUES(202, 'TEST 2')") self.__options_6 = { "uuid": _uuid.UUID("{ff75a12a-98d1-414c-96af-9e9d4b179678}"), "address": "server_6.mysql.com:3060", "user": MySQLInstances().user, "passwd": MySQLInstances().passwd, } self.__server_6 = MySQLServer(**self.__options_6) MySQLServer.add(self.__server_6) self.__group_3 = Group("GROUPID3", "Third description.") Group.add(self.__group_3) self.__group_3.add_server(self.__server_5) self.__group_3.add_server(self.__server_6) tests.utils.configure_decoupled_master(self.__group_3, self.__server_5) group_4 = Group("GROUPID4", "4TH description.") Group.add(group_4) group_5 = Group("GROUPID5", "5TH description.") Group.add(group_5) group_6 = Group("GROUPID6", "6TH description.") Group.add(group_6) group_7 = Group("GROUPID7", "7TH description.") Group.add(group_7) group_8 = Group("GROUPID8", "8TH description.") Group.add(group_8) group_9 = Group("GROUPID9", "9TH description.") Group.add(group_9) group_10 = Group("GROUPID10", "10TH description.") Group.add(group_10) group_11 = Group("GROUPID11", "11TH description.") Group.add(group_11) group_12 = Group("GROUPID12", "12TH description.") Group.add(group_12) group_13 = Group("GROUPID13", "13TH description.") Group.add(group_13) group_14 = Group("GROUPID14", "14TH description.") Group.add(group_14) self.__shard_mapping_list = ShardMapping.list_shard_mapping_defn() self.assertEquals(self.__shard_mapping_list, []) self.__shard_mapping_id_1 = ShardMapping.define("RANGE", "GROUPID10") self.__shard_mapping_id_2 = ShardMapping.define("RANGE", "GROUPID11") self.__shard_mapping_id_3 = ShardMapping.define("RANGE", "GROUPID12") #Test with sharding type values in lower case self.__shard_mapping_id_4 = ShardMapping.define("range", "GROUPID13") self.__shard_mapping_id_5 = ShardMapping.define("range", "GROUPID14") self.__shard_mapping_1 = \ ShardMapping.add(self.__shard_mapping_id_1, "db1.t1", "userID1") self.__shard_mapping_2 = \ ShardMapping.add(self.__shard_mapping_id_2, "db2.t2", "userID2") self.__shard_mapping_3 = \ ShardMapping.add(self.__shard_mapping_id_3, "db3.t3", "userID3") self.__shard_mapping_4 = \ ShardMapping.add(self.__shard_mapping_id_4, "db4.t4", "userID4") self.__shard_mapping_5 = \ ShardMapping.add(self.__shard_mapping_id_5, "prune_db.prune_table", "userID") self.__shard_id_1 = Shards.add("GROUPID1") self.__shard_id_2 = Shards.add("GROUPID10") self.__shard_id_3 = Shards.add("GROUPID11") self.__shard_id_4 = Shards.add("GROUPID4") self.__shard_id_5 = Shards.add("GROUPID5") self.__shard_id_6 = Shards.add("GROUPID6") self.__shard_id_7 = Shards.add("GROUPID7") self.__shard_id_8 = Shards.add("GROUPID8") self.__shard_id_9 = Shards.add("GROUPID9") self.__shard_id_10 = Shards.add("GROUPID2") self.__shard_id_11 = Shards.add("GROUPID3") self.__range_sharding_specification_1 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 0, self.__shard_id_1.shard_id) self.__range_sharding_specification_2 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 1001, self.__shard_id_2.shard_id) self.__range_sharding_specification_3 = RangeShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, 2001, self.__shard_id_3.shard_id) self.__range_sharding_specification_4 = RangeShardingSpecification.add( self.__shard_mapping_2.shard_mapping_id, 3001, self.__shard_id_4.shard_id) self.__range_sharding_specification_5 = RangeShardingSpecification.add( self.__shard_mapping_2.shard_mapping_id, 4001, self.__shard_id_5.shard_id) self.__range_sharding_specification_6 = RangeShardingSpecification.add( self.__shard_mapping_3.shard_mapping_id, 6001, self.__shard_id_6.shard_id) self.__range_sharding_specification_7 = RangeShardingSpecification.add( self.__shard_mapping_3.shard_mapping_id, 7001, self.__shard_id_7.shard_id) self.__range_sharding_specification_8 = RangeShardingSpecification.add( self.__shard_mapping_4.shard_mapping_id, 8001, self.__shard_id_8.shard_id) self.__range_sharding_specification_9 = RangeShardingSpecification.add( self.__shard_mapping_4.shard_mapping_id, 10001, self.__shard_id_9.shard_id) self.__range_sharding_specification_10 = RangeShardingSpecification.add( self.__shard_mapping_5.shard_mapping_id, 100, self.__shard_id_10.shard_id) self.__range_sharding_specification_11 = RangeShardingSpecification.add( self.__shard_mapping_5.shard_mapping_id, 201, self.__shard_id_11.shard_id)
def setUp(self): self.manager, self.proxy = tests.utils.setup_xmlrpc() self.__options_1 = { "uuid" : _uuid.UUID("{aa75b12b-98d1-414c-96af-9e9d4b179678}"), "address" : MySQLInstances().get_address(0), "user" : MySQLInstances().user, "passwd" : MySQLInstances().passwd, } uuid_server1 = MySQLServer.discover_uuid(self.__options_1["address"]) self.__options_1["uuid"] = _uuid.UUID(uuid_server1) self.__server_1 = MySQLServer(**self.__options_1) MySQLServer.add(self.__server_1) self.__group_1 = Group("GROUPID1", "First description.") Group.add(self.__group_1) self.__group_1.add_server(self.__server_1) tests.utils.configure_decoupled_master(self.__group_1, self.__server_1) self.__options_2 = { "uuid" : _uuid.UUID("{aa45b12b-98d1-414c-96af-9e9d4b179678}"), "address" : MySQLInstances().get_address(1), "user" : MySQLInstances().user, "passwd" : MySQLInstances().passwd, } uuid_server2 = MySQLServer.discover_uuid(self.__options_2["address"]) self.__options_2["uuid"] = _uuid.UUID(uuid_server2) self.__server_2 = MySQLServer(**self.__options_2) MySQLServer.add(self.__server_2) self.__server_2.connect() self.__server_2.exec_stmt("DROP DATABASE IF EXISTS db1") self.__server_2.exec_stmt("CREATE DATABASE db1") self.__server_2.exec_stmt("CREATE TABLE db1.t1" "(userID INT, name VARCHAR(30))") for i in range(1, 501): self.__server_2.exec_stmt("INSERT INTO db1.t1 " "VALUES(%s, 'TEST %s')" % (i, i)) self.__group_2 = Group("GROUPID2", "Second description.") Group.add(self.__group_2) self.__group_2.add_server(self.__server_2) tests.utils.configure_decoupled_master(self.__group_2, self.__server_2) self.__options_3 = { "uuid" : _uuid.UUID("{bb75b12b-98d1-414c-96af-9e9d4b179678}"), "address" : MySQLInstances().get_address(2), "user" : MySQLInstances().user, "passwd" : MySQLInstances().passwd, } uuid_server3 = MySQLServer.discover_uuid(self.__options_3["address"]) self.__options_3["uuid"] = _uuid.UUID(uuid_server3) self.__server_3 = MySQLServer(**self.__options_3) MySQLServer.add( self.__server_3) self.__server_3.connect() self.__server_3.exec_stmt("DROP DATABASE IF EXISTS db1") self.__server_3.exec_stmt("CREATE DATABASE db1") self.__server_3.exec_stmt("CREATE TABLE db1.t1" "(userID INT, name VARCHAR(30))") for i in range(1, 501): self.__server_3.exec_stmt("INSERT INTO db1.t1 " "VALUES(%s, 'TEST %s')" % (i, i)) self.__group_3 = Group("GROUPID3", "Third description.") Group.add( self.__group_3) self.__group_3.add_server(self.__server_3) tests.utils.configure_decoupled_master(self.__group_3, self.__server_3) self.__options_4 = { "uuid" : _uuid.UUID("{bb45b12b-98d1-414c-96af-9e9d4b179678}"), "address" : MySQLInstances().get_address(3), "user" : MySQLInstances().user, "passwd" : MySQLInstances().passwd, } uuid_server4 = MySQLServer.discover_uuid(self.__options_4["address"]) self.__options_4["uuid"] = _uuid.UUID(uuid_server4) self.__server_4 = MySQLServer(**self.__options_4) MySQLServer.add(self.__server_4) self.__server_4.connect() self.__server_4.exec_stmt("DROP DATABASE IF EXISTS db1") self.__server_4.exec_stmt("CREATE DATABASE db1") self.__server_4.exec_stmt("CREATE TABLE db1.t1" "(userID INT, name VARCHAR(30))") for i in range(1, 501): self.__server_4.exec_stmt("INSERT INTO db1.t1 " "VALUES(%s, 'TEST %s')" % (i, i)) self.__group_4 = Group("GROUPID4", "Fourth description.") Group.add( self.__group_4) self.__group_4.add_server(self.__server_4) tests.utils.configure_decoupled_master(self.__group_4, self.__server_4) self.__options_5 = { "uuid" : _uuid.UUID("{cc75b12b-98d1-414c-96af-9e9d4b179678}"), "address" : MySQLInstances().get_address(4), "user" : MySQLInstances().user, "passwd" : MySQLInstances().passwd, } uuid_server5 = MySQLServer.discover_uuid(self.__options_5["address"]) self.__options_5["uuid"] = _uuid.UUID(uuid_server5) self.__server_5 = MySQLServer(**self.__options_5) MySQLServer.add(self.__server_5) self.__server_5.connect() self.__server_5.exec_stmt("DROP DATABASE IF EXISTS db1") self.__server_5.exec_stmt("CREATE DATABASE db1") self.__server_5.exec_stmt("CREATE TABLE db1.t1" "(userID INT, name VARCHAR(30))") for i in range(1, 501): self.__server_5.exec_stmt("INSERT INTO db1.t1 " "VALUES(%s, 'TEST %s')" % (i, i)) self.__group_5 = Group("GROUPID5", "Fifth description.") Group.add( self.__group_5) self.__group_5.add_server(self.__server_5) tests.utils.configure_decoupled_master(self.__group_5, self.__server_5) self.__options_6 = { "uuid" : _uuid.UUID("{cc45b12b-98d1-414c-96af-9e9d4b179678}"), "address" : MySQLInstances().get_address(5), "user" : MySQLInstances().user, "passwd" : MySQLInstances().passwd, } uuid_server6 = MySQLServer.discover_uuid(self.__options_6["address"]) self.__options_6["uuid"] = _uuid.UUID(uuid_server6) self.__server_6 = MySQLServer(**self.__options_6) MySQLServer.add(self.__server_6) self.__server_6.connect() self.__server_6.exec_stmt("DROP DATABASE IF EXISTS db1") self.__server_6.exec_stmt("CREATE DATABASE db1") self.__server_6.exec_stmt("CREATE TABLE db1.t1" "(userID INT, name VARCHAR(30))") for i in range(1, 501): self.__server_6.exec_stmt("INSERT INTO db1.t1 " "VALUES(%s, 'TEST %s')" % (i, i)) self.__group_6 = Group("GROUPID6", "Sixth description.") Group.add( self.__group_6) self.__group_6.add_server(self.__server_6) tests.utils.configure_decoupled_master(self.__group_6, self.__server_6) self.__shard_mapping_list = ShardMapping.list_shard_mapping_defn() self.assertEquals( self.__shard_mapping_list, []) self.__shard_mapping_id_1 = ShardMapping.define("HASH", "GROUPID1") self.__shard_mapping_1 = ShardMapping.add( self.__shard_mapping_id_1, "db1.t1", "userID" ) self.__shard_1 = Shards.add("GROUPID2") self.__shard_2 = Shards.add("GROUPID3") self.__shard_3 = Shards.add("GROUPID4") self.__shard_4 = Shards.add("GROUPID5") self.__shard_5 = Shards.add("GROUPID6") self.__hash_sharding_specification_1 = HashShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, self.__shard_1.shard_id ) self.__hash_sharding_specification_2 = HashShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, self.__shard_2.shard_id ) self.__hash_sharding_specification_3 = HashShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, self.__shard_3.shard_id ) self.__hash_sharding_specification_4 = HashShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, self.__shard_4.shard_id ) self.__hash_sharding_specification_5 = HashShardingSpecification.add( self.__shard_mapping_1.shard_mapping_id, self.__shard_5.shard_id )
def _setup_shard_switch_split(shard_id, source_group_id, destination_group_id, split_value, prune_limit, cmd, update_only): """Setup the moved shard to map to the new group. :param shard_id: The shard ID of the shard that needs to be moved. :param source_group_id: The group_id of the source shard. :param destn_group_id: The ID of the group to which the shard needs to be moved. :param split_value: Indicates the value at which the range for the particular shard will be split. Will be set only for shard split operations. :param prune_limit: The number of DELETEs that should be done in one batch. :param cmd: Indicates the type of re-sharding operation. :update_only: Only update the state store and skip provisioning. """ #Fetch the Range sharding specification. range_sharding_spec, source_shard, shard_mappings, shard_mapping_defn = \ _services_sharding.verify_and_fetch_shard(shard_id) #Disable the old shard source_shard.disable() #Remove the old shard. range_sharding_spec.remove() source_shard.remove() destination_group = Group.fetch(destination_group_id) if destination_group is None: raise _errors.ShardingError(_services_sharding.SHARD_GROUP_NOT_FOUND % (destination_group_id, )) destn_group_master = MySQLServer.fetch(destination_group.master) if destn_group_master is None: raise _errors.ShardingError( _services_sharding.SHARD_GROUP_MASTER_NOT_FOUND) destn_group_master.connect() #Make the destination group as read only to disable updates until the #connectors update their caches, thus avoiding inconsistency. destn_group_master.read_only = True #Add the new shards. Generate new shard IDs for the shard being #split and also for the shard that is created as a result of the split. new_shard_1 = Shards.add(source_shard.group_id, "DISABLED") new_shard_2 = Shards.add(destination_group_id, "DISABLED") #Both of the shard mappings associated with this shard_id should #be of the same sharding type. Hence it is safe to use one of the #shard mappings. if shard_mappings[0].type_name == "HASH": #In the case of a split involving a HASH sharding scheme, #the shard that is split gets a new shard_id, while the split #gets the new computed lower_bound and also a new shard id. #NOTE: How the shard that is split retains its lower_bound. HashShardingSpecification.add_hash_split( range_sharding_spec.shard_mapping_id, new_shard_1.shard_id, range_sharding_spec.lower_bound ) HashShardingSpecification.add_hash_split( range_sharding_spec.shard_mapping_id, new_shard_2.shard_id, split_value ) else: #Add the new ranges. Note that the shard being split retains #its lower_bound, while the new shard gets the computed, #lower_bound. RangeShardingSpecification.add( range_sharding_spec.shard_mapping_id, range_sharding_spec.lower_bound, new_shard_1.shard_id ) RangeShardingSpecification.add( range_sharding_spec.shard_mapping_id, split_value, new_shard_2.shard_id ) #The sleep ensures that the connector have refreshed their caches with the #new shards that have been added as a result of the split. time.sleep(_utils.TTL) #The source shard group master would have been marked as read only #during the sync. Remove the read_only flag. source_group = Group.fetch(source_group_id) if source_group is None: raise _errors.ShardingError(_services_sharding.SHARD_GROUP_NOT_FOUND % (source_group_id, )) source_group_master = MySQLServer.fetch(source_group.master) if source_group_master is None: raise _errors.ShardingError( _services_sharding.SHARD_GROUP_MASTER_NOT_FOUND) source_group_master.connect() #Kill all the existing connections on the servers source_group.kill_connections_on_servers() #Allow connections on the source group master source_group_master.read_only = False #Allow connections on the destination group master destn_group_master.read_only = False #Setup replication for the new group from the global server _group_replication.setup_group_replication \ (shard_mapping_defn[2], destination_group_id) #Enable the split shards new_shard_1.enable() new_shard_2.enable() #Trigger changing the mappings for the shard that was copied if not update_only: _events.trigger_within_procedure( PRUNE_SHARDS, new_shard_1.shard_id, new_shard_2.shard_id, prune_limit )
def _check_shard_information(shard_id, destn_group_id, mysqldump_binary, mysqlclient_binary, split_value, config_file, prune_limit, cmd, update_only): """Verify the sharding information before starting a re-sharding operation. :param shard_id: The destination shard ID. :param destn_group_id: The Destination group ID. :param mysqldump_binary: The path to the mysqldump binary. :param mysqlclient_binary: The path to the mysqlclient binary. :param split_value: The point at which the sharding definition should be split. :param config_file: The complete path to the fabric configuration file. :param prune_limit: The number of DELETEs that should be done in one batch. :param cmd: Indicates if it is a split or a move being executed. :param update_only: If the operation is a update only operation. """ if not _services_utils.is_valid_binary(mysqldump_binary): raise _errors.ShardingError(_services_sharding.MYSQLDUMP_NOT_FOUND % mysqldump_binary) if not _services_utils.is_valid_binary(mysqlclient_binary): raise _errors.ShardingError(_services_sharding.MYSQLCLIENT_NOT_FOUND % mysqlclient_binary) if cmd == "SPLIT": range_sharding_spec, _, shard_mappings, _ = \ _services_sharding.verify_and_fetch_shard(shard_id) upper_bound = \ SHARDING_SPECIFICATION_HANDLER[shard_mappings[0].type_name].\ get_upper_bound( range_sharding_spec.lower_bound, range_sharding_spec.shard_mapping_id, shard_mappings[0].type_name ) #If the underlying sharding scheme is a HASH. When a shard is split, #all the tables that are part of the shard, have the same sharding #scheme. All the shard mappings associated with this shard_id will be #of the same sharding type. Hence it is safe to use one of the shard #mappings. if shard_mappings[0].type_name == "HASH": if split_value is not None: raise _errors.ShardingError( _services_sharding.NO_LOWER_BOUND_FOR_HASH_SHARDING) if upper_bound is None: #While splitting a range, retrieve the next upper bound and #find the mid-point, in the case where the next upper_bound #is unavailable pick the maximum value in the set of values in #the shard. upper_bound = HashShardingSpecification.fetch_max_key(shard_id) #Calculate the split value. split_value = \ SHARDING_DATATYPE_HANDLER[shard_mappings[0].type_name].\ split_value( range_sharding_spec.lower_bound, upper_bound ) elif split_value is not None: if not (SHARDING_DATATYPE_HANDLER[shard_mappings[0].type_name].\ is_valid_split_value( split_value, range_sharding_spec.lower_bound, upper_bound ) ): raise _errors.ShardingError( _services_sharding.INVALID_LOWER_BOUND_VALUE % (split_value, )) elif split_value is None: raise _errors.ShardingError( _services_sharding.SPLIT_VALUE_NOT_DEFINED) #Ensure that the group does not already contain a shard. if Shards.lookup_shard_id(destn_group_id) is not None: raise _errors.ShardingError( _services_sharding.SHARD_MOVE_DESTINATION_NOT_EMPTY % (destn_group_id, )) #Fetch the group information for the source shard that #needs to be moved. source_shard = Shards.fetch(shard_id) if source_shard is None: raise _errors.ShardingError(_services_sharding.SHARD_NOT_FOUND % (shard_id, )) #Fetch the group_id and the group that hosts the source shard. source_group_id = source_shard.group_id destn_group = Group.fetch(destn_group_id) if destn_group is None: raise _errors.ShardingError(_services_sharding.SHARD_GROUP_NOT_FOUND % (destn_group_id, )) if not update_only: _events.trigger_within_procedure(BACKUP_SOURCE_SHARD, shard_id, source_group_id, destn_group_id, mysqldump_binary, mysqlclient_binary, split_value, config_file, prune_limit, cmd, update_only) else: _events.trigger_within_procedure(SETUP_RESHARDING_SWITCH, shard_id, source_group_id, destn_group_id, split_value, prune_limit, cmd, update_only)