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)
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
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)
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)
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
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)
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)