main 7.2.0
sskarimov 2 months ago
parent e537eadda6
commit f8c32d609b

@ -1,19 +1,47 @@
# Список изменений в версии 7.1.0 # Список изменений в версии 7.2.0
## Добавлено ## Добавлено
### Модуль decort_k8s
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-628 | Добавлен параметр `lb_sysctl` для установки параметров конфигурации sysctl балансировщика нагрузки. |
| BANS-701 | Модуль теперь позволяет задать параметр `master_chipset` для существующего кластера, если значение параметра соответствует чипсету master-узлов. |
### Модуль decort_osimage
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-308 | Добавлена возможность удаления виртуальных образов. |
### Модуль decort_lb
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-627 | Добавлен параметр `sysctl`. |
### Модуль decort_kvmvm ### Модуль decort_kvmvm
| Идентификатор<br>задачи | Описание | | Идентификатор<br>задачи | Описание |
| --- | --- | | --- | --- |
| BANS-650 | Добавлена возможность откатить ВМ к состоянию снимка с помощью нового параметра `rollback_to`. Добавлено возвращаемое значение `snapshots`. | | BANS-651 | Добавлен параметр `get_console_url` для получения ссылки на консоль ВМ. |
| BANS-675 | Для параметра `chipset` добавлено значение по умолчанию `i440fx` при создании ВМ. | | BANS-652 | Добавлены параметры `disks`, `boot.disk_id` и `boot.disk_size` для управления дисками ВМ. |
| BANS-692 | Добавлен параметр `preferred_cpu_cores` и возвращаемое значение `preferred_cpu_cores`. | | BANS-629 | Добавлен параметр `clone_from` для создания ВМ путём клонирования другой ВМ. |
| BANS-694 | Добавлена проверка параметра `hp_backed` при подключении ВМ к `DPDK` сети . |
### Модуль decort_rg
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-424 | Добавлена возможность изменения описания ресурсной группы, а также добавлено возвращаемое значение `description`. |
## Удалено ## Удалено
### Модуль decort_disk
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-657 | Удалён параметр `type`. |
## Исправлено
### Модуль decort_kvmvm ### Модуль decort_kvmvm
| Идентификатор<br>задачи | Описание | | Идентификатор<br>задачи | Описание |
| --- | --- | | --- | --- |
| BANS-679 | Модуль завершал свою работу ошибкой проверки входных параметров при указании целевого состояния `state: absent` и имени ВМ, которой уже не существует. | | BANS-652 | Удален параметр `data_disks` в связи с изменением логики (см. параметр `disks`). Удален параметр `boot_disk` в связи с переименованием в `boot.disk_size`. |
| BANS-707 | При попытке для остановленной ВМ задать новые значения для параметров `chipset`, `cpu_pin`, `hp_backed` или `numa_affinity`, модуль требовал задать для параметра `state` значение, соответствующее остановленной ВМ. |
## Исправлено
### Модуль decort_k8s
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-661 | При создании кластера модуль возвращал информацию только о первой группе worker-узлов. |

@ -5,7 +5,7 @@
| Версия платформы | Версия модулей Ansible | | Версия платформы | Версия модулей Ansible |
|:----------------:|:--------------------------:| |:----------------:|:--------------------------:|
| 4.2.0 | 7.0.x, 7.1.x | | 4.2.0 | 7.0.x, 7.1.x, 7.2.x |
| 4.1.0 | 6.0.x, 6.1.x | | 4.1.0 | 6.0.x, 6.1.x |
| 4.0.0 | 5.6.x, 5.5.x, 5.4.x, 5.3.x | | 4.0.0 | 5.6.x, 5.5.x, 5.4.x, 5.3.x |
| 3.8.8, 3.8.9 | 5.2.6 | | 3.8.8, 3.8.9 | 5.2.6 |

