Exemplo n.º 1
0
    def setup_commands(self, parser):
        # Controller commands
        subcmds = [
            Commands.Subcommands.SetProperty,
            Commands.Subcommands.ListProperties,
            Commands.Subcommands.Shutdown,
            Commands.Subcommands.DrbdOptions
        ]

        con_parser = parser.add_parser(
            Commands.CONTROLLER,
            aliases=["c"],
            formatter_class=argparse.RawTextHelpFormatter,
            description="Controller subcommands")

        con_subp = con_parser.add_subparsers(
            title="Controller commands",
            metavar="",
            description=Commands.Subcommands.generate_desc(subcmds)
        )

        # Controller - get props
        c_ctrl_props = con_subp.add_parser(
            Commands.Subcommands.ListProperties.LONG,
            aliases=[Commands.Subcommands.ListProperties.SHORT],
            description='Print current controller config properties.')
        c_ctrl_props.add_argument('-p', '--pastable', action="store_true", help='Generate pastable output')
        c_ctrl_props.set_defaults(func=self.cmd_print_controller_props)

        #  controller - set props
        c_set_ctrl_props = con_subp.add_parser(
            Commands.Subcommands.SetProperty.LONG,
            aliases=[Commands.Subcommands.SetProperty.SHORT],
            description='Set a controller config property.')
        Commands.add_parser_keyvalue(c_set_ctrl_props, "controller")
        c_set_ctrl_props.set_defaults(func=self.set_props)

        c_drbd_opts = con_subp.add_parser(
            Commands.Subcommands.DrbdOptions.LONG,
            aliases=[Commands.Subcommands.DrbdOptions.SHORT],
            description="Set common drbd options."
        )
        DrbdOptions.add_arguments(c_drbd_opts, DrbdOptions.drbd_options()['options'].keys())
        c_drbd_opts.set_defaults(func=self.cmd_controller_drbd_opts)

        # Controller - shutdown
        c_shutdown = con_subp.add_parser(
            Commands.Subcommands.Shutdown.LONG,
            aliases=[Commands.Subcommands.Shutdown.SHORT],
            description='Shutdown the linstor controller'
        )
        c_shutdown.set_defaults(func=self.cmd_shutdown)

        self.check_subcommands(con_subp, subcmds)
Exemplo n.º 2
0
    def setup_commands(self, parser):
        subcmds = [
            Commands.Subcommands.Create, Commands.Subcommands.Modify,
            Commands.Subcommands.List, Commands.Subcommands.Delete,
            Commands.Subcommands.SetProperty,
            Commands.Subcommands.ListProperties,
            Commands.Subcommands.DrbdOptions, Commands.Subcommands.Spawn,
            Commands.Subcommands.QueryMaxVlmSize, Commands.Subcommands.Adjust
        ]

        # Resource group subcommands
        res_grp_parser = parser.add_parser(
            Commands.RESOURCE_GRP,
            aliases=["rg"],
            formatter_class=argparse.RawTextHelpFormatter,
            description="Resource group subcommands")

        res_grp_subp = res_grp_parser.add_subparsers(
            title="resource group subcommands",
            metavar="",
            description=Commands.Subcommands.generate_desc(subcmds))

        #  ------------ CREATE START
        p_new_res_grp = res_grp_subp.add_parser(
            Commands.Subcommands.Create.LONG,
            aliases=[Commands.Subcommands.Create.SHORT],
            description='Defines a Linstor resource group for use with linstor.'
        )
        p_new_res_grp.add_argument('-d',
                                   '--description',
                                   help="Description for the resource group.")
        self.add_auto_select_argparse_arguments(p_new_res_grp,
                                                use_place_count=True)
        p_new_res_grp.add_argument('name',
                                   type=str,
                                   help='Name of the resource group.')
        p_new_res_grp.set_defaults(func=self.create)
        #  ------------ CREATE END

        #  ------------ MODIFY START
        p_mod_res_grp = res_grp_subp.add_parser(
            Commands.Subcommands.Modify.LONG,
            aliases=[Commands.Subcommands.Modify.SHORT],
            description='Modifies a Linstor resource group')
        p_mod_res_grp.add_argument('-d',
                                   '--description',
                                   help="Description for the resource group.")
        self.add_auto_select_argparse_arguments(p_mod_res_grp,
                                                use_place_count=True)
        p_mod_res_grp.add_argument('name', help='Name of the resource group'
                                   ).completer = self.resource_grp_completer
        p_mod_res_grp.set_defaults(func=self.modify)
        #  ------------ MODIFY END

        #  ------------ DELETE START
        p_rm_res_grp = res_grp_subp.add_parser(
            Commands.Subcommands.Delete.LONG,
            aliases=[Commands.Subcommands.Delete.SHORT],
            description=" Removes a resource group from the linstor cluster.")
        p_rm_res_grp.add_argument('name',
                                  help='Name of the resource group to delete'
                                  ).completer = self.resource_grp_completer
        p_rm_res_grp.set_defaults(func=self.delete)
        #  ------------ DELETE END

        #  ------------ LIST START
        rsc_grp_groupby = [x.name.lower() for x in self._rsc_grp_headers]
        rsc_grp_group_completer = Commands.show_group_completer(
            rsc_grp_groupby, "groupby")

        p_lrscgrps = res_grp_subp.add_parser(
            Commands.Subcommands.List.LONG,
            aliases=[Commands.Subcommands.List.SHORT],
            description='Prints a list of all resource groups known to '
            'linstor. By default, the list is printed as a human readable table.'
        )
        p_lrscgrps.add_argument('-p',
                                '--pastable',
                                action="store_true",
                                help='Generate pastable output')
        p_lrscgrps.add_argument(
            '-g',
            '--groupby',
            nargs='+',
            choices=rsc_grp_groupby,
            type=str.lower).completer = rsc_grp_group_completer
        p_lrscgrps.add_argument('-r',
                                '--resource-groups',
                                nargs='+',
                                type=str,
                                help='Filter by list of resource groups'
                                ).completer = self.resource_grp_completer
        p_lrscgrps.add_argument('--props',
                                nargs='+',
                                type=str,
                                help='Filter list by object properties')
        p_lrscgrps.set_defaults(func=self.list)
        #  ------------ LIST END

        #  ------------ LISTPROPS START
        p_sp = res_grp_subp.add_parser(
            Commands.Subcommands.ListProperties.LONG,
            aliases=[Commands.Subcommands.ListProperties.SHORT],
            description="Prints all properties of the given resource group.")
        p_sp.add_argument('-p',
                          '--pastable',
                          action="store_true",
                          help='Generate pastable output')
        p_sp.add_argument(
            'name', help="Resource group for which to print the properties"
        ).completer = self.resource_grp_completer
        p_sp.set_defaults(func=self.print_props)
        #  ------------ LISTPROPS END

        #  ------------ SETPROPS START
        p_setprop = res_grp_subp.add_parser(
            Commands.Subcommands.SetProperty.LONG,
            aliases=[Commands.Subcommands.SetProperty.SHORT],
            formatter_class=argparse.RawTextHelpFormatter,
            description='Sets properties for the given resource group.')
        p_setprop.add_argument('name',
                               type=str,
                               help='Name of the resource group'
                               ).completer = self.resource_grp_completer
        Commands.add_parser_keyvalue(p_setprop, self.OBJECT_NAME)
        p_setprop.set_defaults(func=self.set_props)
        #  ------------ SETPROPS END

        #  ------------ SETDRBDOPTS START
        p_drbd_opts = res_grp_subp.add_parser(
            Commands.Subcommands.DrbdOptions.LONG,
            aliases=[Commands.Subcommands.DrbdOptions.SHORT],
            description=DrbdOptions.description("resource"))
        p_drbd_opts.add_argument(
            'name', type=str,
            help="Resource group name").completer = self.resource_grp_completer
        DrbdOptions.add_arguments(p_drbd_opts, self.OBJECT_NAME)
        p_drbd_opts.set_defaults(func=self.set_drbd_opts)
        #  ------------ SETDRBDOPTS END

        #  ------------ SPAWN START
        p_spawn = res_grp_subp.add_parser(
            Commands.Subcommands.Spawn.LONG,
            aliases=[Commands.Subcommands.Spawn.SHORT],
            description=
            "Spawns new resource with the settings of the resource group.")
        p_spawn.add_argument('-p',
                             '--partial',
                             action='store_true',
                             help="Allow mismatching volume sizes.")
        p_spawn.add_argument(
            '-d',
            '--definition-only',
            action='store_true',
            help="Do not auto-place resource, only create definitions")
        p_spawn.add_argument('resource_group_name',
                             help="Resource group name to spawn from."
                             ).completer = self.resource_grp_completer
        p_spawn.add_argument(
            'resource_definition_name',
            help=
            "New Resource definition name to create. Will be ignored if EXTERNAL_NAME is set."
        )
        p_spawn.add_argument('--external-name',
                             type=str,
                             help="User specified name")
        p_spawn.add_argument('volume_sizes', nargs='*')
        p_spawn.set_defaults(func=self.spawn)
        #  ------------ SPAWN END

        #  ------------ QMVS START
        p_qmvs = res_grp_subp.add_parser(
            Commands.Subcommands.QueryMaxVlmSize.LONG,
            aliases=[Commands.Subcommands.QueryMaxVlmSize.SHORT],
            description="Queries maximum volume size for a given resource-group"
        )
        p_qmvs.add_argument('-p',
                            '--pastable',
                            action="store_true",
                            help='Generate pastable output')
        p_qmvs.add_argument(
            'resource_group_name',
            help="Resource group name to read auto-config settings from"
        ).completer = self.resource_grp_completer
        p_qmvs.set_defaults(func=self.qmvs)
        #  ------------ QMVS END

        #  ------------ ADJUST START
        p_adjust = res_grp_subp.add_parser(
            Commands.Subcommands.Adjust.LONG,
            aliases=[Commands.Subcommands.Adjust.SHORT],
            description=
            "Adjusts all resource-definition of the given resource-group.\n"
            "CAUTION: This operation might take a long time and even exceed the default 5 min timeout!"
        )
        p_adjust.add_argument('-p',
                              '--pastable',
                              action="store_true",
                              help='Generate pastable output')
        p_adjust.add_argument(
            'resource_group_name',
            nargs="?",
            default=None,
            help=
            "Resource group to adjust. If omitted, all resource groups will be adjusted"
        ).completer = self.resource_grp_completer
        # p_adjust.add_argument('-o', '--overprovision',
        #                       help='Multiplier of thin storage pool\'s free space. Default: 2.0')
        p_adjust.set_defaults(func=self.adjust)
        #  ------------ ADJUST END

        self.check_subcommands(res_grp_subp, subcmds)
