From 10dba22834612ada6e2875cefcb57d9bc06bbedb Mon Sep 17 00:00:00 2001 From: Dmitriy Smirnov Date: Thu, 18 Jul 2024 16:30:58 +0300 Subject: [PATCH] Implement functionality of `cloudapi/account/listComputes` API method in `decort_account_info` module --- CHANGELOG.md | 2 +- library/decort_account_info.py | 101 +++++++++++++++++++++++++++++ module_utils/decort_utils.py | 114 +++++++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8307a8f..647739d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ | Идентификатор
задачи | Описание | | --- | --- | -| BANS-462
BANS-472
BANS-475 | Добавлен новый модуль **decort_account_info**, который позволяет получить следующую информацию об аккаунте:
• основная информация
• используемые и зарезервированные ресурсы
• ресурсные группы | +| BANS-462
BANS-472
BANS-475
BANS-476 | Добавлен новый модуль **decort_account_info**, который позволяет получить следующую информацию об аккаунте:
• основная информация
• используемые и зарезервированные ресурсы
• ресурсные группы
• виртуальные машины | ## Исправления diff --git a/library/decort_account_info.py b/library/decort_account_info.py index 801f990..719743b 100644 --- a/library/decort_account_info.py +++ b/library/decort_account_info.py @@ -31,6 +31,7 @@ class DecortAccountInfo(DecortController): self.id, self.facts = self.account_find( account_name=amodule.params['name'], account_id=amodule.params['id'], + computes_params=self.mapped_computes_params, resource_consumption=amodule.params['resource_consumption'], resource_groups_params=self.mapped_rg_params, fail_if_not_found=True @@ -54,6 +55,75 @@ class DecortAccountInfo(DecortController): required=True, choices=['oauth2', 'jwt'] ), + computes=dict( + type='dict', + options=dict( + filter=dict( + type='dict', + options=dict( + ext_net_id=dict( + type='int', + ), + ext_net_name=dict( + type='str' + ), + id=dict( + type='int', + ), + ip=dict( + type='str' + ), + name=dict( + type='str' + ), + rg_id=dict( + type='int', + ), + rg_name=dict( + type='str' + ), + tech_status=dict( + type='str', + choices=self.COMPUTE_TECH_STATUSES, + ), + vins_id=dict( + type='int' + ), + vm_id=dict( + type='int' + ), + ), + ), + pagination=dict( + type='dict', + options=dict( + number=dict( + type='int', + default=1, + ), + size=dict( + type='int', + required=True, + ), + ), + ), + sorting=dict( + type='dict', + options=dict( + asc=dict( + type='bool', + default=True, + ), + field=dict( + type='str', + choices=\ + self.FIELDS_FOR_SORTING_ACCOUNT_COMPUTE_LIST, + required=True, + ), + ), + ), + ), + ), controller_url=dict( type='str', required=True @@ -149,6 +219,37 @@ class DecortAccountInfo(DecortController): ] ) + @property + def mapped_computes_params(self) -> None | dict: + input_params = self.amodule.params['computes'] + if not input_params: + return input_params + + mapped_params = {} + if input_params['filter']: + mapped_params['compute_id'] = input_params['filter']['id'] + mapped_params['compute_ip'] = input_params['filter']['ip'] + mapped_params['compute_name'] = input_params['filter']['name'] + mapped_params['compute_tech_status'] =\ + input_params['filter']['tech_status'] + mapped_params['ext_net_id'] = input_params['filter']['ext_net_id'] + mapped_params['ext_net_name'] =\ + input_params['filter']['ext_net_name'] + mapped_params['rg_id'] = input_params['filter']['rg_id'] + mapped_params['rg_name'] = input_params['filter']['rg_name'] + if input_params['pagination']: + mapped_params['page_number'] =\ + input_params['pagination']['number'] + mapped_params['page_size'] =\ + input_params['pagination']['size'] + if input_params['sorting']: + mapped_params['sort_by_asc'] =\ + input_params['sorting']['asc'] + mapped_params['sort_by_field'] =\ + input_params['sorting']['field'] + + return mapped_params + @property def mapped_rg_params(self) -> None | dict: input_params = self.amodule.params['resource_groups'] diff --git a/module_utils/decort_utils.py b/module_utils/decort_utils.py index f0453e7..ecec21b 100644 --- a/module_utils/decort_utils.py +++ b/module_utils/decort_utils.py @@ -41,6 +41,27 @@ class DecortController(object): based on the requested authentication type. """ + FIELDS_FOR_SORTING_ACCOUNT_COMPUTE_LIST = [ + 'cpus', + 'createdBy', + 'createdTime', + 'deletedBy', + 'deletedTime', + 'id', + 'name', + 'ram', + 'registered', + 'rgId', + 'rgName', + 'status', + 'techStatus', + 'totalDisksSize', + 'updatedBy', + 'updatedTime', + 'userManaged', + 'vinsConnected', + ] + FIELDS_FOR_SORTING_ACCOUNT_RG_LIST = [ 'createdBy', 'createdTime', @@ -55,6 +76,20 @@ class DecortController(object): 'vinses', ] + COMPUTE_TECH_STATUSES = [ + 'BACKUP_RUNNING', + 'BACKUP_STOPPED', + 'DOWN', + 'MIGRATING', + 'PAUSED', + 'PAUSING', + 'SCHEDULED', + 'STARTED', + 'STARTING', + 'STOPPED', + 'STOPPING', + ] + RESOURCE_GROUP_STATUSES = [ 'CREATED', 'DELETED', @@ -1960,6 +1995,7 @@ class DecortController(object): def account_find(self, account_name, account_id=0, resource_consumption=False, resource_groups_params: None | dict = None, + computes_params: None | dict = None, fail_if_not_found=False): """Find cloud account specified by the name and return facts about the account. Knowing account is required for certain cloud resource management tasks (e.g. creating new RG). @@ -2019,6 +2055,8 @@ class DecortController(object): self.amodule.fail_json(**self.result) return 0, None + account_details['computes_amount'] = account_details.pop('computes') + account_details['createdTime_readable'] = self.sec_to_dt_str( account_details['createdTime'] ) @@ -2049,6 +2087,13 @@ class DecortController(object): **resource_groups_params ) + if computes_params is not None: + account_details['computes'] =\ + self.account_computes( + account_id=account_details['id'], + **computes_params + ) + return account_details['id'], account_details def account_resource_consumption(self, account_id: int, @@ -2131,6 +2176,75 @@ class DecortController(object): return resource_groups + def account_computes( + self, + account_id: int, + compute_id: None | int = None, + compute_ip: None | str = None, + compute_name: None | str = None, + compute_tech_status: None | str = None, + ext_net_id: None | int = None, + ext_net_name: None | str = None, + page_number: int = 1, + page_size: None | int = None, + rg_id: None | int = None, + rg_name: None | str = None, + sort_by_asc=True, + sort_by_field: None | str = None, + ) -> list[dict]: + self.result['waypoints'] += f' -> account_computes' + + if compute_tech_status and ( + not compute_tech_status in self.COMPUTE_TECH_STATUSES + ): + self.result['msg'] = ( + f'{compute_tech_status} is not valid compute tech status' + f' for filtering account computes list.' + ) + self.amodule.fail_json(**self.result) + + sort_by = None + if sort_by_field: + if not sort_by_field in self.FIELDS_FOR_SORTING_ACCOUNT_COMPUTE_LIST: + self.result['msg'] = ( + f'{sort_by_field} is not valid field for sorting' + f' account computes list.' + ) + self.amodule.fail_json(**self.result) + + sort_by_prefix = '+' if sort_by_asc else '-' + sort_by = f'{sort_by_prefix}{sort_by_field}' + + api_params = { + 'accountId': account_id, + 'computeId': compute_id, + 'extNetId': ext_net_id, + 'extNetName': ext_net_name, + 'ipAddress': compute_ip, + 'name': compute_name, + 'page': page_number if page_size else None, + 'rgId': rg_id, + 'rgName': rg_name, + 'size': page_size, + 'sortBy': sort_by, + 'techStatus': compute_tech_status, + } + + api_resp = self.decort_api_call( + arg_req_function=requests.post, + arg_api_name='/restmachine/cloudapi/account/listComputes', + arg_params=api_params, + ) + + computes = api_resp.json()['data'] + + for c in computes: + c['createdTime_readable'] = self.sec_to_dt_str(c['createdTime']) + c['deletedTime_readable'] = self.sec_to_dt_str(c['deletedTime']) + c['updatedTime_readable'] = self.sec_to_dt_str(c['updatedTime']) + + return computes + ################################### # GPU resource manipulation methods ###################################