@ -73,7 +73,6 @@ class decort_disk(DecortController):
name = self.amodule.params['name'], name = self.amodule.params['name'],
description=self.amodule.params['description'], description=self.amodule.params['description'],
size=self.amodule.params['size'], size=self.amodule.params['size'],
type=self.amodule.params['type'],
iops=self.amodule.params['iops'], iops=self.amodule.params['iops'],
sep_id=self.amodule.params['sep_id'], sep_id=self.amodule.params['sep_id'],
pool=self.amodule.params['pool'], pool=self.amodule.params['pool'],
@ -83,7 +82,7 @@ class decort_disk(DecortController):
self.disk_limitIO(disk_id=self.disk_id, self.disk_limitIO(disk_id=self.disk_id,
limits=self.amodule.params['limitIO']) limits=self.amodule.params['limitIO'])
#set share status #set share status
if self.amodule.params['shareable'] and self.amodule.params['type'] == "D": if self.amodule.params['shareable']:
self.disk_share(self.disk_id,self.amodule.params['shareable']) self.disk_share(self.disk_id,self.amodule.params['shareable'])
return return
@ -114,8 +113,7 @@ class decort_disk(DecortController):
self.disk_limitIO(self.disk_id,self.amodule.params['limitIO']) self.disk_limitIO(self.disk_id,self.amodule.params['limitIO'])
#share check/update #share check/update
#raise Exception(self.amodule.params['shareable']) #raise Exception(self.amodule.params['shareable'])
if self.amodule.params['shareable'] != self.disk_info['shareable'] and \ if self.amodule.params['shareable'] != self.disk_info['shareable']:
self.amodule.params['type'] == "D":
self.disk_share(self.disk_id,self.amodule.params['shareable']) self.disk_share(self.disk_id,self.amodule.params['shareable'])
return return
@ -220,15 +218,6 @@ class decort_disk(DecortController):
size=dict( size=dict(
type='int', type='int',
), ),
type=dict(
type='str',
default='D',
choices=[
'B',
'D',
'T',
],
),
iops=dict( iops=dict(
type='int', type='int',
default=2000, default=2000,

@ -82,6 +82,20 @@ class decort_k8s(DecortController):
self.acc_id = self.k8s_info['accountId'] self.acc_id = self.k8s_info['accountId']
# check workers and groups for add or remove? # check workers and groups for add or remove?
aparam_sysctl = arg_amodule.params['lb_sysctl']
if aparam_sysctl is not None:
_, lb_info = self._lb_get_by_id(lb_id=self.k8s_info['lbId'])
sysctl_with_str_values = {
k: str(v) for k, v in aparam_sysctl.items()
}
if sysctl_with_str_values != lb_info['sysctlParams']:
self.message(
'Check for parameter "lb_sysctl" failed: '
'cannot change lb_sysctl for an existing cluster '
'load balancer.'
)
self.exit(fail=True)
if not self.k8s_id: if not self.k8s_id:
validated_k8ci_id = self.k8s_k8ci_find(arg_amodule.params['k8ci_id']) validated_k8ci_id = self.k8s_k8ci_find(arg_amodule.params['k8ci_id'])
if not validated_k8ci_id: if not validated_k8ci_id:
@ -96,6 +110,17 @@ class decort_k8s(DecortController):
self.result['msg'] = "At least one worker group must be present" self.result['msg'] = "At least one worker group must be present"
self.amodule.fail_json(**self.result) self.amodule.fail_json(**self.result)
if (
arg_amodule.params['lb_sysctl'] is not None
and not arg_amodule.params['with_lb']
):
self.message(
'Check for parameter "lb_sysctl" failed: '
'"lb_sysctl" can only be set if the parameter "with_lb" '
'is set to True.'
)
self.exit(fail=True)
return return
def package_facts(self,check_mode=False): def package_facts(self,check_mode=False):
@ -129,6 +154,7 @@ class decort_k8s(DecortController):
ret_dict['account_id'] = self.acc_id ret_dict['account_id'] = self.acc_id
ret_dict['k8s_Masters'] = self.k8s_info['k8sGroups']['masters'] ret_dict['k8s_Masters'] = self.k8s_info['k8sGroups']['masters']
ret_dict['k8s_Workers'] = self.k8s_info['k8sGroups']['workers'] ret_dict['k8s_Workers'] = self.k8s_info['k8sGroups']['workers']
ret_dict['lb_id'] = self.k8s_info['lbId']
return ret_dict return ret_dict
@ -200,6 +226,7 @@ class decort_k8s(DecortController):
self.amodule.params['description'], self.amodule.params['description'],
self.amodule.params['extnet_only'], self.amodule.params['extnet_only'],
master_chipset, master_chipset,
lb_sysctl=self.amodule.params['lb_sysctl'],
) )
if not k8s_id: if not k8s_id:
@ -216,10 +243,12 @@ class decort_k8s(DecortController):
if self.k8s_id: if self.k8s_id:
self.k8s_should_exist = True self.k8s_should_exist = True
self.k8s_workers_modify( if len(target_wgs) > 1:
arg_k8swg=self.k8s_info, self.k8s_workers_modify(
arg_modwg=target_wgs, arg_k8swg=self.k8s_info,
) arg_modwg=target_wgs,
)
self.k8s_info = self.k8s_get_by_id(k8s_id=self.k8s_id)
return return
def destroy(self): def destroy(self):
@ -230,11 +259,21 @@ class decort_k8s(DecortController):
def action(self, disared_state, started=True, preupdate: bool = False): def action(self, disared_state, started=True, preupdate: bool = False):
if self.amodule.params['master_chipset'] is not None: if self.amodule.params['master_chipset'] is not None:
self.result['msg'] = ( for master_node in self.k8s_info['k8sGroups']['masters'][
'"master_chipset" parameter must not be specified ' 'detailedInfo'
'when modifying an existing K8s cluster.' ]:
) _, master_node_info, _ = self._compute_get_by_id(
self.exit(fail=True) comp_id=master_node['id']
)
if (
master_node_info['chipset']
!= self.amodule.params['master_chipset']
):
self.result['msg'] = (
'"master_chipset" cannot be changed '
'for existing K8s cluster.'
)
self.exit(fail=True)
if preupdate: if preupdate:
# K8s info updating # K8s info updating
@ -434,6 +473,9 @@ class decort_k8s(DecortController):
type='str', type='str',
choices=['Q35', 'i440fx'], choices=['Q35', 'i440fx'],
), ),
lb_sysctl=dict(
type='dict',
),
), ),
supports_check_mode=True, supports_check_mode=True,
required_one_of=[ required_one_of=[

@ -37,15 +37,62 @@ class decort_kvmvm(DecortController):
validated_rg_id = 0 validated_rg_id = 0
validated_rg_facts = None validated_rg_facts = None
self.vm_to_clone_id = 0
self.vm_to_clone_info = None
if arg_amodule.params['clone_from'] is not None:
self.vm_to_clone_id, self.vm_to_clone_info, _ = (
self._compute_get_by_id(
comp_id=self.aparams['clone_from']['id'],
)
)
if not self.vm_to_clone_id:
self.message(
f'Check for parameter "clone_from.id" failed: '
f'VM ID {self.aparams["clone_from"]["id"]} does not exist.'
)
self.exit(fail=True)
elif self.vm_to_clone_info['status'] in ('DESTROYED', 'DELETED'):
self.message(
f'Check for parameter "clone_from.id" failed: '
f'VM ID {self.aparams["clone_from"]["id"]} is in '
f'{self.vm_to_clone_info["status"]} state and '
f'cannot be cloned.'
)
self.exit(fail=True)
clone_id, clone_dict, _ = self.compute_find(
comp_name=self.aparams['name'],
rg_id=self.vm_to_clone_info['rgId'],
)
self.check_amodule_args_for_clone(
clone_id=clone_id,
clone_dict=clone_dict,
)
self.check_amodule_args_for_change()
if not clone_id:
clone_id = self.clone()
self.comp_id, self.comp_info, self.rg_id = self._compute_get_by_id(
comp_id=clone_id,
need_custom_fields=True,
need_console_url=self.aparams['get_console_url'],
)
return
comp_id = arg_amodule.params['id']
# Analyze Compute name & ID, RG name & ID and build arguments to compute_find accordingly. # Analyze Compute name & ID, RG name & ID and build arguments to compute_find accordingly.
if arg_amodule.params['name'] == "" and arg_amodule.params['id'] == 0: if arg_amodule.params['name'] == "" and comp_id == 0:
self.result['failed'] = True self.result['failed'] = True
self.result['changed'] = False self.result['changed'] = False
self.result['msg'] = "Cannot manage Compute when its ID is 0 and name is empty." self.result['msg'] = "Cannot manage Compute when its ID is 0 and name is empty."
self.fail_json(**self.result) self.fail_json(**self.result)
# fail the module - exit # fail the module - exit
if not arg_amodule.params['id']: # manage Compute by name -> need RG identity if not comp_id: # manage Compute by name -> need RG identity
if not arg_amodule.params['rg_id']: # RG ID is not set -> locate RG by name -> need account ID if not arg_amodule.params['rg_id']: # RG ID is not set -> locate RG by name -> need account ID
validated_acc_id, _ = self.account_find(arg_amodule.params['account_name'], validated_acc_id, _ = self.account_find(arg_amodule.params['account_name'],
arg_amodule.params['account_id']) arg_amodule.params['account_id'])
@ -78,18 +125,21 @@ class decort_kvmvm(DecortController):
# because this Compute does not exist or something goes wrong in the upstream API # because this Compute does not exist or something goes wrong in the upstream API
# We call compute_find with check_state=False as we also consider the case when a Compute # We call compute_find with check_state=False as we also consider the case when a Compute
# specified by account / RG / compute name never existed and will be created for the first time. # specified by account / RG / compute name never existed and will be created for the first time.
self.comp_id, self.comp_info, self.rg_id = self.compute_find(comp_id=arg_amodule.params['id'], self.comp_id, self.comp_info, self.rg_id = self.compute_find(comp_id=comp_id,
comp_name=arg_amodule.params['name'], comp_name=arg_amodule.params['name'],
rg_id=validated_rg_id, rg_id=validated_rg_id,
check_state=False, check_state=False,
need_custom_fields=True) need_custom_fields=True,
need_console_url=self.aparams['get_console_url'])
if self.comp_id: if self.comp_id:
self.comp_should_exist = True self.comp_should_exist = True
self.acc_id = self.comp_info['accountId'] self.acc_id = self.comp_info['accountId']
self.check_amodule_args_for_change()
else: else:
if self.amodule.params['state'] != 'absent': if self.amodule.params['state'] != 'absent':
self.check_amodule_args_for_create() self.check_amodule_args_for_create()
return return
def check_amodule_args(self): def check_amodule_args(self):
@ -215,7 +265,11 @@ class decort_kvmvm(DecortController):
# each of the following calls will abort if argument is missing # each of the following calls will abort if argument is missing
self.check_amodule_argument('cpu') self.check_amodule_argument('cpu')
self.check_amodule_argument('ram') self.check_amodule_argument('ram')
validated_bdisk_size = self.amodule.params['boot_disk'] or 0 validated_bdisk_size = 0
if self.amodule.params['boot'] is not None:
validated_bdisk_size = self.amodule.params['boot'].get(
'disk_size', 0
)
image_id, image_facts = None, None image_id, image_facts = None, None
if self.aparam_image: if self.aparam_image:
@ -295,7 +349,7 @@ class decort_kvmvm(DecortController):
self.comp_id = self.kvmvm_provision(rg_id=self.rg_id, self.comp_id = self.kvmvm_provision(rg_id=self.rg_id,
comp_name=self.amodule.params['name'], comp_name=self.amodule.params['name'],
cpu=self.amodule.params['cpu'], ram=self.amodule.params['ram'], cpu=self.amodule.params['cpu'], ram=self.amodule.params['ram'],
boot_disk=validated_bdisk_size, boot_disk_size=validated_bdisk_size,
image_id=image_id, image_id=image_id,
description=self.amodule.params['description'], description=self.amodule.params['description'],
userdata=cloud_init_params, userdata=cloud_init_params,
@ -340,10 +394,10 @@ class decort_kvmvm(DecortController):
new_networks=self.amodule.params['networks'], new_networks=self.amodule.params['networks'],
) )
# Next manage data disks # Next manage data disks
if self.amodule.params['data_disks'] is not None: if self.amodule.params['disks'] is not None:
self.compute_data_disks( self.compute_disks(
comp_dict=self.comp_info, comp_dict=self.comp_info,
new_data_disks=self.amodule.params['data_disks'], aparam_disks=self.amodule.params['disks'],
) )
self.compute_affinity(self.comp_info, self.compute_affinity(self.comp_info,
@ -372,6 +426,7 @@ class decort_kvmvm(DecortController):
_, self.comp_info, _ = self.compute_find( _, self.comp_info, _ = self.compute_find(
comp_id=self.comp_id, comp_id=self.comp_id,
need_custom_fields=True, need_custom_fields=True,
need_console_url=self.amodule.params['get_console_url'],
) )
if self.compute_update_args: if self.compute_update_args:
@ -404,6 +459,7 @@ class decort_kvmvm(DecortController):
_, self.comp_info, _ = self.compute_find( _, self.comp_info, _ = self.compute_find(
comp_id=self.comp_id, comp_id=self.comp_id,
need_custom_fields=True, need_custom_fields=True,
need_console_url=self.amodule.params['get_console_url'],
) )
self.modify() self.modify()
self.comp_should_exist = True self.comp_should_exist = True
@ -435,12 +491,27 @@ class decort_kvmvm(DecortController):
order_changing=self.aparams['network_order_changing'], order_changing=self.aparams['network_order_changing'],
) )
boot_disk_new_size = self.amodule.params['boot_disk'] if self.amodule.params['disks'] is not None:
if boot_disk_new_size: self.compute_disks(
self.compute_bootdisk_size(self.comp_info, boot_disk_new_size) comp_dict=self.comp_info,
aparam_disks=self.amodule.params['disks'],
)
if self.amodule.params['data_disks'] is not None: aparam_boot = self.amodule.params['boot']
self.compute_data_disks(self.comp_info, self.amodule.params['data_disks']) if aparam_boot is not None:
aparam_disk_id = aparam_boot['disk_id']
if aparam_disk_id is not None:
for disk in self.comp_info['disks']:
if disk['id'] == aparam_disk_id and disk['type'] != 'B':
self.compute_boot_disk(
comp_id=self.comp_info['id'],
boot_disk=aparam_disk_id,
)
break
boot_disk_new_size = aparam_boot['disk_size']
if boot_disk_new_size:
self.compute_bootdisk_size(self.comp_info, boot_disk_new_size)
self.compute_resize(self.comp_info, self.compute_resize(self.comp_info,
self.amodule.params['cpu'], self.amodule.params['ram'], self.amodule.params['cpu'], self.amodule.params['ram'],
@ -530,6 +601,8 @@ class decort_kvmvm(DecortController):
vnc_password="", vnc_password="",
snapshots=[], snapshots=[],
preferred_cpu_cores=[], preferred_cpu_cores=[],
clones=[],
clone_reference=0,
) )
if check_mode or self.comp_info is None: if check_mode or self.comp_info is None:
@ -600,6 +673,12 @@ class decort_kvmvm(DecortController):
ret_dict['preferred_cpu_cores'] = self.comp_info['preferredCpu'] ret_dict['preferred_cpu_cores'] = self.comp_info['preferredCpu']
if self.amodule.params['get_console_url']:
ret_dict['console_url'] = self.comp_info['console_url']
ret_dict['clones'] = self.comp_info['clones']
ret_dict['clone_reference'] = self.comp_info['cloneReference']
return ret_dict return ret_dict
def check_amodule_args_for_create(self): def check_amodule_args_for_create(self):
@ -641,11 +720,12 @@ class decort_kvmvm(DecortController):
if ( if (
self.aparams['sep_id'] is not None self.aparams['sep_id'] is not None
and self.aparams['boot_disk'] is None and self.aparams['boot'] is None
and self.aparams['boot']['disk_size'] is None
): ):
self.message( self.message(
'Check for parameter "sep_id" failed: ' 'Check for parameter "sep_id" failed: '
'"image_id" or "image_name" or "boot_disk" ' '"image_id" or "image_name" or "boot.disk_size" '
'must be specified to set sep_id.' 'must be specified to set sep_id.'
) )
self.exit(fail=True) self.exit(fail=True)
@ -680,8 +760,16 @@ class decort_kvmvm(DecortController):
description=dict( description=dict(
type='str', type='str',
), ),
boot_disk=dict( boot=dict(
type='int', type='dict',
options=dict(
disk_id=dict(
type='int',
),
disk_size=dict(
type='int',
),
),
), ),
sep_id=dict( sep_id=dict(
type='int', type='int',
@ -696,8 +784,24 @@ class decort_kvmvm(DecortController):
cpu=dict( cpu=dict(
type='int', type='int',
), ),
data_disks=dict( # list of integer disk IDs disks=dict(
type='list', type='dict',
options=dict(
mode=dict(
type='str',
choices=[
'update',
'detach',
'delete',
'match',
],
default='update',
),
ids=dict(
type='list',
elements='int',
),
),
), ),
id=dict( id=dict(
type='int', type='int',
@ -836,40 +940,135 @@ class decort_kvmvm(DecortController):
type='list', type='list',
elements='int', elements='int',
), ),
get_console_url=dict(
type='bool',
default=False,
),
clone_from=dict(
type='dict',
options=dict(
id=dict(
type='int',
required=True,
),
force=dict(
type='bool',
default=False,
),
snapshot=dict(
type='dict',
options=dict(
name=dict(
type='str',
),
timestamp=dict(
type='int',
),
datetime=dict(
type='str',
),
),
mutually_exclusive=[
('name', 'timestamp', 'datetime'),
],
),
),
),
), ),
supports_check_mode=True, supports_check_mode=True,
required_one_of=[ required_one_of=[
('id', 'name'), ('id', 'name'),
], ],
required_by={
'clone_from': 'name',
},
) )
def check_amodule_args_for_change(self): def check_amodule_args_for_change(self):
check_errors = False check_errors = False
new_boot_disk_size = self.amodule.params['boot_disk'] comp_info = self.vm_to_clone_info or self.comp_info
if new_boot_disk_size is not None: comp_id = comp_info['id']
for disk in self.comp_info['disks']:
if disk['type'] == 'B': aparam_boot = self.amodule.params['boot']
boot_disk_size = disk['sizeMax'] if aparam_boot is not None:
break new_boot_disk_size = aparam_boot['disk_size']
else: if new_boot_disk_size is not None:
check_errors = True boot_disk_size = 0
self.message( for disk in self.comp_info['disks']:
f'Can\'t set boot disk size for Compute ' if disk['type'] == 'B':
f'{self.comp_info["id"]}, because it doesn\'t have a ' boot_disk_size = disk['sizeMax']
f'boot disk.' break
) else:
if aparam_boot is None or aparam_boot['disk_id'] is None:
check_errors = True
self.message(
f'Can\'t set boot disk size for Compute '
f'{comp_id}, because it doesn\'t '
f'have a boot disk.'
)
if new_boot_disk_size < boot_disk_size:
check_errors = True
self.message(
f'New boot disk size {new_boot_disk_size} is less'
f' than current {boot_disk_size} for Compute ID '
f'{comp_id}'
)
if new_boot_disk_size < boot_disk_size: aparam_disks = self.amodule.params['disks']
check_errors = True aparam_boot_disk_id = aparam_boot['disk_id']
self.message( comp_disk_ids = [disk['id'] for disk in self.comp_info['disks']]
f'New boot disk size {new_boot_disk_size} is less than ' if aparam_disks is None:
f'current {boot_disk_size} for Compute ID ' if (
f'{self.comp_info["id"]}' aparam_boot_disk_id is not None
) and aparam_boot_disk_id not in comp_disk_ids
):
check_errors = True
self.message(
f'Check for parameter "boot.disk_id" failed: '
f'disk {aparam_boot_disk_id} is not attached to '
f'Compute ID {self.comp_id}.'
)
else:
match aparam_disks['mode']:
case 'update':
if (
aparam_boot_disk_id not in comp_disk_ids
and aparam_boot_disk_id not in aparam_disks['ids']
):
check_errors = True
self.message(
f'Check for parameter "boot.disk_id" failed: '
f'disk {aparam_boot_disk_id} is not attached '
f'to Compute ID {self.comp_id}.'
)
case 'match':
if aparam_boot_disk_id not in aparam_disks['ids']:
check_errors = True
self.message(
f'Check for parameter "boot.disk_id" failed: '
f'disk {aparam_boot_disk_id} is not in '
f'disks.ids'
)
case 'detach' | 'delete':
if aparam_boot_disk_id in aparam_disks['ids']:
check_errors = True
self.message(
f'Check for parameter "boot.disk_id" failed: '
f'disk {aparam_boot_disk_id} cannot be '
f'detached or deleted to set as boot disk.'
)
elif aparam_boot_disk_id not in comp_disk_ids:
check_errors = True
self.message(
f'Check for parameter "boot.disk_id" failed: '
f'disk {aparam_boot_disk_id} is not attached '
f'to Compute ID {self.comp_id}.'
)
if ( if (
not self.comp_info['imageId'] not comp_info['imageId']
and self.amodule.params['state'] in ('poweredon', 'paused') and self.amodule.params['state'] in ('poweredon', 'paused')
): ):
check_errors = True check_errors = True
@ -880,7 +1079,7 @@ class decort_kvmvm(DecortController):
is_vm_stopped_or_will_be_stopped = ( is_vm_stopped_or_will_be_stopped = (
( (
self.comp_info['techStatus'] == 'STOPPED' comp_info['techStatus'] == 'STOPPED'
and ( and (
self.amodule.params['state'] is None self.amodule.params['state'] is None
or self.amodule.params['state'] in ( or self.amodule.params['state'] in (
@ -889,7 +1088,7 @@ class decort_kvmvm(DecortController):
) )
) )
or ( or (
self.comp_info['techStatus'] != 'STOPPED' comp_info['techStatus'] != 'STOPPED'
and self.amodule.params['state'] in ( and self.amodule.params['state'] in (
'halted', 'poweredoff', 'halted', 'poweredoff',
) )
@ -905,7 +1104,7 @@ class decort_kvmvm(DecortController):
) )
vm_snapshot_labels = [ vm_snapshot_labels = [
snapshot['label'] for snapshot in self.comp_info['snapSets'] snapshot['label'] for snapshot in comp_info['snapSets']
] ]
if self.amodule.params['rollback_to'] not in vm_snapshot_labels: if self.amodule.params['rollback_to'] not in vm_snapshot_labels:
check_errors = True check_errors = True
@ -913,7 +1112,7 @@ class decort_kvmvm(DecortController):
f'Check for parameter "rollback_to" failed: ' f'Check for parameter "rollback_to" failed: '
f'snapshot with label ' f'snapshot with label '
f'{self.amodule.params["rollback_to"]} does not exist ' f'{self.amodule.params["rollback_to"]} does not exist '
f'for VM ID{self.comp_info["id"]}.' f'for VM ID {comp_id}.'
) )
params_to_check = { params_to_check = {
@ -925,7 +1124,7 @@ class decort_kvmvm(DecortController):
for param_name, comp_field_name in params_to_check.items(): for param_name, comp_field_name in params_to_check.items():
if ( if (
self.aparams[param_name] is not None self.aparams[param_name] is not None
and self.comp_info[comp_field_name] != self.aparams[param_name] and comp_info[comp_field_name] != self.aparams[param_name]
and not is_vm_stopped_or_will_be_stopped and not is_vm_stopped_or_will_be_stopped
): ):
check_errors = True check_errors = True
@ -944,7 +1143,7 @@ class decort_kvmvm(DecortController):
if ( if (
self.aparam_networks_has_dpdk self.aparam_networks_has_dpdk
and not self.comp_info['hpBacked'] and not comp_info['hpBacked']
and not self.aparams['hp_backed'] and not self.aparams['hp_backed']
): ):
check_errors = True check_errors = True
@ -954,9 +1153,149 @@ class decort_kvmvm(DecortController):
'to a DPDK network.' 'to a DPDK network.'
) )
is_vm_started_or_will_be_started = (
(
comp_info['techStatus'] == 'STARTED'
and (
self.amodule.params['state'] is None
or self.amodule.params['state'] in (
'poweredon', 'present',
)
)
)
or (
comp_info['techStatus'] != 'STARTED'
and self.amodule.params['state'] == 'poweredon'
)
)
if self.amodule.params['get_console_url']:
if not is_vm_started_or_will_be_started:
check_errors = True
self.message(
'Check for parameter "get_console_url" failed: '
'VM must be started to get console url.'
)
aparam_disks = self.aparams['disks']
if aparam_disks is not None:
if self.comp_info['snapSets']:
match aparam_disks['mode']:
case 'detach' | 'delete':
check_errors = True
self.message(
f'Check for parameter "disks" failed: '
f'cannot {aparam_disks["mode"]} disks for '
f'Compute ID {self.comp_id} while snapshots '
f'exist in compute.'
)
case 'match':
comp_disk_ids = {
disk['id'] for disk in self.comp_info['disks']
}
disks = set(aparam_disks['ids'])
disks_to_detach = comp_disk_ids - disks
if disks_to_detach:
check_errors = True
self.message(
f'Check for parameter "disks" failed: '
f'disks {disks_to_detach} cannot be detached '
f'from Compute ID {self.comp_id} while '
f'snapshots exist in compute.'
)
if check_errors:
self.exit(fail=True)
def check_amodule_args_for_clone(self, clone_id: int, clone_dict: dict):
check_errors = False
aparam_clone_from = self.aparams['clone_from']
if (
clone_id
and clone_dict['cloneReference'] != self.vm_to_clone_id
):
check_errors = True
self.message(
'Check for parameter "name" failed: '
f'VM with name {self.aparams["name"]} '
f'already exists.'
)
if (
self.vm_to_clone_info['techStatus'] == 'STARTED'
and not aparam_clone_from['force']
):
check_errors = True
self.message(
'Check for parameter "clone_from.force" failed: '
'VM must be stopped or parameter "force" must be True '
'to clone it.'
)
aparam_snapshot = aparam_clone_from['snapshot']
snapshot_timestamps = [
snapshot['timestamp']
for snapshot in self.vm_to_clone_info['snapSets']
]
if aparam_snapshot is not None:
if (
aparam_snapshot['name'] is not None
and aparam_snapshot['name'] not in (
snapshot['label']
for snapshot in self.vm_to_clone_info['snapSets']
)
):
check_errors = True
self.message(
'Check for parameter "clone_from.snapshot.name" '
'failed: snapshot with name '
f'{aparam_snapshot["name"]} does not exist for VM ID '
f'{self.vm_to_clone_id}.'
)
if (
aparam_snapshot['timestamp'] is not None
and aparam_snapshot['timestamp'] not in snapshot_timestamps
):
check_errors = True
self.message(
'Check for parameter "clone_from.snapshot.timestamp" '
'failed: snapshot with timestamp '
f'{aparam_snapshot["timestamp"]} does not exist for '
f'VM ID {self.vm_to_clone_id}.'
)
if aparam_snapshot['datetime'] is not None:
timestamp_from_dt_str = self.dt_str_to_sec(
dt_str=aparam_snapshot['datetime']
)
if timestamp_from_dt_str not in snapshot_timestamps:
check_errors = True
self.message(
'Check for parameter "clone_from.snapshot.datetime" '
'failed: snapshot with datetime '
f'{aparam_snapshot["datetime"]} does not exist for '
f'VM ID {self.vm_to_clone_id}.'
)
if check_errors: if check_errors:
self.exit(fail=True) self.exit(fail=True)
def clone(self):
clone_from_snapshot = self.aparams['clone_from']['snapshot']
snapshot_timestamp, snapshot_name, snapshot_datetime = None, None, None
if clone_from_snapshot:
snapshot_timestamp = clone_from_snapshot['timestamp']
snapshot_name = clone_from_snapshot['name']
snapshot_datetime = clone_from_snapshot['datetime']
clone_id = self.compute_clone(
compute_id=self.vm_to_clone_id,
name=self.aparams['name'],
force=self.aparams['clone_from']['force'],
snapshot_timestamp=snapshot_timestamp,
snapshot_name=snapshot_name,
snapshot_datetime=snapshot_datetime,
)
return clone_id
# Workflow digest: # Workflow digest:
# 1) authenticate to DECORT controller & validate authentication by issuing API call - done when creating DECSController # 1) authenticate to DECORT controller & validate authentication by issuing API call - done when creating DECSController
# 2) check if the VM with the specified id or rg_name:name exists # 2) check if the VM with the specified id or rg_name:name exists
@ -976,8 +1315,6 @@ def main():
amodule = subj.amodule amodule = subj.amodule
if subj.comp_id: if subj.comp_id:
subj.check_amodule_args_for_change()
if subj.comp_info['status'] in ("DISABLED", "MIGRATING", "DELETING", "DESTROYING", "ERROR", "REDEPLOYING"): if subj.comp_info['status'] in ("DISABLED", "MIGRATING", "DELETING", "DESTROYING", "ERROR", "REDEPLOYING"):
# cannot do anything on the existing Compute in the listed states # cannot do anything on the existing Compute in the listed states
subj.error() # was subj.nop() subj.error() # was subj.nop()
@ -1001,6 +1338,7 @@ def main():
_, subj.comp_info, _ = subj.compute_find( _, subj.comp_info, _ = subj.compute_find(
comp_id=subj.comp_id, comp_id=subj.comp_id,
need_custom_fields=True, need_custom_fields=True,
need_console_url=amodule.params['get_console_url'],
) )
subj.modify() subj.modify()
elif amodule.params['state'] == 'absent': elif amodule.params['state'] == 'absent':
@ -1041,6 +1379,7 @@ def main():
_, subj.comp_info, _ = subj.compute_find( _, subj.comp_info, _ = subj.compute_find(
comp_id=subj.comp_id, comp_id=subj.comp_id,
need_custom_fields=True, need_custom_fields=True,
need_console_url=amodule.params['get_console_url'],
) )
# #
# We no longer need to re-read RG facts, as all network info is now available inside # We no longer need to re-read RG facts, as all network info is now available inside

@ -103,19 +103,16 @@ class decort_lb(DecortController):
self.rg_id,self.vins_id, self.rg_id,self.vins_id,
self.amodule.params['ext_net_id'], self.amodule.params['ext_net_id'],
self.amodule.params['ha_lb'], self.amodule.params['ha_lb'],
self.amodule.params['description']) self.amodule.params['description'],
sysctl=self.amodule.params['sysctl'],)
if self.lb_id and (self.amodule.params['backends'] or if self.lb_id and (self.amodule.params['backends'] or
self.amodule.params['frontends']): self.amodule.params['frontends']):
self.lb_id, self.lb_facts = self.lb_find(0,self.amodule.params['lb_name'],self.rg_id) self.lb_id, self.lb_facts = self.lb_find(0,self.amodule.params['lb_name'],self.rg_id)
self.lb_update( self.lb_update(
self.lb_facts['primaryNode'], lb_facts=self.lb_facts,
self.lb_facts['frontendHAIP'], aparam_backends=self.amodule.params['backends'],
self.lb_facts['backendHAIP'], aparam_frontends=self.amodule.params['frontends'],
self.lb_facts['backends'], aparam_servers=self.amodule.params['servers'],
self.lb_facts['frontends'],
self.amodule.params['backends'],
self.amodule.params['servers'],
self.amodule.params['frontends']
) )
return return
@ -127,14 +124,11 @@ class decort_lb(DecortController):
_, self.lb_facts = self._lb_get_by_id(lb_id=self.lb_id) _, self.lb_facts = self._lb_get_by_id(lb_id=self.lb_id)
self.lb_update( self.lb_update(
self.lb_facts['primaryNode'], lb_facts=self.lb_facts,
self.lb_facts['frontendHAIP'], aparam_backends=self.amodule.params['backends'],
self.lb_facts['backendHAIP'], aparam_frontends=self.amodule.params['frontends'],
self.lb_facts['backends'], aparam_servers=self.amodule.params['servers'],
self.lb_facts['frontends'], aparam_sysctl=self.aparams['sysctl'],
self.amodule.params['backends'],
self.amodule.params['servers'],
self.amodule.params['frontends'],
) )
if d_state != '': if d_state != '':
@ -196,6 +190,7 @@ class decort_lb(DecortController):
ret_dict = dict(id=0, ret_dict = dict(id=0,
name="none", name="none",
state="CHECK_MODE", state="CHECK_MODE",
sysctl={},
) )
if arg_check_mode: if arg_check_mode:
@ -216,6 +211,7 @@ class decort_lb(DecortController):
if self.amodule.params['state']!="absent": if self.amodule.params['state']!="absent":
ret_dict['backends'] = self.lb_facts['backends'] ret_dict['backends'] = self.lb_facts['backends']
ret_dict['frontends'] = self.lb_facts['frontends'] ret_dict['frontends'] = self.lb_facts['frontends']
ret_dict['sysctl'] = self.lb_facts['sysctlParams']
return ret_dict return ret_dict
@property @property
@ -292,6 +288,9 @@ class decort_lb(DecortController):
type='bool', type='bool',
default=False, default=False,
), ),
sysctl=dict(
type='dict',
),
), ),
supports_check_mode=True, supports_check_mode=True,
required_one_of=[ required_one_of=[

@ -279,9 +279,8 @@ def main():
amodule.exit_json(**decon.result) amodule.exit_json(**decon.result)
if decon.validated_virt_image_id > 0 and amodule.params['state'] == "absent": if decon.validated_virt_image_id > 0 and amodule.params['state'] == "absent":
decon.result['msg'] = ("Osimage module cannot delete virtual images.") amodule.image_id_delete = decon.validated_virt_image_id
decon.result['failed'] = True decort_osimage.decort_image_delete(decon, amodule)
amodule.exit_json(**decon.result)
elif amodule.params['image_name'] or amodule.params['image_id']: elif amodule.params['image_name'] or amodule.params['image_id']:
image_id, image_facts = decort_osimage.decort_image_find(decon, amodule) image_id, image_facts = decort_osimage.decort_image_find(decon, amodule)

@ -121,6 +121,7 @@ class decort_rg(DecortController):
arg_res_types=self.amodule.params['resType'], arg_res_types=self.amodule.params['resType'],
arg_newname=self.amodule.params['rename'], arg_newname=self.amodule.params['rename'],
arg_sep_pools=self.amodule.params['sep_pools'], arg_sep_pools=self.amodule.params['sep_pools'],
arg_desc=self.amodule.params['description'],
) )
self.rg_should_exist = True self.rg_should_exist = True
return return
@ -235,6 +236,7 @@ class decort_rg(DecortController):
ret_dict['ViNS'] = self.rg_facts['vins'] ret_dict['ViNS'] = self.rg_facts['vins']
ret_dict['computes'] = self.rg_facts['vms'] ret_dict['computes'] = self.rg_facts['vms']
ret_dict['uniqPools'] = self.rg_facts['uniqPools'] ret_dict['uniqPools'] = self.rg_facts['uniqPools']
ret_dict['description'] = self.rg_facts['desc']
return ret_dict return ret_dict
@ -362,6 +364,7 @@ def main():
or amodule.params['resType'] or amodule.params['resType']
or amodule.params['rename'] != "" or amodule.params['rename'] != ""
or amodule.params['sep_pools'] is not None or amodule.params['sep_pools'] is not None
or amodule.params['description'] is not None
): ):
decon.update() decon.update()
if amodule.params['access']: if amodule.params['access']:

@ -1130,81 +1130,77 @@ class DecortController(object):
break break
return return
def compute_data_disks(self, comp_dict, new_data_disks): @waypoint
"""Manage attachment of data disks to the Compute instance. @checkmode
def compute_disks(self, comp_dict: dict, aparam_disks: dict):
@param (dict) comp_dict: dictionary with Compute facts, that identifies the Compute instance disks = set(aparam_disks['ids'])
to manage data disks for. mode = aparam_disks['mode']
@param (list of int) new_data_disks: list of integer IDs for the disks that must be attached to
this Compute instance. If some disk IDs appear in this list, but are not present in comp_dict, comp_disks = {disk['id'] for disk in comp_dict['disks']}
these disks will be attached. Vice versa, if some disks appear in comp_dict but are not present disks_to_attach = set()
in data_disks, such disks will be detached. disks_to_detach = set()
disks_to_delete = set()
Note: match mode:
1) you cannot control boot disk attachment, so including this Compute's boot disk ID case 'update':
into data_disk list will have no effect (as well as not listing it there). disks_to_attach = disks - comp_disks
2) this function may modify data_disks by removing from it an ID that corresponds to case 'detach':
this Compute's boot disk (if found). disks_to_detach = disks & comp_disks
3) In view of #2, upstream code may need to reread compute facts (com_dict) so that it case 'delete':
contains updated information about attached disks. disks_to_delete = disks & comp_disks
""" case 'match':
disks_to_attach = disks - comp_disks
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "compute_data_disks") disks_to_detach = comp_disks - disks
if self.amodule.check_mode: for disk_id in disks_to_attach:
self.result['failed'] = False api_params = {
self.result['msg'] = ("compute_data_disks() in check mode: managing data disks on Compute " 'computeId': comp_dict['id'],
"ID {} was requested.").format(comp_dict['id']) 'diskId': disk_id,
return 'diskType': 'D',
}
bdisk_id = 0 self.decort_api_call(
current_list = [] arg_req_function=requests.post,
detach_list = [] arg_api_name='/restmachine/cloudapi/compute/diskAttach',
attach_list = [] arg_params=api_params,
)
# 'data_disks' argument for decort_kvmvm module expects list of integer disk IDs. self.set_changed()
# However, if the value for disk ID comes via Jinja templating like this:
# data_disks:
# - "{{ my_disk.facts.id }}" <= will come as string, which is WRONG!!!
# - 4571 <= no Jinja templae, will come as int - OK
#
# then all values when entering this method will be of type string. We need to
# explicitly cast int type on all of them.
if new_data_disks is not None:
for idx, repair in enumerate(new_data_disks):
new_data_disks[idx] = int(repair)
else:
new_data_disks = []
for disk in comp_dict['disks']:
if disk['type'] == 'B':
bdisk_id = disk['id']
if bdisk_id in new_data_disks:
# If boot disk ID is listed in data_disks - remove it
new_data_disks.remove(bdisk_id)
elif disk['type'] == 'D':
# build manipulation sets for 'D' type disks only
current_list.append(disk['id'])
if disk['id'] not in new_data_disks:
detach_list.append(disk['id'])
attach_list = [did for did in new_data_disks if did not in current_list]
for did in detach_list:
api_params = dict(computeId=comp_dict['id'], diskId=did)
self.decort_api_call(requests.post, "/restmachine/cloudapi/compute/diskDetach", api_params)
# On success the above call will return here. On error it will abort execution by calling fail_json.
self.result['changed'] = True
for did in attach_list: for disk_id in disks_to_detach:
api_params = dict(computeId=comp_dict['id'], diskId=did) api_params = {
self.decort_api_call(requests.post, "/restmachine/cloudapi/compute/diskAttach", api_params) 'computeId': comp_dict['id'],
# On success the above call will return here. On error it will abort execution by calling fail_json. 'diskId': disk_id,
self.result['changed'] = True }
self.decort_api_call(
arg_req_function=requests.post,
arg_api_name='/restmachine/cloudapi/compute/diskDetach',
arg_params=api_params,
)
self.set_changed()
self.result['failed'] = False for disk_id in disks_to_delete:
api_params = {
'computeId': comp_dict['id'],
'diskId': disk_id,
}
self.decort_api_call(
arg_req_function=requests.post,
arg_api_name='/restmachine/cloudapi/compute/diskDel',
arg_params=api_params,
)
self.set_changed()
return @waypoint
@checkmode
def compute_boot_disk(self, comp_id: int, boot_disk: int):
api_params = {
'computeId': comp_id,
'diskId': boot_disk,
}
self.decort_api_call(
arg_req_function=requests.post,
arg_api_name='/restmachine/cloudapi/compute/bootDiskSet',
arg_params=api_params,
)
self.set_changed()
def compute_delete(self, comp_id, permanently=False,detach=True): def compute_delete(self, comp_id, permanently=False,detach=True):
"""Delete a Compute instance identified by its ID. It is assumed that the Compute with the specified """Delete a Compute instance identified by its ID. It is assumed that the Compute with the specified
@ -1233,7 +1229,12 @@ class DecortController(object):
return return
def _compute_get_by_id(self, comp_id, need_custom_fields: bool = False): def _compute_get_by_id(
self,
comp_id,
need_custom_fields: bool = False,
need_console_url: bool = False,
):
"""Helper function that locates compute instance by ID and returns Compute facts. """Helper function that locates compute instance by ID and returns Compute facts.
@param (int) comp_id: ID of the Compute instance to find and return facts for. @param (int) comp_id: ID of the Compute instance to find and return facts for.
@ -1266,16 +1267,23 @@ class DecortController(object):
) )
ret_comp_dict['custom_fields'] = custom_fields ret_comp_dict['custom_fields'] = custom_fields
if need_console_url and ret_comp_dict['techStatus'] == 'STARTED':
console_url = self.compute_get_console_url(
compute_id=ret_comp_id,
)
ret_comp_dict['console_url'] = console_url
else: else:
self.result['warning'] = ("compute_get_by_id(): failed to get Compute by ID {}. HTTP code {}, " self.result['warning'] = ("compute_get_by_id(): failed to get Compute by ID {}. HTTP code {}, "
"response {}.").format(comp_id, api_resp.status_code, api_resp.reason) "response {}.").format(comp_id, api_resp.status_code, api_resp.reason)
return ret_comp_id, ret_comp_dict, ret_rg_id return ret_comp_id, ret_comp_dict, ret_rg_id
def compute_find(self, comp_id, def compute_find(self, comp_id: int = 0,
comp_name="", rg_id=0, comp_name="", rg_id=0,
check_state=True, check_state=True,
need_custom_fields: bool = False): need_custom_fields: bool = False,
need_console_url: bool = False):
"""Tries to find Compute instance according to the specified parameters. On success returns non-zero """Tries to find Compute instance according to the specified parameters. On success returns non-zero
Compute ID and a dictionary with Compute details, or 0 for ID and None for the dictionary on failure. Compute ID and a dictionary with Compute details, or 0 for ID and None for the dictionary on failure.
@ -1312,6 +1320,7 @@ class DecortController(object):
self._compute_get_by_id( self._compute_get_by_id(
comp_id=comp_id, comp_id=comp_id,
need_custom_fields=need_custom_fields, need_custom_fields=need_custom_fields,
need_console_url=need_console_url,
) )
) )
if not ret_comp_id: if not ret_comp_id:
@ -1352,6 +1361,7 @@ class DecortController(object):
_, ret_comp_dict, _ = self._compute_get_by_id( _, ret_comp_dict, _ = self._compute_get_by_id(
comp_id=ret_comp_id, comp_id=ret_comp_id,
need_custom_fields=need_custom_fields, need_custom_fields=need_custom_fields,
need_console_url=need_console_url,
) )
break break
@ -1436,7 +1446,7 @@ class DecortController(object):
def kvmvm_provision(self, rg_id, def kvmvm_provision(self, rg_id,
comp_name, comp_name,
cpu, ram, cpu, ram,
boot_disk, boot_disk_size,
image_id, image_id,
chipset: Literal['Q35', 'i440fx'] = 'i440fx', chipset: Literal['Q35', 'i440fx'] = 'i440fx',
description="", description="",
@ -1478,12 +1488,12 @@ class DecortController(object):
'name': comp_name, 'name': comp_name,
'cpu': cpu, 'cpu': cpu,
'ram': ram, 'ram': ram,
'bootDisk': boot_disk, 'bootDisk': boot_disk_size,
'sepId': sep_id, 'sepId': sep_id,
'pool': pool_name, 'pool': pool_name,
'interfaces': '[]', # we create VM without any network connections 'interfaces': '[]', # we create VM without any network connections
'chipset': chipset, 'chipset': chipset,
'withoutBootDisk': not boot_disk, 'withoutBootDisk': not boot_disk_size,
'preferredCpu': preferred_cpu_cores, 'preferredCpu': preferred_cpu_cores,
} }
if description: if description:
@ -2096,6 +2106,48 @@ class DecortController(object):
) )
self.set_changed() self.set_changed()
@waypoint
@checkmode
def compute_clone(
self,
compute_id: int,
name: str,
snapshot_timestamp: int | None = None,
snapshot_name: str | None = None,
snapshot_datetime: str | None = None,
force: bool = False,
):
_snapshot_timestamp = snapshot_timestamp
if snapshot_datetime:
_snapshot_timestamp = self.dt_str_to_sec(dt_str=snapshot_datetime)
api_params = {
'computeId': compute_id,
'name': name,
'force': force,
'snapshotName': snapshot_name,
'snapshotTimestamp': _snapshot_timestamp,
}
api_resp = self.decort_api_call(
arg_req_function=requests.post,
arg_api_name='/restmachine/cloudapi/compute/clone',
arg_params=api_params,
)
self.set_changed()
return int(api_resp.content)
@waypoint
def compute_get_console_url(self, compute_id: int):
api_response = self.decort_api_call(
arg_req_function=requests.post,
arg_api_name='/restmachine/cloudapi/compute/getConsoleUrl',
arg_params={
'computeId': compute_id,
},
)
return api_response.text
################################### ###################################
# OS image manipulation methods # OS image manipulation methods
################################### ###################################
@ -2616,7 +2668,7 @@ class DecortController(object):
# TODO: this method will not work in its current implementation. Update it for new .../rg/update specs. # TODO: this method will not work in its current implementation. Update it for new .../rg/update specs.
def rg_update(self, arg_rg_dict, arg_quotas, arg_res_types, arg_newname, arg_sep_pools): def rg_update(self, arg_rg_dict, arg_quotas, arg_res_types, arg_newname, arg_sep_pools, arg_desc: str | None = None):
"""Manage quotas for an existing RG. """Manage quotas for an existing RG.
@param arg_rg_dict: dictionary with RG facts as returned by rg_find(...) method or .../rg/get API @param arg_rg_dict: dictionary with RG facts as returned by rg_find(...) method or .../rg/get API
@ -2697,6 +2749,10 @@ class DecortController(object):
api_params['clearUniqPools'] = True api_params['clearUniqPools'] = True
update_required = True update_required = True
if arg_desc is not None and arg_desc != arg_rg_dict['desc']:
api_params['desc'] = arg_desc
update_required = True
if update_required: if update_required:
self.decort_api_call(requests.post, "/restmachine/cloudapi/rg/update", api_params) self.decort_api_call(requests.post, "/restmachine/cloudapi/rg/update", api_params)
# On success the above call will return here. On error it will abort execution by calling fail_json. # On success the above call will return here. On error it will abort execution by calling fail_json.
@ -4518,7 +4574,7 @@ class DecortController(object):
return 0, None return 0, None
def disk_create(self, accountId, name, description, size, type, iops, sep_id, pool): def disk_create(self, accountId, name, description, size, iops, sep_id, pool):
"""Provision Disk according to the specified arguments. """Provision Disk according to the specified arguments.
Note that disks created by this method will be of type 'D' (data disks). Note that disks created by this method will be of type 'D' (data disks).
If critical error occurs the embedded call to API function will abort further execution If critical error occurs the embedded call to API function will abort further execution
@ -4542,7 +4598,6 @@ class DecortController(object):
name=name, name=name,
description=description, description=description,
size=size, size=size,
type=type,
iops=iops, iops=iops,
sep_id=sep_id, sep_id=sep_id,
pool=pool ) pool=pool )
@ -5140,6 +5195,7 @@ class DecortController(object):
description, description,
extnet_only, extnet_only,
master_chipset: Literal['Q35', 'i440fx'] = 'i440fx', master_chipset: Literal['Q35', 'i440fx'] = 'i440fx',
lb_sysctl: dict | None = None,
): ):
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "k8s_provision") self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "k8s_provision")
@ -5185,6 +5241,9 @@ class DecortController(object):
userData=json.dumps(default_worker['ci_user_data']), userData=json.dumps(default_worker['ci_user_data']),
extnetOnly=extnet_only, extnetOnly=extnet_only,
chipset=master_chipset, chipset=master_chipset,
lbSysctlParams=lb_sysctl and json.dumps(
{k: str(v) for k, v in lb_sysctl.items()}
),
) )
upload_files = None upload_files = None
@ -5903,7 +5962,7 @@ class DecortController(object):
self.amodule.fail_json(**self.result) self.amodule.fail_json(**self.result)
return 0, None return 0, None
def lb_provision(self,lb_name,rg_id,vins_id,ext_net_id,ha_status,description,start=True): def lb_provision(self,lb_name,rg_id,vins_id,ext_net_id,ha_status,description,start=True, sysctl: dict | None = None):
"""Provision LB according to the specified arguments. """Provision LB according to the specified arguments.
If critical error occurs the embedded call to API function will abort further execution of If critical error occurs the embedded call to API function will abort further execution of
the script and relay error to Ansible. the script and relay error to Ansible.
@ -5932,7 +5991,10 @@ class DecortController(object):
vinsId=vins_id, vinsId=vins_id,
highlyAvailable=ha_status, highlyAvailable=ha_status,
start=start, start=start,
desc=description desc=description,
sysctlParams=sysctl and json.dumps(
{k: str(v) for k, v in sysctl.items()}
),
) )
api_resp = self.decort_api_call(requests.post, api_url, api_params) api_resp = self.decort_api_call(requests.post, api_url, api_params)
# On success the above call will return here. On error it will abort execution by calling fail_json. # On success the above call will return here. On error it will abort execution by calling fail_json.
@ -6259,7 +6321,14 @@ class DecortController(object):
api_resp = self.decort_api_call(requests.post, api_url, api_params) api_resp = self.decort_api_call(requests.post, api_url, api_params)
self.result['changed'] = True self.result['changed'] = True
def lb_update(self,prime,front_ha_ip,back_ha_ip,lb_backends=[],lb_frontends=[],mod_backends=[],mod_servers=[],mod_frontends=[]): def lb_update(
self,
lb_facts: dict,
aparam_backends: list | None,
aparam_frontends: list | None,
aparam_servers: list | None,
aparam_sysctl: dict | None,
):
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_update") self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "lb_update")
@ -6271,11 +6340,13 @@ class DecortController(object):
self.result['msg'] = result_msg self.result['msg'] = result_msg
return return
if mod_backends is None: lb_backends = lb_facts['backends']
lb_frontends = lb_facts['frontends']
if aparam_backends is None:
upd_back_list = [back['name'] for back in lb_backends] upd_back_list = [back['name'] for back in lb_backends]
else: else:
#lists from module and cloud #lists from module and cloud
mod_backs_list = [back['name'] for back in mod_backends] mod_backs_list = [back['name'] for back in aparam_backends]
lb_backs_list = [back['name'] for back in lb_backends] lb_backs_list = [back['name'] for back in lb_backends]
#ADD\DEL\UPDATE LISTS OF BACKENDS #ADD\DEL\UPDATE LISTS OF BACKENDS
del_list_backs = set(lb_backs_list).difference(mod_backs_list) del_list_backs = set(lb_backs_list).difference(mod_backs_list)
@ -6294,21 +6365,21 @@ class DecortController(object):
if add_back_list: if add_back_list:
self._lb_create_backends( self._lb_create_backends(
add_back_list, add_back_list,
mod_backends, aparam_backends,
mod_servers aparam_servers
) )
if upd_back_list: if upd_back_list:
if mod_backends is not None or mod_servers is not None: if aparam_backends is not None or aparam_servers is not None:
self._lb_update_backends( self._lb_update_backends(
upd_back_list, upd_back_list,
lb_backends, lb_backends,
mod_backends, aparam_backends,
mod_servers, aparam_servers,
) )
if mod_frontends is not None: if aparam_frontends is not None:
mod_front_list = [front['name'] for front in mod_frontends] mod_front_list = [front['name'] for front in aparam_frontends]
lb_front_list = [front['name'] for front in lb_frontends] lb_front_list = [front['name'] for front in lb_frontends]
del_list_fronts = set(lb_front_list).difference(mod_front_list) del_list_fronts = set(lb_front_list).difference(mod_front_list)
@ -6318,6 +6389,8 @@ class DecortController(object):
if del_list_fronts: if del_list_fronts:
self._lb_delete_fronts(del_list_fronts) self._lb_delete_fronts(del_list_fronts)
front_ha_ip = lb_facts['frontendHAIP']
back_ha_ip = lb_facts['backendHAIP']
#set bind_ip #set bind_ip
if front_ha_ip != "": if front_ha_ip != "":
bind_ip = front_ha_ip bind_ip = front_ha_ip
@ -6326,15 +6399,24 @@ class DecortController(object):
bind_ip = back_ha_ip bind_ip = back_ha_ip
if front_ha_ip == "" and back_ha_ip == "": if front_ha_ip == "" and back_ha_ip == "":
prime = lb_facts['primaryNode']
if prime["frontendIp"] != "": if prime["frontendIp"] != "":
bind_ip = prime["frontendIp"] bind_ip = prime["frontendIp"]
else: else:
bind_ip = prime["backendIp"] bind_ip = prime["backendIp"]
if add_list_fronts: if add_list_fronts:
self._lb_add_fronts(add_list_fronts,mod_frontends,bind_ip) self._lb_add_fronts(add_list_fronts,aparam_frontends,bind_ip)
if upd_front_list: if upd_front_list:
self._lb_update_fronts(upd_front_list,lb_frontends,mod_frontends,bind_ip) self._lb_update_fronts(upd_front_list,lb_frontends,aparam_frontends,bind_ip)
if aparam_sysctl is not None:
sysctl_with_str_values = {k: str(v) for k, v in aparam_sysctl.items()}
if sysctl_with_str_values != lb_facts['sysctlParams']:
self.lb_update_sysctl(
lb_id=lb_facts['id'],
sysctl=aparam_sysctl,
)
return return
@ -6556,6 +6638,22 @@ class DecortController(object):
return return
@waypoint
@checkmode
def lb_update_sysctl(self, lb_id: int, sysctl: dict):
sysctl_with_str_values = json.dumps(
{k: str(v) for k, v in sysctl.items()}
)
self.decort_api_call(
arg_req_function=requests.post,
arg_api_name='/restmachine/cloudapi/lb/updateSysctlParams',
arg_params={
'lbId': lb_id,
'sysctlParams': sysctl_with_str_values,
},
)
self.set_changed()
@waypoint @waypoint
@checkmode @checkmode
def snapshot_create(self, compute_id: int, label: str): def snapshot_create(self, compute_id: int, label: str):