Exemplo n.º 3
0
    def setup_commands(self, parser):
        subcmds = [
            Commands.Subcommands.List, Commands.Subcommands.SetProperty,
            Commands.Subcommands.ListProperties,
            Commands.Subcommands.DrbdOptions,
            Commands.Subcommands.DrbdPeerDeviceOptions,
            ResourceConnectionCommands.Path
        ]

        res_conn_parser = parser.add_parser(
            Commands.RESOURCE_CONN,
            aliases=["rc"],
            formatter_class=argparse.RawTextHelpFormatter,
            description="Resource connection subcommands")
        subp = res_conn_parser.add_subparsers(
            title="resource connection commands",
            metavar="",
            description=Commands.Subcommands.generate_desc(subcmds))

        rescon_groubby = [x.name for x in ResourceConnectionCommands._headers]
        res_group_completer = Commands.show_group_completer(
            rescon_groubby, "groupby")

        p_lresconn = subp.add_parser(
            Commands.Subcommands.List.LONG,
            aliases=[Commands.Subcommands.List.SHORT],
            description=
            'Prints a list of all resource connections for the given resource. '
            + 'By default, the list is printed as a human readable table.')
        p_lresconn.add_argument('-p',
                                '--pastable',
                                action="store_true",
                                help='Generate pastable output')
        p_lresconn.add_argument(
            '-g', '--groupby', nargs='+',
            choices=rescon_groubby).completer = res_group_completer
        p_lresconn.add_argument(
            'resource_name',
            help="Resource name").completer = self.resource_completer
        p_lresconn.set_defaults(func=self.list)

        # show properties
        p_sp = subp.add_parser(
            Commands.Subcommands.ListProperties.LONG,
            aliases=[Commands.Subcommands.ListProperties.SHORT],
            description=
            "Prints all properties of the given resource connection.")
        p_sp.add_argument('-p',
                          '--pastable',
                          action="store_true",
                          help='Generate pastable output')
        p_sp.add_argument('node_name_a',
                          help="Node name source of the connection."
                          ).completer = self.node_completer
        p_sp.add_argument('node_name_b',
                          help="Node name target of the connection."
                          ).completer = self.node_completer
        p_sp.add_argument(
            'resource_name',
            help="Resource name").completer = self.resource_completer
        p_sp.set_defaults(func=self.print_props)

        # set properties
        p_setprop = subp.add_parser(
            Commands.Subcommands.SetProperty.LONG,
            aliases=[Commands.Subcommands.SetProperty.SHORT],
            formatter_class=argparse.RawTextHelpFormatter,
            description='Sets properties for the given resource connection.')
        p_setprop.add_argument('node_name_a',
                               help="Node name source of the connection."
                               ).completer = self.node_completer
        p_setprop.add_argument('node_name_b',
                               help="Node name target of the connection."
                               ).completer = self.node_completer
        p_setprop.add_argument(
            'resource_name', type=str,
            help='Name of the resource').completer = self.resource_completer
        Commands.add_parser_keyvalue(p_setprop, "rsc-conn")
        p_setprop.set_defaults(func=self.set_props)

        # drbd peer device options
        p_drbd_peer_opts = subp.add_parser(
            Commands.Subcommands.DrbdOptions.LONG,
            aliases=[
                Commands.Subcommands.DrbdOptions.SHORT,
                Commands.Subcommands.DrbdPeerDeviceOptions.LONG,
                Commands.Subcommands.DrbdPeerDeviceOptions.SHORT
            ],
            description=DrbdOptions.description("peer-device"))
        p_drbd_peer_opts.add_argument('node_a',
                                      type=str,
                                      help="1. Node in the node connection"
                                      ).completer = self.node_completer
        p_drbd_peer_opts.add_argument('node_b',
                                      type=str,
                                      help="2. Node in the node connection"
                                      ).completer = self.node_completer
        p_drbd_peer_opts.add_argument(
            'resource_name', type=str,
            help="Resource name").completer = self.resource_completer

        DrbdOptions.add_arguments(p_drbd_peer_opts, self.OBJECT_NAME)
        p_drbd_peer_opts.set_defaults(func=self.drbd_opts)

        # Path commands
        path_subcmds = [
            Commands.Subcommands.Create, Commands.Subcommands.List,
            Commands.Subcommands.Delete
        ]

        path_parser = subp.add_parser(
            ResourceConnectionCommands.Path.LONG,
            formatter_class=argparse.RawTextHelpFormatter,
            aliases=[ResourceConnectionCommands.Path.SHORT],
            description="%s subcommands" %
            ResourceConnectionCommands.Path.LONG)

        path_subp = path_parser.add_subparsers(
            title="%s subcommands" % Commands.Subcommands.Interface.LONG,
            metavar="",
            description=Commands.Subcommands.generate_desc(path_subcmds))

        # create path
        path_create = path_subp.add_parser(
            Commands.Subcommands.Create.LONG,
            aliases=[Commands.Subcommands.Create.SHORT],
            description='Creates a new resource connection path')
        path_create.add_argument(
            "node_a", type=str,
            help="1. Node of the connection").completer = self.node_completer
        path_create.add_argument(
            "node_b", type=str,
            help="2. Node of the connection").completer = self.node_completer
        path_create.add_argument(
            "resource_name", type=str,
            help="Resource name").completer = self.resource_completer
        path_create.add_argument("path_name", help="Name of the created path")
        path_create.add_argument("netinterface_a",
                                 help="Netinterface name to use for 1. node"
                                 ).completer = self.netif_completer
        path_create.add_argument(
            "netinterface_b", help="Netinterface name to use for the 2. node"
        ).completer = self.netif_completer
        path_create.set_defaults(func=self.path_create)

        # delete path
        path_delete = path_subp.add_parser(
            Commands.Subcommands.Delete.LONG,
            aliases=[Commands.Subcommands.Delete.SHORT],
            description='Deletes an existing resource connection path')
        path_delete.add_argument(
            "node_a", type=str,
            help="1. Node of the connection").completer = self.node_completer
        path_delete.add_argument(
            "node_b", type=str,
            help="2. Node of the connection").completer = self.node_completer
        path_delete.add_argument(
            "resource_name", type=str,
            help="Resource name").completer = self.resource_completer
        path_delete.add_argument("path_name", help="Name of the created path")
        path_delete.set_defaults(func=self.path_delete)

        # list path
        path_list = path_subp.add_parser(
            Commands.Subcommands.List.LONG,
            aliases=[Commands.Subcommands.List.SHORT],
            description='List all existing resource connection paths')
        path_list.add_argument('-p',
                               '--pastable',
                               action="store_true",
                               help='Generate pastable output')
        path_list.add_argument(
            "node_a", type=str,
            help="1. Node of the connection").completer = self.node_completer
        path_list.add_argument(
            "node_b", type=str,
            help="2. Node of the connection").completer = self.node_completer
        path_list.add_argument(
            "resource_name", type=str,
            help="Resource name").completer = self.resource_completer
        path_list.set_defaults(func=self.path_list)

        self.check_subcommands(path_subp, path_subcmds)
        self.check_subcommands(subp, subcmds)
