Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
import six
from cliff import show, lister
from osc_lib import exceptions
from osc_lib import utils as osc_utils
from datetime import datetime
import argparse

from workloadmgrclient import utils
from workloadmgrclient.v1 import WorkloadmgrCommand
from workloadmgrclient.v1.validators import validate_int_value
from docutils.nodes import option_string


validate_fields = {
    "interval": {"lower_bound": 1, "upper_bound": None},
    "retention_policy_value": {"lower_bound": 1, "upper_bound": 365},
    # '-1' for 'NEVER' and '0' for 'ALWAYS'
    "fullbackup_interval": {"lower_bound": -1, "upper_bound": 999},
}

class PolicyCommand(WorkloadmgrCommand):
    resource = "workload_policy"

    @staticmethod
    def produce_policy_output(objects=None):
        if objects:
            utils.print_list(objects, ["ID", "Name", "Description", "Status"])
            # print assigned project if only one policy to display
            if len(objects) == 1 and objects[0].policy_assignments:
                utils.print_list(
                    objects[0].policy_assignments, ["project_id", "project_name"]
                )
        return


class ListPolicy(PolicyCommand, lister.Lister):
    """List all available policies."""

    def take_action(self, parsed_args):
        client = self.get_client()
        policy_objs = client.list() or []
        headers = ["ID", "Name", "Description", "Status"]
        columns = ["id", "name", "description", "status"]
        return (
            headers,
            (osc_utils.get_item_properties(s, columns) for s in policy_objs),
        )


