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))