class ScCloudComputingInstanceReinstall: def __init__(self, endpoint, token, instance_id, name, region_id, image_id, image_regexp, wait, update_interval, checkmode): self.api = ScApi(token, endpoint) self.instance = self.api.toolbox.find_instance(instance_id=instance_id, instance_name=name, region_id=region_id, must=True) if not image_id and not image_regexp: self.image_id = self.instance['image_id'] else: self.image_id = self.api.toolbox.find_image_id( image_id=image_id, image_regexp=image_regexp, region_id=region_id) self.wait = wait self.update_interval = update_interval self.checkmode = checkmode # copypaste, refactor, TODO def wait_for_statuses(self, status_done, statuses_continue): start_time = time.time() if self.wait: time.sleep(self.update_interval) # workaround around bug in APIs while self.instance['status'] not in statuses_continue + [status_done]: if not self.wait: break if time.time() > start_time + self.wait: raise WaitError( msg=f"Timeout waiting instance {self.instance['id']} " f"status {status_done} or {statuses_continue}. " f"Last state was {self.instance['status']}", timeout=time.time() - start_time) time.sleep(self.update_interval) self.instance = self.api.get_instances(self.instance['id']) if self.instance['status'] == status_done: return True else: if self.instance['status'] in statuses_continue: return False else: if self.wait: raise WaitError( msg=f"Timeout waiting instance {self.instance['id']} " f"status {status_done}. " f"Last state was {self.instance['status']}", timeout=time.time() - start_time) def run(self): if self.checkmode: self.instance['changed'] = True return self.instance self.api.post_instances_reinstall(instance_id=self.instance['id'], image_id=self.image_id) self.wait_for_statuses(status_done='ACTIVE', statuses_continue=[]) self.instance['changed'] = True return self.instance
class ScCloudComputingInstanceInfo(): def __init__(self, endpoint, token, instance_id, name, region_id): self.api = ScApi(token, endpoint) self.instance_id = self.api.toolbox.find_instance( instance_id=instance_id, instance_name=name, region_id=region_id, must=True)['id'] def run(self): result = self.api.get_instances(self.instance_id) result['changed'] = False return result
class ScCloudComputingInstanceState: def __init__(self, endpoint, token, state, instance_id, name, region_id, image_id, image_regexp, wait, update_interval, checkmode): self.api = ScApi(token, endpoint) self.state = state self.instance_id = self.api.toolbox.find_instance( instance_id=instance_id, instance_name=name, region_id=region_id, must=True)['id'] self.image_id = image_id self.image_regexp = image_regexp self.wait = wait self.update_interval = update_interval self.checkmode = checkmode def wait_for_statuses(self, status_done, statuses_continue): start_time = time.time() while self.instance['status'] not in statuses_continue + [status_done]: if not self.wait: break if time.time() > start_time + self.wait: raise WaitError( msg=f"Timeout waiting instance {self.instance['id']} " f"status {status_done} or {statuses_continue}. " f"Last state was {self.instance['status']}", timeout=time.time() - start_time) time.sleep(self.update_interval) self.instance = self.api.get_instances(self.instance_id) if self.instance['status'] == status_done: return True else: if self.instance['status'] in statuses_continue: return False else: if self.wait: raise WaitError( msg=f"Timeout waiting instance {self.instance['id']} " f"status {status_done}. " f"Last state was {self.instance['status']}", timeout=time.time() - start_time) def shutdown(self): if self.instance['status'] == 'RESCUE': raise ModuleError('Shutdown is not supported in rescue mode.') if self.wait_for_statuses(status_done='SWITCHED_OFF', statuses_continue=['ACTIVE']): self.instance['changed'] = False return self.instance if self.checkmode: self.instance['changed'] = True return self.instance self.api.post_instance_switch_off(self.instance_id) self.wait_for_statuses(status_done='SWITCHED_OFF', statuses_continue=[]) self.instance = self.api.get_instances(self.instance_id) self.instance['changed'] = True return self.instance def normalize(self): if self.wait_for_statuses(status_done='ACTIVE', statuses_continue=['SWITCHED_OFF', 'RESCUE']): self.instance['changed'] = False return self.instance if self.checkmode: self.instance['changed'] = True return self.instance if self.instance['status'] == 'SWITCHED_OFF': self.api.post_instance_switch_on(self.instance_id) elif self.instance['status'] == 'RESCUE': self.api.post_instance_unrescue(self.instance_id) self.wait_for_statuses(status_done='ACTIVE', statuses_continue=[]) self.instance = self.api.get_instances(self.instance_id) self.instance['changed'] = True return self.instance def rescue(self): if self.image_id or self.image_regexp: image_id = self.api.toolbox.find_image_id( image_id=self.image_id, image_regexp=self.image_regexp, region_id=self.instance['region_id'], must=True) else: image_id = None if self.wait_for_statuses(status_done='RESCUE', statuses_continue=['ACTIVE', 'SWITCHED_OFF']): self.instance['changed'] = False return self.instance if self.checkmode: self.instance['changed'] = True return self.instance self.api.post_instance_rescue(self.instance_id, image_id) self.wait_for_statuses(status_done='RESCUE', statuses_continue=[]) self.instance = self.api.get_instances(self.instance_id) self.instance['changed'] = True return self.instance def reboot(self): raise NotImplementedError def run(self): self.instance = self.api.get_instances(self.instance_id) if self.state == 'shutdown': return self.shutdown() elif self.state == 'rescue': return self.rescue() elif self.state == 'rebooted': return self.reboot() elif self.state == 'normal': return self.normalize() else: raise ModuleError(f"Unknown state={self.state}")
class ScCloudComputingInstanceCreate(): def __init__(self, endpoint, token, region_id, name, image_id, image_regexp, flavor_id, flavor_name, gpn_enabled, ipv6_enabled, ssh_key_fingerprint, ssh_key_name, backup_copies, wait, update_interval, checkmode): self.checkmode = checkmode self.api = ScApi(token, endpoint) if region_id is None: raise ModuleError("region_id is mandatory for state=present.") self.region_id = region_id if not name: raise ModuleError("Name is mandatory for state=present.") self.name = name self.instance_id = None self.flavor_id = self.get_flavor_id(flavor_id, flavor_name) self.image_id = self.api.toolbox.find_image_id( image_id=image_id, image_regexp=image_regexp, region_id=region_id, must=True) self.gpn_enabled = gpn_enabled self.ipv6_enabled = ipv6_enabled self.ssh_key_fingerprint = self.get_ssh_key_fingerprint( ssh_key_fingerprint, ssh_key_name) self.backup_copies = backup_copies self.wait = wait self.update_interval = update_interval self.checkmode = checkmode def get_ssh_key_fingerprint(self, ssh_key_fingerprint, ssh_key_name): if ssh_key_fingerprint: return ssh_key_fingerprint if ssh_key_name: for key in self.api.list_ssh_keys(): if key['name'] == ssh_key_name: return key['fingerprint'] raise ModuleError(f"Unable to find ssh key {ssh_key_name}") return None def get_flavor_id(self, flavor_id, flavor_name): if flavor_id and flavor_name: raise ModuleError("Both flavor_id and flavor_name are present.") if not flavor_id and not flavor_name: raise ModuleError('Need either flavor_id or flavor_name.') if flavor_name: flavor_id = self.api.toolbox.find_cloud_flavor_id_by_name( flavor_name=flavor_name, region_id=self.region_id, must=True) return flavor_id def create_instance(self): instance = self.api.post_instance( region_id=self.region_id, name=self.name, flavor_id=self.flavor_id, image_id=self.image_id, gpn_enabled=self.image_id, ipv6_enabled=self.ipv6_enabled, ssh_key_fingerprint=self.ssh_key_fingerprint, backup_copies=self.backup_copies) return instance def wait_for(self, instance): start_time = time.time() instance = self.api.get_instances(instance['id']) if not self.wait: return instance while instance['status'] != 'ACTIVE': time.sleep(self.update_interval) elapsed = time.time() - start_time if elapsed > self.wait: raise WaitError( msg=f"Timeout while waiting instance {instance['id']}" f" to become ACTIVE. Last status was {instance['status']}", timeout=elapsed) instance = self.api.get_instances(instance['id']) return instance def run(self): instance = self.api.toolbox.find_instance(self.instance_id, self.name, self.region_id, must=False) if instance: instance['changed'] = NOT_CHANGED else: if not self.checkmode: instance = self.create_instance() instance = self.wait_for(instance) else: instance = { 'info': 'Instance shold be created, ' 'but check_mode is activated. ' 'no real instance was created.' } instance['changed'] = CHANGED return instance