def print_props(cc, args): lstmsg = Commands._request_list(cc, API_LST_NODE, MsgLstNode()) if lstmsg: for n in lstmsg.nodes: if n.name == args.node_name: Commands._print_props(n.props) break return None
def print_props(cc, args): lstmsg = Commands._request_list(cc, API_LST_STOR_POOL, MsgLstStorPool()) if lstmsg: for stp in lstmsg.stor_pools: if stp.stor_pool_name == args.storage_pool_name: Commands._print_props(stp.props) break return None
def print_props(cc, args): lstmsg = Commands._request_list(cc, API_LST_RSC_DFN, MsgLstRscDfn()) if lstmsg: for rsc_dfn in lstmsg.rsc_dfns: if rsc_dfn.rsc_name == args.resource_name: Commands._print_props(rsc_dfn.rsc_dfn_props) break return None
def print_props(cc, args): lstmsg = Commands._request_list(cc, API_LST_RSC, MsgLstRsc()) if lstmsg: for rsc in lstmsg.resources: if rsc.name == args.resource_name: Commands._print_props(rsc.props) break return None
def list(cc, args): lstmsg = Commands._get_list_message(cc, API_LST_RSC, MsgLstRsc(), args) if lstmsg: rsc_dfns = Commands._get_list_message(cc, API_LST_RSC_DFN, MsgLstRscDfn(), args).rsc_dfns rsc_dfn_map = {x.rsc_name: x for x in rsc_dfns} stor_pools = Commands._get_list_message(cc, API_LST_STOR_POOL, MsgLstStorPool(), args).stor_pools stor_pool_map = {x.stor_pool_name: x for x in stor_pools} tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) tbl.add_column("ResourceName") tbl.add_column("Node") tbl.add_column("Port") tbl.add_column("Device", color=Output.color(Color.DARKGREEN, args.no_color)) tbl.add_column("State", color=Output.color(Color.DARKGREEN, args.no_color), just_txt='>') for rsc in lstmsg.resources: rsc_dfn = rsc_dfn_map[rsc.name] diskless = FLAG_DISKLESS in rsc.rsc_flags if not diskless: storage_pool_name = Commands._get_prop( rsc.props, KEY_STOR_POOL_NAME) storage_pool = stor_pool_map[storage_pool_name] driver_key = StoragePoolCommands.get_driver_key( storage_pool.driver) block_device = Commands._get_prop(storage_pool.props, driver_key) # print(storage_pool) marked_delete = FLAG_DELETE in rsc.rsc_flags # rsc_state = ResourceCommands.find_rsc_state(lstmsg.resource_states, rsc.name, rsc.node_name) tbl.add_row([ rsc.name, rsc.node_name, rsc_dfn.rsc_dfn_port, tbl.color_cell("DISKLESS", Color.GREEN) if diskless else block_device, tbl.color_cell("DELETING", Color.RED) if marked_delete else "ok" ]) tbl.show() return None
def list(cc, args): lstmsg = Commands._get_list_message(cc, API_LST_NODE, MsgLstNode(), args) if lstmsg: tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) tbl.add_column("Node") tbl.add_column("NodeType") tbl.add_column("IPs") tbl.add_column("State", color=Output.color(Color.DARKGREEN, args.no_color)) for n in lstmsg.nodes: ips = [if_.address for if_ in n.net_interfaces] tbl.add_row([ n.name, n.type, ",".join(ips), tbl.color_cell("ok", Color.DARKGREEN) if n.connected else tbl.color_cell("OFFLINE", Color.RED) ]) tbl.show() # prntfrm = "{node:<20s} {type:<10s} {uuid:<40s}" # print(prntfrm.format(node="Node", type="NodeType", uuid="UUID")) # netiffrm = " + {name:<20s} {address:>20s}" # for n in lstmsg.nodes: # print(prntfrm.format(node=n.name, type=n.type, uuid=n.uuid)) # for interface in n.net_interfaces: # print(netiffrm.format( # name=interface.name, # address=interface.address)) return None
def list(cc, args): lstmsg = Commands._get_list_message(cc, API_LST_RSC_DFN, MsgLstRscDfn(), args) if lstmsg: tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) tbl.add_column("ResourceName") tbl.add_column("Port") tbl.add_column("State", color=Output.color(Color.DARKGREEN, args.no_color)) for rsc_dfn in lstmsg.rsc_dfns: tbl.add_row([ rsc_dfn.rsc_name, rsc_dfn.rsc_dfn_port, tbl.color_cell("DELETING", Color.RED) if FLAG_DELETE in rsc_dfn.rsc_dfn_flags else tbl.color_cell( "ok", Color.DARKGREEN) ]) tbl.show() # prntfrm = "{rsc:<20s} {port:<10s} {uuid:<40s}" # print(prntfrm.format(rsc="Resource-name", port="Port", uuid="UUID")) # for rsc_dfn in lstmsg.rsc_dfns: # print(prntfrm.format(rsc=rsc_dfn.rsc_name, # port=str(rsc_dfn.rsc_dfn_port), uuid=rsc_dfn.rsc_dfn_uuid)) return None
def delete(cc, args): del_msgs = [] p = MsgDelNode() p.node_name = args.name del_msgs.append(p) return Commands._delete_and_output(cc, args, API_DEL_NODE, del_msgs)
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 create(cc, args): p = MsgCrtRscDfn() p.rsc_dfn.rsc_name = args.name if args.port: p.rsc_dfn.rsc_dfn_port = args.port # if args.secret: # p.secret = args.secret return Commands._create(cc, API_CRT_RSC_DFN, p, args)
def delete(cc, args): del_msgs = [] for rsc_name in args.name: p = MsgDelRscDfn() p.rsc_name = rsc_name del_msgs.append(p) return Commands._delete_and_output(cc, args, API_DEL_RSC_DFN, del_msgs)
def delete(cc, args): del_msgs = [] for storpool_name in args.name: p = MsgDelStorPoolDfn() p.stor_pool_name = storpool_name del_msgs.append(p) return Commands._delete_and_output(cc, args, API_DEL_STOR_POOL_DFN, del_msgs)
def delete(cc, args): del_msgs = [] for node_name in args.node_name: p = MsgDelStorPool() p.stor_pool_name = args.name p.node_name = node_name del_msgs.append(p) return Commands._delete_and_output(cc, args, API_DEL_STOR_POOL, del_msgs)
def create(cc, args): p = MsgCrtVlmDfn() p.rsc_name = args.resource_name vlmdf = p.vlm_dfns.add() vlmdf.vlm_size = VolumeDefinitionCommands._get_volume_size(args.size) if args.minor is not None: vlmdf.vlm_minor = args.minor return Commands._create(cc, API_CRT_VLM_DFN, p, args)
def delete(cc, args): del_msgs = [] for node_name in args.node_name: p = MsgDelRsc() p.rsc_name = args.name p.node_name = node_name del_msgs.append(p) return Commands._delete_and_output(cc, args, API_DEL_RSC, del_msgs)
def completer(cc, prefix, **kwargs): possible = set() lstmsg = Commands._get_list_message(cc, API_LST_NODE, MsgLstNode()) if lstmsg: for node in lstmsg.nodes: possible.add(node.name) if prefix: return [node for node in possible if node.startswith(prefix)] return possible
def completer(cc, prefix, **kwargs): possible = set() lstmsg = Commands._get_list_message(cc, API_LST_STOR_POOL, MsgLstStorPool()) if lstmsg: for storpool in lstmsg.resources: possible.add(storpool.stor_pool_name) if prefix: return [res for res in possible if res.startswith(prefix)] return possible
def completer(cc, prefix, **kwargs): possible = set() lstmsg = Commands._get_list_message(cc, API_LST_RSC, MsgLstRsc()) if lstmsg: for rsc in lstmsg.resources: possible.add(rsc.name) if prefix: return [res for res in possible if res.startswith(prefix)] return possible
def create(cc, args): p = MsgCrtRsc() p.rsc.name = args.resource_name p.rsc.node_name = args.node_name if not args.diskless and args.storage_pool: prop = LinStorMapEntry() prop.key = KEY_STOR_POOL_NAME prop.value = args.storage_pool p.rsc.props.extend([prop]) if args.diskless: p.rsc.rsc_flags.append(FLAG_DISKLESS) return Commands._create(cc, API_CRT_RSC, p, args)
def list_volumes(cc, args): lstmsg = Commands._get_list_message(cc, API_LST_RSC, MsgLstRsc(), args) # type: MsgLstRsc if lstmsg: tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) tbl.add_column("Node") tbl.add_column("Resource") tbl.add_column("VolumeNr") tbl.add_column("MinorNr") tbl.add_column("State", color=Output.color(Color.DARKGREEN, args.no_color), just_txt='>') for rsc in lstmsg.resources: rsc_state = ResourceCommands.get_resource_state( lstmsg.resource_states, rsc.node_name, rsc.name) for vlm in rsc.vlms: if rsc_state: vlm_state = ResourceCommands.get_volume_state( rsc_state.vlm_states, vlm.vlm_nr) else: vlm_state = None state = tbl.color_cell("unknown", Color.YELLOW) if vlm_state: state = "ok" problems = [] if not vlm_state.is_present: problems.append("not present") if vlm_state.disk_failed: problems.append("disk failed") if problems: state = tbl.color_cell(", ".join(problems), Color.RED) tbl.add_row([ rsc.node_name, rsc.name, str(vlm.vlm_nr), str(vlm.vlm_minor_nr), state ]) tbl.show() return None
def list(cc, args): lstmsg = Commands._get_list_message(cc, API_LST_STOR_POOL_DFN, MsgLstStorPoolDfn(), args) if lstmsg: tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) tbl.add_column("StoragePool") for storpool_dfn in lstmsg.stor_pool_dfns: tbl.add_row([ storpool_dfn.stor_pool_name ]) tbl.show() # prntfrm = "{storpool:<20s} {uuid:<40s}" # print(prntfrm.format(storpool="StorpoolDfn-name", uuid="UUID")) # for storpool_dfn in lstmsg.stor_pool_dfns: # print(prntfrm.format(storpool=storpool_dfn.stor_pool_name, uuid=storpool_dfn.uuid)) return None
def create(cc, args): p = MsgCrtStorPool() p.stor_pool.stor_pool_name = args.name p.stor_pool.node_name = args.node_name # construct correct driver name if args.driver == 'lvmthin': driver = 'LvmThin' else: driver = args.driver.title() p.stor_pool.driver = '{driver}Driver'.format(driver=driver) # set driver device pool property prop = p.stor_pool.props.add() prop.key = StoragePoolCommands.device_key_map[driver] prop.value = args.driver_device return Commands._create(cc, API_CRT_STOR_POOL, p, args)
def list(cc, args): lstmsg = Commands._get_list_message(cc, API_LST_RSC_DFN, MsgLstRscDfn(), args) if lstmsg: tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) tbl.add_column("ResourceName") tbl.add_column("VolumeNr") tbl.add_column("VolumeMinor") tbl.add_column("Size") tbl.add_column("State", color=Output.color(Color.DARKGREEN, args.no_color)) for rsc_dfn in lstmsg.rsc_dfns: for vlmdfn in rsc_dfn.vlm_dfns: tbl.add_row([ rsc_dfn.rsc_name, vlmdfn.vlm_nr, vlmdfn.vlm_minor, approximate_size_string(vlmdfn.vlm_size), tbl.color_cell("DELETING", Color.RED) if FLAG_DELETE in rsc_dfn.rsc_dfn_flags else tbl.color_cell( "ok", Color.DARKGREEN) ]) tbl.show() # prntfrm = "{res:<15s} {uuid:<40s} {vlmnr:<5s} {vlmminor:<10s} {vlmsize:<10s}" # print(prntfrm.format(res="Resource", uuid="UUID", vlmnr="VlmNr", vlmminor="VlmMinor", vlmsize="Size")) # prntfrm = "{res:<15s} {uuid:<40s} {vlmnr:<5d} {vlmminor:<10d} {vlmsize:<20s}" # for rscdfn in lstmsg.rsc_dfns: # for vlmdfn in rscdfn.vlm_dfns: # print(prntfrm.format( # res=rscdfn.rsc_name, # uuid=vlmdfn.vlm_dfn_uuid, # vlmnr=vlmdfn.vlm_nr, # vlmminor=vlmdfn.vlm_minor, # vlmsize=approximate_size_string(vlmdfn.vlm_size))) return None
def create(cc, args): p = MsgCrtNode() def gen_nif(k, v): prop = LinStorMapEntry() prop.key = "%s/%s/%s" % (NAMESPC_NETIF, args.interface_name, k) prop.value = v p.node.props.extend([prop]) # interface gen_nif(KEY_NETIF_TYPE, args.interface_type) gen_nif(KEY_NETCOM_TYPE, args.communication_type) p.node.name = args.name p.node.type = args.node_type netif = p.node.net_interfaces.add() netif.name = args.interface_name netif.address = args.ip port = args.port if not port: if args.communication_type == VAL_NETCOM_TYPE_PLAIN: port = DFLT_CTRL_PORT_PLAIN if p.node.type == VAL_NODE_TYPE_CTRL else DFLT_STLT_PORT_PLAIN elif args.communication_type == VAL_NETCOM_TYPE_SSL: port = DFLT_CTRL_PORT_SSL else: Output.err( "Communication type %s has no default port" % (args.communication_type), args.no_color) gen_nif(KEY_PORT_NR, str(port)) satcon = p.satellite_connections.add() satcon.net_interface_name = args.interface_name satcon.port = port satcon.encryption_type = args.communication_type return Commands._create(cc, API_CRT_NODE, p, args)
def list(cc, args): lstmsg = Commands._get_list_message(cc, API_LST_STOR_POOL, MsgLstStorPool(), args) if lstmsg: tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) tbl.add_column("StoragePool") tbl.add_column("Node") tbl.add_column("Driver") tbl.add_column("DriverDevice") tbl.add_column("SupportsSnapshots") for storpool in lstmsg.stor_pools: driver_device_prop = [x for x in storpool.props if x.key == StoragePoolCommands.device_key_map[storpool.driver[:-len('Driver')]]] driver_device = driver_device_prop[0].value if driver_device_prop else '' supports_snapshots_prop = [x for x in storpool.static_traits if x.key == KEY_STOR_POOL_SUPPORTS_SNAPSHOTS] supports_snapshots = supports_snapshots_prop[0].value if supports_snapshots_prop else '' tbl.add_row([ storpool.stor_pool_name, storpool.node_name, storpool.driver, driver_device, supports_snapshots ]) tbl.show() # prntfrm = "{storpool:<20s} {uuid:<40s} {node:<30s} {driver:<20s}" # print(prntfrm.format(storpool="Storpool-name", uuid="UUID", node="Node", driver="Driver")) # for storpool in lstmsg.stor_pools: # print(prntfrm.format( # storpool=storpool.stor_pool_name, # uuid=storpool.stor_pool_uuid, # node=storpool.node_name, # driver=storpool.driver)) return None
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 delete(cc, args): p = MsgDelVlmDfn() p.rsc_name = args.resource_name p.vlm_nr = args.volume_nr return Commands._delete_and_output(cc, args, API_DEL_VLM_DFN, [p])
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_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_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