def _create_instances(context, db_info, datastore, datastore_version, instances): Redis_conf = CONF.get(datastore_version.manager) num_instances = len(instances) total_volume_allocation = 0 # Validate and Cache flavors nova_client = remote.create_nova_client(context) unique_flavors = set(map(lambda i: i['flavor_id'], instances)) flavor_cache = {} for fid in unique_flavors: try: flavor_cache.update({fid: nova_client.flavors.get(fid)}) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=fid) # Checking volumes name_index = 1 for instance in instances: if not instance.get('name'): instance['name'] = "%s-member-%s" % (db_info.name, name_index) name_index += 1 volume_size = instance.get('volume_size') if Redis_conf.volume_support: models.validate_volume_size(volume_size) total_volume_allocation += volume_size else: if volume_size: raise exception.VolumeNotSupported() ephemeral_support = Redis_conf.device_path flavor_id = instance['flavor_id'] flavor = flavor_cache[flavor_id] if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) # Check quotas quota_request = { 'instances': num_instances, 'volumes': total_volume_allocation } check_quotas(context.tenant, quota_request) # Creating member instances return map( lambda instance: inst_models.Instance.create( context, instance['name'], instance['flavor_id'], datastore_version.image_id, [], [], datastore, datastore_version, instance.get('volume_size'), None, instance.get('availability_zone', None), instance.get('nics', None), configuration_id=None, cluster_config={ "id": db_info.id, "instance_type": "member" }), instances)
def _check_instances(context, instances, datastore_version, allowed_instance_count=None): instance_count = len(instances) if allowed_instance_count: if instance_count not in allowed_instance_count: raise exception.ClusterNumInstancesNotSupported( num_instances=allowed_instance_count ) flavor_ids = [instance['flavor_id'] for instance in instances] if len(set(flavor_ids)) != 1: raise exception.ClusterFlavorsNotEqual() flavor_id = flavor_ids[0] nova_client = remote.create_nova_client(context) try: flavor = nova_client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) mongo_conf = CONF.get(datastore_version.manager) volume_sizes = [instance['volume_size'] for instance in instances if instance.get('volume_size', None)] if mongo_conf.volume_support: if len(volume_sizes) != instance_count: raise exception.ClusterVolumeSizeRequired() if len(set(volume_sizes)) != 1: raise exception.ClusterVolumeSizesNotEqual() volume_size = volume_sizes[0] models.validate_volume_size(volume_size) else: # TODO(amcreynolds): is ephemeral possible for mongodb clusters? if len(volume_sizes) > 0: raise exception.VolumeNotSupported() ephemeral_support = mongo_conf.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id)
def _create_instances(context, db_info, datastore, datastore_version, instances, extended_properties, locality): Redis_conf = CONF.get(datastore_version.manager) num_instances = len(instances) total_volume_allocation = 0 # Validate and Cache flavors nova_client = remote.create_nova_client(context) unique_flavors = set(map(lambda i: i['flavor_id'], instances)) flavor_cache = {} for fid in unique_flavors: try: flavor_cache.update({fid: nova_client.flavors.get(fid)}) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=fid) # Checking volumes name_index = 1 for instance in instances: if not instance.get('name'): instance['name'] = "%s-member-%s" % (db_info.name, name_index) name_index += 1 volume_size = instance.get('volume_size') if Redis_conf.volume_support: models.validate_volume_size(volume_size) total_volume_allocation += volume_size else: if volume_size: raise exception.VolumeNotSupported() ephemeral_support = Redis_conf.device_path flavor_id = instance['flavor_id'] flavor = flavor_cache[flavor_id] if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) # Check quotas quota_request = {'instances': num_instances, 'volumes': total_volume_allocation} check_quotas(context.tenant, quota_request) # Creating member instances return map(lambda instance: inst_models.Instance.create(context, instance['name'], instance['flavor_id'], datastore_version.image_id, [], [], datastore, datastore_version, instance.get('volume_size'), None, instance.get( 'availability_zone', None), instance.get('nics', None), configuration_id=None, cluster_config={ "id": db_info.id, "instance_type": "member"}, locality=locality ), instances)
def _validate_cluster_instances(context, instances, datastore, datastore_version): """Validate the flavor and volume""" ds_conf = CONF.get(datastore_version.manager) num_instances = len(instances) # Check number of instances is at least min_cluster_member_count if num_instances < ds_conf.min_cluster_member_count: raise exception.ClusterNumInstancesNotLargeEnough( num_instances=ds_conf.min_cluster_member_count) # Checking flavors and get delta for quota check flavor_ids = [instance['flavor_id'] for instance in instances] if len(set(flavor_ids)) != 1: raise exception.ClusterFlavorsNotEqual() flavor_id = flavor_ids[0] nova_client = remote.create_nova_client(context) try: flavor = nova_client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {'instances': num_instances} # Checking volumes and get delta for quota check volume_sizes = [instance['volume_size'] for instance in instances if instance.get('volume_size', None)] volume_size = None if ds_conf.volume_support: if len(volume_sizes) != num_instances: raise exception.ClusterVolumeSizeRequired() if len(set(volume_sizes)) != 1: raise exception.ClusterVolumeSizesNotEqual() volume_size = volume_sizes[0] cluster_models.validate_volume_size(volume_size) deltas['volumes'] = volume_size * num_instances else: if len(volume_sizes) > 0: raise exception.VolumeNotSupported() ephemeral_support = ds_conf.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) # quota check check_quotas(context.tenant, deltas) # Checking networks are same for the cluster instance_nics = [] for instance in instances: nics = instance.get('nics') if nics: instance_nics.append(nics[0].get('net-id')) if len(set(instance_nics)) > 1: raise exception.ClusterNetworksNotEqual() if not instance_nics: return instance_nic = instance_nics[0] try: nova_client.networks.get(instance_nic) except nova_exceptions.NotFound: raise exception.NetworkNotFound(uuid=instance_nic)
def _check_instances(context, instances, datastore_version, allowed_instance_count=None): instance_count = len(instances) if allowed_instance_count: if instance_count not in allowed_instance_count: raise exception.ClusterNumInstancesNotSupported( num_instances=allowed_instance_count ) flavor_ids = [instance['flavor_id'] for instance in instances] if len(set(flavor_ids)) != 1: raise exception.ClusterFlavorsNotEqual() flavor_id = flavor_ids[0] nova_client = clients.create_nova_client(context) try: flavor = nova_client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) mongo_conf = CONF.get(datastore_version.manager) volume_sizes = [instance['volume_size'] for instance in instances if instance.get('volume_size', None)] if mongo_conf.volume_support: if len(volume_sizes) != instance_count: raise exception.ClusterVolumeSizeRequired() if len(set(volume_sizes)) != 1: raise exception.ClusterVolumeSizesNotEqual() volume_size = volume_sizes[0] models.validate_volume_size(volume_size) else: # TODO(amcreynolds): is ephemeral possible for mongodb clusters? if len(volume_sizes) > 0: raise exception.VolumeNotSupported() ephemeral_support = mongo_conf.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id)
def test_validate_volume_size(self): self.patch_conf_property('max_accepted_volume_size', 10) models.validate_volume_size(9) models.validate_volume_size(10) self.assertRaises(exception.VolumeQuotaExceeded, models.validate_volume_size, 11) self.assertRaises(exception.VolumeSizeNotSpecified, models.validate_volume_size, None)
def create(cls, context, name, datastore, datastore_version, instances, extended_properties): LOG.debug("Initiating cluster creation.") vertica_conf = CONF.get(datastore_version.manager) num_instances = len(instances) # Matching number of instances with configured cluster_member_count if num_instances != vertica_conf.cluster_member_count: raise exception.ClusterNumInstancesNotSupported(num_instances=vertica_conf.cluster_member_count) # Checking flavors flavor_ids = [instance["flavor_id"] for instance in instances] if len(set(flavor_ids)) != 1: raise exception.ClusterFlavorsNotEqual() flavor_id = flavor_ids[0] nova_client = remote.create_nova_client(context) try: flavor = nova_client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {"instances": num_instances} # Checking volumes volume_sizes = [instance["volume_size"] for instance in instances if instance.get("volume_size", None)] volume_size = None if vertica_conf.volume_support: if len(volume_sizes) != num_instances: raise exception.ClusterVolumeSizeRequired() if len(set(volume_sizes)) != 1: raise exception.ClusterVolumeSizesNotEqual() volume_size = volume_sizes[0] models.validate_volume_size(volume_size) deltas["volumes"] = volume_size * num_instances else: if len(volume_sizes) > 0: raise exception.VolumeNotSupported() ephemeral_support = vertica_conf.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) check_quotas(context.tenant, deltas) nics = [instance.get("nics", None) for instance in instances] azs = [instance.get("availability_zone", None) for instance in instances] # Updating Cluster Task db_info = models.DBCluster.create( name=name, tenant_id=context.tenant, datastore_version_id=datastore_version.id, task_status=ClusterTasks.BUILDING_INITIAL, ) # Creating member instances for i in range(0, num_instances): if i == 0: member_config = {"id": db_info.id, "instance_type": "master"} else: member_config = {"id": db_info.id, "instance_type": "member"} instance_name = "%s-member-%s" % (name, str(i + 1)) inst_models.Instance.create( context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, nics=nics[i], availability_zone=azs[i], configuration_id=None, cluster_config=member_config, ) # Calling taskmanager to further proceed for cluster-configuration task_api.load(context, datastore_version.manager).create_cluster(db_info.id) return VerticaCluster(context, db_info, datastore, datastore_version)
def create(cls, context, name, datastore, datastore_version, instances): # TODO(amcreynolds): consider moving into CONF and even supporting # TODO(amcreynolds): an array of values, e.g. [3, 5, 7] # TODO(amcreynolds): or introduce a min/max num_instances and set # TODO(amcreynolds): both to 3 num_instances = len(instances) if num_instances != 3: raise exception.ClusterNumInstancesNotSupported(num_instances=3) flavor_ids = [instance['flavor_id'] for instance in instances] if len(set(flavor_ids)) != 1: raise exception.ClusterFlavorsNotEqual() flavor_id = flavor_ids[0] nova_client = remote.create_nova_client(context) try: flavor = nova_client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) mongo_conf = CONF.get(datastore_version.manager) num_configsvr = mongo_conf.num_config_servers_per_cluster num_mongos = mongo_conf.num_query_routers_per_cluster delta_instances = num_instances + num_configsvr + num_mongos deltas = {'instances': delta_instances} volume_sizes = [instance['volume_size'] for instance in instances if instance.get('volume_size', None)] volume_size = None if mongo_conf.volume_support: if len(volume_sizes) != num_instances: raise exception.ClusterVolumeSizeRequired() if len(set(volume_sizes)) != 1: raise exception.ClusterVolumeSizesNotEqual() volume_size = volume_sizes[0] models.validate_volume_size(volume_size) # TODO(amcreynolds): for now, mongos+configsvr same flavor+disk deltas['volumes'] = volume_size * delta_instances else: # TODO(amcreynolds): is ephemeral possible for mongodb clusters? if len(volume_sizes) > 0: raise exception.VolumeNotSupported() ephemeral_support = mongo_conf.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) check_quotas(context.tenant, deltas) db_info = models.DBCluster.create( name=name, tenant_id=context.tenant, datastore_version_id=datastore_version.id, task_status=ClusterTasks.BUILDING_INITIAL) replica_set_name = "rs1" member_config = {"id": db_info.id, "shard_id": utils.generate_uuid(), "instance_type": "member", "replica_set_name": replica_set_name} for i in range(1, num_instances + 1): instance_name = "%s-%s-%s" % (name, replica_set_name, str(i)) inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, availability_zone=None, nics=None, configuration_id=None, cluster_config=member_config) configsvr_config = {"id": db_info.id, "instance_type": "config_server"} for i in range(1, num_configsvr + 1): instance_name = "%s-%s-%s" % (name, "configsvr", str(i)) inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, availability_zone=None, nics=None, configuration_id=None, cluster_config=configsvr_config) mongos_config = {"id": db_info.id, "instance_type": "query_router"} for i in range(1, num_mongos + 1): instance_name = "%s-%s-%s" % (name, "mongos", str(i)) inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, availability_zone=None, nics=None, configuration_id=None, cluster_config=mongos_config) task_api.load(context, datastore_version.manager).create_cluster( db_info.id) return MongoDbCluster(context, db_info, datastore, datastore_version)
def _create_instances(context, db_info, datastore, datastore_version, instances, new_cluster): vertica_conf = CONF.get(datastore_version.manager) num_instances = len(instances) existing = inst_models.DBInstance.find_all(cluster_id=db_info.id).all() num_existing = len(existing) # Matching number of instances with configured cluster_member_count if new_cluster \ and num_instances != vertica_conf.cluster_member_count: raise exception.ClusterNumInstancesNotSupported( num_instances=vertica_conf.cluster_member_count) # Checking flavors flavor_ids = [instance['flavor_id'] for instance in instances] if len(set(flavor_ids)) != 1: raise exception.ClusterFlavorsNotEqual() flavor_id = flavor_ids[0] nova_client = remote.create_nova_client(context) try: flavor = nova_client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {'instances': num_instances} # Checking volumes volume_sizes = [instance['volume_size'] for instance in instances if instance.get('volume_size', None)] volume_size = None if vertica_conf.volume_support: if len(volume_sizes) != num_instances: raise exception.ClusterVolumeSizeRequired() if len(set(volume_sizes)) != 1: raise exception.ClusterVolumeSizesNotEqual() volume_size = volume_sizes[0] models.validate_volume_size(volume_size) deltas['volumes'] = volume_size * num_instances else: if len(volume_sizes) > 0: raise exception.VolumeNotSupported() ephemeral_support = vertica_conf.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) check_quotas(context.tenant, deltas) nics = [instance.get('nics', None) for instance in instances] azs = [instance.get('availability_zone', None) for instance in instances] # Creating member instances minstances = [] for i in range(0, num_instances): if i == 0 and new_cluster: member_config = {"id": db_info.id, "instance_type": "master"} else: member_config = {"id": db_info.id, "instance_type": "member"} instance_name = "%s-member-%s" % (db_info.name, str(i + num_existing + 1)) minstances.append( inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, nics=nics[i], availability_zone=azs[i], configuration_id=None, cluster_config=member_config) ) return minstances
def create(cls, context, name, datastore, datastore_version, instances): # TODO(amcreynolds): consider moving into CONF and even supporting # TODO(amcreynolds): an array of values, e.g. [3, 5, 7] # TODO(amcreynolds): or introduce a min/max num_instances and set # TODO(amcreynolds): both to 3 num_instances = len(instances) if num_instances != 3: raise exception.ClusterNumInstancesNotSupported(num_instances=3) flavor_ids = [instance['flavor_id'] for instance in instances] if len(set(flavor_ids)) != 1: raise exception.ClusterFlavorsNotEqual() flavor_id = flavor_ids[0] nova_client = remote.create_nova_client(context) try: flavor = nova_client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) mongo_conf = CONF.get(datastore_version.manager) num_configsvr = mongo_conf.num_config_servers_per_cluster num_mongos = mongo_conf.num_query_routers_per_cluster delta_instances = num_instances + num_configsvr + num_mongos deltas = {'instances': delta_instances} volume_sizes = [ instance['volume_size'] for instance in instances if instance.get('volume_size', None) ] volume_size = None if mongo_conf.volume_support: if len(volume_sizes) != num_instances: raise exception.ClusterVolumeSizeRequired() if len(set(volume_sizes)) != 1: raise exception.ClusterVolumeSizesNotEqual() volume_size = volume_sizes[0] models.validate_volume_size(volume_size) # TODO(amcreynolds): for now, mongos+configsvr same flavor+disk deltas['volumes'] = volume_size * delta_instances else: # TODO(amcreynolds): is ephemeral possible for mongodb clusters? if len(volume_sizes) > 0: raise exception.VolumeNotSupported() ephemeral_support = mongo_conf.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) check_quotas(context.tenant, deltas) db_info = models.DBCluster.create( name=name, tenant_id=context.tenant, datastore_version_id=datastore_version.id, task_status=ClusterTasks.BUILDING_INITIAL) replica_set_name = "rs1" member_config = { "id": db_info.id, "shard_id": utils.generate_uuid(), "instance_type": "member", "replica_set_name": replica_set_name } for i in range(1, num_instances + 1): instance_name = "%s-%s-%s" % (name, replica_set_name, str(i)) inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, availability_zone=None, nics=None, configuration_id=None, cluster_config=member_config) configsvr_config = {"id": db_info.id, "instance_type": "config_server"} for i in range(1, num_configsvr + 1): instance_name = "%s-%s-%s" % (name, "configsvr", str(i)) inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, availability_zone=None, nics=None, configuration_id=None, cluster_config=configsvr_config) mongos_config = {"id": db_info.id, "instance_type": "query_router"} for i in range(1, num_mongos + 1): instance_name = "%s-%s-%s" % (name, "mongos", str(i)) inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, availability_zone=None, nics=None, configuration_id=None, cluster_config=mongos_config) task_api.load(context, datastore_version.manager).create_cluster(db_info.id) return MongoDbCluster(context, db_info, datastore, datastore_version)
def create(cls, context, name, datastore, datastore_version, instances, extended_properties): LOG.debug("Initiating cluster creation.") vertica_conf = CONF.get(datastore_version.manager) num_instances = len(instances) # Matching number of instances with configured cluster_member_count if num_instances != vertica_conf.cluster_member_count: raise exception.ClusterNumInstancesNotSupported( num_instances=vertica_conf.cluster_member_count) # Checking flavors flavor_ids = [instance['flavor_id'] for instance in instances] if len(set(flavor_ids)) != 1: raise exception.ClusterFlavorsNotEqual() flavor_id = flavor_ids[0] nova_client = remote.create_nova_client(context) try: flavor = nova_client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {'instances': num_instances} # Checking volumes volume_sizes = [ instance['volume_size'] for instance in instances if instance.get('volume_size', None) ] volume_size = None if vertica_conf.volume_support: if len(volume_sizes) != num_instances: raise exception.ClusterVolumeSizeRequired() if len(set(volume_sizes)) != 1: raise exception.ClusterVolumeSizesNotEqual() volume_size = volume_sizes[0] models.validate_volume_size(volume_size) deltas['volumes'] = volume_size * num_instances else: if len(volume_sizes) > 0: raise exception.VolumeNotSupported() ephemeral_support = vertica_conf.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) check_quotas(context.tenant, deltas) nics = [instance.get('nics', None) for instance in instances] azs = [ instance.get('availability_zone', None) for instance in instances ] # Updating Cluster Task db_info = models.DBCluster.create( name=name, tenant_id=context.tenant, datastore_version_id=datastore_version.id, task_status=ClusterTasks.BUILDING_INITIAL) # Creating member instances for i in range(0, num_instances): if i == 0: member_config = {"id": db_info.id, "instance_type": "master"} else: member_config = {"id": db_info.id, "instance_type": "member"} instance_name = "%s-member-%s" % (name, str(i + 1)) inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, nics=nics[i], availability_zone=azs[i], configuration_id=None, cluster_config=member_config) # Calling taskmanager to further proceed for cluster-configuration task_api.load(context, datastore_version.manager).create_cluster(db_info.id) return VerticaCluster(context, db_info, datastore, datastore_version)
def _create_instances(context, db_info, datastore, datastore_version, instances, extended_properties, locality, new_cluster=True): vertica_conf = CONF.get(datastore_version.manager) num_instances = len(instances) existing = inst_models.DBInstance.find_all(cluster_id=db_info.id).all() num_existing = len(existing) # Matching number of instances with configured cluster_member_count if (new_cluster and num_instances != vertica_conf.cluster_member_count): raise exception.ClusterNumInstancesNotSupported( num_instances=vertica_conf.cluster_member_count) # Checking flavors flavor_ids = [instance['flavor_id'] for instance in instances] if len(set(flavor_ids)) != 1: raise exception.ClusterFlavorsNotEqual() flavor_id = flavor_ids[0] nova_client = remote.create_nova_client(context) try: flavor = nova_client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {'instances': num_instances} # Checking volumes volume_sizes = [ instance['volume_size'] for instance in instances if instance.get('volume_size', None) ] volume_size = None if vertica_conf.volume_support: if len(volume_sizes) != num_instances: raise exception.ClusterVolumeSizeRequired() if len(set(volume_sizes)) != 1: raise exception.ClusterVolumeSizesNotEqual() volume_size = volume_sizes[0] models.validate_volume_size(volume_size) deltas['volumes'] = volume_size * num_instances else: if len(volume_sizes) > 0: raise exception.VolumeNotSupported() ephemeral_support = vertica_conf.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) check_quotas(context.tenant, deltas) nics = [instance.get('nics', None) for instance in instances] azs = [ instance.get('availability_zone', None) for instance in instances ] # Creating member instances minstances = [] for i in range(0, num_instances): if i == 0 and new_cluster: member_config = {"id": db_info.id, "instance_type": "master"} else: member_config = {"id": db_info.id, "instance_type": "member"} instance_name = "%s-member-%s" % (db_info.name, str(i + num_existing + 1)) minstances.append( inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, nics=nics[i], availability_zone=azs[i], configuration_id=None, cluster_config=member_config, locality=locality)) return minstances
def create(cls, context, name, datastore, datastore_version, instances, extended_properties, locality): # TODO(amcreynolds): consider moving into CONF and even supporting # TODO(amcreynolds): an array of values, e.g. [3, 5, 7] # TODO(amcreynolds): or introduce a min/max num_instances and set # TODO(amcreynolds): both to 3 num_instances = len(instances) if num_instances != 3: raise exception.ClusterNumInstancesNotSupported(num_instances=3) flavor_ids = [instance['flavor_id'] for instance in instances] if len(set(flavor_ids)) != 1: raise exception.ClusterFlavorsNotEqual() flavor_id = flavor_ids[0] nova_client = remote.create_nova_client(context) try: flavor = nova_client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) mongo_conf = CONF.get(datastore_version.manager) num_configsvr = (1 if mongo_conf.num_config_servers_per_cluster == 1 else 3) num_mongos = mongo_conf.num_query_routers_per_cluster delta_instances = num_instances + num_configsvr + num_mongos deltas = {'instances': delta_instances} volume_sizes = [instance['volume_size'] for instance in instances if instance.get('volume_size', None)] volume_size = None if mongo_conf.volume_support: if len(volume_sizes) != num_instances: raise exception.ClusterVolumeSizeRequired() if len(set(volume_sizes)) != 1: raise exception.ClusterVolumeSizesNotEqual() volume_size = volume_sizes[0] models.validate_volume_size(volume_size) # TODO(amcreynolds): for now, mongos+configsvr same flavor+disk deltas['volumes'] = volume_size * delta_instances else: # TODO(amcreynolds): is ephemeral possible for mongodb clusters? if len(volume_sizes) > 0: raise exception.VolumeNotSupported() ephemeral_support = mongo_conf.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) check_quotas(context.tenant, deltas) nics = [instance.get('nics', None) for instance in instances] nic = nics[0] for n in nics[1:]: if n != nic: raise ValueError(_('All cluster nics must be the same. ' '%(nic)s != %(n)s') % {'nic': nic, 'n': n}) azs = [instance.get('availability_zone', None) for instance in instances] regions = [instance.get('region_name', None) for instance in instances] db_info = models.DBCluster.create( name=name, tenant_id=context.tenant, datastore_version_id=datastore_version.id, task_status=ClusterTasks.BUILDING_INITIAL) replica_set_name = "rs1" member_config = {"id": db_info.id, "shard_id": utils.generate_uuid(), "instance_type": "member", "replica_set_name": replica_set_name} configsvr_config = {"id": db_info.id, "instance_type": "config_server"} mongos_config = {"id": db_info.id, "instance_type": "query_router"} if mongo_conf.cluster_secure: cluster_key = base64.b64encode(utils.generate_random_password()) member_config['key'] = cluster_key configsvr_config['key'] = cluster_key mongos_config['key'] = cluster_key for i in range(num_instances): instance_name = "%s-%s-%s" % (name, replica_set_name, str(i + 1)) inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, availability_zone=azs[i], nics=nic, configuration_id=None, cluster_config=member_config, modules=instances[i].get('modules'), region_name=regions[i], locality=locality) for i in range(num_configsvr): instance_name = "%s-%s-%s" % (name, "configsvr", str(i + 1)) inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, availability_zone=azs[i % num_instances], nics=nic, configuration_id=None, cluster_config=configsvr_config, region_name=regions[i % num_instances], locality=locality) for i in range(num_mongos): instance_name = "%s-%s-%s" % (name, "mongos", str(i + 1)) inst_models.Instance.create(context, instance_name, flavor_id, datastore_version.image_id, [], [], datastore, datastore_version, volume_size, None, availability_zone=azs[i % num_instances], nics=nic, configuration_id=None, cluster_config=mongos_config, region_name=regions[i % num_instances], locality=locality) task_api.load(context, datastore_version.manager).create_cluster( db_info.id) return MongoDbCluster(context, db_info, datastore, datastore_version)