Exemplo n.º 4
0
    def setup_commands(self, parser):
        """

        :param argparse.ArgumentParser parser:
        :return:
        """

        subcmds = [
            Commands.Subcommands.Create, Commands.Subcommands.List,
            Commands.Subcommands.ListVolumes, Commands.Subcommands.Delete,
            Commands.Subcommands.SetProperty,
            Commands.Subcommands.ListProperties,
            Commands.Subcommands.DrbdPeerDeviceOptions
        ]

        # Resource subcommands
        res_parser = parser.add_parser(
            Commands.RESOURCE,
            aliases=["r"],
            formatter_class=argparse.RawTextHelpFormatter,
            description="Resouce subcommands")
        res_subp = res_parser.add_subparsers(
            title="resource commands",
            metavar="",
            description=Commands.Subcommands.generate_desc(subcmds))

        # new-resource
        p_new_res = res_subp.add_parser(
            Commands.Subcommands.Create.LONG,
            aliases=[Commands.Subcommands.Create.SHORT],
            description='Deploys a resource definition to a node.')
        p_new_res.add_argument('--storage-pool',
                               '-s',
                               type=namecheck(STORPOOL_NAME),
                               help="Storage pool name to use."
                               ).completer = self.storage_pool_dfn_completer
        p_new_res.add_argument('--diskless',
                               '-d',
                               action="store_true",
                               help='Should the resource be diskless')
        p_new_res.add_argument(
            '--async',
            action='store_true',
            help='Do not wait for deployment on satellites before returning')
        p_new_res.add_argument(
            '--auto-place',
            type=int,
            metavar="REPLICA_COUNT",
            help='Auto place a resource to a specified number of nodes')
        p_new_res.add_argument(
            '--do-not-place-with',
            type=namecheck(RES_NAME),
            nargs='+',
            metavar="RESOURCE_NAME",
            help=
            'Try to avoid nodes that already have a given resource deployed.'
        ).completer = self.resource_completer
        p_new_res.add_argument(
            '--do-not-place-with-regex',
            type=str,
            metavar="RESOURCE_REGEX",
            help='Try to avoid nodes that already have a resource ' +
            'deployed whos name is matching the given regular expression.')
        p_new_res.add_argument(
            '--replicas-on-same',
            nargs='+',
            default=[],
            metavar="AUX_NODE_PROPERTY",
            help=
            'Tries to place resources on nodes with the same given auxiliary node property values.'
        )
        p_new_res.add_argument(
            '--replicas-on-different',
            nargs='+',
            default=[],
            metavar="AUX_NODE_PROPERTY",
            help=
            'Tries to place resources on nodes with a different value for the given auxiliary node property.'
        )
        p_new_res.add_argument(
            '--diskless-on-remaining',
            action="store_true",
            help='Will add a diskless resource on all non replica nodes.')
        p_new_res.add_argument('node_name',
                               type=namecheck(NODE_NAME),
                               nargs='*',
                               help='Name of the node to deploy the resource'
                               ).completer = self.node_completer
        p_new_res.add_argument('resource_definition_name',
                               type=namecheck(RES_NAME),
                               help='Name of the resource definition'
                               ).completer = self.resource_dfn_completer
        p_new_res.set_defaults(func=self.create)

        # remove-resource
        p_rm_res = res_subp.add_parser(
            Commands.Subcommands.Delete.LONG,
            aliases=[Commands.Subcommands.Delete.SHORT],
            description='Removes a resource. '
            'The resource is undeployed from the node '
            "and the resource entry is marked for removal from linstor's data "
            'tables. After the node has undeployed the resource, the resource '
            "entry is removed from linstor's data tables.")
        p_rm_res.add_argument(
            '-q',
            '--quiet',
            action="store_true",
            help=
            'Unless this option is used, linstor will issue a safety question '
            'that must be answered with yes, otherwise the operation is canceled.'
        )
        p_rm_res.add_argument(
            '--async',
            action='store_true',
            help='Do not wait for deployment on satellites before returning')
        p_rm_res.add_argument(
            'node_name', nargs="+",
            help='Name of the node').completer = self.node_completer
        p_rm_res.add_argument('name', help='Name of the resource to delete'
                              ).completer = self.resource_completer
        p_rm_res.set_defaults(func=self.delete)

        resgroupby = [x.name for x in ResourceCommands._resource_headers]
        res_group_completer = Commands.show_group_completer(
            resgroupby, "groupby")

        p_lreses = res_subp.add_parser(
            Commands.Subcommands.List.LONG,
            aliases=[Commands.Subcommands.List.SHORT],
            description='Prints a list of all resource definitions known to '
            'linstor. By default, the list is printed as a human readable table.'
        )
        p_lreses.add_argument('-p',
                              '--pastable',
                              action="store_true",
                              help='Generate pastable output')
        p_lreses.add_argument(
            '-g', '--groupby', nargs='+',
            choices=resgroupby).completer = res_group_completer
        p_lreses.add_argument('-r',
                              '--resources',
                              nargs='+',
                              type=namecheck(RES_NAME),
                              help='Filter by list of resources'
                              ).completer = self.resource_completer
        p_lreses.add_argument(
            '-n',
            '--nodes',
            nargs='+',
            type=namecheck(NODE_NAME),
            help='Filter by list of nodes').completer = self.node_completer
        p_lreses.set_defaults(func=self.list)

        # list volumes
        p_lvlms = res_subp.add_parser(
            Commands.Subcommands.ListVolumes.LONG,
            aliases=[Commands.Subcommands.ListVolumes.SHORT],
            description='Prints a list of all volumes.')
        p_lvlms.add_argument('-p',
                             '--pastable',
                             action="store_true",
                             help='Generate pastable output')
        p_lvlms.add_argument(
            '-n',
            '--nodes',
            nargs='+',
            type=namecheck(NODE_NAME),
            help='Filter by list of nodes').completer = self.node_completer
        p_lvlms.add_argument('-s',
                             '--storpools',
                             nargs='+',
                             type=namecheck(STORPOOL_NAME),
                             help='Filter by list of storage pools'
                             ).completer = self.storage_pool_completer
        p_lvlms.add_argument('-r',
                             '--resources',
                             nargs='+',
                             type=namecheck(RES_NAME),
                             help='Filter by list of resources'
                             ).completer = self.resource_completer
        p_lvlms.set_defaults(func=self.list_volumes)

        # show properties
        p_sp = res_subp.add_parser(
            Commands.Subcommands.ListProperties.LONG,
            aliases=[Commands.Subcommands.ListProperties.SHORT],
            description="Prints all properties of the given resource.")
        p_sp.add_argument('-p',
                          '--pastable',
                          action="store_true",
                          help='Generate pastable output')
        p_sp.add_argument('node_name',
                          help="Node name where the resource is deployed."
                          ).completer = self.node_completer
        p_sp.add_argument(
            'resource_name',
            help="Resource name").completer = self.resource_completer
        p_sp.set_defaults(func=self.print_props)

        # set properties
        p_setprop = res_subp.add_parser(
            Commands.Subcommands.SetProperty.LONG,
            aliases=[Commands.Subcommands.SetProperty.SHORT],
            description=
            'Sets properties for the given resource on the given node.')
        p_setprop.add_argument('node_name',
                               type=namecheck(NODE_NAME),
                               help='Node name where resource is deployed.'
                               ).completer = self.node_completer
        p_setprop.add_argument(
            'name', type=namecheck(RES_NAME),
            help='Name of the resource').completer = self.resource_completer
        Commands.add_parser_keyvalue(p_setprop, "resource")
        p_setprop.set_defaults(func=self.set_props)

        # drbd peer device options
        p_drbd_peer_opts = res_subp.add_parser(
            Commands.Subcommands.DrbdPeerDeviceOptions.LONG,
            aliases=[Commands.Subcommands.DrbdPeerDeviceOptions.SHORT],
            description="Set drbd peer-device options.")
        p_drbd_peer_opts.add_argument('node_a',
                                      type=namecheck(NODE_NAME),
                                      help="1. Node in the node connection"
                                      ).completer = self.node_completer
        p_drbd_peer_opts.add_argument('node_b',
                                      type=namecheck(NODE_NAME),
                                      help="1. Node in the node connection"
                                      ).completer = self.node_completer
        p_drbd_peer_opts.add_argument(
            'resource_name', type=namecheck(RES_NAME),
            help="Resource name").completer = self.resource_completer

        DrbdOptions.add_arguments(p_drbd_peer_opts, [
            x for x in DrbdOptions.drbd_options()['options'] if DrbdOptions.
            drbd_options()['options'][x]['category'] == 'peer-device-options'
        ])
        p_drbd_peer_opts.set_defaults(func=self.drbd_peer_opts)

        self.check_subcommands(res_subp, subcmds)
Exemplo n.º 5
0
    def setup_commands(self, parser):
        # Controller commands
        subcmds = [
            Commands.Subcommands.SetProperty,
            Commands.Subcommands.ListProperties,
            Commands.Subcommands.DrbdOptions, Commands.Subcommands.Version,
            Commands.Subcommands.QueryMaxVlmSize
        ]

        con_parser = parser.add_parser(
            Commands.CONTROLLER,
            aliases=["c"],
            formatter_class=argparse.RawTextHelpFormatter,
            description="Controller subcommands")

        con_subp = con_parser.add_subparsers(
            title="Controller commands",
            metavar="",
            description=Commands.Subcommands.generate_desc(subcmds))

        # Controller - get props
        c_ctrl_props = con_subp.add_parser(
            Commands.Subcommands.ListProperties.LONG,
            aliases=[Commands.Subcommands.ListProperties.SHORT],
            description='Print current controller config properties.')
        c_ctrl_props.add_argument('-p',
                                  '--pastable',
                                  action="store_true",
                                  help='Generate pastable output')
        c_ctrl_props.set_defaults(func=self.cmd_print_controller_props)

        #  controller - set props
        c_set_ctrl_props = con_subp.add_parser(
            Commands.Subcommands.SetProperty.LONG,
            aliases=[Commands.Subcommands.SetProperty.SHORT],
            formatter_class=argparse.RawTextHelpFormatter,
            description='Set a controller config property.')
        Commands.add_parser_keyvalue(c_set_ctrl_props, "controller")
        c_set_ctrl_props.set_defaults(func=self.set_props)

        c_drbd_opts = con_subp.add_parser(
            Commands.Subcommands.DrbdOptions.LONG,
            aliases=[Commands.Subcommands.DrbdOptions.SHORT],
            description=DrbdOptions.description("drbd"))
        DrbdOptions.add_arguments(c_drbd_opts, self.OBJECT_NAME)
        c_drbd_opts.set_defaults(func=self.cmd_controller_drbd_opts)

        # Controller - version
        c_shutdown = con_subp.add_parser(
            Commands.Subcommands.Version.LONG,
            aliases=[Commands.Subcommands.Version.SHORT],
            description='Prints the linstor controller version')
        c_shutdown.set_defaults(func=self.cmd_version)

        p_query_max_vlm_size = con_subp.add_parser(
            Commands.Subcommands.QueryMaxVlmSize.LONG,
            aliases=[Commands.Subcommands.QueryMaxVlmSize.SHORT],
            description=
            'Queries the controller for storage pools maximum volume size.')
        p_query_max_vlm_size.add_argument('-p',
                                          '--pastable',
                                          action="store_true",
                                          help='Generate pastable output')
        p_query_max_vlm_size.add_argument(
            '--storage-pool',
            '-s',
            type=str,
            help="Storage pool name to query."
        ).completer = self.storage_pool_dfn_completer
        p_query_max_vlm_size.add_argument(
            '--do-not-place-with',
            type=str,
            nargs='+',
            metavar="RESOURCE_NAME",
            help=
            'Try to avoid nodes that already have a given resource deployed.'
        ).completer = self.resource_completer
        p_query_max_vlm_size.add_argument(
            '--do-not-place-with-regex',
            type=str,
            metavar="RESOURCE_REGEX",
            help='Try to avoid nodes that already have a resource ' +
            'deployed whos name is matching the given regular expression.')
        p_query_max_vlm_size.add_argument(
            '--replicas-on-same',
            nargs='+',
            default=[],
            metavar="AUX_NODE_PROPERTY",
            help=
            'Tries to place resources on nodes with the same given auxiliary node property values.'
        )
        p_query_max_vlm_size.add_argument(
            '--replicas-on-different',
            nargs='+',
            default=[],
            metavar="AUX_NODE_PROPERTY",
            help=
            'Tries to place resources on nodes with a different value for the given auxiliary node property.'
        )
        p_query_max_vlm_size.add_argument('replica_count',
                                          type=int,
                                          metavar="REPLICA_COUNT",
                                          help='The least amount of replicas.')
        p_query_max_vlm_size.set_defaults(func=self.query_max_volume_size)

        self.check_subcommands(con_subp, subcmds)
