diff --git a/CHANGELOG.md b/CHANGELOG.md index 12bb71691..47d02b352 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## v1.5.0 (26 Aug 2022) + +**Features** + +**Prism Central Disaster Recovery** +- Ansible module for Protection Rules +- Ansible info module for Protection Rules +- Ansible module for Recovery Plans +- Ansible info module Recovery Plans +- Ansible module for Recovery Plan Jobs +- Ansible info module Recovery Plan Jobs + +**Full Changelog:** [here](https://github.com/nutanix/nutanix.ansible/compare/v1.4.0...v1.5.0) + ## v1.4.0 (28 July 2022) **Features** diff --git a/README.md b/README.md index 135e1d525..ecc8d8ad7 100644 --- a/README.md +++ b/README.md @@ -8,15 +8,17 @@ It is designed keeping simplicity as the core value. Hence it is 1. Easy to use 2. Easy to develop +Checkout this [blog](https://www.nutanix.dev/2022/08/05/getting-started-with-the-nutanix-ansible-module/) for getting started with nutanix ansible module. + # Version compatibility ## Ansible -> This collection has been tested against following versions: +This collection has been tested against following versions: 1. ansible==5.0.1 2. ansible-core==2.12.3 ## Python -> This collection requires Python 2.7 or greater +This collection requires Python 2.7 or greater ## Prism Cenral > For the 1.1.0 release of the ansible plugin it will have N-2 compatibility with the Prism Central APIs. This release was tested against Prism Central versions pc2022.1.0.2, pc.2021.9.0.5 and pc.2021.8.0.1. @@ -27,6 +29,8 @@ It is designed keeping simplicity as the core value. Hence it is > For the 1.4.0 release of the ansible plugin it will have N-2 compatibility with the Prism Central APIs. This release was tested against Prism Central versions pc.2022.4, pc2022.1.0.2 and pc.2021.9.0.4. +> For the 1.5.0 release of the ansible plugin it will have N-2 compatibility with the Prism Central APIs. This release was tested against Prism Central versions pc.2022.6, pc.2022.4.0.2 and pc2022.1.0.2. + ### Notes: 1. Static routes module (ntnx_static_routes) is supported for PC versions >= pc.2022.1 @@ -131,6 +135,12 @@ ansible-playbook examples/iaas/iaas.yml | ntnx_permissions_info | List permissions info | | ntnx_projects | create, update and delete pc projects | | ntnx_projects_info | Get projects info. | +| ntnx_protection_rules | create, update and delete pc protection rules | +| ntnx_protection_rules_info | Get pc protection rules info. | +| ntnx_recovery_plans | create, update and delete pc recovery plans | +| ntnx_recovery_plans_info | Get pc recovery plans info. | +| ntnx_recovery_plan_jobs | create and perform action on pc recovery plans | +| ntnx_recovery_plan_jobs_info | Get pc recovery plan jobs info. | | ntnx_roles | Create, Update, Delete Nutanix roles | | ntnx_roles_info | Get roles info. | | ntnx_security_rules | Create, update or delete a Security Rule. | diff --git a/examples/dr/protection_policy.yml b/examples/dr/protection_policy.yml new file mode 100644 index 000000000..2a13f786f --- /dev/null +++ b/examples/dr/protection_policy.yml @@ -0,0 +1,168 @@ +######## Description ########### +# Tasks done by this playbook: +# 1. Create synchronous protection policy and asynchronous protection policy +# 2. Update protection policy +# 3. Get created protection plans info and associated entities +# 4. Delete protection plan from primary site. +################################# + + +- name: PC DR + hosts: localhost + gather_facts: false + collections: + - nutanix.ncp + tasks: + - name: Create protection rule with synchronous schedule + ntnx_protection_rules: + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + state: present + wait: True + name: test-ansible + desc: test-ansible-desc + protected_categories: + Environment: + - Dev + - Staging + primary_site: + availability_zone_url: "" + schedules: + - source: + availability_zone_url: "" + destination: + availability_zone_url: "" + protection_type: SYNC + auto_suspend_timeout: 20 + - source: + availability_zone_url: "" + destination: + availability_zone_url: "" + protection_type: SYNC + auto_suspend_timeout: 10 + register: pr + + - name: delete the protection rule + ntnx_protection_rules: + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + state: "absent" + rule_uuid: "{{pr.rule_uuid}}" + + - name: Create protection rule with async schedule + ntnx_protection_rules: + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + state: present + wait: True + name: test-ansible-1 + desc: test-ansible-desc-1 + protected_categories: + Environment: + - Dev + - Testing + primary_site: + availability_zone_url: "" + schedules: + - source: + availability_zone_url: "" + destination: + availability_zone_url: "" + protection_type: ASYNC + rpo: 1 + rpo_unit: HOUR + snapshot_type: "CRASH_CONSISTENT" + local_retention_policy: + num_snapshots: 1 + remote_retention_policy: + rollup_retention_policy: + snapshot_interval_type: HOURLY + multiple: 2 + + - source: + availability_zone_url: "" + destination: + availability_zone_url: "" + protection_type: ASYNC + rpo: 1 + rpo_unit: HOUR + snapshot_type: "CRASH_CONSISTENT" + local_retention_policy: + num_snapshots: 2 + remote_retention_policy: + num_snapshots: 1 + register: result + + - name: Update previously created protection policy + ntnx_protection_rules: + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + state: present + wait: True + rule_uuid: "{{result.rule_uuid}}" + name: test-ansible-updated + desc: test-ansible-desc-updated + protected_categories: + Environment: + - Testing + primary_site: + availability_zone_url: "" + schedules: + - source: + availability_zone_url: "" + destination: + availability_zone_url: "" + protection_type: ASYNC + rpo: 2 + rpo_unit: DAY + snapshot_type: "APPLICATION_CONSISTENT" + local_retention_policy: + num_snapshots: 1 + remote_retention_policy: + rollup_retention_policy: + snapshot_interval_type: YEARLY + multiple: 2 + + - source: + availability_zone_url: "" + destination: + availability_zone_url: "" + protection_type: ASYNC + rpo: 2 + rpo_unit: DAY + snapshot_type: "APPLICATION_CONSISTENT" + local_retention_policy: + num_snapshots: 1 + remote_retention_policy: + num_snapshots: 2 + register: pr + + - name: Get protection policy info and its associated vms info + ntnx_protection_rules_info: + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + rule_uuid: "{{pr.rule_uuid}}" + register: result + + - debug: + msg: "{{result}}" + + - name: delete the protection rule + ntnx_protection_rules: + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + state: "absent" + rule_uuid: "{{pr.rule_uuid}}" + \ No newline at end of file diff --git a/examples/dr/recovery_plan_with_execution.yml b/examples/dr/recovery_plan_with_execution.yml new file mode 100644 index 000000000..b99c92c29 --- /dev/null +++ b/examples/dr/recovery_plan_with_execution.yml @@ -0,0 +1,180 @@ +######## Description ########### +# Tasks done by this playbook: +# 1. Create Recovery plan using ntnx_recovery_plans +# 2. Update recovery plan stages and networks +# 3. Get created recovery plan info and affected entities +# 4. Use this info to run test failover on recovery site using ntnx_recovery_plan_jobs +# 5. Run cleanup of vms created by test failover on recovery site +# 6. Get final status of both recovery plan jobs using info module +# 7. Delete recovery plan from primary site. +################################# +- name: PC DR + hosts: localhost + gather_facts: false + collections: + - nutanix.ncp + tasks: +################################# Create recovery plans using ntnx_recovery_plans ############# + - name: Create recovery plan with custom ip network mapping + ntnx_recovery_plans: + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + state: "present" + name: example-rp + desc: recovery plan desc + stages: + - vms: + - name: "test-check" + enable_script_exec: true + delay: 10 + primary_location: + url: "" + recovery_location: + url: "" + network_type: NON_STRETCH + network_mappings: + - primary: + test: + name: "" + gateway_ip: "xx.xx.xx.xx" + prefix: "24" + custom_ip_config: + - vm: + name: "test-check" + ip: "xx.xx.xx.xx" + prod: + name: "" + gateway_ip: "xx.xx.xx.xx" + prefix: "24" + custom_ip_config: + - vm: + name: "test-check" + ip: "xx.xx.xx.xx" + recovery: + test: + name: "" + gateway_ip: "xx.xx.xx.xx" + prefix: "24" + custom_ip_config: + - vm: + name: "test-check" + ip: "xx.xx.xx.xx" + prod: + name: "" + gateway_ip: "xx.xx.xx.xx" + prefix: "24" + custom_ip_config: + - vm: + name: "test-check" + ip: "xx.xx.xx.xx" + register: result + + + - debug: + msg: "{{result}}" + + + - name: Update recovery plan by adding more stages and remove custom IP to enable dynamic IP allocation + ntnx_recovery_plans: + plan_uuid: "{{result.plan_uuid}}" + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + state: "present" + name: example-rp-updated + desc: recovery plan desc updated + stages: + - vms: + - name: "test-check" + enable_script_exec: true + categories: + - key: Environment + value: Staging + enable_script_exec: true + delay: 2 + - categories: + - key: Environment + value: Dev + primary_location: + url: "" + recovery_location: + url: "" + network_type: NON_STRETCH + network_mappings: + - primary: + test: + name: "" + prod: + name: "" + recovery: + test: + name: "" + prod: + name: "" + register: recovery_plan + + +#################################### Lets recover the vms on recovery site using ntnx_recovery_plan_jobs ################ + + - name: recovery plan info and its affected entities get + ntnx_recovery_plans_info: + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + plan_uuid: "{{recovery_plan.plan_uuid}}" + register: recovery_plan_info + + - debug: + msg: "{{recovery_plan_info}}" + + # We can also perform FAILOVER, LIVE_MIGRATE and FAILOVER here + - name: Run migrate (planned failover) + ntnx_recovery_plan_jobs: + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + state: "present" + name: test-failover-123 + recovery_plan: + uuid: "{{recovery_plan.plan_uuid}}" + failed_site: + url: "" + recovery_site: + url: "" + action: MIGRATE + ignore_validation_failures: true + register: migrate_job + + - debug: + msg: "{{migrate_job}}" + + - name: Get recovery plan job status using info module + ntnx_recovery_plan_jobs_info: + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + job_uuid: "{{migrate_job.job_uuid}}" + register: result + ignore_errors: True + + - debug: + msg: "{{result}}" + + ###################################### delete the recovery plan ################# + + - name: Delete recovery plan + ntnx_recovery_plans: + nutanix_host: "" + nutanix_username: "" + nutanix_password: "" + validate_certs: false + job_uuid: "{{migrate_job.job_uuid}}" + plan_uuid: "{{recovery_plan.plan_uuid}}" + state: "absent" + register: result \ No newline at end of file diff --git a/plugins/modules/ntnx_protection_rules.py b/plugins/modules/ntnx_protection_rules.py index fc2147c4b..a27b7d6c6 100644 --- a/plugins/modules/ntnx_protection_rules.py +++ b/plugins/modules/ntnx_protection_rules.py @@ -367,6 +367,176 @@ """ RETURN = r""" +api_version: + description: API Version of the Nutanix v3 API framework. + returned: always + type: str + sample: "3.1" +metadata: + description: The protection policy metadata + returned: always + type: dict + sample: { + "categories": {}, + "categories_mapping": {}, + "creation_time": "2022-08-26T07:06:25Z", + "kind": "protection_rule", + "last_update_time": "2022-08-26T07:06:26Z", + "owner_reference": { + "kind": "user", + "name": "admin", + "uuid": "00000000-0000-0000-0000-000000000000" + }, + "spec_hash": "00000000000000000000000000000000000000000000000000", + "spec_version": 0, + "uuid": "ccccccc-24ea-43cc-a779-8620d08de1ad" + } +spec: + description: An intentful representation of a protection rule spec + returned: always + type: dict + sample: { + "description": "test-ansible-desc", + "name": "test-ansible", + "resources": { + "availability_zone_connectivity_list": [ + { + "destination_availability_zone_index": 1, + "snapshot_schedule_list": [ + { + "local_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "recovery_point_objective_secs": 3600, + "remote_snapshot_retention_policy": { + "rollup_retention_policy": { + "multiple": 2, + "snapshot_interval_type": "HOURLY" + } + }, + "snapshot_type": "CRASH_CONSISTENT" + } + ], + "source_availability_zone_index": 0 + }, + { + "destination_availability_zone_index": 0, + "snapshot_schedule_list": [ + { + "local_snapshot_retention_policy": { + "num_snapshots": 2 + }, + "recovery_point_objective_secs": 3600, + "remote_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "snapshot_type": "CRASH_CONSISTENT" + } + ], + "source_availability_zone_index": 1 + } + ], + "category_filter": { + "params": { + "Environment": [ + "Dev", + "Staging" + ] + }, + "type": "CATEGORIES_MATCH_ANY" + }, + "ordered_availability_zone_list": [ + { + "availability_zone_url": "az1-url" + }, + { + "availability_zone_url": "az2-url" + } + ], + "primary_location_list": [ + 0 + ] + } + } +status: + description: An intentful representation of a protection policy status + returned: always + type: dict + sample: { + "description": "test-ansible-desc", + "execution_context": { + "task_uuid": [ + "asdse03b4-e272-45df-93eb-afe0749b761b" + ] + }, + "name": "test-ansible", + "resources": { + "availability_zone_connectivity_list": [ + { + "destination_availability_zone_index": 1, + "snapshot_schedule_list": [ + { + "local_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "recovery_point_objective_secs": 3600, + "remote_snapshot_retention_policy": { + "rollup_retention_policy": { + "multiple": 2, + "snapshot_interval_type": "HOURLY" + } + }, + "snapshot_type": "CRASH_CONSISTENT" + } + ], + "source_availability_zone_index": 0 + }, + { + "destination_availability_zone_index": 0, + "snapshot_schedule_list": [ + { + "local_snapshot_retention_policy": { + "num_snapshots": 2 + }, + "recovery_point_objective_secs": 3600, + "remote_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "snapshot_type": "CRASH_CONSISTENT" + } + ], + "source_availability_zone_index": 1 + } + ], + "category_filter": { + "params": { + "Environment": [ + "Dev", + "Staging" + ] + }, + "type": "CATEGORIES_MATCH_ANY" + }, + "ordered_availability_zone_list": [ + { + "availability_zone_url": "az1-url" + }, + { + "availability_zone_url": "az2-url" + } + ], + "primary_location_list": [ + 0 + ], + "start_time": "" + }, + "state": "COMPLETE" + } +rule_uuid: + description: The created protection rule uuid + returned: always + type: str + sample: "ccccccc-24ea-43cc-a779-8620d08de1ad" """ from ..module_utils import utils # noqa: E402 diff --git a/plugins/modules/ntnx_protection_rules_info.py b/plugins/modules/ntnx_protection_rules_info.py index 96d0ca974..218581dd9 100644 --- a/plugins/modules/ntnx_protection_rules_info.py +++ b/plugins/modules/ntnx_protection_rules_info.py @@ -58,6 +58,175 @@ """ RETURN = r""" +rule_affected_entities: + description: + - affected entities to protection policy + - only obtained when uuid is used for getting info of protection policy + returned: always + type: dict + sample: { + "entity_list": [ + { + "vm_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "asdasds-490b-498a-a51c-2a13c38582cc" + } + } + ] + } +rule_info: + description: + - intent response of protection policy + - only obtained when uuid is used for getting info of protection policy + returned: always + type: dict + sample: { + "api_version": "3.1", + "metadata": { + "categories": {}, + "categories_mapping": {}, + "creation_time": "2022-08-26T10:56:08Z", + "kind": "protection_rule", + "last_update_time": "2022-08-26T12:02:42Z", + "owner_reference": { + "kind": "user", + "name": "admin", + "uuid": "00000000-0000-0000-0000-000000000000" + }, + "spec_hash": "00000000000000000000000000000000000000000000000000", + "spec_version": 1, + "uuid": "asdasasdda-7a99-43ea-b49e-9120f955a518" + }, + "spec": { + "name": "test-check", + "resources": { + "availability_zone_connectivity_list": [ + { + "destination_availability_zone_index": 1, + "snapshot_schedule_list": [ + { + "local_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "recovery_point_objective_secs": 3600, + "remote_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "snapshot_type": "CRASH_CONSISTENT" + } + ], + "source_availability_zone_index": 0 + }, + { + "destination_availability_zone_index": 0, + "snapshot_schedule_list": [ + { + "local_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "recovery_point_objective_secs": 3600, + "remote_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "snapshot_type": "CRASH_CONSISTENT" + } + ], + "source_availability_zone_index": 1 + } + ], + "category_filter": { + "params": { + "Environment": [ + "Staging" + ] + }, + "type": "CATEGORIES_MATCH_ANY" + }, + "ordered_availability_zone_list": [ + { + "availability_zone_url": "az1-url", + "cluster_uuid": "c1uuid" + }, + { + "availability_zone_url": "az2-url", + "cluster_uuid": "c2uuid" + } + ], + "primary_location_list": [ + 0 + ] + } + }, + "status": { + "description": "", + "execution_context": { + "task_uuid": [ + "asdasd-8d8d-4dc9-87ad-5e66530bcfab" + ] + }, + "name": "test-check", + "resources": { + "availability_zone_connectivity_list": [ + { + "destination_availability_zone_index": 1, + "snapshot_schedule_list": [ + { + "local_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "recovery_point_objective_secs": 3600, + "remote_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "snapshot_type": "CRASH_CONSISTENT" + } + ], + "source_availability_zone_index": 0 + }, + { + "destination_availability_zone_index": 0, + "snapshot_schedule_list": [ + { + "local_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "recovery_point_objective_secs": 3600, + "remote_snapshot_retention_policy": { + "num_snapshots": 1 + }, + "snapshot_type": "CRASH_CONSISTENT" + } + ], + "source_availability_zone_index": 1 + } + ], + "category_filter": { + "params": { + "Environment": [ + "Staging" + ] + }, + "type": "CATEGORIES_MATCH_ANY" + }, + "ordered_availability_zone_list": [ + { + "availability_zone_url": "az1-url", + "cluster_uuid": "c1uuid" + }, + { + "availability_zone_url": "az2-url", + "cluster_uuid": "c2uuid" + } + ], + "primary_location_list": [ + 0 + ], + "start_time": "" + }, + "state": "COMPLETE" + } + } """ from ..module_utils.base_info_module import BaseInfoModule # noqa: E402 diff --git a/plugins/modules/ntnx_recovery_plan_jobs.py b/plugins/modules/ntnx_recovery_plan_jobs.py index a08caa292..a1acfb586 100644 --- a/plugins/modules/ntnx_recovery_plan_jobs.py +++ b/plugins/modules/ntnx_recovery_plan_jobs.py @@ -170,6 +170,250 @@ """ RETURN = r""" +api_version: + description: API Version of the Nutanix v3 API framework. + returned: always + type: str + sample: "3.1" +metadata: + description: The recovery plan jobs's kind metadata + returned: always + type: dict + sample: { + "kind": "recovery_plan_job", + "name": "test-failover-123", + "uuid": "adasds-d541-4df8-ab0e-53b2b62519b3" + } +status: + description: An intentful job and its execution status of a recovery plan job + returned: always + type: dict + sample: { + "end_time": "2022-08-26T11:35:49Z", + "execution_status": { + "operation_status": { + "percentage_complete": 100, + "status": "COMPLETED" + }, + "percentage_complete": 100, + "postprocessing_status": { + "percentage_complete": 100, + "status": "COMPLETED" + }, + "preprocessing_status": { + "percentage_complete": 100, + "status": "COMPLETED" + }, + "status": "COMPLETED_WITH_WARNING" + }, + "name": "test-failover-123", + "recovery_plan_specification": { + "description": "recovery plan desc updated", + "name": "example-rp-updated", + "resources": { + "parameters": { + "availability_zone_list": [ + { + "availability_zone_url": "az1-url" + }, + { + "availability_zone_url":"az2-url" + } + ], + "network_mapping_list": [ + { + "are_networks_stretched": false, + "availability_zone_network_mapping_list": [ + { + "availability_zone_url": "az1-url", + "recovery_network": { + "name": "vlan" + }, + "test_network": { + "name": "vlan" + } + }, + { + "availability_zone_url":"az2-url", + "recovery_network": { + "name": "vlan" + }, + "test_network": { + "name": "vlan" + } + } + ] + } + ], + "primary_location_index": 0 + }, + "stage_list": [ + { + "delay_time_secs": 2, + "stage_uuid": "3aa0a257-ca5d-4a17-b19f-36918cfa7dd0", + "stage_work": { + "recover_entities": { + "entity_info_list": [ + { + "any_entity_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "asdasds-490b-498a-a51c-2a13c38582cc" + }, + "script_list": [ + { + "enable_script_exec": true + } + ] + }, + { + "categories": { + "Environment": "Staging" + }, + "script_list": [ + { + "enable_script_exec": true + } + ] + } + ] + } + } + }, + { + "stage_uuid": "e9bb2595-9bc7-4630-a87c-8499203d8c23", + "stage_work": { + "recover_entities": { + "entity_info_list": [ + { + "categories": { + "Environment": "Dev" + } + } + ] + } + } + } + ] + } + }, + "resources": { + "execution_parameters": { + "action_type": "MIGRATE", + "failed_availability_zone_list": [ + { + "availability_zone_url": "az1-url" + } + ], + "recovery_availability_zone_list": [ + { + "availability_zone_url":"az2-url" + } + ] + }, + "recovery_plan_reference": { + "kind": "recovery_plan", + "uuid": "adasdsd-9afe-477d-90c3-8cd6bec88b2d" + } + }, + "start_time": "2022-08-26T11:33:51Z", + "validation_information": { + "errors_list": [], + "warnings_list": [ + { + "affected_any_reference_list": [ + { + "kind": "vm", + "name": "test-check", + "uuid": "asdasds-490b-498a-a51c-2a13c38582cc" + } + ], + "cause_and_resolution_message_list": [ + { + "cause": "VMs are unprotected.", + "resolution_list": ["xx", "xx"] + } + ], + "impact_message_list": ["xx", "xx"], + "message": "xyz", + "validation_type": "ENTITY" + }, + { + "affected_any_reference_list": [ + { + "kind": "vm", + "name": "test-check", + "uuid": "dasdadasd-490b-498a-a51c-2a13c38582cc" + } + ], + "cause_and_resolution_message_list": [ + { + "cause": "xyz", + "resolution_list": ["xx", "xx"] + } + ], + "impact_message_list": [ + "The post recovery script execution will fail." + ], + "message": "xyz", + "validation_type": "ENTITY" + }, + { + "affected_any_reference_list": [ + { + "kind": "vm", + "name": "test-check", + "uuid": "adssasd-490b-498a-a51c-2a13c38582cc" + } + ], + "cause_and_resolution_message_list": [ + { + "cause": "Entities might also be present as part of a category specified in the Recovery Plan.", + "resolution_list": ["xx", "xx"] + } + ], + "impact_message_list": [ + "xyz" + ], + "message": "Duplicate instances exist for one or more of the entities in the Recovery Plan.", + "validation_type": "ENTITY" + }, + { + "affected_any_reference_list": [], + "cause_and_resolution_message_list": [ + { + "cause": "xyz", + "resolution_list": ["xx", "xx"] + } + ], + "impact_message_list": [ + "No entity will be recovered for stage 2" + ], + "message": "No entity found for recovery for a stage 2.", + "validation_type": "ENTITY" + }, + { + "affected_any_reference_list": [], + "cause_and_resolution_message_list": [ + { + "cause": "The categories might no longer be in use.", + "resolution_list": ["xx", "xx"] + } + ], + "impact_message_list": [ + "No entities will be recovered for these categories." + ], + "message": "xxxxxxx", + "validation_type": "CATEGORY" + } + ] + } + } +job_uuid: + description: The created recovery plan job's uuid + returned: always + type: str + sample: "cccccc01-4232-4ba8-a125-a2478f9383a9" """ import time # noqa: E402 diff --git a/plugins/modules/ntnx_recovery_plan_jobs_info.py b/plugins/modules/ntnx_recovery_plan_jobs_info.py index 4d58fc970..c12374c4d 100644 --- a/plugins/modules/ntnx_recovery_plan_jobs_info.py +++ b/plugins/modules/ntnx_recovery_plan_jobs_info.py @@ -58,6 +58,251 @@ """ RETURN = r""" +api_version: + description: + - API Version of the Nutanix v3 API framework. + - only when when job info is obtained using uuid + returned: always + type: str + sample: "3.1" +metadata: + description: + - The recovery plan jobs's kind metadata + - only when when job info is obtained using uuid + returned: always + type: dict + sample: { + "kind": "recovery_plan_job", + "name": "test-failover-123", + "uuid": "adasds-d541-4df8-ab0e-53b2b62519b3" + } +status: + description: + - An intentful job and its execution status of a recovery plan job + - only when when job info is obtained using uuid + returned: always + type: dict + sample: { + "end_time": "2022-08-26T11:35:49Z", + "execution_status": { + "operation_status": { + "percentage_complete": 100, + "status": "COMPLETED" + }, + "percentage_complete": 100, + "postprocessing_status": { + "percentage_complete": 100, + "status": "COMPLETED" + }, + "preprocessing_status": { + "percentage_complete": 100, + "status": "COMPLETED" + }, + "status": "COMPLETED_WITH_WARNING" + }, + "name": "test-failover-123", + "recovery_plan_specification": { + "description": "recovery plan desc updated", + "name": "example-rp-updated", + "resources": { + "parameters": { + "availability_zone_list": [ + { + "availability_zone_url": "az1-url" + }, + { + "availability_zone_url":"az2-url" + } + ], + "network_mapping_list": [ + { + "are_networks_stretched": false, + "availability_zone_network_mapping_list": [ + { + "availability_zone_url": "az1-url", + "recovery_network": { + "name": "vlan" + }, + "test_network": { + "name": "vlan" + } + }, + { + "availability_zone_url":"az2-url", + "recovery_network": { + "name": "vlan" + }, + "test_network": { + "name": "vlan" + } + } + ] + } + ], + "primary_location_index": 0 + }, + "stage_list": [ + { + "delay_time_secs": 2, + "stage_uuid": "3aa0a257-ca5d-4a17-b19f-36918cfa7dd0", + "stage_work": { + "recover_entities": { + "entity_info_list": [ + { + "any_entity_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "asdasds-490b-498a-a51c-2a13c38582cc" + }, + "script_list": [ + { + "enable_script_exec": true + } + ] + }, + { + "categories": { + "Environment": "Staging" + }, + "script_list": [ + { + "enable_script_exec": true + } + ] + } + ] + } + } + }, + { + "stage_uuid": "e9bb2595-9bc7-4630-a87c-8499203d8c23", + "stage_work": { + "recover_entities": { + "entity_info_list": [ + { + "categories": { + "Environment": "Dev" + } + } + ] + } + } + } + ] + } + }, + "resources": { + "execution_parameters": { + "action_type": "MIGRATE", + "failed_availability_zone_list": [ + { + "availability_zone_url": "az1-url" + } + ], + "recovery_availability_zone_list": [ + { + "availability_zone_url":"az2-url" + } + ] + }, + "recovery_plan_reference": { + "kind": "recovery_plan", + "uuid": "adasdsd-9afe-477d-90c3-8cd6bec88b2d" + } + }, + "start_time": "2022-08-26T11:33:51Z", + "validation_information": { + "errors_list": [], + "warnings_list": [ + { + "affected_any_reference_list": [ + { + "kind": "vm", + "name": "test-check", + "uuid": "asdasds-490b-498a-a51c-2a13c38582cc" + } + ], + "cause_and_resolution_message_list": [ + { + "cause": "VMs are unprotected.", + "resolution_list": ["xx", "xx"] + } + ], + "impact_message_list": ["xx", "xx"], + "message": "xyz", + "validation_type": "ENTITY" + }, + { + "affected_any_reference_list": [ + { + "kind": "vm", + "name": "test-check", + "uuid": "dasdadasd-490b-498a-a51c-2a13c38582cc" + } + ], + "cause_and_resolution_message_list": [ + { + "cause": "xyz", + "resolution_list": ["xx", "xx"] + } + ], + "impact_message_list": [ + "The post recovery script execution will fail." + ], + "message": "xyz", + "validation_type": "ENTITY" + }, + { + "affected_any_reference_list": [ + { + "kind": "vm", + "name": "test-check", + "uuid": "adssasd-490b-498a-a51c-2a13c38582cc" + } + ], + "cause_and_resolution_message_list": [ + { + "cause": "xyz", + "resolution_list": ["xx", "xx"] + } + ], + "impact_message_list": [ + "xyz" + ], + "message": "Duplicate instances exist for one or more of the entities in the Recovery Plan.", + "validation_type": "ENTITY" + }, + { + "affected_any_reference_list": [], + "cause_and_resolution_message_list": [ + { + "cause": "xyz", + "resolution_list": ["xx", "xx"] + } + ], + "impact_message_list": [ + "No entity will be recovered for stage 2" + ], + "message": "No entity found for recovery for a stage 2.", + "validation_type": "ENTITY" + }, + { + "affected_any_reference_list": [], + "cause_and_resolution_message_list": [ + { + "cause": "The categories might no longer be in use.", + "resolution_list": ["xx", "xx"] + } + ], + "impact_message_list": [ + "No entities will be recovered for these categories." + ], + "message": "xxxxxxx", + "validation_type": "CATEGORY" + } + ] + } + } """ from ..module_utils.base_info_module import BaseInfoModule # noqa: E402 diff --git a/plugins/modules/ntnx_recovery_plans.py b/plugins/modules/ntnx_recovery_plans.py index 8b281c3d5..777ce9f2b 100644 --- a/plugins/modules/ntnx_recovery_plans.py +++ b/plugins/modules/ntnx_recovery_plans.py @@ -510,6 +510,366 @@ """ RETURN = r""" +api_version: + description: API Version of the Nutanix v3 API framework. + returned: always + type: str + sample: "3.1" +metadata: + description: The recovery plan's kind metadata + returned: always + type: dict + sample: { + "api_version": "3.1", + "metadata": { + "categories": {}, + "categories_mapping": {}, + "creation_time": "2022-08-26T11:28:03Z", + "kind": "recovery_plan", + "last_update_time": "2022-08-26T11:28:06Z", + "owner_reference": { + "kind": "user", + "name": "admin", + "uuid": "00000000-0000-0000-0000-000000000000" + }, + "spec_hash": "00000000000000000000000000000000000000000000000000", + "spec_version": 0, + "uuid": "730d6bc5-a243-4b24-80e1-07a795de94a4" + } + } +spec: + description: An intentful representation of a recovery plan spec + returned: always + type: dict + sample: { + "description": "recovery plan desc", + "name": "example-rp", + "resources": { + "parameters": { + "availability_zone_list": [ + { + "availability_zone_url": "az1-url" + }, + { + "availability_zone_url": "az2-url" + } + ], + "floating_ip_assignment_list": [], + "network_mapping_list": [ + { + "are_networks_stretched": false, + "availability_zone_network_mapping_list": [ + { + "availability_zone_url": "az1-url", + "recovery_ip_assignment_list": [ + { + "ip_config_list": [ + { + "ip_address": "cutom_ip_1" + } + ], + "vm_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "sdasdsd-490b-498a-a51c-2a13c38582cc" + } + } + ], + "recovery_network": { + "name": "vlan1", + "subnet_list": [ + { + "gateway_ip": "xx.xx.xx.xx", + "prefix_length": 24 + } + ] + }, + "test_ip_assignment_list": [ + { + "ip_config_list": [ + { + "ip_address": "xx.xx.xx.xx" + } + ], + "vm_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "df5bad89-490b-498a-a51c-2a13c38582cc" + } + } + ], + "test_network": { + "name": "vlan1", + "subnet_list": [ + { + "gateway_ip": "xx.xx.xx.xx", + "prefix_length": 24 + } + ] + } + }, + { + "availability_zone_url": "az2-url", + "recovery_ip_assignment_list": [ + { + "ip_config_list": [ + { + "ip_address": "xx.xx.xx.xx" + } + ], + "vm_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "dasdsdsd-490b-498a-a51c-2a13c38582cc" + } + } + ], + "recovery_network": { + "name": "vlan1", + "subnet_list": [ + { + "gateway_ip": "xx.xx.xx.xx", + "prefix_length": 24 + } + ] + }, + "test_ip_assignment_list": [ + { + "ip_config_list": [ + { + "ip_address": "xx.xx.xx.xx" + } + ], + "vm_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "asdasds-490b-498a-a51c-2a13c38582cc" + } + } + ], + "test_network": { + "name": "vlan1", + "subnet_list": [ + { + "gateway_ip": "xx.xx.xx.xx", + "prefix_length": 24 + } + ] + } + } + ] + } + ], + "primary_location_index": 0 + }, + "stage_list": [ + { + "delay_time_secs": 10, + "stage_uuid": "20967cc9-0dce-4e4c-86db-c27556137efd", + "stage_work": { + "recover_entities": { + "entity_info_list": [ + { + "any_entity_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "asdasdasd-490b-498a-a51c-2a13c38582cc" + }, + "script_list": [ + { + "enable_script_exec": true + } + ] + } + ] + } + } + } + ] + } + } +status: + description: An intentful representation of a recovery plan status + returned: always + type: dict + sample: { + "description": "recovery plan desc", + "execution_context": { + "task_uuid": [ + "e459dd06-7cf2-45f1-9f1f-04482b0e5a0a" + ] + }, + "latest_test_time": "", + "latest_validation_time": "", + "name": "example-rp", + "recovery_availability_zone_order_list": [ + { + "availability_zone_order_list": [ + [ + { + "availability_zone_url": "az1-url" + }, + { + "availability_zone_url": "az2-url" + } + ] + ], + "availability_zone_url": "az1-url" + } + ], + "resources": { + "parameters": { + "availability_zone_list": [ + { + "availability_zone_url": "az1-url" + }, + { + "availability_zone_url": "az2-url" + } + ], + "network_mapping_list": [ + { + "are_networks_stretched": false, + "availability_zone_network_mapping_list": [ + { + "availability_zone_url": "az1-url", + "recovery_ip_assignment_list": [ + { + "ip_config_list": [ + { + "ip_address": "xx.xx.xx.xx" + } + ], + "vm_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "asdasds-490b-498a-a51c-2a13c38582cc" + } + } + ], + "recovery_network": { + "name": "vlan1", + "subnet_list": [ + { + "external_connectivity_state": "DISABLED", + "gateway_ip": "xx.xx.xx.xx", + "prefix_length": 24 + } + ] + }, + "test_ip_assignment_list": [ + { + "ip_config_list": [ + { + "ip_address": "xx.xx.xx.xx" + } + ], + "vm_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "asdasds-490b-498a-a51c-2a13c38582cc" + } + } + ], + "test_network": { + "name": "vlan1", + "subnet_list": [ + { + "external_connectivity_state": "DISABLED", + "gateway_ip": "xx.xx.xx.xx", + "prefix_length": 24 + } + ] + } + }, + { + "availability_zone_url": "az2-url", + "recovery_ip_assignment_list": [ + { + "ip_config_list": [ + { + "ip_address": "xx.xx.xx.xx" + } + ], + "vm_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "adasds-490b-498a-a51c-2a13c38582cc" + } + } + ], + "recovery_network": { + "name": "vlan1", + "subnet_list": [ + { + "external_connectivity_state": "DISABLED", + "gateway_ip": "xx.xx.xx.xx", + "prefix_length": 24 + } + ] + }, + "test_ip_assignment_list": [ + { + "ip_config_list": [ + { + "ip_address": "xx.xx.xx.xx" + } + ], + "vm_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "adasds-490b-498a-a51c-2a13c38582cc" + } + } + ], + "test_network": { + "name": "vlan1", + "subnet_list": [ + { + "external_connectivity_state": "DISABLED", + "gateway_ip": "xx.xx.xx.xx", + "prefix_length": 24 + } + ] + } + } + ] + } + ], + "primary_location_index": 0 + }, + "stage_list": [ + { + "delay_time_secs": 10, + "stage_uuid": "626eeb24-fd45-426e-90de-6535f8a6b59c", + "stage_work": { + "recover_entities": { + "entity_info_list": [ + { + "any_entity_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "asdasd-490b-498a-a51c-2a13c38582cc" + }, + "script_list": [ + { + "enable_script_exec": true + } + ] + } + ] + } + } + } + ] + }, + "state": "COMPLETE" + } +plan_uuid: + description: The created recovery plan's uuid + returned: always + type: str + sample: "cccccc01-4232-4ba8-a125-a2478f9383a9" """ from ..module_utils import utils # noqa: E402 diff --git a/plugins/modules/ntnx_recovery_plans_info.py b/plugins/modules/ntnx_recovery_plans_info.py index 82229bd52..6ec1e4222 100644 --- a/plugins/modules/ntnx_recovery_plans_info.py +++ b/plugins/modules/ntnx_recovery_plans_info.py @@ -55,7 +55,287 @@ register: result """ RETURN = r""" - +associated_entities: + description: + - associated entities to recovery plan + - only obtained when uuid is used for getting info of recovery plan + returned: always + type: dict + sample: { + "entities_per_availability_zone_list": [ + { + "availability_zone_order_list": [ + { + "availability_zone_list": [ + { + "availability_zone_url": "az1-url" + }, + { + "availability_zone_url": "az2-url" + } + ] + } + ], + "availability_zone_url": "az1-url", + "entity_list": [ + { + "any_entity_reference": { + "kind": "vm", + "name": "test-check-63", + "uuid": "da240e012e-d099-4acd-a8b0-ee33f4d45a25" + }, + "is_recovery_point": false, + "recovery_availability_zone_order_index": 0 + }, + { + "any_entity_reference": { + "kind": "vm", + "name": "integration_test_dr_vm", + "uuid": "da76qwe13-4ad0-4231-b376-16b3fa2da0cf" + }, + "is_recovery_point": true, + "recovery_availability_zone_order_index": 0 + }, + { + "any_entity_reference": { + "kind": "vm", + "name": "integration_test_dr_vm", + "uuid": "da76qwe13-4ad0-4231-b376-16b3fa2da0cf" + }, + "is_recovery_point": false, + "recovery_availability_zone_order_index": 0 + } + ] + } + ] + } +recovery_plan_info: + description: + - recovery plan intent response + - only obtained when uuid is used for getting info of recovery plan + returned: always + type: dict + sample: { + "api_version": "3.1", + "metadata": { + "categories": {}, + "categories_mapping": {}, + "creation_time": "2022-08-26T11:16:33Z", + "kind": "recovery_plan", + "last_update_time": "2022-08-26T11:16:48Z", + "owner_reference": { + "kind": "user", + "name": "admin", + "uuid": "00000000-0000-0000-0000-000000000000" + }, + "spec_hash": "00000000000000000000000000000000000000000000000000", + "spec_version": 1, + "uuid": "4312fc47-6d3a-44df-bb64-d17e095203f2" + }, + "spec": { + "description": "recovery plan desc updated", + "name": "example-rp-updated", + "resources": { + "parameters": { + "availability_zone_list": [ + { + "availability_zone_url": "az1-url" + }, + { + "availability_zone_url": "az2-url" + } + ], + "network_mapping_list": [ + { + "are_networks_stretched": false, + "availability_zone_network_mapping_list": [ + { + "availability_zone_url": "az1-url", + "recovery_network": { + "name": "vlan1" + }, + "test_network": { + "name": "vlan1" + } + }, + { + "availability_zone_url": "az2-url", + "recovery_network": { + "name": "vlan1" + }, + "test_network": { + "name": "vlan2" + } + } + ] + } + ], + "primary_location_index": 0 + }, + "stage_list": [ + { + "delay_time_secs": 2, + "stage_uuid": "da6a7469-2b6a-4b69-a181-53814fb08e0b", + "stage_work": { + "recover_entities": { + "entity_info_list": [ + { + "any_entity_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "asdsadsd-7c0e-4214-9785-6949a2c7369a" + }, + "script_list": [ + { + "enable_script_exec": true + } + ] + }, + { + "categories": { + "Environment": "Staging" + }, + "script_list": [ + { + "enable_script_exec": true + } + ] + } + ] + } + } + }, + { + "stage_uuid": "ad914f0a-1ec3-4eb1-a8ce-ce6de230477f", + "stage_work": { + "recover_entities": { + "entity_info_list": [ + { + "categories": { + "Environment": "Dev" + } + } + ] + } + } + } + ] + } + }, + "status": { + "description": "recovery plan desc updated", + "execution_context": { + "task_uuid": [ + "946336ac-9ee9-4df2-bfe2-7e9ff4f3ce25" + ] + }, + "latest_test_time": "", + "latest_validation_time": "", + "name": "example-rp-updated", + "recovery_availability_zone_order_list": [ + { + "availability_zone_order_list": [ + [ + { + "availability_zone_url": "az1-url" + }, + { + "availability_zone_url": "az2-url" + } + ] + ], + "availability_zone_url": "az1-url" + } + ], + "resources": { + "parameters": { + "availability_zone_list": [ + { + "availability_zone_url": "az1-url" + }, + { + "availability_zone_url": "az2-url" + } + ], + "network_mapping_list": [ + { + "are_networks_stretched": false, + "availability_zone_network_mapping_list": [ + { + "availability_zone_url": "az1-url", + "recovery_network": { + "name": "vlan1" + }, + "test_network": { + "name": "vlan1" + } + }, + { + "availability_zone_url": "az2-url", + "recovery_network": { + "name": "vlan1" + }, + "test_network": { + "name": "vlan1" + } + } + ] + } + ], + "primary_location_index": 0 + }, + "stage_list": [ + { + "delay_time_secs": 2, + "stage_uuid": "da6a7469-2b6a-4b69-a181-53814fb08e0b", + "stage_work": { + "recover_entities": { + "entity_info_list": [ + { + "any_entity_reference": { + "kind": "vm", + "name": "test-check", + "uuid": "asasda-7c0e-4214-9785-6949a2c7369a" + }, + "script_list": [ + { + "enable_script_exec": true + } + ] + }, + { + "categories": { + "Environment": "Staging" + }, + "script_list": [ + { + "enable_script_exec": true + } + ] + } + ] + } + } + }, + { + "stage_uuid": "ad914f0a-1ec3-4eb1-a8ce-ce6de230477f", + "stage_work": { + "recover_entities": { + "entity_info_list": [ + { + "categories": { + "Environment": "Dev" + } + } + ] + } + } + } + ] + }, + "state": "COMPLETE" + } + } """