Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8c554c8edd | |||
| becbe65993 |
@@ -1,30 +0,0 @@
|
|||||||
repos:
|
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
||||||
rev: v5.0.0
|
|
||||||
hooks:
|
|
||||||
- id: end-of-file-fixer
|
|
||||||
- id: no-commit-to-branch
|
|
||||||
name: no-commit-to-branch (main, master, dev_*)
|
|
||||||
args:
|
|
||||||
- --pattern
|
|
||||||
- dev_.*
|
|
||||||
- repo: https://github.com/pycqa/flake8
|
|
||||||
rev: 7.2.0
|
|
||||||
hooks:
|
|
||||||
- id: flake8
|
|
||||||
exclude: |
|
|
||||||
(?x)^(
|
|
||||||
module_utils/decort_utils.py |
|
|
||||||
library/decort_bservice.py |
|
|
||||||
library/decort_disk.py |
|
|
||||||
library/decort_group.py |
|
|
||||||
library/decort_k8s.py |
|
|
||||||
library/decort_kvmvm.py |
|
|
||||||
library/decort_lb.py |
|
|
||||||
library/decort_osimage.py |
|
|
||||||
library/decort_pfw.py |
|
|
||||||
library/decort_rg.py |
|
|
||||||
library/decort_vins.py
|
|
||||||
)$
|
|
||||||
args:
|
|
||||||
- --extend-ignore=E402
|
|
||||||
117
CHANGELOG.md
117
CHANGELOG.md
@@ -1,122 +1,11 @@
|
|||||||
# Список изменений в версии 9.0.0
|
# Список изменений в версии 10.0.1
|
||||||
|
|
||||||
## Добавлено
|
## Добавлено
|
||||||
### Глобально
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-798 | Обновлены системные требования: версия интерпретатора Python обновлена до 3.12, версия Python-библиотеки ansible обновлена до 11.6.0 |
|
|
||||||
|
|
||||||
### Модуль decort_kvmvm
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-790 | Добавлен параметр `zone_id` и возвращаемое значение `zone_id`. |
|
|
||||||
| BANS-810 | Добавлен параметр `guest_agent` и возвращаемое значение `guest_agent`. |
|
|
||||||
| BANS-806 | Добавлен параметр `get_snapshot_merge_status` и возвращаемое значение `snapshot_merge_status`. |
|
|
||||||
| BANS-823 | Добавлено значение `TRUNK` для параметра `networks.type`. |
|
|
||||||
| BANS-813 | Добавлено значение `SDN` для параметра `networks.type`. |
|
|
||||||
| BANS-835 | Добавлена возможность использования параметра `networks.mtu` для внешней сети. |
|
|
||||||
|
|
||||||
### Модуль decort_lb
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-793 | Добавлен параметр `zone_id` и возвращаемое значение `zone_id`. |
|
|
||||||
| BANS-819 | Добавлено возвращаемое значение `account_id`. |
|
|
||||||
| BANS-800 | Добавлены значения `stopped` и `started` для параметра `state` и возвращаемое значение `tech_status`. |
|
|
||||||
|
|
||||||
### Модуль decort_k8s
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-794 | Добавлен параметр `zone_id` и возвращаемое значение `zone_id`. |
|
|
||||||
| BANS-804 | Добавлены значения `stopped` и `started` для параметра `state`. |
|
|
||||||
|
|
||||||
### Модуль decort_vins
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-791 | Добавлен параметр `zone_id` и возвращаемое значение `zone_id`. |
|
|
||||||
|
|
||||||
### Модуль decort_bservice
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-792 | Добавлен параметр `zone_id` и возвращаемое значение `zone_id`. |
|
|
||||||
| BANS-805 | Добавлены значения `stopped` и `started` для параметра `state`. |
|
|
||||||
|
|
||||||
### Модуль decort_user_info
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-796 | Добавлен параметр `zones` и возвращаемое значение `zones`. |
|
|
||||||
| BANS-826 | Добавлен параметр `trunks` и возвращаемое значение `trunks`. |
|
|
||||||
|
|
||||||
### Модуль decort_account
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-789 | Добавлен параметр `default_zone_id` и возвращаемые значение `zoneIds`, `defaultZoneId`. |
|
|
||||||
|
|
||||||
### Модуль decort_account_info
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-809 | Добавлено значение `MERGE` для параметра `computes.filter.tech_status`. |
|
|
||||||
| BANS-855 | Добавлены значения `SNAPCREATE`, `CLONING`, `ROLLBACK` для параметра `computes.filter.tech_status`. |
|
|
||||||
|
|
||||||
### Модуль decort_rg
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-812 | Добавлен параметр `sdn_access_group_id` и возвращаемое значение `sdn_access_group_id`. |
|
|
||||||
|
|
||||||
### Модуль decort_zone
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-795 | Добавлен модуль `decort_zone` для получения информации о зонах. |
|
|
||||||
|
|
||||||
### Модуль decort_trunk
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-825 | Добавлен модуль `decort_trunk` для получения информации о транковых портах. |
|
|
||||||
|
|
||||||
### Модуль decort_snapshot
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-808 | Добавлено значение `merge_aborted` для параметра `state`. |
|
|
||||||
|
|
||||||
### Модуль decort_osimage
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-849 | Добавлен параметр `account_id`, используемый при создании шаблонных и виртуальных образов. |
|
|
||||||
|
|
||||||
## Удалено
|
## Удалено
|
||||||
### Модуль decort_disk
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-815 | Удалено значение по умолчанию для параметра `description`. |
|
|
||||||
|
|
||||||
### Модуль decort_lb
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-815 | Удалено значение по умолчанию для параметра `description`. |
|
|
||||||
|
|
||||||
### Модуль decort_k8s
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-804 | Удален параметр `started` в связи с переносом логики в параметр `state` (значение `started`). |
|
|
||||||
|
|
||||||
### Модуль decort_bservice
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-805 | Удален параметр `started` в связи с переносом логики в параметр `state` (значение `started`). |
|
|
||||||
|
|
||||||
### Модуль decort_osimage
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-849 | Удален параметр `account_Id` в связи с переименованием в `account_id`. |
|
|
||||||
|
|
||||||
## Исправлено
|
## Исправлено
|
||||||
### Модуль decort_lb
|
### Модуль decort_group
|
||||||
| Идентификатор<br>задачи | Описание |
|
| Идентификатор<br>задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BANS-803 | Модуль завершал работу ошибкой Python при создании балансировщика с указанием параметра `backends` или `frontends`. |
|
| BANS-941 | Исправлена ошибка, из-за которой не происходил запуск группы после создании с указанием параметра `timeoutStart`. |
|
||||||
| BANS-820 | Выполнение модуля с указанием параметра `vins_id` и без указания параметра `ext_net_id` вызывало создание балансировщика с некорректной сетевой конфигурацией, дальнейшее добавление конфигурации backend к которому завершалось ошибкой платформы. |
|
|
||||||
| BANS-799 | Скорректирована логика параметра целевого состояния `present`. Теперь состояние `present` соответствует тому, что балансировщик нагрузки существует, и не приводит к изменению состояния существующего балансировщика нагрузки. Также для параметра `state` значение по умолчанию `present` теперь только при создании балансировщика нагрузки. |
|
|
||||||
|
|
||||||
### Модуль decort_account
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BANS-817 | Модуль некорректно отслеживал завершение удаления и восстановления аккаунта. |
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
| Версия платформы | Версия модулей Ansible |
|
| Версия платформы | Версия модулей Ansible |
|
||||||
|:----------------:|:--------------------------:|
|
|:----------------:|:--------------------------:|
|
||||||
|
| 4.4.0 | 10.0.x |
|
||||||
| 4.4.0 build 963 | 9.0.x |
|
| 4.4.0 build 963 | 9.0.x |
|
||||||
| 4.3.0 | 8.0.x |
|
| 4.3.0 | 8.0.x |
|
||||||
| 4.2.0 | 7.0.x, 7.1.x, 7.2.x |
|
| 4.2.0 | 7.0.x, 7.1.x, 7.2.x |
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class decort_bservice(DecortController):
|
|||||||
self.fail_json(**self.result)
|
self.fail_json(**self.result)
|
||||||
if not arg_amodule.params['id']:
|
if not arg_amodule.params['id']:
|
||||||
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.acc_info = self.account_find(arg_amodule.params['account_name'],
|
validated_acc_id, self._acc_info = self.account_find(arg_amodule.params['account_name'],
|
||||||
arg_amodule.params['account_id'])
|
arg_amodule.params['account_id'])
|
||||||
if not validated_acc_id:
|
if not validated_acc_id:
|
||||||
self.result['failed'] = True
|
self.result['failed'] = True
|
||||||
@@ -113,7 +113,7 @@ class decort_bservice(DecortController):
|
|||||||
)
|
)
|
||||||
if self.bservice_id:
|
if self.bservice_id:
|
||||||
_, self.bservice_info = self.bservice_get_by_id(self.bservice_id)
|
_, self.bservice_info = self.bservice_get_by_id(self.bservice_id)
|
||||||
self.bservice_state(self.bservice_info,'enabled')
|
self.bservice_state(self.bservice_info, self.aparams['state'])
|
||||||
return
|
return
|
||||||
|
|
||||||
def action(self,d_state):
|
def action(self,d_state):
|
||||||
@@ -176,7 +176,6 @@ class decort_bservice(DecortController):
|
|||||||
),
|
),
|
||||||
state=dict(
|
state=dict(
|
||||||
type='str',
|
type='str',
|
||||||
default='present',
|
|
||||||
choices=[
|
choices=[
|
||||||
'absent',
|
'absent',
|
||||||
'disabled',
|
'disabled',
|
||||||
@@ -298,23 +297,28 @@ def main():
|
|||||||
subj.action(amodule.params['state'])
|
subj.action(amodule.params['state'])
|
||||||
if amodule.params['state'] == 'absent':
|
if amodule.params['state'] == 'absent':
|
||||||
subj.nop()
|
subj.nop()
|
||||||
elif subj.bservice_info['status'] in ('ENABLED', 'DISABLED'):
|
elif subj.bservice_info['status'] in (
|
||||||
|
'ENABLED', 'DISABLED', 'CREATED',
|
||||||
|
):
|
||||||
if amodule.params['state'] == 'absent':
|
if amodule.params['state'] == 'absent':
|
||||||
subj.destroy()
|
subj.destroy()
|
||||||
else:
|
else:
|
||||||
subj.action(amodule.params['state'])
|
subj.action(amodule.params['state'])
|
||||||
elif subj.bservice_info['status'] == "DESTROED":
|
elif subj.bservice_info['status'] == "DESTROYED":
|
||||||
if amodule.params['state'] in ('present','enabled'):
|
if amodule.params['state'] in ('present','enabled'):
|
||||||
subj.create()
|
subj.create()
|
||||||
subj.action(amodule.params['state'])
|
subj.action(amodule.params['state'])
|
||||||
if amodule.params['state'] == 'absent':
|
if amodule.params['state'] == 'absent':
|
||||||
subj.nop()
|
subj.nop()
|
||||||
else:
|
else:
|
||||||
if amodule.params['state'] == 'absent':
|
state = amodule.params['state']
|
||||||
|
if state is None:
|
||||||
|
state = 'present'
|
||||||
|
if state == 'absent':
|
||||||
subj.nop()
|
subj.nop()
|
||||||
if amodule.params['state'] in ('present','started'):
|
if state in ('present','started'):
|
||||||
subj.create()
|
subj.create()
|
||||||
elif amodule.params['state'] in ('stopped', 'disabled','enabled'):
|
elif state in ('stopped', 'disabled','enabled'):
|
||||||
subj.error()
|
subj.error()
|
||||||
|
|
||||||
if subj.result['failed']:
|
if subj.result['failed']:
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ class decort_disk(DecortController):
|
|||||||
validated_acc_id, validated_acc_info = self.account_find(
|
validated_acc_id, validated_acc_info = self.account_find(
|
||||||
arg_amodule.params['account_name'],
|
arg_amodule.params['account_name'],
|
||||||
arg_amodule.params['account_id'])
|
arg_amodule.params['account_id'])
|
||||||
|
self.acc_id = validated_acc_id
|
||||||
|
self._acc_info = validated_acc_info
|
||||||
if not validated_acc_id:
|
if not validated_acc_id:
|
||||||
self.result['changed'] = False
|
self.result['changed'] = False
|
||||||
self.result['msg'] = (
|
self.result['msg'] = (
|
||||||
@@ -51,8 +53,6 @@ class decort_disk(DecortController):
|
|||||||
)
|
)
|
||||||
self.amodule.fail_json(**self.result)
|
self.amodule.fail_json(**self.result)
|
||||||
|
|
||||||
self.acc_id = validated_acc_id
|
|
||||||
self._acc_info = validated_acc_info
|
|
||||||
validated_disk_id, validated_disk_facts = self.disk_find(
|
validated_disk_id, validated_disk_facts = self.disk_find(
|
||||||
disk_id=arg_amodule.params['id'],
|
disk_id=arg_amodule.params['id'],
|
||||||
name=arg_amodule.params['name'] if "name" in arg_amodule.params else "",
|
name=arg_amodule.params['name'] if "name" in arg_amodule.params else "",
|
||||||
@@ -67,15 +67,21 @@ class decort_disk(DecortController):
|
|||||||
self.disk_id = validated_disk_id
|
self.disk_id = validated_disk_id
|
||||||
self.disk_info = validated_disk_facts
|
self.disk_info = validated_disk_facts
|
||||||
|
|
||||||
def create(self):
|
if self.disk_id:
|
||||||
|
self.acc_id = validated_disk_facts['accountId']
|
||||||
|
self.check_amodule_args_for_change()
|
||||||
|
else:
|
||||||
|
self.check_amodule_args_for_create()
|
||||||
|
|
||||||
self.disk_id = self.disk_create(accountId=self.acc_id,
|
def create(self):
|
||||||
|
self.disk_id = self.disk_create(
|
||||||
|
accountId=self.acc_id,
|
||||||
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'],
|
||||||
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'],
|
||||||
|
storage_policy_id=self.aparams['storage_policy_id'],
|
||||||
)
|
)
|
||||||
#IO tune
|
#IO tune
|
||||||
if self.amodule.params['limitIO']:
|
if self.amodule.params['limitIO']:
|
||||||
@@ -115,14 +121,25 @@ class decort_disk(DecortController):
|
|||||||
#raise Exception(self.amodule.params['shareable'])
|
#raise Exception(self.amodule.params['shareable'])
|
||||||
if self.amodule.params['shareable'] != self.disk_info['shareable']:
|
if self.amodule.params['shareable'] != self.disk_info['shareable']:
|
||||||
self.disk_share(self.disk_id,self.amodule.params['shareable'])
|
self.disk_share(self.disk_id,self.amodule.params['shareable'])
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if (
|
||||||
|
aparam_storage_policy_id is not None
|
||||||
|
and aparam_storage_policy_id != self.disk_info['storage_policy_id']
|
||||||
|
):
|
||||||
|
self.disk_change_storage_policy(
|
||||||
|
disk_id=self.disk_id,
|
||||||
|
storage_policy_id=aparam_storage_policy_id,
|
||||||
|
)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
self.disk_id = self.disk_delete(disk_id=self.disk_id,
|
self.disk_delete(disk_id=self.disk_id,
|
||||||
detach=self.amodule.params['force_detach'],
|
detach=self.amodule.params['force_detach'],
|
||||||
permanently=self.amodule.params['permanently'],
|
permanently=self.amodule.params['permanently'],
|
||||||
reason=self.amodule.params['reason'])
|
reason=self.amodule.params['reason'])
|
||||||
self.disk_info['status'] = "DELETED"
|
self.disk_id, self.disk_info = self._disk_get_by_id(self.disk_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
def rename(self):
|
def rename(self):
|
||||||
@@ -175,6 +192,8 @@ class decort_disk(DecortController):
|
|||||||
ret_dict['iotune'] = self.disk_info['iotune']
|
ret_dict['iotune'] = self.disk_info['iotune']
|
||||||
ret_dict['size_available'] = self.disk_info['sizeAvailable']
|
ret_dict['size_available'] = self.disk_info['sizeAvailable']
|
||||||
ret_dict['size_used'] = self.disk_info['sizeUsed']
|
ret_dict['size_used'] = self.disk_info['sizeUsed']
|
||||||
|
ret_dict['storage_policy_id'] = self.disk_info['storage_policy_id']
|
||||||
|
ret_dict['to_clean'] = self.disk_info['to_clean']
|
||||||
|
|
||||||
return ret_dict
|
return ret_dict
|
||||||
|
|
||||||
@@ -219,10 +238,6 @@ class decort_disk(DecortController):
|
|||||||
size=dict(
|
size=dict(
|
||||||
type='int',
|
type='int',
|
||||||
),
|
),
|
||||||
iops=dict(
|
|
||||||
type='int',
|
|
||||||
default=2000,
|
|
||||||
),
|
|
||||||
limitIO=dict(
|
limitIO=dict(
|
||||||
type='dict',
|
type='dict',
|
||||||
options=dict(
|
options=dict(
|
||||||
@@ -287,6 +302,9 @@ class decort_disk(DecortController):
|
|||||||
'present',
|
'present',
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
storage_policy_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=[
|
required_one_of=[
|
||||||
@@ -294,6 +312,73 @@ class decort_disk(DecortController):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def check_amodule_args_for_change(self):
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
if self.check_aparam_storage_policy_id() is False:
|
||||||
|
check_errors = True
|
||||||
|
if self.check_aparam_size() is False:
|
||||||
|
check_errors = True
|
||||||
|
|
||||||
|
if check_errors:
|
||||||
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
def check_amodule_args_for_create(self):
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if aparam_storage_policy_id is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
'storage_policy_id must be specified when creating '
|
||||||
|
'a new disk'
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.check_aparam_storage_policy_id() is False:
|
||||||
|
check_errors = True
|
||||||
|
if self.check_aparam_size() is False:
|
||||||
|
check_errors = True
|
||||||
|
|
||||||
|
if check_errors:
|
||||||
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
def check_aparam_storage_policy_id(self) -> bool:
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if (
|
||||||
|
aparam_storage_policy_id is not None
|
||||||
|
and aparam_storage_policy_id
|
||||||
|
not in self.acc_info['storage_policy_ids']
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
f'Account ID {self.acc_id} does not have access to '
|
||||||
|
f'storage_policy_id {aparam_storage_policy_id}'
|
||||||
|
)
|
||||||
|
|
||||||
|
return not check_errors
|
||||||
|
|
||||||
|
def check_aparam_size(self) -> bool:
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_size = self.aparams['size']
|
||||||
|
if (
|
||||||
|
aparam_size is not None
|
||||||
|
and aparam_size <= 0
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg=(
|
||||||
|
'Check for parameter "size" failed: '
|
||||||
|
f'Disk cannot be size {aparam_size}'
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
return not check_errors
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
decon = decort_disk()
|
decon = decort_disk()
|
||||||
amodule = decon.amodule
|
amodule = decon.amodule
|
||||||
@@ -339,7 +424,7 @@ def main():
|
|||||||
if decon.result['failed']:
|
if decon.result['failed']:
|
||||||
amodule.fail_json(**decon.result)
|
amodule.fail_json(**decon.result)
|
||||||
else:
|
else:
|
||||||
if decon.result['changed'] and amodule.params['state'] in ('present'):
|
if decon.result['changed']:
|
||||||
_, decon.disk_info = decon.disk_find(decon.disk_id)
|
_, decon.disk_info = decon.disk_find(decon.disk_id)
|
||||||
decon.result['facts'] = decon.package_facts(amodule.check_mode)
|
decon.result['facts'] = decon.package_facts(amodule.check_mode)
|
||||||
amodule.exit_json(**decon.result)
|
amodule.exit_json(**decon.result)
|
||||||
|
|||||||
@@ -36,10 +36,14 @@ class decort_group(DecortController):
|
|||||||
group_id=arg_amodule.params['id'],
|
group_id=arg_amodule.params['id'],
|
||||||
group_name=arg_amodule.params['name'],
|
group_name=arg_amodule.params['name'],
|
||||||
)
|
)
|
||||||
|
self.acc_id = self.bservice_info['accountId']
|
||||||
|
self.rg_id = self.bservice_info['rgId']
|
||||||
|
|
||||||
if self.group_id:
|
if self.group_id:
|
||||||
self.group_should_exist = True
|
self.group_should_exist = True
|
||||||
self.check_amodule_args_for_change()
|
self.check_amodule_args_for_change()
|
||||||
|
else:
|
||||||
|
self.check_amodule_args_for_create()
|
||||||
|
|
||||||
return
|
return
|
||||||
def nop(self):
|
def nop(self):
|
||||||
@@ -84,6 +88,17 @@ class decort_group(DecortController):
|
|||||||
warning=True,
|
warning=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
driver = self.aparams['driver']
|
||||||
|
if driver is None:
|
||||||
|
driver = 'KVM_X86'
|
||||||
|
self.message(
|
||||||
|
msg=self.MESSAGES.default_value_used(
|
||||||
|
param_name='driver',
|
||||||
|
default_value=driver,
|
||||||
|
),
|
||||||
|
warning=True,
|
||||||
|
)
|
||||||
|
|
||||||
self.group_id=self.group_provision(
|
self.group_id=self.group_provision(
|
||||||
bs_id=self.bservice_id,
|
bs_id=self.bservice_id,
|
||||||
arg_name=self.amodule.params['name'],
|
arg_name=self.amodule.params['name'],
|
||||||
@@ -92,11 +107,12 @@ class decort_group(DecortController):
|
|||||||
arg_ram=self.amodule.params['ram'],
|
arg_ram=self.amodule.params['ram'],
|
||||||
arg_boot_disk=self.amodule.params['boot_disk'],
|
arg_boot_disk=self.amodule.params['boot_disk'],
|
||||||
arg_image_id=self.amodule.params['image_id'],
|
arg_image_id=self.amodule.params['image_id'],
|
||||||
arg_driver=self.amodule.params['driver'],
|
|
||||||
arg_role=self.amodule.params['role'],
|
arg_role=self.amodule.params['role'],
|
||||||
arg_network=self.amodule.params['networks'],
|
arg_network=self.amodule.params['networks'],
|
||||||
arg_timeout=self.amodule.params['timeoutStart'],
|
arg_timeout=self.amodule.params['timeoutStart'],
|
||||||
chipset=chipset,
|
chipset=chipset,
|
||||||
|
storage_policy_id=self.aparams['storage_policy_id'],
|
||||||
|
driver=driver,
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.amodule.params['state'] in ('started','present'):
|
if self.amodule.params['state'] in ('started','present'):
|
||||||
@@ -196,6 +212,7 @@ class decort_group(DecortController):
|
|||||||
ret_dict['techStatus'] = self.group_info['techStatus']
|
ret_dict['techStatus'] = self.group_info['techStatus']
|
||||||
ret_dict['state'] = self.group_info['status']
|
ret_dict['state'] = self.group_info['status']
|
||||||
ret_dict['Computes'] = self.group_info['computes']
|
ret_dict['Computes'] = self.group_info['computes']
|
||||||
|
ret_dict['driver'] = self.group_info['driver']
|
||||||
return ret_dict
|
return ret_dict
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -229,17 +246,6 @@ class decort_group(DecortController):
|
|||||||
image_id=dict(
|
image_id=dict(
|
||||||
type='int',
|
type='int',
|
||||||
),
|
),
|
||||||
image_name=dict(
|
|
||||||
type='str',
|
|
||||||
),
|
|
||||||
driver=dict(
|
|
||||||
type='str',
|
|
||||||
choices=[
|
|
||||||
'KVM_X86',
|
|
||||||
'SVA_KVM_X86',
|
|
||||||
],
|
|
||||||
default='KVM_X86',
|
|
||||||
),
|
|
||||||
boot_disk=dict(
|
boot_disk=dict(
|
||||||
type='int',
|
type='int',
|
||||||
),
|
),
|
||||||
@@ -287,17 +293,16 @@ class decort_group(DecortController):
|
|||||||
'i440fx',
|
'i440fx',
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
storage_policy_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
driver=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=[
|
required_one_of=[
|
||||||
('id', 'name'),
|
('id', 'name'),
|
||||||
('id', 'networks'),
|
|
||||||
('id', 'count'),
|
|
||||||
('id', 'cpu'),
|
|
||||||
('id', 'ram'),
|
|
||||||
('id', 'boot_disk'),
|
|
||||||
('id', 'image_id'),
|
|
||||||
('id', 'driver'),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -306,7 +311,7 @@ class decort_group(DecortController):
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
self.aparams['chipset'] is None
|
self.aparams['chipset'] is None
|
||||||
and self.aparams['count'] > len(self.group_info['computes'])
|
and (self.aparams['count'] if self.aparams['count'] is not None else 0) > len(self.group_info['computes'])
|
||||||
):
|
):
|
||||||
check_errors = True
|
check_errors = True
|
||||||
self.message(
|
self.message(
|
||||||
@@ -335,9 +340,71 @@ class decort_group(DecortController):
|
|||||||
)
|
)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if aparam_storage_policy_id is not None:
|
||||||
|
for compute in self.group_info['computes']:
|
||||||
|
_, compute_info, _ = self._compute_get_by_id(compute['id'])
|
||||||
|
for disk in compute_info['disks']:
|
||||||
|
if aparam_storage_policy_id != disk['storage_policy_id']:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" '
|
||||||
|
'failed: storage_policy_id can not be changed '
|
||||||
|
f'for compute ID {compute['id']} '
|
||||||
|
f'disk ID {disk['id']}'
|
||||||
|
)
|
||||||
|
|
||||||
|
aparam_driver = self.aparams['driver']
|
||||||
|
if (
|
||||||
|
aparam_driver is not None
|
||||||
|
and aparam_driver != self.group_info['driver']
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "driver" failed: '
|
||||||
|
'driver can not be changed'
|
||||||
|
)
|
||||||
|
|
||||||
if check_errors:
|
if check_errors:
|
||||||
self.exit(fail=True)
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
def check_amodule_args_for_create(self):
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if aparam_storage_policy_id is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
'storage_policy_id must be specified when creating '
|
||||||
|
'a new group'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if (
|
||||||
|
aparam_storage_policy_id
|
||||||
|
not in self.rg_info['storage_policy_ids']
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
f'RG ID {self.rg_id} does not have access to '
|
||||||
|
f'storage_policy_id {aparam_storage_policy_id}'
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
aparam_storage_policy_id
|
||||||
|
not in self.acc_info['storage_policy_ids']
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
f'Account ID {self.acc_id} does not have access to '
|
||||||
|
f'storage_policy_id {aparam_storage_policy_id}'
|
||||||
|
)
|
||||||
|
|
||||||
|
if check_errors:
|
||||||
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
subj = decort_group()
|
subj = decort_group()
|
||||||
amodule = subj.amodule
|
amodule = subj.amodule
|
||||||
@@ -359,8 +426,7 @@ def main():
|
|||||||
|
|
||||||
if subj.group_id:
|
if subj.group_id:
|
||||||
if subj.group_info['status'] in ("DELETING","DESTROYNG","CREATING","DESTROYING",
|
if subj.group_info['status'] in ("DELETING","DESTROYNG","CREATING","DESTROYING",
|
||||||
"ENABLING","DISABLING","RESTORING","MODELED",
|
"ENABLING","DISABLING","RESTORING","MODELED","DESTROYED"):
|
||||||
"DISABLED","DESTROYED"):
|
|
||||||
subj.error()
|
subj.error()
|
||||||
elif subj.group_info['status'] in ("DELETED","DESTROYED"):
|
elif subj.group_info['status'] in ("DELETED","DESTROYED"):
|
||||||
if amodule.params['state'] == 'absent':
|
if amodule.params['state'] == 'absent':
|
||||||
|
|||||||
@@ -166,7 +166,8 @@ class decort_k8s(DecortController):
|
|||||||
if wg[param] is None:
|
if wg[param] is None:
|
||||||
wg[param] = default_value
|
wg[param] = default_value
|
||||||
|
|
||||||
k8s_id = self.k8s_provision(self.amodule.params['name'],
|
k8s_id = self.k8s_provision(
|
||||||
|
self.amodule.params['name'],
|
||||||
self.amodule.params['k8ci_id'],
|
self.amodule.params['k8ci_id'],
|
||||||
self.amodule.params['rg_id'],
|
self.amodule.params['rg_id'],
|
||||||
self.amodule.params['vins_id'],
|
self.amodule.params['vins_id'],
|
||||||
@@ -190,9 +191,10 @@ class decort_k8s(DecortController):
|
|||||||
self.amodule.params['oidc_cert'],
|
self.amodule.params['oidc_cert'],
|
||||||
self.amodule.params['description'],
|
self.amodule.params['description'],
|
||||||
self.amodule.params['extnet_only'],
|
self.amodule.params['extnet_only'],
|
||||||
master_chipset,
|
master_chipset=master_chipset,
|
||||||
lb_sysctl=self.amodule.params['lb_sysctl'],
|
lb_sysctl=self.amodule.params['lb_sysctl'],
|
||||||
zone_id=self.aparams['zone_id'],
|
zone_id=self.aparams['zone_id'],
|
||||||
|
storage_policy_id=self.aparams['storage_policy_id'],
|
||||||
)
|
)
|
||||||
|
|
||||||
if not k8s_id:
|
if not k8s_id:
|
||||||
@@ -241,6 +243,12 @@ class decort_k8s(DecortController):
|
|||||||
)
|
)
|
||||||
self.exit(fail=True)
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
if (
|
||||||
|
self.aparams['name'] is not None
|
||||||
|
and self.aparams['name'] != self.k8s_info['name']
|
||||||
|
):
|
||||||
|
self.k8s_update(id=self.k8s_id, name=self.aparams['name'])
|
||||||
|
|
||||||
if preupdate:
|
if preupdate:
|
||||||
# K8s info updating
|
# K8s info updating
|
||||||
self.k8s_info = self.k8s_get_by_id(k8s_id=self.k8s_id)
|
self.k8s_info = self.k8s_get_by_id(k8s_id=self.k8s_id)
|
||||||
@@ -275,9 +283,6 @@ class decort_k8s(DecortController):
|
|||||||
type='str',
|
type='str',
|
||||||
default='',
|
default='',
|
||||||
),
|
),
|
||||||
quotas=dict(
|
|
||||||
type='dict',
|
|
||||||
),
|
|
||||||
state=dict(
|
state=dict(
|
||||||
type='str',
|
type='str',
|
||||||
default='present',
|
default='present',
|
||||||
@@ -448,6 +453,9 @@ class decort_k8s(DecortController):
|
|||||||
zone_id=dict(
|
zone_id=dict(
|
||||||
type='int',
|
type='int',
|
||||||
),
|
),
|
||||||
|
storage_policy_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=[
|
required_one_of=[
|
||||||
@@ -499,6 +507,32 @@ class decort_k8s(DecortController):
|
|||||||
'K8s cluster must be stopped to migrate to a zone.'
|
'K8s cluster must be stopped to migrate to a zone.'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if aparam_storage_policy_id is not None:
|
||||||
|
computes_ids = []
|
||||||
|
for master_node in self.k8s_info['k8sGroups']['masters'][
|
||||||
|
'detailedInfo'
|
||||||
|
]:
|
||||||
|
computes_ids.append(master_node['id'])
|
||||||
|
for wg in self.k8s_info['k8sGroups']['workers']:
|
||||||
|
workers_ids = [
|
||||||
|
worker['id'] for worker in wg['detailedInfo']
|
||||||
|
]
|
||||||
|
computes_ids.extend(workers_ids)
|
||||||
|
for compute_id in computes_ids:
|
||||||
|
_, compute_info, _ = self._compute_get_by_id(
|
||||||
|
comp_id=compute_id
|
||||||
|
)
|
||||||
|
for disk in compute_info['disks']:
|
||||||
|
if aparam_storage_policy_id != disk['storage_policy_id']:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" '
|
||||||
|
'failed: storage_policy_id can not be changed '
|
||||||
|
f'for k8s cluster ID {self.k8s_id} compute ID '
|
||||||
|
f'{compute_id} disk ID {disk['id']}'
|
||||||
|
)
|
||||||
|
|
||||||
if check_errors:
|
if check_errors:
|
||||||
self.exit(fail=True)
|
self.exit(fail=True)
|
||||||
|
|
||||||
@@ -540,6 +574,26 @@ class decort_k8s(DecortController):
|
|||||||
if self.check_aparam_zone_id() is False:
|
if self.check_aparam_zone_id() is False:
|
||||||
check_errors = True
|
check_errors = True
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if aparam_storage_policy_id is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
'storage_policy_id must be specified when creating '
|
||||||
|
'a new cluster'
|
||||||
|
)
|
||||||
|
elif (
|
||||||
|
aparam_storage_policy_id
|
||||||
|
not in self.rg_info['storage_policy_ids']
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
f'RG ID {self.rg_id} does not have access to '
|
||||||
|
f'storage_policy_id {aparam_storage_policy_id}'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if check_errors:
|
if check_errors:
|
||||||
self.exit(fail=True)
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ class decort_kvmvm(DecortController):
|
|||||||
comp_id=self.aparams['clone_from']['id'],
|
comp_id=self.aparams['clone_from']['id'],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
self.rg_id = self.vm_to_clone_info['rgId']
|
||||||
if not self.vm_to_clone_id:
|
if not self.vm_to_clone_id:
|
||||||
self.message(
|
self.message(
|
||||||
f'Check for parameter "clone_from.id" failed: '
|
f'Check for parameter "clone_from.id" failed: '
|
||||||
@@ -73,7 +74,7 @@ class decort_kvmvm(DecortController):
|
|||||||
|
|
||||||
clone_id, clone_dict, _ = self.compute_find(
|
clone_id, clone_dict, _ = self.compute_find(
|
||||||
comp_name=self.aparams['name'],
|
comp_name=self.aparams['name'],
|
||||||
rg_id=self.vm_to_clone_info['rgId'],
|
rg_id=self.rg_id,
|
||||||
)
|
)
|
||||||
self.check_amodule_args_for_clone(
|
self.check_amodule_args_for_clone(
|
||||||
clone_id=clone_id,
|
clone_id=clone_id,
|
||||||
@@ -389,7 +390,7 @@ class decort_kvmvm(DecortController):
|
|||||||
Compute instance with the specified characteristics into the target Resource Group.
|
Compute instance with the specified characteristics into the target Resource Group.
|
||||||
The target RG must exist.
|
The target RG must exist.
|
||||||
"""
|
"""
|
||||||
# the following parameters must be present: cpu, ram, image_id or image_name
|
# the following parameters must be present: cpu, ram, image_id
|
||||||
# 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')
|
||||||
@@ -429,27 +430,15 @@ class decort_kvmvm(DecortController):
|
|||||||
|
|
||||||
image_id, image_facts = None, None
|
image_id, image_facts = None, None
|
||||||
if self.aparam_image:
|
if self.aparam_image:
|
||||||
# either image_name or image_id must be present
|
|
||||||
if (
|
if (
|
||||||
self.check_amodule_argument('image_id', abort=False)
|
self.check_amodule_argument('image_id', abort=False)
|
||||||
and self.amodule.params['image_id'] > 0
|
and self.amodule.params['image_id'] > 0
|
||||||
):
|
):
|
||||||
# find image by image ID and account ID
|
# find image by image ID and account ID
|
||||||
# image_find(self, image_id, image_name, account_id, rg_id=0, sepid=0, pool=""):
|
# image_find(self, image_id, account_id, rg_id=0, sepid=0, pool=""):
|
||||||
image_id, image_facts = self.image_find(
|
image_id, image_facts = self.image_find(
|
||||||
image_id=self.amodule.params['image_id'],
|
image_id=self.amodule.params['image_id'],
|
||||||
image_name="",
|
|
||||||
account_id=self.acc_id)
|
account_id=self.acc_id)
|
||||||
elif (
|
|
||||||
self.check_amodule_argument('image_name', abort=False)
|
|
||||||
and self.amodule.params['image_name'] != ""
|
|
||||||
):
|
|
||||||
# find image by image name and account ID
|
|
||||||
image_id, image_facts = self.image_find(
|
|
||||||
image_id=0,
|
|
||||||
image_name=self.amodule.params['image_name'],
|
|
||||||
account_id=self.acc_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
if validated_bdisk_size <= image_facts['size']:
|
if validated_bdisk_size <= image_facts['size']:
|
||||||
# adjust disk size to the minimum allowed by OS image, which will be used to spin off this Compute
|
# adjust disk size to the minimum allowed by OS image, which will be used to spin off this Compute
|
||||||
@@ -523,9 +512,11 @@ class decort_kvmvm(DecortController):
|
|||||||
# if we get through here, all parameters required to create new Compute instance should be at hand
|
# if we get through here, all parameters required to create new Compute instance should be at hand
|
||||||
|
|
||||||
# NOTE: KVM VM is created in HALTED state and must be explicitly started
|
# NOTE: KVM VM is created in HALTED state and must be explicitly started
|
||||||
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_size=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'],
|
||||||
@@ -542,7 +533,10 @@ class decort_kvmvm(DecortController):
|
|||||||
boot_loader_type=loader_type,
|
boot_loader_type=loader_type,
|
||||||
network_interface_naming=network_interface_naming,
|
network_interface_naming=network_interface_naming,
|
||||||
hot_resize=hot_resize,
|
hot_resize=hot_resize,
|
||||||
zone_id=self.aparams['zone_id'],)
|
zone_id=self.aparams['zone_id'],
|
||||||
|
storage_policy_id=self.aparams['storage_policy_id'],
|
||||||
|
os_version=self.aparams['os_version'],
|
||||||
|
)
|
||||||
self.comp_should_exist = True
|
self.comp_should_exist = True
|
||||||
|
|
||||||
# Originally we would have had to re-read comp_info after VM was provisioned
|
# Originally we would have had to re-read comp_info after VM was provisioned
|
||||||
@@ -579,7 +573,7 @@ class decort_kvmvm(DecortController):
|
|||||||
if self.amodule.params['disks'] is not None:
|
if self.amodule.params['disks'] is not None:
|
||||||
self.compute_disks(
|
self.compute_disks(
|
||||||
comp_dict=self.comp_info,
|
comp_dict=self.comp_info,
|
||||||
aparam_disks=self.amodule.params['disks'],
|
aparam_disks_dict=self.amodule.params['disks'],
|
||||||
)
|
)
|
||||||
|
|
||||||
self.compute_affinity(self.comp_info,
|
self.compute_affinity(self.comp_info,
|
||||||
@@ -626,8 +620,7 @@ class decort_kvmvm(DecortController):
|
|||||||
Note that this handler deletes the VM permanently together with all assigned disk resources.
|
Note that this handler deletes the VM permanently together with all assigned disk resources.
|
||||||
"""
|
"""
|
||||||
self.compute_delete(comp_id=self.comp_id, permanently=True)
|
self.compute_delete(comp_id=self.comp_id, permanently=True)
|
||||||
self.comp_info['status'] = 'DESTROYED'
|
self.comp_id, self.comp_info, _ = self._compute_get_by_id(self.comp_id)
|
||||||
self.comp_should_exist = False
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def restore(self):
|
def restore(self):
|
||||||
@@ -676,7 +669,7 @@ class decort_kvmvm(DecortController):
|
|||||||
if self.amodule.params['disks'] is not None:
|
if self.amodule.params['disks'] is not None:
|
||||||
self.compute_disks(
|
self.compute_disks(
|
||||||
comp_dict=self.comp_info,
|
comp_dict=self.comp_info,
|
||||||
aparam_disks=self.amodule.params['disks'],
|
aparam_disks_dict=self.amodule.params['disks'],
|
||||||
)
|
)
|
||||||
|
|
||||||
aparam_boot = self.amodule.params['boot']
|
aparam_boot = self.amodule.params['boot']
|
||||||
@@ -695,6 +688,59 @@ class decort_kvmvm(DecortController):
|
|||||||
if boot_disk_new_size:
|
if boot_disk_new_size:
|
||||||
self.compute_bootdisk_size(self.comp_info, boot_disk_new_size)
|
self.compute_bootdisk_size(self.comp_info, boot_disk_new_size)
|
||||||
|
|
||||||
|
boot_order = aparam_boot['order']
|
||||||
|
if (
|
||||||
|
boot_order is not None
|
||||||
|
and self.comp_info['bootOrder'] != boot_order
|
||||||
|
):
|
||||||
|
self.compute_set_boot_order(
|
||||||
|
vm_id=self.comp_id,
|
||||||
|
order=boot_order,
|
||||||
|
)
|
||||||
|
|
||||||
|
disk_redeploy = aparam_boot['disk_redeploy']
|
||||||
|
if disk_redeploy:
|
||||||
|
auto_start = False
|
||||||
|
if self.aparams['state'] is None:
|
||||||
|
if self.comp_info['techStatus'] == 'STARTED':
|
||||||
|
auto_start = True
|
||||||
|
else:
|
||||||
|
if self.aparams['state'] == 'started':
|
||||||
|
auto_start = True
|
||||||
|
|
||||||
|
disk_size = None
|
||||||
|
if (
|
||||||
|
aparam_boot is not None
|
||||||
|
and aparam_boot['disk_size'] is not None
|
||||||
|
):
|
||||||
|
disk_size = aparam_boot['disk_size']
|
||||||
|
elif self.aparams['image_id'] is not None:
|
||||||
|
_, image_facts = self.image_find(
|
||||||
|
image_id=self.aparams['image_id'],
|
||||||
|
)
|
||||||
|
disk_size = image_facts['size']
|
||||||
|
|
||||||
|
os_version = None
|
||||||
|
if (
|
||||||
|
self.aparams['image_id'] is None
|
||||||
|
or self.aparams['image_id'] == self.comp_info['imageId']
|
||||||
|
):
|
||||||
|
if self.aparams['os_version'] is None:
|
||||||
|
os_version = self.comp_info['os_version']
|
||||||
|
else:
|
||||||
|
os_version = self.aparams['os_version']
|
||||||
|
elif self.aparams['image_id'] != self.comp_info['imageId']:
|
||||||
|
os_version = self.aparams['os_version']
|
||||||
|
|
||||||
|
self.compute_disk_redeploy(
|
||||||
|
vm_id=self.comp_id,
|
||||||
|
storage_policy_id=self.aparams['storage_policy_id'],
|
||||||
|
image_id=self.aparams['image_id'],
|
||||||
|
disk_size=disk_size,
|
||||||
|
auto_start=auto_start,
|
||||||
|
os_version=os_version,
|
||||||
|
)
|
||||||
|
|
||||||
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'],
|
||||||
wait_for_state_change=arg_wait_cycles)
|
wait_for_state_change=arg_wait_cycles)
|
||||||
@@ -754,6 +800,28 @@ class decort_kvmvm(DecortController):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
aparam_cdrom = self.aparams['cdrom']
|
||||||
|
if aparam_cdrom is not None:
|
||||||
|
mode = aparam_cdrom['mode']
|
||||||
|
image_id = aparam_cdrom['image_id']
|
||||||
|
if (
|
||||||
|
mode == 'insert'
|
||||||
|
and self.comp_info['cdImageId'] != image_id
|
||||||
|
):
|
||||||
|
self.compute_cd_insert(
|
||||||
|
vm_id=self.comp_id,
|
||||||
|
image_id=image_id,
|
||||||
|
)
|
||||||
|
elif mode == 'eject':
|
||||||
|
self.compute_cd_eject(
|
||||||
|
vm_id=self.comp_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.aparams['abort_cloning']:
|
||||||
|
self.compute_clone_abort(
|
||||||
|
vm_id=self.comp_id,
|
||||||
|
)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -773,6 +841,7 @@ class decort_kvmvm(DecortController):
|
|||||||
'boot.loader_type': 'loaderType',
|
'boot.loader_type': 'loaderType',
|
||||||
'network_interface_naming': 'networkInterfaceNaming',
|
'network_interface_naming': 'networkInterfaceNaming',
|
||||||
'hot_resize': 'hotResize',
|
'hot_resize': 'hotResize',
|
||||||
|
'os_version': 'os_version',
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_nested_value(
|
def get_nested_value(
|
||||||
@@ -814,6 +883,14 @@ class decort_kvmvm(DecortController):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if aparam_value is not None and aparam_value != comp_value:
|
if aparam_value is not None and aparam_value != comp_value:
|
||||||
|
# If disk_redeploy = True no need to update os_version.
|
||||||
|
# Updating os_version through compute_disk_redeploy
|
||||||
|
if (
|
||||||
|
aparam_name == 'os_version'
|
||||||
|
and self.aparams['boot'] is not None
|
||||||
|
and self.aparams['boot']['disk_redeploy']
|
||||||
|
):
|
||||||
|
continue
|
||||||
result_args[aparam_name.replace('.', '_')] = (
|
result_args[aparam_name.replace('.', '_')] = (
|
||||||
aparam_value
|
aparam_value
|
||||||
)
|
)
|
||||||
@@ -837,7 +914,6 @@ class decort_kvmvm(DecortController):
|
|||||||
cpu="",
|
cpu="",
|
||||||
ram="",
|
ram="",
|
||||||
disk_size=0,
|
disk_size=0,
|
||||||
data_disks=[], # IDs of attached data disks; this list can be emty
|
|
||||||
state="CHECK_MODE",
|
state="CHECK_MODE",
|
||||||
tech_status="",
|
tech_status="",
|
||||||
account_id=0,
|
account_id=0,
|
||||||
@@ -898,18 +974,19 @@ class decort_kvmvm(DecortController):
|
|||||||
elif iface['connType'] == "VLAN": # This is direct external network connection
|
elif iface['connType'] == "VLAN": # This is direct external network connection
|
||||||
ret_dict['public_ips'].append(iface['ipAddress'])
|
ret_dict['public_ips'].append(iface['ipAddress'])
|
||||||
|
|
||||||
|
iface['security_group_mode'] = iface.pop('enable_secgroups')
|
||||||
|
iface['security_group_ids'] = iface.pop('security_groups')
|
||||||
|
|
||||||
ret_dict['cpu'] = self.comp_info['cpus']
|
ret_dict['cpu'] = self.comp_info['cpus']
|
||||||
ret_dict['ram'] = self.comp_info['ram']
|
ret_dict['ram'] = self.comp_info['ram']
|
||||||
|
|
||||||
ret_dict['image_id'] = self.comp_info['imageId']
|
ret_dict['image_id'] = self.comp_info['imageId']
|
||||||
|
|
||||||
for ddisk in self.comp_info['disks']:
|
ret_dict['disks'] = self.comp_info['disks']
|
||||||
if ddisk['type'] == 'B':
|
for disk in ret_dict['disks']:
|
||||||
|
if disk['type'] == 'B':
|
||||||
# if it is a boot disk - store its size
|
# if it is a boot disk - store its size
|
||||||
ret_dict['disk_size'] = ddisk['sizeMax']
|
ret_dict['disk_size'] = disk['sizeMax']
|
||||||
elif ddisk['type'] == 'D':
|
|
||||||
# if it is a data disk - append its ID to the list of data disks IDs
|
|
||||||
ret_dict['data_disks'].append(ddisk['id'])
|
|
||||||
|
|
||||||
ret_dict['chipset'] = self.comp_info['chipset']
|
ret_dict['chipset'] = self.comp_info['chipset']
|
||||||
|
|
||||||
@@ -960,15 +1037,30 @@ class decort_kvmvm(DecortController):
|
|||||||
self.comp_info['snapshot_merge_status']
|
self.comp_info['snapshot_merge_status']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ret_dict['cd_image_id'] = self.comp_info['cdImageId']
|
||||||
|
|
||||||
|
ret_dict['boot_order'] = self.comp_info['bootOrder']
|
||||||
|
|
||||||
|
ret_dict['os_version'] = self.comp_info['os_version']
|
||||||
|
|
||||||
|
ret_dict['boot_loader_metaiso'] = self.comp_info['loaderMetaIso']
|
||||||
|
if self.comp_info['loaderMetaIso'] is not None:
|
||||||
|
ret_dict['boot_loader_metaiso'] = {
|
||||||
|
'device_name': self.comp_info['loaderMetaIso']['devicename'],
|
||||||
|
'path': self.comp_info['loaderMetaIso']['path'],
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.amodule.params['get_cloning_status']:
|
||||||
|
ret_dict['cloning_status'] = self.compute_get_clone_status(
|
||||||
|
vm_id=self.comp_id,
|
||||||
|
)
|
||||||
|
|
||||||
return ret_dict
|
return ret_dict
|
||||||
|
|
||||||
def check_amodule_args_for_create(self):
|
def check_amodule_args_for_create(self):
|
||||||
check_errors = False
|
check_errors = False
|
||||||
# Check for unacceptable parameters for a blank Compute
|
# Check for unacceptable parameters for a blank Compute
|
||||||
if (
|
if self.aparams['image_id'] is not None:
|
||||||
self.aparams['image_id'] is not None
|
|
||||||
or self.aparams['image_name'] is not None
|
|
||||||
):
|
|
||||||
self.aparam_image = True
|
self.aparam_image = True
|
||||||
for param in (
|
for param in (
|
||||||
'network_interface_naming',
|
'network_interface_naming',
|
||||||
@@ -1017,7 +1109,7 @@ class decort_kvmvm(DecortController):
|
|||||||
check_errors = True
|
check_errors = True
|
||||||
self.message(
|
self.message(
|
||||||
f'Check for parameter "{parameter}" failed: '
|
f'Check for parameter "{parameter}" failed: '
|
||||||
f'"image_id" or "image_name" must be specified '
|
f'"image_id" must be specified '
|
||||||
f'to set {parameter}.'
|
f'to set {parameter}.'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1029,7 +1121,7 @@ class decort_kvmvm(DecortController):
|
|||||||
check_errors = True
|
check_errors = True
|
||||||
self.message(
|
self.message(
|
||||||
'Check for parameter "sep_id" failed: '
|
'Check for parameter "sep_id" failed: '
|
||||||
'"image_id" or "image_name" or "boot.disk_size" '
|
'"image_id" or "boot.disk_size" '
|
||||||
'must be specified to set sep_id.'
|
'must be specified to set sep_id.'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1072,6 +1164,39 @@ class decort_kvmvm(DecortController):
|
|||||||
if self.check_aparam_networks_trunk() is False:
|
if self.check_aparam_networks_trunk() is False:
|
||||||
check_errors = True
|
check_errors = True
|
||||||
|
|
||||||
|
if self.aparams['cdrom'] is not None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "cdrom" failed: '
|
||||||
|
'cdrom can be specified only for existing compute.'
|
||||||
|
)
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if aparam_storage_policy_id is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
'storage_policy_id must be specified when creating '
|
||||||
|
'a new compute'
|
||||||
|
)
|
||||||
|
elif (
|
||||||
|
aparam_storage_policy_id
|
||||||
|
not in self.rg_info['storage_policy_ids']
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
f'RG ID {self.rg_id} does not have access to '
|
||||||
|
f'storage_policy_id {aparam_storage_policy_id}'
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.aparams['abort_cloning'] is not None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "abort_cloning" failed: '
|
||||||
|
'abort_cloning can be specified only for existing compute.'
|
||||||
|
)
|
||||||
|
|
||||||
if check_errors:
|
if check_errors:
|
||||||
self.exit(fail=True)
|
self.exit(fail=True)
|
||||||
|
|
||||||
@@ -1114,6 +1239,19 @@ class decort_kvmvm(DecortController):
|
|||||||
'unknown',
|
'unknown',
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
from_cdrom=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
order=dict(
|
||||||
|
type='list',
|
||||||
|
elements='str',
|
||||||
|
choices=[
|
||||||
|
e.value for e in self.VMBootDevice
|
||||||
|
],
|
||||||
|
),
|
||||||
|
disk_redeploy=dict(
|
||||||
|
type='bool',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
sep_id=dict(
|
sep_id=dict(
|
||||||
@@ -1142,9 +1280,24 @@ class decort_kvmvm(DecortController):
|
|||||||
],
|
],
|
||||||
default='update',
|
default='update',
|
||||||
),
|
),
|
||||||
ids=dict(
|
objects=dict(
|
||||||
type='list',
|
type='list',
|
||||||
elements='int',
|
elements='dict',
|
||||||
|
options=dict(
|
||||||
|
id=dict(
|
||||||
|
type='int',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
pci_slot_num_hex=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
bus_num_hex=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
required_together=[
|
||||||
|
('pci_slot_num_hex', 'bus_num_hex'),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1155,9 +1308,6 @@ class decort_kvmvm(DecortController):
|
|||||||
image_id=dict(
|
image_id=dict(
|
||||||
type='int',
|
type='int',
|
||||||
),
|
),
|
||||||
image_name=dict(
|
|
||||||
type='str',
|
|
||||||
),
|
|
||||||
name=dict(
|
name=dict(
|
||||||
type='str',
|
type='str',
|
||||||
),
|
),
|
||||||
@@ -1190,6 +1340,16 @@ class decort_kvmvm(DecortController):
|
|||||||
mac=dict(
|
mac=dict(
|
||||||
type='str',
|
type='str',
|
||||||
),
|
),
|
||||||
|
security_group_ids=dict(
|
||||||
|
type='list',
|
||||||
|
elements='int',
|
||||||
|
),
|
||||||
|
security_group_mode=dict(
|
||||||
|
type='bool',
|
||||||
|
),
|
||||||
|
enabled=dict(
|
||||||
|
type='bool',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
required_if=[
|
required_if=[
|
||||||
('type', 'VINS', ('id',)),
|
('type', 'VINS', ('id',)),
|
||||||
@@ -1197,7 +1357,7 @@ class decort_kvmvm(DecortController):
|
|||||||
('type', 'VFNIC', ('id',)),
|
('type', 'VFNIC', ('id',)),
|
||||||
('type', 'DPDK', ('id',)),
|
('type', 'DPDK', ('id',)),
|
||||||
('type', 'TRUNK', ('id',)),
|
('type', 'TRUNK', ('id',)),
|
||||||
('type', 'SDN', ('id', 'mac')),
|
('type', 'SDN', ('id',)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
network_order_changing=dict(
|
network_order_changing=dict(
|
||||||
@@ -1326,6 +1486,16 @@ class decort_kvmvm(DecortController):
|
|||||||
('name', 'timestamp', 'datetime'),
|
('name', 'timestamp', 'datetime'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
sep_pool_name=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
sep_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
storage_policy_id=dict(
|
||||||
|
type='int',
|
||||||
|
requiered=True,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
network_interface_naming=dict(
|
network_interface_naming=dict(
|
||||||
@@ -1368,6 +1538,34 @@ class decort_kvmvm(DecortController):
|
|||||||
get_snapshot_merge_status=dict(
|
get_snapshot_merge_status=dict(
|
||||||
type='bool',
|
type='bool',
|
||||||
),
|
),
|
||||||
|
cdrom=dict(
|
||||||
|
type='dict',
|
||||||
|
options=dict(
|
||||||
|
mode=dict(
|
||||||
|
type='str',
|
||||||
|
choices=[
|
||||||
|
'insert',
|
||||||
|
'eject',
|
||||||
|
],
|
||||||
|
default='insert',
|
||||||
|
),
|
||||||
|
image_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
storage_policy_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
os_version=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
get_cloning_status=dict(
|
||||||
|
type='bool',
|
||||||
|
),
|
||||||
|
abort_cloning=dict(
|
||||||
|
type='bool',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=[
|
required_one_of=[
|
||||||
@@ -1404,30 +1602,6 @@ class decort_kvmvm(DecortController):
|
|||||||
|
|
||||||
aparam_boot = self.amodule.params['boot']
|
aparam_boot = self.amodule.params['boot']
|
||||||
if aparam_boot is not None:
|
if aparam_boot is not None:
|
||||||
new_boot_disk_size = aparam_boot['disk_size']
|
|
||||||
if new_boot_disk_size is not None:
|
|
||||||
boot_disk_size = 0
|
|
||||||
for disk in self.comp_info['disks']:
|
|
||||||
if disk['type'] == 'B':
|
|
||||||
boot_disk_size = disk['sizeMax']
|
|
||||||
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}'
|
|
||||||
)
|
|
||||||
|
|
||||||
aparam_disks = self.amodule.params['disks']
|
aparam_disks = self.amodule.params['disks']
|
||||||
aparam_boot_disk_id = aparam_boot['disk_id']
|
aparam_boot_disk_id = aparam_boot['disk_id']
|
||||||
comp_disk_ids = [disk['id'] for disk in self.comp_info['disks']]
|
comp_disk_ids = [disk['id'] for disk in self.comp_info['disks']]
|
||||||
@@ -1479,6 +1653,75 @@ class decort_kvmvm(DecortController):
|
|||||||
f'to Compute ID {self.comp_id}.'
|
f'to Compute ID {self.comp_id}.'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self.check_aparam_boot_disk_redeploy() is False:
|
||||||
|
check_errors = True
|
||||||
|
|
||||||
|
new_boot_disk_size = aparam_boot['disk_size']
|
||||||
|
if new_boot_disk_size is not None:
|
||||||
|
boot_disk_size = 0
|
||||||
|
for disk in self.comp_info['disks']:
|
||||||
|
if disk['type'] == 'B':
|
||||||
|
boot_disk_size = disk['sizeMax']
|
||||||
|
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}'
|
||||||
|
)
|
||||||
|
|
||||||
|
cd_rom_image_id = aparam_boot['from_cdrom']
|
||||||
|
if cd_rom_image_id is not None:
|
||||||
|
if not (
|
||||||
|
self.comp_info['techStatus'] == 'STOPPED'
|
||||||
|
and self.aparams['state'] == 'started'
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
f'Check for parameter "boot.from_cdrom" failed: '
|
||||||
|
f'VM ID {self.comp_id} must be stopped and "state" '
|
||||||
|
'must be "started" to boot from CD-ROM.'
|
||||||
|
)
|
||||||
|
_, image_info = self._image_get_by_id(
|
||||||
|
image_id=cd_rom_image_id,
|
||||||
|
)
|
||||||
|
if image_info is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "boot.from_cdrom" failed: '
|
||||||
|
f'Image ID {cd_rom_image_id} not found.'
|
||||||
|
)
|
||||||
|
elif image_info['type'] != 'cdrom':
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "boot.from_cdrom" failed: '
|
||||||
|
f'Image ID {cd_rom_image_id} is not a cd-rom type.'
|
||||||
|
)
|
||||||
|
|
||||||
|
boot_order_list = aparam_boot['order']
|
||||||
|
if boot_order_list is not None:
|
||||||
|
boot_order_duplicates = set([
|
||||||
|
boot_dev for boot_dev in boot_order_list
|
||||||
|
if boot_order_list.count(boot_dev) > 1
|
||||||
|
])
|
||||||
|
if boot_order_duplicates:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "boot.order" failed: '
|
||||||
|
'List of boot devices has duplicates: '
|
||||||
|
f'{boot_order_duplicates}.'
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not comp_info['imageId']
|
not comp_info['imageId']
|
||||||
and self.amodule.params['state'] in (
|
and self.amodule.params['state'] in (
|
||||||
@@ -1574,24 +1817,24 @@ class decort_kvmvm(DecortController):
|
|||||||
'VM must be started to get console url.'
|
'VM must be started to get console url.'
|
||||||
)
|
)
|
||||||
|
|
||||||
aparam_disks = self.aparams['disks']
|
aparam_disks_dict = self.aparams['disks']
|
||||||
if aparam_disks is not None:
|
if aparam_disks_dict is not None:
|
||||||
aparam_disks_ids = aparam_disks['ids']
|
aparam_disks = aparam_disks_dict.get('objects', [])
|
||||||
|
aparam_disks_ids = [disk['id'] for disk in aparam_disks]
|
||||||
comp_boot_disk_id = None
|
comp_boot_disk_id = None
|
||||||
for comp_disk in self.comp_info['disks']:
|
for comp_disk in self.comp_info['disks']:
|
||||||
if comp_disk['type'] == 'B':
|
if comp_disk['type'] == 'B':
|
||||||
comp_boot_disk_id = comp_disk['id']
|
comp_boot_disk_id = comp_disk['id']
|
||||||
break
|
break
|
||||||
disks_to_detach = []
|
disks_to_detach = []
|
||||||
match aparam_disks['mode']:
|
match aparam_disks_dict['mode']:
|
||||||
case 'detach' | 'delete':
|
case 'detach' | 'delete':
|
||||||
disks_to_detach = aparam_disks_ids
|
disks_to_detach = aparam_disks_ids
|
||||||
case 'match':
|
case 'match':
|
||||||
comp_disk_ids = {
|
comp_disk_ids = {
|
||||||
disk['id'] for disk in self.comp_info['disks']
|
disk['id'] for disk in self.comp_info['disks']
|
||||||
}
|
}
|
||||||
disks = set(aparam_disks_ids)
|
disks_to_detach = comp_disk_ids - set(aparam_disks_ids)
|
||||||
disks_to_detach = comp_disk_ids - disks
|
|
||||||
if (
|
if (
|
||||||
comp_boot_disk_id is not None
|
comp_boot_disk_id is not None
|
||||||
and comp_boot_disk_id in disks_to_detach
|
and comp_boot_disk_id in disks_to_detach
|
||||||
@@ -1611,6 +1854,18 @@ class decort_kvmvm(DecortController):
|
|||||||
f'Compute ID {self.comp_id} while snapshots exist.'
|
f'Compute ID {self.comp_id} while snapshots exist.'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if aparam_disks_dict['mode'] in ('delete', 'detach'):
|
||||||
|
for disk in aparam_disks:
|
||||||
|
for param, value in disk.items():
|
||||||
|
if param != 'id' and value is not None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "disks.objects" '
|
||||||
|
'failed: only disk id can be specified if '
|
||||||
|
'disks.mode is "delete" or "detach"'
|
||||||
|
)
|
||||||
|
break
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
self.aparams['cpu'] is not None
|
self.aparams['cpu'] is not None
|
||||||
@@ -1637,11 +1892,72 @@ class decort_kvmvm(DecortController):
|
|||||||
|
|
||||||
aparam_networks = self.aparams['networks']
|
aparam_networks = self.aparams['networks']
|
||||||
if aparam_networks is not None:
|
if aparam_networks is not None:
|
||||||
|
vm_networks = self.comp_info['interfaces']
|
||||||
|
if (
|
||||||
|
not vm_networks
|
||||||
|
and not self.is_vm_stopped_or_will_be_stopped
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "networks" failed: '
|
||||||
|
'VM must be stopped before attach it\'s first network.'
|
||||||
|
)
|
||||||
|
vm_networks_ids = [
|
||||||
|
network['netId'] for network in vm_networks
|
||||||
|
if network['type'] != self.VMNetType.EMPTY.value
|
||||||
|
]
|
||||||
|
aparam_networks_ids = [
|
||||||
|
network['id'] for network in aparam_networks
|
||||||
|
if network['type'] != self.VMNetType.EMPTY.value
|
||||||
|
]
|
||||||
|
new_networks = list(
|
||||||
|
set(aparam_networks_ids) - set(vm_networks_ids)
|
||||||
|
)
|
||||||
net_types = {net['type'] for net in aparam_networks}
|
net_types = {net['type'] for net in aparam_networks}
|
||||||
|
if new_networks:
|
||||||
|
if not (
|
||||||
|
len(new_networks) == 1
|
||||||
|
and self.VMNetType.DPDK.value in net_types
|
||||||
|
) and not self.is_vm_stopped_or_will_be_stopped:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "networks" failed: '
|
||||||
|
'VM must be stopped to attach non-DPDK network.'
|
||||||
|
)
|
||||||
|
|
||||||
if self.VMNetType.TRUNK.value in net_types:
|
if self.VMNetType.TRUNK.value in net_types:
|
||||||
if self.check_aparam_networks_trunk() is False:
|
if self.check_aparam_networks_trunk() is False:
|
||||||
check_errors = True
|
check_errors = True
|
||||||
|
|
||||||
|
for network in aparam_networks:
|
||||||
|
if (
|
||||||
|
network['enabled'] is not None
|
||||||
|
and network['type'] not in [
|
||||||
|
self.VMNetType.VINS.value,
|
||||||
|
self.VMNetType.EXTNET.value,
|
||||||
|
self.VMNetType.DPDK.value,
|
||||||
|
self.VMNetType.SDN.value,
|
||||||
|
self.VMNetType.TRUNK.value,
|
||||||
|
]
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "networks.enabled" failed: '
|
||||||
|
'Can not enable or disable network '
|
||||||
|
f'ID {network['id']} and type {network['type']}.'
|
||||||
|
'Only networks of type VINS, EXTNET, DPDK, SDN, TRUNK '
|
||||||
|
'can be enabled or disabled.'
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.check_aparam_cdrom() is False:
|
||||||
|
check_errors = True
|
||||||
|
|
||||||
|
if self.check_aparam_storage_policy_id() is False:
|
||||||
|
check_errors = True
|
||||||
|
|
||||||
|
if self.check_aparam_image_id() is False:
|
||||||
|
check_errors = True
|
||||||
|
|
||||||
if check_errors:
|
if check_errors:
|
||||||
self.exit(fail=True)
|
self.exit(fail=True)
|
||||||
|
|
||||||
@@ -1731,6 +2047,9 @@ class decort_kvmvm(DecortController):
|
|||||||
snapshot_timestamp=snapshot_timestamp,
|
snapshot_timestamp=snapshot_timestamp,
|
||||||
snapshot_name=snapshot_name,
|
snapshot_name=snapshot_name,
|
||||||
snapshot_datetime=snapshot_datetime,
|
snapshot_datetime=snapshot_datetime,
|
||||||
|
sep_pool_name=self.aparams['clone_from']['sep_pool_name'],
|
||||||
|
sep_id=self.aparams['clone_from']['sep_id'],
|
||||||
|
storage_policy_id=self.aparams['clone_from']['storage_policy_id'],
|
||||||
)
|
)
|
||||||
return clone_id
|
return clone_id
|
||||||
|
|
||||||
@@ -1812,6 +2131,130 @@ class decort_kvmvm(DecortController):
|
|||||||
|
|
||||||
return not check_errors
|
return not check_errors
|
||||||
|
|
||||||
|
def check_aparam_cdrom(self) -> bool | None:
|
||||||
|
check_errors = False
|
||||||
|
aparam_cdrom = self.aparams['cdrom']
|
||||||
|
if aparam_cdrom is not None:
|
||||||
|
mode = aparam_cdrom['mode']
|
||||||
|
if self.is_vm_stopped_or_will_be_stopped:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "cdrom" failed: '
|
||||||
|
f'VM ID {self.comp_id} must be started to {mode} '
|
||||||
|
f'CD-ROM.'
|
||||||
|
)
|
||||||
|
image_id = aparam_cdrom['image_id']
|
||||||
|
match mode:
|
||||||
|
case 'insert':
|
||||||
|
if image_id is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "cdrom.image_id" failed: '
|
||||||
|
f'cdrom.image_id must be specified '
|
||||||
|
f'if cdrom.mode is "insert".'
|
||||||
|
)
|
||||||
|
_, image_info = self._image_get_by_id(
|
||||||
|
image_id=image_id,
|
||||||
|
)
|
||||||
|
if image_info is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "cdrom.image_id" failed: '
|
||||||
|
f'Image ID {image_id} not found.'
|
||||||
|
)
|
||||||
|
elif image_info['type'] != 'cdrom':
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "cdrom.image_id" failed: '
|
||||||
|
f'Image ID {image_id} is not a CD-ROM type.'
|
||||||
|
)
|
||||||
|
case 'eject':
|
||||||
|
if image_id is not None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "cdrom.image_id" failed: '
|
||||||
|
f'cdrom.image_id must not be specified '
|
||||||
|
f'if cdrom.mode is "eject".'
|
||||||
|
)
|
||||||
|
if not self.comp_info['cdImageId']:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "cdrom.mode" failed: '
|
||||||
|
f'VM ID {self.comp_id} does not have CD-ROM '
|
||||||
|
'to eject.'
|
||||||
|
)
|
||||||
|
|
||||||
|
return not check_errors
|
||||||
|
|
||||||
|
def check_aparam_storage_policy_id(self) -> bool:
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if aparam_storage_policy_id is not None:
|
||||||
|
for disk in self.comp_info['disks']:
|
||||||
|
if aparam_storage_policy_id != disk['storage_policy_id']:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
'storage_policy_id can not be changed for compute '
|
||||||
|
f'ID {self.comp_id} disk ID {disk['id']}'
|
||||||
|
)
|
||||||
|
|
||||||
|
return not check_errors
|
||||||
|
|
||||||
|
def check_aparam_boot_disk_redeploy(self) -> bool:
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
disk_redeploy = self.aparams['boot']['disk_redeploy']
|
||||||
|
if disk_redeploy:
|
||||||
|
if self.aparams['storage_policy_id'] is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "storage_policy_id" failed:'
|
||||||
|
'"storage_policy_id" must be specified to redeploy.'
|
||||||
|
)
|
||||||
|
|
||||||
|
vm_has_boot_disk = False
|
||||||
|
for disk in self.comp_info['disks']:
|
||||||
|
if disk['type'] == 'B':
|
||||||
|
vm_has_boot_disk = True
|
||||||
|
break
|
||||||
|
if not vm_has_boot_disk:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "boot.redeploy" failed: '
|
||||||
|
'VM does not have boot disk to redeploy.'
|
||||||
|
)
|
||||||
|
|
||||||
|
aparam_disks = self.amodule.params['disks']
|
||||||
|
if aparam_disks is not None and aparam_disks['mode'] == 'match':
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "disks.mode" failed: '
|
||||||
|
'"disks.mode" must not be "match" to redeploy.'
|
||||||
|
)
|
||||||
|
|
||||||
|
return not check_errors
|
||||||
|
|
||||||
|
def check_aparam_image_id(self) -> bool:
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_image_id = self.aparams['image_id']
|
||||||
|
if aparam_image_id is not None:
|
||||||
|
if aparam_image_id != self.comp_info['imageId']:
|
||||||
|
if (
|
||||||
|
self.aparams['boot'] is None
|
||||||
|
or self.aparams['boot']['disk_redeploy'] is None
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
'Check for parameter "image_id" failed: '
|
||||||
|
'"boot.disk_redeploy" must be set to True to change '
|
||||||
|
'VM image.'
|
||||||
|
)
|
||||||
|
|
||||||
|
return not check_errors
|
||||||
|
|
||||||
def find_networks_tags_intersections(
|
def find_networks_tags_intersections(
|
||||||
self,
|
self,
|
||||||
trunk_networks: list,
|
trunk_networks: list,
|
||||||
@@ -1958,7 +2401,7 @@ def main():
|
|||||||
amodule = subj.amodule
|
amodule = subj.amodule
|
||||||
|
|
||||||
if subj.comp_id:
|
if subj.comp_id:
|
||||||
if subj.comp_info['status'] in ("DISABLED", "MIGRATING", "DELETING", "DESTROYING", "ERROR", "REDEPLOYING"):
|
if subj.comp_info['status'] in ("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()
|
||||||
elif subj.comp_info['status'] in ("ENABLED", "DISABLED"):
|
elif subj.comp_info['status'] in ("ENABLED", "DISABLED"):
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ class decort_lb(DecortController):
|
|||||||
if not self.lb_id:
|
if not self.lb_id:
|
||||||
self.result['failed'] = True
|
self.result['failed'] = True
|
||||||
self.result['msg'] = "Specified LB ID {} not found."\
|
self.result['msg'] = "Specified LB ID {} not found."\
|
||||||
.format(arg_amodule.params['lb _id'])
|
.format(arg_amodule.params['lb_id'])
|
||||||
self.fail_json(**self.result)
|
self.amodule.fail_json(**self.result)
|
||||||
self.rg_id = self.lb_facts['rgId']
|
self.rg_id = self.lb_facts['rgId']
|
||||||
self.vins_id = self.lb_facts['vinsId']
|
self.vins_id = self.lb_facts['vinsId']
|
||||||
|
|
||||||
@@ -51,12 +51,11 @@ class decort_lb(DecortController):
|
|||||||
self.rg_id, self.rg_facts = self.rg_find(0,arg_amodule.params['rg_id'], arg_rg_name="")
|
self.rg_id, self.rg_facts = self.rg_find(0,arg_amodule.params['rg_id'], arg_rg_name="")
|
||||||
if not self.rg_id:
|
if not self.rg_id:
|
||||||
self.result['failed'] = True
|
self.result['failed'] = True
|
||||||
self.result['msg'] = "Specified RG ID {} not found.".format(arg_amodule.params['vins_id'])
|
self.result['msg'] = "Specified RG ID {} not found.".format(arg_amodule.params['rg_id'])
|
||||||
self.amodule.fail_json(**self.result)
|
self.amodule.fail_json(**self.result)
|
||||||
self.acc_id = self.rg_facts['accountId']
|
self.acc_id = self.rg_facts['accountId']
|
||||||
|
|
||||||
elif arg_amodule.params['account_id'] or arg_amodule.params['account_name'] != "":
|
elif arg_amodule.params['account_id'] or arg_amodule.params['account_name'] != "":
|
||||||
|
|
||||||
if not arg_amodule.params['rg_name']:
|
if not arg_amodule.params['rg_name']:
|
||||||
self.result['failed'] = True
|
self.result['failed'] = True
|
||||||
self.result['msg'] = ("RG name must be specified with account present")
|
self.result['msg'] = ("RG name must be specified with account present")
|
||||||
@@ -163,8 +162,9 @@ class decort_lb(DecortController):
|
|||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
self.lb_delete(self.lb_id, self.amodule.params['permanently'])
|
self.lb_delete(self.lb_id, self.amodule.params['permanently'])
|
||||||
self.lb_facts['status'] = 'DESTROYED'
|
self.lb_id, self.lb_facts = self._lb_get_by_id(self.lb_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
def nop(self):
|
def nop(self):
|
||||||
"""No operation (NOP) handler for LB management by decort_lb module.
|
"""No operation (NOP) handler for LB management by decort_lb module.
|
||||||
This function is intended to be called from the main switch construct of the module
|
This function is intended to be called from the main switch construct of the module
|
||||||
@@ -252,10 +252,6 @@ class decort_lb(DecortController):
|
|||||||
type='int',
|
type='int',
|
||||||
default=0,
|
default=0,
|
||||||
),
|
),
|
||||||
ext_ip_addr=dict(
|
|
||||||
type='str',
|
|
||||||
default='',
|
|
||||||
),
|
|
||||||
state=dict(
|
state=dict(
|
||||||
type='str',
|
type='str',
|
||||||
choices=[
|
choices=[
|
||||||
@@ -411,10 +407,10 @@ def main():
|
|||||||
if decon.result['failed']:
|
if decon.result['failed']:
|
||||||
amodule.fail_json(**decon.result)
|
amodule.fail_json(**decon.result)
|
||||||
else:
|
else:
|
||||||
if decon.result['changed'] and amodule.params['state'] != 'absent':
|
if decon.result['changed']:
|
||||||
_, decon.lb_facts = decon.lb_find(decon.lb_id)
|
_, decon.lb_facts = decon.lb_find(lb_id=decon.lb_id)
|
||||||
if decon.lb_id:
|
|
||||||
decon.result['facts'] = decon.package_facts(amodule.check_mode)
|
decon.result['facts'] = decon.package_facts(amodule.check_mode)
|
||||||
amodule.exit_json(**decon.result)
|
amodule.exit_json(**decon.result)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ class decort_osimage(DecortController):
|
|||||||
self.validated_virt_image_id = 0
|
self.validated_virt_image_id = 0
|
||||||
self.validated_image_name = amodule.params['image_name']
|
self.validated_image_name = amodule.params['image_name']
|
||||||
self.validated_virt_image_name = None
|
self.validated_virt_image_name = None
|
||||||
self.validated_virt_image_id = amodule.params['virt_id']
|
self.image_info: dict
|
||||||
|
self.virt_image_info: dict
|
||||||
if amodule.params['account_name']:
|
if amodule.params['account_name']:
|
||||||
self.validated_account_id, _ = self.account_find(amodule.params['account_name'])
|
self.validated_account_id, _ = self.account_find(amodule.params['account_name'])
|
||||||
else:
|
else:
|
||||||
@@ -34,23 +35,51 @@ class decort_osimage(DecortController):
|
|||||||
self.result['changed'] = False
|
self.result['changed'] = False
|
||||||
self.result['msg'] = ("Cannot find account '{}'").format(amodule.params['account_name'])
|
self.result['msg'] = ("Cannot find account '{}'").format(amodule.params['account_name'])
|
||||||
amodule.fail_json(**self.result)
|
amodule.fail_json(**self.result)
|
||||||
|
self.acc_id = self.validated_account_id
|
||||||
|
|
||||||
|
if (
|
||||||
if amodule.params['virt_id'] != 0 and amodule.params['virt_name']:
|
self.aparams['virt_id'] != 0
|
||||||
self.validated_virt_image_id, image_facts =\
|
or self.aparams['virt_name'] is not None
|
||||||
|
):
|
||||||
|
self.validated_virt_image_id, self.virt_image_info = (
|
||||||
self.decort_virt_image_find(amodule)
|
self.decort_virt_image_find(amodule)
|
||||||
if (self.validated_virt_image_id and
|
)
|
||||||
amodule.params['virt_name'] != image_facts['name']):
|
if self.virt_image_info:
|
||||||
|
_, linked_image_info = self._image_get_by_id(
|
||||||
|
image_id=self.virt_image_info['linkTo']
|
||||||
|
)
|
||||||
|
self.acc_id = linked_image_info['accountId']
|
||||||
|
if (
|
||||||
|
self.aparams['virt_name'] is not None
|
||||||
|
and self.aparams['virt_name']
|
||||||
|
!= self.virt_image_info['name']
|
||||||
|
):
|
||||||
self.decort_virt_image_rename(amodule)
|
self.decort_virt_image_rename(amodule)
|
||||||
self.result['msg'] = 'Virtual image renamed successfully'
|
self.result['msg'] = 'Virtual image renamed successfully'
|
||||||
elif amodule.params['image_id'] != 0 and amodule.params['image_name']:
|
elif (
|
||||||
self.validated_image_id, image_facts = self.decort_image_find(amodule)
|
self.aparams['image_id'] != 0
|
||||||
if (self.validated_image_id and
|
or self.aparams['image_name'] is not None
|
||||||
amodule.params['image_name'] != image_facts['name']):
|
):
|
||||||
|
self.validated_image_id, self.image_info = (
|
||||||
|
self.decort_image_find(amodule)
|
||||||
|
)
|
||||||
|
if self.image_info:
|
||||||
|
self.acc_id = self.image_info['accountId']
|
||||||
|
if (
|
||||||
|
amodule.params['image_name']
|
||||||
|
and amodule.params['image_name'] != self.image_info['name']
|
||||||
|
):
|
||||||
decort_osimage.decort_image_rename(self,amodule)
|
decort_osimage.decort_image_rename(self,amodule)
|
||||||
self.result['msg'] = ("Image renamed successfully")
|
self.result['msg'] = ("Image renamed successfully")
|
||||||
|
|
||||||
|
if self.validated_image_id:
|
||||||
|
self.check_amodule_args_for_change()
|
||||||
|
elif self.validated_virt_image_id:
|
||||||
|
self.check_amodule_args_for_change_virt_image()
|
||||||
|
elif self.aparams['virt_name']:
|
||||||
|
self.check_amodule_args_for_create_virt_image()
|
||||||
|
else:
|
||||||
|
self.check_amodule_args_for_create_image()
|
||||||
|
|
||||||
def decort_image_find(self, amodule):
|
def decort_image_find(self, amodule):
|
||||||
# function that finds the OS image
|
# function that finds the OS image
|
||||||
@@ -121,9 +150,9 @@ class decort_osimage(DecortController):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# function that creates OS image
|
# function that creates OS image
|
||||||
image_facts = self.image_create(img_name=self.validated_image_name,
|
image_facts = self.image_create(
|
||||||
|
img_name=self.validated_image_name,
|
||||||
url=amodule.params['url'],
|
url=amodule.params['url'],
|
||||||
gid=amodule.params['gid'],
|
|
||||||
boot_mode=boot_mode,
|
boot_mode=boot_mode,
|
||||||
boot_loader_type=loader_type,
|
boot_loader_type=loader_type,
|
||||||
hot_resize=hot_resize,
|
hot_resize=hot_resize,
|
||||||
@@ -134,8 +163,9 @@ class decort_osimage(DecortController):
|
|||||||
passwordDL=amodule.params['passwordDL'],
|
passwordDL=amodule.params['passwordDL'],
|
||||||
sepId=amodule.params['sepId'],
|
sepId=amodule.params['sepId'],
|
||||||
poolName=amodule.params['poolName'],
|
poolName=amodule.params['poolName'],
|
||||||
drivers=amodule.params['drivers'],
|
network_interface_naming=network_interface_naming,
|
||||||
network_interface_naming=network_interface_naming)
|
storage_policy_id=amodule.params['storage_policy_id'],
|
||||||
|
)
|
||||||
self.result['changed'] = True
|
self.result['changed'] = True
|
||||||
return image_facts
|
return image_facts
|
||||||
|
|
||||||
@@ -151,8 +181,9 @@ class decort_osimage(DecortController):
|
|||||||
def decort_image_delete(self,amodule):
|
def decort_image_delete(self,amodule):
|
||||||
# function that removes an image
|
# function that removes an image
|
||||||
self.image_delete(imageId=amodule.image_id_delete)
|
self.image_delete(imageId=amodule.image_id_delete)
|
||||||
self.result['changed'] = True
|
_, image_facts = decort_osimage._image_get_by_id(self, amodule.image_id_delete)
|
||||||
self.result['msg'] = ("Image '{}' deleted").format(amodule.image_id_delete)
|
self.result['facts'] = decort_osimage.decort_osimage_package_facts(image_facts, amodule.check_mode)
|
||||||
|
return
|
||||||
|
|
||||||
def decort_virt_image_create(self,amodule):
|
def decort_virt_image_create(self,amodule):
|
||||||
# function that creates a virtual image
|
# function that creates a virtual image
|
||||||
@@ -231,6 +262,8 @@ class decort_osimage(DecortController):
|
|||||||
'networkInterfaceNaming'
|
'networkInterfaceNaming'
|
||||||
]
|
]
|
||||||
ret_dict['hot_resize'] = arg_osimage_facts['hotResize']
|
ret_dict['hot_resize'] = arg_osimage_facts['hotResize']
|
||||||
|
ret_dict['storage_policy_id'] = arg_osimage_facts['storage_policy_id']
|
||||||
|
ret_dict['to_clean'] = arg_osimage_facts['to_clean']
|
||||||
return ret_dict
|
return ret_dict
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -273,17 +306,9 @@ class decort_osimage(DecortController):
|
|||||||
'present',
|
'present',
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
drivers=dict(
|
|
||||||
type='str',
|
|
||||||
default='KVM_X86',
|
|
||||||
),
|
|
||||||
url=dict(
|
url=dict(
|
||||||
type='str',
|
type='str',
|
||||||
),
|
),
|
||||||
gid=dict(
|
|
||||||
type='int',
|
|
||||||
default=0,
|
|
||||||
),
|
|
||||||
sepId=dict(
|
sepId=dict(
|
||||||
type='int',
|
type='int',
|
||||||
default=0,
|
default=0,
|
||||||
@@ -333,10 +358,102 @@ class decort_osimage(DecortController):
|
|||||||
'eth',
|
'eth',
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
storage_policy_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def check_amodule_args_for_change(self):
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if (
|
||||||
|
aparam_storage_policy_id is not None
|
||||||
|
and aparam_storage_policy_id
|
||||||
|
not in self.acc_info['storage_policy_ids']
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
f'Account ID {self.acc_id} does not have access to '
|
||||||
|
f'storage_policy_id {aparam_storage_policy_id}'
|
||||||
|
)
|
||||||
|
|
||||||
|
if check_errors:
|
||||||
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
def check_amodule_args_for_change_virt_image(self):
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if (
|
||||||
|
aparam_storage_policy_id is not None
|
||||||
|
and (
|
||||||
|
aparam_storage_policy_id
|
||||||
|
!= self.virt_image_info['storage_policy_id']
|
||||||
|
)
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
'storage_policy_id can not be changed in virtual image'
|
||||||
|
)
|
||||||
|
|
||||||
|
if check_errors:
|
||||||
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
def check_amodule_args_for_create_image(self):
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_account_id = self.aparams['account_id']
|
||||||
|
if aparam_account_id is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "account_id" failed: '
|
||||||
|
'account_id must be specified when creating '
|
||||||
|
'a new image'
|
||||||
|
)
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if aparam_storage_policy_id is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
'storage_policy_id must be specified when creating '
|
||||||
|
'a new image'
|
||||||
|
)
|
||||||
|
elif (
|
||||||
|
aparam_storage_policy_id
|
||||||
|
not in self.acc_info['storage_policy_ids']
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
f'Account ID {self.acc_id} does not have access to '
|
||||||
|
f'storage_policy_id {aparam_storage_policy_id}'
|
||||||
|
)
|
||||||
|
|
||||||
|
if check_errors:
|
||||||
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
def check_amodule_args_for_create_virt_image(self):
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_storage_policy_id = self.aparams['storage_policy_id']
|
||||||
|
if aparam_storage_policy_id is not None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "storage_policy_id" failed: '
|
||||||
|
'storage_policy_id can not be specified when creating '
|
||||||
|
'virtual image'
|
||||||
|
)
|
||||||
|
|
||||||
|
if check_errors:
|
||||||
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
decon = decort_osimage()
|
decon = decort_osimage()
|
||||||
amodule = decon.amodule
|
amodule = decon.amodule
|
||||||
@@ -360,15 +477,31 @@ def main():
|
|||||||
decon.result['msg'] = ("Cannot find OS image")
|
decon.result['msg'] = ("Cannot find OS image")
|
||||||
amodule.fail_json(**decon.result)
|
amodule.fail_json(**decon.result)
|
||||||
|
|
||||||
if decon.validated_virt_image_id and decon.target_image_id:
|
if decon.validated_virt_image_id:
|
||||||
if decort_osimage.decort_osimage_package_facts(image_facts)['linkto'] != decon.target_image_id:
|
if (
|
||||||
|
decon.target_image_id
|
||||||
|
and decort_osimage.decort_osimage_package_facts(image_facts)[
|
||||||
|
'linkto'
|
||||||
|
] != decon.target_image_id
|
||||||
|
):
|
||||||
decort_osimage.decort_virt_image_link(decon,amodule)
|
decort_osimage.decort_virt_image_link(decon,amodule)
|
||||||
decon.result['changed'] = True
|
decon.result['changed'] = True
|
||||||
amodule.exit_json(**decon.result)
|
amodule.exit_json(**decon.result)
|
||||||
|
if (
|
||||||
|
amodule.params['storage_policy_id'] is not None
|
||||||
|
and amodule.params['storage_policy_id']
|
||||||
|
!= image_facts['storage_policy_id']
|
||||||
|
):
|
||||||
|
decon.image_change_storage_policy(
|
||||||
|
image_id=decon.validated_virt_image_id,
|
||||||
|
storage_policy_id=amodule.params['storage_policy_id'],
|
||||||
|
)
|
||||||
|
|
||||||
if decon.validated_virt_image_id > 0 and amodule.params['state'] == "absent":
|
if amodule.params['state'] == "absent" and decon.validated_virt_image_id:
|
||||||
amodule.image_id_delete = decon.validated_virt_image_id
|
amodule.image_id_delete = decon.validated_virt_image_id
|
||||||
decort_osimage.decort_image_delete(decon, amodule)
|
image_id, image_facts = decort_osimage.decort_virt_image_find(decon, amodule)
|
||||||
|
if image_facts['status'] != 'PURGED':
|
||||||
|
decort_osimage.decort_image_delete(decon,amodule)
|
||||||
|
|
||||||
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)
|
||||||
@@ -386,12 +519,34 @@ def main():
|
|||||||
|
|
||||||
elif amodule.params['state'] == "absent" and decon.validated_image_id:
|
elif amodule.params['state'] == "absent" and decon.validated_image_id:
|
||||||
amodule.image_id_delete = decon.validated_image_id
|
amodule.image_id_delete = decon.validated_image_id
|
||||||
|
image_id, image_facts = decort_osimage.decort_image_find(decon, amodule)
|
||||||
|
if image_facts['status'] != 'DESTROYED':
|
||||||
decort_osimage.decort_image_delete(decon,amodule)
|
decort_osimage.decort_image_delete(decon,amodule)
|
||||||
|
|
||||||
|
if decon.validated_image_id:
|
||||||
|
if (
|
||||||
|
amodule.params['storage_policy_id'] is not None
|
||||||
|
and amodule.params['storage_policy_id']
|
||||||
|
!= image_facts['storage_policy_id']
|
||||||
|
):
|
||||||
|
decon.image_change_storage_policy(
|
||||||
|
image_id=decon.validated_image_id,
|
||||||
|
storage_policy_id=amodule.params['storage_policy_id'],
|
||||||
|
)
|
||||||
|
|
||||||
if decon.result['failed'] == True:
|
if decon.result['failed'] == True:
|
||||||
# we failed to find the specified image - fail the module
|
# we failed to find the specified image - fail the module
|
||||||
decon.result['changed'] = False
|
decon.result['changed'] = False
|
||||||
amodule.fail_json(**decon.result)
|
amodule.fail_json(**decon.result)
|
||||||
|
else:
|
||||||
|
if decon.validated_image_id:
|
||||||
|
_, image_facts = decon.decort_image_find(amodule=amodule)
|
||||||
|
elif decon.validated_virt_image_id:
|
||||||
|
_, image_facts = decon.decort_virt_image_find(amodule=amodule)
|
||||||
|
decon.result['facts'] = decort_osimage.decort_osimage_package_facts(
|
||||||
|
arg_osimage_facts=image_facts,
|
||||||
|
arg_check_mode=amodule.check_mode,
|
||||||
|
)
|
||||||
|
|
||||||
amodule.exit_json(**decon.result)
|
amodule.exit_json(**decon.result)
|
||||||
|
|
||||||
|
|||||||
@@ -102,16 +102,47 @@ class decort_rg(DecortController):
|
|||||||
resources = self.rg_facts['Resources']['Reserved']
|
resources = self.rg_facts['Resources']['Reserved']
|
||||||
incorrect_quota = dict(Requested=dict(),
|
incorrect_quota = dict(Requested=dict(),
|
||||||
Reserved=dict(),)
|
Reserved=dict(),)
|
||||||
query_key_map = dict(cpu='cpu',
|
query_key_map = dict(
|
||||||
|
cpu='cpu',
|
||||||
ram='ram',
|
ram='ram',
|
||||||
disk='disksize',
|
disk='disksize',
|
||||||
ext_ips='extips',
|
ext_ips='extips',
|
||||||
net_transfer='exttraffic',)
|
net_transfer='exttraffic',
|
||||||
|
storage_policies='policies',
|
||||||
|
)
|
||||||
if self.amodule.params['quotas']:
|
if self.amodule.params['quotas']:
|
||||||
for quota_item in self.amodule.params['quotas']:
|
for quota_item in self.amodule.params['quotas']:
|
||||||
if self.amodule.params['quotas'][quota_item] < resources[query_key_map[quota_item]]:
|
if quota_item == 'storage_policies':
|
||||||
incorrect_quota['Requested'][quota_item]=self.amodule.params['quotas'][quota_item]
|
rg_storage_policies = resources[query_key_map[quota_item]]
|
||||||
incorrect_quota['Reserved'][quota_item]=resources[query_key_map[quota_item]]
|
aparam_storage_policies = self.amodule.params['quotas'][
|
||||||
|
quota_item
|
||||||
|
]
|
||||||
|
for aparam_storage_policy in aparam_storage_policies:
|
||||||
|
aparam_storage_policy_id = aparam_storage_policy['id']
|
||||||
|
rg_storage_policy = rg_storage_policies.get(
|
||||||
|
str(aparam_storage_policy_id)
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
rg_storage_policy
|
||||||
|
and aparam_storage_policy['storage_size_gb']
|
||||||
|
< rg_storage_policy['disksize']
|
||||||
|
):
|
||||||
|
incorrect_quota['Requested'][quota_item] = (
|
||||||
|
self.amodule.params['quotas'][quota_item]
|
||||||
|
)
|
||||||
|
incorrect_quota['Reserved'][quota_item] = (
|
||||||
|
resources[query_key_map[quota_item]]
|
||||||
|
)
|
||||||
|
elif (
|
||||||
|
self.amodule.params['quotas'][quota_item]
|
||||||
|
< resources[query_key_map[quota_item]]
|
||||||
|
):
|
||||||
|
incorrect_quota['Requested'][quota_item] = (
|
||||||
|
self.amodule.params['quotas'][quota_item]
|
||||||
|
)
|
||||||
|
incorrect_quota['Reserved'][quota_item] = (
|
||||||
|
resources[query_key_map[quota_item]]
|
||||||
|
)
|
||||||
|
|
||||||
if incorrect_quota['Requested']:
|
if incorrect_quota['Requested']:
|
||||||
self.result['msg'] = ("Cannot limit less than already reserved'{}'").format(incorrect_quota)
|
self.result['msg'] = ("Cannot limit less than already reserved'{}'").format(incorrect_quota)
|
||||||
@@ -243,6 +274,7 @@ class decort_rg(DecortController):
|
|||||||
ret_dict['uniqPools'] = self.rg_facts['uniqPools']
|
ret_dict['uniqPools'] = self.rg_facts['uniqPools']
|
||||||
ret_dict['description'] = self.rg_facts['desc']
|
ret_dict['description'] = self.rg_facts['desc']
|
||||||
ret_dict['sdn_access_group_id'] = self.rg_facts['sdn_access_group_id']
|
ret_dict['sdn_access_group_id'] = self.rg_facts['sdn_access_group_id']
|
||||||
|
ret_dict['storage_policy_ids'] = self.rg_facts['storage_policy_ids']
|
||||||
|
|
||||||
return ret_dict
|
return ret_dict
|
||||||
|
|
||||||
|
|||||||
351
library/decort_security_group.py
Normal file
351
library/decort_security_group.py
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
DOCUMENTATION = r'''
|
||||||
|
---
|
||||||
|
module: decort_security_group
|
||||||
|
|
||||||
|
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||||
|
'''
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils.decort_utils import DecortController
|
||||||
|
|
||||||
|
|
||||||
|
class DecortSecurityGroup(DecortController):
|
||||||
|
id: int = 0
|
||||||
|
facts: dict = dict()
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(AnsibleModule(**self.amodule_init_args))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def amodule_init_args(self) -> dict:
|
||||||
|
return self.pack_amodule_init_args(
|
||||||
|
argument_spec=dict(
|
||||||
|
account_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
description=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
name=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
rules=dict(
|
||||||
|
type='dict',
|
||||||
|
options=dict(
|
||||||
|
mode=dict(
|
||||||
|
type='str',
|
||||||
|
choices=[
|
||||||
|
e.value
|
||||||
|
for e in self.SecurityGroupRuleMode
|
||||||
|
],
|
||||||
|
default=self.SecurityGroupRuleMode.update.value,
|
||||||
|
),
|
||||||
|
objects=dict(
|
||||||
|
type='list',
|
||||||
|
elements='dict',
|
||||||
|
required=True,
|
||||||
|
options=dict(
|
||||||
|
direction=dict(
|
||||||
|
type='str',
|
||||||
|
choices=[
|
||||||
|
e.name for e in
|
||||||
|
self.SecurityGroupRuleDirection
|
||||||
|
],
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
ethertype=dict(
|
||||||
|
type='str',
|
||||||
|
choices=[
|
||||||
|
e.name for e in
|
||||||
|
self.SecurityGroupRuleEtherType
|
||||||
|
],
|
||||||
|
),
|
||||||
|
id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
port_range=dict(
|
||||||
|
type='dict',
|
||||||
|
options=dict(
|
||||||
|
min=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
max=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
protocol=dict(
|
||||||
|
type='str',
|
||||||
|
choices=[
|
||||||
|
e.name for e in
|
||||||
|
self.SecurityGroupRuleProtocol
|
||||||
|
],
|
||||||
|
),
|
||||||
|
remote_ip_prefix=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
state=dict(
|
||||||
|
type='str',
|
||||||
|
choices=[e.value for e in self.SecurityGroupState],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
supports_check_mode=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if self.aparams['id'] is not None:
|
||||||
|
self.id = self.aparams['id']
|
||||||
|
elif self.aparams['name'] is not None:
|
||||||
|
security_group = self.security_group_find(
|
||||||
|
account_id=self.aparams['account_id'],
|
||||||
|
name=self.aparams['name'],
|
||||||
|
)
|
||||||
|
if security_group:
|
||||||
|
self.id = security_group['id']
|
||||||
|
|
||||||
|
if self.id:
|
||||||
|
self.get_info()
|
||||||
|
self.check_amodule_args_for_change()
|
||||||
|
self.change()
|
||||||
|
else:
|
||||||
|
self.check_amodule_args_for_create()
|
||||||
|
self.create()
|
||||||
|
if not self.amodule.check_mode:
|
||||||
|
self.change_rules()
|
||||||
|
|
||||||
|
if self.result['changed']:
|
||||||
|
self.get_info()
|
||||||
|
self.exit()
|
||||||
|
|
||||||
|
def get_info(self):
|
||||||
|
self.facts: dict = self.security_group_get(id=self.id)
|
||||||
|
self.facts['created_timestamp'] = self.facts.pop('created_at')
|
||||||
|
self.facts['updated_timestamp'] = self.facts.pop('updated_at')
|
||||||
|
for rule in self.facts['rules']:
|
||||||
|
rule['port_range'] = {
|
||||||
|
'min': rule.pop('port_range_min'),
|
||||||
|
'max': rule.pop('port_range_max'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def check_amodule_args_for_create(self):
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_account_id = self.aparams['account_id']
|
||||||
|
if aparam_account_id is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "account_id" failed: '
|
||||||
|
'account_id must be specified when creating '
|
||||||
|
'a new security group'
|
||||||
|
)
|
||||||
|
|
||||||
|
aparam_name = self.aparams['name']
|
||||||
|
if aparam_name is None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "name" failed: '
|
||||||
|
'name must be specified when creating '
|
||||||
|
'a new security group'
|
||||||
|
)
|
||||||
|
|
||||||
|
aparam_state = self.aparams['state']
|
||||||
|
if (
|
||||||
|
aparam_state is not None
|
||||||
|
and aparam_state == self.SecurityGroupState.absent.value
|
||||||
|
):
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "state" failed: '
|
||||||
|
'state can not be "absent" when creating '
|
||||||
|
'a new security group'
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.check_aparam_rules(for_create=True) is False:
|
||||||
|
check_errors = True
|
||||||
|
|
||||||
|
if check_errors:
|
||||||
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
def check_amodule_args_for_change(self):
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
if self.check_aparam_rules() is False:
|
||||||
|
check_errors = True
|
||||||
|
|
||||||
|
if check_errors:
|
||||||
|
self.exit(fail=True)
|
||||||
|
|
||||||
|
def check_aparam_rules(self, for_create: bool = False):
|
||||||
|
check_errors = False
|
||||||
|
|
||||||
|
aparam_rules = self.aparams['rules']
|
||||||
|
if aparam_rules is None:
|
||||||
|
return True
|
||||||
|
|
||||||
|
mode = aparam_rules['mode']
|
||||||
|
rules = aparam_rules['objects']
|
||||||
|
|
||||||
|
if for_create and mode == self.SecurityGroupRuleMode.delete.value:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "rules.mode" failed: '
|
||||||
|
'mode can not be "delete" when creating '
|
||||||
|
'new security group'
|
||||||
|
)
|
||||||
|
|
||||||
|
sg_rules_ids = []
|
||||||
|
if self.facts.get('rules'):
|
||||||
|
sg_rules_ids = [rule['id'] for rule in self.facts['rules']]
|
||||||
|
for rule in rules:
|
||||||
|
rule_id = rule.get('id')
|
||||||
|
if rule_id is not None:
|
||||||
|
if for_create:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "rules.objects.id" failed: '
|
||||||
|
'can not set rule id when creating new '
|
||||||
|
'security group'
|
||||||
|
)
|
||||||
|
elif rule_id not in sg_rules_ids:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "rules.objects.id" failed: '
|
||||||
|
f'rule ID {rule_id} not found for '
|
||||||
|
f'security group ID {self.id}'
|
||||||
|
)
|
||||||
|
if mode == self.SecurityGroupRuleMode.delete.value:
|
||||||
|
for param, value in rule.items():
|
||||||
|
if param != 'id' and value is not None:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "rules.objects" '
|
||||||
|
'failed: only rule id can be specified if'
|
||||||
|
'rules.mode is "delete"'
|
||||||
|
)
|
||||||
|
break
|
||||||
|
elif mode == self.SecurityGroupRuleMode.delete.value:
|
||||||
|
check_errors = True
|
||||||
|
self.message(
|
||||||
|
msg='Check for parameter "rules.objects" '
|
||||||
|
'failed: rule id must be specified if mode is delete'
|
||||||
|
)
|
||||||
|
|
||||||
|
return not check_errors
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
security_groups_by_account_id = self.user_security_groups(
|
||||||
|
account_id=self.aparams['account_id']
|
||||||
|
)
|
||||||
|
sg_names = [sg['name'] for sg in security_groups_by_account_id]
|
||||||
|
if self.aparams['name'] not in sg_names:
|
||||||
|
self.id = self.security_group_create(
|
||||||
|
account_id=self.aparams['account_id'],
|
||||||
|
name=self.aparams['name'],
|
||||||
|
description=self.aparams['description'],
|
||||||
|
)
|
||||||
|
|
||||||
|
def change(self):
|
||||||
|
self.change_state()
|
||||||
|
self.change_params()
|
||||||
|
self.change_rules()
|
||||||
|
|
||||||
|
def change_state(self):
|
||||||
|
if self.aparams['state'] == self.SecurityGroupState.absent.value:
|
||||||
|
self.delete()
|
||||||
|
|
||||||
|
def change_params(self):
|
||||||
|
aparam_name = self.aparams['name']
|
||||||
|
aparam_description = self.aparams['description']
|
||||||
|
new_name, new_description = None, None
|
||||||
|
if (
|
||||||
|
aparam_name is not None
|
||||||
|
and aparam_name != self.facts['name']
|
||||||
|
):
|
||||||
|
new_name = aparam_name
|
||||||
|
if (
|
||||||
|
aparam_description is not None
|
||||||
|
and aparam_description != self.facts['description']
|
||||||
|
):
|
||||||
|
new_description = aparam_description
|
||||||
|
if new_name or new_description:
|
||||||
|
self.security_group_update(
|
||||||
|
security_group_id=self.id,
|
||||||
|
name=new_name,
|
||||||
|
description=new_description,
|
||||||
|
)
|
||||||
|
|
||||||
|
def change_rules(self):
|
||||||
|
aparam_rules = self.aparams['rules']
|
||||||
|
if aparam_rules is not None:
|
||||||
|
rules = aparam_rules['objects']
|
||||||
|
match aparam_rules['mode']:
|
||||||
|
case self.SecurityGroupRuleMode.delete.value:
|
||||||
|
for rule in rules:
|
||||||
|
self.security_group_detele_rule(
|
||||||
|
security_group_id=self.id,
|
||||||
|
rule_id=rule['id'],
|
||||||
|
)
|
||||||
|
case self.SecurityGroupRuleMode.match.value:
|
||||||
|
for rule in rules:
|
||||||
|
if rule.get('id') is None:
|
||||||
|
self.create_rule(rule=rule)
|
||||||
|
|
||||||
|
sg_rules_ids = set(
|
||||||
|
[rule['id'] for rule in self.facts['rules']]
|
||||||
|
)
|
||||||
|
aparam_rules_ids = set(
|
||||||
|
[rule['id'] for rule in rules if rule.get('id')]
|
||||||
|
)
|
||||||
|
rules_ids_to_delete = sg_rules_ids - aparam_rules_ids
|
||||||
|
for rule_id in rules_ids_to_delete:
|
||||||
|
self.security_group_detele_rule(
|
||||||
|
security_group_id=self.id,
|
||||||
|
rule_id=rule_id,
|
||||||
|
)
|
||||||
|
case self.SecurityGroupRuleMode.update.value:
|
||||||
|
for rule in rules:
|
||||||
|
if rule.get('id') is None:
|
||||||
|
self.create_rule(rule=rule)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
self.security_group_detele(security_group_id=self.id)
|
||||||
|
self.facts = {}
|
||||||
|
self.exit()
|
||||||
|
|
||||||
|
def create_rule(self, rule: dict):
|
||||||
|
port_range_min, port_range_max = None, None
|
||||||
|
if rule.get('port_range'):
|
||||||
|
port_range_min = rule['port_range'].get('min')
|
||||||
|
port_range_max = rule['port_range'].get('max')
|
||||||
|
self.security_group_create_rule(
|
||||||
|
security_group_id=self.id,
|
||||||
|
direction=self.SecurityGroupRuleDirection[rule['direction']],
|
||||||
|
ethertype=(
|
||||||
|
self.SecurityGroupRuleEtherType[rule['ethertype']]
|
||||||
|
if rule.get('ethertype') else None
|
||||||
|
),
|
||||||
|
protocol=(
|
||||||
|
self.SecurityGroupRuleProtocol[rule['protocol']]
|
||||||
|
if rule.get('protocol') else None
|
||||||
|
),
|
||||||
|
port_range_min=port_range_min,
|
||||||
|
port_range_max=port_range_max,
|
||||||
|
remote_ip_prefix=rule.get('remote_ip_prefix'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
DecortSecurityGroup().run()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
50
library/decort_storage_policy.py
Normal file
50
library/decort_storage_policy.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
DOCUMENTATION = r'''
|
||||||
|
---
|
||||||
|
module: decort_storage_policy
|
||||||
|
|
||||||
|
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||||
|
'''
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils.decort_utils import DecortController
|
||||||
|
|
||||||
|
|
||||||
|
class DecortStoragePolicy(DecortController):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(AnsibleModule(**self.amodule_init_args))
|
||||||
|
self.id: int = self.aparams['id']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def amodule_init_args(self) -> dict:
|
||||||
|
return self.pack_amodule_init_args(
|
||||||
|
argument_spec=dict(
|
||||||
|
id=dict(
|
||||||
|
type='int',
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
supports_check_mode=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.get_info()
|
||||||
|
self.exit()
|
||||||
|
|
||||||
|
def get_info(self):
|
||||||
|
self.facts = self.storage_policy_get(id=self.id)
|
||||||
|
self.facts['sep_pools'] = self.facts.pop('access_seps_pools')
|
||||||
|
self.facts['iops_limit'] = self.facts.pop('limit_iops')
|
||||||
|
self.facts['usage']['account_ids'] = self.facts['usage'].pop(
|
||||||
|
'accounts'
|
||||||
|
)
|
||||||
|
self.facts['usage']['rg_ids'] = self.facts['usage'].pop('resgroups')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
DecortStoragePolicy().run()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -48,6 +48,9 @@ class DecortUserInfo(DecortController):
|
|||||||
e.value for e in self.AccountStatus
|
e.value for e in self.AccountStatus
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
zone_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
pagination=dict(
|
pagination=dict(
|
||||||
@@ -303,6 +306,143 @@ class DecortUserInfo(DecortController):
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
storage_policies=dict(
|
||||||
|
type='dict',
|
||||||
|
options=dict(
|
||||||
|
filter=dict(
|
||||||
|
type='dict',
|
||||||
|
options=dict(
|
||||||
|
account_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
description=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
iops_limit=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
name=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
pool_name=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
rg_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
sep_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
status=dict(
|
||||||
|
type='str',
|
||||||
|
choices=[
|
||||||
|
e.value for e
|
||||||
|
in self.StoragePolicyStatus
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pagination=dict(
|
||||||
|
type='dict',
|
||||||
|
apply_defaults=True,
|
||||||
|
options=dict(
|
||||||
|
number=dict(
|
||||||
|
type='int',
|
||||||
|
default=1,
|
||||||
|
),
|
||||||
|
size=dict(
|
||||||
|
type='int',
|
||||||
|
default=50,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
sorting=dict(
|
||||||
|
type='dict',
|
||||||
|
options=dict(
|
||||||
|
asc=dict(
|
||||||
|
type='bool',
|
||||||
|
default=True,
|
||||||
|
),
|
||||||
|
field=dict(
|
||||||
|
type='str',
|
||||||
|
choices=[
|
||||||
|
e.value for e
|
||||||
|
in self.StoragePoliciesSortableField
|
||||||
|
],
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
security_groups=dict(
|
||||||
|
type='dict',
|
||||||
|
options=dict(
|
||||||
|
filter=dict(
|
||||||
|
type='dict',
|
||||||
|
options=dict(
|
||||||
|
account_id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
created_timestamp_max=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
created_timestamp_min=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
description=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
id=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
name=dict(
|
||||||
|
type='str',
|
||||||
|
),
|
||||||
|
updated_timestamp_max=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
updated_timestamp_min=dict(
|
||||||
|
type='int',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pagination=dict(
|
||||||
|
type='dict',
|
||||||
|
apply_defaults=True,
|
||||||
|
options=dict(
|
||||||
|
number=dict(
|
||||||
|
type='int',
|
||||||
|
default=1,
|
||||||
|
),
|
||||||
|
size=dict(
|
||||||
|
type='int',
|
||||||
|
default=50,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
sorting=dict(
|
||||||
|
type='dict',
|
||||||
|
options=dict(
|
||||||
|
asc=dict(
|
||||||
|
type='bool',
|
||||||
|
default=True,
|
||||||
|
),
|
||||||
|
field=dict(
|
||||||
|
type='str',
|
||||||
|
choices=[
|
||||||
|
e.name for e
|
||||||
|
in self.SecurityGroupSortableField
|
||||||
|
],
|
||||||
|
required=True,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
)
|
)
|
||||||
@@ -390,6 +530,8 @@ class DecortUserInfo(DecortController):
|
|||||||
self.AccountStatus(input_args_filter_status)
|
self.AccountStatus(input_args_filter_status)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
mapped_args['zone_id'] = input_args_filter['zone_id']
|
||||||
|
|
||||||
input_args_pagination = input_args['pagination']
|
input_args_pagination = input_args['pagination']
|
||||||
if input_args_pagination:
|
if input_args_pagination:
|
||||||
mapped_args['page_number'] = input_args_pagination['number']
|
mapped_args['page_number'] = input_args_pagination['number']
|
||||||
@@ -552,6 +694,82 @@ class DecortUserInfo(DecortController):
|
|||||||
|
|
||||||
return mapped_args
|
return mapped_args
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mapped_storage_policies_args(self):
|
||||||
|
"""
|
||||||
|
Map the module argument `storage_policies` to
|
||||||
|
arguments dictionary for the method
|
||||||
|
`DecortController.user_storage_policies`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
input_args = self.aparams['storage_policies']
|
||||||
|
if not input_args:
|
||||||
|
return input_args
|
||||||
|
|
||||||
|
mapped_args = {}
|
||||||
|
|
||||||
|
input_args_filter = input_args['filter']
|
||||||
|
if input_args_filter:
|
||||||
|
mapped_args.update(input_args_filter)
|
||||||
|
|
||||||
|
input_args_filter_status = input_args_filter['status']
|
||||||
|
if input_args_filter_status:
|
||||||
|
mapped_args['status'] = (
|
||||||
|
self.StoragePolicyStatus(input_args_filter_status)
|
||||||
|
)
|
||||||
|
|
||||||
|
input_args_pagination = input_args['pagination']
|
||||||
|
if input_args_pagination:
|
||||||
|
mapped_args['page_number'] = input_args_pagination['number']
|
||||||
|
mapped_args['page_size'] = input_args_pagination['size']
|
||||||
|
|
||||||
|
input_args_sorting = input_args['sorting']
|
||||||
|
if input_args_sorting:
|
||||||
|
mapped_args['sort_by_asc'] = input_args_sorting['asc']
|
||||||
|
|
||||||
|
input_args_sorting_field = input_args_sorting['field']
|
||||||
|
if input_args_sorting_field:
|
||||||
|
mapped_args['sort_by_field'] = (
|
||||||
|
self.StoragePoliciesSortableField(input_args_sorting_field)
|
||||||
|
)
|
||||||
|
|
||||||
|
return mapped_args
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mapped_security_groups_args(self):
|
||||||
|
"""
|
||||||
|
Map the module argument `security_groups` to
|
||||||
|
arguments dictionary for the method
|
||||||
|
`DecortController.user_security_groups`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
input_args = self.aparams['security_groups']
|
||||||
|
if not input_args:
|
||||||
|
return input_args
|
||||||
|
|
||||||
|
mapped_args = {}
|
||||||
|
|
||||||
|
input_args_filter = input_args['filter']
|
||||||
|
if input_args_filter:
|
||||||
|
mapped_args.update(input_args_filter)
|
||||||
|
|
||||||
|
input_args_pagination = input_args['pagination']
|
||||||
|
if input_args_pagination:
|
||||||
|
mapped_args['page_number'] = input_args_pagination['number']
|
||||||
|
mapped_args['page_size'] = input_args_pagination['size']
|
||||||
|
|
||||||
|
input_args_sorting = input_args['sorting']
|
||||||
|
if input_args_sorting:
|
||||||
|
mapped_args['sort_by_asc'] = input_args_sorting['asc']
|
||||||
|
|
||||||
|
input_args_sorting_field = input_args_sorting['field']
|
||||||
|
if input_args_sorting_field:
|
||||||
|
mapped_args['sort_by_field'] = (
|
||||||
|
self.SecurityGroupSortableField[input_args_sorting_field]
|
||||||
|
)
|
||||||
|
|
||||||
|
return mapped_args
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.get_info()
|
self.get_info()
|
||||||
self.exit()
|
self.exit()
|
||||||
@@ -606,6 +824,52 @@ class DecortUserInfo(DecortController):
|
|||||||
trunk_facts['ovs_bridge'] = trunk_facts.pop('ovsBridge')
|
trunk_facts['ovs_bridge'] = trunk_facts.pop('ovsBridge')
|
||||||
trunk_facts['vlan_ids'] = trunk_facts.pop('trunkTags')
|
trunk_facts['vlan_ids'] = trunk_facts.pop('trunkTags')
|
||||||
|
|
||||||
|
if self.aparams['storage_policies']:
|
||||||
|
self.facts['storage_policies'] = self.user_storage_policies(
|
||||||
|
**self.mapped_storage_policies_args
|
||||||
|
)
|
||||||
|
for storage_policy_facts in self.facts['storage_policies']:
|
||||||
|
storage_policy_facts['sep_pools'] = storage_policy_facts.pop(
|
||||||
|
'access_seps_pools'
|
||||||
|
)
|
||||||
|
storage_policy_facts['iops_limit'] = storage_policy_facts.pop(
|
||||||
|
'limit_iops'
|
||||||
|
)
|
||||||
|
storage_policy_facts['usage']['account_ids'] = (
|
||||||
|
storage_policy_facts['usage'].pop('accounts')
|
||||||
|
)
|
||||||
|
storage_policy_facts['usage']['rg_ids'] = (
|
||||||
|
storage_policy_facts['usage'].pop('resgroups')
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.aparams['security_groups']:
|
||||||
|
self.facts['security_groups'] = self.user_security_groups(
|
||||||
|
**self.mapped_security_groups_args
|
||||||
|
)
|
||||||
|
for security_groups_facts in self.facts['security_groups']:
|
||||||
|
for rule in security_groups_facts.get('rules', []):
|
||||||
|
rule['port_range'] = {
|
||||||
|
'min': rule.pop('port_range_min'),
|
||||||
|
'max': rule.pop('port_range_max'),
|
||||||
|
}
|
||||||
|
|
||||||
|
security_groups_facts['created_timestamp'] = (
|
||||||
|
security_groups_facts.pop('created_at')
|
||||||
|
)
|
||||||
|
security_groups_facts['created_timestamp_readable'] = (
|
||||||
|
self.sec_to_dt_str(security_groups_facts[
|
||||||
|
'created_timestamp'
|
||||||
|
])
|
||||||
|
)
|
||||||
|
security_groups_facts['updated_timestamp'] = (
|
||||||
|
security_groups_facts.pop('updated_at')
|
||||||
|
)
|
||||||
|
security_groups_facts['updated_timestamp_readable'] = (
|
||||||
|
self.sec_to_dt_str(security_groups_facts[
|
||||||
|
'updated_timestamp'
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
DecortUserInfo().run()
|
DecortUserInfo().run()
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ class decort_vins(DecortController):
|
|||||||
|
|
||||||
return
|
return
|
||||||
def delete(self):
|
def delete(self):
|
||||||
self.vins_delete(self.vins_id, permanently=True)
|
self.vins_delete(self.vins_id, self.amodule.params['permanently'])
|
||||||
self.vins_facts['status'] = 'DESTROYED'
|
self.vins_facts['status'] = 'DESTROYED'
|
||||||
return
|
return
|
||||||
def nop(self):
|
def nop(self):
|
||||||
@@ -320,6 +320,10 @@ class decort_vins(DecortController):
|
|||||||
type='str',
|
type='str',
|
||||||
default='',
|
default='',
|
||||||
),
|
),
|
||||||
|
permanently=dict(
|
||||||
|
type='bool',
|
||||||
|
default=False,
|
||||||
|
),
|
||||||
vins_id=dict(
|
vins_id=dict(
|
||||||
type='int',
|
type='int',
|
||||||
default=0,
|
default=0,
|
||||||
@@ -416,6 +420,7 @@ def main():
|
|||||||
vins_should_exist = True
|
vins_should_exist = True
|
||||||
elif amodule.params['state'] == 'absent':
|
elif amodule.params['state'] == 'absent':
|
||||||
# destroy permanently
|
# destroy permanently
|
||||||
|
if decon.amodule.params['permanently']:
|
||||||
decon.delete()
|
decon.delete()
|
||||||
vins_should_exist = False
|
vins_should_exist = False
|
||||||
elif amodule.params['state'] == 'disabled':
|
elif amodule.params['state'] == 'disabled':
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
DOCUMENTATION = r'''
|
DOCUMENTATION = r'''
|
||||||
---
|
---
|
||||||
module: decort_snapshot
|
module: decort_vm_snapshot
|
||||||
|
|
||||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||||
'''
|
'''
|
||||||
@@ -12,7 +12,7 @@ from ansible.module_utils.basic import AnsibleModule
|
|||||||
from ansible.module_utils.decort_utils import DecortController
|
from ansible.module_utils.decort_utils import DecortController
|
||||||
|
|
||||||
|
|
||||||
class DecortSnapshot(DecortController):
|
class DecortVMSnapshot(DecortController):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(AnsibleModule(**self.amodule_init_args))
|
super().__init__(AnsibleModule(**self.amodule_init_args))
|
||||||
self.check_amodule_args()
|
self.check_amodule_args()
|
||||||
@@ -181,7 +181,7 @@ class DecortSnapshot(DecortController):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
DecortSnapshot().run()
|
DecortVMSnapshot().run()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user