Ejemplo n.º 1
0
    def setup_commands(parser):
        # new-storpol definition
        p_new_storpool_dfn = parser.add_parser(
            'create-storage-pool-definition',
            aliases=['crtstorpooldfn'],
            description='Defines a Linstor storpool definition for use with linstor.')
        p_new_storpool_dfn.add_argument(
            'name',
            type=namecheck(STORPOOL_NAME),
            help='Name of the new storpool definition')
        p_new_storpool_dfn.set_defaults(func=StoragePoolDefinitionCommands.create)

        # modify-storpool

        # remove-storpool definition
        # TODO description
        p_rm_storpool_dfn = parser.add_parser(
            'delete-storage-pool-definition',
            aliases=['delstorpooldfn'],
            description=' Removes a storage pool definition ')
        p_rm_storpool_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_storpool_dfn.add_argument(
            'name',
            nargs="+",
            help='Name of the storage pool to delete').completer = StoragePoolDefinitionCommands.completer
        p_rm_storpool_dfn.set_defaults(func=StoragePoolDefinitionCommands.delete)

        # list storpool definitions
        storpooldfngroupby = ('Name')
        storpooldfn_group_completer = Commands.show_group_completer(storpooldfngroupby, "groupby")

        p_lstorpooldfs = parser.add_parser(
            'list-storage-pool-definitions',
            aliases=['list-storage-pool-definition', 'ls-storage-pool-dfn', 'display-storage-pool-definition',
                     'dspstorpooldfn'],
            description='Prints a list of all storage pool definitions known to '
            'linstor. By default, the list is printed as a human readable table.')
        p_lstorpooldfs.add_argument('-p', '--pastable', action="store_true", help='Generate pastable output')
        p_lstorpooldfs.add_argument('-g', '--groupby', nargs='+',
                                    choices=storpooldfngroupby).completer = storpooldfn_group_completer
        p_lstorpooldfs.add_argument(
            '-R', '--storpool', nargs='+', type=namecheck(STORPOOL_NAME),
            help='Filter by list of storage pool'
        ).completer = StoragePoolDefinitionCommands.completer
        p_lstorpooldfs.set_defaults(func=StoragePoolDefinitionCommands.list)

        # show properties
        p_sp = parser.add_parser(
            'get-storage-pool-definition-properties',
            aliases=['get-storage-pool-definition-props', 'dspstorpoolprp'],
            description="Prints all properties of the given storage pool definition.")
        p_sp.add_argument(
            'storage_pool_name',
            help="Storage pool definition for which to print the properties"
        ).completer = StoragePoolDefinitionCommands.completer
        p_sp.set_defaults(func=StoragePoolDefinitionCommands.print_props)
Ejemplo n.º 2
0
    def setup_commands(self, parser):
        sp = parser.add_parser('drbd-options',
                               description=DrbdOptions._options['help'])

        def mybool(x):
            return x.lower() in ('y', 'yes', 't', 'true', 'on')

        for opt in DrbdOptions._options:
            if opt == 'help':
                continue
            if DrbdOptions._options[opt]['type'] == 'handler':
                sp.add_argument('--' + opt,
                                choices=DrbdOptions._options[opt]['handlers'])
            if DrbdOptions._options[opt]['type'] == 'boolean':
                sp.add_argument('--' + opt,
                                type=mybool,
                                help="yes/no (Default: %s)" %
                                (DrbdOptions._options[opt]['default']))
            if DrbdOptions._options[opt]['type'] == 'string':
                sp.add_argument('--' + opt)
            if DrbdOptions._options[opt]['type'] == 'numeric':
                min_ = DrbdOptions._options[opt]['min']
                max_ = DrbdOptions._options[opt]['max']
                default = DrbdOptions._options[opt]['default']
                if "unit" in DrbdOptions._options[opt]:
                    unit = "; Unit: " + DrbdOptions._options[opt]['unit']
                else:
                    unit = ""
                # sp.add_argument('--' + opt, type=rangecheck(min_, max_),
                #                 default=default, help="Range: [%d, %d]; Default: %d" %(min_, max_, default))
                # setting a default sets the option to != None, which makes
                # filterNew relatively complex
                sp.add_argument('--' + opt,
                                type=rangecheck(min_, max_),
                                help="Range: [%d, %d]; Default: %d%s" %
                                (min_, max_, default, unit))
        for opt in DrbdOptions._options:
            if opt == 'help':
                continue
            else:
                sp.add_argument('--%s-%s' % (self.unsetprefix, opt),
                                action='store_true')

        sp.add_argument('--common', action="store_true")
        sp.add_argument('--resource',
                        type=namecheck(RES_NAME),
                        help='Name of the resource to modify'
                        ).completer = ResourceCommands.completer
        sp.add_argument('--volume', help='Name of the volume to modify'
                        ).completer = ResourceCommands.completer_volume
        sp.set_defaults(func=self._optioncommand)

        return sp
