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