Exemplo n.º 6
0
    def setup_commands(self, parser):
        subcmds = [
            Commands.Subcommands.Create, Commands.Subcommands.List,
            Commands.Subcommands.Delete, Commands.Subcommands.SetProperty,
            Commands.Subcommands.ListProperties,
            Commands.Subcommands.DrbdOptions
        ]

        # volume group subcommands
        vlm_grp_parser = parser.add_parser(
            Commands.VOLUME_GRP,
            aliases=["vg"],
            formatter_class=argparse.RawTextHelpFormatter,
            description="Resource definition subcommands")

        vlm_grp_subp = vlm_grp_parser.add_subparsers(
            title="resource definition subcommands",
            metavar="",
            description=Commands.Subcommands.generate_desc(subcmds))

        #  ------------ CREATE START
        p_new_vlm_grp = vlm_grp_subp.add_parser(
            Commands.Subcommands.Create.LONG,
            aliases=[Commands.Subcommands.Create.SHORT],
            description='Defines a Linstor volume group for use with linstor.')
        p_new_vlm_grp.add_argument('name',
                                   type=str,
                                   help='Name of the resource group.')
        p_new_vlm_grp.add_argument('-n', '--vlmnr', type=int)
        p_new_vlm_grp.set_defaults(func=self.create)
        #  ------------ CREATE END

        #  ------------ DELETE START
        p_rm_vlm_grp = vlm_grp_subp.add_parser(
            Commands.Subcommands.Delete.LONG,
            aliases=[Commands.Subcommands.Delete.SHORT],
            description=" Removes a volume group from the linstor cluster.")
        p_rm_vlm_grp.add_argument('name', help='Name of the resource group'
                                  ).completer = self.resource_grp_completer
        p_rm_vlm_grp.add_argument('volume_nr',
                                  type=int,
                                  help="Volume number to delete.")
        p_rm_vlm_grp.set_defaults(func=self.delete)
        #  ------------ DELETE END

        #  ------------ LIST START
        vlm_grp_groupby = [x.name for x in self._vlm_grp_headers]
        vlm_grp_group_completer = Commands.show_group_completer(
            vlm_grp_groupby, "groupby")

        p_lvlmgrps = vlm_grp_subp.add_parser(
            Commands.Subcommands.List.LONG,
            aliases=[Commands.Subcommands.List.SHORT],
            description=
            'Prints a list of all volume groups for a resource group known to '
            'linstor. By default, the list is printed as a human readable table.'
        )
        p_lvlmgrps.add_argument('-p',
                                '--pastable',
                                action="store_true",
                                help='Generate pastable output')
        p_lvlmgrps.add_argument(
            '-g', '--groupby', nargs='+',
            choices=vlm_grp_groupby).completer = vlm_grp_group_completer
        p_lvlmgrps.add_argument('-R',
                                '--resources',
                                nargs='+',
                                type=str,
                                help='Filter by list of resource groups'
                                ).completer = self.resource_grp_completer
        p_lvlmgrps.add_argument('name', help="Resource group name.")
        p_lvlmgrps.set_defaults(func=self.list)
        #  ------------ LIST END

        #  ------------ LISTPROPS START
        p_sp = vlm_grp_subp.add_parser(
            Commands.Subcommands.ListProperties.LONG,
            aliases=[Commands.Subcommands.ListProperties.SHORT],
            description="Prints all properties of the given volume group.")
        p_sp.add_argument('-p',
                          '--pastable',
                          action="store_true",
                          help='Generate pastable output')
        p_sp.add_argument(
            'name', help="Resource group for which to print the properties"
        ).completer = self.resource_grp_completer
        p_sp.add_argument('volume_nr', type=int, help="Volume number")
        p_sp.set_defaults(func=self.print_props)
        #  ------------ LISTPROPS END

        #  ------------ SETPROPS START
        p_setprop = vlm_grp_subp.add_parser(
            Commands.Subcommands.SetProperty.LONG,
            aliases=[Commands.Subcommands.SetProperty.SHORT],
            formatter_class=argparse.RawTextHelpFormatter,
            description='Sets properties for the given volume group.')
        p_setprop.add_argument('name',
                               type=str,
                               help='Name of the resource group')
        p_setprop.add_argument('volume_nr', type=int, help="Volume number")
        Commands.add_parser_keyvalue(p_setprop, self.OBJECT_NAME)
        p_setprop.set_defaults(func=self.set_props)
        #  ------------ SETPROPS END

        #  ------------ SETDRBDOPTS START
        p_drbd_opts = vlm_grp_subp.add_parser(
            Commands.Subcommands.DrbdOptions.LONG,
            aliases=[Commands.Subcommands.DrbdOptions.SHORT],
            description=DrbdOptions.description("resource"))
        p_drbd_opts.add_argument(
            'name', type=str,
            help="Resource group name").completer = self.resource_grp_completer
        p_drbd_opts.add_argument('volume_nr', type=int, help="Volume number")
        DrbdOptions.add_arguments(p_drbd_opts, self.OBJECT_NAME)
        p_drbd_opts.set_defaults(func=self.set_drbd_opts)
        #  ------------ SETDRBDOPTS END

        self.check_subcommands(vlm_grp_subp, subcmds)