Ejemplo n.º 3
0
    def setup_commands(parser):
        # new-resource
        p_new_res = parser.add_parser(
            'create-resource',
            aliases=['crtrsc'],
            description='Defines a DRBD resource for use with linstor. '
            'Unless a specific IP port-number is supplied, the port-number is '
            'automatically selected by the linstor controller on the current node. '
        )
        p_new_res.add_argument(
            '-s',
            '--storage-pool',
            type=namecheck(STORPOOL_NAME),
            help="Storage pool name to use."
        ).completer = StoragePoolDefinitionCommands.completer
        p_new_res.add_argument('-d',
                               '--diskless',
                               action="store_true",
                               help='Should the resource be diskless')
        p_new_res.add_argument(
            'resource_name',
            type=namecheck(RES_NAME),
            help='Name of the resource definition'
        ).completer = ResourceDefinitionCommands.completer
        p_new_res.add_argument(
            'node_name',
            type=namecheck(NODE_NAME),
            help='Name of the new resource').completer = NodeCommands.completer
        p_new_res.set_defaults(func=ResourceCommands.create)

        # modify-resource
        p_mod_res_command = 'modify-resource'
        p_mod_res = parser.add_parser(p_mod_res_command,
                                      aliases=['mfyrsc', 'mr'],
                                      description='Modifies a DRBD resource.')
        p_mod_res.add_argument('-m',
                               '--managed',
                               choices=(BOOL_TRUE, BOOL_FALSE))
        p_mod_res.add_argument(
            'name', type=namecheck(RES_NAME),
            help='Name of the resource').completer = ResourceCommands.completer
        p_mod_res.set_defaults(func=Commands.cmd_enoimp)
        p_mod_res.set_defaults(command=p_mod_res_command)

        # remove-resource
        p_rm_res = parser.add_parser(
            'delete-resource',
            aliases=['delrsc'],
            description=
            ' Removes a resource and its associated 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.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('name', help='Name of the resource to delete'
                              ).completer = ResourceCommands.completer
        p_rm_res.add_argument(
            'node_name', nargs="+",
            help='Name of the node').completer = NodeCommands.completer
        p_rm_res.set_defaults(func=ResourceCommands.delete)

        resverbose = ('Port', )
        resgroupby = ('Name', 'Port', 'State')
        res_verbose_completer = Commands.show_group_completer(
            resverbose, "show")
        res_group_completer = Commands.show_group_completer(
            resgroupby, "groupby")

        p_lreses = parser.add_parser(
            'list-resources',
            aliases=['list-resource', 'ls-rsc', 'display-resources', 'dsprsc'],
            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(
            '-s', '--show', nargs='+',
            choices=resverbose).completer = res_verbose_completer
        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 = ResourceCommands.completer
        p_lreses.set_defaults(func=ResourceCommands.list)

        # list volumes
        p_lvlms = parser.add_parser(
            'list-volumes',
            aliases=['list-volume', 'ls-vlm', 'display-volumes', 'dspvlm'],
            description='Prints a list of all volumes.')
        p_lvlms.add_argument('-p',
                             '--pastable',
                             action="store_true",
                             help='Generate pastable output')
        p_lvlms.add_argument('resource', nargs='?')
        p_lvlms.set_defaults(func=ResourceCommands.list_volumes)

        # show properties
        p_sp = parser.add_parser(
            'get-resource-properties',
            aliases=['get-resource-props', 'dsprscprp'],
            description="Prints all properties of the given resource.")
        p_sp.add_argument('resource_name',
                          help="Resource for which to print the properties"
                          ).completer = ResourceCommands.completer
        p_sp.set_defaults(func=ResourceCommands.print_props)
Ejemplo n.º 4
0
    def setup_commands(parser):
        p_new_res_dfn = parser.add_parser(
            'create-resource-definition',
            aliases=['crtrscdfn'],
            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=ResourceDefinitionCommands.create)

        # remove-resource definition
        # TODO description
        p_rm_res_dfn = parser.add_parser(
            'delete-resource-definition',
            aliases=['delrscdfn'],
            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 = ResourceDefinitionCommands.completer
        p_rm_res_dfn.set_defaults(func=ResourceDefinitionCommands.delete)

        resverbose = ('Port', )
        resgroupby = ('Name', 'Port', 'State')
        res_verbose_completer = Commands.show_group_completer(
            resverbose, "show")
        res_group_completer = Commands.show_group_completer(
            resgroupby, "groupby")

        p_lrscdfs = parser.add_parser(
            'list-resource-definitions',
            aliases=[
                'list-resource-definition', 'dsprscdfn',
                'display-resource-definitions', 'resource-definitions',
                'dsprscdfn'
            ],
            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(
            '-s', '--show', nargs='+',
            choices=resverbose).completer = res_verbose_completer
        p_lrscdfs.add_argument(
            '-g', '--groupby', nargs='+',
            choices=resgroupby).completer = res_group_completer
        p_lrscdfs.add_argument(
            '-R',
            '--resources',
            nargs='+',
            type=namecheck(RES_NAME),
            help='Filter by list of resources'
        ).completer = ResourceDefinitionCommands.completer
        p_lrscdfs.set_defaults(func=ResourceDefinitionCommands.list)

        # show properties
        p_sp = parser.add_parser(
            'get-resource-definition-properties',
            aliases=['get-resource-definition-props', 'dsprscdfnprp'],
            description=
            "Prints all properties of the given resource definitions.")
        p_sp.add_argument(
            'resource_name',
            help="Resource definition for which to print the properties"
        ).completer = ResourceDefinitionCommands.completer
        p_sp.set_defaults(func=ResourceDefinitionCommands.print_props)
Ejemplo n.º 5
0
    def setup_parser(self):
        parser = argparse.ArgumentParser(prog="linstor")
        parser.add_argument('--version',
                            '-v',
                            action='version',
                            version='%(prog)s ' + VERSION + '; ' + GITHASH)
        parser.add_argument(
            '--no-color',
            action="store_true",
            help=
            'Do not use colors in output. Useful for old terminals/scripting.')
        parser.add_argument(
            '--no-utf8',
            action="store_true",
            help='Do not use utf-8 characters in output (i.e., tables).')
        parser.add_argument(
            '--warn-as-error',
            action="store_true",
            help='Treat WARN return code as error (i.e., return code > 0).')
        parser.add_argument(
            '--controllers',
            default='localhost:%d' % DFLT_CTRL_PORT_PLAIN,
            help=
            'Comma separated list of controllers (e.g.: "host1:port,host2:port"). '
            'If the environment variable %s is set, '
            'the ones set via this argument get appended.' %
            KEY_LS_CONTROLLERS)
        parser.add_argument('-m', '--machine-readable', action="store_true")
        parser.add_argument('-t',
                            '--timeout',
                            default=20,
                            type=int,
                            help="Connection timeout value.")
        parser.add_argument(
            '--disable-config',
            action="store_true",
            help="Disable config loading and only use commandline arguments.")

        subp = parser.add_subparsers(title='subcommands',
                                     description='valid subcommands',
                                     help='Use the list command to print a '
                                     'nicer looking overview of all valid '
                                     'commands')

        # interactive mode
        parser_ia = subp.add_parser('interactive',
                                    description='Start interactive mode')
        parser_ia.set_defaults(func=self.cmd_interactive)

        # help
        p_help = subp.add_parser('help',
                                 description='Print help for a command')
        p_help.add_argument('command')
        p_help.set_defaults(func=self.cmd_help)

        # list
        p_list = subp.add_parser('list',
                                 aliases=['commands', 'list-commands'],
                                 description='List available commands')
        p_list.set_defaults(func=self.cmd_list)

        # exit
        p_exit = subp.add_parser('exit',
                                 aliases=['quit'],
                                 description='Only useful in interactive mode')
        p_exit.set_defaults(func=self.cmd_exit)

        # poke
        p_poke = subp.add_parser('poke')
        p_poke.add_argument('-q', '--quiet', action="store_true")
        p_poke.set_defaults(func=self.cmd_enoimp)

        # type checkers (generate them only once)
        check_node_name = namecheck(NODE_NAME)
        check_res_name = namecheck(RES_NAME)
        check_snaps_name = namecheck(SNAPS_NAME)

        # Quorum control, completion of the action parameter
        quorum_completer_possible = ('ignore', 'unignore')

        def quorum_action_completer(prefix, **kwargs):
            possible = list(quorum_completer_possible)
            if prefix is not None and prefix != "":
                possible = [
                    item for item in possible if item.startswith(prefix)
                ]
            return possible

        p_quorum = subp.add_parser(
            "quorum-control",
            aliases=["qc"],
            description="Sets quorum parameters on linstor cluster nodes")
        p_quorum.add_argument(
            '-o',
            '--override',
            action="store_true",
            help="Override change protection in a partition without quorum")
        p_quorum.add_argument(
            "action",
            choices=quorum_completer_possible,
            help="The action to perform on the affected nodes"
        ).completer = quorum_action_completer
        p_quorum.add_argument("name",
                              nargs="+",
                              type=check_node_name,
                              help="Name of the affected node or nodes"
                              ).completer = NodeCommands.completer
        p_quorum.set_defaults(func=self.cmd_enoimp)

        # add all node commands
        NodeCommands.setup_commands(subp)

        # new-resource definition
        ResourceDefinitionCommands.setup_commands(subp)

        # add all resource commands
        ResourceCommands.setup_commands(subp)

        # add all storage pool definition commands
        StoragePoolDefinitionCommands.setup_commands(subp)

        # add all storage pools commands
        StoragePoolCommands.setup_commands(subp)

        # add all volume definition commands
        VolumeDefinitionCommands.setup_commands(subp)

        def vol_completer(prefix, parsed_args, **kwargs):
            server_rc, res_list = self.__list_resources(True)
            possible = set()
            for r in res_list:
                name, _, vol_list = r
                if name == parsed_args.name:
                    vol_list.sort(key=lambda vol_entry: vol_entry[0])
                    for v in vol_list:
                        vol_id, _ = v
                        possible.add(str(vol_id))

            return possible

        # resize-volume
        p_resize_vol_command = 'resize-volume'
        p_resize_vol = subp.add_parser(
            p_resize_vol_command,
            aliases=['resize'],
            description='Resizes a volume to the specified size, which must be '
            'greater than the current size of the volume.')
        p_resize_vol.add_argument(
            'name', type=check_res_name,
            help='Name of the resource').completer = ResourceCommands.completer
        p_resize_vol.add_argument('id', help='Volume ID',
                                  type=int).completer = vol_completer
        p_resize_vol.add_argument(
            'size',
            help='New size of the volume. '
            'The default unit for size is GiB (size * (2 ^ 30) bytes). '
            'Another unit can be specified by using an according postfix. '
            "linstor's internal granularity for the capacity of volumes is one "
            'Kibibyte (2 ^ 10 bytes). All other unit specifications are implicitly '
            'converted to Kibibyte, so that the actual size value used by linstor '
            'is the smallest natural number of Kibibytes that is large enough to '
            'accommodate a volume of the requested size in the specified size unit.'
        ).completer = VolumeDefinitionCommands.size_completer
        p_resize_vol.set_defaults(func=self.cmd_enoimp)
        p_resize_vol.set_defaults(command=p_resize_vol_command)

        # connect
        p_conn = subp.add_parser('connect-resource',
                                 description='Connect resource on node',
                                 aliases=['connect'])
        p_conn.add_argument(
            'resource',
            type=check_res_name).completer = ResourceCommands.completer
        p_conn.add_argument(
            'node', type=check_node_name).completer = NodeCommands.completer
        p_conn.set_defaults(func=self.cmd_enoimp)

        # reconnect
        p_reconn = subp.add_parser('reconnect-resource',
                                   description='Reconnect resource on node',
                                   aliases=['reconnect'])
        p_reconn.add_argument(
            'resource',
            type=check_res_name).completer = ResourceCommands.completer
        p_reconn.add_argument(
            'node', type=check_node_name).completer = NodeCommands.completer
        p_reconn.set_defaults(func=self.cmd_enoimp)

        # disconnect
        p_disconn = subp.add_parser('disconnect-resource',
                                    description='Disconnect resource on node',
                                    aliases=['disconnect'])
        p_disconn.add_argument(
            'resource',
            type=check_res_name).completer = ResourceCommands.completer
        p_disconn.add_argument(
            'node', type=check_node_name).completer = NodeCommands.completer
        p_disconn.set_defaults(func=self.cmd_enoimp)

        # flags
        p_flags = subp.add_parser('set-flags',
                                  description='Set flags of resource on node',
                                  aliases=['flags'])
        p_flags.add_argument(
            'resource', type=check_res_name,
            help='Name of the resource').completer = ResourceCommands.completer
        p_flags.add_argument(
            'node', type=check_node_name,
            help='Name of the node').completer = NodeCommands.completer
        p_flags.add_argument('--reconnect', choices=(0, 1), type=int)
        p_flags.add_argument('--updcon', choices=(0, 1), type=int)
        p_flags.add_argument('--overwrite', choices=(0, 1), type=int)
        p_flags.add_argument('--discard', choices=(0, 1), type=int)
        p_flags.set_defaults(func=self.cmd_enoimp)

        # free space
        def redundancy_type(r):
            r = int(r)
            if r < 1:
                raise argparse.ArgumentTypeError('Minimum redundancy is 1')
            return r

        p_fspace = subp.add_parser('list-free-space',
                                   description='Queries the maximum size of a'
                                   ' volume that could be deployed with the'
                                   ' specified level of redundancy',
                                   aliases=['free-space'])
        p_fspace.add_argument('-s',
                              '--site',
                              default='',
                              help="only consider nodes from this site")
        p_fspace.add_argument('redundancy',
                              type=redundancy_type,
                              help='Redundancy level (>=1)')
        p_fspace.set_defaults(func=self.cmd_enoimp)

        # deploy
        p_deploy = subp.add_parser(
            'deploy-resource',
            aliases=['deploy'],
            description='Deploys a resource on n automatically selected nodes '
            "of the linstor cluster. Using the information in linstor's data "
            'tables, the linstor server tries to find n nodes that have enough '
            'free storage capacity to deploy the resource resname.')
        p_deploy.add_argument(
            'resource',
            type=check_res_name).completer = ResourceCommands.completer
        p_deploy.add_argument('-i',
                              '--increase',
                              action="store_true",
                              help='Increase the redundancy count relative to'
                              ' the currently set value by a number of'
                              ' <redundancy_count>')
        p_deploy.add_argument('-d',
                              '--decrease',
                              action="store_true",
                              help='Decrease the redundancy count relative to'
                              ' the currently set value by a number of'
                              ' <redundancy_count>')
        p_deploy.add_argument('redundancy_count',
                              type=redundancy_type,
                              help='The redundancy count specifies the number'
                              ' of nodes to which the resource should be'
                              ' deployed. It must be at least 1 and at most'
                              ' the number of nodes in the cluster')
        p_deploy.add_argument('--with-clients', action="store_true")
        p_deploy.add_argument('-s',
                              '--site',
                              default='',
                              help="only consider nodes from this site")
        p_deploy.set_defaults(func=self.cmd_enoimp)

        # undeploy
        p_undeploy = subp.add_parser(
            'undeploy-resource',
            aliases=['undeploy'],
            description='Undeploys a resource from all nodes. The resource '
            "definition is still kept in linstor's data tables.")
        p_undeploy.add_argument('-q', '--quiet', action="store_true")
        p_undeploy.add_argument('-f', '--force', action="store_true")
        p_undeploy.add_argument(
            'resource',
            type=check_res_name).completer = ResourceCommands.completer
        p_undeploy.set_defaults(func=self.cmd_enoimp)

        # update-pool
        p_upool = subp.add_parser(
            'update-pool',
            description='Checks the storage pool total size and free space on '
            'the local node and updates the associated values in the data '
            'tables on the control volume.')
        p_upool.set_defaults(func=self.cmd_enoimp)

        # new-snapshot
        p_nsnap = subp.add_parser(
            'add-snapshot',
            aliases=['ns', 'create-snapshot', 'cs', 'new-snapshot', 'as'],
            description='Create a LVM snapshot')
        p_nsnap.add_argument('snapshot',
                             type=check_snaps_name,
                             help='Name of the snapshot')
        p_nsnap.add_argument(
            'resource', type=check_res_name,
            help='Name of the resource').completer = ResourceCommands.completer
        p_nsnap.add_argument('nodes',
                             type=check_node_name,
                             help='List of nodes',
                             nargs='+').completer = NodeCommands.completer
        p_nsnap.set_defaults(func=self.cmd_enoimp)

        # Snapshot commands:
        # These commands do not follow the usual option order:
        # For example remove-snapshot should have the snapshot name as first argument and the resource as
        # second argument. BUT: There are (potentially) more snapshots than resources, so specifying the
        # resource first and then completing only the snapshots for that resource makes more sense.

        # remove-snapshot
        def snaps_completer(prefix, parsed_args, **kwargs):
            server_rc, res_list = self._list_snapshots()
            possible = set()
            for r in res_list:
                res_name, snaps_list = r
                if res_name == parsed_args.resource:
                    for s in snaps_list:
                        snaps_name, _ = s
                        possible.add(snaps_name)

            return possible

        p_rmsnap = subp.add_parser(
            'remove-snapshot',
            aliases=['delete-snapshot', 'ds'],
            description='Remove LVM snapshot of a resource')
        p_rmsnap.add_argument('-f', '--force', action="store_true")
        p_rmsnap.add_argument(
            'resource', type=check_res_name,
            help='Name of the resource').completer = ResourceCommands.completer
        p_rmsnap.add_argument(
            'snapshot',
            type=check_snaps_name,
            nargs="+",
            help='Name of the snapshot').completer = snaps_completer
        p_rmsnap.set_defaults(func=self.cmd_enoimp)

        # remove-snapshot-assignment
        p_rmsnapas = subp.add_parser(
            'remove-snapshot-assignment',
            aliases=['rsa', 'delete-snapshot-assignment', 'dsa'],
            description='Remove snapshot assignment')
        p_rmsnapas.add_argument('-f', '--force', action="store_true")
        p_rmsnapas.add_argument(
            'resource', type=check_res_name,
            help='Name of the resource').completer = ResourceCommands.completer
        p_rmsnapas.add_argument(
            'snapshot', type=check_snaps_name,
            help='Name of the snapshot').completer = snaps_completer
        p_rmsnapas.add_argument(
            'node', type=check_node_name,
            help='Name of the node').completer = NodeCommands.completer
        p_rmsnapas.set_defaults(func=self.cmd_enoimp)

        # restore-snapshot
        p_restsnap = subp.add_parser('restore-snapshot',
                                     aliases=['rs'],
                                     description='Restore snapshot')
        p_restsnap.add_argument(
            'resource',
            type=check_res_name,
            help=
            'Name of the new resource that gets created from existing snapshot'
        )
        p_restsnap.add_argument('snapshot_resource',
                                type=check_res_name,
                                help='Name of the resource that was snapshoted'
                                ).completer = ResourceCommands.completer
        p_restsnap.add_argument(
            'snapshot', type=check_snaps_name,
            help='Name of the snapshot').completer = snaps_completer
        p_restsnap.set_defaults(func=self.cmd_enoimp)

        # resume-all
        p_resume_all = subp.add_parser(
            'resume-all', description="Resumes all failed assignments")
        p_resume_all.set_defaults(func=self.cmd_enoimp)

        def shutdown_restart(command, description, func, aliases=False):
            if aliases:
                p_cmd = subp.add_parser(command,
                                        aliases=aliases,
                                        description=description)
            else:
                p_cmd = subp.add_parser(command, description=description)
            p_cmd.add_argument(
                '-l',
                '--satellite',
                action="store_true",
                help=
                'If given, also send a shutdown command to connected satellites.',
                default=False)
            p_cmd.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_cmd.add_argument(
                '-r',
                '--resources',
                action="store_true",
                help='Shutdown all linstor-controlled resources too',
                default=False)
            p_cmd.add_argument('-c',
                               '--ctrlvol',
                               action="store_true",
                               help='Do not drbdadm down the control volume',
                               default=False)
            p_cmd.set_defaults(func=func)

        # shutdown
        shutdown_restart('shutdown',
                         description='Stops the local linstor server process.',
                         func=self.cmd_enoimp)
        # restart
        shutdown_restart(
            'restart',
            description='Restarts the local linstor server process.',
            func=self.cmd_enoimp)

        # snapshots
        snapgroupby = ("Resource", "Name", "State")
        snap_group_completer = Commands.show_group_completer(
            snapgroupby, "groupby")

        p_lsnaps = subp.add_parser('list-snapshots',
                                   aliases=['s', 'snapshots'],
                                   description='List available snapshots')
        p_lsnaps.add_argument('-p',
                              '--pastable',
                              action="store_true",
                              help='Generate pastable output')
        p_lsnaps.add_argument(
            '-g', '--groupby', nargs='+',
            choices=snapgroupby).completer = snap_group_completer
        p_lsnaps.add_argument('-R',
                              '--resources',
                              nargs='+',
                              type=check_res_name,
                              help='Filter by list of resources'
                              ).completer = ResourceCommands.completer
        p_lsnaps.set_defaults(func=self.cmd_enoimp)

        # snapshot-assignments
        snapasgroupby = ("Resource", "Name", "Node", "State")

        snapas_group_completer = Commands.show_group_completer(
            snapasgroupby, "groupby")

        p_lsnapas = subp.add_parser('list-snapshot-assignments',
                                    aliases=['sa', 'snapshot-assignments'],
                                    description='List snapshot assignments')
        p_lsnapas.add_argument('-p',
                               '--pastable',
                               action="store_true",
                               help='Generate pastable output')
        p_lsnapas.add_argument(
            '-g', '--groupby', nargs='+',
            choices=snapasgroupby).completer = snapas_group_completer
        p_lsnapas.add_argument(
            '-N',
            '--nodes',
            nargs='+',
            type=check_node_name,
            help='Filter by list of nodes').completer = NodeCommands.completer
        p_lsnapas.add_argument('-R',
                               '--resources',
                               nargs='+',
                               type=check_res_name,
                               help='Filter by list of resources'
                               ).completer = ResourceCommands.completer
        p_lsnapas.set_defaults(func=self.cmd_enoimp)

        # export
        def exportnamecheck(name):
            if name == '*':
                return name
            return check_res_name(name)

        p_export = subp.add_parser(
            'export-res',
            aliases=['export'],
            description='Exports the configuration files of the specified '
            'linstor resource for use with drbdadm. If "*" is used as '
            'resource name, the configuration files of all linstor resources '
            'deployed on the local node are exported. The configuration files will '
            'be created (or updated) in the linstor directory for temporary '
            'configuration files, typically /var/lib/drbd.d.')
        p_export.add_argument(
            'resource',
            nargs="+",
            type=exportnamecheck,
            help='Name of the resource').completer = ResourceCommands.completer
        p_export.set_defaults(func=self.cmd_enoimp)

        # free-port-nr
        p_free_port_nr = subp.add_parser(
            'free-port-nr',
            description='Find an unallocated TCP/IP port number')
        p_free_port_nr.set_defaults(func=self.cmd_enoimp)

        # free-minor-nr
        p_free_minor_nr = subp.add_parser(
            'free-minor-nr', description='Find an unallocated minor number')
        p_free_minor_nr.set_defaults(func=self.cmd_enoimp)

        # query-port-nr
        p_query_port_nr = subp.add_parser(
            'query-port-nr',
            description='Query the allocation status of a TCP/IP port number')
        p_query_port_nr.add_argument('port', help='TCP/IP port number')
        p_query_port_nr.set_defaults(func=self.cmd_enoimp)

        # query-minor-nr
        p_query_minor_nr = subp.add_parser(
            'query-minor-nr',
            description='Query the allocation status of a minor number')
        p_query_minor_nr.add_argument('minor', help='Device file minor number')
        p_query_minor_nr.set_defaults(func=self.cmd_enoimp)

        # server-version
        p_server_version = subp.add_parser(
            'server-version',
            description='Queries version information from the linstor server')
        p_server_version.set_defaults(func=self.cmd_enoimp)

        # message-log
        p_message_log = subp.add_parser(
            'list-message-log',
            aliases=['message-log', 'list-ml', 'ml'],
            description='Queries the server\'s message log')
        p_message_log.set_defaults(func=self.cmd_enoimp)

        # clear-message-log
        p_message_log = subp.add_parser(
            'clear-message-log',
            aliases=['clear-ml', 'cml'],
            description='Queries the server\'s message log')
        p_message_log.set_defaults(func=self.cmd_enoimp)

        # query-conf
        p_queryconf = subp.add_parser('query-conf',
                                      description='Print the DRBD'
                                      ' configuration file for a given'
                                      ' resource on a given node')
        p_queryconf.add_argument(
            'node', type=check_node_name,
            help='Name of the node').completer = NodeCommands.completer
        p_queryconf.add_argument(
            'resource', type=check_res_name,
            help='Name of the resource').completer = ResourceCommands.completer
        p_queryconf.set_defaults(func=self.cmd_enoimp)

        # ping
        p_ping = subp.add_parser('ping',
                                 description='Pings the server. The '
                                 'server should answer with a "Pong"')
        p_ping.set_defaults(func=self.cmd_ping)

        # initcv
        p_join = subp.add_parser('initcv',
                                 description='Initialize control volume')
        p_join.add_argument('-q', '--quiet', action="store_true")
        p_join.add_argument('dev', help='Path to the control volume')
        p_join.set_defaults(func=self.cmd_enoimp)

        # debug
        p_debug = subp.add_parser('debug')
        p_debug.add_argument('cmd')
        p_debug.set_defaults(func=self.cmd_enoimp)

        # drbd options
        drbd_options = DrbdOptions()
        drbd_options.setup_commands(subp)

        # handlers
        # currently we do not parse the xml-output because drbd-utils are not ready for it
        # number and handler names are very static, so use a list for now and add this feature to
        # drbd-utils later
        handlers = (
            'after-resync-target',
            'before-resync-target',
            'fence-peer',
            'initial-split-brain',
            'local-io-error',
            'pri-lost',
            'pri-lost-after-sb',
            'pri-on-incon-degr',
            'split-brain',
        )
        p_handlers = subp.add_parser(
            'handlers', description='Set or unset event handlers.')
        p_handlers.add_argument('--common', action="store_true")
        p_handlers.add_argument('--resource',
                                type=check_res_name,
                                help='Name of the resource to modify'
                                ).completer = ResourceCommands.completer
        for handler in handlers:
            p_handlers.add_argument('--' + handler,
                                    help='Please refer to drbd.conf(5)',
                                    metavar='cmd')
            p_handlers.add_argument('--unset-' + handler, action='store_true')
        p_handlers.set_defaults(func=self.cmd_enoimp)

        # list-options
        p_listopts = subp.add_parser('list-options',
                                     description='List drbd options set',
                                     aliases=['show-options'])
        p_listopts.add_argument('resource',
                                type=check_res_name,
                                help='Name of the resource to show'
                                ).completer = ResourceCommands.completer
        p_listopts.set_defaults(func=self.cmd_enoimp)
        # p_listopts.set_defaults(doobj=do)
        # p_listopts.set_defaults(noobj=no)
        # p_listopts.set_defaults(roobj=ro)
        # p_listopts.set_defaults(pdoobj=pdo)

        # edit config
        p_editconf = subp.add_parser(
            'modify-config',
            description='Modify linstor configuration',
            aliases=['edit-config'])
        p_editconf.add_argument(
            '--node',
            '-n',
            type=check_node_name,
            help='Name of the node. This enables node specific options '
            '(e.g. plugin settings)').completer = NodeCommands.completer
        p_editconf.set_defaults(func=self.cmd_enoimp)
        p_editconf.set_defaults(type="edit")

        # export config
        p_exportconf = subp.add_parser(
            'export-config',
            description='Export linstor configuration',
            aliases=['cat-config'])
        p_exportconf.add_argument(
            '--node', '-n', type=check_node_name,
            help='Name of the node.').completer = NodeCommands.completer
        p_exportconf.add_argument('--file',
                                  '-f',
                                  help='File to save configuration')
        p_exportconf.set_defaults(func=self.cmd_enoimp)
        p_exportconf.set_defaults(type="export")

        # export ctrl-vol
        p_exportctrlvol = subp.add_parser(
            'export-ctrlvol',
            description='Export linstor control volume as json blob')
        p_exportctrlvol.add_argument(
            '--file',
            '-f',
            help='File to save configuration json blob, if not given: stdout')
        p_exportctrlvol.set_defaults(func=self.cmd_enoimp)

        # import ctrl-vol
        p_importctrlvol = subp.add_parser(
            'import-ctrlvol',
            description='Import linstor control volume from json blob')
        p_importctrlvol.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_importctrlvol.add_argument(
            '--file',
            '-f',
            help='File to load configuration json blob, if not given: stdin')
        p_importctrlvol.set_defaults(func=self.cmd_enoimp)

        # role
        p_role = subp.add_parser(
            'role',
            description=
            'Show role of local linstor (controlnode/satellite/unknown)')
        p_role.set_defaults(func=self.cmd_enoimp)

        # reelect
        p_reelect = subp.add_parser(
            'reelect',
            description='Reelect leader. DO NOT USE this command '
            'if you do not understand all implications!')
        p_reelect.add_argument(
            '--force-win',
            action='store_true',
            help='This is a last resort command to bring up a single leader '
            'in order to get access to the control volume (e.g. remove node '
            'in 2 node cluster)')
        p_reelect.set_defaults(func=self.cmd_enoimp)

        argcomplete.autocomplete(parser)

        return parser
Ejemplo n.º 6
0
    def setup_commands(parser):
        p_new_vol_command = 'create-volume-definition'
        p_new_vol = parser.add_parser(
            p_new_vol_command,
            aliases=['crtvlmdfn'],
            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('-m', '--minor', type=int)
        p_new_vol.add_argument('-d', '--deploy', type=int)
        p_new_vol.add_argument('-s',
                               '--site',
                               default='',
                               help="only consider nodes from this site")
        p_new_vol.add_argument(
            'resource_name',
            type=namecheck(RES_NAME),
            help='Name of an existing resource'
        ).completer = ResourceDefinitionCommands.completer
        p_new_vol.add_argument(
            'size',
            help='Size of the volume in resource. '
            'The default unit for size is GiB (size * (2 ^ 30) bytes). '
            'Another unit can be specified by using an according postfix. '
            "Linstor's internal granularity for the capacity of volumes is one "
            'Kibibyte (2 ^ 10 bytes). All other unit specifications are implicitly '
            'converted to Kibibyte, so that the actual size value used by linstor '
            'is the smallest natural number of Kibibytes that is large enough to '
            'accommodate a volume of the requested size in the specified size unit.'
        ).completer = VolumeDefinitionCommands.size_completer
        p_new_vol.set_defaults(func=VolumeDefinitionCommands.create)
        p_new_vol.set_defaults(command=p_new_vol_command)

        # remove-volume definition
        p_rm_vol = parser.add_parser(
            'delete-volume-definition',
            aliases=['delvlmdfn'],
            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 = ResourceDefinitionCommands.completer
        p_rm_vol.add_argument('volume_nr',
                              type=int,
                              help="Volume number to delete.")
        p_rm_vol.set_defaults(func=VolumeDefinitionCommands.delete)

        # list volume definitions
        resgroupby = ()
        volgroupby = resgroupby + ('Vol_ID', 'Size', 'Minor')
        vol_group_completer = Commands.show_group_completer(
            volgroupby, 'groupby')

        p_lvols = parser.add_parser(
            'list-volume-definitions',
            aliases=[
                'list-volume-definition', 'dspvlmdfn',
                'display-volume-definitions', 'volume-definitions', 'dspvlmdfn'
            ],
            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=volgroupby).completer = vol_group_completer
        p_lvols.add_argument('-R',
                             '--resources',
                             nargs='+',
                             type=namecheck(RES_NAME),
                             help='Filter by list of resources'
                             ).completer = ResourceDefinitionCommands.completer
        p_lvols.set_defaults(func=VolumeDefinitionCommands.list)
Ejemplo n.º 7
0
    def setup_commands(parser):
        # create node
        p_new_node = parser.add_parser(
            'create-node',
            aliases=['crtnode'],
            description=
            'Creates a node entry for a node that participates in the '
            'linstor cluster.')
        p_new_node.add_argument(
            '-p',
            '--port',
            type=rangecheck(1, 65535),
            help='default: Satellite %s for %s; Controller %s for %s; %s for %s'
            %
            (DFLT_STLT_PORT_PLAIN, VAL_NETCOM_TYPE_PLAIN, DFLT_CTRL_PORT_PLAIN,
             VAL_NETCOM_TYPE_PLAIN, DFLT_CTRL_PORT_SSL, VAL_NETCOM_TYPE_SSL))
        ntype_def = VAL_NODE_TYPE_STLT
        p_new_node.add_argument('--node-type',
                                choices=(VAL_NODE_TYPE_CTRL, VAL_NODE_TYPE_AUX,
                                         VAL_NODE_TYPE_CMBD,
                                         VAL_NODE_TYPE_STLT),
                                default=VAL_NODE_TYPE_STLT,
                                help='Node type (default: %s)' % (ntype_def))
        ctype_def = VAL_NETCOM_TYPE_PLAIN
        p_new_node.add_argument(
            '--communication-type',
            choices=(VAL_NETCOM_TYPE_PLAIN, VAL_NETCOM_TYPE_SSL),
            default=ctype_def,
            help='Communication type (default: %s)' % (ctype_def))
        itype_def = VAL_NETIF_TYPE_IP
        p_new_node.add_argument('--interface-type',
                                choices=(VAL_NETIF_TYPE_IP, ),
                                default=itype_def,
                                help='Interface type (default: %s)' %
                                (itype_def))
        iname_def = 'default'
        p_new_node.add_argument('--interface-name',
                                default=iname_def,
                                help='Interface name (default: %s)' %
                                (iname_def))
        p_new_node.add_argument(
            'name',
            help='Name of the new node, must match the nodes hostname',
            type=namecheck(NODE_NAME))
        p_new_node.add_argument(
            'ip',
            help='IP address of the new node').completer = ip_completer("name")
        p_new_node.set_defaults(func=NodeCommands.create)

        # modify-node
        p_mod_node_command = 'modify-node'
        p_mod_node = parser.add_parser(p_mod_node_command,
                                       aliases=['mfynode', 'mn'],
                                       description='Modifies a linstor node.')
        p_mod_node.add_argument('-a',
                                '--address-family',
                                metavar="FAMILY",
                                choices=['ipv4', 'ipv6'],
                                help='FAMILY: "ipv4" (default) or "ipv6"')
        p_mod_node.add_argument('-s', '--storage')
        p_mod_node.add_argument(
            'name', type=namecheck(NODE_NAME),
            help='Name of the node').completer = NodeCommands.completer
        p_mod_node.add_argument(
            '--address',
            help='Network address of the node').completer = ip_completer(
                "name")
        p_mod_node.set_defaults(func=Commands.cmd_enoimp)
        p_mod_node.set_defaults(command=NodeCommands.modify)

        # remove-node
        p_rm_node = parser.add_parser(
            'delete-node',
            aliases=['delnode'],
            description='Removes a node from the linstor cluster. '
            'All linstor resources that are still deployed on the specified '
            'node are marked for undeployment, and the node entry is marked for '
            "removal from linstor's data tables. The specified node is "
            'expected to undeploy all resources. As soon as all resources have been '
            'undeployed from the node, the node entry is removed from '
            "linstor's data tables.")
        p_rm_node.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_node.add_argument('name', help='Name of the node to remove'
                               ).completer = NodeCommands.completer
        p_rm_node.set_defaults(func=NodeCommands.delete)

        # list nodes
        nodesverbose = ('Family', 'IP', 'Site')
        nodesgroupby = ('Name', 'Pool_Size', 'Pool_Free', 'Family', 'IP',
                        'State')

        nodes_verbose_completer = Commands.show_group_completer(
            nodesverbose, "show")
        nodes_group_completer = Commands.show_group_completer(
            nodesgroupby, "groupby")
        p_lnodes = parser.add_parser(
            'list-nodes',
            aliases=['list-node', 'ls-nodes', 'display-nodes', 'dspnode'],
            description='Prints a list of all cluster nodes known to linstor. '
            'By default, the list is printed as a human readable table.')
        p_lnodes.add_argument('-p',
                              '--pastable',
                              action="store_true",
                              help='Generate pastable output')
        p_lnodes.add_argument(
            '-s', '--show', nargs='+',
            choices=nodesverbose).completer = nodes_verbose_completer
        p_lnodes.add_argument(
            '-g', '--groupby', nargs='+',
            choices=nodesgroupby).completer = nodes_group_completer
        p_lnodes.add_argument(
            '-N',
            '--nodes',
            nargs='+',
            type=namecheck(NODE_NAME),
            help='Filter by list of nodes').completer = NodeCommands.completer
        p_lnodes.set_defaults(func=NodeCommands.list)

        # show properties
        p_sp = parser.add_parser(
            'get-node-properties',
            aliases=['get-node-props', 'dspnodeprp'],
            description="Prints all properties of the given node.")
        p_sp.add_argument('node_name',
                          help="Node for which to print the properties"
                          ).completer = NodeCommands.completer
        p_sp.set_defaults(func=NodeCommands.print_props)