Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e54a9591e4 | |||
| 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
|
||||
212
CHANGELOG.md
212
CHANGELOG.md
@@ -1,122 +1,170 @@
|
||||
# Список изменений в версии 9.0.0
|
||||
# Список изменений в версии 11.0.0
|
||||
|
||||
## Добавлено
|
||||
### Глобально
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-798 | Обновлены системные требования: версия интерпретатора Python обновлена до 3.12, версия Python-библиотеки ansible обновлена до 11.6.0 |
|
||||
| BANS-909 | В системные требования добавлена библиотека Python `dynamix_sdk`. |
|
||||
| BANS-918 | Добавлен общий для всех модулей параметр `ignore_api_compatibility`. |
|
||||
| BANS-913 | Добавлен общий для всех модулей параметр `ignore_sdk_version_check`. |
|
||||
| BANS-954 | Добавлен модуль `decort_vm` в связи с переименованием из `decort_kvmvm`. |
|
||||
| BANS-953 | Добавлен модуль `decort_image` в связи с переименованием из `decort_osimage`. |
|
||||
| BANS-997 | Добавлен модуль `decort_security_group_list`, позволяющий получить список доступных групп безопасности. |
|
||||
| BANS-884 | Добавлен модуль `decort_disk_list`, позволяющий получить список доступных дисков. |
|
||||
| BANS-936 | Добавлен модуль `decort_rg_list`, позволяющий получить список доступных ресурсных групп. |
|
||||
| BANS-949 | Добавлен модуль `decort_vins_list`, позволяющий получить список доступных внутренних сетей. |
|
||||
| BANS-940 | Добавлен модуль `decort_vm_list`, позволяющий получить список доступных виртуальных машин. |
|
||||
| BANS-959 | Добавлен модуль `decort_flip_group_list`, позволяющий получить список доступных групп с плавающим IP-адресом. |
|
||||
| BANS-952 | Добавлен модуль `decort_image_list`, позволяющий получить список доступных образов. |
|
||||
| BANS-983 | Добавлен модуль `decort_account_list`, позволяющий получить список доступных аккаунтов. |
|
||||
| BANS-985 | Добавлен модуль `decort_audit_list`, позволяющий получить список аудитов. |
|
||||
| BANS-988 | Добавлен модуль `decort_trunk_list`, позволяющий получить список доступных транковых портов. |
|
||||
| BANS-987 | Добавлен модуль `decort_zone_list`, позволяющий получить список доступных зон. |
|
||||
| BANS-989 | Добавлен модуль `decort_storage_policy_list`, позволяющий получить список политик хранения. |
|
||||
| BANS-945 | Добавлен модуль `decort_user` в связи с переименованием из `decort_user_info`. |
|
||||
|
||||
### Модуль decort_kvmvm
|
||||
### Модуль decort_vm
|
||||
| Идентификатор<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` для внешней сети. |
|
||||
| BANS-926 | Для параметра `chipset` добавлено значение по умолчанию `Q35` при создании ВМ. |
|
||||
| BANS-933 | Добавлено возвращаемое значение `pinned_to_node` в связи с переименованием из `pinned_to_stack`. |
|
||||
| BANS-934 | Добавлено возвращаемое значение `read_only`. |
|
||||
| BANS-994 | Добавлена возможность задать параметр `mtu` при создании сетевого интерфейса для TRUNK-сети и изменить `mtu` у существующего интерфейса, подключённого к TRUNK-сети. |
|
||||
| BANS-991 | Добавлена возможность указать параметр `ip_addr` при присоединении и изменении `DPDK` сети. |
|
||||
| BANS-1017 | Добавлено возвращаемое значение `disks.cache`. |
|
||||
| BANS-1034 | Добавлена возможность указать параметр `ip_addr` при присоединении и изменении `VFNIC` сети. |
|
||||
| BANS-992 | Добавлен параметр `networks.net_prefix`. |
|
||||
|
||||
### Модуль decort_lb
|
||||
### Модуль decort_group
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-793 | Добавлен параметр `zone_id` и возвращаемое значение `zone_id`. |
|
||||
| BANS-819 | Добавлено возвращаемое значение `account_id`. |
|
||||
| BANS-800 | Добавлены значения `stopped` и `started` для параметра `state` и возвращаемое значение `tech_status`. |
|
||||
| BANS-927 | Для параметра `chipset` добавлено значение по умолчанию `Q35` при создании группы. |
|
||||
|
||||
### Модуль 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`. |
|
||||
| BANS-928 | Для параметра `chipset` добавлено значение по умолчанию `Q35` при создании кластера. |
|
||||
|
||||
### Модуль 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` для получения информации о зонах. |
|
||||
| BANS-966 | Добавлен параметр `get_resource_consumption` и возвращаемое значение `resource_consumption`. |
|
||||
|
||||
### Модуль decort_trunk
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-825 | Добавлен модуль `decort_trunk` для получения информации о транковых портах. |
|
||||
| BANS-993 | Добавлено возвращаемое значение `mtu`. |
|
||||
| BANS-976 | Добавлены возвращаемые значения `created_datetime`, `deleted_datetime`, `updated_datetime`. |
|
||||
|
||||
### Модуль decort_snapshot
|
||||
### Модуль decort_zone
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-808 | Добавлено значение `merge_aborted` для параметра `state`. |
|
||||
| BANS-970 | Добавлены возвращаемые значения `created_datetime`, `updated_datetime` и возвращаемые значения `account_ids`, `bservice_ids`, `vm_ids`, `extnet_ids`, `k8s_ids`, `lb_ids`, `vins_ids` в связи с переименованием из `accountIds`, `bserviceIds`, `computeIds`, `extnetIds`, `k8sIds`, `lbIds`, `vinsIds`. |
|
||||
| BANS-1024 | Добавлено возвращаемое значение `node_auto_start`. |
|
||||
|
||||
### Модуль decort_osimage
|
||||
### Модуль decort_vm_snapshot
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-849 | Добавлен параметр `account_id`, используемый при создании шаблонных и виртуальных образов. |
|
||||
| BANS-978 | Добавлено возвращаемое значение `datetime`. |
|
||||
|
||||
### Модуль decort_storage_policy
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-977 | Добавлены возвращаемые значения `sep_name`, `sep_tech_status`. |
|
||||
|
||||
## Удалено
|
||||
### Модуль decort_disk
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-815 | Удалено значение по умолчанию для параметра `description`. |
|
||||
| BANS-1019 | Добавлено возвращаемое значение `cache_mode`. |
|
||||
| BANS-1050 | Добавлено возвращаемое значение `blkdiscard`. |
|
||||
|
||||
### Модуль 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
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-803 | Модуль завершал работу ошибкой Python при создании балансировщика с указанием параметра `backends` или `frontends`. |
|
||||
| BANS-820 | Выполнение модуля с указанием параметра `vins_id` и без указания параметра `ext_net_id` вызывало создание балансировщика с некорректной сетевой конфигурацией, дальнейшее добавление конфигурации backend к которому завершалось ошибкой платформы. |
|
||||
| BANS-799 | Скорректирована логика параметра целевого состояния `present`. Теперь состояние `present` соответствует тому, что балансировщик нагрузки существует, и не приводит к изменению состояния существующего балансировщика нагрузки. Также для параметра `state` значение по умолчанию `present` теперь только при создании балансировщика нагрузки. |
|
||||
| BANS-954 | Удалён модуль `decort_kvmvm` в связи с переименованием в `decort_vm`. |
|
||||
| BANS-969 | Модуль `decort_account_info` расформирован, его функционал перенесён в модули: `decort_disk_list`, `decort_rg_list`, `decort_vins_list`, `decort_vm_list`, `decort_flip_group_list`, `decort_image_list`, `decort_account`. |
|
||||
| BANS-953 | Удалён модуль `decort_osimage` в связи с переименованием в `decort_image`. |
|
||||
| BANS-945 | Удалён модуль `decort_user_info` в связи с переименованием в `decort_user`. |
|
||||
|
||||
### Модуль decort_account
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-817 | Модуль некорректно отслеживал завершение удаления и восстановления аккаунта. |
|
||||
| BANS-924 | Удалён параметр `quotas.ext_traffic`. |
|
||||
| BANS-998 |Для параметра `state` удалено значение по умолчанию. |
|
||||
|
||||
### Модуль decort_rg
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-925 | Удалён параметр `quotas.net_transfer`. |
|
||||
|
||||
### Модуль decort_vm
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-926 | Для параметра `chipset` удалено значение по умолчанию `i440fx` при создании ВМ. |
|
||||
| BANS-933 | Удалено возвращаемое значение `pinned_to_stack` в связи с переименованием в `pinned_to_node`. |
|
||||
| BANS-961 | Параметр `storage_policy_id` удалён из обязательных при пересоздании загрузочного диска. |
|
||||
|
||||
### Модуль decort_group
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-927 | Для параметра `chipset` удалено значение по умолчанию `i440fx` при создании группы. |
|
||||
| BANS-1027 | Удалён параметр `driver`. |
|
||||
|
||||
### Модуль decort_k8s
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-928 | Для параметра `chipset` удалено значение по умолчанию `i440fx` при создании кластера. |
|
||||
|
||||
### Модуль decort_user
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-983 | Удалён параметр `accounts` и возвращаемое значение `accounts` в связи с переносом этой функциональности в модуль `decort_account_list`. |
|
||||
| BANS-985 | Удалён параметр `audits` и возвращаемое значение `audits` в связи с переносом этой функциональности в модуль `decort_audit_list`. |
|
||||
| BANS-988 | Удалён параметр `trunks` и возвращаемое значение `trunks` в связи с переносом этой функциональности в модуль `decort_trunk_list`. |
|
||||
| BANS-987 | Удалён параметр `zones` и возвращаемое значение `zones` в связи с переносом этой функциональности в модуль `decort_zone_list`. |
|
||||
| BANS-989 | Удалён параметр `storage_policies` и возвращаемое значение `storage_policies` в связи с переносом этой функциональности в модуль `decort_storage_policy_list`. |
|
||||
| BANS-997 | Удалён параметр `security_groups` и возвращаемое значение `security_groups` в связи с переносом этой функциональности в модуль `decort_security_group_list`. |
|
||||
|
||||
### Модуль decort_zone
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-970 | Удалены возвращаемые значения `accountIds`, `bserviceIds`, `computeIds`, `extnetIds`, `k8sIds`, `lbIds`, `vinsIds` в связи с переименованием в `account_ids`, `bservice_ids`, `vm_ids`, `extnet_ids`, `k8s_ids`, `lb_ids`, `vins_ids`. |
|
||||
|
||||
### Модуль decort_disk
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-1004 | Удалён параметр `reason` |
|
||||
|
||||
### Модуль decort_security_group
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-1000 | Удалено возвращаемое значение `rules.remote_ip_prefix` в связи с переименованием в `rules.remote_net_cidr`. |
|
||||
| BANS-1013 | Удален параметр `rules.objects.remote_ip_prefix` в связи с переименованием в `rules.objects.remote_net_cidr`. |
|
||||
|
||||
### Модуль decort_vm_snapshot
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-1012 | Удалено возвращаемое значение `disks` в связи с переименованием в `disk_ids`. |
|
||||
|
||||
## Исправлено
|
||||
### Модуль decort_vm
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-996 | Параметры `mac`, `security_groups`, `enable_secgroups`, `enabled` сетевого интерфейса DPDK-сети могли меняться при изменении `mtu`. |
|
||||
| BANS-1052 | Параметры `numa_affinity`, `cpu_pin`, `hp_backed` не применялись при создании ВМ без образа. |
|
||||
|
||||
### Модуль decort_bservice
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-389 | После создания базовой службы, модуль не возвращал информацию о созданном объекте. |
|
||||
|
||||
### Модуль decort_vm_snapshot
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-1022 | После создания снимка не возвращалась информация о снимке. |
|
||||
|
||||
### Модуль decort_k8s
|
||||
| Идентификатор<br>задачи | Описание |
|
||||
| --- | --- |
|
||||
| BANS-1033 | Модуль без необходимости выполнял запрос к API `/cloudapi/k8s/update`, передавая в него параметры, не вызывающие изменения. |
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
| Версия платформы | Версия модулей Ansible |
|
||||
|:----------------:|:--------------------------:|
|
||||
| 4.5.0 | 11.0.x |
|
||||
| 4.4.0 | 10.0.x |
|
||||
| 4.4.0 build 963 | 9.0.x |
|
||||
| 4.3.0 | 8.0.x |
|
||||
| 4.2.0 | 7.0.x, 7.1.x, 7.2.x |
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
#
|
||||
# DECORT osimage module example
|
||||
# DECORT image module example
|
||||
#
|
||||
- hosts: localhost
|
||||
tasks:
|
||||
- name: create
|
||||
decort_osimage:
|
||||
decort_image:
|
||||
authenticator: oauth2
|
||||
verify_ssl: False
|
||||
controller_url: "https://ds1.digitalenergy.online"
|
||||
@@ -1,14 +1,14 @@
|
||||
---
|
||||
#
|
||||
# DECORT osimage module example
|
||||
# DECORT image module example
|
||||
#
|
||||
- hosts: localhost
|
||||
tasks:
|
||||
- name: create_virtual_osimage
|
||||
decort_osimage:
|
||||
- name: create_virtual_image
|
||||
decort_image:
|
||||
authenticator: oauth2
|
||||
controller_url: "https://ds1.digitalenergy.online"
|
||||
image_name: "alpine_linux_3.14.0"
|
||||
virt_name: "alpine_last"
|
||||
delegate_to: localhost
|
||||
register: osimage
|
||||
register: image
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
#
|
||||
# DECORT osimage module example
|
||||
# DECORT image module example
|
||||
#
|
||||
- hosts: localhost
|
||||
tasks:
|
||||
- name: get_osimage
|
||||
decort_osimage:
|
||||
- name: get_image
|
||||
decort_image:
|
||||
authenticator: oauth2
|
||||
controller_url: "https://ds1.digitalenergy.online"
|
||||
image_name: "alpine_linux_3.14.0"
|
||||
@@ -1,14 +1,14 @@
|
||||
---
|
||||
#
|
||||
# DECORT osimage module example
|
||||
# DECORT image module example
|
||||
#
|
||||
- hosts: localhost
|
||||
tasks:
|
||||
- name: rename_osimage
|
||||
decort_osimage:
|
||||
- name: rename_image
|
||||
decort_image:
|
||||
authenticator: oauth2
|
||||
controller_url: "https://ds1.digitalenergy.online"
|
||||
image_name: "alpine_linux_3.14.0v2.0"
|
||||
image_id: 54321
|
||||
delegate_to: localhost
|
||||
register: osimage
|
||||
register: image
|
||||
@@ -62,6 +62,10 @@ class DecortAccount(DecortController):
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
get_resource_consumption=dict(
|
||||
type='bool',
|
||||
default=False,
|
||||
),
|
||||
quotas=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
@@ -71,9 +75,6 @@ class DecortAccount(DecortController):
|
||||
disks_size=dict(
|
||||
type='int',
|
||||
),
|
||||
ext_traffic=dict(
|
||||
type='int',
|
||||
),
|
||||
gpu=dict(
|
||||
type='int',
|
||||
),
|
||||
@@ -94,7 +95,6 @@ class DecortAccount(DecortController):
|
||||
'disabled',
|
||||
'present',
|
||||
],
|
||||
default='present',
|
||||
),
|
||||
sep_pools=dict(
|
||||
type='list',
|
||||
@@ -131,7 +131,7 @@ class DecortAccount(DecortController):
|
||||
"""
|
||||
|
||||
arg_state = self.aparams['state']
|
||||
if 'absent' in arg_state:
|
||||
if arg_state is not None and 'absent' in arg_state:
|
||||
# Parameters or combinations of parameters that can
|
||||
# cause changing the object.
|
||||
changing_params = [
|
||||
@@ -175,6 +175,7 @@ class DecortAccount(DecortController):
|
||||
if check_error:
|
||||
self.exit(fail=True)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.check_amodule_args_for_change()
|
||||
@@ -187,6 +188,7 @@ class DecortAccount(DecortController):
|
||||
self.acc_id, self._acc_info = self.account_find(
|
||||
account_name=self.aparams['name'],
|
||||
account_id=self.aparams['id'],
|
||||
resource_consumption=self.aparams['get_resource_consumption'],
|
||||
)
|
||||
# If this is a repeated getting info
|
||||
else:
|
||||
@@ -195,6 +197,9 @@ class DecortAccount(DecortController):
|
||||
if not self.amodule.check_mode:
|
||||
self.acc_id, self._acc_info = self.account_find(
|
||||
account_id=self.acc_id,
|
||||
resource_consumption=(
|
||||
self.aparams['get_resource_consumption']
|
||||
),
|
||||
)
|
||||
self.facts = self.acc_info
|
||||
|
||||
@@ -361,7 +366,6 @@ class DecortAccount(DecortController):
|
||||
quotas_naming = [
|
||||
['cpu', 'CU_C', 'cpu_quota'],
|
||||
['disks_size', 'CU_DM', 'disks_size_quota'],
|
||||
['ext_traffic', 'CU_NP', 'ext_traffic_quota'],
|
||||
['gpu', 'gpu_units', 'gpu_quota'],
|
||||
['public_ip', 'CU_I', 'public_ip_quota'],
|
||||
['ram', 'CU_M', 'ram_quota'],
|
||||
|
||||
@@ -8,565 +8,46 @@ description: See L(Module Documentation,https://repository.basistech.ru/BASIS/de
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
|
||||
class DecortAccountInfo(DecortController):
|
||||
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(
|
||||
audits=dict(
|
||||
type='bool',
|
||||
default=False
|
||||
),
|
||||
computes=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
ext_net_id=dict(
|
||||
type='int',
|
||||
),
|
||||
ext_net_name=dict(
|
||||
type='str'
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
ip=dict(
|
||||
type='str'
|
||||
),
|
||||
name=dict(
|
||||
type='str'
|
||||
),
|
||||
rg_id=dict(
|
||||
type='int',
|
||||
),
|
||||
rg_name=dict(
|
||||
type='str'
|
||||
),
|
||||
tech_status=dict(
|
||||
type='str',
|
||||
choices=self.COMPUTE_TECH_STATUSES,
|
||||
),
|
||||
),
|
||||
),
|
||||
pagination=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
number=dict(
|
||||
type='int',
|
||||
default=1,
|
||||
),
|
||||
size=dict(
|
||||
type='int',
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
sorting=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
asc=dict(
|
||||
type='bool',
|
||||
default=True,
|
||||
),
|
||||
field=dict(
|
||||
type='str',
|
||||
choices=self.FIELDS_FOR_SORTING_ACCOUNT_COMPUTE_LIST, # noqa: E501
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
disks=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
size=dict(
|
||||
type='int',
|
||||
),
|
||||
type=dict(
|
||||
type='str',
|
||||
choices=self.DISK_TYPES,
|
||||
),
|
||||
),
|
||||
),
|
||||
pagination=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
number=dict(
|
||||
type='int',
|
||||
default=1,
|
||||
),
|
||||
size=dict(
|
||||
type='int',
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
sorting=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
asc=dict(
|
||||
type='bool',
|
||||
default=True,
|
||||
),
|
||||
field=dict(
|
||||
type='str',
|
||||
choices=self.FIELDS_FOR_SORTING_ACCOUNT_DISK_LIST, # noqa: E501
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
flip_groups=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
ext_net_id=dict(
|
||||
type='int',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
ip=dict(
|
||||
type='str',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
vins_id=dict(
|
||||
type='int',
|
||||
),
|
||||
vins_name=dict(
|
||||
type='str',
|
||||
),
|
||||
),
|
||||
),
|
||||
pagination=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
number=dict(
|
||||
type='int',
|
||||
default=1,
|
||||
),
|
||||
size=dict(
|
||||
type='int',
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
images=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
type=dict(
|
||||
type='str',
|
||||
choices=self.IMAGE_TYPES,
|
||||
),
|
||||
),
|
||||
),
|
||||
pagination=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
number=dict(
|
||||
type='int',
|
||||
default=1,
|
||||
),
|
||||
size=dict(
|
||||
type='int',
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
sorting=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
asc=dict(
|
||||
type='bool',
|
||||
default=True,
|
||||
),
|
||||
field=dict(
|
||||
type='str',
|
||||
choices=self.FIELDS_FOR_SORTING_ACCOUNT_IMAGE_LIST, # noqa: E501
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
resource_groups=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str'
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=self.RESOURCE_GROUP_STATUSES,
|
||||
),
|
||||
vins_id=dict(
|
||||
type='int'
|
||||
),
|
||||
vm_id=dict(
|
||||
type='int'
|
||||
),
|
||||
),
|
||||
),
|
||||
pagination=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
number=dict(
|
||||
type='int',
|
||||
default=1,
|
||||
),
|
||||
size=dict(
|
||||
type='int',
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
sorting=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
asc=dict(
|
||||
type='bool',
|
||||
default=True,
|
||||
),
|
||||
field=dict(
|
||||
type='str',
|
||||
choices=self.FIELDS_FOR_SORTING_ACCOUNT_RG_LIST, # noqa: E501
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
resource_consumption=dict(
|
||||
type='bool',
|
||||
default=False
|
||||
),
|
||||
vinses=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
ext_ip=dict(
|
||||
type='str',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str'
|
||||
),
|
||||
rg_id=dict(
|
||||
type='int',
|
||||
),
|
||||
),
|
||||
),
|
||||
pagination=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
number=dict(
|
||||
type='int',
|
||||
default=1,
|
||||
),
|
||||
size=dict(
|
||||
type='int',
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
sorting=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
asc=dict(
|
||||
type='bool',
|
||||
default=True,
|
||||
),
|
||||
field=dict(
|
||||
type='str',
|
||||
choices=self.FIELDS_FOR_SORTING_ACCOUNT_VINS_LIST, # noqa: E501
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
mutually_exclusive=[
|
||||
('id', 'name')
|
||||
],
|
||||
required_one_of=[
|
||||
('id', 'name')
|
||||
],
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@property
|
||||
def mapped_computes_args(self) -> None | dict:
|
||||
"""
|
||||
Map the module argument `computes` to
|
||||
arguments dictionary for the method
|
||||
`DecortController.account_computes`
|
||||
(excluding for `account_id`).
|
||||
"""
|
||||
|
||||
input_args = self.aparams['computes']
|
||||
if not input_args:
|
||||
return input_args
|
||||
|
||||
mapped_args = {}
|
||||
if input_args['filter']:
|
||||
mapped_args['compute_id'] = input_args['filter']['id']
|
||||
mapped_args['compute_ip'] = input_args['filter']['ip']
|
||||
mapped_args['compute_name'] = input_args['filter']['name']
|
||||
mapped_args['compute_tech_status'] =\
|
||||
input_args['filter']['tech_status']
|
||||
mapped_args['ext_net_id'] = input_args['filter']['ext_net_id']
|
||||
mapped_args['ext_net_name'] =\
|
||||
input_args['filter']['ext_net_name']
|
||||
mapped_args['rg_id'] = input_args['filter']['rg_id']
|
||||
mapped_args['rg_name'] = input_args['filter']['rg_name']
|
||||
if input_args['pagination']:
|
||||
mapped_args['page_number'] =\
|
||||
input_args['pagination']['number']
|
||||
mapped_args['page_size'] =\
|
||||
input_args['pagination']['size']
|
||||
if input_args['sorting']:
|
||||
mapped_args['sort_by_asc'] =\
|
||||
input_args['sorting']['asc']
|
||||
mapped_args['sort_by_field'] =\
|
||||
input_args['sorting']['field']
|
||||
|
||||
return mapped_args
|
||||
|
||||
@property
|
||||
def mapped_disks_args(self) -> None | dict:
|
||||
"""
|
||||
Map the module argument `disks` to
|
||||
arguments dictionary for the method
|
||||
`DecortController.account_disks`
|
||||
(excluding for `account_id`).
|
||||
"""
|
||||
|
||||
input_args = self.aparams['disks']
|
||||
if not input_args:
|
||||
return input_args
|
||||
|
||||
mapped_args = {}
|
||||
if input_args['filter']:
|
||||
mapped_args['disk_id'] = input_args['filter']['id']
|
||||
mapped_args['disk_name'] = input_args['filter']['name']
|
||||
mapped_args['disk_size'] = input_args['filter']['size']
|
||||
mapped_args['disk_type'] = input_args['filter']['type']
|
||||
if input_args['pagination']:
|
||||
mapped_args['page_number'] =\
|
||||
input_args['pagination']['number']
|
||||
mapped_args['page_size'] =\
|
||||
input_args['pagination']['size']
|
||||
if input_args['sorting']:
|
||||
mapped_args['sort_by_asc'] =\
|
||||
input_args['sorting']['asc']
|
||||
mapped_args['sort_by_field'] =\
|
||||
input_args['sorting']['field']
|
||||
|
||||
return mapped_args
|
||||
|
||||
@property
|
||||
def mapped_flip_groups_args(self) -> None | dict:
|
||||
"""
|
||||
Map the module argument `flip_groups` to
|
||||
arguments dictionary for the method
|
||||
`DecortController.account_flip_groups`
|
||||
(excluding for `account_id`).
|
||||
"""
|
||||
|
||||
input_args = self.aparams['flip_groups']
|
||||
if not input_args:
|
||||
return input_args
|
||||
|
||||
mapped_args = {}
|
||||
if input_args['filter']:
|
||||
mapped_args['ext_net_id'] = input_args['filter']['ext_net_id']
|
||||
mapped_args['flig_group_id'] = input_args['filter']['id']
|
||||
mapped_args['flig_group_ip'] = input_args['filter']['ip']
|
||||
mapped_args['flig_group_name'] = input_args['filter']['name']
|
||||
mapped_args['vins_id'] = input_args['filter']['vins_id']
|
||||
mapped_args['vins_name'] = input_args['filter']['vins_name']
|
||||
if input_args['pagination']:
|
||||
mapped_args['page_number'] =\
|
||||
input_args['pagination']['number']
|
||||
mapped_args['page_size'] =\
|
||||
input_args['pagination']['size']
|
||||
|
||||
return mapped_args
|
||||
|
||||
@property
|
||||
def mapped_images_args(self) -> None | dict:
|
||||
"""
|
||||
Map the module argument `images` to
|
||||
arguments dictionary for the method
|
||||
`DecortController.account_images`
|
||||
(excluding for `account_id`).
|
||||
"""
|
||||
|
||||
input_args = self.aparams['images']
|
||||
if not input_args:
|
||||
return input_args
|
||||
|
||||
mapped_args = {}
|
||||
if input_args['filter']:
|
||||
mapped_args['image_id'] = input_args['filter']['id']
|
||||
mapped_args['image_name'] = input_args['filter']['name']
|
||||
mapped_args['image_type'] = input_args['filter']['type']
|
||||
if input_args['pagination']:
|
||||
mapped_args['page_number'] =\
|
||||
input_args['pagination']['number']
|
||||
mapped_args['page_size'] =\
|
||||
input_args['pagination']['size']
|
||||
if input_args['sorting']:
|
||||
mapped_args['sort_by_asc'] =\
|
||||
input_args['sorting']['asc']
|
||||
mapped_args['sort_by_field'] =\
|
||||
input_args['sorting']['field']
|
||||
|
||||
return mapped_args
|
||||
|
||||
@property
|
||||
def mapped_rg_args(self) -> None | dict:
|
||||
"""
|
||||
Map the module argument `resource_groups` to
|
||||
arguments dictionary for the method
|
||||
`DecortController.account_resource_groups`
|
||||
(excluding for `account_id`).
|
||||
"""
|
||||
|
||||
input_args = self.aparams['resource_groups']
|
||||
if not input_args:
|
||||
return input_args
|
||||
|
||||
mapped_args = {}
|
||||
if input_args['filter']:
|
||||
mapped_args['rg_id'] =\
|
||||
input_args['filter']['id']
|
||||
mapped_args['rg_name'] =\
|
||||
input_args['filter']['name']
|
||||
mapped_args['rg_status'] =\
|
||||
input_args['filter']['status']
|
||||
mapped_args['vins_id'] =\
|
||||
input_args['filter']['vins_id']
|
||||
mapped_args['vm_id'] =\
|
||||
input_args['filter']['vm_id']
|
||||
if input_args['pagination']:
|
||||
mapped_args['page_number'] =\
|
||||
input_args['pagination']['number']
|
||||
mapped_args['page_size'] =\
|
||||
input_args['pagination']['size']
|
||||
if input_args['sorting']:
|
||||
mapped_args['sort_by_asc'] =\
|
||||
input_args['sorting']['asc']
|
||||
mapped_args['sort_by_field'] =\
|
||||
input_args['sorting']['field']
|
||||
|
||||
return mapped_args
|
||||
|
||||
@property
|
||||
def mapped_vinses_args(self) -> None | dict:
|
||||
"""
|
||||
Map the module argument `vinses` to
|
||||
arguments dictionary for the method
|
||||
`DecortController.account_vinses`
|
||||
(excluding for `account_id`).
|
||||
"""
|
||||
|
||||
input_args = self.aparams['vinses']
|
||||
if not input_args:
|
||||
return input_args
|
||||
|
||||
mapped_args = {}
|
||||
if input_args['filter']:
|
||||
mapped_args['vins_id'] = input_args['filter']['id']
|
||||
mapped_args['vins_name'] = input_args['filter']['name']
|
||||
mapped_args['ext_ip'] = input_args['filter']['ext_ip']
|
||||
mapped_args['rg_id'] = input_args['filter']['rg_id']
|
||||
if input_args['pagination']:
|
||||
mapped_args['page_number'] =\
|
||||
input_args['pagination']['number']
|
||||
mapped_args['page_size'] =\
|
||||
input_args['pagination']['size']
|
||||
if input_args['sorting']:
|
||||
mapped_args['sort_by_asc'] =\
|
||||
input_args['sorting']['asc']
|
||||
mapped_args['sort_by_field'] =\
|
||||
input_args['sorting']['field']
|
||||
|
||||
return mapped_args
|
||||
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
self.id, self.facts = self.account_find(
|
||||
account_name=self.aparams['name'],
|
||||
account_id=self.aparams['id'],
|
||||
audits=self.aparams['audits'],
|
||||
computes_args=self.mapped_computes_args,
|
||||
disks_args=self.mapped_disks_args,
|
||||
flip_groups_args=self.mapped_flip_groups_args,
|
||||
images_args=self.mapped_images_args,
|
||||
resource_consumption=self.aparams['resource_consumption'],
|
||||
resource_groups_args=self.mapped_rg_args,
|
||||
vinses_args=self.mapped_vinses_args,
|
||||
fail_if_not_found=True,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
DecortAccountInfo().run()
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
app_id=dict(type='raw'),
|
||||
app_secret=dict(type='raw'),
|
||||
authenticator=dict(type='raw'),
|
||||
controller_url=dict(type='raw'),
|
||||
domain=dict(type='raw'),
|
||||
jwt=dict(type='raw'),
|
||||
oauth2_url=dict(type='raw'),
|
||||
password=dict(type='raw'),
|
||||
username=dict(type='raw'),
|
||||
verify_ssl=dict(type='raw'),
|
||||
ignore_api_compatibility=dict(type='raw'),
|
||||
ignore_sdk_version_check=dict(type='raw'),
|
||||
audits=dict(type='raw'),
|
||||
computes=dict(type='raw'),
|
||||
disks=dict(type='raw'),
|
||||
flip_groups=dict(type='raw'),
|
||||
id=dict(type='raw'),
|
||||
images=dict(type='raw'),
|
||||
name=dict(type='raw'),
|
||||
resource_groups=dict(type='raw'),
|
||||
resource_consumption=dict(type='raw'),
|
||||
vinses=dict(type='raw'),
|
||||
),
|
||||
)
|
||||
|
||||
module.fail_json(
|
||||
msg=(
|
||||
'The functionality of the module has been moved to the modules '
|
||||
'"decort_disk_list", "decort_rg_list", "decort_vm_list", '
|
||||
'"decort_vins_list", "decort_image_list", '
|
||||
'"decort_flip_group_list", "decort_account".'
|
||||
'\nPlease use the new modules to get information about the objects'
|
||||
' available to the account.'
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
130
library/decort_account_list.py
Normal file
130
library/decort_account_list.py
Normal file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_account_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortAccountList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
access_type=dict(
|
||||
type='str',
|
||||
choices=sdk_types.AccessType._member_names_,
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=sdk_types.AccountStatus._member_names_,
|
||||
),
|
||||
zone_id=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=(
|
||||
sdk_types.AccountForCAAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
aparam_status: str | None = aparam_filter['status']
|
||||
aparam_access_type: str | None = aparam_filter['access_type']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.AccountForCAAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.cloudapi.account.list(
|
||||
access_type=(
|
||||
sdk_types.AccessType[aparam_access_type]
|
||||
if aparam_access_type else None
|
||||
),
|
||||
id=aparam_filter['id'],
|
||||
name=aparam_filter['name'],
|
||||
status=(
|
||||
sdk_types.AccountStatus[aparam_status]
|
||||
if aparam_status else None
|
||||
),
|
||||
zone_id=aparam_filter['zone_id'],
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortAccountList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
168
library/decort_audit_list.py
Normal file
168
library/decort_audit_list.py
Normal file
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_audit_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortAuditList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
account_id=dict(
|
||||
type='int',
|
||||
),
|
||||
api_url_path=dict(
|
||||
type='str',
|
||||
),
|
||||
bservice_id=dict(
|
||||
type='int',
|
||||
),
|
||||
exclude_audit_lines=dict(
|
||||
type='bool',
|
||||
),
|
||||
flip_group_id=dict(
|
||||
type='int',
|
||||
),
|
||||
request_id=dict(
|
||||
type='str',
|
||||
),
|
||||
k8s_id=dict(
|
||||
type='int',
|
||||
),
|
||||
lb_id=dict(
|
||||
type='int',
|
||||
),
|
||||
max_status_code=dict(
|
||||
type='int',
|
||||
),
|
||||
min_status_code=dict(
|
||||
type='int',
|
||||
),
|
||||
request_timestamp_end=dict(
|
||||
type='int',
|
||||
),
|
||||
request_timestamp_start=dict(
|
||||
type='int',
|
||||
),
|
||||
rg_id=dict(
|
||||
type='int',
|
||||
),
|
||||
sep_id=dict(
|
||||
type='int',
|
||||
),
|
||||
user_name=dict(
|
||||
type='str',
|
||||
),
|
||||
vins_id=dict(
|
||||
type='int',
|
||||
),
|
||||
vm_id=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=(
|
||||
sdk_types.AuditAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.AuditAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.cloudapi.audit.list(
|
||||
account_id=aparam_filter['account_id'],
|
||||
api_url_path=aparam_filter['api_url_path'],
|
||||
bservice_id=aparam_filter['bservice_id'],
|
||||
exclude_audit_lines=aparam_filter['exclude_audit_lines'] or False,
|
||||
flip_group_id=aparam_filter['flip_group_id'],
|
||||
request_id=aparam_filter['request_id'],
|
||||
k8s_id=aparam_filter['k8s_id'],
|
||||
lb_id=aparam_filter['lb_id'],
|
||||
max_status_code=aparam_filter['max_status_code'],
|
||||
min_status_code=aparam_filter['min_status_code'],
|
||||
request_timestamp_end=aparam_filter['request_timestamp_end'],
|
||||
request_timestamp_start=aparam_filter['request_timestamp_start'],
|
||||
rg_id=aparam_filter['rg_id'],
|
||||
sep_id=aparam_filter['sep_id'],
|
||||
user_name=aparam_filter['user_name'],
|
||||
vins_id=aparam_filter['vins_id'],
|
||||
vm_id=aparam_filter['vm_id'],
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortAuditList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -28,7 +28,7 @@ class decort_bservice(DecortController):
|
||||
self.fail_json(**self.result)
|
||||
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
|
||||
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'])
|
||||
if not validated_acc_id:
|
||||
self.result['failed'] = True
|
||||
@@ -113,7 +113,9 @@ class decort_bservice(DecortController):
|
||||
)
|
||||
if 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'])
|
||||
|
||||
self.bservice_should_exist = True
|
||||
return
|
||||
|
||||
def action(self,d_state):
|
||||
@@ -176,7 +178,6 @@ class decort_bservice(DecortController):
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
default='present',
|
||||
choices=[
|
||||
'absent',
|
||||
'disabled',
|
||||
@@ -260,71 +261,80 @@ class decort_bservice(DecortController):
|
||||
if check_errors:
|
||||
self.exit(fail=True)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
amodule = self.amodule
|
||||
|
||||
if self.amodule.check_mode:
|
||||
self.result['changed'] = False
|
||||
if self.bservice_id:
|
||||
self.result['failed'] = False
|
||||
self.result['facts'] = self.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**self.result)
|
||||
# we exit the module at this point
|
||||
else:
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = ("Cannot locate B-service name '{}'. Other arguments are: B-service ID {}, "
|
||||
"RG name '{}', RG ID {}, Account '{}'.").format(amodule.params['name'],
|
||||
amodule.params['id'],
|
||||
amodule.params['rg_name'],
|
||||
amodule.params['rg_id'],
|
||||
amodule.params['account_name'])
|
||||
amodule.fail_json(**self.result)
|
||||
pass
|
||||
|
||||
|
||||
#MAIN MANAGE PART
|
||||
|
||||
if self.bservice_id:
|
||||
if self.bservice_info['status'] in ("DELETING","DESTROYNG","RECONFIGURING","DESTROYING",
|
||||
"ENABLING","DISABLING","RESTORING","MODELED"):
|
||||
self.error()
|
||||
elif self.bservice_info['status'] == "DELETED":
|
||||
if amodule.params['state'] in (
|
||||
'disabled', 'enabled', 'present', 'started', 'stopped'
|
||||
):
|
||||
self.restore(self.bservice_id)
|
||||
self.action(amodule.params['state'])
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.nop()
|
||||
elif self.bservice_info['status'] in (
|
||||
'ENABLED', 'DISABLED', 'CREATED',
|
||||
):
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.destroy()
|
||||
else:
|
||||
self.action(amodule.params['state'])
|
||||
elif self.bservice_info['status'] == "DESTROYED":
|
||||
if amodule.params['state'] in ('present','enabled'):
|
||||
self.create()
|
||||
self.action(amodule.params['state'])
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.nop()
|
||||
else:
|
||||
state = amodule.params['state']
|
||||
if state is None:
|
||||
state = 'present'
|
||||
if state == 'absent':
|
||||
self.nop()
|
||||
if state in ('present','started'):
|
||||
self.create()
|
||||
elif state in ('stopped', 'disabled','enabled'):
|
||||
self.error()
|
||||
|
||||
if self.result['failed']:
|
||||
amodule.fail_json(**self.result)
|
||||
else:
|
||||
if self.bservice_should_exist:
|
||||
_, self.bservice_info = self.bservice_get_by_id(self.bservice_id)
|
||||
self.result['facts'] = self.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**self.result)
|
||||
else:
|
||||
amodule.exit_json(**self.result)
|
||||
|
||||
def main():
|
||||
subj = decort_bservice()
|
||||
amodule = subj.amodule
|
||||
|
||||
if subj.amodule.check_mode:
|
||||
subj.result['changed'] = False
|
||||
if subj.bservice_id:
|
||||
subj.result['failed'] = False
|
||||
subj.result['facts'] = subj.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**subj.result)
|
||||
# we exit the module at this point
|
||||
else:
|
||||
subj.result['failed'] = True
|
||||
subj.result['msg'] = ("Cannot locate B-service name '{}'. Other arguments are: B-service ID {}, "
|
||||
"RG name '{}', RG ID {}, Account '{}'.").format(amodule.params['name'],
|
||||
amodule.params['id'],
|
||||
amodule.params['rg_name'],
|
||||
amodule.params['rg_id'],
|
||||
amodule.params['account_name'])
|
||||
amodule.fail_json(**subj.result)
|
||||
pass
|
||||
|
||||
|
||||
#MAIN MANAGE PART
|
||||
decort_bservice().run()
|
||||
|
||||
if subj.bservice_id:
|
||||
if subj.bservice_info['status'] in ("DELETING","DESTROYNG","RECONFIGURING","DESTROYING",
|
||||
"ENABLING","DISABLING","RESTORING","MODELED"):
|
||||
subj.error()
|
||||
elif subj.bservice_info['status'] == "DELETED":
|
||||
if amodule.params['state'] in (
|
||||
'disabled', 'enabled', 'present', 'started', 'stopped'
|
||||
):
|
||||
subj.restore(subj.bservice_id)
|
||||
subj.action(amodule.params['state'])
|
||||
if amodule.params['state'] == 'absent':
|
||||
subj.nop()
|
||||
elif subj.bservice_info['status'] in ('ENABLED', 'DISABLED'):
|
||||
if amodule.params['state'] == 'absent':
|
||||
subj.destroy()
|
||||
else:
|
||||
subj.action(amodule.params['state'])
|
||||
elif subj.bservice_info['status'] == "DESTROED":
|
||||
if amodule.params['state'] in ('present','enabled'):
|
||||
subj.create()
|
||||
subj.action(amodule.params['state'])
|
||||
if amodule.params['state'] == 'absent':
|
||||
subj.nop()
|
||||
else:
|
||||
if amodule.params['state'] == 'absent':
|
||||
subj.nop()
|
||||
if amodule.params['state'] in ('present','started'):
|
||||
subj.create()
|
||||
elif amodule.params['state'] in ('stopped', 'disabled','enabled'):
|
||||
subj.error()
|
||||
|
||||
if subj.result['failed']:
|
||||
amodule.fail_json(**subj.result)
|
||||
else:
|
||||
if subj.bservice_should_exist:
|
||||
_, subj.bservice_info = subj.bservice_get_by_id(subj.bservice_id)
|
||||
subj.result['facts'] = subj.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**subj.result)
|
||||
else:
|
||||
amodule.exit_json(**subj.result)
|
||||
if __name__ == "__main__":
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -23,7 +23,7 @@ class decort_disk(DecortController):
|
||||
self.disk_id = 0
|
||||
self.account_id = 0
|
||||
# limitIO check for exclusive parameters
|
||||
|
||||
|
||||
if arg_amodule.params['limitIO']:
|
||||
self.disk_check_iotune_arg(arg_amodule.params['limitIO'])
|
||||
|
||||
@@ -41,6 +41,8 @@ class decort_disk(DecortController):
|
||||
validated_acc_id, validated_acc_info = self.account_find(
|
||||
arg_amodule.params['account_name'],
|
||||
arg_amodule.params['account_id'])
|
||||
self.acc_id = validated_acc_id
|
||||
self._acc_info = validated_acc_info
|
||||
if not validated_acc_id:
|
||||
self.result['changed'] = False
|
||||
self.result['msg'] = (
|
||||
@@ -51,8 +53,6 @@ class decort_disk(DecortController):
|
||||
)
|
||||
self.amodule.fail_json(**self.result)
|
||||
|
||||
self.acc_id = validated_acc_id
|
||||
self._acc_info = validated_acc_info
|
||||
validated_disk_id, validated_disk_facts = self.disk_find(
|
||||
disk_id=arg_amodule.params['id'],
|
||||
name=arg_amodule.params['name'] if "name" in arg_amodule.params else "",
|
||||
@@ -67,70 +67,130 @@ class decort_disk(DecortController):
|
||||
self.disk_id = validated_disk_id
|
||||
self.disk_info = validated_disk_facts
|
||||
|
||||
if self.disk_id:
|
||||
self.acc_id = validated_disk_facts['accountId']
|
||||
self.check_amodule_args_for_change()
|
||||
else:
|
||||
self.check_amodule_args_for_create()
|
||||
|
||||
def compare_iotune_params(self, new_iotune: dict, current_iotune: dict):
|
||||
io_fields = sdk_types.IOTuneAPIResultNM.model_fields.keys()
|
||||
|
||||
for field in io_fields:
|
||||
new_value = new_iotune.get(field)
|
||||
current_value = current_iotune.get(field)
|
||||
|
||||
if new_value != current_value:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def limit_io(self, aparam_limit_io: dict):
|
||||
self.sdk_checkmode(self.api.cloudapi.disks.limit_io)(
|
||||
disk_id=self.disk_id,
|
||||
read_bytes_sec_max=(aparam_limit_io.get('read_bytes_sec_max')),
|
||||
read_bytes_sec=(aparam_limit_io.get('read_bytes_sec')),
|
||||
read_iops_sec_max=(aparam_limit_io.get('read_iops_sec_max')),
|
||||
read_iops_sec=(aparam_limit_io.get('read_iops_sec')),
|
||||
size_iops_sec=(aparam_limit_io.get('size_iops_sec')),
|
||||
total_bytes_sec_max=(aparam_limit_io.get('total_bytes_sec_max')),
|
||||
total_bytes_sec=(aparam_limit_io.get('total_bytes_sec')),
|
||||
total_iops_sec_max=(aparam_limit_io.get('total_iops_sec_max')),
|
||||
total_iops_sec=(aparam_limit_io.get('total_iops_sec')),
|
||||
write_bytes_sec_max=(aparam_limit_io.get('write_bytes_sec_max')),
|
||||
write_bytes_sec=(aparam_limit_io.get('write_bytes_sec')),
|
||||
write_iops_sec_max=(aparam_limit_io.get('write_iops_sec_max')),
|
||||
write_iops_sec=(aparam_limit_io.get('write_iops_sec')),
|
||||
)
|
||||
|
||||
def create(self):
|
||||
|
||||
self.disk_id = self.disk_create(accountId=self.acc_id,
|
||||
name = self.amodule.params['name'],
|
||||
description=self.amodule.params['description'],
|
||||
size=self.amodule.params['size'],
|
||||
iops=self.amodule.params['iops'],
|
||||
sep_id=self.amodule.params['sep_id'],
|
||||
pool=self.amodule.params['pool'],
|
||||
self.disk_id = self.sdk_checkmode(self.api.cloudapi.disks.create)(
|
||||
account_id=self.acc_id,
|
||||
name=self.amodule.params['name'],
|
||||
size_gb=self.amodule.params['size'],
|
||||
storage_policy_id=self.aparams['storage_policy_id'],
|
||||
description=self.amodule.params['description'],
|
||||
sep_id=self.amodule.params['sep_id'],
|
||||
sep_pool_name=self.amodule.params['pool'],
|
||||
)
|
||||
#IO tune
|
||||
if self.amodule.params['limitIO']:
|
||||
self.disk_limitIO(disk_id=self.disk_id,
|
||||
limits=self.amodule.params['limitIO'])
|
||||
aparam_limit_io: dict[str, int | None] = self.amodule.params['limitIO']
|
||||
self.limit_io(aparam_limit_io=aparam_limit_io)
|
||||
#set share status
|
||||
if self.amodule.params['shareable']:
|
||||
self.disk_share(self.disk_id,self.amodule.params['shareable'])
|
||||
self.sdk_checkmode(self.api.cloudapi.disks.share)(
|
||||
disk_id=self.disk_id,
|
||||
)
|
||||
return
|
||||
|
||||
def action(self,restore=False):
|
||||
|
||||
#restore never be done
|
||||
if restore:
|
||||
self.disk_restore(self.disk_id)
|
||||
self.sdk_checkmode(self.api.cloudapi.disks.restore)(
|
||||
disk_id=self.disk_id,
|
||||
)
|
||||
#rename if id present
|
||||
if (
|
||||
self.amodule.params['name'] is not None
|
||||
and self.amodule.params['name'] != self.disk_info['name']
|
||||
):
|
||||
self.disk_rename(disk_id=self.disk_id,
|
||||
name=self.amodule.params['name'])
|
||||
self.rename()
|
||||
#resize
|
||||
if (
|
||||
self.amodule.params['size'] is not None
|
||||
and self.amodule.params['size'] != self.disk_info['sizeMax']
|
||||
):
|
||||
self.disk_resize(self.disk_info,self.amodule.params['size'])
|
||||
self.sdk_checkmode(self.api.cloudapi.disks.resize2)(
|
||||
disk_id=self.disk_id,
|
||||
disk_size_gb=self.amodule.params['size'],
|
||||
)
|
||||
#IO TUNE
|
||||
if self.amodule.params['limitIO']:
|
||||
clean_io = [param for param in self.amodule.params['limitIO'] \
|
||||
if self.amodule.params['limitIO'][param] == None]
|
||||
for key in clean_io: del self.amodule.params['limitIO'][key]
|
||||
if self.amodule.params['limitIO'] != self.disk_info['iotune']:
|
||||
self.disk_limitIO(self.disk_id,self.amodule.params['limitIO'])
|
||||
aparam_limit_io: dict[str, int | None] = self.amodule.params['limitIO']
|
||||
if aparam_limit_io:
|
||||
if not self.compare_iotune_params(
|
||||
new_iotune=aparam_limit_io,
|
||||
current_iotune=self.disk_info['iotune'],
|
||||
):
|
||||
self.limit_io(aparam_limit_io=aparam_limit_io)
|
||||
|
||||
#share check/update
|
||||
#raise Exception(self.amodule.params['shareable'])
|
||||
if self.amodule.params['shareable'] != self.disk_info['shareable']:
|
||||
self.disk_share(self.disk_id,self.amodule.params['shareable'])
|
||||
if self.amodule.params['shareable'] != self.disk_info['shareable']:
|
||||
if self.amodule.params['shareable']:
|
||||
self.sdk_checkmode(self.api.cloudapi.disks.share)(
|
||||
disk_id=self.disk_id,
|
||||
)
|
||||
else:
|
||||
self.sdk_checkmode(self.api.cloudapi.disks.unshare)(
|
||||
disk_id=self.disk_id,
|
||||
)
|
||||
|
||||
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.sdk_checkmode(self.api.ca.disks.change_disk_storage_policy)(
|
||||
disk_id=self.disk_id,
|
||||
storage_policy_id=aparam_storage_policy_id,
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
def delete(self):
|
||||
self.disk_id = self.disk_delete(disk_id=self.disk_id,
|
||||
detach=self.amodule.params['force_detach'],
|
||||
permanently=self.amodule.params['permanently'],
|
||||
reason=self.amodule.params['reason'])
|
||||
self.disk_info['status'] = "DELETED"
|
||||
self.sdk_checkmode(self.api.cloudapi.disks.delete)(
|
||||
disk_id=self.disk_id,
|
||||
detach=self.amodule.params['force_detach'],
|
||||
permanently=self.amodule.params['permanently'],
|
||||
)
|
||||
self.disk_id, self.disk_info = self._disk_get_by_id(self.disk_id)
|
||||
return
|
||||
|
||||
|
||||
def rename(self):
|
||||
|
||||
|
||||
self.disk_rename(diskId = self.disk_id,
|
||||
name = self.amodule.params['name'])
|
||||
self.disk_info['name'] = self.amodule.params['name']
|
||||
self.sdk_checkmode(self.api.cloudapi.disks.rename)(
|
||||
disk_id=self.disk_id,
|
||||
name=self.amodule.params['name'],
|
||||
)
|
||||
return
|
||||
|
||||
def nop(self):
|
||||
@@ -175,6 +235,10 @@ class decort_disk(DecortController):
|
||||
ret_dict['iotune'] = self.disk_info['iotune']
|
||||
ret_dict['size_available'] = self.disk_info['sizeAvailable']
|
||||
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']
|
||||
ret_dict['cache_mode'] = self.disk_info['cache']
|
||||
ret_dict['blkdiscard'] = self.disk_info['blkdiscard']
|
||||
|
||||
return ret_dict
|
||||
|
||||
@@ -219,12 +283,9 @@ class decort_disk(DecortController):
|
||||
size=dict(
|
||||
type='int',
|
||||
),
|
||||
iops=dict(
|
||||
type='int',
|
||||
default=2000,
|
||||
),
|
||||
limitIO=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
total_bytes_sec=dict(
|
||||
type='int',
|
||||
@@ -275,10 +336,6 @@ class decort_disk(DecortController):
|
||||
type='bool',
|
||||
default=False,
|
||||
),
|
||||
reason=dict(
|
||||
type='str',
|
||||
default='Managed by Ansible decort_disk',
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
default='present',
|
||||
@@ -287,6 +344,9 @@ class decort_disk(DecortController):
|
||||
'present',
|
||||
],
|
||||
),
|
||||
storage_policy_id=dict(
|
||||
type='int',
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
required_one_of=[
|
||||
@@ -294,57 +354,127 @@ class decort_disk(DecortController):
|
||||
],
|
||||
)
|
||||
|
||||
def main():
|
||||
decon = decort_disk()
|
||||
amodule = decon.amodule
|
||||
#
|
||||
#Full range of Disk status is as follows:
|
||||
#
|
||||
# "ASSIGNED","MODELED", "CREATING","CREATED","DELETED", "DESTROYED","PURGED",
|
||||
#
|
||||
if decon.disk_id:
|
||||
#disk exist
|
||||
if decon.disk_info['status'] in ["MODELED", "CREATING"]:
|
||||
decon.result['failed'] = True
|
||||
decon.result['changed'] = False
|
||||
decon.result['msg'] = ("No change can be done for existing Disk ID {} because of its current "
|
||||
"status '{}'").format(decon.disk_id, decon.disk_info['status'])
|
||||
# "ASSIGNED","CREATED","DELETED","PURGED", "DESTROYED"
|
||||
elif decon.disk_info['status'] in ["ASSIGNED","CREATED"]:
|
||||
if amodule.params['state'] == 'absent':
|
||||
decon.delete()
|
||||
elif amodule.params['state'] == 'present':
|
||||
decon.action()
|
||||
elif decon.disk_info['status'] in ["PURGED", "DESTROYED"]:
|
||||
#re-provision disk
|
||||
if amodule.params['state'] in ('present'):
|
||||
decon.create()
|
||||
else:
|
||||
decon.nop()
|
||||
elif decon.disk_info['status'] == "DELETED":
|
||||
if amodule.params['state'] in ('present'):
|
||||
decon.action(restore=True)
|
||||
elif (amodule.params['state'] == 'absent' and
|
||||
amodule.params['permanently']):
|
||||
decon.delete()
|
||||
else:
|
||||
decon.nop()
|
||||
else:
|
||||
# preexisting Disk was not found
|
||||
if amodule.params['state'] == 'absent':
|
||||
decon.nop()
|
||||
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
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
#
|
||||
#Full range of Disk status is as follows:
|
||||
#
|
||||
# "ASSIGNED","MODELED", "CREATING","CREATED","DELETED", "DESTROYED","PURGED",
|
||||
#
|
||||
amodule = self.amodule
|
||||
if self.disk_id:
|
||||
#disk exist
|
||||
if self.disk_info['status'] in ["MODELED", "CREATING"]:
|
||||
self.result['failed'] = True
|
||||
self.result['changed'] = False
|
||||
self.result['msg'] = ("No change can be done for existing Disk ID {} because of its current "
|
||||
"status '{}'").format(self.disk_id, self.disk_info['status'])
|
||||
# "ASSIGNED","CREATED","DELETED","PURGED", "DESTROYED"
|
||||
elif self.disk_info['status'] in ["ASSIGNED","CREATED"]:
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.delete()
|
||||
elif amodule.params['state'] == 'present':
|
||||
self.action()
|
||||
elif self.disk_info['status'] in ["PURGED", "DESTROYED"]:
|
||||
#re-provision disk
|
||||
if amodule.params['state'] in ('present'):
|
||||
self.create()
|
||||
else:
|
||||
self.nop()
|
||||
elif self.disk_info['status'] == "DELETED":
|
||||
if amodule.params['state'] in ('present'):
|
||||
self.action(restore=True)
|
||||
elif (amodule.params['state'] == 'absent' and
|
||||
amodule.params['permanently']):
|
||||
self.delete()
|
||||
else:
|
||||
self.nop()
|
||||
else:
|
||||
decon.create()
|
||||
|
||||
if decon.result['failed']:
|
||||
amodule.fail_json(**decon.result)
|
||||
else:
|
||||
if decon.result['changed'] and amodule.params['state'] in ('present'):
|
||||
_, decon.disk_info = decon.disk_find(decon.disk_id)
|
||||
decon.result['facts'] = decon.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**decon.result)
|
||||
# preexisting Disk was not found
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.nop()
|
||||
else:
|
||||
self.create()
|
||||
|
||||
if __name__ == "__main__":
|
||||
if self.result['failed']:
|
||||
amodule.fail_json(**self.result)
|
||||
else:
|
||||
if self.result['changed']:
|
||||
_, self.disk_info = self.disk_find(self.disk_id)
|
||||
self.result['facts'] = self.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**self.result)
|
||||
|
||||
|
||||
def main():
|
||||
decort_disk().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
#SHARE
|
||||
|
||||
155
library/decort_disk_list.py
Normal file
155
library/decort_disk_list.py
Normal file
@@ -0,0 +1,155 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_disk_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortDiskList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
account_id=dict(
|
||||
type='int',
|
||||
),
|
||||
account_name=dict(
|
||||
type='str',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
sep_id=dict(
|
||||
type='int',
|
||||
),
|
||||
sep_pool_name=dict(
|
||||
type='str',
|
||||
),
|
||||
shared=dict(
|
||||
type='bool',
|
||||
),
|
||||
disk_max_size_gb=dict(
|
||||
type='int',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=sdk_types.DiskStatus._member_names_,
|
||||
),
|
||||
storage_policy_id=dict(
|
||||
type='int',
|
||||
),
|
||||
type=dict(
|
||||
type='str',
|
||||
choices=sdk_types.DiskType._member_names_,
|
||||
),
|
||||
),
|
||||
),
|
||||
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=(
|
||||
sdk_types.DiskForListAndListDeletedAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
aparam_status: str | None = aparam_filter['status']
|
||||
aparam_type: str | None = aparam_filter['type']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.DiskForListAndListDeletedAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.cloudapi.disks.list(
|
||||
account_id=aparam_filter['account_id'],
|
||||
account_name=aparam_filter['account_name'],
|
||||
disk_max_size_gb=aparam_filter['disk_max_size_gb'],
|
||||
id=aparam_filter['id'],
|
||||
name=aparam_filter['name'],
|
||||
sep_id=aparam_filter['sep_id'],
|
||||
sep_pool_name=aparam_filter['sep_pool_name'],
|
||||
shared=aparam_filter['shared'],
|
||||
status=(
|
||||
sdk_types.DiskStatus[aparam_status]
|
||||
if aparam_status else None
|
||||
),
|
||||
storage_policy_id=aparam_filter['storage_policy_id'],
|
||||
type=(
|
||||
sdk_types.DiskType[aparam_type]
|
||||
if aparam_type else None
|
||||
),
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortDiskList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
150
library/decort_flip_group_list.py
Normal file
150
library/decort_flip_group_list.py
Normal file
@@ -0,0 +1,150 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_flip_group_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortFlipGroupList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
account_id=dict(
|
||||
type='int',
|
||||
),
|
||||
client_ids=dict(
|
||||
type='list',
|
||||
elements='int',
|
||||
),
|
||||
conn_id=dict(
|
||||
type='int',
|
||||
),
|
||||
ext_net_id=dict(
|
||||
type='int',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
include_deleted=dict(
|
||||
type='bool',
|
||||
default=False,
|
||||
),
|
||||
ip_addr=dict(
|
||||
type='str',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=sdk_types.FlipGroupStatus._member_names_,
|
||||
),
|
||||
vins_id=dict(
|
||||
type='int',
|
||||
),
|
||||
vins_name=dict(
|
||||
type='str',
|
||||
),
|
||||
),
|
||||
),
|
||||
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=(
|
||||
sdk_types.FlipGroupForListAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
aparam_status: str | None = aparam_filter['status']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.FlipGroupForListAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.cloudapi.flipgroup.list(
|
||||
account_id=aparam_filter['account_id'],
|
||||
client_ids=aparam_filter['client_ids'],
|
||||
conn_id=aparam_filter['conn_id'],
|
||||
ext_net_id=aparam_filter['ext_net_id'],
|
||||
id=aparam_filter['id'],
|
||||
ip_addr=aparam_filter['ip_addr'],
|
||||
name=aparam_filter['name'],
|
||||
status=(
|
||||
sdk_types.FlipGroupStatus[aparam_status]
|
||||
if aparam_status else None
|
||||
),
|
||||
vins_id=aparam_filter['vins_id'],
|
||||
vins_name=aparam_filter['vins_name'],
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortFlipGroupList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -36,11 +36,15 @@ class decort_group(DecortController):
|
||||
group_id=arg_amodule.params['id'],
|
||||
group_name=arg_amodule.params['name'],
|
||||
)
|
||||
self.acc_id = self.bservice_info['accountId']
|
||||
self.rg_id = self.bservice_info['rgId']
|
||||
|
||||
if self.group_id:
|
||||
self.group_should_exist = True
|
||||
self.check_amodule_args_for_change()
|
||||
|
||||
else:
|
||||
self.check_amodule_args_for_create()
|
||||
|
||||
return
|
||||
def nop(self):
|
||||
"""No operation (NOP) handler for B-service.
|
||||
@@ -77,7 +81,7 @@ class decort_group(DecortController):
|
||||
def create(self):
|
||||
chipset = self.aparams['chipset']
|
||||
if chipset is None:
|
||||
chipset = 'i440fx'
|
||||
chipset = 'Q35'
|
||||
self.message(
|
||||
msg=f'Chipset not specified, '
|
||||
f'default value "{chipset}" will be used.',
|
||||
@@ -92,13 +96,13 @@ class decort_group(DecortController):
|
||||
arg_ram=self.amodule.params['ram'],
|
||||
arg_boot_disk=self.amodule.params['boot_disk'],
|
||||
arg_image_id=self.amodule.params['image_id'],
|
||||
arg_driver=self.amodule.params['driver'],
|
||||
arg_role=self.amodule.params['role'],
|
||||
arg_network=self.amodule.params['networks'],
|
||||
arg_timeout=self.amodule.params['timeoutStart'],
|
||||
arg_timeout=self.amodule.params['timeoutStart'],
|
||||
chipset=chipset,
|
||||
storage_policy_id=self.aparams['storage_policy_id'],
|
||||
)
|
||||
|
||||
|
||||
if self.amodule.params['state'] in ('started','present'):
|
||||
self.group_state(self.bservice_id,self.group_id,self.amodule.params['state'])
|
||||
|
||||
@@ -196,6 +200,7 @@ class decort_group(DecortController):
|
||||
ret_dict['techStatus'] = self.group_info['techStatus']
|
||||
ret_dict['state'] = self.group_info['status']
|
||||
ret_dict['Computes'] = self.group_info['computes']
|
||||
ret_dict['driver'] = self.group_info['driver']
|
||||
return ret_dict
|
||||
|
||||
@property
|
||||
@@ -229,17 +234,6 @@ class decort_group(DecortController):
|
||||
image_id=dict(
|
||||
type='int',
|
||||
),
|
||||
image_name=dict(
|
||||
type='str',
|
||||
),
|
||||
driver=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
'KVM_X86',
|
||||
'SVA_KVM_X86',
|
||||
],
|
||||
default='KVM_X86',
|
||||
),
|
||||
boot_disk=dict(
|
||||
type='int',
|
||||
),
|
||||
@@ -287,17 +281,13 @@ class decort_group(DecortController):
|
||||
'i440fx',
|
||||
]
|
||||
),
|
||||
storage_policy_id=dict(
|
||||
type='int',
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
required_one_of=[
|
||||
('id', 'name'),
|
||||
('id', 'networks'),
|
||||
('id', 'count'),
|
||||
('id', 'cpu'),
|
||||
('id', 'ram'),
|
||||
('id', 'boot_disk'),
|
||||
('id', 'image_id'),
|
||||
('id', 'driver'),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -306,7 +296,7 @@ class decort_group(DecortController):
|
||||
|
||||
if (
|
||||
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
|
||||
self.message(
|
||||
@@ -335,58 +325,113 @@ class decort_group(DecortController):
|
||||
)
|
||||
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']}'
|
||||
)
|
||||
|
||||
if check_errors:
|
||||
self.exit(fail=True)
|
||||
|
||||
def main():
|
||||
subj = decort_group()
|
||||
amodule = subj.amodule
|
||||
|
||||
if amodule.params['state'] == 'check':
|
||||
subj.result['changed'] = False
|
||||
if subj.group_id:
|
||||
# cluster is found - package facts and report success to Ansible
|
||||
subj.result['failed'] = False
|
||||
subj.result['facts'] = subj.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**subj.result)
|
||||
# we exit the module at this point
|
||||
else:
|
||||
subj.result['failed'] = True
|
||||
subj.result['msg'] = ("Cannot locate Group name '{}'. "
|
||||
"B-service ID {}").format(amodule.params['name'],
|
||||
amodule.params['bservice_id'],)
|
||||
amodule.fail_json(**subj.result)
|
||||
def check_amodule_args_for_create(self):
|
||||
check_errors = False
|
||||
|
||||
if subj.group_id:
|
||||
if subj.group_info['status'] in ("DELETING","DESTROYNG","CREATING","DESTROYING",
|
||||
"ENABLING","DISABLING","RESTORING","MODELED",
|
||||
"DISABLED","DESTROYED"):
|
||||
subj.error()
|
||||
elif subj.group_info['status'] in ("DELETED","DESTROYED"):
|
||||
if amodule.params['state'] == 'absent':
|
||||
subj.nop()
|
||||
if amodule.params['state'] in ('present','started','stopped'):
|
||||
subj.create()
|
||||
elif subj.group_info['techStatus'] in ("STARTED","STOPPED"):
|
||||
if amodule.params['state'] == 'absent':
|
||||
subj.destroy()
|
||||
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)
|
||||
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
amodule = self.amodule
|
||||
|
||||
if amodule.params['state'] == 'check':
|
||||
self.result['changed'] = False
|
||||
if self.group_id:
|
||||
# cluster is found - package facts and report success to Ansible
|
||||
self.result['failed'] = False
|
||||
self.result['facts'] = self.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**self.result)
|
||||
# we exit the module at this point
|
||||
else:
|
||||
subj.action()
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = ("Cannot locate Group name '{}'. "
|
||||
"B-service ID {}").format(amodule.params['name'],
|
||||
amodule.params['bservice_id'],)
|
||||
amodule.fail_json(**self.result)
|
||||
|
||||
if self.group_id:
|
||||
if self.group_info['status'] in ("DELETING","DESTROYNG","CREATING","DESTROYING",
|
||||
"ENABLING","DISABLING","RESTORING","MODELED","DESTROYED"):
|
||||
self.error()
|
||||
elif self.group_info['status'] in ("DELETED","DESTROYED"):
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.nop()
|
||||
if amodule.params['state'] in ('present','started','stopped'):
|
||||
self.create()
|
||||
elif self.group_info['techStatus'] in ("STARTED","STOPPED"):
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.destroy()
|
||||
else:
|
||||
self.action()
|
||||
|
||||
else:
|
||||
if amodule.params['state'] == 'absent':
|
||||
subj.nop()
|
||||
if amodule.params['state'] in ('present','started','stopped'):
|
||||
subj.create()
|
||||
|
||||
if subj.result['failed']:
|
||||
amodule.fail_json(**subj.result)
|
||||
else:
|
||||
if subj.group_should_exist:
|
||||
subj.result['facts'] = subj.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**subj.result)
|
||||
else:
|
||||
amodule.exit_json(**subj.result)
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.nop()
|
||||
if amodule.params['state'] in ('present','started','stopped'):
|
||||
self.create()
|
||||
|
||||
if self.result['failed']:
|
||||
amodule.fail_json(**self.result)
|
||||
else:
|
||||
if self.group_should_exist:
|
||||
self.result['facts'] = self.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**self.result)
|
||||
else:
|
||||
amodule.exit_json(**self.result)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
def main():
|
||||
decort_group().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
558
library/decort_image.py
Normal file
558
library/decort_image.py
Normal file
@@ -0,0 +1,558 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_image
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home).
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.basic import env_fallback
|
||||
|
||||
from ansible.module_utils.decort_utils import *
|
||||
|
||||
|
||||
class decort_image(DecortController):
|
||||
def __init__(self):
|
||||
super(decort_image, self).__init__(AnsibleModule(**self.amodule_init_args))
|
||||
amodule = self.amodule
|
||||
|
||||
self.validated_image_id = 0
|
||||
self.validated_virt_image_id = 0
|
||||
self.validated_image_name = amodule.params['image_name']
|
||||
self.validated_virt_image_name = None
|
||||
self.image_info: dict
|
||||
self.virt_image_info: dict
|
||||
if amodule.params['account_name']:
|
||||
self.validated_account_id, _ = self.account_find(amodule.params['account_name'])
|
||||
else:
|
||||
self.validated_account_id = amodule.params['account_id']
|
||||
|
||||
if self.validated_account_id == 0:
|
||||
# we failed either to find or access the specified account - fail the module
|
||||
self.result['failed'] = True
|
||||
self.result['changed'] = False
|
||||
self.result['msg'] = ("Cannot find account '{}'").format(amodule.params['account_name'])
|
||||
amodule.fail_json(**self.result)
|
||||
self.acc_id = self.validated_account_id
|
||||
|
||||
if (
|
||||
self.aparams['virt_id'] != 0
|
||||
or self.aparams['virt_name'] is not None
|
||||
):
|
||||
self.validated_virt_image_id, self.virt_image_info = (
|
||||
self.decort_virt_image_find(amodule)
|
||||
)
|
||||
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.result['msg'] = 'Virtual image renamed successfully'
|
||||
elif (
|
||||
self.aparams['image_id'] != 0
|
||||
or self.aparams['image_name'] is not None
|
||||
):
|
||||
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_image.decort_image_rename(self,amodule)
|
||||
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):
|
||||
# function that finds the OS image
|
||||
image_id, image_facts = self.image_find(image_id=amodule.params['image_id'], image_name=self.validated_image_name,
|
||||
account_id=self.validated_account_id, rg_id=0,
|
||||
sepid=amodule.params['sep_id'],
|
||||
pool=amodule.params['pool'])
|
||||
return image_id, image_facts
|
||||
|
||||
def decort_virt_image_find(self, amodule):
|
||||
# function that finds a virtual image
|
||||
image_id, image_facts = self.virt_image_find(image_id=amodule.params['virt_id'],
|
||||
account_id=self.validated_account_id, rg_id=0,
|
||||
sepid=amodule.params['sep_id'],
|
||||
virt_name=amodule.params['virt_name'],
|
||||
pool=amodule.params['pool'])
|
||||
return image_id, image_facts
|
||||
|
||||
|
||||
|
||||
def decort_image_create(self,amodule):
|
||||
aparam_boot = self.aparams['boot']
|
||||
boot_mode = 'bios'
|
||||
loader_type = 'unknown'
|
||||
if aparam_boot is not None:
|
||||
if aparam_boot['mode'] is None:
|
||||
self.message(
|
||||
msg=self.MESSAGES.default_value_used(
|
||||
param_name='boot.mode',
|
||||
default_value=boot_mode
|
||||
),
|
||||
warning=True,
|
||||
)
|
||||
else:
|
||||
boot_mode = aparam_boot['mode']
|
||||
|
||||
if aparam_boot['loader_type'] is None:
|
||||
self.message(
|
||||
msg=self.MESSAGES.default_value_used(
|
||||
param_name='boot.loader_type',
|
||||
default_value=loader_type
|
||||
),
|
||||
warning=True,
|
||||
)
|
||||
else:
|
||||
loader_type = aparam_boot['loader_type']
|
||||
|
||||
network_interface_naming = self.aparams['network_interface_naming']
|
||||
if network_interface_naming is None:
|
||||
network_interface_naming = 'ens'
|
||||
self.message(
|
||||
msg=self.MESSAGES.default_value_used(
|
||||
param_name='network_interface_naming',
|
||||
default_value=network_interface_naming
|
||||
),
|
||||
warning=True,
|
||||
)
|
||||
|
||||
hot_resize = self.aparams['hot_resize']
|
||||
if hot_resize is None:
|
||||
hot_resize = False
|
||||
self.message(
|
||||
msg=self.MESSAGES.default_value_used(
|
||||
param_name='hot_resize',
|
||||
default_value=hot_resize
|
||||
),
|
||||
warning=True,
|
||||
)
|
||||
|
||||
# function that creates OS image
|
||||
image_facts = self.image_create(
|
||||
img_name=self.validated_image_name,
|
||||
url=amodule.params['url'],
|
||||
boot_mode=boot_mode,
|
||||
boot_loader_type=loader_type,
|
||||
hot_resize=hot_resize,
|
||||
username=amodule.params['image_username'],
|
||||
password=amodule.params['image_password'],
|
||||
account_id=self.validated_account_id,
|
||||
usernameDL=amodule.params['usernameDL'],
|
||||
passwordDL=amodule.params['passwordDL'],
|
||||
sepId=amodule.params['sepId'],
|
||||
poolName=amodule.params['poolName'],
|
||||
network_interface_naming=network_interface_naming,
|
||||
storage_policy_id=amodule.params['storage_policy_id'],
|
||||
)
|
||||
self.result['changed'] = True
|
||||
return image_facts
|
||||
|
||||
def decort_virt_image_link(self,amodule):
|
||||
# function that links an OS image to a virtual one
|
||||
self.virt_image_link(imageId=self.validated_virt_image_id, targetId=self.target_image_id)
|
||||
image_id, image_facts = decort_image.decort_virt_image_find(self, amodule)
|
||||
self.result['facts'] = decort_image.decort_image_package_facts(image_facts, amodule.check_mode)
|
||||
self.result['msg'] = ("Image '{}' linked to virtual image '{}'").format(self.target_image_id,
|
||||
decort_image.decort_image_package_facts(image_facts)['id'],)
|
||||
return image_id, image_facts
|
||||
|
||||
def decort_image_delete(self,amodule):
|
||||
# function that removes an image
|
||||
self.image_delete(imageId=amodule.image_id_delete)
|
||||
_, image_facts = decort_image._image_get_by_id(self, amodule.image_id_delete)
|
||||
self.result['facts'] = decort_image.decort_image_package_facts(image_facts, amodule.check_mode)
|
||||
return
|
||||
|
||||
def decort_virt_image_create(self,amodule):
|
||||
# function that creates a virtual image
|
||||
image_facts = self.virt_image_create(
|
||||
name=amodule.params['virt_name'],
|
||||
target_id=self.target_image_id,
|
||||
account_id=self.aparams['account_id'],
|
||||
)
|
||||
image_id, image_facts = decort_image.decort_virt_image_find(self, amodule)
|
||||
self.result['facts'] = decort_image.decort_image_package_facts(image_facts, amodule.check_mode)
|
||||
return image_id, image_facts
|
||||
|
||||
def decort_image_rename(self,amodule):
|
||||
# image renaming function
|
||||
image_facts = self.image_rename(imageId=self.validated_image_id, name=amodule.params['image_name'])
|
||||
self.result['msg'] = ("Image renamed successfully")
|
||||
image_id, image_facts = decort_image.decort_image_find(self, amodule)
|
||||
return image_id, image_facts
|
||||
|
||||
def decort_virt_image_rename(self, amodule):
|
||||
image_facts = self.image_rename(imageId=self.validated_virt_image_id,
|
||||
name=amodule.params['virt_name'])
|
||||
self.result['msg'] = ("Virtual image renamed successfully")
|
||||
image_id, image_facts = self.decort_virt_image_find(amodule)
|
||||
return image_id, image_facts
|
||||
|
||||
@staticmethod
|
||||
def decort_image_package_facts(
|
||||
arg_image_facts: dict | None,
|
||||
arg_check_mode=False,
|
||||
):
|
||||
"""Package a dictionary of OS image according to the decort_image module specification. This
|
||||
dictionary will be returned to the upstream Ansible engine at the completion of the module run.
|
||||
|
||||
@param arg_image_facts: dictionary with OS image facts as returned by API call to .../images/list
|
||||
@param arg_check_mode: boolean that tells if this Ansible module is run in check mode.
|
||||
|
||||
@return: dictionary with OS image specs populated from arg_image_facts.
|
||||
"""
|
||||
|
||||
ret_dict = dict(id=0,
|
||||
name="none",
|
||||
size=0,
|
||||
type="none",
|
||||
state="CHECK_MODE", )
|
||||
|
||||
if arg_check_mode:
|
||||
# in check mode return immediately with the default values
|
||||
return ret_dict
|
||||
|
||||
if arg_image_facts is None:
|
||||
# if void facts provided - change state value to ABSENT and return
|
||||
ret_dict['state'] = "ABSENT"
|
||||
return ret_dict
|
||||
|
||||
ret_dict['id'] = arg_image_facts['id']
|
||||
ret_dict['name'] = arg_image_facts['name']
|
||||
ret_dict['size'] = arg_image_facts['size']
|
||||
# ret_dict['arch'] = arg_image_facts['architecture']
|
||||
ret_dict['sep_id'] = arg_image_facts['sepId']
|
||||
ret_dict['pool'] = arg_image_facts['pool']
|
||||
ret_dict['state'] = arg_image_facts['status']
|
||||
ret_dict['linkto'] = arg_image_facts['linkTo']
|
||||
ret_dict['accountId'] = arg_image_facts['accountId']
|
||||
ret_dict['boot_mode'] = arg_image_facts['bootType']
|
||||
|
||||
ret_dict['boot_loader_type'] = ''
|
||||
match arg_image_facts['type']:
|
||||
case 'cdrom' | 'virtual' as type:
|
||||
ret_dict['type'] = type
|
||||
case _ as boot_loader_type:
|
||||
ret_dict['type'] = 'template'
|
||||
ret_dict['boot_loader_type'] = boot_loader_type
|
||||
|
||||
ret_dict['network_interface_naming'] = arg_image_facts[
|
||||
'networkInterfaceNaming'
|
||||
]
|
||||
ret_dict['hot_resize'] = arg_image_facts['hotResize']
|
||||
ret_dict['storage_policy_id'] = arg_image_facts['storage_policy_id']
|
||||
ret_dict['to_clean'] = arg_image_facts['to_clean']
|
||||
return ret_dict
|
||||
|
||||
@property
|
||||
def amodule_init_args(self) -> dict:
|
||||
return self.pack_amodule_init_args(
|
||||
argument_spec=dict(
|
||||
pool=dict(
|
||||
type='str',
|
||||
default='',
|
||||
),
|
||||
sep_id=dict(
|
||||
type='int',
|
||||
default=0,
|
||||
),
|
||||
account_name=dict(
|
||||
type='str',
|
||||
),
|
||||
account_id=dict(
|
||||
type='int',
|
||||
),
|
||||
image_name=dict(
|
||||
type='str',
|
||||
),
|
||||
image_id=dict(
|
||||
type='int',
|
||||
default=0,
|
||||
),
|
||||
virt_id=dict(
|
||||
type='int',
|
||||
default=0,
|
||||
),
|
||||
virt_name=dict(
|
||||
type='str',
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
default='present',
|
||||
choices=[
|
||||
'absent',
|
||||
'present',
|
||||
],
|
||||
),
|
||||
url=dict(
|
||||
type='str',
|
||||
),
|
||||
sepId=dict(
|
||||
type='int',
|
||||
default=0,
|
||||
),
|
||||
poolName=dict(
|
||||
type='str',
|
||||
),
|
||||
hot_resize=dict(
|
||||
type='bool',
|
||||
),
|
||||
image_username=dict(
|
||||
type='str',
|
||||
),
|
||||
image_password=dict(
|
||||
type='str',
|
||||
),
|
||||
usernameDL=dict(
|
||||
type='str',
|
||||
),
|
||||
passwordDL=dict(
|
||||
type='str',
|
||||
),
|
||||
boot=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
mode=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
'bios',
|
||||
'uefi',
|
||||
],
|
||||
),
|
||||
loader_type=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
'windows',
|
||||
'linux',
|
||||
'unknown',
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
network_interface_naming=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
'ens',
|
||||
'eth',
|
||||
],
|
||||
),
|
||||
storage_policy_id=dict(
|
||||
type='int',
|
||||
),
|
||||
),
|
||||
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)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
amodule = self.amodule
|
||||
if amodule.params['virt_name'] or amodule.params['virt_id']:
|
||||
|
||||
image_id, image_facts = self.decort_virt_image_find(amodule)
|
||||
if amodule.params['image_name'] or amodule.params['image_id']:
|
||||
self.target_image_id, _ = self.decort_image_find(amodule)
|
||||
else:
|
||||
self.target_image_id = 0
|
||||
if self.decort_image_package_facts(image_facts)['id'] > 0:
|
||||
self.result['facts'] = self.decort_image_package_facts(image_facts, amodule.check_mode)
|
||||
self.validated_virt_image_id = self.decort_image_package_facts(image_facts)['id']
|
||||
self.validated_virt_image_name = self.decort_image_package_facts(image_facts)['name']
|
||||
|
||||
if self.decort_image_package_facts(image_facts)['id'] == 0 and amodule.params['state'] == "present" and self.target_image_id > 0:
|
||||
image_id, image_facts = self.decort_virt_image_create(amodule)
|
||||
self.result['msg'] = ("Virtual image '{}' created").format(self.decort_image_package_facts(image_facts)['id'])
|
||||
self.result['changed'] = True
|
||||
elif self.decort_image_package_facts(image_facts)['id'] == 0 and amodule.params['state'] == "present" and self.target_image_id == 0:
|
||||
self.result['msg'] = ("Cannot find OS image")
|
||||
amodule.fail_json(**self.result)
|
||||
|
||||
if self.validated_virt_image_id:
|
||||
if (
|
||||
self.target_image_id
|
||||
and self.decort_image_package_facts(image_facts)[
|
||||
'linkto'
|
||||
] != self.target_image_id
|
||||
):
|
||||
self.decort_virt_image_link(amodule)
|
||||
self.result['changed'] = True
|
||||
amodule.exit_json(**self.result)
|
||||
if (
|
||||
amodule.params['storage_policy_id'] is not None
|
||||
and amodule.params['storage_policy_id']
|
||||
!= image_facts['storage_policy_id']
|
||||
):
|
||||
self.image_change_storage_policy(
|
||||
image_id=self.validated_virt_image_id,
|
||||
storage_policy_id=amodule.params['storage_policy_id'],
|
||||
)
|
||||
|
||||
if amodule.params['state'] == "absent" and self.validated_virt_image_id:
|
||||
amodule.image_id_delete = self.validated_virt_image_id
|
||||
image_id, image_facts = self.decort_virt_image_find(amodule)
|
||||
if image_facts['status'] != 'PURGED':
|
||||
self.decort_image_delete(amodule)
|
||||
|
||||
elif amodule.params['image_name'] or amodule.params['image_id']:
|
||||
image_id, image_facts = self.decort_image_find(amodule)
|
||||
self.validated_image_id = self.decort_image_package_facts(image_facts)['id']
|
||||
if self.decort_image_package_facts(image_facts)['id'] > 0:
|
||||
self.result['facts'] = self.decort_image_package_facts(image_facts, amodule.check_mode)
|
||||
|
||||
if amodule.params['state'] == "present" and self.validated_image_id == 0 and amodule.params['image_name'] and amodule.params['url']:
|
||||
self.decort_image_create(amodule)
|
||||
self.result['changed'] = True
|
||||
image_id, image_facts = self.decort_image_find(amodule)
|
||||
self.result['msg'] = ("OS image '{}' created").format(self.decort_image_package_facts(image_facts)['id'])
|
||||
self.result['facts'] = self.decort_image_package_facts(image_facts, amodule.check_mode)
|
||||
self.validated_image_id = self.decort_image_package_facts(image_facts)['id']
|
||||
|
||||
elif amodule.params['state'] == "absent" and self.validated_image_id:
|
||||
amodule.image_id_delete = self.validated_image_id
|
||||
image_id, image_facts = self.decort_image_find(amodule)
|
||||
if image_facts['status'] != 'DESTROYED':
|
||||
self.decort_image_delete(amodule)
|
||||
|
||||
if self.validated_image_id:
|
||||
if (
|
||||
amodule.params['storage_policy_id'] is not None
|
||||
and amodule.params['storage_policy_id']
|
||||
!= image_facts['storage_policy_id']
|
||||
):
|
||||
self.image_change_storage_policy(
|
||||
image_id=self.validated_image_id,
|
||||
storage_policy_id=amodule.params['storage_policy_id'],
|
||||
)
|
||||
|
||||
if self.result['failed'] == True:
|
||||
# we failed to find the specified image - fail the module
|
||||
self.result['changed'] = False
|
||||
amodule.fail_json(**self.result)
|
||||
else:
|
||||
if self.validated_image_id:
|
||||
_, image_facts = self.decort_image_find(amodule=amodule)
|
||||
elif self.validated_virt_image_id:
|
||||
_, image_facts = self.decort_virt_image_find(amodule=amodule)
|
||||
self.result['facts'] = self.decort_image_package_facts(
|
||||
arg_image_facts=image_facts,
|
||||
arg_check_mode=amodule.check_mode,
|
||||
)
|
||||
|
||||
amodule.exit_json(**self.result)
|
||||
|
||||
|
||||
def main():
|
||||
decort_image().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
162
library/decort_image_list.py
Normal file
162
library/decort_image_list.py
Normal file
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_image_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortImageList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
bootable=dict(
|
||||
type='bool',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
enabled=dict(
|
||||
type='bool',
|
||||
),
|
||||
hot_resize=dict(
|
||||
type='bool',
|
||||
),
|
||||
size_gb=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
public=dict(
|
||||
type='bool',
|
||||
),
|
||||
sep_id=dict(
|
||||
type='int',
|
||||
),
|
||||
sep_name=dict(
|
||||
type='str',
|
||||
),
|
||||
sep_pool_name=dict(
|
||||
type='str',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=sdk_types.ImageStatus._member_names_,
|
||||
),
|
||||
type=dict(
|
||||
type='str',
|
||||
choices=sdk_types.ImageType._member_names_,
|
||||
),
|
||||
storage_policy_id=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=(
|
||||
sdk_types.ImageForListAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
aparam_status: str | None = aparam_filter['status']
|
||||
aparam_type: str | None = aparam_filter['type']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.ImageForListAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.ca.image.list(
|
||||
bootable=aparam_filter['bootable'],
|
||||
enabled=aparam_filter['enabled'],
|
||||
hot_resize=aparam_filter['hot_resize'],
|
||||
id=aparam_filter['id'],
|
||||
name=aparam_filter['name'],
|
||||
public=aparam_filter['public'],
|
||||
sep_id=aparam_filter['sep_id'],
|
||||
sep_name=aparam_filter['sep_name'],
|
||||
sep_pool_name=aparam_filter['sep_pool_name'],
|
||||
size_gb=aparam_filter['size_gb'],
|
||||
status=(
|
||||
sdk_types.ImageStatus[aparam_status]
|
||||
if aparam_status else None
|
||||
),
|
||||
storage_policy_id=aparam_filter['storage_policy_id'],
|
||||
type=(
|
||||
sdk_types.ImageType[aparam_type]
|
||||
if aparam_type else None
|
||||
),
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortImageList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -25,6 +25,7 @@ class DecortJWT(DecortController):
|
||||
|
||||
return amodule_init_args
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.result['jwt'] = self.jwt
|
||||
self.amodule.exit_json(**self.result)
|
||||
|
||||
@@ -33,10 +33,10 @@ class decort_k8s(DecortController):
|
||||
'taints': [],
|
||||
'annotations': [],
|
||||
'ci_user_data': {},
|
||||
'chipset': 'i440fx',
|
||||
'chipset': 'Q35',
|
||||
}
|
||||
|
||||
if arg_amodule.params['name'] == "" and arg_amodule.params['id'] is None:
|
||||
if arg_amodule.params['name'] is None and arg_amodule.params['id'] is None:
|
||||
self.result['failed'] = True
|
||||
self.result['changed'] = False
|
||||
self.result['msg'] = "Cannot manage k8s cluster when its ID is 0 and name is empty."
|
||||
@@ -158,7 +158,7 @@ class decort_k8s(DecortController):
|
||||
def create(self):
|
||||
master_chipset = self.amodule.params['master_chipset']
|
||||
if master_chipset is None:
|
||||
master_chipset = 'i440fx'
|
||||
master_chipset = 'Q35'
|
||||
|
||||
target_wgs = deepcopy(self.amodule.params['workers'])
|
||||
for wg in target_wgs:
|
||||
@@ -166,34 +166,36 @@ class decort_k8s(DecortController):
|
||||
if wg[param] is None:
|
||||
wg[param] = default_value
|
||||
|
||||
k8s_id = self.k8s_provision(self.amodule.params['name'],
|
||||
self.amodule.params['k8ci_id'],
|
||||
self.amodule.params['rg_id'],
|
||||
self.amodule.params['vins_id'],
|
||||
self.amodule.params['network_plugin'],
|
||||
self.amodule.params['master_count'],
|
||||
self.amodule.params['master_cpu'],
|
||||
self.amodule.params['master_ram'],
|
||||
self.amodule.params['master_disk'],
|
||||
self.amodule.params['master_sepid'],
|
||||
self.amodule.params['master_pool'],
|
||||
target_wgs[0],
|
||||
self.amodule.params['extnet_id'],
|
||||
self.amodule.params['with_lb'],
|
||||
self.amodule.params['ha_lb'],
|
||||
self.amodule.params['additionalSANs'],
|
||||
self.amodule.params['init_conf'],
|
||||
self.amodule.params['cluster_conf'],
|
||||
self.amodule.params['kublet_conf'],
|
||||
self.amodule.params['kubeproxy_conf'],
|
||||
self.amodule.params['join_conf'],
|
||||
self.amodule.params['oidc_cert'],
|
||||
self.amodule.params['description'],
|
||||
self.amodule.params['extnet_only'],
|
||||
master_chipset,
|
||||
lb_sysctl=self.amodule.params['lb_sysctl'],
|
||||
zone_id=self.aparams['zone_id'],
|
||||
)
|
||||
k8s_id = self.k8s_provision(
|
||||
self.amodule.params['name'],
|
||||
self.amodule.params['k8ci_id'],
|
||||
self.amodule.params['rg_id'],
|
||||
self.amodule.params['vins_id'],
|
||||
self.amodule.params['network_plugin'],
|
||||
self.amodule.params['master_count'],
|
||||
self.amodule.params['master_cpu'],
|
||||
self.amodule.params['master_ram'],
|
||||
self.amodule.params['master_disk'],
|
||||
self.amodule.params['master_sepid'],
|
||||
self.amodule.params['master_pool'],
|
||||
target_wgs[0],
|
||||
self.amodule.params['extnet_id'],
|
||||
self.amodule.params['with_lb'],
|
||||
self.amodule.params['ha_lb'],
|
||||
self.amodule.params['additionalSANs'],
|
||||
self.amodule.params['init_conf'],
|
||||
self.amodule.params['cluster_conf'],
|
||||
self.amodule.params['kublet_conf'],
|
||||
self.amodule.params['kubeproxy_conf'],
|
||||
self.amodule.params['join_conf'],
|
||||
self.amodule.params['oidc_cert'],
|
||||
self.amodule.params['description'],
|
||||
self.amodule.params['extnet_only'],
|
||||
master_chipset=master_chipset,
|
||||
lb_sysctl=self.amodule.params['lb_sysctl'],
|
||||
zone_id=self.aparams['zone_id'],
|
||||
storage_policy_id=self.aparams['storage_policy_id'],
|
||||
)
|
||||
|
||||
if not k8s_id:
|
||||
if k8s_id == 0:
|
||||
@@ -241,6 +243,12 @@ class decort_k8s(DecortController):
|
||||
)
|
||||
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:
|
||||
# K8s info updating
|
||||
self.k8s_info = self.k8s_get_by_id(k8s_id=self.k8s_id)
|
||||
@@ -275,9 +283,6 @@ class decort_k8s(DecortController):
|
||||
type='str',
|
||||
default='',
|
||||
),
|
||||
quotas=dict(
|
||||
type='dict',
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
default='present',
|
||||
@@ -296,7 +301,6 @@ class decort_k8s(DecortController):
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
default='',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
@@ -448,6 +452,9 @@ class decort_k8s(DecortController):
|
||||
zone_id=dict(
|
||||
type='int',
|
||||
),
|
||||
storage_policy_id=dict(
|
||||
type='int',
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
required_one_of=[
|
||||
@@ -499,6 +506,32 @@ class decort_k8s(DecortController):
|
||||
'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:
|
||||
self.exit(fail=True)
|
||||
|
||||
@@ -540,71 +573,96 @@ class decort_k8s(DecortController):
|
||||
if self.check_aparam_zone_id() is False:
|
||||
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:
|
||||
self.exit(fail=True)
|
||||
|
||||
|
||||
def main():
|
||||
subj = decort_k8s()
|
||||
amodule = subj.amodule
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
amodule = self.amodule
|
||||
|
||||
if subj.amodule.check_mode:
|
||||
subj.result['changed'] = False
|
||||
if subj.k8s_id:
|
||||
# cluster is found - package facts and report success to Ansible
|
||||
subj.result['failed'] = False
|
||||
subj.result['facts'] = subj.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**subj.result)
|
||||
# we exit the module at this point
|
||||
else:
|
||||
subj.result['failed'] = True
|
||||
subj.result['msg'] = ("Cannot locate K8s cluster name '{}'. "
|
||||
"RG ID {}").format(amodule.params['name'],
|
||||
amodule.params['rg_id'],)
|
||||
amodule.fail_json(**subj.result)
|
||||
|
||||
if subj.k8s_id:
|
||||
if subj.k8s_info['status'] in ("DELETING","DESTROYNG","CREATING","DESTROYING",
|
||||
"ENABLING","DISABLING","RESTORING","MODELED"):
|
||||
subj.error()
|
||||
elif subj.k8s_info['status'] == "DELETED":
|
||||
if amodule.params['state'] in (
|
||||
'disabled', 'enabled', 'present', 'started', 'stopped'
|
||||
):
|
||||
subj.k8s_restore(subj.k8s_id)
|
||||
subj.action(disared_state=amodule.params['state'],
|
||||
preupdate=True)
|
||||
if amodule.params['state'] == 'absent':
|
||||
if amodule.params['permanent']:
|
||||
subj.destroy()
|
||||
else:
|
||||
subj.nop()
|
||||
elif subj.k8s_info['status'] in ('ENABLED', 'DISABLED'):
|
||||
if amodule.params['state'] == 'absent':
|
||||
subj.destroy()
|
||||
if self.amodule.check_mode:
|
||||
self.result['changed'] = False
|
||||
if self.k8s_id:
|
||||
# cluster is found - package facts and report success to Ansible
|
||||
self.result['failed'] = False
|
||||
self.result['facts'] = self.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**self.result)
|
||||
# we exit the module at this point
|
||||
else:
|
||||
subj.action(disared_state=amodule.params['state'])
|
||||
elif subj.k8s_info['status'] == "DESTROYED":
|
||||
if amodule.params['state'] in ('present','enabled'):
|
||||
subj.create()
|
||||
if amodule.params['state'] == 'absent':
|
||||
subj.nop()
|
||||
else:
|
||||
if amodule.params['state'] == 'absent':
|
||||
subj.nop()
|
||||
if amodule.params['state'] in ('present','started'):
|
||||
subj.create()
|
||||
elif amodule.params['state'] in ('stopped', 'disabled','enabled'):
|
||||
subj.error()
|
||||
|
||||
if subj.result['failed']:
|
||||
amodule.fail_json(**subj.result)
|
||||
else:
|
||||
if subj.k8s_should_exist:
|
||||
subj.result['facts'] = subj.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**subj.result)
|
||||
else:
|
||||
amodule.exit_json(**subj.result)
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = ("Cannot locate K8s cluster name '{}'. "
|
||||
"RG ID {}").format(amodule.params['name'],
|
||||
amodule.params['rg_id'],)
|
||||
amodule.fail_json(**self.result)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if self.k8s_id:
|
||||
if self.k8s_info['status'] in ("DELETING","DESTROYNG","CREATING","DESTROYING",
|
||||
"ENABLING","DISABLING","RESTORING","MODELED"):
|
||||
self.error()
|
||||
elif self.k8s_info['status'] == "DELETED":
|
||||
if amodule.params['state'] in (
|
||||
'disabled', 'enabled', 'present', 'started', 'stopped'
|
||||
):
|
||||
self.k8s_restore(self.k8s_id)
|
||||
self.action(disared_state=amodule.params['state'],
|
||||
preupdate=True)
|
||||
if amodule.params['state'] == 'absent':
|
||||
if amodule.params['permanent']:
|
||||
self.destroy()
|
||||
else:
|
||||
self.nop()
|
||||
elif self.k8s_info['status'] in ('ENABLED', 'DISABLED'):
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.destroy()
|
||||
else:
|
||||
self.action(disared_state=amodule.params['state'])
|
||||
elif self.k8s_info['status'] == "DESTROYED":
|
||||
if amodule.params['state'] in ('present','enabled'):
|
||||
self.create()
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.nop()
|
||||
else:
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.nop()
|
||||
if amodule.params['state'] in ('present','started'):
|
||||
self.create()
|
||||
elif amodule.params['state'] in ('stopped', 'disabled','enabled'):
|
||||
self.error()
|
||||
|
||||
if self.result['failed']:
|
||||
amodule.fail_json(**self.result)
|
||||
else:
|
||||
if self.k8s_should_exist:
|
||||
self.result['facts'] = self.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**self.result)
|
||||
else:
|
||||
amodule.exit_json(**self.result)
|
||||
|
||||
|
||||
def main():
|
||||
decort_k8s().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -42,8 +42,8 @@ class decort_lb(DecortController):
|
||||
if not self.lb_id:
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = "Specified LB ID {} not found."\
|
||||
.format(arg_amodule.params['lb _id'])
|
||||
self.fail_json(**self.result)
|
||||
.format(arg_amodule.params['lb_id'])
|
||||
self.amodule.fail_json(**self.result)
|
||||
self.rg_id = self.lb_facts['rgId']
|
||||
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="")
|
||||
if not self.rg_id:
|
||||
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.acc_id = self.rg_facts['accountId']
|
||||
|
||||
elif arg_amodule.params['account_id'] or arg_amodule.params['account_name'] != "":
|
||||
|
||||
if not arg_amodule.params['rg_name']:
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = ("RG name must be specified with account present")
|
||||
@@ -163,8 +162,9 @@ class decort_lb(DecortController):
|
||||
|
||||
def delete(self):
|
||||
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
|
||||
|
||||
def nop(self):
|
||||
"""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
|
||||
@@ -252,10 +252,6 @@ class decort_lb(DecortController):
|
||||
type='int',
|
||||
default=0,
|
||||
),
|
||||
ext_ip_addr=dict(
|
||||
type='str',
|
||||
default='',
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
@@ -365,56 +361,60 @@ class decort_lb(DecortController):
|
||||
if check_errors:
|
||||
self.exit(fail=True)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
amodule = self.amodule
|
||||
if self.lb_id:
|
||||
if self.lb_facts['status'] in ["MODELED", "DISABLING", "ENABLING", "DELETING","DESTROYING","RESTORING"]:
|
||||
self.result['failed'] = True
|
||||
self.result['changed'] = False
|
||||
self.result['msg'] = ("No change can be done for existing LB ID {} because of its current "
|
||||
"status '{}'").format(self.lb_id, self.lb_facts['status'])
|
||||
elif self.lb_facts['status'] in ('DISABLED', 'ENABLED', 'CREATED'):
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.delete()
|
||||
else:
|
||||
self.action(d_state=amodule.params['state'])
|
||||
elif self.lb_facts['status'] == "DELETED":
|
||||
if amodule.params['state'] == 'present':
|
||||
self.action(restore=True)
|
||||
elif amodule.params['state'] == 'enabled':
|
||||
self.action(d_state='enabled', restore=True)
|
||||
elif (amodule.params['state'] == 'absent' and
|
||||
amodule.params['permanently']):
|
||||
self.delete()
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
self.error()
|
||||
elif self.lb_facts['status'] == "DESTROYED":
|
||||
if amodule.params['state'] in ('present', 'enabled'):
|
||||
self.create()
|
||||
elif amodule.params['state'] == 'absent':
|
||||
self.nop()
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
self.error()
|
||||
else:
|
||||
state = amodule.params['state']
|
||||
if state is None:
|
||||
state = 'present'
|
||||
if state == 'absent':
|
||||
self.nop()
|
||||
elif state in ('present', 'enabled', 'stopped', 'started'):
|
||||
self.create()
|
||||
elif state == 'disabled':
|
||||
self.error()
|
||||
|
||||
if self.result['failed']:
|
||||
amodule.fail_json(**self.result)
|
||||
else:
|
||||
if self.result['changed']:
|
||||
_, self.lb_facts = self.lb_find(lb_id=self.lb_id)
|
||||
self.result['facts'] = self.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**self.result)
|
||||
|
||||
|
||||
def main():
|
||||
decon = decort_lb()
|
||||
amodule = decon.amodule
|
||||
if decon.lb_id:
|
||||
if decon.lb_facts['status'] in ["MODELED", "DISABLING", "ENABLING", "DELETING","DESTROYING","RESTORING"]:
|
||||
decon.result['failed'] = True
|
||||
decon.result['changed'] = False
|
||||
decon.result['msg'] = ("No change can be done for existing LB ID {} because of its current "
|
||||
"status '{}'").format(decon.lb_id, decon.lb_facts['status'])
|
||||
elif decon.lb_facts['status'] in ('DISABLED', 'ENABLED', 'CREATED'):
|
||||
if amodule.params['state'] == 'absent':
|
||||
decon.delete()
|
||||
else:
|
||||
decon.action(d_state=amodule.params['state'])
|
||||
elif decon.lb_facts['status'] == "DELETED":
|
||||
if amodule.params['state'] == 'present':
|
||||
decon.action(restore=True)
|
||||
elif amodule.params['state'] == 'enabled':
|
||||
decon.action(d_state='enabled', restore=True)
|
||||
elif (amodule.params['state'] == 'absent' and
|
||||
amodule.params['permanently']):
|
||||
decon.delete()
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
decon.error()
|
||||
elif decon.lb_facts['status'] == "DESTROYED":
|
||||
if amodule.params['state'] in ('present', 'enabled'):
|
||||
decon.create()
|
||||
elif amodule.params['state'] == 'absent':
|
||||
decon.nop()
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
decon.error()
|
||||
else:
|
||||
state = amodule.params['state']
|
||||
if state is None:
|
||||
state = 'present'
|
||||
if state == 'absent':
|
||||
decon.nop()
|
||||
elif state in ('present', 'enabled', 'stopped', 'started'):
|
||||
decon.create()
|
||||
elif state == 'disabled':
|
||||
decon.error()
|
||||
decort_lb().run()
|
||||
|
||||
if decon.result['failed']:
|
||||
amodule.fail_json(**decon.result)
|
||||
else:
|
||||
if decon.result['changed'] and amodule.params['state'] != 'absent':
|
||||
_, decon.lb_facts = decon.lb_find(decon.lb_id)
|
||||
if decon.lb_id:
|
||||
decon.result['facts'] = decon.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**decon.result)
|
||||
if __name__ == "__main__":
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -4,397 +4,59 @@ DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_osimage
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home).
|
||||
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.basic import env_fallback
|
||||
|
||||
from ansible.module_utils.decort_utils import *
|
||||
|
||||
|
||||
class decort_osimage(DecortController):
|
||||
def __init__(self):
|
||||
super(decort_osimage, self).__init__(AnsibleModule(**self.amodule_init_args))
|
||||
amodule = self.amodule
|
||||
|
||||
self.validated_image_id = 0
|
||||
self.validated_virt_image_id = 0
|
||||
self.validated_image_name = amodule.params['image_name']
|
||||
self.validated_virt_image_name = None
|
||||
self.validated_virt_image_id = amodule.params['virt_id']
|
||||
if amodule.params['account_name']:
|
||||
self.validated_account_id, _ = self.account_find(amodule.params['account_name'])
|
||||
else:
|
||||
self.validated_account_id = amodule.params['account_id']
|
||||
|
||||
if self.validated_account_id == 0:
|
||||
# we failed either to find or access the specified account - fail the module
|
||||
self.result['failed'] = True
|
||||
self.result['changed'] = False
|
||||
self.result['msg'] = ("Cannot find account '{}'").format(amodule.params['account_name'])
|
||||
amodule.fail_json(**self.result)
|
||||
|
||||
|
||||
if amodule.params['virt_id'] != 0 and amodule.params['virt_name']:
|
||||
self.validated_virt_image_id, image_facts =\
|
||||
self.decort_virt_image_find(amodule)
|
||||
if (self.validated_virt_image_id and
|
||||
amodule.params['virt_name'] != image_facts['name']):
|
||||
self.decort_virt_image_rename(amodule)
|
||||
self.result['msg'] = 'Virtual image renamed successfully'
|
||||
elif amodule.params['image_id'] != 0 and amodule.params['image_name']:
|
||||
self.validated_image_id, image_facts = self.decort_image_find(amodule)
|
||||
if (self.validated_image_id and
|
||||
amodule.params['image_name'] != image_facts['name']):
|
||||
decort_osimage.decort_image_rename(self,amodule)
|
||||
self.result['msg'] = ("Image renamed successfully")
|
||||
|
||||
|
||||
|
||||
def decort_image_find(self, amodule):
|
||||
# function that finds the OS image
|
||||
image_id, image_facts = self.image_find(image_id=amodule.params['image_id'], image_name=self.validated_image_name,
|
||||
account_id=self.validated_account_id, rg_id=0,
|
||||
sepid=amodule.params['sep_id'],
|
||||
pool=amodule.params['pool'])
|
||||
return image_id, image_facts
|
||||
|
||||
def decort_virt_image_find(self, amodule):
|
||||
# function that finds a virtual image
|
||||
image_id, image_facts = self.virt_image_find(image_id=amodule.params['virt_id'],
|
||||
account_id=self.validated_account_id, rg_id=0,
|
||||
sepid=amodule.params['sep_id'],
|
||||
virt_name=amodule.params['virt_name'],
|
||||
pool=amodule.params['pool'])
|
||||
return image_id, image_facts
|
||||
|
||||
|
||||
|
||||
def decort_image_create(self,amodule):
|
||||
aparam_boot = self.aparams['boot']
|
||||
boot_mode = 'bios'
|
||||
loader_type = 'unknown'
|
||||
if aparam_boot is not None:
|
||||
if aparam_boot['mode'] is None:
|
||||
self.message(
|
||||
msg=self.MESSAGES.default_value_used(
|
||||
param_name='boot.mode',
|
||||
default_value=boot_mode
|
||||
),
|
||||
warning=True,
|
||||
)
|
||||
else:
|
||||
boot_mode = aparam_boot['mode']
|
||||
|
||||
if aparam_boot['loader_type'] is None:
|
||||
self.message(
|
||||
msg=self.MESSAGES.default_value_used(
|
||||
param_name='boot.loader_type',
|
||||
default_value=loader_type
|
||||
),
|
||||
warning=True,
|
||||
)
|
||||
else:
|
||||
loader_type = aparam_boot['loader_type']
|
||||
|
||||
network_interface_naming = self.aparams['network_interface_naming']
|
||||
if network_interface_naming is None:
|
||||
network_interface_naming = 'ens'
|
||||
self.message(
|
||||
msg=self.MESSAGES.default_value_used(
|
||||
param_name='network_interface_naming',
|
||||
default_value=network_interface_naming
|
||||
),
|
||||
warning=True,
|
||||
)
|
||||
|
||||
hot_resize = self.aparams['hot_resize']
|
||||
if hot_resize is None:
|
||||
hot_resize = False
|
||||
self.message(
|
||||
msg=self.MESSAGES.default_value_used(
|
||||
param_name='hot_resize',
|
||||
default_value=hot_resize
|
||||
),
|
||||
warning=True,
|
||||
)
|
||||
|
||||
# function that creates OS image
|
||||
image_facts = self.image_create(img_name=self.validated_image_name,
|
||||
url=amodule.params['url'],
|
||||
gid=amodule.params['gid'],
|
||||
boot_mode=boot_mode,
|
||||
boot_loader_type=loader_type,
|
||||
hot_resize=hot_resize,
|
||||
username=amodule.params['image_username'],
|
||||
password=amodule.params['image_password'],
|
||||
account_id=self.validated_account_id,
|
||||
usernameDL=amodule.params['usernameDL'],
|
||||
passwordDL=amodule.params['passwordDL'],
|
||||
sepId=amodule.params['sepId'],
|
||||
poolName=amodule.params['poolName'],
|
||||
drivers=amodule.params['drivers'],
|
||||
network_interface_naming=network_interface_naming)
|
||||
self.result['changed'] = True
|
||||
return image_facts
|
||||
|
||||
def decort_virt_image_link(self,amodule):
|
||||
# function that links an OS image to a virtual one
|
||||
self.virt_image_link(imageId=self.validated_virt_image_id, targetId=self.target_image_id)
|
||||
image_id, image_facts = decort_osimage.decort_virt_image_find(self, amodule)
|
||||
self.result['facts'] = decort_osimage.decort_osimage_package_facts(image_facts, amodule.check_mode)
|
||||
self.result['msg'] = ("Image '{}' linked to virtual image '{}'").format(self.target_image_id,
|
||||
decort_osimage.decort_osimage_package_facts(image_facts)['id'],)
|
||||
return image_id, image_facts
|
||||
|
||||
def decort_image_delete(self,amodule):
|
||||
# function that removes an image
|
||||
self.image_delete(imageId=amodule.image_id_delete)
|
||||
self.result['changed'] = True
|
||||
self.result['msg'] = ("Image '{}' deleted").format(amodule.image_id_delete)
|
||||
|
||||
def decort_virt_image_create(self,amodule):
|
||||
# function that creates a virtual image
|
||||
image_facts = self.virt_image_create(
|
||||
name=amodule.params['virt_name'],
|
||||
target_id=self.target_image_id,
|
||||
account_id=self.aparams['account_id'],
|
||||
)
|
||||
image_id, image_facts = decort_osimage.decort_virt_image_find(self, amodule)
|
||||
self.result['facts'] = decort_osimage.decort_osimage_package_facts(image_facts, amodule.check_mode)
|
||||
return image_id, image_facts
|
||||
|
||||
def decort_image_rename(self,amodule):
|
||||
# image renaming function
|
||||
image_facts = self.image_rename(imageId=self.validated_image_id, name=amodule.params['image_name'])
|
||||
self.result['msg'] = ("Image renamed successfully")
|
||||
image_id, image_facts = decort_osimage.decort_image_find(self, amodule)
|
||||
return image_id, image_facts
|
||||
|
||||
def decort_virt_image_rename(self, amodule):
|
||||
image_facts = self.image_rename(imageId=self.validated_virt_image_id,
|
||||
name=amodule.params['virt_name'])
|
||||
self.result['msg'] = ("Virtual image renamed successfully")
|
||||
image_id, image_facts = self.decort_virt_image_find(amodule)
|
||||
return image_id, image_facts
|
||||
|
||||
@staticmethod
|
||||
def decort_osimage_package_facts(
|
||||
arg_osimage_facts: dict | None,
|
||||
arg_check_mode=False,
|
||||
):
|
||||
"""Package a dictionary of OS image according to the decort_osimage module specification. This
|
||||
dictionary will be returned to the upstream Ansible engine at the completion of the module run.
|
||||
|
||||
@param arg_osimage_facts: dictionary with OS image facts as returned by API call to .../images/list
|
||||
@param arg_check_mode: boolean that tells if this Ansible module is run in check mode.
|
||||
|
||||
@return: dictionary with OS image specs populated from arg_osimage_facts.
|
||||
"""
|
||||
|
||||
ret_dict = dict(id=0,
|
||||
name="none",
|
||||
size=0,
|
||||
type="none",
|
||||
state="CHECK_MODE", )
|
||||
|
||||
if arg_check_mode:
|
||||
# in check mode return immediately with the default values
|
||||
return ret_dict
|
||||
|
||||
if arg_osimage_facts is None:
|
||||
# if void facts provided - change state value to ABSENT and return
|
||||
ret_dict['state'] = "ABSENT"
|
||||
return ret_dict
|
||||
|
||||
ret_dict['id'] = arg_osimage_facts['id']
|
||||
ret_dict['name'] = arg_osimage_facts['name']
|
||||
ret_dict['size'] = arg_osimage_facts['size']
|
||||
# ret_dict['arch'] = arg_osimage_facts['architecture']
|
||||
ret_dict['sep_id'] = arg_osimage_facts['sepId']
|
||||
ret_dict['pool'] = arg_osimage_facts['pool']
|
||||
ret_dict['state'] = arg_osimage_facts['status']
|
||||
ret_dict['linkto'] = arg_osimage_facts['linkTo']
|
||||
ret_dict['accountId'] = arg_osimage_facts['accountId']
|
||||
ret_dict['boot_mode'] = arg_osimage_facts['bootType']
|
||||
|
||||
ret_dict['boot_loader_type'] = ''
|
||||
match arg_osimage_facts['type']:
|
||||
case 'cdrom' | 'virtual' as type:
|
||||
ret_dict['type'] = type
|
||||
case _ as boot_loader_type:
|
||||
ret_dict['type'] = 'template'
|
||||
ret_dict['boot_loader_type'] = boot_loader_type
|
||||
|
||||
ret_dict['network_interface_naming'] = arg_osimage_facts[
|
||||
'networkInterfaceNaming'
|
||||
]
|
||||
ret_dict['hot_resize'] = arg_osimage_facts['hotResize']
|
||||
return ret_dict
|
||||
|
||||
@property
|
||||
def amodule_init_args(self) -> dict:
|
||||
return self.pack_amodule_init_args(
|
||||
argument_spec=dict(
|
||||
pool=dict(
|
||||
type='str',
|
||||
default='',
|
||||
),
|
||||
sep_id=dict(
|
||||
type='int',
|
||||
default=0,
|
||||
),
|
||||
account_name=dict(
|
||||
type='str',
|
||||
),
|
||||
account_id=dict(
|
||||
type='int',
|
||||
),
|
||||
image_name=dict(
|
||||
type='str',
|
||||
),
|
||||
image_id=dict(
|
||||
type='int',
|
||||
default=0,
|
||||
),
|
||||
virt_id=dict(
|
||||
type='int',
|
||||
default=0,
|
||||
),
|
||||
virt_name=dict(
|
||||
type='str',
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
default='present',
|
||||
choices=[
|
||||
'absent',
|
||||
'present',
|
||||
],
|
||||
),
|
||||
drivers=dict(
|
||||
type='str',
|
||||
default='KVM_X86',
|
||||
),
|
||||
url=dict(
|
||||
type='str',
|
||||
),
|
||||
gid=dict(
|
||||
type='int',
|
||||
default=0,
|
||||
),
|
||||
sepId=dict(
|
||||
type='int',
|
||||
default=0,
|
||||
),
|
||||
poolName=dict(
|
||||
type='str',
|
||||
),
|
||||
hot_resize=dict(
|
||||
type='bool',
|
||||
),
|
||||
image_username=dict(
|
||||
type='str',
|
||||
),
|
||||
image_password=dict(
|
||||
type='str',
|
||||
),
|
||||
usernameDL=dict(
|
||||
type='str',
|
||||
),
|
||||
passwordDL=dict(
|
||||
type='str',
|
||||
),
|
||||
boot=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
mode=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
'bios',
|
||||
'uefi',
|
||||
],
|
||||
),
|
||||
loader_type=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
'windows',
|
||||
'linux',
|
||||
'unknown',
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
network_interface_naming=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
'ens',
|
||||
'eth',
|
||||
],
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
def main():
|
||||
decon = decort_osimage()
|
||||
amodule = decon.amodule
|
||||
if amodule.params['virt_name'] or amodule.params['virt_id']:
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
app_id=dict(type='raw'),
|
||||
app_secret=dict(type='raw'),
|
||||
authenticator=dict(type='raw'),
|
||||
controller_url=dict(type='raw'),
|
||||
domain=dict(type='raw'),
|
||||
jwt=dict(type='raw'),
|
||||
oauth2_url=dict(type='raw'),
|
||||
password=dict(type='raw'),
|
||||
username=dict(type='raw'),
|
||||
verify_ssl=dict(type='raw'),
|
||||
ignore_api_compatibility=dict(type='raw'),
|
||||
ignore_sdk_version_check=dict(type='raw'),
|
||||
pool=dict(type='raw'),
|
||||
sep_id=dict(type='raw'),
|
||||
account_name=dict(type='raw'),
|
||||
account_id=dict(type='raw'),
|
||||
image_name=dict(type='raw'),
|
||||
image_id=dict(type='raw'),
|
||||
virt_id=dict(type='raw'),
|
||||
virt_name=dict(type='raw'),
|
||||
state=dict(type='raw'),
|
||||
url=dict(type='raw'),
|
||||
sepId=dict(type='raw'),
|
||||
poolName=dict(type='raw'),
|
||||
hot_resize=dict(type='raw'),
|
||||
image_username=dict(type='raw'),
|
||||
image_password=dict(type='raw'),
|
||||
usernameDL=dict(type='raw'),
|
||||
passwordDL=dict(type='raw'),
|
||||
boot=dict(type='raw'),
|
||||
network_interface_naming=dict(type='raw'),
|
||||
storage_policy_id=dict(type='raw'),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
image_id, image_facts = decort_osimage.decort_virt_image_find(decon, amodule)
|
||||
if amodule.params['image_name'] or amodule.params['image_id']:
|
||||
decon.target_image_id, _ = decort_osimage.decort_image_find(decon, amodule)
|
||||
else:
|
||||
decon.target_image_id = 0
|
||||
if decort_osimage.decort_osimage_package_facts(image_facts)['id'] > 0:
|
||||
decon.result['facts'] = decort_osimage.decort_osimage_package_facts(image_facts, amodule.check_mode)
|
||||
decon.validated_virt_image_id = decort_osimage.decort_osimage_package_facts(image_facts)['id']
|
||||
decon.validated_virt_image_name = decort_osimage.decort_osimage_package_facts(image_facts)['name']
|
||||
module.fail_json(
|
||||
msg=(
|
||||
'The module "decort_osimage" has been renamed to "decort_image". '
|
||||
'Please update your playbook to use "decort_image" '
|
||||
'instead of "decort_osimage".'
|
||||
),
|
||||
)
|
||||
|
||||
if decort_osimage.decort_osimage_package_facts(image_facts)['id'] == 0 and amodule.params['state'] == "present" and decon.target_image_id > 0:
|
||||
image_id, image_facts = decort_osimage.decort_virt_image_create(decon,amodule)
|
||||
decon.result['msg'] = ("Virtual image '{}' created").format(decort_osimage.decort_osimage_package_facts(image_facts)['id'])
|
||||
decon.result['changed'] = True
|
||||
elif decort_osimage.decort_osimage_package_facts(image_facts)['id'] == 0 and amodule.params['state'] == "present" and decon.target_image_id == 0:
|
||||
decon.result['msg'] = ("Cannot find OS image")
|
||||
amodule.fail_json(**decon.result)
|
||||
|
||||
if decon.validated_virt_image_id and decon.target_image_id:
|
||||
if decort_osimage.decort_osimage_package_facts(image_facts)['linkto'] != decon.target_image_id:
|
||||
decort_osimage.decort_virt_image_link(decon,amodule)
|
||||
decon.result['changed'] = True
|
||||
amodule.exit_json(**decon.result)
|
||||
|
||||
if decon.validated_virt_image_id > 0 and amodule.params['state'] == "absent":
|
||||
amodule.image_id_delete = decon.validated_virt_image_id
|
||||
decort_osimage.decort_image_delete(decon, amodule)
|
||||
|
||||
elif amodule.params['image_name'] or amodule.params['image_id']:
|
||||
image_id, image_facts = decort_osimage.decort_image_find(decon, amodule)
|
||||
decon.validated_image_id = decort_osimage.decort_osimage_package_facts(image_facts)['id']
|
||||
if decort_osimage.decort_osimage_package_facts(image_facts)['id'] > 0:
|
||||
decon.result['facts'] = decort_osimage.decort_osimage_package_facts(image_facts, amodule.check_mode)
|
||||
|
||||
if amodule.params['state'] == "present" and decon.validated_image_id == 0 and amodule.params['image_name'] and amodule.params['url']:
|
||||
decort_osimage.decort_image_create(decon,amodule)
|
||||
decon.result['changed'] = True
|
||||
image_id, image_facts = decort_osimage.decort_image_find(decon, amodule)
|
||||
decon.result['msg'] = ("OS image '{}' created").format(decort_osimage.decort_osimage_package_facts(image_facts)['id'])
|
||||
decon.result['facts'] = decort_osimage.decort_osimage_package_facts(image_facts, amodule.check_mode)
|
||||
decon.validated_image_id = decort_osimage.decort_osimage_package_facts(image_facts)['id']
|
||||
|
||||
elif amodule.params['state'] == "absent" and decon.validated_image_id:
|
||||
amodule.image_id_delete = decon.validated_image_id
|
||||
decort_osimage.decort_image_delete(decon,amodule)
|
||||
|
||||
if decon.result['failed'] == True:
|
||||
# we failed to find the specified image - fail the module
|
||||
decon.result['changed'] = False
|
||||
amodule.fail_json(**decon.result)
|
||||
|
||||
amodule.exit_json(**decon.result)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -86,60 +86,65 @@ class decort_pfw(DecortController):
|
||||
|
||||
return
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
amodule = self.amodule
|
||||
|
||||
pfw_facts = None # will hold PFW facts as returned by pfw_configure
|
||||
|
||||
#
|
||||
# Validate module arguments:
|
||||
# 1) specified Compute instance exists in correct state
|
||||
# 2) specified ViNS exists
|
||||
# 3) ViNS has GW function
|
||||
# 4) Compute is connected to this ViNS
|
||||
#
|
||||
|
||||
validated_comp_id, comp_facts, rg_id = self.compute_find(amodule.params['compute_id'])
|
||||
if not validated_comp_id:
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = "Cannot find specified Compute ID {}.".format(amodule.params['compute_id'])
|
||||
amodule.fail_json(**self.result)
|
||||
|
||||
validated_vins_id, vins_facts = self.vins_find(amodule.params['vins_id'])
|
||||
if not validated_vins_id:
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = "Cannot find specified ViNS ID {}.".format(amodule.params['vins_id'])
|
||||
amodule.fail_json(**self.result)
|
||||
|
||||
gw_vnf_facts = vins_facts['vnfs'].get('GW')
|
||||
if not gw_vnf_facts or gw_vnf_facts['status'] == "DESTROYED":
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = "ViNS ID {} does not have a configured external connection.".format(validated_vins_id)
|
||||
amodule.fail_json(**self.result)
|
||||
|
||||
#
|
||||
# Initial validation of module arguments is complete
|
||||
#
|
||||
|
||||
if amodule.params['state'] == 'absent':
|
||||
# ignore amodule.params['rules'] and remove all rules associated with this Compute
|
||||
pfw_facts = self.pfw_configure(comp_facts, vins_facts, None)
|
||||
elif amodule.params['rules'] is not None:
|
||||
# manage PFW rules accodring to the module arguments
|
||||
pfw_facts = self.pfw_configure(comp_facts, vins_facts, amodule.params['rules'])
|
||||
else:
|
||||
pfw_facts = self._pfw_get(comp_facts['id'], vins_facts['id'])
|
||||
|
||||
#
|
||||
# complete module run
|
||||
#
|
||||
if self.result['failed']:
|
||||
amodule.fail_json(**self.result)
|
||||
else:
|
||||
# prepare PFW facts to be returned as part of self.result and then call exit_json(...)
|
||||
self.result['facts'] = self.decort_pfw_package_facts(comp_facts, vins_facts, pfw_facts, amodule.check_mode)
|
||||
amodule.exit_json(**self.result)
|
||||
|
||||
|
||||
def main():
|
||||
decon = decort_pfw()
|
||||
amodule = decon.amodule
|
||||
decort_pfw().run()
|
||||
|
||||
pfw_facts = None # will hold PFW facts as returned by pfw_configure
|
||||
|
||||
#
|
||||
# Validate module arguments:
|
||||
# 1) specified Compute instance exists in correct state
|
||||
# 2) specified ViNS exists
|
||||
# 3) ViNS has GW function
|
||||
# 4) Compute is connected to this ViNS
|
||||
#
|
||||
|
||||
validated_comp_id, comp_facts, rg_id = decon.compute_find(amodule.params['compute_id'])
|
||||
if not validated_comp_id:
|
||||
decon.result['failed'] = True
|
||||
decon.result['msg'] = "Cannot find specified Compute ID {}.".format(amodule.params['compute_id'])
|
||||
amodule.fail_json(**decon.result)
|
||||
|
||||
validated_vins_id, vins_facts = decon.vins_find(amodule.params['vins_id'])
|
||||
if not validated_vins_id:
|
||||
decon.result['failed'] = True
|
||||
decon.result['msg'] = "Cannot find specified ViNS ID {}.".format(amodule.params['vins_id'])
|
||||
amodule.fail_json(**decon.result)
|
||||
|
||||
gw_vnf_facts = vins_facts['vnfs'].get('GW')
|
||||
if not gw_vnf_facts or gw_vnf_facts['status'] == "DESTROYED":
|
||||
decon.result['failed'] = True
|
||||
decon.result['msg'] = "ViNS ID {} does not have a configured external connection.".format(validated_vins_id)
|
||||
amodule.fail_json(**decon.result)
|
||||
|
||||
#
|
||||
# Initial validation of module arguments is complete
|
||||
#
|
||||
|
||||
if amodule.params['state'] == 'absent':
|
||||
# ignore amodule.params['rules'] and remove all rules associated with this Compute
|
||||
pfw_facts = decon.pfw_configure(comp_facts, vins_facts, None)
|
||||
elif amodule.params['rules'] is not None:
|
||||
# manage PFW rules accodring to the module arguments
|
||||
pfw_facts = decon.pfw_configure(comp_facts, vins_facts, amodule.params['rules'])
|
||||
else:
|
||||
pfw_facts = decon._pfw_get(comp_facts['id'], vins_facts['id'])
|
||||
|
||||
#
|
||||
# complete module run
|
||||
#
|
||||
if decon.result['failed']:
|
||||
amodule.fail_json(**decon.result)
|
||||
else:
|
||||
# prepare PFW facts to be returned as part of decon.result and then call exit_json(...)
|
||||
decon.result['facts'] = decon.decort_pfw_package_facts(comp_facts, vins_facts, pfw_facts, amodule.check_mode)
|
||||
amodule.exit_json(**decon.result)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -97,26 +97,56 @@ class decort_rg(DecortController):
|
||||
self.amodule.params['rg_name'],
|
||||
self.validated_acc_id)
|
||||
return
|
||||
|
||||
|
||||
def update(self):
|
||||
resources = self.rg_facts['Resources']['Reserved']
|
||||
incorrect_quota = dict(Requested=dict(),
|
||||
Reserved=dict(),)
|
||||
query_key_map = dict(cpu='cpu',
|
||||
ram='ram',
|
||||
disk='disksize',
|
||||
ext_ips='extips',
|
||||
net_transfer='exttraffic',)
|
||||
query_key_map = dict(
|
||||
cpu='cpu',
|
||||
ram='ram',
|
||||
disk='disksize',
|
||||
ext_ips='extips',
|
||||
storage_policies='policies',
|
||||
)
|
||||
if 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]]:
|
||||
incorrect_quota['Requested'][quota_item]=self.amodule.params['quotas'][quota_item]
|
||||
incorrect_quota['Reserved'][quota_item]=resources[query_key_map[quota_item]]
|
||||
if quota_item == 'storage_policies':
|
||||
rg_storage_policies = 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']:
|
||||
self.result['msg'] = ("Cannot limit less than already reserved'{}'").format(incorrect_quota)
|
||||
self.result['failed'] = True
|
||||
|
||||
|
||||
if not self.result['failed']:
|
||||
self.rg_update(
|
||||
arg_rg_dict=self.rg_facts,
|
||||
@@ -243,6 +273,7 @@ class decort_rg(DecortController):
|
||||
ret_dict['uniqPools'] = self.rg_facts['uniqPools']
|
||||
ret_dict['description'] = self.rg_facts['desc']
|
||||
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
|
||||
|
||||
@@ -375,73 +406,78 @@ class decort_rg(DecortController):
|
||||
# 4) if RG exists: check desired state, desired configuration -> initiate action accordingly
|
||||
# 5) report result to Ansible
|
||||
|
||||
def main():
|
||||
decon = decort_rg()
|
||||
amodule = decon.amodule
|
||||
#amodule.check_mode=True
|
||||
if decon.validated_rg_id > 0:
|
||||
if decon.rg_facts['status'] in ["MODELED", "DISABLING", "ENABLING", "DELETING", "DESTROYING", "CONFIRMED"]:
|
||||
decon.error()
|
||||
elif decon.rg_facts['status'] in ("CREATED"):
|
||||
if amodule.params['state'] == 'absent':
|
||||
decon.destroy()
|
||||
elif amodule.params['state'] == "disabled":
|
||||
decon.enable()
|
||||
if amodule.params['state'] in ['present', 'enabled']:
|
||||
if (
|
||||
amodule.params['quotas']
|
||||
or amodule.params['resType']
|
||||
or amodule.params['rename'] != ""
|
||||
or amodule.params['sep_pools'] is not None
|
||||
or amodule.params['description'] is not None
|
||||
):
|
||||
decon.update()
|
||||
if amodule.params['access']:
|
||||
decon.access()
|
||||
if amodule.params['def_netType'] is not None:
|
||||
decon.setDefNet()
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
amodule = self.amodule
|
||||
#amodule.check_mode=True
|
||||
if self.validated_rg_id > 0:
|
||||
if self.rg_facts['status'] in ["MODELED", "DISABLING", "ENABLING", "DELETING", "DESTROYING", "CONFIRMED"]:
|
||||
self.error()
|
||||
elif self.rg_facts['status'] in ("CREATED"):
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.destroy()
|
||||
elif amodule.params['state'] == "disabled":
|
||||
self.enable()
|
||||
if amodule.params['state'] in ['present', 'enabled']:
|
||||
if (
|
||||
amodule.params['quotas']
|
||||
or amodule.params['resType']
|
||||
or amodule.params['rename'] != ""
|
||||
or amodule.params['sep_pools'] is not None
|
||||
or amodule.params['description'] is not None
|
||||
):
|
||||
self.update()
|
||||
if amodule.params['access']:
|
||||
self.access()
|
||||
if amodule.params['def_netType'] is not None:
|
||||
self.setDefNet()
|
||||
|
||||
elif decon.rg_facts['status'] == "DELETED":
|
||||
if amodule.params['state'] == 'absent' and amodule.params['permanently'] == True:
|
||||
decon.destroy()
|
||||
elif (amodule.params['state'] == 'present'
|
||||
or amodule.params['state'] == 'disabled'):
|
||||
decon.restore()
|
||||
elif amodule.params['state'] == 'enabled':
|
||||
decon.restore()
|
||||
decon.enable()
|
||||
elif decon.rg_facts['status'] in ("DISABLED"):
|
||||
if amodule.params['state'] == 'absent':
|
||||
decon.destroy()
|
||||
elif amodule.params['state'] == ("enabled"):
|
||||
decon.enable()
|
||||
elif self.rg_facts['status'] == "DELETED":
|
||||
if amodule.params['state'] == 'absent' and amodule.params['permanently'] == True:
|
||||
self.destroy()
|
||||
elif (amodule.params['state'] == 'present'
|
||||
or amodule.params['state'] == 'disabled'):
|
||||
self.restore()
|
||||
elif amodule.params['state'] == 'enabled':
|
||||
self.restore()
|
||||
self.enable()
|
||||
elif self.rg_facts['status'] in ("DISABLED"):
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.destroy()
|
||||
elif amodule.params['state'] == ("enabled"):
|
||||
self.enable()
|
||||
|
||||
else:
|
||||
if amodule.params['state'] in ('present', 'enabled'):
|
||||
if not amodule.params['rg_name']:
|
||||
decon.result['failed'] = True
|
||||
decon.result['msg'] = (
|
||||
'Resource group could not be created because'
|
||||
' the "rg_name" parameter was not specified.'
|
||||
)
|
||||
else:
|
||||
decon.create()
|
||||
if amodule.params['access'] and not amodule.check_mode:
|
||||
decon.access()
|
||||
elif amodule.params['state'] in ('disabled'):
|
||||
decon.error()
|
||||
|
||||
|
||||
if decon.result['failed']:
|
||||
amodule.fail_json(**decon.result)
|
||||
else:
|
||||
if decon.rg_should_exist:
|
||||
if decon.result['changed']:
|
||||
decon.get_info()
|
||||
decon.result['facts'] = decon.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**decon.result)
|
||||
else:
|
||||
amodule.exit_json(**decon.result)
|
||||
if amodule.params['state'] in ('present', 'enabled'):
|
||||
if not amodule.params['rg_name']:
|
||||
self.result['failed'] = True
|
||||
self.result['msg'] = (
|
||||
'Resource group could not be created because'
|
||||
' the "rg_name" parameter was not specified.'
|
||||
)
|
||||
else:
|
||||
self.create()
|
||||
if amodule.params['access'] and not amodule.check_mode:
|
||||
self.access()
|
||||
elif amodule.params['state'] in ('disabled'):
|
||||
self.error()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if self.result['failed']:
|
||||
amodule.fail_json(**self.result)
|
||||
else:
|
||||
if self.rg_should_exist:
|
||||
if self.result['changed']:
|
||||
self.get_info()
|
||||
self.result['facts'] = self.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**self.result)
|
||||
else:
|
||||
amodule.exit_json(**self.result)
|
||||
|
||||
|
||||
def main():
|
||||
decort_rg().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
148
library/decort_rg_list.py
Normal file
148
library/decort_rg_list.py
Normal file
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_rg_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortRGList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
account_id=dict(
|
||||
type='int',
|
||||
),
|
||||
account_name=dict(
|
||||
type='str',
|
||||
),
|
||||
created_after_timestamp=dict(
|
||||
type='int',
|
||||
),
|
||||
created_before_timestamp=dict(
|
||||
type='int',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
include_deleted=dict(
|
||||
type='bool',
|
||||
),
|
||||
lock_status=dict(
|
||||
type='str',
|
||||
choices=sdk_types.LockStatus._member_names_,
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=(
|
||||
sdk_types.ResourceGroupStatus._member_names_
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
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=(
|
||||
sdk_types.ResourceGroupAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
aparam_status: str | None = aparam_filter['status']
|
||||
aparam_lock_status: str | None = aparam_filter['lock_status']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.ResourceGroupAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.cloudapi.rg.list(
|
||||
account_id=aparam_filter['account_id'],
|
||||
account_name=aparam_filter['account_name'],
|
||||
created_after_timestamp=aparam_filter['created_after_timestamp'],
|
||||
created_before_timestamp=aparam_filter['created_before_timestamp'],
|
||||
id=aparam_filter['id'],
|
||||
include_deleted=aparam_filter['include_deleted'] or False,
|
||||
lock_status=(
|
||||
sdk_types.LockStatus[aparam_lock_status]
|
||||
if aparam_lock_status else None
|
||||
),
|
||||
name=aparam_filter['name'],
|
||||
status=(
|
||||
sdk_types.ResourceGroupStatus[aparam_status]
|
||||
if aparam_status else None
|
||||
),
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortRGList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
366
library/decort_security_group.py
Normal file
366
library/decort_security_group.py
Normal file
@@ -0,0 +1,366 @@
|
||||
#!/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
|
||||
|
||||
from dynamix_sdk import exceptions as sdk_exceptions
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
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=(
|
||||
sdk_types.TrafficDirection.
|
||||
_member_names_
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
ethertype=dict(
|
||||
type='str',
|
||||
choices=(
|
||||
sdk_types.SGRuleEthertype.
|
||||
_member_names_
|
||||
),
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
port_range=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
min=dict(
|
||||
type='int',
|
||||
),
|
||||
max=dict(
|
||||
type='int',
|
||||
),
|
||||
),
|
||||
),
|
||||
protocol=dict(
|
||||
type='str',
|
||||
choices=(
|
||||
sdk_types.SGRuleProtocol._member_names_
|
||||
),
|
||||
),
|
||||
remote_net_cidr=dict(
|
||||
type='str',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
choices=[e.value for e in self.SecurityGroupState],
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
if self.aparams['id'] is not None:
|
||||
self.id = self.aparams['id']
|
||||
elif self.aparams['name'] is not None:
|
||||
security_groups = self.api.cloudapi.security_group.list(
|
||||
account_id=self.aparams['account_id'],
|
||||
name=self.aparams['name'],
|
||||
)
|
||||
if security_groups.data:
|
||||
self.id = security_groups.data[0].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):
|
||||
try:
|
||||
storage_policy_model = self.api.cloudapi.security_group.get(
|
||||
security_group_id=self.id
|
||||
)
|
||||
except sdk_exceptions.RequestException as e:
|
||||
if (
|
||||
e.orig_exception.response
|
||||
and e.orig_exception.response.status_code == 404
|
||||
):
|
||||
self.message(
|
||||
self.MESSAGES.obj_not_found(
|
||||
obj='security_group',
|
||||
id=self.id,
|
||||
)
|
||||
)
|
||||
self.exit(fail=True)
|
||||
raise e
|
||||
|
||||
self.facts = storage_policy_model.model_dump()
|
||||
|
||||
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):
|
||||
id = self.sdk_checkmode(self.api.cloudapi.security_group.create)(
|
||||
account_id=self.aparams['account_id'],
|
||||
name=self.aparams['name'],
|
||||
description=self.aparams['description'],
|
||||
)
|
||||
if id:
|
||||
self.id = id
|
||||
|
||||
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.sdk_checkmode(self.api.cloudapi.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.sdk_checkmode(self.api.cloudapi.security_group.delete)(
|
||||
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.sdk_checkmode(self.api.cloudapi.security_group.create_rule)(
|
||||
security_group_id=self.id,
|
||||
traffic_direction=(
|
||||
sdk_types.TrafficDirection[rule['direction']]
|
||||
),
|
||||
ethertype=(
|
||||
sdk_types.SGRuleEthertype[rule['ethertype']]
|
||||
if rule.get('ethertype') else sdk_types.SGRuleEthertype.IPV4
|
||||
),
|
||||
protocol=(
|
||||
sdk_types.SGRuleProtocol[rule['protocol']]
|
||||
if rule.get('protocol') else None
|
||||
),
|
||||
port_range_min=port_range_min,
|
||||
port_range_max=port_range_max,
|
||||
remote_net_cidr=rule.get('remote_net_cidr'),
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
DecortSecurityGroup().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
132
library/decort_security_group_list.py
Normal file
132
library/decort_security_group_list.py
Normal file
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_security_group_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortSecurityGroupList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
account_id=dict(
|
||||
type='int',
|
||||
),
|
||||
created_after_timestamp=dict(
|
||||
type='int',
|
||||
),
|
||||
created_before_timestamp=dict(
|
||||
type='int',
|
||||
),
|
||||
description=dict(
|
||||
type='str',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
updated_after_timestamp=dict(
|
||||
type='int',
|
||||
),
|
||||
updated_before_timestamp=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=(
|
||||
sdk_types.SecurityGroupAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.SecurityGroupAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.cloudapi.security_group.list(
|
||||
account_id=aparam_filter['account_id'],
|
||||
created_after_timestamp=aparam_filter['created_after_timestamp'],
|
||||
created_before_timestamp=aparam_filter['created_before_timestamp'],
|
||||
description=aparam_filter['description'],
|
||||
id=aparam_filter['id'],
|
||||
name=aparam_filter['name'],
|
||||
updated_after_timestamp=aparam_filter['updated_after_timestamp'],
|
||||
updated_before_timestamp=aparam_filter['updated_before_timestamp'],
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortSecurityGroupList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
65
library/decort_storage_policy.py
Normal file
65
library/decort_storage_policy.py
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/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
|
||||
|
||||
from dynamix_sdk import exceptions as sdk_exceptions
|
||||
|
||||
|
||||
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,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
try:
|
||||
storage_policy_model = self.api.cloudapi.storage_policy.get(
|
||||
id=self.id
|
||||
)
|
||||
except sdk_exceptions.RequestException as e:
|
||||
if (
|
||||
e.orig_exception.response
|
||||
and e.orig_exception.response.status_code == 404
|
||||
):
|
||||
self.message(
|
||||
self.MESSAGES.obj_not_found(
|
||||
obj='storage_policy',
|
||||
id=self.id,
|
||||
)
|
||||
)
|
||||
self.exit(fail=True)
|
||||
raise e
|
||||
|
||||
self.facts = storage_policy_model.model_dump()
|
||||
|
||||
|
||||
def main():
|
||||
DecortStoragePolicy().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
152
library/decort_storage_policy_list.py
Normal file
152
library/decort_storage_policy_list.py
Normal file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_storage_policy_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortStoragePolicyList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
account_id=dict(
|
||||
type='int',
|
||||
),
|
||||
description=dict(
|
||||
type='str',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
iops_limit=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
rg_id=dict(
|
||||
type='int',
|
||||
),
|
||||
sep_id=dict(
|
||||
type='int',
|
||||
),
|
||||
sep_pool_name=dict(
|
||||
type='str',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=(
|
||||
sdk_types.StoragePolicyStatus._member_names_
|
||||
),
|
||||
),
|
||||
sep_tech_status=dict(
|
||||
type='str',
|
||||
choices=sdk_types.SEPTechStatus._member_names_,
|
||||
),
|
||||
),
|
||||
),
|
||||
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=(
|
||||
sdk_types.StoragePolicyAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
aparam_status: str | None = aparam_filter['status']
|
||||
aparam_sep_tech_status: str | None = aparam_filter['sep_tech_status']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.StoragePolicyAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.cloudapi.storage_policy.list(
|
||||
account_id=aparam_filter['account_id'],
|
||||
description=aparam_filter['description'],
|
||||
id=aparam_filter['id'],
|
||||
iops_limit=aparam_filter['iops_limit'],
|
||||
name=aparam_filter['name'],
|
||||
rg_id=aparam_filter['rg_id'],
|
||||
sep_id=aparam_filter['sep_id'],
|
||||
sep_pool_name=aparam_filter['sep_pool_name'],
|
||||
status=(
|
||||
sdk_types.StoragePolicyStatus[aparam_status]
|
||||
if aparam_status else None
|
||||
),
|
||||
sep_tech_status=(
|
||||
sdk_types.SEPTechStatus[aparam_sep_tech_status]
|
||||
if aparam_sep_tech_status else None
|
||||
),
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortStoragePolicyList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -10,6 +10,8 @@ description: See L(Module Documentation,https://repository.basistech.ru/BASIS/de
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk import exceptions as sdk_exceptions
|
||||
|
||||
|
||||
class DecortTrunk(DecortController):
|
||||
def __init__(self):
|
||||
@@ -28,19 +30,31 @@ class DecortTrunk(DecortController):
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
self.facts = self.trunk_get(id=self.id)
|
||||
self.facts['account_ids'] = self.facts.pop('accountIds')
|
||||
self.facts['created_timestamp'] = self.facts.pop('created_at')
|
||||
self.facts['deleted_timestamp'] = self.facts.pop('deleted_at')
|
||||
self.facts['updated_timestamp'] = self.facts.pop('updated_at')
|
||||
self.facts['native_vlan_id'] = self.facts.pop('nativeVlanId')
|
||||
self.facts['ovs_bridge'] = self.facts.pop('ovsBridge')
|
||||
self.facts['vlan_ids'] = self.facts.pop('trunkTags')
|
||||
try:
|
||||
trunk_model = self.api.cloudapi.trunk.get(
|
||||
id=self.id
|
||||
)
|
||||
except sdk_exceptions.RequestException as e:
|
||||
if (
|
||||
e.orig_exception.response
|
||||
and e.orig_exception.response.status_code == 404
|
||||
):
|
||||
self.message(
|
||||
self.MESSAGES.obj_not_found(
|
||||
obj='trunk',
|
||||
id=self.id,
|
||||
)
|
||||
)
|
||||
self.exit(fail=True)
|
||||
raise e
|
||||
|
||||
self.facts = trunk_model.model_dump()
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
123
library/decort_trunk_list.py
Normal file
123
library/decort_trunk_list.py
Normal file
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_trunk_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortTrunkList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
account_ids=dict(
|
||||
type='list',
|
||||
elements='int',
|
||||
),
|
||||
ids=dict(
|
||||
type='list',
|
||||
elements='int',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=sdk_types.TrunkStatus._member_names_,
|
||||
),
|
||||
vlan_ids=dict(
|
||||
type='str',
|
||||
),
|
||||
),
|
||||
),
|
||||
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=(
|
||||
sdk_types.TrunkAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
aparam_status: str | None = aparam_filter['status']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.TrunkAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.cloudapi.trunk.list(
|
||||
account_ids=aparam_filter['account_ids'],
|
||||
ids=aparam_filter['ids'],
|
||||
status=(
|
||||
sdk_types.TrunkStatus[aparam_status]
|
||||
if aparam_status else None
|
||||
),
|
||||
vlan_ids=aparam_filter['vlan_ids'],
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortTrunkList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
68
library/decort_user.py
Normal file
68
library/decort_user.py
Normal file
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_user
|
||||
|
||||
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 DecortUser(DecortController):
|
||||
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(
|
||||
api_methods=dict(
|
||||
type='bool',
|
||||
default=False,
|
||||
),
|
||||
objects_search=dict(
|
||||
type='str',
|
||||
),
|
||||
resource_consumption=dict(
|
||||
type='bool',
|
||||
default=False,
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
self.facts = self.usermanager_whoami_result
|
||||
self.id = self.facts['name']
|
||||
|
||||
user_get = self.user_get(id=self.id)
|
||||
for key in ['emailaddresses', 'data']:
|
||||
self.facts[key] = user_get[key]
|
||||
|
||||
if self.aparams['resource_consumption']:
|
||||
self.facts.update(self.user_resource_consumption())
|
||||
|
||||
if self.aparams['api_methods']:
|
||||
self.facts['api_methods'] = self.user_api_methods(id=self.id)
|
||||
|
||||
search_string = self.aparams['objects_search']
|
||||
if search_string:
|
||||
self.facts['objects_search'] = self.user_objects_search(
|
||||
search_string=search_string,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
DecortUser().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -8,607 +8,37 @@ description: See L(Module Documentation,https://repository.basistech.ru/BASIS/de
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
|
||||
class DecortUserInfo(DecortController):
|
||||
def __init__(self):
|
||||
super().__init__(AnsibleModule(**self.amodule_init_args))
|
||||
self.check_amodule_args()
|
||||
|
||||
@property
|
||||
def amodule_init_args(self) -> dict:
|
||||
return self.pack_amodule_init_args(
|
||||
argument_spec=dict(
|
||||
accounts=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
deleted=dict(
|
||||
type='bool',
|
||||
default=False,
|
||||
),
|
||||
filter=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
rights=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
e.value for e in self.AccountUserRights
|
||||
],
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
e.value for e in self.AccountStatus
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
pagination=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
number=dict(
|
||||
type='int',
|
||||
default=1,
|
||||
),
|
||||
size=dict(
|
||||
type='int',
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
resource_consumption=dict(
|
||||
type='bool',
|
||||
default=False,
|
||||
),
|
||||
sorting=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
asc=dict(
|
||||
type='bool',
|
||||
default=True,
|
||||
),
|
||||
field=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
e.value
|
||||
for e in self.AccountSortableField
|
||||
],
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
api_methods=dict(
|
||||
type='bool',
|
||||
default=False,
|
||||
),
|
||||
audits=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
api_method=dict(
|
||||
type='str',
|
||||
),
|
||||
status_code=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
min=dict(
|
||||
type='int',
|
||||
),
|
||||
max=dict(
|
||||
type='int',
|
||||
),
|
||||
),
|
||||
),
|
||||
time=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
start=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
timestamp=dict(
|
||||
type='int',
|
||||
),
|
||||
datetime=dict(
|
||||
type='str',
|
||||
),
|
||||
),
|
||||
mutually_exclusive=[
|
||||
('timestamp', 'datetime'),
|
||||
],
|
||||
),
|
||||
end=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
timestamp=dict(
|
||||
type='int',
|
||||
),
|
||||
datetime=dict(
|
||||
type='str',
|
||||
),
|
||||
),
|
||||
mutually_exclusive=[
|
||||
('timestamp', 'datetime'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
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.AuditsSortableField
|
||||
],
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
objects_search=dict(
|
||||
type='str',
|
||||
),
|
||||
resource_consumption=dict(
|
||||
type='bool',
|
||||
default=False,
|
||||
),
|
||||
zones=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
deletable=dict(
|
||||
type='bool',
|
||||
),
|
||||
description=dict(
|
||||
type='str',
|
||||
),
|
||||
grid_id=dict(
|
||||
type='int',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
node_id=dict(
|
||||
type='int',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
e.value for e in self.ZoneStatus
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
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=self.ZoneField._member_names_,
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
trunks=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
ids=dict(
|
||||
type='list',
|
||||
),
|
||||
account_ids=dict(
|
||||
type='list',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=[
|
||||
e.value for e in self.TrunkStatus
|
||||
],
|
||||
),
|
||||
vlan_ids=dict(
|
||||
type='list',
|
||||
),
|
||||
),
|
||||
),
|
||||
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.TrunksSortableField
|
||||
],
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
def check_amodule_args(self):
|
||||
"""
|
||||
Additional validation of Ansible Module arguments.
|
||||
This validation cannot be implemented using
|
||||
Ansible Argument spec.
|
||||
"""
|
||||
|
||||
check_error = False
|
||||
|
||||
match self.aparams['audits']:
|
||||
case {
|
||||
'filter': {'time': {'start': {'datetime': str() as dt_str}}}
|
||||
}:
|
||||
if self.dt_str_to_sec(dt_str=dt_str) is None:
|
||||
self.message(self.MESSAGES.str_not_parsed(string=dt_str))
|
||||
check_error = True
|
||||
match self.aparams['audits']:
|
||||
case {
|
||||
'filter': {'time': {'end': {'datetime': str() as dt_str}}}
|
||||
}:
|
||||
if self.dt_str_to_sec(dt_str=dt_str) is None:
|
||||
self.message(self.MESSAGES.str_not_parsed(string=dt_str))
|
||||
check_error = True
|
||||
|
||||
aparam_trunks = self.aparams['trunks']
|
||||
if (
|
||||
aparam_trunks is not None
|
||||
and aparam_trunks['filter'] is not None
|
||||
and aparam_trunks['filter']['vlan_ids'] is not None
|
||||
):
|
||||
for vlan_id in aparam_trunks['filter']['vlan_ids']:
|
||||
if not (
|
||||
self.TRUNK_VLAN_ID_MIN_VALUE
|
||||
<= vlan_id
|
||||
<= self.TRUNK_VLAN_ID_MAX_VALUE
|
||||
):
|
||||
check_error = True
|
||||
self.message(
|
||||
'Check for parameter "trunks.filter.vlan_ids" failed: '
|
||||
f'VLAN ID {vlan_id} must be in range 1-4095.'
|
||||
)
|
||||
|
||||
if check_error:
|
||||
self.exit(fail=True)
|
||||
|
||||
@property
|
||||
def mapped_accounts_args(self) -> None | dict:
|
||||
"""
|
||||
Map the module argument `accounts` to
|
||||
arguments dictionary for the method
|
||||
`DecortController.user_accounts`.
|
||||
"""
|
||||
|
||||
input_args = self.aparams['accounts']
|
||||
if not input_args:
|
||||
return input_args
|
||||
|
||||
mapped_args = {}
|
||||
|
||||
mapped_args['deleted'] = input_args['deleted']
|
||||
|
||||
mapped_args['resource_consumption'] = (
|
||||
input_args['resource_consumption']
|
||||
)
|
||||
|
||||
input_args_filter = input_args['filter']
|
||||
if input_args_filter:
|
||||
input_args_filter_rights = input_args_filter['rights']
|
||||
if input_args_filter_rights:
|
||||
mapped_args['account_user_rights'] = (
|
||||
self.AccountUserRights(input_args_filter_rights)
|
||||
)
|
||||
|
||||
mapped_args['account_id'] = input_args_filter['id']
|
||||
|
||||
mapped_args['account_name'] = input_args_filter['name']
|
||||
|
||||
input_args_filter_status = input_args_filter['status']
|
||||
if input_args_filter_status:
|
||||
mapped_args['account_status'] = (
|
||||
self.AccountStatus(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.AccountSortableField(input_args_sorting_field)
|
||||
)
|
||||
|
||||
return mapped_args
|
||||
|
||||
@property
|
||||
def mapped_audits_args(self):
|
||||
"""
|
||||
Map the module argument `audits` to
|
||||
arguments dictionary for the method
|
||||
`DecortController.user_audits`.
|
||||
"""
|
||||
|
||||
input_args = self.aparams['audits']
|
||||
if not input_args:
|
||||
return input_args
|
||||
|
||||
mapped_args = {}
|
||||
|
||||
input_args_filter = input_args['filter']
|
||||
if input_args_filter:
|
||||
mapped_args['api_method'] = input_args_filter['api_method']
|
||||
|
||||
match input_args_filter['status_code']:
|
||||
case {'min': int() as min_status_code}:
|
||||
mapped_args['min_status_code'] = min_status_code
|
||||
match input_args_filter['status_code']:
|
||||
case {'max': int() as max_status_code}:
|
||||
mapped_args['max_status_code'] = max_status_code
|
||||
|
||||
match input_args_filter['time']:
|
||||
case {'start': {'timestamp': int() as start_unix_time}}:
|
||||
mapped_args['start_unix_time'] = start_unix_time
|
||||
case {'start': {'datetime': str() as start_dt_str}}:
|
||||
mapped_args['start_unix_time'] = self.dt_str_to_sec(
|
||||
dt_str=start_dt_str
|
||||
)
|
||||
match input_args_filter['time']:
|
||||
case {'end': {'timestamp': int() as end_unix_time}}:
|
||||
mapped_args['end_unix_time'] = end_unix_time
|
||||
case {'end': {'datetime': str() as end_dt_str}}:
|
||||
mapped_args['end_unix_time'] = self.dt_str_to_sec(
|
||||
dt_str=end_dt_str
|
||||
)
|
||||
|
||||
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.AuditsSortableField(input_args_sorting_field)
|
||||
)
|
||||
|
||||
return mapped_args
|
||||
|
||||
@property
|
||||
def mapped_zones_args(self):
|
||||
"""
|
||||
Map the module argument `zones` to
|
||||
arguments dictionary for the method
|
||||
`DecortController.user_zones`.
|
||||
"""
|
||||
|
||||
input_args = self.aparams['zones']
|
||||
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.ZoneStatus(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.ZoneField._member_map_[input_args_sorting_field]
|
||||
)
|
||||
|
||||
return mapped_args
|
||||
|
||||
@property
|
||||
def mapped_trunks_args(self):
|
||||
"""
|
||||
Map the module argument `trunks` to
|
||||
arguments dictionary for the method
|
||||
`DecortController.user_trunks`.
|
||||
"""
|
||||
|
||||
input_args = self.aparams['trunks']
|
||||
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.TrunkStatus(input_args_filter_status)
|
||||
)
|
||||
|
||||
input_args_filter_vlan_ids = input_args_filter['vlan_ids']
|
||||
if input_args_filter_vlan_ids is not None:
|
||||
mapped_args['vlan_ids'] = ', '.join(
|
||||
map(str, input_args_filter_vlan_ids)
|
||||
)
|
||||
|
||||
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.TrunksSortableField(input_args_sorting_field)
|
||||
)
|
||||
|
||||
return mapped_args
|
||||
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
self.facts = self.user_whoami()
|
||||
self.id = self.facts['name']
|
||||
|
||||
user_get = self.user_get(id=self.id)
|
||||
for key in ['emailaddresses', 'data']:
|
||||
self.facts[key] = user_get[key]
|
||||
|
||||
if self.aparams['accounts']:
|
||||
self.facts['accounts'] = self.user_accounts(
|
||||
**self.mapped_accounts_args,
|
||||
)
|
||||
|
||||
if self.aparams['resource_consumption']:
|
||||
self.facts.update(self.user_resource_consumption())
|
||||
|
||||
if self.aparams['audits']:
|
||||
self.facts['audits'] = self.user_audits(**self.mapped_audits_args)
|
||||
|
||||
if self.aparams['api_methods']:
|
||||
self.facts['api_methods'] = self.user_api_methods(id=self.id)
|
||||
|
||||
search_string = self.aparams['objects_search']
|
||||
if search_string:
|
||||
self.facts['objects_search'] = self.user_objects_search(
|
||||
search_string=search_string,
|
||||
)
|
||||
|
||||
if self.aparams['zones']:
|
||||
self.facts['zones'] = self.user_zones(**self.mapped_zones_args)
|
||||
|
||||
if self.aparams['trunks']:
|
||||
self.facts['trunks'] = self.user_trunks(**self.mapped_trunks_args)
|
||||
for trunk_facts in self.facts['trunks']:
|
||||
trunk_facts['account_ids'] = trunk_facts.pop('accountIds')
|
||||
trunk_facts['created_timestamp'] = trunk_facts.pop(
|
||||
'created_at'
|
||||
)
|
||||
trunk_facts['deleted_timestamp'] = trunk_facts.pop(
|
||||
'deleted_at'
|
||||
)
|
||||
trunk_facts['updated_timestamp'] = trunk_facts.pop(
|
||||
'updated_at'
|
||||
)
|
||||
trunk_facts['native_vlan_id'] = trunk_facts.pop(
|
||||
'nativeVlanId'
|
||||
)
|
||||
trunk_facts['ovs_bridge'] = trunk_facts.pop('ovsBridge')
|
||||
trunk_facts['vlan_ids'] = trunk_facts.pop('trunkTags')
|
||||
|
||||
|
||||
def main():
|
||||
DecortUserInfo().run()
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
app_id=dict(type='raw'),
|
||||
app_secret=dict(type='raw'),
|
||||
authenticator=dict(type='raw'),
|
||||
controller_url=dict(type='raw'),
|
||||
domain=dict(type='raw'),
|
||||
jwt=dict(type='raw'),
|
||||
oauth2_url=dict(type='raw'),
|
||||
password=dict(type='raw'),
|
||||
username=dict(type='raw'),
|
||||
verify_ssl=dict(type='raw'),
|
||||
ignore_api_compatibility=dict(type='raw'),
|
||||
ignore_sdk_version_check=dict(type='raw'),
|
||||
api_methods=dict(type='raw'),
|
||||
objects_search=dict(type='raw'),
|
||||
resource_consumption=dict(type='raw'),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
module.fail_json(
|
||||
msg=(
|
||||
'The module "decort_user_info" has been renamed to "decort_user". '
|
||||
'Please update your playbook to use "decort_user" '
|
||||
'instead of "decort_user_info".'
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -170,7 +170,7 @@ class decort_vins(DecortController):
|
||||
|
||||
return
|
||||
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'
|
||||
return
|
||||
def nop(self):
|
||||
@@ -320,6 +320,10 @@ class decort_vins(DecortController):
|
||||
type='str',
|
||||
default='',
|
||||
),
|
||||
permanently=dict(
|
||||
type='bool',
|
||||
default=False,
|
||||
),
|
||||
vins_id=dict(
|
||||
type='int',
|
||||
default=0,
|
||||
@@ -361,101 +365,106 @@ class decort_vins(DecortController):
|
||||
# 4) if ViNS exists: check desired state, desired configuration -> initiate action(s) accordingly
|
||||
# 5) report result to Ansible
|
||||
|
||||
def main():
|
||||
decon = decort_vins()
|
||||
amodule = decon.amodule
|
||||
#
|
||||
# Initial validation of module arguments is complete
|
||||
#
|
||||
# At this point non-zero vins_id means that we will be managing pre-existing ViNS
|
||||
# Otherwise we are about to create a new one as follows:
|
||||
# - if validated_rg_id is non-zero, create ViNS @ RG level
|
||||
# - if validated_rg_id is zero, create ViNS @ account level
|
||||
#
|
||||
# When managing existing ViNS we need to account for both "static" and "transient"
|
||||
# status. Full range of ViNS statii is as follows:
|
||||
#
|
||||
# "MODELED", "CREATED", "ENABLED", "ENABLING", "DISABLED", "DISABLING", "DELETED", "DELETING", "DESTROYED", "DESTROYING"
|
||||
#
|
||||
# if cconfig_save is true, only config save without other updates
|
||||
vins_should_exist = False
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
amodule = self.amodule
|
||||
#
|
||||
# Initial validation of module arguments is complete
|
||||
#
|
||||
# At this point non-zero vins_id means that we will be managing pre-existing ViNS
|
||||
# Otherwise we are about to create a new one as follows:
|
||||
# - if validated_rg_id is non-zero, create ViNS @ RG level
|
||||
# - if validated_rg_id is zero, create ViNS @ account level
|
||||
#
|
||||
# When managing existing ViNS we need to account for both "static" and "transient"
|
||||
# status. Full range of ViNS statii is as follows:
|
||||
#
|
||||
# "MODELED", "CREATED", "ENABLED", "ENABLING", "DISABLED", "DISABLING", "DELETED", "DELETING", "DESTROYED", "DESTROYING"
|
||||
#
|
||||
# if cconfig_save is true, only config save without other updates
|
||||
vins_should_exist = False
|
||||
|
||||
if decon.vins_id:
|
||||
vins_should_exist = True
|
||||
if decon.vins_facts['status'] in ["MODELED", "DISABLING", "ENABLING", "DELETING", "DESTROYING"]:
|
||||
# error: nothing can be done to existing ViNS in the listed statii regardless of
|
||||
# the requested state
|
||||
decon.result['failed'] = True
|
||||
decon.result['changed'] = False
|
||||
decon.result['msg'] = ("No change can be done for existing ViNS ID {} because of its current "
|
||||
"status '{}'").format(decon.vins_id, decon.vins_facts['status'])
|
||||
elif decon.vins_facts['status'] == "DISABLED":
|
||||
if amodule.params['state'] == 'absent':
|
||||
decon.delete()
|
||||
vins_should_exist = False
|
||||
elif amodule.params['state'] in ('present', 'disabled'):
|
||||
# update ViNS, leave in disabled state
|
||||
decon.action()
|
||||
elif amodule.params['state'] == 'enabled':
|
||||
# update ViNS and enable
|
||||
decon.action('enabled')
|
||||
elif decon.vins_facts['status'] in ["CREATED", "ENABLED"]:
|
||||
if amodule.params['state'] == 'absent':
|
||||
decon.delete()
|
||||
vins_should_exist = False
|
||||
elif amodule.params['state'] in ('present', 'enabled'):
|
||||
# update ViNS
|
||||
decon.action()
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
# disable and update ViNS
|
||||
decon.action('disabled')
|
||||
elif decon.vins_facts['status'] == "DELETED":
|
||||
if amodule.params['state'] in ['present', 'enabled']:
|
||||
# restore and enable
|
||||
decon.action(restore=True)
|
||||
vins_should_exist = True
|
||||
elif amodule.params['state'] == 'absent':
|
||||
# destroy permanently
|
||||
decon.delete()
|
||||
vins_should_exist = False
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
decon.error()
|
||||
vins_should_exist = False
|
||||
elif decon.vins_facts['status'] == "DESTROYED":
|
||||
if amodule.params['state'] in ('present', 'enabled'):
|
||||
# need to re-provision ViNS;
|
||||
decon.create()
|
||||
vins_should_exist = True
|
||||
elif amodule.params['state'] == 'absent':
|
||||
decon.nop()
|
||||
vins_should_exist = False
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
decon.error()
|
||||
else:
|
||||
# Preexisting ViNS was not found.
|
||||
vins_should_exist = False # we will change it back to True if ViNS is created or restored
|
||||
# If requested state is 'absent' - nothing to do
|
||||
if amodule.params['state'] == 'absent':
|
||||
decon.nop()
|
||||
elif amodule.params['state'] in ('present', 'enabled'):
|
||||
decon.check_amodule_argument('vins_name')
|
||||
# as we already have account ID and RG ID we can create ViNS and get vins_id on success
|
||||
decon.create()
|
||||
if self.vins_id:
|
||||
vins_should_exist = True
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
decon.error()
|
||||
#
|
||||
# conditional switch end - complete module run
|
||||
#
|
||||
if decon.result['failed']:
|
||||
amodule.fail_json(**decon.result)
|
||||
else:
|
||||
# prepare ViNS facts to be returned as part of decon.result and then call exit_json(...)
|
||||
if decon.result['changed']:
|
||||
_, decon.vins_facts = decon.vins_find(decon.vins_id)
|
||||
decon.result['facts'] = decon.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**decon.result)
|
||||
if self.vins_facts['status'] in ["MODELED", "DISABLING", "ENABLING", "DELETING", "DESTROYING"]:
|
||||
# error: nothing can be done to existing ViNS in the listed statii regardless of
|
||||
# the requested state
|
||||
self.result['failed'] = True
|
||||
self.result['changed'] = False
|
||||
self.result['msg'] = ("No change can be done for existing ViNS ID {} because of its current "
|
||||
"status '{}'").format(self.vins_id, self.vins_facts['status'])
|
||||
elif self.vins_facts['status'] == "DISABLED":
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.delete()
|
||||
vins_should_exist = False
|
||||
elif amodule.params['state'] in ('present', 'disabled'):
|
||||
# update ViNS, leave in disabled state
|
||||
self.action()
|
||||
elif amodule.params['state'] == 'enabled':
|
||||
# update ViNS and enable
|
||||
self.action('enabled')
|
||||
elif self.vins_facts['status'] in ["CREATED", "ENABLED"]:
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.delete()
|
||||
vins_should_exist = False
|
||||
elif amodule.params['state'] in ('present', 'enabled'):
|
||||
# update ViNS
|
||||
self.action()
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
# disable and update ViNS
|
||||
self.action('disabled')
|
||||
elif self.vins_facts['status'] == "DELETED":
|
||||
if amodule.params['state'] in ['present', 'enabled']:
|
||||
# restore and enable
|
||||
self.action(restore=True)
|
||||
vins_should_exist = True
|
||||
elif amodule.params['state'] == 'absent':
|
||||
# destroy permanently
|
||||
if self.amodule.params['permanently']:
|
||||
self.delete()
|
||||
vins_should_exist = False
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
self.error()
|
||||
vins_should_exist = False
|
||||
elif self.vins_facts['status'] == "DESTROYED":
|
||||
if amodule.params['state'] in ('present', 'enabled'):
|
||||
# need to re-provision ViNS;
|
||||
self.create()
|
||||
vins_should_exist = True
|
||||
elif amodule.params['state'] == 'absent':
|
||||
self.nop()
|
||||
vins_should_exist = False
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
self.error()
|
||||
else:
|
||||
# Preexisting ViNS was not found.
|
||||
vins_should_exist = False # we will change it back to True if ViNS is created or restored
|
||||
# If requested state is 'absent' - nothing to do
|
||||
if amodule.params['state'] == 'absent':
|
||||
self.nop()
|
||||
elif amodule.params['state'] in ('present', 'enabled'):
|
||||
self.check_amodule_argument('vins_name')
|
||||
# as we already have account ID and RG ID we can create ViNS and get vins_id on success
|
||||
self.create()
|
||||
vins_should_exist = True
|
||||
elif amodule.params['state'] == 'disabled':
|
||||
self.error()
|
||||
#
|
||||
# conditional switch end - complete module run
|
||||
#
|
||||
if self.result['failed']:
|
||||
amodule.fail_json(**self.result)
|
||||
else:
|
||||
# prepare ViNS facts to be returned as part of self.result and then call exit_json(...)
|
||||
if self.result['changed']:
|
||||
_, self.vins_facts = self.vins_find(self.vins_id)
|
||||
self.result['facts'] = self.package_facts(amodule.check_mode)
|
||||
amodule.exit_json(**self.result)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
def main():
|
||||
decort_vins().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
141
library/decort_vins_list.py
Normal file
141
library/decort_vins_list.py
Normal file
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_vins_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortVINSList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
account_id=dict(
|
||||
type='int',
|
||||
),
|
||||
ext_net_ip=dict(
|
||||
type='str',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
include_deleted=dict(
|
||||
type='bool',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
rg_id=dict(
|
||||
type='int',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=sdk_types.VINSStatus._member_names_,
|
||||
),
|
||||
vnfdev_id=dict(
|
||||
type='int',
|
||||
),
|
||||
zone_id=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=(
|
||||
sdk_types.VINSForListAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
aparam_status: str | None = aparam_filter['status']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.VINSForListAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.cloudapi.vins.list(
|
||||
account_id=aparam_filter['account_id'],
|
||||
ext_net_ip=aparam_filter['ext_net_ip'],
|
||||
id=aparam_filter['id'],
|
||||
include_deleted=aparam_filter['include_deleted'] or False,
|
||||
name=aparam_filter['name'],
|
||||
rg_id=aparam_filter['rg_id'],
|
||||
status=(
|
||||
sdk_types.VINSStatus[aparam_status]
|
||||
if aparam_status else None
|
||||
),
|
||||
vnfdev_id=aparam_filter['vnfdev_id'],
|
||||
zone_id=aparam_filter['zone_id'],
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortVINSList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
2510
library/decort_vm.py
Normal file
2510
library/decort_vm.py
Normal file
File diff suppressed because it is too large
Load Diff
158
library/decort_vm_list.py
Normal file
158
library/decort_vm_list.py
Normal file
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_vm_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortVMList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
account_id=dict(
|
||||
type='int',
|
||||
),
|
||||
ext_net_id=dict(
|
||||
type='int',
|
||||
),
|
||||
ext_net_name=dict(
|
||||
type='str',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
include_deleted=dict(
|
||||
type='bool',
|
||||
),
|
||||
ip_addr=dict(
|
||||
type='str',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
rg_id=dict(
|
||||
type='int',
|
||||
),
|
||||
rg_name=dict(
|
||||
type='str',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=sdk_types.VMStatus._member_names_,
|
||||
),
|
||||
tech_status=dict(
|
||||
type='str',
|
||||
choices=sdk_types.VMTechStatus._member_names_,
|
||||
),
|
||||
zone_id=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=(
|
||||
sdk_types.VMAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
aparam_status: str | None = aparam_filter['status']
|
||||
aparam_tech_status: str | None = aparam_filter['tech_status']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.VMAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.cloudapi.compute.list(
|
||||
account_id=aparam_filter['account_id'],
|
||||
ext_net_id=aparam_filter['ext_net_id'],
|
||||
ext_net_name=aparam_filter['ext_net_name'],
|
||||
id=aparam_filter['id'],
|
||||
include_deleted=aparam_filter['include_deleted'] or False,
|
||||
ip_addr=aparam_filter['ip_addr'],
|
||||
name=aparam_filter['name'],
|
||||
rg_id=aparam_filter['rg_id'],
|
||||
rg_name=aparam_filter['rg_name'],
|
||||
status=(
|
||||
sdk_types.VMStatus[aparam_status]
|
||||
if aparam_status else None
|
||||
),
|
||||
tech_status=(
|
||||
sdk_types.VMTechStatus[aparam_tech_status]
|
||||
if aparam_tech_status else None
|
||||
),
|
||||
zone_id=aparam_filter['zone_id'],
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortVMList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
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
|
||||
'''
|
||||
@@ -12,7 +12,7 @@ from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
|
||||
class DecortSnapshot(DecortController):
|
||||
class DecortVMSnapshot(DecortController):
|
||||
def __init__(self):
|
||||
super().__init__(AnsibleModule(**self.amodule_init_args))
|
||||
self.check_amodule_args()
|
||||
@@ -30,9 +30,10 @@ class DecortSnapshot(DecortController):
|
||||
self.exit(fail=True)
|
||||
|
||||
self.vm_name = self.vm_facts['name']
|
||||
self.vm_snapshots = self.vm_facts['snapSets']
|
||||
self.vm_snapshots = self.api.ca.compute.snapshot_list(
|
||||
vm_id=self.vm_id).data
|
||||
self.vm_snapshot_labels = [
|
||||
snapshot['label'] for snapshot in self.vm_snapshots
|
||||
snapshot.label for snapshot in self.vm_snapshots
|
||||
]
|
||||
|
||||
self.new_snapshot_label = None
|
||||
@@ -102,21 +103,23 @@ class DecortSnapshot(DecortController):
|
||||
if check_error:
|
||||
self.exit(fail=True)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info(first_run=True)
|
||||
self.get_info()
|
||||
self.check_amodule_args_for_change()
|
||||
self.change()
|
||||
self.exit()
|
||||
|
||||
def get_info(self, first_run: bool = False):
|
||||
if not first_run:
|
||||
self.vm_snapshots = self.snapshot_list(
|
||||
compute_id=self.aparams_vm_id,
|
||||
)
|
||||
def get_info(self, update_vm_snapshots: bool = False):
|
||||
if update_vm_snapshots:
|
||||
self.vm_snapshots = self.api.cloudapi.compute.snapshot_list(
|
||||
vm_id=self.aparams_vm_id,
|
||||
).data
|
||||
|
||||
label = self.new_snapshot_label or self.aparams_label
|
||||
for snapshot in self.vm_snapshots:
|
||||
if snapshot['label'] == label:
|
||||
self.facts = snapshot
|
||||
if snapshot.label == label:
|
||||
self.facts = snapshot.model_dump()
|
||||
if self.aparams['usage']:
|
||||
self.facts['stored'] = self.get_snapshot_usage()
|
||||
self.facts['vm_id'] = self.aparams_vm_id
|
||||
@@ -134,11 +137,11 @@ class DecortSnapshot(DecortController):
|
||||
self.abort_merge()
|
||||
|
||||
def create(self):
|
||||
self.snapshot_create(
|
||||
compute_id=self.aparams_vm_id,
|
||||
self.sdk_checkmode(self.api.cloudapi.compute.snapshot_create)(
|
||||
vm_id=self.aparams_vm_id,
|
||||
label=self.new_snapshot_label,
|
||||
)
|
||||
self.get_info()
|
||||
self.get_info(update_vm_snapshots=True)
|
||||
|
||||
def delete(self):
|
||||
self.snapshot_delete(
|
||||
@@ -149,7 +152,7 @@ class DecortSnapshot(DecortController):
|
||||
|
||||
def abort_merge(self):
|
||||
self.snapshot_abort_merge(
|
||||
vm_id=self.aparams_vm_id,
|
||||
vm_id=self.aparams_vm_id,
|
||||
label=self.aparams_label,
|
||||
)
|
||||
self.get_info()
|
||||
@@ -161,7 +164,7 @@ class DecortSnapshot(DecortController):
|
||||
label=label,
|
||||
)
|
||||
return common_snapshots_usage_info['stored']
|
||||
|
||||
|
||||
def check_amodule_args_for_change(self):
|
||||
check_errors = False
|
||||
|
||||
@@ -171,7 +174,7 @@ class DecortSnapshot(DecortController):
|
||||
):
|
||||
check_errors = True
|
||||
self.message(
|
||||
f'Check for parameter "state" failed: '
|
||||
'Check for parameter "state" failed: '
|
||||
'Merge can be aborted only for VM in "MERGE" tech status.'
|
||||
)
|
||||
|
||||
@@ -179,9 +182,8 @@ class DecortSnapshot(DecortController):
|
||||
self.exit(fail=True)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
DecortSnapshot().run()
|
||||
DecortVMSnapshot().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
@@ -10,6 +10,8 @@ description: See L(Module Documentation,https://repository.basistech.ru/BASIS/de
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk import exceptions as sdk_exceptions
|
||||
|
||||
|
||||
class DecortZone(DecortController):
|
||||
def __init__(self):
|
||||
@@ -28,16 +30,29 @@ class DecortZone(DecortController):
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
self.facts = self.zone_get(id=self.id)
|
||||
self.facts['grid_id'] = self.facts.pop('gid')
|
||||
self.facts['created_timestamp'] = self.facts.pop('createdTime')
|
||||
self.facts['updated_timestamp'] = self.facts.pop('updatedTime')
|
||||
self.facts['node_ids'] = self.facts.pop('nodeIds')
|
||||
try:
|
||||
zone_model = self.api.cloudapi.zone.get(id=self.id)
|
||||
except sdk_exceptions.RequestException as e:
|
||||
if (
|
||||
e.orig_exception.response
|
||||
and e.orig_exception.response.status_code == 404
|
||||
):
|
||||
self.message(
|
||||
self.MESSAGES.obj_not_found(
|
||||
obj='zone',
|
||||
id=self.id,
|
||||
)
|
||||
)
|
||||
self.exit(fail=True)
|
||||
raise e
|
||||
|
||||
self.facts = zone_model.model_dump()
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
133
library/decort_zone_list.py
Normal file
133
library/decort_zone_list.py
Normal file
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_zone_list
|
||||
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
|
||||
'''
|
||||
|
||||
from typing import Any
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.decort_utils import DecortController
|
||||
|
||||
from dynamix_sdk.base import get_alias, name_mapping_dict
|
||||
import dynamix_sdk.types as sdk_types
|
||||
|
||||
|
||||
class DecortZoneList(DecortController):
|
||||
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(
|
||||
filter=dict(
|
||||
type='dict',
|
||||
apply_defaults=True,
|
||||
options=dict(
|
||||
deletable=dict(
|
||||
type='bool',
|
||||
),
|
||||
description=dict(
|
||||
type='str',
|
||||
),
|
||||
grid_id=dict(
|
||||
type='int',
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
),
|
||||
name=dict(
|
||||
type='str',
|
||||
),
|
||||
node_id=dict(
|
||||
type='int',
|
||||
),
|
||||
status=dict(
|
||||
type='str',
|
||||
choices=sdk_types.ZoneStatus._member_names_,
|
||||
),
|
||||
),
|
||||
),
|
||||
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=(
|
||||
sdk_types.ZoneForListAPIResultNM
|
||||
.model_fields.keys()
|
||||
),
|
||||
required=True,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
@DecortController.handle_sdk_exceptions
|
||||
def run(self):
|
||||
self.get_info()
|
||||
self.exit()
|
||||
|
||||
def get_info(self):
|
||||
aparam_filter: dict[str, Any] = self.aparams['filter']
|
||||
aparam_status: str | None = aparam_filter['status']
|
||||
|
||||
aparam_pagination: dict[str, Any] = self.aparams['pagination']
|
||||
|
||||
aparam_sorting: dict[str, Any] | None = self.aparams['sorting']
|
||||
sort_by: str | None = None
|
||||
if aparam_sorting:
|
||||
sorting_field = get_alias(
|
||||
field_name=aparam_sorting['field'],
|
||||
model_cls=sdk_types.ZoneForListAPIResultNM,
|
||||
name_mapping_dict=name_mapping_dict,
|
||||
)
|
||||
sort_by_prefix = '+' if aparam_sorting['asc'] else '-'
|
||||
sort_by = f'{sort_by_prefix}{sorting_field}'
|
||||
|
||||
self.facts = self.api.cloudapi.zone.list(
|
||||
deletable=aparam_filter['deletable'],
|
||||
description=aparam_filter['description'],
|
||||
grid_id=aparam_filter['grid_id'],
|
||||
id=aparam_filter['id'],
|
||||
name=aparam_filter['name'],
|
||||
node_id=aparam_filter['node_id'],
|
||||
status=(
|
||||
sdk_types.ZoneStatus[aparam_status]
|
||||
if aparam_status else None
|
||||
),
|
||||
page_number=aparam_pagination['number'],
|
||||
page_size=aparam_pagination['size'],
|
||||
sort_by=sort_by,
|
||||
).model_dump()['data']
|
||||
|
||||
|
||||
def main():
|
||||
DecortZoneList().run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
-r requirements.txt
|
||||
pre-commit==4.1.0
|
||||
@@ -1,2 +1,3 @@
|
||||
ansible==11.6.0
|
||||
requests==2.32.3
|
||||
git+https://repository.basistech.ru/BASIS/dynamix-python-sdk.git@1.4.latest
|
||||
|
||||
Reference in New Issue
Block a user