Exemplo n.º 7
0
    def setup_commands(self, parser):
        # volume definition subcommands
        subcmds = [
            Commands.Subcommands.Create, Commands.Subcommands.List,
            Commands.Subcommands.Delete, Commands.Subcommands.SetSize,
            Commands.Subcommands.SetProperty,
            Commands.Subcommands.ListProperties,
            Commands.Subcommands.DrbdOptions
        ]

        vol_def_parser = parser.add_parser(
            Commands.VOLUME_DEF,
            aliases=["vd"],
            formatter_class=argparse.RawTextHelpFormatter,
            description="Volume definition subcommands")

        vol_def_subp = vol_def_parser.add_subparsers(
            title="Volume definition commands",
            metavar="",
            description=Commands.Subcommands.generate_desc(subcmds))

        p_new_vol = vol_def_subp.add_parser(
            Commands.Subcommands.Create.LONG,
            aliases=[Commands.Subcommands.Create.SHORT],
            description='Defines a volume with a capacity of size for use with '
            'linstore. If the resource resname exists already, a new volume is '
            'added to that resource, otherwise the resource is created automatically '
            'with default settings. Unless minornr is specified, a minor number for '
            "the volume's DRBD block device is assigned automatically by the "
            'linstor server.')
        p_new_vol.add_argument('--storage-pool',
                               '-s',
                               type=namecheck(STORPOOL_NAME),
                               help="Storage pool name to use."
                               ).completer = self.storage_pool_dfn_completer
        p_new_vol.add_argument('-n', '--vlmnr', type=int)
        p_new_vol.add_argument('-m', '--minor', type=int)
        p_new_vol.add_argument(
            '--encrypt',
            action="store_true",
            help="Encrypt created volumes using cryptsetup.")
        p_new_vol.add_argument('resource_name',
                               type=namecheck(RES_NAME),
                               help='Name of an existing resource'
                               ).completer = self.resource_dfn_completer
        p_new_vol.add_argument(
            'size', help=VolumeDefinitionCommands.VOLUME_SIZE_HELP
        ).completer = VolumeDefinitionCommands.size_completer
        p_new_vol.set_defaults(func=self.create)

        # remove-volume definition
        p_rm_vol = vol_def_subp.add_parser(
            Commands.Subcommands.Delete.LONG,
            aliases=[Commands.Subcommands.Delete.SHORT],
            description=
            'Removes a volume definition from the linstor cluster, and removes '
            'the volume definition from the resource definition. The volume is '
            'undeployed from all nodes and the volume entry is marked for removal '
            "from the resource definition in linstor's data tables. After all "
            'nodes have undeployed the volume, the volume entry is removed from '
            'the resource definition.')
        p_rm_vol.add_argument(
            '-q',
            '--quiet',
            action="store_true",
            help=
            'Unless this option is used, linstor will issue a safety question '
            'that must be answered with yes, otherwise the operation is canceled.'
        )
        p_rm_vol.add_argument('resource_name',
                              help='Resource name of the volume definition'
                              ).completer = self.resource_dfn_completer
        p_rm_vol.add_argument('volume_nr',
                              type=int,
                              help="Volume number to delete.")
        p_rm_vol.set_defaults(func=self.delete)

        # list volume definitions
        vlm_dfn_groupby = [x.name for x in self._vlm_dfn_headers]
        vlm_dfn_group_completer = Commands.show_group_completer(
            vlm_dfn_groupby, "groupby")

        p_lvols = vol_def_subp.add_parser(
            Commands.Subcommands.List.LONG,
            aliases=[Commands.Subcommands.List.SHORT],
            description=
            ' Prints a list of all volume definitions known to linstor. '
            'By default, the list is printed as a human readable table.')
        p_lvols.add_argument('-p',
                             '--pastable',
                             action="store_true",
                             help='Generate pastable output')
        p_lvols.add_argument(
            '-g', '--groupby', nargs='+',
            choices=vlm_dfn_groupby).completer = vlm_dfn_group_completer
        p_lvols.add_argument('-R',
                             '--resources',
                             nargs='+',
                             type=namecheck(RES_NAME),
                             help='Filter by list of resources'
                             ).completer = self.resource_dfn_completer
        p_lvols.set_defaults(func=self.list)

        # show properties
        p_sp = vol_def_subp.add_parser(
            Commands.Subcommands.ListProperties.LONG,
            aliases=[Commands.Subcommands.ListProperties.SHORT],
            description="Prints all properties of the given volume definition."
        )
        p_sp.add_argument('-p',
                          '--pastable',
                          action="store_true",
                          help='Generate pastable output')
        p_sp.add_argument(
            'resource_name',
            help="Resource name").completer = self.resource_dfn_completer
        p_sp.add_argument('volume_nr', type=int, help="Volume number")
        p_sp.set_defaults(func=self.print_props)

        # set properties
        p_setprop = vol_def_subp.add_parser(
            Commands.Subcommands.SetProperty.LONG,
            aliases=[Commands.Subcommands.SetProperty.SHORT],
            description='Sets properties for the given volume definition.')
        p_setprop.add_argument(
            'resource_name',
            help="Resource name").completer = self.resource_dfn_completer
        p_setprop.add_argument('volume_nr', type=int, help="Volume number")
        Commands.add_parser_keyvalue(p_setprop, "volume-definition")
        p_setprop.set_defaults(func=self.set_props)

        p_drbd_opts = vol_def_subp.add_parser(
            Commands.Subcommands.DrbdOptions.LONG,
            aliases=[Commands.Subcommands.DrbdOptions.SHORT],
            description="Set drbd volume options.")
        p_drbd_opts.add_argument(
            'resource_name', type=namecheck(RES_NAME),
            help="Resource name").completer = self.resource_dfn_completer
        p_drbd_opts.add_argument('volume_nr', type=int, help="Volume number")
        DrbdOptions.add_arguments(p_drbd_opts, [
            x for x in DrbdOptions.drbd_options()['options']
            if x in DrbdOptions.drbd_options()['filters']['volume']
        ])
        p_drbd_opts.set_defaults(func=self.set_drbd_opts)

        # set size
        p_set_size = vol_def_subp.add_parser(
            Commands.Subcommands.SetSize.LONG,
            aliases=[Commands.Subcommands.SetSize.SHORT],
            description='Change the size of a volume. '
            'Decreasing the size is only supported when the resource definition does not have any '
            'resources. '
            'Increasing the size is supported even when the resource definition has resources. '
            'Filesystems present on the volumes will not be resized.')
        p_set_size.add_argument('resource_name',
                                type=namecheck(RES_NAME),
                                help='Name of an existing resource'
                                ).completer = self.resource_dfn_completer
        p_set_size.add_argument('volume_nr', type=int, help="Volume number")
        p_set_size.add_argument(
            'size', help=VolumeDefinitionCommands.VOLUME_SIZE_HELP
        ).completer = VolumeDefinitionCommands.size_completer
        p_set_size.set_defaults(func=self.set_volume_size)

        self.check_subcommands(vol_def_subp, subcmds)