class ShowPolicy(PolicyCommand, show.ShowOne):
    """Show a policy."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "policy_id", metavar="<policy_id>", help="ID of the policy."
        )

    def action_return(self, policy_obj):
        if policy_obj:
            data = {}
            for field_value in policy_obj.field_values:
                data[field_value["policy_field_name"]] = field_value["value"]
            # TODO check for after project assignment
            self.produce_policy_output([policy_obj])
            return zip(*sorted(six.iteritems(data)))

    def take_action(self, parsed_args):
        client = self.get_client()
        policy_obj = client.get(parsed_args.policy_id)
        return self.action_return(policy_obj)


class MultiKWArgsAction(argparse.Action):
    def __init__(
        self,
        option_strings,
        dest,
        help=None,
        required=False,
        metavar=None,
        ):
        
        super(MultiKWArgsAction, self).__init__(
            option_strings=option_strings,
            dest=dest,
            nargs=None,
            const=None,
            default=[],
            type=None,
            choices=None,
            required=required,
            help=help,
            metavar=metavar,
            )
        
    def __call__(self, parser, namespace, values, option_string=None):
        if getattr(namespace, self.dest) is None:
            setattr(namespace, self.dest, [])
        
        for value in values.split(','):
            if '=' not in value:
                raise argparse.ArgumentTypeError(
                    "Invalid argument '%s'. arguments must be of the "
                    "form --<cmd> <key=value>" % value
                )
        getattr(namespace, self.dest).append(values.split(','))
        


class CreatePolicy(ShowPolicy):
    """Creates a policy."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "display_name", metavar="<display_name>", help="policy name."
        )
        parser.add_argument(
            "--policy-fields",
            metavar="<key=value>",
            action="append",
            dest="policy_fields",
            required=True,
            default=[],
            help="Specify following key value pairs for policy fields "
            "Specify option multiple times to include multiple keys. "
            " 'start_time' : '10:30 PM' (must be positive number) "
            "--policy-fields start_time='10:30 PM'",
        )
        parser.add_argument(
            "--hourly",
            metavar="interval=<n>,retention=<count>,snapshot_type=<incremental|full>",
            action=MultiKWArgsAction,
            dest='hourly',
            help="Specify following key value pairs for hourly jobschedule "
            "interval=<n> where n is no of hours within list (1,2,3,4,6,8,12,24) "
            "retention=<snapshots count>"
            "snapshot_type=<full|incremental>"
            "For example --hourly interval='4',retention='1',snapshot_type='incremental' "
            "If you don't specify this option, following default value"
            " 'interval' : '1' "
            " 'retention' : '30' "
            " 'snapshot_type' : 'incremental' ",
        )
        parser.add_argument(
            "--daily",
            metavar="backup_time=<time>,retention=<count>,snapshot_type=<incremental|full>",
            action=MultiKWArgsAction,
            dest='daily',
            help="Specify following key value pairs for daily jobschedule "
            "backup_time='1:30 12:30 00:30'"
            "retention=<snapshots count>"
            "snapshot_type=<full|incremental>"
            "For example --daily backup_time='01:00 02:00 11:00',retention='1',snapshot_type='incremental' "
            " meaning of above input : everyday 1 PM, 2PM,11PM incremental snapshot get trigger, only 1 snapshot remain per day ",
        )
        parser.add_argument(
            "--weekly",
            metavar="backup_day=<days>,retention=<count>,snapshot_type=<incremental|full>",
            action=MultiKWArgsAction,
            dest='weekly',
            help="Specify following key value pairs for weekly jobschedule "
            "backup_day=[mon,tue,wed,thu,fri,sat,sun]"
            "retention=<snapshots count>"
            "snapshot_type=<full|incremental>"
            "For example --weekly backup_day='sun mon tue',retention='1',snapshot_type='incremental' "
            " meaning of above input : incremental snapshot get trigger on every sun day on backup_time specified on daily option",
        )
        parser.add_argument(
            "--monthly",
            metavar="month_backup_day=<date>,retention=<count>,snapshot_type=<incremental|full>",
            action=MultiKWArgsAction,
            dest='monthly',
            help="Specify following key value pairs for monthly jobschedule "
            "month_backup_day=<1-31|last>, 'last': last day of the month"
            "retention=<snapshots count>"
            "snapshot_type=<full|incremental>"
            "For example --monthly month_backup_day='1 2 3',retention=1,snapshot_type='incremental'"
            " meaning of above input : every month 1st day of the month, 1 snapshot remain on every end of month, snapshot type incremental ",
        )
        parser.add_argument(
            "--yearly",
            metavar="backup_month=<month>,retention=<count>,snapshot_type=<incremental|full>",
            action=MultiKWArgsAction,
            dest='yearly',
            help="Specify following key value pairs for yearly jobschedule "
            "backup_month=[jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec]"
            "retention=<snapshots count>"
            "snapshot_type=<full|incremental>"
            "For example --yearly backup_month='jan feb',retention='1',snapshot_type='full'"
            " meaning of above input : every year Jan 1 full snapshot reamin for retention",
        )
        
        parser.add_argument(
            "--manual",
            metavar="retention=<snapshots count>,retention_days_to_keep=<num of days>",
            action=MultiKWArgsAction,
            dest='manual',
            help="Specify following key value pairs for manual jobschedule \n"
            "retention=<snapshots count> "
            "retention_days_to_keep=<num of days> \n"
            "retention_days_to_keep only available for immutable Backup Targets\n"
            "For example --manual retention=30 retention_days_to_keep=30 "
            "meaning of above input : manually trigger snapshot get deleted after retention value hit",
        )

        parser.add_argument(
            "--display-description",
            metavar="<display_description>",
            help="Optional policy description. (Default=No description)",
            default="No description",
        )
        parser.add_argument(
            "--metadata",
            metavar="<key=value>",
            action="append",
            dest="metadata",
            default=[],
            help="Specify a key value pairs to include in the policy create metadata "
            "Specify option multiple times to include multiple keys. "
            "key=value",
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        try:
            policy_fields = {}
            err_msg = None

            for policy_field_str in parsed_args.policy_fields:
                err_msg = (
                    "Invalid policy argument '%s'. policy arguments must be of the "
                    "form --policy-fields <key=value>" % policy_field_str
                )
                for kv_str in policy_field_str.split(","):
                    try:
                        k, v = kv_str.split("=", 1)
                    except ValueError:
                        raise exceptions.CommandError(err_msg)
                    if k =='start_time':
                        try:
                            datetime.strptime(v, '%I:%M %p')
                        except ValueError:
                            raise exceptions.CommandError("Invalid policy argument 'start_time'. start_time must be in format '%I:%M %p' eg. '3:00 PM', 10:30 AM")
                    if k in policy_fields:
                        policy_fields[k] = v
                    else:
                        policy_fields.setdefault(k, v)

            policy_fields.update(utils.validate_policy_param(parsed_args))
            
            if len(parsed_args.manual) > 0:
                data_dict = dict(item.split("=") for item in parsed_args.manual[0])
                policy_fields['manual'] = {'retention': data_dict.get('retention', None)}
                policy_fields['retentionmanual'] = {'retentionmanual': data_dict.get('retention_days_to_keep', None)}
            else:
                policy_fields['manual'] = {'retention': None}
                policy_fields['retentionmanual'] = {'retentionmanual': None}
            metadata = {}
            for metadata_str in parsed_args.metadata:
                for kv_str in metadata_str.split(","):
                    try:
                        k, v = kv_str.split("=", 1)
                    except ValueError:
                        err_msg = (
                            "Invalid metadata argument '%s'. metadata arguments must be of the "
                            "form --metadata <key=value>" % metadata_str
                        )
                        raise exceptions.CommandError(err_msg)

                    if k in metadata:
                        metadata[k] = v
                    else:
                        metadata.setdefault(k, v)

            policy_obj = self._perform_operation(
                client, parsed_args, policy_fields, metadata
            )
            return self.action_return(policy_obj)
        except Exception as ex:
            raise exceptions.CommandError(str(ex))

    def _perform_operation(self, client, args, policy_fields, metadata):
        return client.create(
            args.display_name, args.display_description, policy_fields, metadata
        )


class UpdatePolicy(CreatePolicy):
    """Update a policy."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "policy_id", metavar="<policy_id>", help="ID of the policy."
        )
        parser.add_argument(
            "--display-name", metavar="<display-name>", help="policy name."
        )
        parser.add_argument(
            "--display-description",
            metavar="<display-description>",
            help="Optional policy description.",
        )
        parser.add_argument(
            "--policy-fields",
            metavar="<key=key-name>",
            action="append",
            dest="policy_fields",
            default=[],
            help="Specify following key value pairs for policy fields "
            "Specify option multiple times to include multiple keys. "
            " 'start_time' : '10:30 PM' (must be positive number) "
            "--policy-fields start_time='10:30 PM'",
        )

        parser.add_argument(
            "--hourly",
            metavar="interval=<n>,retention=<count>,snapshot_type=<incremental|full>",
            action=MultiKWArgsAction,
            dest="hourly",
            help="Specify following key value pairs for hourly jobschedule "
            "interval=<n> where n is no of hours within list (1,2,3,4,6,8,12,24) "
            "retention=<snapshots count>"
            "snapshot_type=<full|incremental>"
            "For example --hourly interval='4',retention='1',snapshot_type='incremental' "
            "If you don't specify this option, following default value"
            " 'interval' : '1' "
            " 'retention' : '30' "
            " 'snapshot_type' : 'incremental' ",
        )

        parser.add_argument(
            "--daily",
            metavar="backup_time=<time>,retention=<count>,snapshot_type=<incremental|full>",
            action=MultiKWArgsAction,
            dest="daily",
            help="Specify following key value pairs for daily jobschedule "
            "backup_time='1:30 12:30 00:30'"
            "retention=<snapshots count>"
            "snapshot_type=<full|incremental>"
            "For example --daily backup_time='01:00 02:00 21:00',retention='1',snapshot_type='incremental' "
            " meaning of above input : everyday 1 , 2, 11 incremental snapshot get trigger, only 1 snapshot remain per day ",
        )

        parser.add_argument(
            "--weekly",
            metavar="backup_day=<days>,retention=<count>,snapshot_type=<incremental|full>",
            action=MultiKWArgsAction,
            dest="weekly",
            help="Specify following key value pairs for weekly jobschedule "
            "backup_day=[mon,tue,wed,thu,fri,sat,sun]"
            "retention=<snapshots count>"
            "snapshot_type=<full|incremental>"
            "For example --weekly backup_day='sun mon',retention='1',snapshot_type='incremental'"
            " meaning of above input : incremental snapshot get trigger on every sun day on backup_time specified on daily option",
        )
        parser.add_argument(
            "--monthly",
            metavar="month_backup_day=<days>,retention=<count>,snapshot_type=<incremental|full>",
            action=MultiKWArgsAction,
            dest="monthly",
            help="Specify following key value pairs for monthly jobschedule "
            "month_backup_day=<1-31|last>, 'last': last day of the month"
            "retention=<snapshots count>"
            "snapshot_type=<full|incremental>"
            "For example --monthly month_backup_day='1 2 3',retention='1',snapshot_type='incremental'"
            " meaning of above input : every month 1st day of the month, 1 snapshot remain on every end of month, snapshot type incremental ",
        )

        parser.add_argument(
            "--yearly",
            metavar="backup_month=<months>,retention=<count>,snapshot_type=<incremental|full>",
            action=MultiKWArgsAction,
            dest="yearly",
            help="Specify following key value pairs for yearly jobschedule "
            "backup_month=[jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec]"
            "retention=<snapshots count>"
            "snapshot_type=<full|incremental>"
            "For example --yearly month_of_the_year='jan feb',retention='1',snapshot_type='full'"
            " meaning of above input : every year Jan 1 full snapshot reamin for retention",
        )

        parser.add_argument(
            "--manual",
            metavar="retention=<snapshots count>,retention_days_to_keep=<num of days>",
            action=MultiKWArgsAction,
            dest="manual",
            help="Specify following key value pairs for manual jobschedule \n"
            "retention=<snapshots count> "
            "retention_days_to_keep=<num of days> \n"
            "retention_days_to_keep only available for immutable Backup Targets\n"
            "For example --manual retention=30,retention_days_to_keep=30 "
            "meaning of above input : manually trigger snapshot get deleted after retention value hit",
        )


        parser.add_argument(
            "--metadata",
            metavar="<key=key-name>",
            action="append",
            dest="metadata",
            default=[],
            help="Specify a key value pairs to include in the policy update metadata "
            "Specify option multiple times to include multiple keys. "
            "key=value",
        )

    def _perform_operation(self, client, args, policy_fields, metadata):
        return client.update(
            args.policy_id,
            args.display_name,
            args.display_description,
            policy_fields,
            metadata,
        )


class DeletePolicy(PolicyCommand):
    """Remove a policy."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "policy_id", metavar="<policy_id>", help="ID of the policy."
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        client.delete(parsed_args.policy_id)


class AssignPolicy(ShowPolicy):
    """Assign/Remove policy to given projects."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "policy_id", metavar="<policy_id>", help="ID of the policy."
        )
        parser.add_argument(
            "--add_project",
            metavar="<project_id>",
            action="append",
            dest="add_project",
            default=[],
            help="ID of the projects to assign policy. "
            "--add_project <project_id> --add_project <project_id>",
        )
        parser.add_argument(
            "--remove_project",
            metavar="<project_id>",
            action="append",
            dest="remove_project",
            default=[],
            help="ID of the projects to remove policy. "
            "--remove_project <project_id> --remove_project <project_id>",
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        result = client.assign(
            parsed_args.policy_id, parsed_args.add_project, parsed_args.remove_project
        )

        if len(result["failed_ids"]) > 0:
            msg = "Please verify failed project id's are valid"
            utils.print_data_vertically([result["failed_ids"]], ["Failed_projects"])
            raise exceptions.CommandError(msg)
        else:
            return self.action_return(result["policy"])


class ListAssignedPolicy(PolicyCommand, lister.Lister):
    """List assigned policies on given project."""

    @staticmethod
    def _add_arguments(parser):
        parser.add_argument(
            "project_id",
            metavar="<project_id>",
            help="ID of the project to list assigned policies.",
        )

    def take_action(self, parsed_args):
        client = self.get_client()
        policy_objs = client.get_assigned_policies(parsed_args.project_id) or []
        headers = ["ID", "Name", "Deleted", "CreatedAt"]
        columns = ["policy_id", "policy_name", "deleted", "created_at"]
        return (
            headers,
            (osc_utils.get_dict_properties(s, columns) for s in policy_objs),
        )