def stop_instances()

in source/lambda/schedulers/ec2_service.py [0:0]


    def stop_instances(self, kwargs):

        def is_in_stopping_state(state):
            return (state & 0xFF) in Ec2Service.EC2_STOPPING_STATES

        self._init_scheduler(kwargs)

        stopped_instances = kwargs[schedulers.PARAM_STOPPED_INSTANCES]
        stop_tags = kwargs[schedulers.PARAM_CONFIG].stopped_tags
        if stop_tags is None:
            stop_tags = []
        stop_tags_key_names = [t["Key"] for t in stop_tags]

        start_tags_keys = [{"Key": t["Key"]} for t in kwargs[schedulers.PARAM_CONFIG].started_tags if
                           t["Key"] not in stop_tags_key_names]

        methods = ["stop_instances", "create_tags", "delete_tags", "describe_instances"]
        client = get_client_with_retries("ec2", methods=methods, context=self._context, session=self._session,
                                         region=self._region)

        for instance_batch in list(self.instance_batches(stopped_instances, STOP_BATCH_SIZE)):

            instance_ids = [i.id for i in instance_batch]

            # split in hibernated and non hibernated, instanced that are stopped for resizing cannot be hibernated
            hibernated = [i.id for i in instance_batch if i.hibernate and not i.resized]
            not_hibernated = [i.id for i in instance_batch if i.id not in hibernated]

            for inst in [i for i in instance_batch if i.hibernate and i.resized]:
                self._logger.warning(WARN_NO_HIBERNATE_RESIZED, inst.id)

            instances_stopping = []

            try:
                while len(hibernated) > 0:
                    try:
                        stop_resp = client.stop_instances_with_retries(InstanceIds=hibernated, Hibernate=True)
                        instances_stopping += [i["InstanceId"] for i in stop_resp.get("StoppingInstances", []) if
                                               is_in_stopping_state(i.get("CurrentState", {}).get("Code", ""))]
                        break
                    except ClientError as ex:
                        instance_id = None
                        if ex.response.get("Error", {}).get("Code") == "UnsupportedHibernationConfiguration":
                            instance_id = ex.response["Error"]["Message"].split(":")[-1].strip()
                        elif ex.response.get("Error", {}).get("Code") == "UnsupportedOperation":
                            instance_id = ex.response["Error"]["Message"].split(" ")[1].strip()
                        if instance_id in hibernated:
                            self._logger.warning(WARN_NOT_HIBERNATED, instance_id, ex)
                            hibernated.remove(instance_id)
                            not_hibernated.append(instance_id)
                        else:
                            self._logger.error(ERR_STOPPING_INSTANCES, ",".join(hibernated), str(ex))

                if len(not_hibernated) > 0:
                    try:
                        stop_resp = client.stop_instances_with_retries(InstanceIds=not_hibernated, Hibernate=False)
                        instances_stopping += [i["InstanceId"] for i in stop_resp.get("StoppingInstances", []) if
                                               is_in_stopping_state(i.get("CurrentState", {}).get("Code", ""))]
                    except Exception as ex:
                        self._logger.error(ERR_STOPPING_INSTANCES, ",".join(not_hibernated), str(ex))

                get_status_count = 0
                if len(instances_stopping) < len(instance_ids):
                    time.sleep(5)

                    instances_stopping = [i["InstanceId"] for i in self.get_instance_status(client, instance_ids) if
                                          is_in_stopping_state(i.get("State", {}).get("Code", ""))]

                    if len(instances_stopping) == len(instance_ids):
                        break

                    get_status_count += 1
                    if get_status_count > 3:
                        for i in instance_ids:
                            if i not in instances_stopping:
                                self._logger.warning(WARNING_INSTANCE_NOT_STOPPING, i)
                        break

                if len(instances_stopping) > 0:
                    try:
                        if start_tags_keys is not None and len(start_tags_keys):
                            self._logger.info(INFO_REMOVING_KEYS, "start",
                                              ",".join(["\"{}\"".format(k["Key"]) for k in start_tags_keys]),
                                              ",".join(instances_stopping))
                            client.delete_tags_with_retries(Resources=instances_stopping, Tags=start_tags_keys)
                        if len(stop_tags) > 0:
                            self._logger.info(INF_ADD_KEYS, "stop", str(stop_tags), ",".join(instances_stopping))
                            client.create_tags_with_retries(Resources=instances_stopping, Tags=stop_tags)
                    except Exception as ex:
                        self._logger.warning(WARN_STOPPED_INSTANCES_TAGGING, ','.join(instances_stopping), str(ex))

                for i in instances_stopping:
                    yield i, InstanceSchedule.STATE_STOPPED

            except Exception as ex:
                self._logger.error(ERR_STOPPING_INSTANCES, ",".join(instance_ids), str(ex))