Exemplo n.º 8
0
    def setup_commands(self, parser):
        subcmds = [
            Commands.Subcommands.Create,
            Commands.Subcommands.MakeAvailable,
            Commands.Subcommands.List,
            Commands.Subcommands.ListVolumes,
            Commands.Subcommands.Delete,
            Commands.Subcommands.SetProperty,
            Commands.Subcommands.ListProperties,
            Commands.Subcommands.DrbdPeerDeviceOptions,
            Commands.Subcommands.ToggleDisk,
            Commands.Subcommands.CreateTransactional,
            Commands.Subcommands.Activate,
            Commands.Subcommands.Deactivate,
            Commands.Subcommands.Involved
        ]

        # Resource subcommands
        res_parser = parser.add_parser(
            Commands.RESOURCE,
            aliases=["r"],
            formatter_class=argparse.RawTextHelpFormatter,
            description="Resouce subcommands")
        res_subp = res_parser.add_subparsers(
            title="resource commands",
            metavar="",
            description=Commands.Subcommands.generate_desc(subcmds)
        )

        # new-resource
        p_new_res = res_subp.add_parser(
            Commands.Subcommands.Create.LONG,
            aliases=[Commands.Subcommands.Create.SHORT],
            description='Deploys a resource definition to a node.')
        p_new_res.add_argument(
            '--diskless', '-d',
            action="store_true",
            help='DEPRECATED. Use --nvme-initiator or --drbd-diskless instead'
        )
        p_new_res.add_argument(
            '--node-id',
            type=int,
            help='Override the automatic selection of DRBD node ID'
        )
        p_new_res.add_argument(
            '--async',
            action='store_true',
            help='Deprecated, kept for compatibility'
        )
        p_new_res.add_argument(
            '--nvme-initiator',
            action="store_true",
            help='Mark this resource as initiator'
        )
        p_new_res.add_argument(
            '--drbd-diskless',
            action="store_true",
            help='Mark this resource as drbd diskless'
        )
        p_new_res.add_argument(
            '--inactive',
            action="store_true",
            help="Marks the resource created as inactive"
        )
        self.add_auto_select_argparse_arguments(p_new_res)
        p_new_res.add_argument(
            'node_name',
            type=str,
            nargs='*',
            help='Name of the node to deploy the resource').completer = self.node_completer
        p_new_res.add_argument(
            'resource_definition_name',
            type=str,
            help='Name of the resource definition').completer = self.resource_dfn_completer
        p_new_res.set_defaults(func=self.create, allowed_states=[DefaultState, ResourceCreateTransactionState])

        # make available
        p_mkavial = res_subp.add_parser(
            Commands.Subcommands.MakeAvailable.LONG,
            aliases=[Commands.Subcommands.MakeAvailable.SHORT],
            description='Make a resource available on a node, noop if already exists.')
        p_mkavial.add_argument(
            '--diskful',
            action="store_true",
            help='Make the resource diskful on the node.'
        )
        p_mkavial.add_argument(
            '-l', '--layer-list',
            type=self.layer_data_check,
            help="Comma separated layer list, order is from left to right top-down "
                 "This means the top most layer is on the left. "
                 "Possible layers are: " + ",".join(linstor.Linstor.layer_list()))
        p_mkavial.add_argument(
            'node_name',
            type=str,
            help='Name of the node to deploy the resource').completer = self.node_completer
        p_mkavial.add_argument(
            'resource_name',
            type=str,
            help='Name of the resource definition').completer = self.resource_dfn_completer
        p_mkavial.set_defaults(func=self.make_available)

        # remove-resource
        p_rm_res = res_subp.add_parser(
            Commands.Subcommands.Delete.LONG,
            aliases=[Commands.Subcommands.Delete.SHORT],
            description='Removes a resource. '
            'The resource is undeployed from the node '
            "and the resource entry is marked for removal from linstor's data "
            'tables. After the node has undeployed the resource, the resource '
            "entry is removed from linstor's data tables.")
        p_rm_res.add_argument(
            '--async',
            action='store_true',
            help='Deprecated, kept for compatibility'
        )
        p_rm_res.add_argument('node_name',
                              nargs="+",
                              help='Name of the node').completer = self.node_completer
        p_rm_res.add_argument('name',
                              help='Name of the resource to delete').completer = self.resource_completer
        p_rm_res.set_defaults(func=self.delete)

        resgroupby = [x.name.lower() for x in ResourceCommands._resource_headers]
        res_group_completer = Commands.show_group_completer(resgroupby, "groupby")

        p_lreses = res_subp.add_parser(
            Commands.Subcommands.List.LONG,
            aliases=[Commands.Subcommands.List.SHORT],
            description='Prints a list of all resource definitions known to '
            'linstor. By default, the list is printed as a human readable table.')
        p_lreses.add_argument('-p', '--pastable', action="store_true", help='Generate pastable output')
        p_lreses.add_argument(
            '-g', '--groupby',
            nargs='+',
            choices=resgroupby,
            type=str.lower).completer = res_group_completer
        p_lreses.add_argument(
            '-r', '--resources',
            nargs='+',
            type=str,
            help='Filter by list of resources').completer = self.resource_completer
        p_lreses.add_argument(
            '-n', '--nodes',
            nargs='+',
            type=str,
            help='Filter by list of nodes').completer = self.node_completer
        p_lreses.add_argument(
            '-a', '--all',
            action="store_true",
            help='Show all resources.')
        p_lreses.add_argument(
            '--faulty',
            action="store_true",
            help='Only show faulty resource.')
        p_lreses.add_argument('--props', nargs='+', type=str, help='Filter list by object properties')
        p_lreses.set_defaults(func=self.list)

        p_involved = res_subp.add_parser(
            Commands.Subcommands.Involved.LONG,
            aliases=[Commands.Subcommands.Involved.SHORT],
            description='Prints a list of resourced involved on a given node')
        p_involved.add_argument('-p', '--pastable', action="store_true", help='Generate pastable output')
        p_involved.add_argument('-i', '--inuse', action="store_true", help='Only show resource bundles that are used.')
        p_involved.add_argument(
            '-d',
            '--diskless-inuse',
            action="store_true",
            help='Only show resource bundles that have a diskless in-use.')
        p_involved.add_argument(
            '-m',
            '--min-diskful',
            type=int,
            default=None,
            help='Only show resource bundles that have less diskful replicas.')
        p_involved.add_argument(
            'node',
            type=str,
            help='Node name where a resource is used').completer = self.node_completer
        p_involved.set_defaults(func=self.involved)

        # list volumes
        p_lvlms = res_subp.add_parser(
            Commands.Subcommands.ListVolumes.LONG,
            aliases=[Commands.Subcommands.ListVolumes.SHORT],
            description='Prints a list of all volumes.'
        )
        p_lvlms.add_argument('-p', '--pastable', action="store_true", help='Generate pastable output')
        p_lvlms.add_argument(
            '-n', '--nodes',
            nargs='+',
            type=str,
            help='Filter by list of nodes').completer = self.node_completer
        p_lvlms.add_argument('-s', '--storage-pools', nargs='+', type=str,
                             help='Filter by list of storage pools').completer = self.storage_pool_completer
        p_lvlms.add_argument(
            '-r', '--resources',
            nargs='+',
            type=str,
            help='Filter by list of resources').completer = self.resource_completer
        p_lvlms.add_argument(
            '-a', '--all',
            action="store_true",
            help='Show all resources.'
        )
        p_lvlms.set_defaults(func=self.list_volumes)

        # show properties
        p_sp = res_subp.add_parser(
            Commands.Subcommands.ListProperties.LONG,
            aliases=[Commands.Subcommands.ListProperties.SHORT],
            description="Prints all properties of the given resource.")
        p_sp.add_argument('-p', '--pastable', action="store_true", help='Generate pastable output')
        p_sp.add_argument(
            'node_name',
            help="Node name where the resource is deployed.").completer = self.node_completer
        p_sp.add_argument(
            'resource_name',
            help="Resource name").completer = self.resource_completer
        p_sp.set_defaults(func=self.print_props)

        # set properties
        p_setprop = res_subp.add_parser(
            Commands.Subcommands.SetProperty.LONG,
            aliases=[Commands.Subcommands.SetProperty.SHORT],
            formatter_class=argparse.RawTextHelpFormatter,
            description='Sets properties for the given resource on the given node.')
        p_setprop.add_argument(
            'node_name',
            type=str,
            help='Node name where resource is deployed.').completer = self.node_completer
        p_setprop.add_argument(
            'name',
            type=str,
            help='Name of the resource'
        ).completer = self.resource_completer
        Commands.add_parser_keyvalue(p_setprop, "resource")
        p_setprop.set_defaults(func=self.set_props)

        # drbd peer device options
        p_drbd_peer_opts = res_subp.add_parser(
            Commands.Subcommands.DrbdPeerDeviceOptions.LONG,
            aliases=[Commands.Subcommands.DrbdPeerDeviceOptions.SHORT],
            description=DrbdOptions.description("peer-device")
        )
        p_drbd_peer_opts.add_argument(
            'node_a',
            type=str,
            help="1. Node in the node connection"
        ).completer = self.node_completer
        p_drbd_peer_opts.add_argument(
            'node_b',
            type=str,
            help="1. Node in the node connection"
        ).completer = self.node_completer
        p_drbd_peer_opts.add_argument(
            'resource_name',
            type=str,
            help="Resource name"
        ).completer = self.resource_completer

        DrbdOptions.add_arguments(p_drbd_peer_opts, self.CONN_OBJECT_NAME)
        p_drbd_peer_opts.set_defaults(func=self.drbd_peer_opts)

        # toggle-disk
        p_toggle_disk = res_subp.add_parser(
            Commands.Subcommands.ToggleDisk.LONG,
            aliases=[Commands.Subcommands.ToggleDisk.SHORT],
            description='Toggles a resource between diskless and having disks.')
        p_toggle_disk_group_storage = p_toggle_disk.add_mutually_exclusive_group(required=False)
        p_toggle_disk_group_storage.add_argument(
            '--storage-pool', '-s',
            type=str,
            help="Add disks to a diskless resource using this storage pool name"
        ).completer = self.storage_pool_dfn_completer
        p_toggle_disk_group_storage.add_argument(
            '--default-storage-pool', '--dflt',
            action='store_true',
            help="Add disks to a diskless resource using the storage pools determined from the properties of the "
                 "objects to which the volumes belong"
        )
        p_toggle_disk_group_storage.add_argument(
            '--diskless', '-d',
            action='store_true',
            help="Remove the disks from a resource (toggles --drbd-diskless)"
        )
        p_toggle_disk.add_argument(
            '--async',
            action='store_true',
            help='Deprecated, kept for compatibility'
        )
        p_toggle_disk.add_argument(
            '--migrate-from',
            type=str,
            metavar="MIGRATION_SOURCE",
            help='Name of the node on which the resource should be deleted once the sync is complete. '
                 'Only applicable when adding a disk to a diskless resource. '
                 'The command will complete once the new disk has been added; '
                 'the deletion will occur later in the background.'
        ).completer = self.node_completer
        p_toggle_disk.add_argument(
            'node_name',
            type=str,
            help='Node name where resource is deployed'
        ).completer = self.node_completer
        p_toggle_disk.add_argument(
            'name',
            type=str,
            help='Name of the resource'
        ).completer = self.resource_dfn_completer
        p_toggle_disk.set_defaults(func=self.toggle_disk, parser=p_toggle_disk)

        # activate/deactivate resource commands
        p_activate = res_subp.add_parser(
            Commands.Subcommands.Activate.LONG,
            aliases=[Commands.Subcommands.Activate.SHORT],
            description='Activate a resource.')
        p_activate.add_argument(
            'node_name',
            type=str,
            help='Node name of the resource').completer = self.node_completer
        p_activate.add_argument(
            'resource_name',
            type=str,
            help='Name of the resource').completer = self.resource_dfn_completer
        p_activate.set_defaults(func=self.activate)

        p_deactivate = res_subp.add_parser(
            Commands.Subcommands.Deactivate.LONG,
            aliases=[Commands.Subcommands.Deactivate.SHORT],
            description='Deactivate a resource.')
        p_deactivate.add_argument(
            'node_name',
            type=str,
            help='Node name of the resource').completer = self.node_completer
        p_deactivate.add_argument(
            'resource_name',
            type=str,
            help='Name of the resource').completer = self.resource_dfn_completer
        p_deactivate.set_defaults(func=self.deactivate)

        # resource creation transaction commands
        transactional_create_subcmds = [
            Commands.Subcommands.Begin,
            Commands.Subcommands.Abort,
            Commands.Subcommands.Commit
        ]

        transactional_create_parser = res_subp.add_parser(
            Commands.Subcommands.CreateTransactional.LONG,
            formatter_class=argparse.RawTextHelpFormatter,
            aliases=[Commands.Subcommands.CreateTransactional.SHORT],
            description="%s subcommands" % Commands.Subcommands.CreateTransactional.LONG)

        transactional_create_subp = transactional_create_parser.add_subparsers(
            title="%s subcommands" % Commands.Subcommands.CreateTransactional.LONG,
            description=Commands.Subcommands.generate_desc(transactional_create_subcmds))

        # begin resource creation transaction
        p_transactional_create_begin = transactional_create_subp.add_parser(
            Commands.Subcommands.Begin.LONG,
            aliases=[Commands.Subcommands.Begin.SHORT],
            description='Start group of resources to create in a single transaction.')
        p_transactional_create_begin.add_argument(
            '--terminate-on-error',
            action='store_true',
            help='Abort the transaction when any command fails'
        )
        p_transactional_create_begin.set_defaults(func=self.transactional_create_begin)

        # abort resource creation transaction
        p_transactional_create_abort = transactional_create_subp.add_parser(
            Commands.Subcommands.Abort.LONG,
            aliases=[Commands.Subcommands.Abort.SHORT],
            description='Abort resource creation transaction.')
        p_transactional_create_abort.set_defaults(
            func=self.transactional_create_abort, allowed_states=[ResourceCreateTransactionState])

        # commit resource creation transaction
        p_transactional_create_commit = transactional_create_subp.add_parser(
            Commands.Subcommands.Commit.LONG,
            aliases=[Commands.Subcommands.Commit.SHORT],
            description='Create resources defined in the current resource creation transaction.')
        p_transactional_create_commit.add_argument(
            '--async',
            action='store_true',
            help='Deprecated, kept for compatibility'
        )
        p_transactional_create_commit.set_defaults(
            func=self.transactional_create_commit, allowed_states=[ResourceCreateTransactionState])

        self.check_subcommands(transactional_create_subp, transactional_create_subcmds)
        self.check_subcommands(res_subp, subcmds)