@ -0,0 +1,25 @@
1. [Введение](./введение.md)
- [Введение](./введение.md#введение)
- [Системные требования](./введение.md#системные-требования)
- [Подготовка к работе](./введение.md#подготовка-к-работе)
- [Авторизация](./введение.md#авторизация)
- [Общие параметры модулей для авторизации](./введение.md#общие-параметры-модулей-для-авторизации)
- [Пример авторизации с помощью DECS3O](./введение.md#пример-авторизации-с-помощью-decs3o)
- [Пример авторизации с помощью BVS](./введение.md#пример-авторизации-с-помощью-bvs)
- [Пример авторизации с помощью JSON Web Token](./введение.md#пример-авторизации-с-помощью-json-web-token)
2. Ansible модули DECORT:
- [Модуль decort_kvmvm](./модуль-decort_kvmvm.md) - управление виртуальными машинами
- [Модуль decort_osimage](./модуль-decort_osimage.md) - управление образами
- [Модуль decort_disk](./модуль-decort_disk.md) - управление дисками
- [Модуль decort_pfw](./модуль-decort_pfw.md) - управление правилами переадресации портов
- [Модуль decort_rg](./модуль-decort_rg.md) - управление ресурсными группами
- [Модуль decort_vins](./модуль-decort_vins.md) - управление внутренними сетями
- [Модуль decort_jwt](./модуль-decort_jwt.md) - получение авторизационного токена
- [Модуль decort_bservice](./модуль-decort_bservice.md) - управление базовыми службами
- [Модуль decort_group](./модуль-decort_group.md)- управление группами базовой службы
- [Модуль decort_k8s](./модуль-decort_k8s.md) - управление кластерами Kubernetes
- [Модуль decort_lb](./модуль-decort_lb.md) - управление балансировщиками нагрузки
- [Модуль decort_account_info](./модуль-decort_account_info.md) - получение информации об аккаунте
- [Модуль decort_account](./модуль-decort_account.md) - управление аккаунтами
- [Модуль decort_user_info](./модуль-decort_user_info.md) - получение информации о пользователе
- [Модуль decort_snapshot](./модуль-decort_snapshot.md) - управление снимками виртуальной машины

@ -0,0 +1,250 @@
# Модули Ansible для управления облачными ресурсами в платформе DECORT
## Введение
Настоящая документация содержит руководство пользователя по библиотеке модулей decort для Ansible. С помощью этих модулей Вы сможете управлять созданием и конфигурированием облачных ресурсов в платформе DECORT (Digital Energy Cloud Orchestration Technology).
По каждому модулю есть своя документация, в которой вы можете найти список доступных действий, подробную информацию о входных параметрах и возвращаемых данных, а также примеры использования.
## Системные требования
Убедитесь, что Ваша система соответствует требованиям для работы модуля DECORT.
Системные требования для работы модуля:
- Ansible 10.6.0
- Python 3.10.12
- PyJWT 2.10.1 Python module
- requests 2.32.3 Python module
- DynamiX Enterprise 4.2.0
## Подготовка к работе
Для начала работы необходимо, чтобы Ansible было известно местоположение файлов модулей. Для этого необходимо:
- либо разместить директории **library** и **module_utils** в одной директории с плейбуками
- либо в рабочей директории, из которой будет запускаться Ansible, разместить файл **ansible.cfg**, в котором задать пути к файлам модулей, например:
```
[defaults]
library=./library
module_utils=./module_utils
```
## Авторизация
### Общие параметры модулей для авторизации
<table>
<tr>
<th colspan="6">Параметр</th>
<th>Тип</th>
<th>Описание</th>
</tr>
<tr>
<td colspan="6">
app_id
</td>
<td>
(str)
</td>
<td>
Идентификатор приложения, использующийся для получения токена в режимах
<code>authenticator: bvs</code> или <code>authenticator: decs3o</code>.
Данный параметр является обязательным для указанных режимов. Если
параметр не задан в playbook, модуль будет использовать значение
переменной окружения <code>DECORT_APP_ID</code>.
</td>
</tr>
<tr>
<td colspan="6">
app_secret
</td>
<td>
(str)
</td>
<td>
Секретный ключ приложения, использующийся для получения токена в режимах
<code>authenticator: bvs</code> или <code>authenticator: decs3o</code>.
Данный параметр является обязательным для указанных режимов.
Так как он содержит секретную информацию, то его не рекомендуется
задавать непосредственно в playbook. Если параметр не задан в playbook,
то модуль будет использовать значение переменной окружения
<code>DECORT_APP_SECRET</code>.
</td>
</tr>
<tr>
<td colspan="6">
authenticator
</td>
<td>
(str)
<br>Значения:
<br/><code>bvs</code>
<br/><code>decs3o</code>
<br/><code>oauth2</code>
<br/><code>jwt</code>
<br>Default: <code>decs3o</code>
</td>
<td>
Режим аутентификации для получения токена.
Значение <code>oauth2</code> является устаревшим и равнозначным
<code>decs3o</code>.
</td>
</tr>
<tr>
<td colspan="6">
controller_url
</td>
<td>
(str)
</td>
<td>
URL контроллера, соответствующего экземпляру облачной платформы
DECORT. Данный параметр является обязательным.
</td>
</tr>
<tr>
<td colspan="6">
domain
</td>
<td>
(str)
</td>
<td>
Домен BVS, использующийся для получения токена в режиме
<code>authenticator: bvs</code>. Данный параметр является
обязательным для указанного режима. Если параметр не задан в playbook,
модуль будет использовать значение переменной окружения
<code>DECORT_DOMAIN</code>.
</td>
</tr>
<tr>
<td colspan="6">
jwt
</td>
<td>
(str)
</td>
<td>
JSON Web Token (JWT), который будет использоваться для подключения
к контроллеру облачной платформы DECORT в режиме
<code>authenticator: jwt</code>. Данный параметр является
обязательным для указанного режима. Так как он содержит
потенциально секретную информацию, а сам JWT, как правило,
имеет ограниченное время жизни, то его не рекомендуется задавать
непосредственно в playbook. Если этот параметр не определен в
playbook, то модуль будет использовать значение переменной
окружения <code>DECORT_JWT</code>.
</td>
</tr>
<tr>
<td colspan="6">
oauth2_url
</td>
<td>
(str)
</td>
<td>
URL авторизационного сервера, работающего по протоколу Oauth2,
который должен использоваться в режимах
<code>authenticator: bvs</code>
или <code>authenticator: decs3o</code>. Данный параметр является
обязательным для указанных режимов. Если параметр не задан в
playbook, модуль будет использовать значение переменной
окружения <code>DECORT_OAUTH2_URL</code>.
</td>
</tr>
<tr>
<td colspan="6">
password
</td>
<td>
(str)
</td>
<td>
Пароль пользователя, который должен использоваться в режиме
<code>authenticator: bvs</code>. Данный параметр является
обязательным для указанного режима. Так как он содержит секретную
информацию, то его не рекомендуется задавать непосредственно
в playbook. Если параметр не задан в playbook, модуль будет
использовать значение переменной окружения
<code>DECORT_PASSWORD</code>.
</td>
</tr>
<tr>
<td colspan="6">
username
</td>
<td>
(str)
</td>
<td>
Логин пользователя, который должен использоваться в режиме
<code>authenticator: bvs</code>. Данный параметр является
обязательным для указанного режима. Если параметр не задан в playbook,
модуль будет использовать значение переменной окружения
<code>DECORT_USERNAME</code>.
</td>
</tr>
<tr>
<td colspan="6">
verify_ssl
</td>
<td>
(bool)
<br>Default: <code>true</code>
</td>
<td>
Позволяет отключить проверку SSL сертификатов при выполнении API
вызовов в адрес контроллера облачной инфраструктуры, например,
при работе с изолированной облачной инфраструктурой, использующей
самоподписанные сертификаты. Применяйте данный параметр с
осторожностью, предпочтительно в защищенных средах.
</td>
</tr>
</table>
### Пример авторизации с помощью DECS3O
```
- name: Example
hosts: localhost
tasks:
- name: DECS3O auth
decort_module_name:
# Специфичные для модулей параметры упущены
# Пример демонстрирует только параметры для авторизации
app_id: "{{ app_id }}"
app_secret: "{{ app_secret }}"
authenticator: decs3o
controller_url: https://dynamix.local
oauth2_url: https://sso-dynamix.local
```
### Пример авторизации с помощью BVS
```
- name: Example
hosts: localhost
tasks:
- name: BVS auth
decort_module_name:
# Специфичные для модулей параметры упущены
# Пример демонстрирует только параметры для авторизации
app_id: "{{ app_id }}"
app_secret: "{{ app_secret }}"
authenticator: bvs
controller_url: https://dynamix.local
oauth2_url: https://bvs.local
domain: dynamix
username: "{{ username }}"
password: "{{ password }}"
```
### Пример авторизации с помощью JSON Web Token
```
- name: Example
hosts: localhost
tasks:
- name: Auth with JWT
decort_module_name:
# Специфичные для модулей параметры упущены
# Пример демонстрирует только параметры для авторизации
authenticator: jwt
controller_url: "{{ controller_url }}"
jwt: "{{ jwt }}"
```

@ -0,0 +1,992 @@
# Модуль decort_account
## Обзор модуля
Модуль **decort_account** предназначен для выполнения следующих действий над аккаунтом:
- **удалить в корзину** (см. [параметр state](#state) и [примеры](#в-корзину))
- **удалить безвозвратно** (см. [параметр state](#state) и [примеры](#безвозвратно))
- **восстановить из корзины** (см. [параметр state](#state) и [примеры](#восстановить-из-корзины))
- **выключить/включить** (см. [параметр state](#state) и [примеры](#выключитьвключить))
- **изменить права доступа** (см. [параметр acl](#acl) и [примеры](#изменить-права-доступа))
- **изменить имя** (см. [параметр name](#name) и [примеры](#переименовать))
- **изменить квоты** (см. [параметр quotas](#quotas) и [примеры](#изменить-квоты))
- **выключить/включить отправку уведомлений о предоставлении доступа к ресурсам** (см. [параметр access_emails](#access_emails) и [примеры](#выключитьвключить-отправку-уведомлений-о-предоставлении-доступа-к-ресурсам))
- **изменить доступные пулы СХД** (см. [параметр sep_pools](#sep_pools) и [примеры](#изменить-доступные-пулы-схд))
## Параметры модуля
Ниже приведен список параметров для модуля **decort_account** (за исключением [общих параметров авторизации](./введение.md#общие-параметры-модулей-для-авторизации)):
<table>
<tr>
<th colspan="6">Параметр</th>
<th>Тип</th>
<th>Описание</th>
</tr>
<tr>
<td colspan="6">
<a name="access_emails">
access_emails
</a>
</td>
<td>
(bool)
</td>
<td>
Выключение/включение отправки пользователям на эл. почту уведомлений о предоставлении доступа к ресурсам.
</td>
</tr>
<tr>
<td colspan="6">
<a name="acl">
acl
</a>
</td>
<td>
(dict)
</td>
<td>
Целевые права доступа.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
mode
</td>
<td>
(str)
<br>Значения:
<br><code>match</code>
<br><code>revoke</code>
<br><code>update</code>
<br>Default: <code>update</code>
</td>
<td>
Режим изменения прав доступа для указанных пользователей.
<br><code>match</code> - привести в соответствие для указанных
пользователей, удалить предоставленные для других.
<br><code>revoke</code> - отозвать для указанных пользователей,
если предоставлены.
<br><code>update</code> - привести в соответствие для указанных
пользователей, оставить без изменения предоставленные для
других.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
users
</td>
<td>
(list)
</td>
<td>
Список словарей, описывающих права доступа пользователей.
<br>Обязательный параметр.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td colspan="4">
rights
</td>
<td>
(str)
<br>Значения:
<br><code>R</code>
<br><code>RCX</code>
<br><code>ARCXDU</code>
<br>Default: <code>R</code>
</td>
<td>
Права доступа.
<br>При <code>mode: revoke</code> не используется.
<br>При <code>mode: match</code> и <code>mode: update</code>
права <code>ARCXDU</code> считаются соответствующими
правам <code>CXDRAU</code>.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td colspan="4">
id
</td>
<td>
(str)
</td>
<td>
Идентификатор пользователя.
<br>Обязательный параметр.
</td>
</tr>
<tr>
<td colspan="6">
id
</td>
<td>
(int)
</td>
<td>
Идентификатор целевого аккаунта.
<br>Обязательный параметр, если не задан параметр
<code>name</code>.
</td>
</tr>
<tr>
<td colspan="6">
<a name="name">
name
</a>
</td>
<td>
(str)
</td>
<td>
Имя целевого аккаунта.
<br>Может быть альтернативой параметру <code>id</code>,
за исключением случая, когда необходимо получить
информацию о безвозвратно удалённом объекте.
<br>Если задан совместно с параметром <code>id</code>,
то используется для переименования (целевое имя).
</td>
</tr>
<tr>
<td colspan="6">
<a name="quotas">
quotas
</a>
</td>
<td>
(dict)
</td>
<td>
Целевые квоты.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
cpu
</td>
<td>
(int)
</td>
<td>
Количество виртуальных процессоров.
<br><code>-1</code> - удалить квоту.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
disks_size
</td>
<td>
(int)
</td>
<td>
Объём дисков в ГБ.
<br><code>-1</code> - удалить квоту.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
ext_traffic
</td>
<td>
(int)
</td>
<td>
Объём трафика внешних сетей.
<br><code>-1</code> - удалить квоту.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
gpu
</td>
<td>
(int)
</td>
<td>
Количество графических процессоров.
<br><code>-1</code> - удалить квоту.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
public_ip
</td>
<td>
(int)
</td>
<td>
Количество внешних IP-адресов.
<br><code>-1</code> - удалить квоту.
</td>
</tr>
</tr>
<tr>
<td></td>
<td colspan="5">
ram
</td>
<td>
(int)
</td>
<td>
Объём оперативной памяти в МБ.
<br><code>-1</code> - удалить квоту.
</td>
</tr>
<tr>
<td colspan="6">
<a name="sep_pools">
sep_pools
</a>
</td>
<td>
(list)
</td>
<td>
Список словарей, описывающих доступные пулы СХД.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
sep_id
</td>
<td>
(int)
</td>
<td>
Идентификатор системы хранения данных.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
pool_names
</td>
<td>
(list)
</td>
<td>
Список названий пулов системы хранения данных.
</td>
</tr>
<tr>
<td colspan="6">
<a name="state">
state
</a>
</td>
<td>
(str)
<br>Значения:
<br><code>absent</code>
<br><code>absent_permanently</code>
<br><code>confirmed</code>
<br><code>disabled</code>
<br><code>present</code>
<br>Default: <code>present</code>
</td>
<td>
Целевое состояние.
<br><code>absent</code> - удалён в корзину, безвозвратно удалён
или не существует. Если существует и не удалён, то будет удалён
в корзину.
<br><code>absent_permanently</code> - безвозвратно удалён или
не существует. Если существует и не удалён или удалён в корзину,
то будет безвозвратно удалён.
<br> При значениях <code>absent</code> и <code>absent_permanently</code>
использование других параметров модуля, вызывающих изменение объекта,
не допускается.
<br><code>confirmed</code> - включён. Если выключен, то будет включён.
Если удалён в корзину, то будет восстановлен из корзины.
<br><code>disabled</code> - выключен. Если включён, то будет выключен.
Если удалён в корзину, то будет восстановлен из корзины и выключен.
<br><code>present</code> - существует и не удалён. Если удалён в
корзину, то будет восстановлен из корзины.
</td>
</tr>
</table>
## Возвращаемые значения
Модуль **decort_account** возвращает информацию об аккаунте в виде словаря `facts` со следующими ключами:
<table>
<tr>
<th colspan="6">
Ключ
</th>
<th>
Тип
<br>данных
</th>
<th>
Описание
</th>
</tr>
<tr>
<td colspan="6">
acl
</td>
<td>
list
</td>
<td>
Список словарей, описывающих доступы пользователей.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
canBeDeleted
</td>
<td>
bool
</td>
<td>
Может ли быть удалён.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
right
</td>
<td>
str
</td>
<td>
Права.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
status
</td>
<td>
str
</td>
<td>
Статус.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
type
</td>
<td>
str
</td>
<td>
Тип.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
userGroupId
</td>
<td>
str
</td>
<td>
Идентификатор пользователя или группы пользователей.
</td>
</tr>
<tr>
<td colspan="6">
company
</td>
<td>
str
</td>
<td>
Название компании.
</td>
</tr>
<tr>
<td colspan="6">
companyurl
</td>
<td>
str
</td>
<td>
URL компании.
</td>
</tr>
<tr>
<td colspan="6">
computeFeatures
</td>
<td>
list
</td>
<td>
Список дополнительных возможностей гипервизора, доступных ВМ.
</td>
</tr>
<tr>
<td colspan="6">
computes_amount
</td>
<td>
dict
</td>
<td>
Количество ВМ по состоянию.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
started
</td>
<td>
int
</td>
<td>
Количество запущенных ВМ.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
stopped
</td>
<td>
int
</td>
<td>
Количество остановленных ВМ.
</td>
</tr>
<tr>
<td colspan="6">
cpu_allocation_parameter
</td>
<td>
str
</td>
<td>
Режим выделения ЦП.
</td>
</tr>
<tr>
<td colspan="6">
cpu_allocation_ratio
</td>
<td>
str
</td>
<td>
Коэффициент для режима выделения ЦП.
</td>
</tr>
<tr>
<td colspan="6">
createdBy
</td>
<td>
str
</td>
<td>
Идентификатор пользователя, который создал.
</td>
</tr>
<tr>
<td colspan="6">
createdTime
</td>
<td>
int
</td>
<td>
Unix-время создания.
</td>
</tr>
<tr>
<td colspan="6">
createdTime_readable
</td>
<td>
str
</td>
<td>
Дата и время создания.
</td>
</tr>
<tr>
<td colspan="6">
deactivationTime
</td>
<td>
int
</td>
<td>
Unix-время выключения.
</td>
</tr>
<tr>
<td colspan="6">
deactivationTime_readable
</td>
<td>
str
</td>
<td>
Дата и время выключения.
</td>
</tr>
<tr>
<td colspan="6">
deletedBy
</td>
<td>
str
</td>
<td>
Идентификатор пользователя, который удалил.
</td>
</tr>
<tr>
<td colspan="6">
deletedTime
</td>
<td>
int
</td>
<td>
Unix-время удаления.
</td>
</tr>
<tr>
<td colspan="6">
deletedTime_readable
</td>
<td>
str
</td>
<td>
Дата и время удаления.
</td>
</tr>
<tr>
<td colspan="6">
displayname
</td>
<td>
str
</td>
<td>
Отображаемое имя.
</td>
</tr>
<tr>
<td colspan="6">
id
</td>
<td>
int
</td>
<td>
Идентификатор.
</td>
</tr>
<tr>
<td colspan="6">
name
</td>
<td>
str
</td>
<td>
Имя.
</td>
</tr>
<tr>
<td colspan="6">
resourceLimits
</td>
<td>
dict
</td>
<td>
Квоты на ресурсы.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
CU_C
</td>
<td>
int
</td>
<td>
Количество виртуальных процессоров.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
CU_D
</td>
<td>
int
</td>
<td>
Объём диска в ГБ.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
CU_DM
</td>
<td>
int
</td>
<td>
Объём дисков в ГБ.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
CU_I
</td>
<td>
int
</td>
<td>
Количество внешних IP-адресов.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
CU_M
</td>
<td>
float
</td>
<td>
Объём оперативной памяти в МБ.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
CU_NP
</td>
<td>
int
</td>
<td>
Объём трафика внешних сетей.
</td>
</tr>
<tr>
<td></td>
<td colspan="5">
gpu_units
</td>
<td>
int
</td>
<td>
Количество графических процессоров.
</td>
</tr>
<tr>
<td colspan="6">
sendAccessEmails
</td>
<td>
bool
</td>
<td>
Отправка пользователям на эл. почту уведомлений о предоставлении доступа.
</td>
</tr>
<tr>
<td colspan="6">
status
</td>
<td>
str
</td>
<td>
Статус.
</td>
</tr>
<tr>
<td colspan="6">
uniqPools
</td>
<td>
list
</td>
<td>
Список доступных пулов СХД.
</td>
</tr>
<tr>
<td colspan="6">
updatedTime
</td>
<td>
int
</td>
<td>
Unix-время обновления.
</td>
</tr>
<tr>
<td colspan="6">
updatedTime_readable
</td>
<td>
str
</td>
<td>
Дата и время обновления.
</td>
</tr>
<tr>
<td colspan="6">
vins
</td>
<td>
list
</td>
<td>
Список идентификаторов внутренних сетей на уровне аккаунта.
</td>
</tr>
<tr>
<td colspan="6">
vinses_amount
</td>
<td>
int
</td>
<td>
Количество внутренних сетей.
</td>
</tr>
</table>
## Примеры использования
### Удалить
#### В корзину
```
- name: Example
hosts: localhost
tasks:
- name: Delete account
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
state: absent
```
#### Безвозвратно
```
- name: Example
hosts: localhost
tasks:
- name: Delete account
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
state: absent_permanently
```
### Восстановить из корзины
```
- name: Example
hosts: localhost
tasks:
- name: Restore account from recycle bin
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
state: present
```
### Выключить/включить
#### Выключить
```
- name: Example
hosts: localhost
tasks:
- name: Disable account
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
state: disabled
```
#### Включить
```
- name: Example
hosts: localhost
tasks:
- name: Enable account
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
state: confirmed
```
### Изменить права доступа
#### Отозвать
```
- name: Example
hosts: localhost
tasks:
- name: Revoke user access rights
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
acl:
mode: revoke
users:
- id: "{{ user1_id }}"
- id: "{{ user2_id }}"
```
#### Обновить
```
- name: Example
hosts: localhost
tasks:
- name: Update user access rights
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
acl:
mode: update
users:
- id: "{{ user1_id }}"
rights: R
- id: "{{ user2_id }}"
rights: RCX
```
#### Привести в соответствие
```
- name: Example
hosts: localhost
tasks:
- name: Match user access rights
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
acl:
mode: match
users:
- id: "{{ user1_id }}"
rights: ARCXDU
- id: "{{ user2_id }}"
rights: RCX
```
### Переименовать
```
- name: Example
hosts: localhost
tasks:
- name: Rename account
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
name: "{{ account_new_name }}"
```
### Изменить квоты
#### На объём дисков
```
- name: Example
hosts: localhost
tasks:
- name: Update account quota of disks size
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
quotas:
disks_size: 500
```
#### На количество внешних IP-адресов
```
- name: Example
hosts: localhost
tasks:
- name: Update account quota of public IP amount
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
quotas:
public_ip: 10
```
### Выключить/включить отправку уведомлений о предоставлении доступа к ресурсам
#### Выключить
```
- name: Example
hosts: localhost
tasks:
- name: Disable sending access emails
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
access_emails: false
```
#### Включить
```
- name: Example
hosts: localhost
tasks:
- name: Enable sending access emails
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
access_emails: true
```
### Изменить доступные пулы СХД
```
- name: Example
hosts: localhost
tasks:
- name: Change available sep pools
decort_account:
# Параметры для авторизации упущены
id: "{{ account_id }}"
sep_pools:
- sep_id: 1
pool_names:
- pool1
```

File diff suppressed because it is too large Load Diff

@ -0,0 +1,82 @@
# Модуль decort_bservice
## Обзор модуля decort_bservice
Базовая служба (Basic Service) это несколько групп виртуальных серверов (compute), создаваемых и управляемых как единое целое.
Все compute(s) в группе имеют одни и те же характеристики (cpu/ram/boot disk size/OS image + сетевые подключения). Для разных групп эти характеристики могут быть разными.
Группы в составе Basic Service могут иметь отношения parent-child с другими группами. Наличие таких отношений определяет последовательность запуска групп ("сначала parents").
На основе ресурсов, предоставляемых и управляемых через Basic Service, могут создаваться другие сервисы.
`Для взаимодействия с группами виртуальных серверов используется модуль decort_group.`
Модуль decort_bservice предназначен для управления базовыми службами, в которых находятся группы виртуальных серверов.
Данный модуль позволяет:
- Создавать Basic Service
- Удалять Basic Service (безвозвратно).
- Включать/выключать Basic Service
- Запускать Basic Service
- Запрашивать информацию о Basic Service.
## Параметры модуля decort_bservice
Ниже приведен список параметров для модуля **decort_bservice** (за исключением [общих параметров авторизации](./введение.md#общие-параметры-модулей-для-авторизации)):
| Параметр | Тип, допустимые значения | Описание |
| ------ | ------ | ------ |
| account_id | (int) | Уникальный целочисленный идентификатор аккаунта, которому принадлежит ресурсная группа. При идентификации базовой службы и ресурсной группы по именам (см. параметры `name` и `rg_name`) должен быть задан либо идентификатор, либо имя аккаунта (см. параметр `account_name`). Если одновременно заданы и `account_id`, и `account_name`, то `account_name` игнорируется.|
|account_name | (string) | Имя аккаунта, которому принадлежит ресурсная группа. При идентификации базовой службы и ресурсной группы по именам (см. параметры `name` и `rg_name`) должен быть задан либо идентификатор (см. `account_id`), либо имя аккаунта. Если одновременно заданы и `account_id`, и `account_name`, то `account_name` игнорируется. |
|state | Значения: `absent`, `disabled`, `enabled`, `present`, `check`. <br> Default: `present`| Целевое состояние базовой службы. Значения `present` и `enabled` равнозначны.|
| started | (bool) <br> Default: `true` | Параметр, определяющий состояние добавленных виртуальных серверов в Basic Service. Запускать их, или нет. |
| name | (string) | Имя базовой службы. Данный параметр является обязательным при создании базовой службы и при изменении если не задан `id`. |
| sshuser | (string) | Имя пользователя, который будет создан на всех виртуальных серверах базовой службы. Используется в паре с `sshkey`. |
| sshkey | (string) | SSH ключ, который будет загружен на все виртуальные сервера базовой службы. Используется в паре с `sshuser`. |
| id | (int) | Уникальный целочисленный идентификатор базовой службы. Используется для поиска, изменения и удаления базовой службы. |
| rg_id | (int) | Уникальный целочисленный идентификатор ресурсной группы базовой службы. |
| rg_name | (string) | Имя ресурсной группы базовой службы. |
## Возвращаемые значения модуля decort_bservice
Модуль decort_bservice возвращает информацию о базовой службе в виде словаря facts со следующими ключами:
|Ключ | Тип данных | Описание|
| ------ | ------ | ------ |
|id | int | Уникальный целочисленный идентификатор базовой службы.|
|name | string | Имя базовой службы.|
| techStatus | string | Технический статус базовой службы. |
|state | string | Статус базовой службы.|
| rg_id | int | Уникальный целочисленный идентификатор ресурсной группы, в которой находится базовая служба.|
| account_id | int | Уникальный целочисленный идентификатор аккаунта, в котором находится ресурсная группа.|
| groups | list | Список словарей с информацией о группах базовой службы.|
## Пример использования модуля decort_bservice
Данный пример создаёт базовую службу с именем databases.
```
- name: Create Basic Service
decort_bservice:
authenticator: jwt
controller_url: "{{ controller_url }}"
jwt: "{{ auth_token }}"
name: databases
rg_id: "{{ rg_id }}"
register: db_bservice
```
Данный пример удаляет базовую службу с названием databases.
```
- name: Delete Basic Service
decort_bservice:
authenticator: jwt
controller_url: "{{ controller_url }}"
jwt: "{{ auth_token }}"
state: absent
name: databases
rg_id: "{{ rg_id }}"
register: db_bservice
```

@ -0,0 +1,159 @@
# Модуль decort_disk
## Обзор модуля decort_disk
Модуль decort_disk предназначен для управления дисками и позволяет производить с ними следующие действия:
- создавать
- удалять (в корзину или безвозвратно)
- восстановливать из корзины
- изменять:
- имя
- размер
- лимиты ввода/вывода
- включать/отключать общий доступ
## Параметры модуля decort_disk
Ниже приведен список параметров для модуля **decort_disk** (за исключением [общих параметров авторизации](./введение.md#общие-параметры-модулей-для-авторизации)):
| Параметр | Тип, допустимые значения | Описание |
| ------ | ------ | ------ |
| account_id | (int) | Уникальный целочисленный идентификатор аккаунта, которому принадлежит данный диск. При идентификации диска по имени (см. параметр `name`) должно быть задан либо идентификатор, либо имя аккаунта (см. параметр `account_name`). Если одновременно заданы и `account_id`, и `account_name`, то `account_name` игнорируется.|
|account_name | (string) | Имя аккаунта, которому принадлежит данный диск. При идентификации диска по имени (см. параметр name) должно быть задано либо имя, либо идентификатор учётной записи (см. параметр `account_id`). Если одновременно заданы и `account_id`, и `account_name`, то `account_name` игнорируется. |
| description | (string)<br>Default: `Disk by decort_disk` | Текстовое описание диска. Данный параметр является опциональным и учитывается только при создании диска, а при всех прочих операциях игнорируется.|
|id | (int) | Уникальный целочисленный идентификатор диска. Соответствующий диск должен существовать (таким образом, с помощью id нельзя создать новый диск, а только управлять уже имеющимися). Если задан данный параметр, то параметры `name`, `account_name` и `account_id` игнорируются.|
| iops | (int)<br>Default: `2000` | Ограничение ввода/вывода диска. Используется при создании диска. |
| force_detach | (bool)<br/>Default: `false` | Задаёт поведение платформы при попытке удалить диск, подключённый к виртуальной машине.<br/>По умолчанию, удаление подключённых дисков не разрешается, и попытка удалить такой диск приведёт к аварийному завершению модуля. Чтобы изменить это поведение, явно установите `force_detach: true`. |
| limitIO | (dict) | Параметр, позволяющий ограничить скорость ввода/вывода диска как в iops, так и в байтах в секунду. Обратите внимание, что параметры с total не задаются вместе с read/write. Все возможные подпараметры можно увидеть в примерах. |
| name | (string) | Имя диска. Для идентификации диска требуется либо его `name` и информация об аккаунте (`account_id` или `account_name`), которому принадлежит диск, либо его `id`.|
| permanently | (bool)<br>Default: `false` | Параметр, использующийся при удалении диска, при значении `true` - диск удалится навсегда, а при `false` - попадёт в корзину. |
| place_with | (int) | Идентификатор образа диска, из которого следует взять параметр `sep_id`, чтобы разместить данный диск на той же системе хранения данных, что и указанный образ диска. Данный параметр является опциональным и используется только на стадии создания диска. Если задан `place_with`, то `sep_id` игнорируется.|
| pool | (string) | Название пула на системе хранения данных, в рамках которой следует создать данный диск. Этот параметр используется только на стадии создания диска и игнорируется при операциях над уже существующими дисками. Параметр является опциональным, если не задан, то платформа будет использовать пул, который сконфигурирован на целевой системе хранения как пул по умолчанию. |
| reason | (string)<br>Default: `Managed by Ansible decort_disk` | Причина, по которой было выполнено какое-либо действие. В данном модуле используется только при удалении диска. |
| sep_id | (int) | Идентификатор системы хранения данных (Storage End-point). Данный параметр определяет систему хранения данных, на ресурсах которой создаётся диск. Используется только при создании диска и игнорируется при прочих операциях. Альтернативой данному параметру является `place_with`, позволяющий разместить диск на той же системе хранения, что и указанный образ диска, на базе которого создаётся виртуальная машина.|
| shareable | (bool)<br>Default: `false` | Включение/отключение общего доступа к диску.
| size | (int) | Размер диска в ГБ. Этот параметр является обязательным при создании диска. Если он задан для уже существующего диска, а текущий размер диска меньше заданного, то будет предпринята попытка увеличить размер диска. При прочих операциях данный параметр игнорируется.|
| state | (str)<br>Значения:<br>`present`<br>`absent`<br>Default: `present` | Целевое состояние диска. |
## Возвращаемые значения модуля decort_disk
Модуль decort_disk возвращает информацию о диске в виде словаря facts со следующими ключами:
|Ключ | Тип данных | Описание|
| ------ | ------ | ------ |
| account_id | int | Уникальный целочисленный идентификатор аккаунта, которому принадлежит диск.|
| computes | dict | Словарь, в котором ключ - идентификатор, а значение - имя виртуальной машины, к которой в настоящий момент подключён диск. Если диск не подключён, то возвращается пустой словарь.|
| gid | int | Идентификатор физического кластера (Grid ID), на ресурсах которого создан диск.|
| id | int | Уникальный целочисленный идентификатор данного диска.|
| iotune | dict | Текущие ограничения ввода/вывода диска. |
| name | string | Имя диска. Обратите внимание, что имя диска не является уникальным с точки зрения системы хранения данных, на которой этот диск расположен.|
| pool | string | Имя пула на системе хранения данных, в котором размещаются ресурсы диска.|
|sep_id | int | Идентификатор системы хранения данных (Storage Endpoint), на которой размещаются ресурсы данного диска.|
| size | int | Размер диска в ГБ.|
| state | string | Текущий статус диска. |
## Пример использования модуля decort_disk
В данном примере создаётся диск размером 50ГБ (`size: 50`), с ограничением ввода/вывода в 2000 iops, на ресурсах системы хранения данных под номером 1 (`sep_id: 1`) в пуле "data01".
```
- name: Manage disk
decort_disk:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
name: "DataDisk01"
size: 50
account_name: "MyAccount"
sep_id: 1
iops: 2000
description: "Disk example"
pool: data01
register: my_data_disk01
```
В следующих двух примерах для существующего диска с именем "DataDisk01" задаются все доступные лимиты на операции ввода/вывода.
```
- name: Manage disk
decort_disk:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
name: "DataDisk01"
account_name: "MyAccount"
limitIO:
read_bytes_sec: 10000
write_bytes_sec: 5000
read_iops_sec и write_iops_sec
read_iops_sec: 2500
write_iops_sec: 1000
read_bytes_sec_max: 11000
write_bytes_sec_max: 6000
read_iops_sec_max: 3000
write_iops_sec_max: 1500
size_iops_sec: 1000
register: my_data_disk01
- name: Manage disk
decort_disk:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
name: "DataDisk01"
account_name: "MyAccount"
limitIO:
total_bytes_sec: 15000
total_iops_sec: 3500
total_bytes_sec_max: 17000
total_iops_sec_max: 4500
size_iops_sec: 1000
register: my_data_disk01
```
В данном примере выполняется восстановление удаленного диска с id 111 из корзины.
```
- name: Manage disk
decort_disk:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
id: 111
size: 10
register: my_data_disk01
```
В данном примере выполняется переименование диска с id 111 на новое имя "NewExampleDisk".
```
- name: Manage disk
decort_disk:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
id: 111
name: "NewExampleDisk"
size: 10
register: my_data_disk01
```
Здесь результат работы модуля decort_disk записывается в переменную my_data_disk01. Для получения идентификатора диска, например, при подключении его к виртуальной машине, следует воспользоваться показанной ниже конструкцией:
```
- name: Manage compute
decort_kvmvm:
<< для краткости фрагмент опущен >>
data_disks:
- "{{ my_data_disk01.facts.id }}"
<< для краткости фрагмент опущен >>
```

@ -0,0 +1,97 @@
# Модуль decort_group
## Обзор модуля decort_group
Модуль **decort_group** позволяет производить следующие действия над группами базовой службы:
- создать
- получить информацию
- запустить/остановить
- подключить/отключить сети (для существующей группы только внутренние сети)
- изменить
- имя
- объём загрузочного диска
- количество ВМ
- роль
- количество виртуальных процессоров
- объём ОЗУ
- удалить (безвозвратно)
## Параметры модуля decort_group
Ниже приведен список параметров для модуля **decort_group** (за исключением [общих параметров авторизации](./введение.md#общие-параметры-модулей-для-авторизации)):
| Параметр | Тип, допустимые значения | Описание |
| ------ | ------ | ------ |
| account_id | (int) | Идентификатор аккаунта. При идентификации диска по имени (см. параметр `name`) должен быть задан либо идентификатор, либо имя аккаунта (см. параметр `account_name`). Если одновременно заданы и `account_id`, и `account_name`, то `account_name` игнорируется. |
| account_name | (string) | Имя аккаунта. При идентификации диска по имени (см. параметр `name`) должно быть задано либо имя, либо идентификатор аккаунта (см. параметр `account_id`). Если одновременно заданы и `account_id`, и `account_name`, то `account_name` игнорируется. |
| boot_disk | (int) | Обьём загрузочного диска. |
| bservice_id | (int) | Идентификатор базовой службы. Обязательный параметр. |
| count | (int) | Количество виртуальных машин. |
| cpu | (int) | Количество виртуальных процессоров. |
| driver | (string)<br>Значения:<br>`KVM_X86`<br>`SVA_KVM_X86`<br>Default: `KVM_X86` | Драйвер. |
| id | (int) | Идентификатор группы. |
| image_id | (int) | Идентификатор образа. |
| name | (str) | Имя группы.<br>Используется для идентификации группы, если не задан параметр `id`, а также для переименования группы, если параметр `id` задан. |
| networks | (list) | Список словарей, описывающих сети, которые должны быть подключены.<br>Ключи словаря:<br>&bull; `type` (string) (обязательный) - тип сети; значения: `VINS` (внутренняя) или `EXTNET` (внешняя)<br>&bull; `id` (int) (обязательный) - идентификатор сети |
| ram | (int) | Объём оперативной памяти. |
| role | (string) | Тег роли. |
| state | (str)<br>Значения:<br>`present`<br>`absent`<br>`started`<br>`stopped`<br>`check`<br>Default: `present` |
| timeoutStart | (int) | Время отсрочки запуска группы после создания в секундах. |
## Возвращаемые значения модуля decort_group
Модуль **decort_group** возвращает информацию о диске в виде словаря facts со следующими ключами:
|Ключ | Тип данных | Описание|
| ------ | ------ | ------ |
| account_id | int | Идентификатор аккаунта. |
| Computes | list | Список словарей, содержащих информацию о виртуальных машинах группы.<br>Ключи словаря:<br>&bull; `id` (int) - идентификатор ВМ<br>&bull; `ipAddresses` (list) - список IP-адресов ВМ<br>&bull; `name` (str) - имя ВМ<br>&bull; `osUsers` (list) - список словарей, содержащих учётные данные пользователей ОС ВМ по умолчанию; ключи: `login` (str) и `password` (str) |
| id | int | Идентификатор группы.|
| name | string | Имя группы.|
| rg_id | int | Идентификатор ресурсной группы. |
| state | string | Состояние группы. |
| techStatus | string | Технический статус группы. |
## Пример использования модуля decort_group
Данный пример создаёт группу с именем `test_group`.
```
- hosts: localhost
tasks:
- name: Create BS group
decort_group:
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
authenticator: oauth2
boot_disk: 10
bservice_id: 1823
controller_url: "https://ds1.digitalenergy.online"
count: 2
cpu: 2
image_id: 518
name: test_group
networks:
- type: VINS
id: 1987
oauth2_url: "https://sso.digitalenergy.online"
ram: 2
verify_ssl: false
register: group_test
```
Данный пример удаляет группу с именем `test_group`.
```
- hosts: localhost
tasks:
- name: Delete BS group
decort_group:
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
authenticator: oauth2
bservice_id: 1823
controller_url: "https://ds1.digitalenergy.online"
name: test_group
oauth2_url: "https://sso.digitalenergy.online"
state: absent
verify_ssl: False
register: group_test
```

@ -0,0 +1,48 @@
# Модуль decort_jwt
## Обзор модуля
Модуль **decort_jwt** предназначен для получения авторизационного токена JWT (JSON Web Token). Данный модуль может быть полезен при массовом создании ресурсов (например, виртуальных машин), так как позволяет оптимизировать количество API вызовов для получения токена.
По сути, данный модуль является провайдером информации и не управляет облачными ресурсами (всегда возвращает `changed: False`).
## Параметры модуля decort_jwt
Список параметров для модуля **decort_jwt** почти полностью совпадает с [общими параметрами модулей для авторизации](./введение.md#общие-параметры-модулей-для-авторизации).
Отличия от общих параметров:
- Параметр `controller_url` не используется.
- Параметр `jwt` не используется.
- В параметре `authenticator` не используется значение `jwt`.
## Возвращаемые значения модуля decort_jwt
| Ключ | Тип данных | Описание |
|---| ------ | ------ |
| jwt | str | JWT токен. |
## Примеры использования
### Пример получения JWT токена с помощью DECS3O
```
- name: Example
hosts: localhost
tasks:
- name: Obtain JWT from DECS3O
decort_jwt:
app_id: "{{ app_id }}"
app_secret: "{{ app_secret }}"
authenticator: decs3o
oauth2_url: https://sso-dynamix.local
```
### Пример получения JWT токена с помощью BVS
```
- name: Example
hosts: localhost
tasks:
- name: Obtain JWT from BVS
decort_jwt:
app_id: "{{ app_id }}"
app_secret: "{{ app_secret }}"
authenticator: bvs
oauth2_url: https://bvs.local
domain: dynamix
username: "{{ username }}"
password: "{{ password }}"
```

@ -0,0 +1,114 @@
# Модуль decort_k8s
## Обзор модуля decort_k8s
Модуль **decort_k8s** предназначен для выполнения следующих действий над кластерами Kubernetes:
- создать
- получить информацию
- отключить/включить/запустить
- изменить группы Worker-узлов
- удалить (в корзину или безвозвратно)
- восстановить из корзины
## Параметры модуля decort_k8s
Ниже приведен список параметров для модуля **decort_k8s** (за исключением [общих параметров авторизации](./введение.md#общие-параметры-модулей-для-авторизации)):
| Параметр | Тип, допустимые значения | Описание |
| ------ | ------ | ------ |
| account_id | (int) | Идентификатор аккаунта. |
| account_name | (string) | Имя аккаунта. |
| additionalSANs | (list) | Список дополнительных SAN (Subject Alternative Names) для использования в процессе автоматического выписывания сертификата Кластера Kubernetes. Можно использовать IP-адреса и доменные имена.
| cluster_conf | (dict) | Словарь с глобальными настройками и конфигурацией для всего кластера. Включает в себя такие настройки, как имя кластера, настройки DNS, методы аутентификации и другие конфигурации всего кластера. |
| description | (string)<br>Default: `Created by decort ansible module` | Описание кластера. |
| extnet_id | (int)<br>Default: `0` | Идентификатор внешней сети. Если задан `0`, то внешняя сеть выбирается автоматически. Если задан параметр `vins_id`, то значение данного параметра будет проигнорировано. Если задан `extnet_only: false`, то внешняя сеть будет подключена к создаваемой внутренней сети, а если `extnet_only: true`, то либо напрямую к каждому узлу кластера (если `with_lb: false`), либо напрямую к балансировщику нагрузки (если `with_lb: true`). |
| extnet_only | (bool)<br>Default: `false` | Не использовать внутреннюю сеть, подключать напрямую к внешней. |
| getConfig | (bool)<br>Default: `false` | Получить данные конфигурации для доступа к кластеру Kubernetes. |
| ha_lb | (bool)<br>Default: `false` | Использовать схему высокой доступности для создаваемого балансировщика нагрузки (если `with_lb: true`). |
| id | (int) | Идентификатор кластера Kubernetes. |
| init_conf | (dict) | Словарь для определения настроек и действий, которые должны быть выполнены перед запуском любого другого компонента в кластере. Позволяет настраивать такие процессы, как регистрация узла, настройка сети и другие задачи инициализации.
| join_conf | (dict) | Словарь для настройки поведения и параметров присоединения узла к кластеру. Включает в себя такие параметры, как control-plane-endpoint кластера, токен и certificate-key. |
| k8ci_id | (int) | Идентификатор конфигурации кластера Kubernetes. |
| kubeproxy_conf | (dict) | Словарь для настройки поведения и настроек Kube-proxy, отвечающего за сетевое проксирование и балансировку нагрузки внутри кластера. Включает в себя такие параметры, как режим прокси, диапазоны IP-адресов кластера и другие конфигурации, специфичные для Kube-proxy. |
| kublet_conf | (dict) | Словарь для настройки поведения и настроек Kubelet, который является агентом основного узла, работающим на каждом узле кластера. Включает в себя такие параметры, как IP-адрес узла, распределение ресурсов, политики вытеснения модулей и другие конфигурации, специфичные для Kubelet. |
| master_chipset | (string)<br>Значения:<br>`Q35`<br>`i440fx` | Эмулируемый чипсет master-узлов. Не поддерживается изменение в существующем кластере. <br>Значение по умолчанию при создании: `i440fx`. |
| master_count | (int)<br>Default: `1` | Количество Master-узлов. |
| master_cpu | (int)<br>Default: `2` | Количество виртуальных процессоров на Master-узле. |
| master_disk | (int)<br>Default: `10` | Объём загрузочного диска на Master-узле. |
| master_pool | (str) | Пул СХД, заданной параметром `master_sepid`. |
| master_ram | (int)<br>Default: `2048` | Объём оперативной памяти на Master-узле. |
| master_sepid | (int) | Идентификатор СХД для Master-узла. Если не задан, то используется СХД образа Master-узла. |
| name | (string) | Имя кластера Kubernetes. |
| network_plugin | (str)<br>Значения:<br>`flannel`<br>`calico`<br>`weavenet`<br>Default: `flannel` | CNI plugin (модуль для управления сетевыми интерфейсами контейнера). Возможные значения могут быть ограничены в используемой конфигурации кластера Kubernetes (параметр `k8ci_id`) |
| oidc_cert | (raw) | Сертификат X.509 для OIDC-провайдера.
| permanent | (bool)<br>Default: `false` | Если выполняется удаление, то выполнить безвозвратное удаление (минуя корзину). |
| rg_id | (int) | Идентификатор ресурсной группы. |
| rg_name | (str) | Имя ресурсной группы. |
| started | (bool)<br>Default: `true` | Запустить кластер.<br>Используется только для существующего кластера. |
| state | (string)<br>Значения:<br>`present`<br>`absent`<br>`enabled`<br>`disabled`<br>`check`<br>Default: `present` | Целевое состояние кластера. |
| lb_sysctl | (dict) | Словарь, описывающий параметры конфигурации sysctl балансировщика нагрузки. Может быть задан только если кластер имеет балансировщик нагрузки. |
| vins_id | (int) | Идентификатор внутренней сети. Если не задан, то будет создана новая внутренняя сеть. Если задан, то заданная внутренняя сеть должна иметь подключение к внешней сети. Если задано `extnet_only: true`, то параметр игнорируется.
| with_lb | (bool)<br>Default: `true` | Создание кластера Kubernetes с размещением Master-узлов за балансировщиком нагрузки. В ином случае каждый узел получит отдельный адрес из внешней сети.
| workers | (list) | Список словарей, описывающих группы Worker-узлов.<br>Ключи словаря:<br>&bull; `annotations` (list) (необязательный) - список строк с annotations в формате: `key1=value1`; значение по умолчанию при создании: `[]`<br>&bull; `chipset` (str) (необязательный) - эмулируемый чипсет. Допустимые значения: `Q35`, `i440fx`; значение по умолчанию при создании: `i440fx`<br>&bull; `ci_user_data` (dict) (необязательный) - конфигурация для cloud-init; значение по умолчанию при создании: `{}`<br>&bull; `cpu` (int) (необязательный) - количество виртуальных процессоров на узле; значение по умолчанию при создании: `1`<br>&bull; `disk` (int) (необязательный) - объём загрузочного диска на узле; если не задан при создании, размер диска будет равен размеру используемого образа<br>&bull; `labels` (list) (необязательный) - список строк с labels в формате: `label1=value1`; значение по умолчанию при создании: `[]`. Метка `workersGroupName` является служебной в платформе и игнорируется при сравнении переданных меток с существующими<br>&bull; `name` (string) (обязательный) - имя группы Worker-узлов<br>&bull; `num` (int) (необязательный) - количество узлов; значение по умолчанию при создании: `1`<br>&bull; `pool` (str) (необязательный) - пул СХД, заданной ключом `sep_id`; если не задан при создании, то пул будет выбран платформой<br>&bull; `ram` (int) (необязательный) - объём оперативной памяти на узле; значение по умолчанию при создании: `1024`<br>&bull; `sep_id` (int) (необязательный) - идентификатор СХД; если не задан при создании, то используется СХД образа узла<br>&bull; `taints` (list) (необязательный) - список строк с taints в формате: `key1=value1:NoSchedule`; значение по умолчанию при создании: `[]`. |
## Возвращаемые значения модуля decort_k8s
Модуль **decort_k8s** возвращает информацию о кластере в виде словаря `facts` со следующими ключами:
| Ключ | Тип данных | Описание |
| ------ | ------ | ------ |
| account_id | int | Идентификатор аккаунта. |
| config | str | Kuber config кластера.
| id | int | Идентификатор кластера. |
| k8s_Masters | dict | Словарь с информацией о группе Master-узлов.<br>Ключи словаря:<br>&bull; `cpu` (int) - количество виртуальных процессоров<br>&bull; `detailedInfo` (list) - список словарей с информацией об узлах; ключи словаря: `id` (int) - идентификатор ВМ, `name` (str) - имя ВМ, `status` (str) - статус ВМ, `techStatus` (str) - технический статус ВМ<br>&bull; `disk` (int) - объём загрузочного диска<br>&bull; `id` (int) - идентификатор группы<br>&bull; `name` (str) - имя группы<br>&bull; `num` (int) - количество узлов<br>&bull; `ram` (int) - объём оперативной памяти
| k8s_Workers | dict | Список словарей с информацией о группах Worker-узлов.<br>Ключи словаря:<br>&bull; `cpu` (int) - количество виртуальных процессоров<br>&bull; `detailedInfo` (list) - список словарей с информацией об узлах; ключи словаря: `id` (int) - идентификатор ВМ, `name` (str) - имя ВМ, `status` (str) - статус ВМ, `techStatus` (str) - технический статус ВМ<br>&bull; `disk` (int) - объём загрузочного диска<br>&bull; `id` (int) - идентификатор группы<br>&bull; `labels` (list) - список строк с labels<br>&bull; `name` (str) - имя группы<br>&bull; `num` (int) - количество узлов<br>&bull; `ram` (int) - объём оперативной памяти<br>&bull; `taints` (list) - список строк с taints
| lb_id | int | Идентификатор балансировщика нагрузки. |
| name | string | Имя кластера. |
| rg_id | int | Идентификатор ресурсной группы. |
| state | string | Статус кластера. |
| techStatus | string | Технический статус кластера. |
| vins_id | int | Идентификатор внутренней сети кластера. |
## Пример использования модуля decort_k8s
Пример создания кластера Kubernetes с именем `cluster-test` с получением Kuber config.
```
- name: Create a k8s cluster named cluster-test
decort_k8s:
authenticator: jwt
controller_url: "https://ds1.digitalenergy.online"
getConfig: true
jwt: "{{ token.jwt }}"
k8ci_id: 18
name: cluster-test
rg_id: 125
workers:
- cpu: 10
disk: 10
name: wg1
num: 1
ram: 1024
chipset: i440fx
ci_user_data: {}
taints:
- key=value:NoSchedule
annotations:
- key=value
labels:
- label=value
- cpu: 10
disk: 10
name: wg2
num: 2
ram: 1024
chipset: Q35
ci_user_data: {}
taints:
- key=value:NoSchedule
annotations:
- key=value
labels:
- label=value
register: k8s_cluster
```

File diff suppressed because it is too large Load Diff

@ -0,0 +1,806 @@
# Модуль decort_lb
## Обзор модуля decort_lb
Модуль **decort_lb** предназначен для выполнения следующих действий над балансировщиками нагрузки:
- создать
- получить информацию
- отключить/включить/запустить/перезапустить
- изменить
- конфигурации backend и frontend
- конфигурацию sysctl
- удалить (в корзину или безвозвратно)
- восстановить из корзины
## Параметры модуля decort_lb
Ниже приведен список параметров для модуля **decort_lb** (за исключением [общих параметров авторизации](./введение.md#общие-параметры-модулей-для-авторизации)):
<table>
<tr>
<th colspan="3">Параметр</th>
<th>Тип</th>
<th>Описание</th>
</tr>
<tr>
<td colspan="3">
account_id
</td>
<td>
(int)
</td>
<td>
Идентификатор аккаунта.
</td>
</tr>
<tr>
<td colspan="3">
account_name
</td>
<td>
(str)
</td>
<td>
Имя аккаунта.
<br> Может быть альтернативой параметру <code>account_id</code>.
</td>
</tr>
<tr>
<td colspan="3">
description
</td>
<td>
(str)
<br>Default: <code>Managed by Ansible module decort_lb</code>
</td>
<td>
Описание балансировщика.
</td>
</tr>
<tr>
<td colspan="3">
backends
</td>
<td>
(list)
</td>
<td>
Список словарей, описывающих конфигурации backend.
</td>
</tr>
<tr>
<td></td>
<td colspan="2">
algorithm
</td>
<td>
(str)
<br>Значения:
<br><code>leastconn</code>
<br><code>roundrobin</code>
<br><code>static-rr</code>
<br>Default: <code>roundrobin</code>
</td>
<td>
Используемый алгоритм.
</td>
</tr>
<tr>
<td></td>
<td colspan="2">
<a name="backend_default_settings">
default_settings
</a>
</td>
<td>
(dict)
</td>
<td>
оварь, описывающий параметры по умолчанию для backend-серверов.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
downinter
</td>
<td>
(int)
<br>Default: <code>1000</code>
</td>
<td>
Интервал в миллисекундах между двумя последовательными проверками
доступности сервера, который считается недоступным.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
fall
</td>
<td>
(int)
<br>Default: <code>2</code>
</td>
<td>
Количество последовательных неудачных проверок доступности, после
которых сервер, ранее считавшийся доступным, начинает считаться
недоступным и временно исключается из схемы балансировки.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
inter
</td>
<td>
(int)
<br>Default: <code>5000</code>
</td>
<td>
Интервал в миллисекундах между двумя последовательными проверками
доступности сервера, который считается доступным.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
maxconn
</td>
<td>
(int)
<br>Default: <code>250</code>
</td>
<td>
Лимит одновременных подключений к серверу. При достижении этого лимита
сервер временно исключается из схемы балансировки.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
maxqueue
</td>
<td>
(int)
<br>Default: <code>256</code>
</td>
<td>
Лимит соединений, ожидающих в очереди. Когда этот предел будет
достигнут, все последующие подключения будут перенаправлены
на другие серверы.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
rise
</td>
<td>
(int)
<br>Default: <code>2</code>
</td>
<td>
Количество проверок, которые должен пройти сервер, считавшийся
недоступным, чтобы начать считаться доступным и снова быть
включенным в схему балансировки.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
slowstart
</td>
<td>
(int)
<br>Default: <code>60000</code>
</td>
<td>
Интервал в миллисекундах с момента когда сервер начинает считаться
доступным, по истечении которого количество фактически разрешенных
подключений к этому серверу будет возвращено до 100% от
установленного лимита.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
weight
</td>
<td>
(int)
<br>Default: <code>100</code>
</td>
<td>
Вес сервера для использования в алгоритмах балансировки.
</td>
</tr>
<tr>
<td></td>
<td colspan="2">
name
</td>
<td>
(str)
</td>
<td>
Название backend. Обязательный параметр.
</td>
</tr>
<tr>
<td colspan="3">
ext_net_id
</td>
<td>
(int)
</td>
<td>
Идентификатор внешней сети.
<br>Может быть не задан, если задан <code>vins_id</code> -
в таком случае балансировщик будет подключён только к
внутренней сети.
</td>
</tr>
<tr>
<td colspan="3">
<a name="frontends">
frontends
</a>
</td>
<td>
(list)
</td>
<td>
Список словарей, описывающих конфигурации frontend.
</td>
</tr>
<tr>
<td></td>
<td colspan="2">
backend
</td>
<td>
(str)
</td>
<td>
Название используемого backend. Обязательный параметр.
</td>
</tr>
<tr>
<td></td>
<td colspan="2">
bindings
</td>
<td>
(list)
</td>
<td>
Список словарей, описывающих конфигурации binding.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
address
</td>
<td>
(str)
</td>
<td>
IP-адрес.
<br>Если не задан, то будет использоваться основной IP-адрес
балансировщика во внешней сети или, если подключена только
внутренняя сеть, основной IP-адрес балансировщика во внутренней сети.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
name
</td>
<td>
(str)
</td>
<td>
Название. Обязательный параметр.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
port
</td>
<td>
(int)
<br>Значения:
<br><code>1</code>-<code>65535</code>
</td>
<td>
Порт. Обязательный параметр.
</td>
</tr>
<tr>
<td colspan="3">
ha_lb
</td>
<td>
bool
<br>Default: <code>false</code>
</td>
<td>
Использовать схему высокой доступности для создаваемого балансировщика.
</td>
</tr>
<tr>
<td colspan="3">
lb_id
</td>
<td>
(int)
</td>
<td>
Идентификатор балансировщика нагрузки.
</td>
</tr>
<tr>
<td colspan="3">
lb_name
</td>
<td>
(str)
</td>
<td>
Имя балансировщика.
</td>
</tr>
<tr>
<td colspan="3">
permanently
</td>
<td>
(bool)
<br>Default: <code>false</code>
</td>
<td>
Если выполняется удаление, то выполнить безвозвратное удаление
(минуя корзину).
</td>
</tr>
<tr>
<td colspan="3">
rg_id
</td>
<td>
(int)
</td>
<td>
Идентификатор ресурсной группы.
</td>
</tr>
<tr>
<td colspan="3">
rg_name
</td>
<td>
(str)
</td>
<td>
Имя ресурсной группы.
<br> В комбинации с заданным аккаунтов может быть альтернативой
параметру <code>rg_id</code>
</td>
</tr>
<tr>
<td colspan="3">
servers
</td>
<td>
(list)
</td>
<td>
Список словарей, описывающих конфигурации backend-серверов.
</td>
</tr>
<tr>
<td></td>
<td colspan="2">
address
</td>
<td>
(str)
</td>
<td>
IP-адрес. Обязательный параметр.
</td>
</tr>
<tr>
<td></td>
<td colspan="2">
backends
</td>
<td>
(list)
</td>
<td>
Список словарей, описывающих параметры backend-сервера для разных
конфигураций backend.
<br>Обязательный параметр.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
check
</td>
<td>
(str)
<br>Значения:
<br><code>enabled</code>
<br><code>disabled</code>
<br>Default: <code>enabled</code>
</td>
<td>
Проверка доступности сервера.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
name
</td>
<td>
(str)
</td>
<td>
Название конфигурации backend. Обязательный параметр.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
port
</td>
<td>
(int)
<br>Значения:
<br><code>1</code>-<code>65535</code>
</td>
<td>
Порт. Обязательный параметр.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>
server_settings
</td>
<td>
(dict)
</td>
<td>
Словарь, описывающий параметры backend-сервера.
<br> Ключи данного словаря аналогичны ключам словаря
<a href=#backend_default_settings>
default_settings
</a>.
</td>
</tr>
<tr>
<td></td>
<td colspan="2">
name
</td>
<td>
(str)
</td>
<td>
Название. Обязательный параметр.
</td>
</tr>
<tr>
<td colspan="3">
state
</td>
<td>
(str)
<br>Значения:
<br><code>present</code>
<br><code>absent</code>
<br><code>enabled</code>
<br><code>disabled</code>
<br><code>restart</code>
<br>Default: <code>present</code>
</td>
<td>
Целевое состояние балансировщика нагрузки.
<br>Выполнение с <code>state=restart</code> позволяет выполнить
перезапуск балансировщика, соответственно, всегда возвращает
<code>changed: true</code>.
<br>Значения <code>present</code> и <code>enabled</code> равнозначны
и соответствуют включённому и запущенному балансировщику.
</td>
</tr>
<tr>
<td colspan="3">
sysctl
</td>
<td>
(dict)
</td>
<td>
Словарь, описывающий параметры конфигурации sysctl.
</td>
</tr>
<tr>
<td colspan="3">
vins_id
</td>
<td>
(int)
</td>
<td>
Идентификатор внутренней сети.
<br>Может быть не задан, если задан <code>ext_net_id</code> -
в таком случае балансировщик будет подключён только к
внешней сети.
</td>
</tr>
<tr>
<td colspan="3">
vins_name
</td>
<td>
(str)
</td>
<td>
Имя внутренней сети.
<br> В комбинации с заданной РГ может быть альтернативой для
параметра <code>vins_id</code>.
</td>
</tr>
</table>
## Возвращаемые значения модуля decort_lb
Модуль **decort_lb** возвращает информацию о балансировщике в виде словаря `facts` со следующими ключами:
<table>
<tr>
<th colspan="4">
Ключ
</th>
<th>
Тип
<br>данных
</th>
<th>
Описание
</th>
</tr>
<tr>
<td colspan="4">
backends
</td>
<td>
list
</td>
<td>
Список словарей, описывающих конфигурации backend.
</td>
</tr>
<tr>
<td></td>
<td colspan="3">
algorithm
</td>
<td>
str
</td>
<td>
Используемый алгоритм.
</td>
</tr>
<tr>
<td></td>
<td colspan="3">
name
</td>
<td>
str
</td>
<td>
Название конфигурации backend.
</td>
</tr>
<tr>
<td></td>
<td colspan="3">
serverDefaultSettings
</td>
<td>
dict
</td>
<td>
оварь, описывающий параметры по умолчанию для backend-серверов.
<br> Ключи данного словаря аналогичны ключам словаря
<a href=#backend_default_settings>
default_settings
</a>.
</td>
</tr>
<tr>
<td></td>
<td colspan="3">
servers
</td>
<td>
list
</td>
<td>
Список словарей, описывающих конфигурации backend-серверов.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td colspan="2">
address
</td>
<td>
str
</td>
<td>
IP-адрес.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td colspan="2">
check
</td>
<td>
str
</td>
<td>
Проверка доступности сервера.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td colspan="2">
name
</td>
<td>
str
</td>
<td>
Название.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td colspan="2">
port
</td>
<td>
int
</td>
<td>
Порт.
</td>
</tr>
<tr>
<td></td>
<td></td>
<td colspan="2">
serverSettings
</td>
<td>
dict
</td>
<td>
оварь, описывающий параметры backend-сервера.
<br> Ключи данного словаря аналогичны ключам словаря
<a href=#backend_default_settings>
default_settings
</a>.
</td>
</tr>
<tr>
<td colspan="4">
frontends
</td>
<td>
list
</td>
<td>
Список словарей, описывающих конфигурации frontend.
<br> Ключи данного словаря аналогичны ключам словарей списка
<a href=#frontends>
frontends
</a>.
</td>
</tr>
<tr>
<td colspan="4">
gid
</td>
<td>
int
</td>
<td>
Идентификатор физического кластера (Grid ID).
</td>
</tr>
<tr>
<td colspan="4">
id
</td>
<td>
int
</td>
<td>
Идентификатор балансировщика.
</td>
</tr>
<tr>
<td colspan="4">
name
</td>
<td>
str
</td>
<td>
Имя балансировщика.
</td>
</tr>
<tr>
<td colspan="4">
rg_id
</td>
<td>
int
</td>
<td>
Идентификатор ресурсной группы.
</td>
</tr>
<tr>
<td colspan="4">
state
</td>
<td>
str
</td>
<td>
Статус балансировщика.
</td>
</tr>
<tr>
<td colspan="4">
sysctl
</td>
<td>
dict
</td>
<td>
Параметры конфигурации sysctl.
</td>
</tr>
</table>

@ -0,0 +1,137 @@
# Модуль decort_osimage
## Обзор модуля decort_osimage
Модуль decort_osimage предназначен для выполнения следующих действий над образами, созданными в облачной платформе DECORT:
- шаблонные образы:
- создать
- получить информацию
- изменить имя
- удалить
- виртуальные образы
- создать
- получить информацию
- изменить
- имя
- целевой образ
- удалить
## Параметры модуля decort_osimage
Ниже приведен список параметров для модуля **decort_osimage** (за исключением [общих параметров авторизации](./введение.md#общие-параметры-модулей-для-авторизации)):
| Параметр | Тип, допустимые значения | Описание |
| ------ | ------ | ------ |
| account_Id | (int) | Уникальный целочисленный идентификатор аккаунта. Используется для поиска образов, а тажке для их создания. |
| account_name | (string) | Имя аккаунта. Используется для получения уникального целочисленного идентификатора аккаунта. |
| boottype | (string)<br>Default: `uefi` | Тип загрузки образа. Используется при создании образа.|
| drivers | (string)<br>Default: `KVM_X86` | Тип виртуальных машин, подходящих для образа. Используется при создании образа.|
| hotresize | (bool)<br>Default: `false` | Поддерживает ли образ "горячее" изменение размера. По умолчанию установлено `false`. Используется при создании образа операционной системы. |
| image_id | (int) | Идентификатор шаблонного образа.
| image_name | (str) | Имя шаблонного образа.
| image_password | (string) | Опциональный пароль для образа. Используется при создании образа.|
| image_username | (string) | Опциональное имя пользователя для образа. Используется при создании образа. |
| imagetype | (string)<br>Default: `linux` | Тип образа. Используется при создании образа.|
| passwordDL | (string) | Пароль для скачивания по URL-адресу. Используется при создании образа. |
| pool | (str) | Имя пула СХД. Используется для поиска существующего образа.
| poolName | (string) | Имя пула СХД. Используется при создании образа. |
| sepId | (integer) | Уникальный целочисленный идентификатор СХД. Используется при создании образа. |
| sep_id | (int) | Идентификатор СХД. Используется для поиска существующего образа.
| state | (string)<br>Значения:<br>`present`<br>`absent`<br>Default: `present` | Целевое состояние образа. `present` - существует, `absent` - удалён. |
| url | (string) | URL-адрес, с которого будет загружен образ. Используется при создании образа.|
| usernameDL | (string) | Имя пользователя для загрузки образа с заданного URL-адреса. Используется при создании образа. |
| virt_id | (integer) | Уникальный целочисленный идентификатор виртуального образа. Может использоваться для получения информации о виртуальном образе, а также для привязки к нему другого образа.|
| virt_name | (string) | Имя виртуального образа. Используется для получения `virt_id`, а в последствии информации о виртуальном образе, а также для создания виртуального образа и привязки к нему другого образа.|
## Возвращаемые значения модуля decort_osimage
Модуль decort_osimage возвращает информацию об образе в виде словаря facts со следующими ключами:
| Ключ | Тип данных | Описание |
| ------ | ------ | ------ |
| accountId | int | Идентификатор аккаунта.
| id | int | Уникальный целочисленный идентификатор данного образа. |
| linkto | int | Уникальный целочисленный идентификатор образа, который привязан к данному виртуальному. |
| name | string | Имя образа. |
| pool | string | Имя пула на системе хранения данных, в котором находится данный образ.|
| sep_id | int | Идентификатор системы хранения данных, на которой хранится данный образ. |
| size | int | Размер образа в ГБ. |
| state | string | Текущий статус образа. |
| type | string | Тип образа. |
## Пример использования модуля decort_osimage
Пример создания шаблонного образа с операционной системой Alpine Linux.
```
- name: Create template image
decort_osimage:
account_Id: 12345
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
authenticator: oauth2
controller_url: "https://ds1.digitalenergy.online"
image_name: alpine_linux_3.19.1
url: https://dl-cdn.alpinelinux.org/alpine/v3.19/releases/cloud/nocloud_alpine-3.19.1-x86_64-uefi-cloudinit-r0.qcow2
verify_ssl: false
register: osimage
```
Пример получения информации о существующем шаблонном образе по его имени.
```
- name: Get template image
decort_osimage:
account_Id: 12345
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
authenticator: oauth2
controller_url: "https://ds1.digitalenergy.online"
image_name: alpine_linux_3.19.1
verify_ssl: false
register: osimage
```
Пример создания виртуального образа. Также в случае, если виртуальный образ уже существует, но к нему привязан другой шаблонный образ, он привяжет к себе указанный в примере шаблонный образ.
```
- name: Create virtual image
decort_osimage:
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
authenticator: oauth2
controller_url: "https://ds1.digitalenergy.online"
image_name: alpine_linux_3.19.1
virt_name: alpine_last
register: osimage
```
Обратите внимание, что в данном примере можно использовать как `image_name`, так и `image_id`. Также можно использовать либо `virt_name`, либо `virt_id`.
Пример переименования образа.
```
- name: Rename template image
decort_osimage:
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
authenticator: oauth2
controller_url: "https://ds1.digitalenergy.online"
image_name: alpine_linux_3.19.1_new_name
image_id: 54321
register: osimage
```
Пример удаления образа
```
- name: Delete image
decort_osimage:
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
authenticator: oauth2
controller_url: "https://ds1.digitalenergy.online"
image_id: 54321
state: absent
```

@ -0,0 +1,66 @@
# Модуль decort_pfw
## Обзор модуля decort_pfw
Модуль **decort_pfw** предназначен для настройки правил переадресации портов (port forwarding, destination NAT) на виртуальном маршрутизаторе заданной внутренней сети для заданной виртуальной машины.
Модуль поддерживает выполнение следующих действий над правилами:
- добавить
- получить информацию
- удалить
## Параметры модуля decort_pfw
Ниже приведен список параметров для модуля **decort_pfw** (за исключением [общих параметров авторизации](./введение.md#общие-параметры-модулей-для-авторизации)):
| Параметр | Тип, допустимые значения | Описание|
| ------ | ------ | ------ |
| compute_id | (int) | Идентификатор виртуальной машины. IP-адрес, который данная ВМ имеет во внутренней сети, заданной параметром `vins_id`, будет использоваться как внутренний IP-адрес в правилах. Обязательный параметр. |
| rules | (list) | Список словарей, описывающих правила переадресации портов для заданной ВМ (параметр `compute_id`) на виртуальном маршрутизаторе заданной внутренней сети (параметр `vins_id`).<br>Ключи словаря:<br>&bull; `local_port` (int) (обязательный) - внутренний порт; значения: от `1` до `65535`<br>&bull; `proto` (str) (обязательный) - протокол; значения: `tcp` или `udp`<br>&bull; `public_port_end` (int) (необязательный) - верхняя граница диапазона внешних портов; значения: от значения ключа `public_port_start` до `65535`;<br>&bull; `public_port_start` (int) (обязательный) - нижняя граница диапазона внешних портов; значения: от `1` до `65535` |
| state | (str)<br>Значения:<br/>`present`<br/>`absent`<br>Default: `present` | Целевое состояние правил.<br>Если `state=absent`, то, независимо от содержания параметра `rules`, будут удалены все правила для заданной ВМ (параметр `compute_id`) на виртуальном маршрутизаторе заданной внутренней сети (параметр `vins_id`). |
| vins_id | (int) | Идентификатор внутренней сети, на виртуальном маршрутизаторе которой настраиваются правила переадресации портов. Заданная ВМ (параметр `compute_id`) должна быть подключена к этой сети. Обязательный параметр. |
## Возвращаемые значения модуля decort_pfw
Модуль **decort_pfw** возвращает информацию о правилах переадресации портов и сопутствующую информацию в виде словаря `facts` со следующими ключами:
|Ключ | Тип данных | Описание|
| ------ | ------ | ------ |
| compute_id | int | Идентификатор ВМ. |
| public_ip | string | IP-адрес во внешней сети, настроенный на виртуальном маршрутизаторе внутренней сети. |
| rules | list | Список словарей, описывающих правила переадресации портов.<br>Ключи словаря:<br>&bull; `id` (int) - идентификатор правила<br>&bull; `localIp` (str) - IP-адрес ВМ<br>&bull; `localPort` (int) - внутренний порт<br>&bull; `protocol` (str) - протокол<br>&bull; `publicPortEnd` (int) - верхняя граница диапазона внешних портов<br>&bull; `publicPortStart` (int) - нижняя граница диапазона внешних портов<br>&bull; `vmId` (int) - идентификатор ВМ<br>&bull; `vmName` (str) - имя ВМ |
| state | string | Статус правил. Значения: `PRESENT` или `ABSENT`. |
| vins_id | int | Идентификатор внутренней сети. |
## Пример использования модуля decort_pfw
В данном примере для существующей ВМ (параметр `compute_id`), подключённой к внутренней сети (параметр `vins_id`), настраиваются два правила переадресации портов:
- Правило для одного порта: внешний порт `30022` на внутренний порт `22` по протоколу `tcp`.
- Правило для диапазона портов: внешние порты с `30080` по `30085` на внутренние порты с `30080` по протоколу `udp`.
```
- name: Add port forwarding rules
decort_pfw:
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
authenticator: oauth2
compute_id: "{{ my_vm.facts.id }}"
controller_url: "https://cloud.digitalenergy.online"
oauth2_url: "https://sso.digitalenergy.online"
rules:
- local_port: 22
proto: tcp
public_port_start: 30022
- local_port: 30080
proto: udp
public_port_end: 30085
public_port_start: 30080
vins_id: "{{ my_vins.facts.id }}"
register: my_pfw_rules
```
В данном примере результат выполнения модуля **decort_pfw** записывается в переменную `my_pfw_rules`. Для доступа к списку правил используйте следующую конструкцию:
```
"{{ my_pfw_rules.facts.rules }}"
```

@ -0,0 +1,223 @@
# Модуль decort_rg
## Обзор модуля decort_rg
Модуль decort_rg предназначен для создания, редактирования и удаления ресурсных групп (Resource Group, RG) в облачной платформе DECORT, а также для получения информации об уже существующей ресурсной группе. Модуль decort_rg позволяет:
- создавать ресурсные группы
- удалять ресурсные группы (в корзину или безвозвратно)
- восстанавливать ресурсные группы из корзины
- включать/отключать ресурсные группы
- запрашивать информацию об уже существующих ресурсных группах
- изменять ресурсные группы:
- переименовывать
- настраивать квоты
- задавать стандартную сеть
- настраивать права доступа для пользователей
- изменять доступные пулы СХД
- изменять описание
## Параметры модуля decort_rg
Ниже приведен список параметров для модуля **decort_rg** (за исключением [общих параметров авторизации](./введение.md#общие-параметры-модулей-для-авторизации)):
| Параметр | Тип, допустимые значения | Описание |
|----------|--------------------------|----------|
| account_id | (int) | Уникальный целочисленный идентификатор аккаунта, в рамках которого создаётся или уже существует данная ресурсная группа. Должен быть задан либо идентификатор, либо имя аккаунта (см. параметр `account_name`). Если одновременно заданы и `account_id`, и `account_name`, то account_name игнорируется. |
| account_name | (string) | Имя аккаунта, в рамках которого создаётся или уже существует данная ресурсная группа. Должно быть задано либо имя, либо идентификатор учётной записи (см. параметр `account_id`). Если одновременно заданы и `account_id`, и `account_name`, то `account_name` игнорируется. |
| access | (dict) | Параметр, позволяющий выдать, забрать или изменить права у пользователя в ресурсной группе. |
| description | (string) | Текстовое описание ресурсной группы. |
| def_netId | (int) | Уникальный целочисленный идентификатор внутренней или внешней сети. Используется для изменения сети по умолчанию в ресурсной группе. |
| def_netType | (string) <br>Значения:<br>`PRIVATE`<br>`PUBLIC`<br>`NONE`<br>Default: `PRIVATE` | Тип сети по умолчанию в ресурсной группе. Используется при создании ресурсной группы, а также при изменении. |
| extNetId | (int) | Уникальный целочисленный идентификатор внешней сети.<br>Если `def_netType: PRIVATE`, то указывает какую внешнюю сеть подключить к создаваемой внутренней сети, которая будет задана как сеть по умолчанию для создаваемой РГ.<br>Если `def_netType: PUBLIC`, то указывает какую внешнюю сеть задать как сеть по умолчанию для создаваемой РГ. |
| extNetIp | (string) | IP-адрес для внешней сети, которая задана в параметре `extNetId`. |
| ipcidr | (string) | IP-адрес внутренней сети. Используется при создании ресурсной группы, чтобы задать IP-адрес сети для создаваемой внутренней сети, которая создастся вместе с ресурсной группой. Используется при параметре `def_netType` в значении `PRIVATE`. |
| owner | (string) | Владелец ресурсной группы. Задаётся при создании ресурсной группы, не обязателен. Если оставить пустое значение - владельцем ресурсной группы будет пользователь, создавший ресурсную группу. |
| permanently | (bool)<br>Default: `false` | Параметр, использующийся при удалении ресурсной группы. При значении `true` - ресурсная группа удалится безвозвратно, а при `false` - попадёт в корзину. |
| quotas | (dict) | Предназначено для задания или изменения квоты на ресурсы в составе данной ресурсной группы. |
| rename | (string) | Новое имя ресурсной группы.<br>Возможно переименование только включенной ресурсной группы. |
| rg_id | (int) | Уникальный целочисленный идентификатор ресурсной группы. Является обязательным при изменении РГ если не заданы `rg_name` и `account_id`/`account_name` |
| rg_name | (string) | Имя ресурсной группы. Данный параметр является обязательным при создании. |
| sep_pools| (list) | Список словарей, описывающих доступные пулы СХД.<br>Ключи словаря:<br>&bull; `sep_id` (int) - идентификатор системы хранения данных.<br>&bull; `pool_names` (list) - список названий пулов системы хранения данных.<br>Чтобы очистить список доступных пулов, нужно указать пустой список `[]`.|
| state | Значения:<br>`present`<br>`absent`<br>`enabled`<br>`disabled`<br>Default: `present` | Целевое состояние ресурсной группы. |
## Возвращаемые значения модуля decort_rg
Модуль decort_rg возвращает информацию о ресурсной группе в виде словаря facts со следующими ключами:
| Ключ | Тип данных | Описание |
|------|------------|----------|
| account_id | int | Уникальный целочисленный идентификатор аккаунта, которому принадлежит данная ресурсная группа. |
| description | string | Текстовое описание ресурсной группы. |
| gid | int | Идентификатор физического кластера (Grid ID), на базе которого развёрнута ресурсная группа. |
| id | int | Уникальный целочисленный идентификатор ресурсной группы. |
| name | string | Имя ресурсной группы. Обратите внимание, что это имя уникально только в рамках аккаунта, которому принадлежит данная ресурсная группа. |
| state | string | Текущее состояние ресурсной группы. |
| quota | dict | Текущие квоты ресурсной группы. |
| resTypes | list | Список типов ресурсов, разрешенных к созданию в данной ресурсной группе. |
| defNetId | int | Уникальный целочисленный идентификатор сети по умолчанию в данной ресурсной группе. |
| defNetType | string | Тип сети по умолчанию в данной ресурсной группе. |
| ViNS | list | Список идентификаторов внутренних сетей ресурсной группы. |
| computes | list | Список идентификаторов виртуальных машин ресурсной группы. |
| uniqPools | list | Список доступных пулов СХД. |
## Пример использования модуля decort_rg
В данном примере показано, как создать ресурсную группу по имени MyRG в аккаунте MyAccount.
```
- name: manage resource group
decort_rg:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
account_name: "MyAccount"
rg_name: "MyRG"
state: present
register: my_rg
delegate_to: localhost
```
В данном примере показано, как создать ресурсную группу по имени MyRG в аккаунте MyAccount, также задать квоты и выдать права на чтение пользователю MyUser.
```
- name: manage resource group
decort_rg:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
account_name: "MyAccount"
rg_name: "MyRG"
access:
action: "grant"
user: "MyUser"
right: "R"
quotas:
cpu: 16
ram: 16384
disk: 100
ext_ips: 20
net_transfer: 1000
state: present
register: my_rg
delegate_to: localhost
```
В данном примере показано, как выдать доступ на чтение и запись пользователю MyUser в ресурсной группе по имени MyRG в аккаунте MyAccount.
```
- name: manage resource group
decort_rg:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
account_name: "MyAccount"
rg_name: "MyRG"
access:
action: "grant"
user: "MyUser"
right: "RCX"
state: present
register: my_rg
delegate_to: localhost
```
В данном примере показано, как сменить квоту в ресурсной группе по имени MyRG в аккаунте MyAccount.
```
- name: manage resource group
decort_rg:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
account_name: "MyAccount"
rg_name: "MyRG"
quotas:
cpu: 16
ram: 16384
disk: 100
ext_ips: 20
net_transfer: 1000
state: present
register: my_rg
delegate_to: localhost
```
В данном примере показано, как изменить сеть по умолчанию в ресурсной группе по имени MyRG в аккаунте MyAccount.
```
- name: manage resource group
decort_rg:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
account_name: "MyAccount"
rg_name: "MyRG"
def_netType: "PRIVATE"
def_netId: 99
state: present
register: my_rg
delegate_to: localhost
```
В данном примере показано, как переименовать ресурсную группу по имени MyRG на новое имя "NewRg" в аккаунте MyAccount.
```
- name: manage resource group
decort_rg:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
account_name: "MyAccount"
rg_name: "MyRG"
rename: "NewRg"
rg_id: 27
state: present
register: my_rg
delegate_to: localhost
```
В данном примере результат работы модуля decort_rg записывается в переменную my_rg.
Модули DECORT, которым для работы требуется ресурсная группа, в качестве одного из параметров, как правило, принимают идентификатор `rg_id`. Так, например, используя модуль `decort_kvmvm` для создания виртуального сервера необходимо указать ресурсную группу, к которой будет принадлежать этот виртуальный сервер. Сделать это можно следующим образом:
```
<прочие детали опущены>
rg_id: "{{ my_rg.facts.id }}"
```
В данном примере показано, как изменить доступные пулы СХД в ресурсной группе по имени MyRG в аккаунте MyAccount.
```
- name: change available sep pools
decort_rg:
authenticator: oauth2
app_id: "{{ my_app_id }}"
app_secret: "{{ my_app_secret }}"
oauth2_url: "https://sso.digitalenergy.online"
controller_url: "https://cloud.digitalenergy.online"
account_name: "MyAccount"
rg_name: "MyRG"
sep_pools:
- sep_id: 1
pool_names:
- sep1_pool1
- sep1_pool2
- sep_id: 2
pool_names:
- sep2_pool1
state: present
register: my_rg
delegate_to: localhost
```

@ -0,0 +1,248 @@
# Модуль decort_snapshot
## Обзор модуля
Модуль **decort_snapshot** предназначен для выполнения следующих действий над снимками виртуальных машин:
- **создать** (см. [параметр state](#state) и [примеры](#создать))
- **удалить** (см. [параметр state](#state) и [примеры](#удалить))
- **получить основную информацию о снимке** (см. [возвращаемые значения](#основная-информация) и [примеры](#получить-основную-информацию-о-снимке))
- **получить информацию о размере снимка** (см. [параметр usage](#usage), [возвращаемые значения](#размер-снимка) и [примеры](#получить-информацию-о-размере-снимка))
## Параметры модуля
Ниже приведен список параметров для модуля **decort_snapshot** (за исключением [общих параметров авторизации](./введение.md#общие-параметры-модулей-для-авторизации)):
<table>
<tr>
<th colspan="6">Параметр</th>
<th>Тип</th>
<th>Описание</th>
</tr>
<tr>
<td colspan="6">
<a name="label">
label
</a>
</td>
<td>
(str)
</td>
<td>
Метка снимка виртуальной машины. Если метка не указана при создании, она будет сгенерирована автоматически на основе даты и времени - <code>vm_name_2024-12-10_16-40-52</code>.
</td>
</tr>
<tr>
<td colspan="6">
<a name="state">
state
</a>
</td>
<td>
(str)
<br>Значения:
<br><code>absent</code>
<br><code>present</code>
</td>
<td>
Целевое состояние.
<br><code>absent</code> - снимок удален.
<br><code>present</code> - снимок существует.
</td>
</tr>
<tr>
<td colspan="6">
<a name="usage">
usage
</a>
</td>
<td>
(bool)
<br>Default:<code>false</code>
</td>
<td>
Получить информацию о реальном размере снимка виртуальной машины.
</td>
</tr>
<tr>
<td colspan="6">
<a name="vm_id">
vm_id
</a>
</td>
<td>
(int)
</td>
<td>
Идентификатор виртуальной машины.
<br>Обязательный параметр.
</td>
</tr>
</table>
## Возвращаемые значения
Модуль **decort_snapshot** возвращает информацию о снимке виртуальной машины в виде словаря `facts` со следующими ключами:
### Основная информация
<table>
<tr>
<th colspan="6">
Ключ
</th>
<th>
Тип
<br>данных
</th>
<th>
Описание
</th>
</tr>
<tr>
<td colspan="6">
disks
</td>
<td>
list
</td>
<td>
Диски
</td>
</tr>
<tr>
<td colspan="6">
guid
</td>
<td>
str
</td>
<td>
Идентификатор снимка
</td>
</tr>
<tr>
<td colspan="6">
label
</td>
<td>
str
</td>
<td>
Метка снимка
</td>
</tr>
<tr>
<td colspan="6">
timestamp
</td>
<td>
int
</td>
<td>
Временная метка создания снимка
</td>
</tr>
<tr>
<td colspan="6">
vm_id
</td>
<td>
int
</td>
<td>
Идентификатор виртуальной машины
</td>
</tr>
</table>
### Размер снимка
<table>
<tr>
<th colspan="6">
Ключ
</th>
<th>
Тип
<br>данных
</th>
<th>
Описание
</th>
</tr>
<tr>
<td colspan="6">
stored
</td>
<td>
float
</td>
<td>
Размер снимка
</td>
</tr>
</table>
## Примеры использования
### Создать
#### С указанием метки
```
- name: Example
hosts: localhost
tasks:
- name: Create snapshot
decort_snapshot:
# Параметры для авторизации упущены
vm_id: "{{ vm_id }}"
label: "{{ snapshot_label }}"
state: present
```
#### Без указания метки
```
- name: Example
hosts: localhost
tasks:
- name: Create snapshot
decort_snapshot:
# Параметры для авторизации упущены
vm_id: "{{ vm_id }}"
state: present
```
### Удалить
```
- name: Example
hosts: localhost
tasks:
- name: Delete snapshot
decort_snapshot:
# Параметры для авторизации упущены
vm_id: "{{ vm_id }}"
label: "{{ snapshot_label }}"
state: absent
```
### Получить основную информацию о снимке
```
- name: Example
hosts: localhost
tasks:
- name: Get basic snapshot info
decort_snapshot:
# Параметры для авторизации упущены
vm_id: "{{ vm_id }}"
label: "{{ snapshot_label }}"
```
### Получить информацию о размере снимка
```
- name: Example
hosts: localhost
tasks:
- name: Get snapshot usage
decort_snapshot:
# Параметры для авторизации упущены
vm_id: "{{ vm_id }}"
label: "{{ snapshot_label }}"
usage: true
```

File diff suppressed because it is too large Load Diff

@ -0,0 +1,110 @@
# Модуль decort_vins
## Обзор модуля decort_vins
Модуль decort_vins предназначен для управления внутренними сетями (Virtual Network Segment, ViNS) и позволяет производить с ними следующие действия:
- создавать
- на уровне ресурсной группы (если РГ задана)
- на уровне аккаунта (если РГ не задана)
- удалять (безвозвратно)
- восстанавливать из корзины
- запрашивать информацию
- включать/отключать
- соединять (необходимы права администратора)
- изменять:
- включать/отключать SSH-доступ к виртуальному маршрутизатору (необходимы права администратора)
- включать/отключать режим **Custom Config** для виртуального маршрутизатора (необходимы права администратора)
- сохранять конфигурацию виртуального маршрутизатора для возможности последующего отката к ней (необходимы права администратора)
## Параметры модуля decort_vins
Ниже приведен список параметров для модуля **decort_vins** (за исключением [общих параметров авторизации](./введение.md#общие-параметры-модулей-для-авторизации)):
| Параметр | Тип, допустимые значения | Описание |
| ------ | ------ | ------ |
| account_id | (int) | Уникальный целочисленный идентификатор аккаунта, которому принадлежит данная внутреняя сеть. При идентификации внутренней сети по имени (см. параметр `vins_name`) должен быть задан либо идентификатор, либо имя аккаунта (см. параметр `account_name`). Если одновременно заданы и `account_id`, и `account_name`, то `account_name` игнорируется.|
| account_name | (string) | Имя аккаунта, которому принадлежит данная внутренняя сеть. При идентификации внутренней сети по имени (см. параметр `vins_name`) должно быть задано либо имя, либо идентификатор аккаунта (см. параметр account_id). Если одновременно заданы и `account_id`, и `account_name`, то `account_name` игнорируется.|
|description | (string)| Текстовое описание внутренней сети. Данный аргумент является опциональным и учитывается только при создании внутренней сети, а при всех прочих операциях игнорируется.|
| ext_net_id | (int) | Идентификатор внешней сети, к которой должна быть подключена внутренняя сеть. Если задать значение `0`, то платформой будет выбрана внешняя сеть по умолчанию. |
| ext_ip_addr | (string) | IP-адрес внешней сети, заданной через параметр `ext_net_id`. Если не задан, то IP-адрес для внешней сети будет выбран платформой автоматически.
| ipcidr | (string) | Адрес сети для создаваемой внутренней сети. Если этот параметр не задан, то платформа назначит адрес автоматически. Обратите внимание, что внутренние сети, принадлежащие одному и тому же аккаунту, не могут иметь пересекающихся сетей.|
|rg_id | (int) | Идентификатор ресурсной группы, в которой должна быть создана или уже существует внутренняя сеть. Если одновременно заданы `rg_id` и `rg_name`, то `rg_name` игнорируется.|
| rg_name | (string) | Имя ресурсной группы, в которой должна быть создана или уже существует внутренняя сеть. Если одновременно заданы `rg_name` и `rg_id`, то `rg_name` игнорируется.|
| state | (string)<br>Значения:<br/>`present`<br/>`absent`<br/>`enabled`<br/>`disabled`<br/>Default: `present` | Целевое состояние внутренней сети. |
| vins_id | (int) | Идентификатор внутренней сети. Соответствующая внутренная сеть должна существовать. Таким образом, с помощью `vins_id` нельзя создать новую внутреннюю сеть, а только управлять уже имеющимися. Если задан данный параметр, то параметры `vins_name`, `account_name`, `account_id`, `rg_name` и `rg_id` игнорируются.|
| vins_name| (string) | Имя внутренней сети. Для идентификации внутренней сети требуется либо `vins_name` и информация об аккаунте/ресурсной группе, которой принадлежит сеть, либо `vins_id`. Обратите внимание, что это имя уникально только в рамках ресурсной группы или аккаунта, на уровне которого существует данная внутренняя сеть.|
| mgmtaddr | (list) | Список существующих IP-адресов виртуального маршрутизатора во внутренней сети, через которые необходимо разрешить SSH-доступ к виртуальному маршрутизатору.
| custom_config | (bool)<br>Default: `false` | Включить/отключить режим пользовательской конфигурации виртуального маршрутизатора. |
| config_save | (bool)<br>Default: `false` | Выполнить сохранение текущей конфигурации виртуального маршрутизатора для возможности последующего отката к ней. |
| connect_to | (list) | Список словарей, содержащих информацию о внутренних сетях, к которым необходимо подключить данную. См. примеры.
## Возвращаемые значения модуля decort_vins
Модуль decort_vins возвращает информацию о внутренней сети в виде словаря facts со следующими ключами:
| Ключ | Тип данных | Описание |
| --- | --- | --- |
| account_id | (int) | Уникальный целочисленный идентификатор аккаунта, которому принадлежит внутренняя сеть. |
| custom_net_addr | (list) | Список IP-адресов пользовательских интерфейсов виртуального маршрутизатора
| ext_ip_addr | (string) | IP-адрес интерфейса, которым виртуальный маршрутизатор подключён к внешней сети. |
| ext_net_id | (int) | Идентификатор внешней сети, к которой подключена внутренняя сеть. `-1` означает, что внутренняя сеть не подключёна к внешней сети. |
| gid | (int) | Идентификатор физического кластера (Grid ID), на базе которого развёрнуты ресурсы данной внутренней сети. |
| id | (int) | Уникальный целочисленный идентификатор внутренней сети. |
| name | (string) | Имя внутренней сети. |
| int_net_addr | (string) | Адрес внутренней сети. |
| rg_id | (int) | Уникальный целочисленный идентификатор ресурсной группы, которой принадлежит данная внутренняя сеть. Если данная внутренняя сеть создана на уровне аккаунта, то `rg_id=0`. |
| ssh_ipaddr | (list) | Список IP-адресов виртуального маршрутизатора во внутренней сети, на которых включён SSH-доступ к нему.
| ssh_password | (str) | Пароль для SSH-доступа к виртуальному маршрутизатору.
| ssh_port | (int) | Номер порта для SSH-подключения к виртуальному маршрутизатору.
| state | (string) | Состояние внутренней сети. |
## Пример использования модуля decort_vins
В данном примере создаётся внутренняя сеть с именем "MyVins01" (vins_name: "MyVins01").
Внутренняя сеть создаётся на уровне ресурсной группы "MyRg01" (rg_name: "MyRg01"), принадлежащей аккаунту "MyMainAccount" (account_name: "MyMainAccount"). Внутренняя сеть будет иметь подключение во внешнюю сеть по умолчанию (ext_net_id: 0).
```
- name: Manage ViNS on resource group level
decort_vins:
account_name: "MyMainAccount"
rg_name: "MyRg01"
authenticator: jwt
jwt: "{{ my_jwt.jwt }}"
controller_url: "https://ds1.digitalenergy.online"
ext_net_id: 0
vins_name: "MyVins01"
register: my_vins
```
Здесь результат исполнения модуля decort_vins записывается в переменную my_vins, которую можно дальше использовать в Ansible playbooks. Ниже показано, как получить и использовать идентификатор внутренней сети для подключения к нему виртуального сервера.
```
- name: Manage virtual machine
decort_kvmvm:
<< для краткости фрагмент опущен >>
networks:
- type: VINS
id: "{{ my_vins.facts.id }}"
<< для краткости фрагмент опущен >>
```
В данном примере идёт создание внутренней сети, а потом её привязка к внутренним сетям с id 864 и 196.
```
- name: Manage ViNS on resource group level
decort_vins:
authenticator: jwt
jwt: "{{ my_jwt.jwt }}"
controller_url: "https://cloud.digitalenergy.online"
vins_name: "ViNS_connected_by_decort_vins_module"
rg_id: 98
connect_to:
- id: 864
ipaddr: 192.168.5.66
netmask: 24
- id: 196
ipaddr: 192.168.9.133
netmask: 24
register: managed_vins
```

@ -1,5 +1,6 @@
## Документация: ## Документация:
- [Модули Ansible версии 7.2.0](./7.2.0/Home.md)
- [Модули Ansible версии 7.1.0](./7.1.0/Home.md) - [Модули Ansible версии 7.1.0](./7.1.0/Home.md)
- [Модули Ansible версии 7.0.0](./7.0.0/Home.md) - [Модули Ansible версии 7.0.0](./7.0.0/Home.md)
- [Модули Ansible версии 6.1.0](./6.1.0/Home.md) - [Модули Ansible версии 6.1.0](./6.1.0/Home.md)

Loading…
Cancel
Save