summaryrefslogtreecommitdiffstats
path: root/ansible_collections/dellemc/unity/plugins/modules/snapshotschedule.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
commit975f66f2eebe9dadba04f275774d4ab83f74cf25 (patch)
tree89bd26a93aaae6a25749145b7e4bca4a1e75b2be /ansible_collections/dellemc/unity/plugins/modules/snapshotschedule.py
parentInitial commit. (diff)
downloadansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.tar.xz
ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.zip
Adding upstream version 7.7.0+dfsg.upstream/7.7.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/dellemc/unity/plugins/modules/snapshotschedule.py')
-rw-r--r--ansible_collections/dellemc/unity/plugins/modules/snapshotschedule.py1002
1 files changed, 1002 insertions, 0 deletions
diff --git a/ansible_collections/dellemc/unity/plugins/modules/snapshotschedule.py b/ansible_collections/dellemc/unity/plugins/modules/snapshotschedule.py
new file mode 100644
index 000000000..aba5524cd
--- /dev/null
+++ b/ansible_collections/dellemc/unity/plugins/modules/snapshotschedule.py
@@ -0,0 +1,1002 @@
+#!/usr/bin/python
+# Copyright: (c) 2020, Dell Technologies
+
+# Apache License version 2.0 (see MODULE-LICENSE or http://www.apache.org/licenses/LICENSE-2.0.txt)
+
+"""Ansible module for managing snapshot schedules on Unity"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = r"""
+module: snapshotschedule
+version_added: '1.1.0'
+short_description: Manage snapshot schedules on Unity storage system
+description:
+- Managing snapshot schedules on Unity storage system includes
+ creating new snapshot schedule, getting details of snapshot schedule,
+ modifying attributes of snapshot schedule, and deleting snapshot schedule.
+
+extends_documentation_fragment:
+ - dellemc.unity.unity
+
+author:
+- Akash Shendge (@shenda1) <ansible.team@dell.com>
+
+options:
+ name:
+ description:
+ - The name of the snapshot schedule.
+ - Name is mandatory for a create operation.
+ - Specify either I(name) or I(id) (but not both) for any operation.
+ type: str
+ id:
+ description:
+ - The ID of the snapshot schedule.
+ type: str
+ type:
+ description:
+ - Type of the rule to be included in snapshot schedule.
+ - Type is mandatory for any create or modify operation.
+ - Once the snapshot schedule is created with one type it can be modified.
+ type: str
+ choices: ['every_n_hours', 'every_day', 'every_n_days', 'every_week',
+ 'every_month']
+ interval:
+ description:
+ - Number of hours between snapshots.
+ - Applicable only when rule type is C(every_n_hours).
+ type: int
+ hours_of_day:
+ description:
+ - Hours of the day when the snapshot will be taken.
+ - Applicable only when rule type is C(every_day).
+ type: list
+ elements: int
+ day_interval:
+ description:
+ - Number of days between snapshots.
+ - Applicable only when rule type is C(every_n_days).
+ type: int
+ days_of_week:
+ description:
+ - Days of the week for which the snapshot schedule rule applies.
+ - Applicable only when rule type is C(every_week).
+ type: list
+ elements: str
+ choices: ['SUNDAY', 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY',
+ 'FRIDAY', 'SATURDAY']
+ day_of_month:
+ description:
+ - Day of the month for which the snapshot schedule rule applies.
+ - Applicable only when rule type is C(every_month).
+ - Value should be [1, 31].
+ type: int
+ hour:
+ description:
+ - The hour when the snapshot will be taken.
+ - Applicable for C(every_n_days), C(every_week), C(every_month) rule types.
+ - For create operation, if I(hour) parameter is not specified, value will
+ be taken as C(0).
+ - Value should be [0, 23].
+ type: int
+ minute:
+ description:
+ - Minute offset from the hour when the snapshot will be taken.
+ - Applicable for all rule types.
+ - For a create operation, if I(minute) parameter is not specified, value will
+ be taken as C(0).
+ - Value should be [0, 59].
+ type: int
+ desired_retention:
+ description:
+ - The number of days/hours for which snapshot will be retained.
+ - When I(auto_delete) is C(true), I(desired_retention) cannot be specified.
+ - Maximum desired retention supported is 31 days or 744 hours.
+ type: int
+ retention_unit:
+ description:
+ - The retention unit for the snapshot.
+ default: 'hours'
+ type: str
+ choices: ['hours' , 'days']
+ auto_delete:
+ description:
+ - Indicates whether the system can automatically delete the snapshot.
+ type: bool
+ state:
+ description:
+ - Define whether the snapshot schedule should exist or not.
+ type: str
+ required: true
+ choices: [absent, present]
+notes:
+- Snapshot schedule created through Ansible will have only one rule.
+- Modification of rule type is not allowed. Within the same type, other
+ parameters can be modified.
+- If an existing snapshot schedule has more than 1 rule in it, only get and
+ delete operation is allowed.
+- The I(check_mode) is not supported.
+"""
+
+EXAMPLES = r"""
+- name: Create snapshot schedule (Rule Type - every_n_hours)
+ dellemc.unity.snapshotschedule:
+ unispherehost: "{{unispherehost}}"
+ validate_certs: "{{validate_certs}}"
+ username: "{{username}}"
+ password: "{{password}}"
+ name: "Ansible_Every_N_Hours_Testing"
+ type: "every_n_hours"
+ interval: 6
+ desired_retention: 24
+ state: "{{state_present}}"
+
+- name: Create snapshot schedule (Rule Type - every_day)
+ dellemc.unity.snapshotschedule:
+ unispherehost: "{{unispherehost}}"
+ validate_certs: "{{validate_certs}}"
+ username: "{{username}}"
+ password: "{{password}}"
+ name: "Ansible_Every_Day_Testing"
+ type: "every_day"
+ hours_of_day:
+ - 8
+ - 14
+ auto_delete: True
+ state: "{{state_present}}"
+
+- name: Create snapshot schedule (Rule Type - every_n_days)
+ dellemc.unity.snapshotschedule:
+ unispherehost: "{{unispherehost}}"
+ validate_certs: "{{validate_certs}}"
+ username: "{{username}}"
+ password: "{{password}}"
+ name: "Ansible_Every_N_Day_Testing"
+ type: "every_n_days"
+ day_interval: 2
+ desired_retention: 16
+ retention_unit: "days"
+ state: "{{state_present}}"
+
+- name: Create snapshot schedule (Rule Type - every_week)
+ dellemc.unity.snapshotschedule:
+ unispherehost: "{{unispherehost}}"
+ validate_certs: "{{validate_certs}}"
+ username: "{{username}}"
+ password: "{{password}}"
+ name: "Ansible_Every_Week_Testing"
+ type: "every_week"
+ days_of_week:
+ - MONDAY
+ - FRIDAY
+ hour: 12
+ minute: 30
+ desired_retention: 200
+ state: "{{state_present}}"
+
+- name: Create snapshot schedule (Rule Type - every_month)
+ dellemc.unity.snapshotschedule:
+ unispherehost: "{{unispherehost}}"
+ validate_certs: "{{validate_certs}}"
+ username: "{{username}}"
+ password: "{{password}}"
+ name: "Ansible_Every_Month_Testing"
+ type: "every_month"
+ day_of_month: 17
+ auto_delete: True
+ state: "{{state_present}}"
+
+- name: Get snapshot schedule details using name
+ dellemc.unity.snapshotschedule:
+ unispherehost: "{{unispherehost}}"
+ validate_certs: "{{validate_certs}}"
+ username: "{{username}}"
+ password: "{{password}}"
+ name: "Ansible_Every_N_Hours_Testing"
+ state: "{{state_present}}"
+
+- name: Get snapshot schedule details using id
+ dellemc.unity.snapshotschedule:
+ unispherehost: "{{unispherehost}}"
+ validate_certs: "{{validate_certs}}"
+ username: "{{username}}"
+ password: "{{password}}"
+ id: "{{id}}"
+ state: "{{state_present}}"
+
+- name: Modify snapshot schedule details id
+ dellemc.unity.snapshotschedule:
+ unispherehost: "{{unispherehost}}"
+ validate_certs: "{{validate_certs}}"
+ username: "{{username}}"
+ password: "{{password}}"
+ id: "{{id}}"
+ type: "every_n_hours"
+ interval: 8
+ state: "{{state_present}}"
+
+- name: Modify snapshot schedule using name
+ dellemc.unity.snapshotschedule:
+ unispherehost: "{{unispherehost}}"
+ validate_certs: "{{validate_certs}}"
+ username: "{{username}}"
+ password: "{{password}}"
+ name: "Ansible_Every_Day_Testing"
+ type: "every_day"
+ desired_retention: 200
+ auto_delete: False
+ state: "{{state_present}}"
+
+- name: Delete snapshot schedule using id
+ dellemc.unity.snapshotschedule:
+ unispherehost: "{{unispherehost}}"
+ validate_certs: "{{validate_certs}}"
+ username: "{{username}}"
+ password: "{{password}}"
+ id: "{{id}}"
+ state: "{{state_absent}}"
+
+- name: Delete snapshot schedule using name
+ dellemc.unity.snapshotschedule:
+ unispherehost: "{{unispherehost}}"
+ validate_certs: "{{validate_certs}}"
+ username: "{{username}}"
+ password: "{{password}}"
+ name: "Ansible_Every_Day_Testing"
+ state: "{{state_absent}}"
+"""
+
+RETURN = r"""
+changed:
+ description: Whether or not the resource has changed.
+ returned: always
+ type: bool
+ sample: True
+
+snapshot_schedule_details:
+ description: Details of the snapshot schedule.
+ returned: When snapshot schedule exists
+ type: dict
+ contains:
+ id:
+ description: The system ID given to the snapshot schedule.
+ type: str
+ name:
+ description: The name of the snapshot schedule.
+ type: str
+ luns:
+ description: Details of volumes for which snapshot schedule
+ applied.
+ type: dict
+ contains:
+ UnityLunList:
+ description: List of volumes for which snapshot schedule
+ applied.
+ type: list
+ contains:
+ UnityLun:
+ description: Detail of volume.
+ type: dict
+ contains:
+ id:
+ description: The system ID given to volume.
+ type: str
+ rules:
+ description: Details of rules that apply to snapshot schedule.
+ type: list
+ contains:
+ id:
+ description: The system ID of the rule.
+ type: str
+ interval:
+ description: Number of days or hours between snaps,
+ depending on the rule type.
+ type: int
+ hours:
+ description: Hourly frequency for the snapshot
+ schedule rule.
+ type: list
+ minute:
+ description: Minute frequency for the snapshot
+ schedule rule.
+ type: int
+ days_of_week:
+ description: Days of the week for which the snapshot
+ schedule rule applies.
+ type: dict
+ contains:
+ DayOfWeekEnumList:
+ description: Enumeration of days of the week.
+ type: list
+ days_of_month:
+ description: Days of the month for which the snapshot
+ schedule rule applies.
+ type: list
+ retention_time:
+ description: Period of time in seconds for which to keep
+ the snapshot.
+ type: int
+ retention_time_in_hours:
+ description: Period of time in hours for which to keep the
+ snapshot.
+ type: int
+ rule_type:
+ description: Type of the rule applied to snapshot schedule.
+ type: str
+ is_auto_delete:
+ description: Indicates whether the system can automatically
+ delete the snapshot based on pool automatic-deletion
+ thresholds.
+ type: bool
+ storage_resources:
+ description: Details of storage resources for which snapshot.
+ schedule applied.
+ type: dict
+ contains:
+ UnityStorageResourceList:
+ description: List of storage resources for which snapshot
+ schedule applied.
+ type: list
+ contains:
+ UnityStorageResource:
+ description: Detail of storage resource.
+ type: dict
+ contains:
+ id:
+ description: The system ID given to storage
+ resource.
+ type: str
+ sample: {
+ "existed": true,
+ "hash": 8742032390151,
+ "id": "snapSch_63",
+ "is_default": false,
+ "is_modified": null,
+ "is_sync_replicated": false,
+ "luns": null,
+ "modification_time": "2021-12-14 21:37:47.905000+00:00",
+ "name": "SS7_empty_hour_SS",
+ "rules": [
+ {
+ "access_type": "FilesystemSnapAccessTypeEnum.CHECKPOINT",
+ "days_of_month": null,
+ "days_of_week": {
+ "DayOfWeekEnumList": []
+ },
+ "existed": true,
+ "hash": 8742032280772,
+ "hours": [
+ 0
+ ],
+ "id": "SchedRule_109",
+ "interval": 2,
+ "is_auto_delete": false,
+ "minute": 0,
+ "retention_time": 86400,
+ "retention_time_in_hours": 24,
+ "rule_type": "every_n_days",
+ "type": "ScheduleTypeEnum.N_DAYS_AT_HHMM"
+ }
+ ],
+ "storage_resources": null,
+ "version": "ScheduleVersionEnum.LEGACY"
+ }
+"""
+
+import logging
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.dellemc.unity.plugins.module_utils.storage.dell \
+ import utils
+
+LOG = utils.get_logger('snapshotschedule')
+
+application_type = "Ansible/1.6.0"
+
+
+class SnapshotSchedule(object):
+ """Class with snapshot schedule operations"""
+
+ def __init__(self):
+ """Define all parameters required by this module"""
+
+ self.module_params = utils.get_unity_management_host_parameters()
+ self.module_params.update(get_snapshotschedule_parameters())
+
+ mutually_exclusive = [['name', 'id'], ['interval', 'hour'],
+ ['hours_of_day', 'hour'],
+ ['interval', 'hours_of_day', 'day_interval',
+ 'days_of_week', 'day_of_month']]
+ required_one_of = [['name', 'id']]
+
+ # initialize the Ansible module
+ self.module = AnsibleModule(
+ argument_spec=self.module_params,
+ supports_check_mode=False,
+ mutually_exclusive=mutually_exclusive,
+ required_one_of=required_one_of
+ )
+ utils.ensure_required_libs(self.module)
+
+ self.unity_conn = utils.get_unity_unisphere_connection(
+ self.module.params, application_type)
+
+ def schedule_modify_required(self, schedule_details):
+ """Check if the desired snapshot schedule state is different from
+ existing snapshot schedule state
+ :param schedule_details: The dict containing snapshot schedule
+ details
+ :return: Boolean value to indicate if modification is needed
+ """
+
+ # Check if existing snapshot schedule has auto_delete = True and
+ # playbook sets desired retention without mentioning auto_delete
+ if schedule_details['rules'][0]['is_auto_delete'] and\
+ self.module.params['desired_retention']\
+ and self.module.params['auto_delete'] is None:
+ self.module.fail_json(msg="Desired retention cannot be "
+ "specified when auto_delete is true"
+ )
+ if schedule_details['rules'][0]['retention_time'] and \
+ self.module.params['auto_delete']:
+ self.module.fail_json(msg="auto_delete cannot be specified when"
+ " existing desired retention is set")
+
+ desired_rule_type = get_schedule_value(self.module.params['type'])
+ existing_rule_string = schedule_details['rules'][0][
+ 'type'].split(".")[1]
+ existing_rule_type = utils.ScheduleTypeEnum[
+ existing_rule_string]._get_properties()['value']
+ modified = False
+
+ # Check if rule type is modified
+ if desired_rule_type != existing_rule_type:
+ self.module.fail_json(msg="Modification of rule type is not"
+ " allowed.")
+
+ # Convert desired retention to seconds
+ duration_in_sec = convert_retention_to_seconds(
+ self.module.params['desired_retention'],
+ self.module.params['retention_unit'])
+
+ if not duration_in_sec:
+ duration_in_sec = schedule_details['rules'][0]['retention_time']
+
+ # Check if common parameters for the rules getting modified
+ if (duration_in_sec and duration_in_sec != schedule_details[
+ 'rules'][0]['retention_time']):
+ modified = True
+ elif (self.module.params['auto_delete'] is not None and
+ self.module.params['auto_delete'] != schedule_details['rules']
+ [0]['is_auto_delete']):
+ modified = True
+
+ if (self.module.params['minute'] is not None and self.module.params[
+ 'minute'] != schedule_details['rules'][0]['minute']):
+ modified = True
+
+ if not modified and desired_rule_type == 0:
+ if (self.module.params['interval'] and self.module.params[
+ 'interval'] != schedule_details['rules'][0]['interval']):
+ modified = True
+ elif not modified and desired_rule_type == 1:
+ if (self.module.params['hours_of_day'] and
+ set(self.module.params['hours_of_day']) !=
+ set(schedule_details['rules'][0]['hours'])):
+ modified = True
+ elif not modified and desired_rule_type == 2:
+ if (self.module.params['day_interval'] and self.module.params[
+ 'day_interval'] != schedule_details['rules'][0]['interval'])\
+ or (self.module.params['hour'] is not None and
+ self.module.params['hour'] != schedule_details[
+ 'rules'][0]['hours'][0]):
+ modified = True
+ elif not modified and desired_rule_type == 3:
+ days = schedule_details['rules'][0]['days_of_week'][
+ 'DayOfWeekEnumList']
+ existing_days = list()
+
+ for day in days:
+ temp = day.split(".")
+ existing_days.append(temp[1])
+
+ if (self.module.params['days_of_week'] and
+ set(self.module.params['days_of_week']) !=
+ set(existing_days)) or\
+ (self.module.params['hour'] is not None and
+ self.module.params['hour'] != schedule_details['rules'][
+ 0]['hours'][0]):
+ modified = True
+ elif not modified and desired_rule_type == 4:
+ if (self.module.params['day_of_month'] and self.module.params[
+ 'day_of_month'] != schedule_details['rules'][0][
+ 'days_of_month'][0]) or\
+ (self.module.params['hour'] is not None and
+ self.module.params['hour'] != schedule_details['rules'][
+ 0]['hours'][0]):
+ modified = True
+ LOG.info("Modify Flag: %s", modified)
+ return modified
+
+ def get_days_of_week_enum(self, days_of_week):
+ """Get the enum for days of week.
+ :param days_of_week: The list of days of week
+ :return: The list of days_of_week enum
+ """
+
+ days_of_week_enum = []
+ for day in days_of_week:
+ if day in utils.DayOfWeekEnum.__members__:
+ days_of_week_enum.append(utils.DayOfWeekEnum[day])
+ else:
+ errormsg = "Invalid choice {0} for days of week".format(day)
+ LOG.error(errormsg)
+ self.module.fail_json(msg=errormsg)
+ return days_of_week_enum
+
+ def create_rule(self, type, interval, hours_of_day, day_interval,
+ days_of_week, day_of_month, hour, minute,
+ desired_retention, retention_unit, auto_delete,
+ schedule_details=None):
+ """Create the rule."""
+
+ duration_in_sec = None
+ if desired_retention:
+ duration_in_sec = convert_retention_to_seconds(desired_retention,
+ retention_unit)
+
+ if not duration_in_sec and schedule_details:
+ duration_in_sec = schedule_details['rules'][0]['retention_time']
+
+ if hour is None and schedule_details is None:
+ hour = 0
+
+ if hour is None and schedule_details:
+ if schedule_details['rules'][0]['hours'] is not None:
+ hour = schedule_details['rules'][0]['hours'][0]
+
+ if minute is None and schedule_details is None:
+ minute = 0
+
+ if minute is None and schedule_details:
+ minute = schedule_details['rules'][0]['minute']
+
+ try:
+ if type == "every_n_hours":
+ if not interval:
+ interval = schedule_details['rules'][0]['interval']
+ rule_dict = utils.snap_schedule.UnitySnapScheduleRule.\
+ every_n_hours(hour_interval=interval, minute=minute,
+ retention_time=duration_in_sec,
+ is_auto_delete=auto_delete)
+ elif type == "every_day":
+ if not hours_of_day:
+ hours_of_day = schedule_details['rules'][0]['hours']
+
+ rule_dict = utils.snap_schedule.UnitySnapScheduleRule.\
+ every_day(hours=hours_of_day, minute=minute,
+ retention_time=duration_in_sec,
+ is_auto_delete=auto_delete)
+ elif type == "every_n_days":
+ if not day_interval:
+ day_interval = schedule_details['rules'][0]['interval']
+
+ rule_dict = utils.snap_schedule.UnitySnapScheduleRule.\
+ every_n_days(day_interval=day_interval, hour=hour,
+ minute=minute,
+ retention_time=duration_in_sec,
+ is_auto_delete=auto_delete)
+ elif type == "every_week":
+ if days_of_week:
+ days_of_week_enum = self.get_days_of_week_enum(days_of_week)
+ else:
+ days = schedule_details['rules'][0]['days_of_week'][
+ 'DayOfWeekEnumList']
+ existing_days = list()
+
+ for day in days:
+ temp = day.split(".")
+ existing_days.append(temp[1])
+ days_of_week_enum = self.get_days_of_week_enum(days_of_week)
+
+ rule_dict = utils.snap_schedule.UnitySnapScheduleRule.\
+ every_week(days_of_week=days_of_week_enum, hour=hour,
+ minute=minute, retention_time=duration_in_sec,
+ is_auto_delete=auto_delete)
+ else:
+ if day_of_month:
+ day_of_month_list = [day_of_month]
+ else:
+ day_of_month_list = schedule_details['rules'][0][
+ 'days_of_month']
+
+ rule_dict = utils.snap_schedule.UnitySnapScheduleRule.\
+ every_month(days_of_month=day_of_month_list, hour=hour,
+ minute=minute, retention_time=duration_in_sec,
+ is_auto_delete=auto_delete)
+
+ return rule_dict
+
+ except Exception as e:
+ errormsg = "Create operation of snapshot schedule rule " \
+ " failed with error {0}".format(str(e))
+ LOG.error(errormsg)
+ self.module.fail_json(msg=errormsg)
+
+ def create_snapshot_schedule(self, name, rule_dict):
+ """Create snapshot schedule.
+ :param name: The name of the snapshot schedule
+ :param rule_dict: The dict of the rule
+ :return: Boolean value to indicate if snapshot schedule created
+ """
+
+ try:
+ utils.snap_schedule.UnitySnapSchedule.create(
+ cli=self.unity_conn._cli, name=name, rules=[rule_dict])
+ return True
+
+ except Exception as e:
+ errormsg = "Create operation of snapshot schedule {0} failed" \
+ " with error {1}".format(name, str(e))
+ LOG.error(errormsg)
+ self.module.fail_json(msg=errormsg)
+
+ def validate_desired_retention(self, desired_retention, retention_unit):
+ """Validates the specified desired retention.
+ :param desired_retention: Desired retention of the snapshot
+ schedule
+ :param retention_unit: Retention unit for the snapshot schedule
+ """
+
+ if retention_unit == 'hours' and (desired_retention < 1 or
+ desired_retention > 744):
+ self.module.fail_json(msg="Please provide a valid integer as the"
+ " desired retention between 1 and 744.")
+ elif retention_unit == 'days' and (desired_retention < 1 or
+ desired_retention > 31):
+ self.module.fail_json(msg="Please provide a valid integer as the"
+ " desired retention between 1 and 31.")
+
+ def return_schedule_instance(self, id):
+ """Return the snapshot schedule instance
+ :param id: The id of the snapshot schedule
+ :return: Instance of the snapshot schedule
+ """
+
+ try:
+ obj_schedule = utils.snap_schedule.UnitySnapSchedule.get(
+ self.unity_conn._cli, id)
+ return obj_schedule
+
+ except Exception as e:
+ error_msg = "Failed to get the snapshot schedule {0} instance" \
+ " with error {1}".format(id, str(e))
+ LOG.error(error_msg)
+ self.module.fail_json(msg=error_msg)
+
+ def delete_snapshot_schedule(self, id):
+ """Delete snapshot schedule.
+ :param id: The ID of the snapshot schedule
+ :return: The boolean value to indicate if snapshot schedule
+ deleted
+ """
+
+ try:
+ obj_schedule = self.return_schedule_instance(id=id)
+ obj_schedule.delete()
+ return True
+
+ except Exception as e:
+ errormsg = "Delete operation of snapshot schedule id:{0} failed" \
+ " with error {1}".format(id, str(e))
+ LOG.error(errormsg)
+ self.module.fail_json(msg=errormsg)
+
+ def modify_snapshot_schedule(self, id, schedule_details):
+ """Modify snapshot schedule details.
+ :param id: The id of the snapshot schedule
+ :param schedule_details: The dict containing schedule details
+ :return: The boolean value to indicate if snapshot schedule
+ modified
+ """
+
+ try:
+ obj_schedule = self.return_schedule_instance(id=id)
+ rule_id = schedule_details['rules'][0]['id']
+
+ if self.module.params['auto_delete'] is None:
+ auto_delete = schedule_details['rules'][0]['is_auto_delete']
+ else:
+ auto_delete = self.module.params['auto_delete']
+
+ if schedule_details['rules'][0]['is_auto_delete'] and\
+ self.module.params['desired_retention'] and\
+ self.module.params['auto_delete'] is False:
+ auto_delete = False
+ elif schedule_details['rules'][0]['retention_time']:
+ auto_delete = None
+
+ rule_dict = self.create_rule(
+ self.module.params['type'], self.module.params['interval'],
+ self.module.params['hours_of_day'],
+ self.module.params['day_interval'],
+ self.module.params['days_of_week'],
+ self.module.params['day_of_month'],
+ self.module.params['hour'], self.module.params['minute'],
+ self.module.params['desired_retention'],
+ self.module.params['retention_unit'], auto_delete,
+ schedule_details)
+
+ obj_schedule.modify(add_rules=[rule_dict],
+ remove_rule_ids=[rule_id])
+ return True
+ except Exception as e:
+ errormsg = "Modify operation of snapshot schedule id:{0} failed" \
+ " with error {1}".format(id, str(e))
+ LOG.error(errormsg)
+ self.module.fail_json(msg=errormsg)
+
+ def get_details(self, id=None, name=None):
+ """Get snapshot schedule details.
+ :param id: The id of the snapshot schedule
+ :param name: The name of the snapshot schedule
+ :return: Dict containing snapshot schedule details if exists
+ """
+
+ id_or_name = id if id else name
+ errormsg = "Failed to get details of snapshot schedule {0} with" \
+ " error {1}"
+ try:
+ if not id:
+ details = utils.snap_schedule.UnitySnapScheduleList.get(
+ self.unity_conn._cli, name=name)
+
+ if details:
+ id = details[0].id
+
+ if id:
+ details = self.unity_conn.get_snap_schedule(_id=id)
+
+ if id and details.existed:
+ rule_list = [rules._get_properties() for rules in
+ details.rules]
+ for rule in rule_list:
+ rule['retention_time_in_hours'] = int(
+ rule['retention_time'] / 3600)
+ rule['rule_type'] = get_rule_type(rule['type'])
+ schedule_details = details._get_properties()
+ schedule_details['rules'] = rule_list
+ return schedule_details
+ else:
+ LOG.info("Failed to get the snapshot schedule %s", id_or_name)
+ return None
+
+ except utils.HttpError as e:
+ if e.http_status == 401:
+ auth_err = "Incorrect username or password, {0}".format(
+ e.message)
+ msg = errormsg.format(id_or_name, auth_err)
+ LOG.error(msg)
+ self.module.fail_json(msg=msg)
+ else:
+ msg = errormsg.format(id_or_name, str(e))
+ LOG.error(msg)
+ self.module.fail_json(msg=msg)
+
+ except utils.UnityResourceNotFoundError as e:
+ msg = errormsg.format(id_or_name, str(e))
+ LOG.error(msg)
+ return None
+
+ except Exception as e:
+ msg = errormsg.format(id_or_name, str(e))
+ LOG.error(msg)
+ self.module.fail_json(msg=msg)
+
+ def validate_parameters(self):
+ """Validate the parameters."""
+
+ try:
+ if self.module.params['interval'] is not None and\
+ self.module.params['interval'] <= 0:
+ self.module.fail_json(msg="Interval can not be less than or"
+ " equal to 0.")
+
+ param_list = ['day_interval', 'day_of_month']
+ for param in param_list:
+ if self.module.params[param] is not None and\
+ self.module.params[param] == 0:
+ self.module.fail_json(msg="{0} can not be 0.".format(
+ param))
+
+ except Exception as e:
+ errormsg = "Failed to validate the module param with error" \
+ " {0}".format(str(e))
+ LOG.error(errormsg)
+ self.module.fail_json(msg=errormsg)
+
+ def perform_module_operation(self):
+ """
+ Perform different actions on snapshot schedule module based on
+ parameters chosen in playbook
+ """
+ name = self.module.params['name']
+ id = self.module.params['id']
+ type = self.module.params['type']
+ interval = self.module.params['interval']
+ hours_of_day = self.module.params['hours_of_day']
+ day_interval = self.module.params['day_interval']
+ days_of_week = self.module.params['days_of_week']
+ day_of_month = self.module.params['day_of_month']
+ hour = self.module.params['hour']
+ minute = self.module.params['minute']
+ desired_retention = self.module.params['desired_retention']
+ retention_unit = self.module.params['retention_unit']
+ auto_delete = self.module.params['auto_delete']
+ state = self.module.params['state']
+
+ # result is a dictionary that contains changed status and snapshot
+ # schedule details
+ result = dict(
+ changed=False,
+ snapshot_schedule_details={}
+ )
+
+ self.validate_parameters()
+
+ if desired_retention is not None:
+ self.validate_desired_retention(desired_retention, retention_unit)
+
+ if auto_delete and desired_retention:
+ self.module.fail_json(msg="Desired retention cannot be "
+ "specified when auto_delete is true"
+ )
+
+ schedule_details = self.get_details(name=name, id=id)
+
+ if not id and schedule_details:
+ id = schedule_details['id']
+
+ if state == 'present' and not schedule_details:
+ if not name:
+ msg = "The parameter name length is 0. It is too short." \
+ " The min length is 1."
+ self.module.fail_json(msg=msg)
+
+ if not type:
+ self.module.fail_json(msg="Rule type is necessary to create"
+ " snapshot schedule")
+
+ if type == "every_n_hours" and interval is None:
+ self.module.fail_json(msg="To create snapshot schedule with"
+ " rule type every_n_hours, interval"
+ " is the mandatory parameter.")
+ elif type == "every_day" and hours_of_day is None:
+ self.module.fail_json(msg="To create snapshot schedule with"
+ " rule type every_day, hours_of_day"
+ " is the mandatory parameter.")
+ elif type == "every_n_days" and day_interval is None:
+ self.module.fail_json(msg="To create snapshot schedule with"
+ " rule type every_n_days,"
+ " day_interval is the mandatory"
+ " parameter.")
+ elif type == "every_week" and days_of_week is None:
+ self.module.fail_json(msg="To create snapshot schedule with"
+ " rule type every_week,"
+ " days_of_week is the mandatory"
+ " parameter.")
+ elif type == "every_month" and day_of_month is None:
+ self.module.fail_json(msg="To create snapshot schedule with"
+ " rule type every_month,"
+ " day_of_month is the mandatory"
+ " parameter.")
+
+ rule_dict = self.create_rule(type, interval, hours_of_day,
+ day_interval, days_of_week,
+ day_of_month, hour, minute,
+ desired_retention, retention_unit,
+ auto_delete)
+ result['changed'] = self.create_snapshot_schedule(name, rule_dict)
+
+ elif state == 'absent' and schedule_details:
+ result['changed'] = self.delete_snapshot_schedule(id)
+
+ if state == 'present' and type and schedule_details and\
+ len(schedule_details['rules']) == 1:
+ if (self.schedule_modify_required(schedule_details)):
+ result['changed'] = self.modify_snapshot_schedule(
+ id, schedule_details)
+
+ result['snapshot_schedule_details'] = self.get_details(name=name,
+ id=id)
+ self.module.exit_json(**result)
+
+
+def get_rule_type(type):
+ """Get the rule type of schedule.
+ :param type: The schedule type enum
+ :return: The rule type of snapshot schedule
+ """
+
+ schedule_type = {
+ "ScheduleTypeEnum.N_HOURS_AT_MM": "every_n_hours",
+ "ScheduleTypeEnum.DAY_AT_HHMM": "every_day",
+ "ScheduleTypeEnum.N_DAYS_AT_HHMM": "every_n_days",
+ "ScheduleTypeEnum.SELDAYS_AT_HHMM": "every_week",
+ "ScheduleTypeEnum.NTH_DAYOFMONTH_AT_HHMM": "every_month"
+ }
+
+ return schedule_type.get(type)
+
+
+def get_schedule_value(type):
+ """Get the enum for schedule.
+ :param type: The type of rule
+ :return: The enum value for rule
+ """
+
+ rule_type = {
+ "every_n_hours": 0,
+ "every_day": 1,
+ "every_n_days": 2,
+ "every_week": 3,
+ "every_month": 4
+ }
+
+ return rule_type.get(type)
+
+
+def convert_retention_to_seconds(desired_retention, retention_unit):
+ """Convert desired retention to seconds.
+ :param desired_retention: The desired retention for snapshot
+ schedule
+ :param retention_unit: The retention unit for snapshot schedule
+ :return: The integer value in seconds
+ """
+
+ duration_in_sec = None
+ if desired_retention:
+ if retention_unit == 'hours':
+ duration_in_sec = desired_retention * 60 * 60
+ else:
+ duration_in_sec = desired_retention * 24 * 60 * 60
+ return duration_in_sec
+
+
+def get_snapshotschedule_parameters():
+ """This method provide parameters required for the ansible snapshot
+ schedule module on Unity"""
+
+ return dict(
+ name=dict(type='str'),
+ id=dict(type='str'),
+ type=dict(type='str', choices=['every_n_hours', 'every_day',
+ 'every_n_days', 'every_week',
+ 'every_month']),
+ interval=dict(type='int'),
+ hours_of_day=dict(type='list', elements='int'),
+ day_interval=dict(type='int'),
+ days_of_week=dict(type='list', elements='str',
+ choices=['SUNDAY', 'MONDAY', 'TUESDAY', 'WEDNESDAY',
+ 'THURSDAY', 'FRIDAY', 'SATURDAY']),
+ day_of_month=dict(type='int'),
+ hour=dict(type='int'),
+ minute=dict(type='int'),
+ desired_retention=dict(type='int'),
+ retention_unit=dict(type='str', choices=['hours', 'days'],
+ default='hours'),
+ auto_delete=dict(type='bool'),
+ state=dict(required=True, type='str', choices=['present', 'absent'])
+ )
+
+
+def main():
+ """ Create Unity snapshot schedule object and perform action on it
+ based on user input from playbook"""
+ obj = SnapshotSchedule()
+ obj.perform_module_operation()
+
+
+if __name__ == '__main__':
+ main()