Exemplo n.º 9
0
    def setup_commands(self, parser):
        subcmds = [
            Commands.Subcommands.Create,
            Commands.Subcommands.List,
            Commands.Subcommands.Delete,
            Commands.Subcommands.SetProperty,
            Commands.Subcommands.ListProperties,
            Commands.Subcommands.DrbdOptions
        ]

        # Resource subcommands
        res_def_parser = parser.add_parser(
            Commands.RESOURCE_DEF,
            aliases=["rd"],
            formatter_class=argparse.RawTextHelpFormatter,
            description="Resource definition subcommands")

        res_def_subp = res_def_parser.add_subparsers(
            title="resource definition subcommands",
            metavar="",
            description=Commands.Subcommands.generate_desc(subcmds)
        )

        p_new_res_dfn = res_def_subp.add_parser(
            Commands.Subcommands.Create.LONG,
            aliases=[Commands.Subcommands.Create.SHORT],
            description='Defines a Linstor resource definition for use with linstor.')
        p_new_res_dfn.add_argument('-p', '--port', type=rangecheck(1, 65535))
        # p_new_res_dfn.add_argument('-s', '--secret', type=str)
        p_new_res_dfn.add_argument('name', type=namecheck(RES_NAME), help='Name of the new resource definition')
        p_new_res_dfn.set_defaults(func=self.create)

        # remove-resource definition
        # TODO description
        p_rm_res_dfn = res_def_subp.add_parser(
            Commands.Subcommands.Delete.LONG,
            aliases=[Commands.Subcommands.Delete.SHORT],
            description=" Removes a resource definition "
            "from the linstor cluster. The resource is undeployed from all nodes "
            "and the resource entry is marked for removal from linstor's data "
            "tables. After all nodes have undeployed the resource, the resource "
            "entry is removed from linstor's data tables.")
        p_rm_res_dfn.add_argument('-q', '--quiet', action="store_true",
                                  help='Unless this option is used, linstor will issue a safety question '
                                  'that must be answered with yes, otherwise the operation is canceled.')
        p_rm_res_dfn.add_argument(
            'name',
            nargs="+",
            help='Name of the resource to delete').completer = self.resource_dfn_completer
        p_rm_res_dfn.set_defaults(func=self.delete)

        rsc_dfn_groupby = [x.name for x in self._rsc_dfn_headers]
        rsc_dfn_group_completer = Commands.show_group_completer(rsc_dfn_groupby, "groupby")

        p_lrscdfs = res_def_subp.add_parser(
            Commands.Subcommands.List.LONG,
            aliases=[Commands.Subcommands.List.SHORT],
            description='Prints a list of all resource definitions known to '
            'linstor. By default, the list is printed as a human readable table.')
        p_lrscdfs.add_argument('-p', '--pastable', action="store_true", help='Generate pastable output')
        p_lrscdfs.add_argument('-g', '--groupby', nargs='+',
                               choices=rsc_dfn_groupby).completer = rsc_dfn_group_completer
        p_lrscdfs.add_argument('-R', '--resources', nargs='+', type=namecheck(RES_NAME),
                               help='Filter by list of resources').completer = self.resource_dfn_completer
        p_lrscdfs.set_defaults(func=self.list)

        # show properties
        p_sp = res_def_subp.add_parser(
            Commands.Subcommands.ListProperties.LONG,
            aliases=[Commands.Subcommands.ListProperties.SHORT],
            description="Prints all properties of the given resource definitions.")
        p_sp.add_argument('-p', '--pastable', action="store_true", help='Generate pastable output')
        p_sp.add_argument(
            'resource_name',
            help="Resource definition for which to print the properties"
        ).completer = self.resource_dfn_completer
        p_sp.set_defaults(func=self.print_props)

        # set properties
        p_setprop = res_def_subp.add_parser(
            Commands.Subcommands.SetProperty.LONG,
            aliases=[Commands.Subcommands.SetProperty.SHORT],
            description='Sets properties for the given resource definition.')
        p_setprop.add_argument('name', type=namecheck(RES_NAME), help='Name of the resource definition')
        Commands.add_parser_keyvalue(p_setprop, 'resource-definition')
        p_setprop.set_defaults(func=self.set_props)

        # drbd options
        p_drbd_opts = res_def_subp.add_parser(
            Commands.Subcommands.DrbdOptions.LONG,
            aliases=[Commands.Subcommands.DrbdOptions.SHORT],
            description="Set drbd resource options."
        )
        p_drbd_opts.add_argument(
            'resource_name',
            type=namecheck(RES_NAME),
            help="Resource name"
        ).completer = self.resource_dfn_completer
        DrbdOptions.add_arguments(
            p_drbd_opts,
            [x for x in DrbdOptions.drbd_options()['options'] if x in DrbdOptions.drbd_options()['filters']['resource']]
        )
        p_drbd_opts.set_defaults(func=self.set_drbd_opts)

        self.check_subcommands(res_def_subp, subcmds)
Exemplo n.º 10
0
    def setup_commands(self, parser):
        subcmds = [
            Commands.Subcommands.Create, Commands.Subcommands.Modify,
            Commands.Subcommands.List, Commands.Subcommands.Delete,
            Commands.Subcommands.SetProperty,
            Commands.Subcommands.ListProperties,
            Commands.Subcommands.DrbdOptions
        ]

        # Resource definition subcommands
        res_def_parser = parser.add_parser(
            Commands.RESOURCE_DEF,
            aliases=["rd"],
            formatter_class=argparse.RawTextHelpFormatter,
            description="Resource definition subcommands")

        res_def_subp = res_def_parser.add_subparsers(
            title="resource definition subcommands",
            metavar="",
            description=Commands.Subcommands.generate_desc(subcmds))

        p_new_res_dfn = res_def_subp.add_parser(
            Commands.Subcommands.Create.LONG,
            aliases=[Commands.Subcommands.Create.SHORT],
            description=
            'Defines a Linstor resource definition for use with linstor.')
        p_new_res_dfn.add_argument('-p', '--port', type=rangecheck(1, 65535))
        p_new_res_dfn.add_argument('-e',
                                   '--external-name',
                                   type=str,
                                   help='User specified name.')
        # p_new_res_dfn.add_argument('-s', '--secret', type=str)
        p_new_res_dfn.add_argument(
            '-l',
            '--layer-list',
            type=self.layer_data_check,
            help="Comma separated layer list, order is from right to left. "
            "This means the top most layer is on the left. "
            "Possible layers are: " + ",".join(linstor.Linstor.layer_list()))
        p_new_res_dfn.add_argument('--peer-slots',
                                   type=rangecheck(1, 31),
                                   help='(DRBD) peer slots for new resources')
        p_new_res_dfn.add_argument(
            '--resource-group',
            help="Attach the resource definition to this resource group"
        ).completer = self.resource_grp_completer
        p_new_res_dfn.add_argument(
            'name',
            nargs="?",
            type=str,
            help=
            'Name of the new resource definition. Will be ignored if EXTERNAL_NAME is set.'
        )
        p_new_res_dfn.set_defaults(func=self.create)

        # modify-resource definition
        p_mod_res_dfn = res_def_subp.add_parser(
            Commands.Subcommands.Modify.LONG,
            aliases=[Commands.Subcommands.Modify.SHORT],
            description='Modifies a Linstor resource definition')
        p_mod_res_dfn.add_argument('--peer-slots',
                                   type=rangecheck(1, 31),
                                   help='(DRBD) peer slots for new resources')
        p_mod_res_dfn.add_argument('name',
                                   help='Name of the resource definition'
                                   ).completer = self.resource_dfn_completer
        p_mod_res_dfn.set_defaults(func=self.modify)

        # remove-resource definition
        # TODO description
        p_rm_res_dfn = res_def_subp.add_parser(
            Commands.Subcommands.Delete.LONG,
            aliases=[Commands.Subcommands.Delete.SHORT],
            description=" Removes a resource definition "
            "from the linstor cluster. The resource is undeployed from all nodes "
            "and the resource entry is marked for removal from linstor's data "
            "tables. After all nodes have undeployed the resource, the resource "
            "entry is removed from linstor's data tables.")
        p_rm_res_dfn.add_argument(
            '--async',
            action='store_true',
            help=
            'Do not wait for actual deletion on satellites before returning')
        p_rm_res_dfn.add_argument('name',
                                  nargs="+",
                                  help='Name of the resource to delete'
                                  ).completer = self.resource_dfn_completer
        p_rm_res_dfn.set_defaults(func=self.delete)

        rsc_dfn_groupby = [x.name for x in self._rsc_dfn_headers]
        rsc_dfn_group_completer = Commands.show_group_completer(
            rsc_dfn_groupby, "groupby")

        p_lrscdfs = res_def_subp.add_parser(
            Commands.Subcommands.List.LONG,
            aliases=[Commands.Subcommands.List.SHORT],
            description='Prints a list of all resource definitions known to '
            'linstor. By default, the list is printed as a human readable table.'
        )
        p_lrscdfs.add_argument('-p',
                               '--pastable',
                               action="store_true",
                               help='Generate pastable output')
        p_lrscdfs.add_argument(
            '-g', '--groupby', nargs='+',
            choices=rsc_dfn_groupby).completer = rsc_dfn_group_completer
        p_lrscdfs.add_argument('-r',
                               '--resource-definitions',
                               nargs='+',
                               type=str,
                               help='Filter by list of resource definitions'
                               ).completer = self.resource_dfn_completer
        p_lrscdfs.add_argument('-e',
                               '--external-name',
                               action="store_true",
                               help='Show user specified name.')
        p_lrscdfs.set_defaults(func=self.list)

        # show properties
        p_sp = res_def_subp.add_parser(
            Commands.Subcommands.ListProperties.LONG,
            aliases=[Commands.Subcommands.ListProperties.SHORT],
            description=
            "Prints all properties of the given resource definitions.")
        p_sp.add_argument('-p',
                          '--pastable',
                          action="store_true",
                          help='Generate pastable output')
        p_sp.add_argument(
            'resource_name',
            help="Resource definition for which to print the properties"
        ).completer = self.resource_dfn_completer
        p_sp.set_defaults(func=self.print_props)

        # set properties
        p_setprop = res_def_subp.add_parser(
            Commands.Subcommands.SetProperty.LONG,
            aliases=[Commands.Subcommands.SetProperty.SHORT],
            formatter_class=argparse.RawTextHelpFormatter,
            description='Sets properties for the given resource definition.')
        p_setprop.add_argument('name',
                               type=str,
                               help='Name of the resource definition')
        Commands.add_parser_keyvalue(p_setprop, 'resource-definition')
        p_setprop.set_defaults(func=self.set_props)

        # drbd options
        p_drbd_opts = res_def_subp.add_parser(
            Commands.Subcommands.DrbdOptions.LONG,
            aliases=[Commands.Subcommands.DrbdOptions.SHORT],
            description=DrbdOptions.description("resource"))
        p_drbd_opts.add_argument(
            'resource_name', type=str,
            help="Resource name").completer = self.resource_dfn_completer
        DrbdOptions.add_arguments(p_drbd_opts, self.OBJECT_NAME)
        p_drbd_opts.set_defaults(func=self.set_drbd_opts)

        self.check_subcommands(res_def_subp, subcmds)
