예제 #1
0
    def shrink(self, instance_ids):
        self.validate_cluster_available()

        context = self.context
        db_info = self.db_info
        datastore_version = self.ds_version

        for db_instance in self.db_instances:
            if db_instance.type == 'master':
                if db_instance.id in instance_ids:
                    raise exception.ClusterShrinkInstanceInUse(
                        id=db_instance.id, reason="Cannot remove master node.")

        all_instance_ids = [
            db_instance.id for db_instance in self.db_instances
        ]

        left_instances = [
            instance_id for instance_id in all_instance_ids
            if instance_id not in instance_ids
        ]

        k = self.k_safety(len(left_instances))

        vertica_conf = CONF.get(datastore_version.manager)
        if k < vertica_conf.min_ksafety:
            raise exception.ClusterNumInstancesBelowSafetyThreshold()

        db_info.update(task_status=ClusterTasks.SHRINKING_CLUSTER)

        task_api.load(context, datastore_version.manager).shrink_cluster(
            self.db_info.id, instance_ids)
        return VerticaCluster(self.context, db_info, self.ds, self.ds_version)
예제 #2
0
    def shrink(self, removal_ids):
        LOG.debug("Shrinking cluster %s.", self.id)

        self.validate_cluster_available()

        cluster_info = self.db_info
        cluster_info.update(task_status=ClusterTasks.SHRINKING_CLUSTER)
        try:
            removal_insts = [
                inst_models.Instance.load(self.context, inst_id)
                for inst_id in removal_ids
            ]
            node_ids = []
            error_ids = []
            for instance in removal_insts:
                node_id = Cluster.get_guest(instance).get_node_id_for_removal()
                if node_id:
                    node_ids.append(node_id)
                else:
                    error_ids.append(instance.id)
            if error_ids:
                raise exception.ClusterShrinkInstanceInUse(
                    id=error_ids,
                    reason="Nodes cannot be removed. Check slots.")

            all_instances = (inst_models.DBInstance.find_all(
                cluster_id=self.id, deleted=False).all())
            remain_insts = [
                inst_models.Instance.load(self.context, inst.id)
                for inst in all_instances if inst.id not in removal_ids
            ]

            for inst in remain_insts:
                guest = Cluster.get_guest(inst)
                guest.remove_nodes(node_ids)
            for inst in removal_insts:
                inst.update_db(cluster_id=None)
            for inst in removal_insts:
                inst_models.Instance.delete(inst)

            return RedisCluster(self.context, cluster_info, self.ds,
                                self.ds_version)
        finally:
            cluster_info.update(task_status=ClusterTasks.NONE)
예제 #3
0
파일: api.py 프로젝트: xgoeforever/trove
    def shrink(self, instance_ids):
        """Removes instances from a cluster.
        Currently only supports removing entire replica sets from the cluster.
        """
        if not len(instance_ids) > 0:
            raise exception.TroveError(
                _('No instances specified for shrink operation.'))

        self._prep_resize()

        all_member_ids = set([member.id for member in self.members])
        all_query_router_ids = set(
            [query_router.id for query_router in self.query_routers])
        target_ids = set(instance_ids)
        target_member_ids = target_ids.intersection(all_member_ids)
        target_query_router_ids = target_ids.intersection(all_query_router_ids)
        target_configsvr_ids = target_ids.difference(
            target_member_ids.union(target_query_router_ids))
        if target_configsvr_ids:
            raise exception.ClusterShrinkInstanceInUse(
                id=list(target_configsvr_ids),
                reason="Cannot remove config servers.")

        remaining_query_router_ids = all_query_router_ids.difference(
            target_query_router_ids)
        if len(remaining_query_router_ids) < 1:
            raise exception.ClusterShrinkInstanceInUse(
                id=list(target_query_router_ids),
                reason="Cannot remove all remaining query routers. At least "
                "one query router must be available in the cluster.")

        if target_member_ids:
            target_members = [
                member for member in self.members
                if member.id in target_member_ids
            ]
            target_shards = {}
            for member in target_members:
                if member.shard_id in target_shards:
                    target_shards[member.shard_id].append(member.id)
                else:
                    target_shards[member.shard_id] = [member.id]
            for target_shard_id in target_shards.keys():
                # check the whole shard is being deleted
                target_shard_member_ids = [
                    member.id for member in target_members
                    if member.shard_id == target_shard_id
                ]
                all_shard_member_ids = [
                    member.id for member in self.members
                    if member.shard_id == target_shard_id
                ]
                if set(target_shard_member_ids) != set(all_shard_member_ids):
                    raise exception.TroveError(
                        _('MongoDB cluster shrink only supports removing an '
                          'entire shard. Shard %(shard)s has members: '
                          '%(instances)s') % {
                              'shard': target_shard_id,
                              'instances': all_shard_member_ids
                          })
                self._check_shard_status(target_shard_member_ids[0])

        # all checks are done by now
        self.update_db(task_status=ClusterTasks.SHRINKING_CLUSTER)
        for instance_id in instance_ids:
            instance = inst_models.load_any_instance(self.context, instance_id)
            instance.delete()
        self.manager.shrink_cluster(self.id, instance_ids)