#!/usr/bin/python DOCUMENTATION = r''' --- module: decort_disk description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). ''' from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import env_fallback from ansible.module_utils.decort_utils import * class decort_disk(DecortController): def __init__(self,arg_amodule): super(decort_disk, self).__init__(arg_amodule) validated_acc_id = 0 validated_acc_info = None self.disk_id = 0 self.account_id = 0 # limitIO check for exclusive parameters if arg_amodule.params['limitIO']: self.disk_check_iotune_arg(arg_amodule.params['limitIO']) if not arg_amodule.params['id']: if ( not arg_amodule.params['account_id'] and not arg_amodule.params['account_name'] ): self.result['changed'] = False self.result['msg'] = ( 'Cannot manage Disk by name without specifying account ID ' 'or name.' ) self.amodule.fail_json(**self.result) validated_acc_id, validated_acc_info = self.account_find( arg_amodule.params['account_name'], arg_amodule.params['account_id']) if not validated_acc_id: self.result['changed'] = False self.result['msg'] = ( f"Current user does not have access to the account " f"ID {arg_amodule.params['account_id']} / " f"name '{arg_amodule.params['account_name']}' " f"or non-existent account specified." ) self.amodule.fail_json(**self.result) self.acc_id = validated_acc_id self.acc_info = validated_acc_info validated_disk_id, validated_disk_facts = self.disk_find( disk_id=arg_amodule.params['id'], name=arg_amodule.params['name'] if "name" in arg_amodule.params else "", account_id=self.acc_id, check_state=False, ) if arg_amodule.params['place_with']: image_id, image_facts = self.image_find(arg_amodule.params['place_with'], "", 0) arg_amodule.params['sep_id'] = image_facts['sepId'] self.disk_id = validated_disk_id self.disk_info = validated_disk_facts def create(self): self.disk_id = self.disk_create(accountId=self.acc_id, name = self.amodule.params['name'], description=self.amodule.params['description'], size=self.amodule.params['size'], type=self.amodule.params['type'], iops=self.amodule.params['iops'], sep_id=self.amodule.params['sep_id'], pool=self.amodule.params['pool'], ) #IO tune if self.amodule.params['limitIO']: self.disk_limitIO(disk_id=self.disk_id, limits=self.amodule.params['limitIO']) #set share status if self.amodule.params['shareable'] and self.amodule.params['type'] == "D": self.disk_share(self.disk_id,self.amodule.params['shareable']) return def action(self,restore=False): #restore never be done if restore: self.disk_restore(self.disk_id) #rename if id present if ( self.amodule.params['name'] is not None and self.amodule.params['name'] != self.disk_info['name'] ): self.disk_rename(disk_id=self.disk_id, name=self.amodule.params['name']) #resize if ( self.amodule.params['size'] is not None and self.amodule.params['size'] != self.disk_info['sizeMax'] ): self.disk_resize(self.disk_info,self.amodule.params['size']) #IO TUNE if self.amodule.params['limitIO']: clean_io = [param for param in self.amodule.params['limitIO'] \ if self.amodule.params['limitIO'][param] == None] for key in clean_io: del self.amodule.params['limitIO'][key] if self.amodule.params['limitIO'] != self.disk_info['iotune']: self.disk_limitIO(self.disk_id,self.amodule.params['limitIO']) #share check/update #raise Exception(self.amodule.params['shareable']) if self.amodule.params['shareable'] != self.disk_info['shareable'] and \ self.amodule.params['type'] == "D": self.disk_share(self.disk_id,self.amodule.params['shareable']) return def delete(self): self.disk_id = self.disk_delete(disk_id=self.disk_id, detach=self.amodule.params['force_detach'], permanently=self.amodule.params['permanently'], reason=self.amodule.params['reason']) self.disk_info['status'] = "DELETED" return def rename(self): self.disk_rename(diskId = self.disk_id, name = self.amodule.params['name']) self.disk_info['name'] = self.amodule.params['name'] return def nop(self): self.result['failed'] = False self.result['changed'] = False if self.disk_id: self.result['msg'] = ("No state change required for Disk ID {} because of its " "current status '{}'.").format(self.disk_id, self.disk_info['status']) else: self.result['msg'] = ("No state change to '{}' can be done for " "non-existent Disk.").format(self.amodule.params['state']) return def package_facts(self, check_mode=False): ret_dict = dict(id=0, name="none", state="CHECK_MODE", size=0, account_id=0, sep_id=0, pool="none", gid=0 ) if check_mode or self.disk_info is None: return ret_dict # remove io param with zero value clean_io = [param for param in self.disk_info['iotune'] if self.disk_info['iotune'][param] == 0] for key in clean_io: del self.disk_info['iotune'][key] ret_dict['id'] = self.disk_info['id'] ret_dict['name'] = self.disk_info['name'] ret_dict['size'] = self.disk_info['sizeMax'] ret_dict['state'] = self.disk_info['status'] ret_dict['account_id'] = self.disk_info['accountId'] ret_dict['sep_id'] = self.disk_info['sepId'] ret_dict['pool'] = self.disk_info['pool'] ret_dict['computes'] = self.disk_info['computes'] ret_dict['gid'] = self.disk_info['gid'] ret_dict['iotune'] = self.disk_info['iotune'] return ret_dict @staticmethod def build_parameters(): """Build and return a dictionary of parameters expected by decort_disk module in a form accepted by AnsibleModule utility class.""" return dict( account_id=dict(type='int', required=False, default=0), account_name=dict(type='str', required=False, default=''), description=dict(type='str', required=False, default='Disk by decort_disk'), app_id=dict(type='str', required=False, fallback=(env_fallback, ['DECORT_APP_ID'])), app_secret=dict(type='str', required=False, fallback=(env_fallback, ['DECORT_APP_SECRET']), no_log=True), authenticator=dict(type='str', required=True, choices=['legacy', 'oauth2', 'jwt']), controller_url=dict(type='str', required=True), id=dict(type='int', required=False, default=0), name=dict(type='str', required=False), force_detach=dict(type='bool', required=False, default=False), jwt=dict(type='str', required=False, fallback=(env_fallback, ['DECORT_JWT']), no_log=True), oauth2_url=dict(type='str', required=False, fallback=(env_fallback, ['DECORT_OAUTH2_URL'])), password=dict(type='str', required=False, fallback=(env_fallback, ['DECORT_PASSWORD']), no_log=True), place_with=dict(type='int', default=0), pool=dict(type='str', default=''), sep_id=dict(type='int', default=0), size=dict(type='int'), type=dict(type='str', required=False, default="D", choices=['B', 'D', 'T']), iops=dict(type='int',required=False,default=2000), limitIO=dict(type='dict', options=dict( total_bytes_sec=dict(required=False,type='int'), read_bytes_sec=dict(required=False,type='int'), write_bytes_sec=dict(required=False,type='int'), total_iops_sec=dict(required=False,type='int'), read_iops_sec=dict(required=False,type='int'), write_iops_sec=dict(required=False,type='int'), total_bytes_sec_max=dict(required=False,type='int'), read_bytes_sec_max=dict(required=False,type='int'), write_bytes_sec_max=dict(required=False,type='int'), total_iops_sec_max=dict(required=False,type='int'), read_iops_sec_max=dict(required=False,type='int'), write_iops_sec_max=dict(required=False,type='int'), size_iops_sec=dict(required=False,type='int'),)), permanently=dict(type='bool', required=False, default=False), shareable=dict(type='bool', required=False, default=False), reason=dict(type='str', required=False,default='Managed by Ansible decort_disk'), state=dict(type='str', default='present', choices=['absent', 'present']), user=dict(type='str', required=False, fallback=(env_fallback, ['DECORT_USER'])), verify_ssl=dict(type='bool', required=False, default=True), workflow_callback=dict(type='str', required=False), workflow_context=dict(type='str', required=False), ) def main(): module_parameters = decort_disk.build_parameters() amodule = AnsibleModule(argument_spec=module_parameters, supports_check_mode=True, mutually_exclusive=[ ['oauth2', 'password'], ['password', 'jwt'], ['jwt', 'oauth2'], ], required_together=[ ['app_id', 'app_secret'], ['user', 'password'], ], required_one_of=[ ['id', 'name'], ], ) decon = decort_disk(amodule) # #Full range of Disk status is as follows: # # "ASSIGNED","MODELED", "CREATING","CREATED","DELETED", "DESTROYED","PURGED", # if decon.disk_id: #disk exist if decon.disk_info['status'] in ["MODELED", "CREATING"]: decon.result['failed'] = True decon.result['changed'] = False decon.result['msg'] = ("No change can be done for existing Disk ID {} because of its current " "status '{}'").format(decon.disk_id, decon.disk_info['status']) # "ASSIGNED","CREATED","DELETED","PURGED", "DESTROYED" elif decon.disk_info['status'] in ["ASSIGNED","CREATED"]: if amodule.params['state'] == 'absent': decon.delete() elif amodule.params['state'] == 'present': decon.action() elif decon.disk_info['status'] in ["PURGED", "DESTROYED"]: #re-provision disk if amodule.params['state'] in ('present'): decon.create() else: decon.nop() elif decon.disk_info['status'] == "DELETED": if amodule.params['state'] in ('present'): decon.action(restore=True) elif (amodule.params['state'] == 'absent' and amodule.params['permanently']): decon.delete() else: decon.nop() else: # preexisting Disk was not found if amodule.params['state'] == 'absent': decon.nop() else: decon.create() if decon.result['failed']: amodule.fail_json(**decon.result) else: if decon.result['changed'] and amodule.params['state'] in ('present'): _, decon.disk_info = decon.disk_find(decon.disk_id) decon.result['facts'] = decon.package_facts(amodule.check_mode) amodule.exit_json(**decon.result) if __name__ == "__main__": main() #SHARE