Exemplo n.º 11
0
    def setup_commands(self, parser):
        subcmds = [
            Commands.Subcommands.Create,
            Commands.Subcommands.AutoPlace,
            Commands.Subcommands.Modify,
            Commands.Subcommands.List,
            Commands.Subcommands.Delete,
            Commands.Subcommands.SetProperty,
            Commands.Subcommands.ListProperties,
            Commands.Subcommands.DrbdOptions,
            Commands.Subcommands.Clone,
            Commands.Subcommands.WaitSync,
        ]

        # Resource definition subcommands
        res_def_parser = parser.add_parser(
            Commands.RESOURCE_DEF,
            aliases=["rd"],
            formatter_class=argparse.RawTextHelpFormatter,
            description="Resource definition subcommands")

        res_def_subp = res_def_parser.add_subparsers(
            title="resource definition subcommands",
            metavar="",
            description=Commands.Subcommands.generate_desc(subcmds))

        p_new_res_dfn = res_def_subp.add_parser(
            Commands.Subcommands.Create.LONG,
            aliases=[Commands.Subcommands.Create.SHORT],
            description=
            'Defines a Linstor resource definition for use with linstor.')
        p_new_res_dfn.add_argument('-p', '--port', type=rangecheck(1, 65535))
        p_new_res_dfn.add_argument('-e',
                                   '--external-name',
                                   type=str,
                                   help='User specified name.')
        # p_new_res_dfn.add_argument('-s', '--secret', type=str)
        p_new_res_dfn.add_argument(
            '-l',
            '--layer-list',
            type=self.layer_data_check,
            help="Comma separated layer list, order is from right to left. "
            "This means the top most layer is on the left. "
            "Possible layers are: " + ",".join(linstor.Linstor.layer_list()))
        p_new_res_dfn.add_argument('--peer-slots',
                                   type=rangecheck(1, 31),
                                   help='(DRBD) peer slots for new resources')
        p_new_res_dfn.add_argument(
            '--resource-group',
            help="Attach the resource definition to this resource group"
        ).completer = self.resource_grp_completer
        p_new_res_dfn.add_argument(
            'name',
            nargs="?",
            type=str,
            help=
            'Name of the new resource definition. Will be ignored if EXTERNAL_NAME is set.'
        )
        p_new_res_dfn.set_defaults(func=self.create)

        p_auto_place = res_def_subp.add_parser(
            Commands.Subcommands.AutoPlace.LONG,
            aliases=[Commands.Subcommands.AutoPlace.SHORT],
            description='Auto place a resource definition')
        self.add_auto_select_argparse_arguments(p_auto_place,
                                                use_place_count=True)
        p_auto_place.add_argument(
            'resource_definition_name',
            help='Name of the resource definition to auto place')
        p_auto_place.add_argument('--nvme-initiator',
                                  action="store_true",
                                  help='Mark this resource as initiator')
        p_auto_place.add_argument('--drbd-diskless',
                                  action="store_true",
                                  help='Mark this resource as drbd diskless')
        p_auto_place.set_defaults(func=self.auto_place)

        # modify-resource definition
        p_mod_res_dfn = res_def_subp.add_parser(
            Commands.Subcommands.Modify.LONG,
            aliases=[Commands.Subcommands.Modify.SHORT],
            description='Modifies a Linstor resource definition')
        p_mod_res_dfn.add_argument('--peer-slots',
                                   type=rangecheck(1, 31),
                                   help='(DRBD) peer slots for new resources')
        p_mod_res_dfn.add_argument(
            '--resource-group', help='Change resource group to the given one.'
        ).completer = self.resource_grp_completer
        p_mod_res_dfn.add_argument('name',
                                   help='Name of the resource definition'
                                   ).completer = self.resource_dfn_completer
        p_mod_res_dfn.set_defaults(func=self.modify)

        # remove-resource definition
        p_rm_res_dfn = res_def_subp.add_parser(
            Commands.Subcommands.Delete.LONG,
            aliases=[Commands.Subcommands.Delete.SHORT],
            description=" Removes a resource definition "
            "from the linstor cluster. The resource is undeployed from all nodes "
            "and the resource entry is marked for removal from linstor's data "
            "tables. After all nodes have undeployed the resource, the resource "
            "entry is removed from linstor's data tables.")
        p_rm_res_dfn.add_argument('--async',
                                  action='store_true',
                                  help='Deprecated, kept for compatibility')
        p_rm_res_dfn.add_argument('name',
                                  nargs="+",
                                  help='Name of the resource to delete'
                                  ).completer = self.resource_dfn_completer
        p_rm_res_dfn.set_defaults(func=self.delete)

        rsc_dfn_groupby = [x.name.lower() for x in self._rsc_dfn_headers]
        rsc_dfn_group_completer = Commands.show_group_completer(
            rsc_dfn_groupby, "groupby")

        p_clone_rscdfn = res_def_subp.add_parser(
            Commands.Subcommands.Clone.LONG,
            aliases=[Commands.Subcommands.Clone.SHORT],
            description=
            "Clones a resource definition with all resources and volumes(including data)."
        )
        p_clone_rscdfn.add_argument('-e',
                                    '--external-name',
                                    type=str,
                                    help='User specified name.')
        p_clone_rscdfn.add_argument('--no-wait',
                                    action="store_true",
                                    help="Wait till cloning is done.")
        p_clone_rscdfn.add_argument(
            '--wait-timeout',
            type=int,
            help="Wait this seconds for the clone to finish.")
        p_clone_rscdfn.add_argument(
            '--use-zfs-clone',
            action="store_true",
            default=None,
            help=
            "Use ZFS clone instead send/recv, but have a dependent snapshot")
        p_clone_rscdfn.add_argument('source_resource',
                                    help="Source resource definition name"
                                    ).completer = self.resource_dfn_completer
        p_clone_rscdfn.add_argument(
            'clone_name',
            nargs="?",
            type=str,
            help='Name of the new resource definition. '
            'Will be ignored if EXTERNAL_NAME is set.')
        p_clone_rscdfn.set_defaults(func=self.clone)

        p_wait_sync = res_def_subp.add_parser(
            Commands.Subcommands.WaitSync.LONG,
            aliases=[Commands.Subcommands.WaitSync.SHORT],
            description=
            "Wait till the given resource is synced or e.g. ready to be resized."
        )
        p_wait_sync.add_argument(
            '--wait-timeout',
            type=int,
            help="Wait this seconds for the clone to finish.")
        p_wait_sync.add_argument("resource_name",
                                 help="Resource name to be checked."
                                 ).completer = self.resource_dfn_completer
        p_wait_sync.set_defaults(func=self.wait_sync)

        p_lrscdfs = res_def_subp.add_parser(
            Commands.Subcommands.List.LONG,
            aliases=[Commands.Subcommands.List.SHORT],
            description='Prints a list of all resource definitions known to '
            'linstor. By default, the list is printed as a human readable table.'
        )
        p_lrscdfs.add_argument('-p',
                               '--pastable',
                               action="store_true",
                               help='Generate pastable output')
        p_lrscdfs.add_argument(
            '-g',
            '--groupby',
            nargs='+',
            choices=rsc_dfn_groupby,
            type=str.lower).completer = rsc_dfn_group_completer
        p_lrscdfs.add_argument('-r',
                               '--resource-definitions',
                               nargs='+',
                               type=str,
                               help='Filter by list of resource definitions'
                               ).completer = self.resource_dfn_completer
        p_lrscdfs.add_argument('-e',
                               '--external-name',
                               action="store_true",
                               help='Show user specified name.')
        p_lrscdfs.add_argument('--props',
                               nargs='+',
                               type=str,
                               help='Filter list by object properties')
        p_lrscdfs.set_defaults(func=self.list)

        # show properties
        p_sp = res_def_subp.add_parser(
            Commands.Subcommands.ListProperties.LONG,
            aliases=[Commands.Subcommands.ListProperties.SHORT],
            description=
            "Prints all properties of the given resource definitions.")
        p_sp.add_argument('-p',
                          '--pastable',
                          action="store_true",
                          help='Generate pastable output')
        p_sp.add_argument(
            'resource_name',
            help="Resource definition for which to print the properties"
        ).completer = self.resource_dfn_completer
        p_sp.set_defaults(func=self.print_props)

        # set properties
        p_setprop = res_def_subp.add_parser(
            Commands.Subcommands.SetProperty.LONG,
            aliases=[Commands.Subcommands.SetProperty.SHORT],
            formatter_class=argparse.RawTextHelpFormatter,
            description='Sets properties for the given resource definition.')
        p_setprop.add_argument('name',
                               type=str,
                               help='Name of the resource definition')
        Commands.add_parser_keyvalue(p_setprop, 'resource-definition')
        p_setprop.set_defaults(func=self.set_props)

        # drbd options
        p_drbd_opts = res_def_subp.add_parser(
            Commands.Subcommands.DrbdOptions.LONG,
            aliases=[Commands.Subcommands.DrbdOptions.SHORT],
            description=DrbdOptions.description("resource"))
        p_drbd_opts.add_argument(
            'resource_name', type=str,
            help="Resource name").completer = self.resource_dfn_completer
        DrbdOptions.add_arguments(p_drbd_opts, self.OBJECT_NAME)
        p_drbd_opts.set_defaults(func=self.set_drbd_opts)

        self.check_subcommands(res_def_subp, subcmds)