From d43ced176fa9a37ede6cdce6fd12d66a31c4dd66 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Fri, 26 Jul 2019 09:41:17 -0400 Subject: [PATCH] RESTify the network endpoints; remove some cruft --- client-api/api_lib/pvcapi.py | 11 +- client-api/pvc-api.py | 626 ++++++++++++++--------------------- docs/manuals/api.md | 30 +- 3 files changed, 274 insertions(+), 393 deletions(-) diff --git a/client-api/api_lib/pvcapi.py b/client-api/api_lib/pvcapi.py index acd1bc59..7ddaf084 100755 --- a/client-api/api_lib/pvcapi.py +++ b/client-api/api_lib/pvcapi.py @@ -376,14 +376,15 @@ def net_add(vni, description, nettype, domain, } return flask.jsonify(output), retcode -def net_modify(vni, description, nettype, domain, - ip4_network, ip4_gateway, ip6_network, ip6_gateway, +def net_modify(vni, description, domain, + ip4_network, ip4_gateway, + ip6_network, ip6_gateway, dhcp4_flag, dhcp4_start, dhcp4_end): """ Modify a virtual client network in the PVC cluster. """ zk_conn = pvc_common.startZKConnection(config['coordinators']) - retflag, retmsg = pvc_network.add_network(zk_conn, vni, description, nettype, domain, + retflag, retmsg = pvc_network.modify_network(zk_conn, vni, description, domain, ip4_network, ip4_gateway, ip6_network, ip6_gateway, dhcp4_flag, dhcp4_start, dhcp4_end) if retflag: @@ -397,12 +398,12 @@ def net_modify(vni, description, nettype, domain, } return flask.jsonify(output), retcode -def net_remove(description): +def net_remove(network): """ Remove a virtual client network from the PVC cluster. """ zk_conn = pvc_common.startZKConnection(config['coordinators']) - retflag, retmsg = pvc_network.remove_network(zk_conn, description) + retflag, retmsg = pvc_network.remove_network(zk_conn, network) if retflag: retcode = 200 else: diff --git a/client-api/pvc-api.py b/client-api/pvc-api.py index 7405e0b0..45408437 100755 --- a/client-api/pvc-api.py +++ b/client-api/pvc-api.py @@ -138,9 +138,6 @@ def api_auth_logout(): @api.route('/api/v1/node', methods=['GET']) @authenticator def api_node(): - """ - Return a list of nodes with limit LIMIT. - """ # Get name limit if 'limit' in flask.request.values: limit = flask.request.values['limit'] @@ -152,9 +149,6 @@ def api_node(): @api.route('/api/v1/node/', methods=['GET']) @authenticator def api_node_root(node): - """ - Return information about node NODE. - """ # Same as specifying /node?limit=NODE return pvcapi.node_list(node) @@ -162,10 +156,6 @@ def api_node_root(node): @api.route('/api/v1/node//coordinator-state', methods=['GET', 'POST']) @authenticator def api_node_coordinator_state(node): - """ - Manage NODE coordinator state. - """ - if flask.request.method == 'GET': return "Test", 200 @@ -182,10 +172,6 @@ def api_node_coordinator_state(node): @api.route('/api/v1/node//domain-state', methods=['GET', 'POST']) @authenticator def api_node_domain_state(node): - """ - Manage NODE domain state. - """ - if flask.request.method == 'GET': return "Test", 200 @@ -343,310 +329,275 @@ def api_vm_node(vm): # # Network endpoints # -@api.route('/api/v1/network', methods=['GET']) +@api.route('/api/v1/network', methods=['GET', 'POST']) @authenticator def api_net(): - """ - Return a list of virtual client networks with limit LIMIT. - """ - # Get name limit - if 'limit' in flask.request.values: - limit = flask.request.values['limit'] - else: - limit = None + if flask.request.method == 'GET': + # Get name limit + if 'limit' in flask.request.values: + limit = flask.request.values['limit'] + else: + limit = None + + return pvcapi.net_list(limit) - return pvcapi.net_list(limit) + if flask.request.method == 'POST': + # Get network VNI + if 'vni' in flask.request.values: + vni = flask.request.values['vni'] + else: + return flask.jsonify({"message":"ERROR: A VNI must be specified for the virtual network."}), 520 + + # Get network description + if 'description' in flask.request.values: + description = flask.request.values['vni'] + else: + return flask.jsonify({"message":"ERROR: A VNI must be specified for the virtual network."}), 520 + + # Get network type + if 'nettype' in flask.request.values: + nettype = flask.request.values['nettype'] + if not 'managed' in nettype and not 'bridged' in nettype: + return flask.jsonify({"message":"ERROR: A valid nettype must be specified: 'managed' or 'bridged'."}), 520 + else: + return flask.jsonify({"message":"ERROR: A nettype must be specified for the virtual network."}), 520 + + # Get network domain + if 'domain' in flask.request.values: + domain = flask.request.values['domain'] + else: + domain = None + + # Get ipv4 network + if 'ip4_network' in flask.request.values: + ip4_network = flask.request.values['ip4_network'] + else: + ip4_network = None + + # Get ipv4 gateway + if 'ip4_gateway' in flask.request.values: + ip4_gateway = flask.request.values['ip4_gateway'] + else: + ip4_gateway = None + + # Get ipv6 network + if 'ip6_network' in flask.request.values: + ip6_network = flask.request.values['ip6_network'] + else: + ip6_network = None + + # Get ipv6 gateway + if 'ip6_gateway' in flask.request.values: + ip6_gateway = flask.request.values['ip6_gateway'] + else: + ip6_gateway = None + + # Get ipv4 DHCP flag + if 'dhcp4' in flask.request.values and flask.request.values['dhcp4']: + dhcp4_flag = True + else: + dhcp4_flag = False + + # Get ipv4 DHCP start + if 'dhcp4_start' in flask.request.values: + dhcp4_start = flask.request.values['dhcp4_start'] + else: + dhcp4_start = None + + # Get ipv4 DHCP end + if 'dhcp4_end' in flask.request.values: + dhcp4_end = flask.request.values['dhcp4_end'] + else: + dhcp4_end = None + + return pvcapi.net_add(vni, description, nettype, domain, + ip4_network, ip4_gateway, ip6_network, ip6_gateway, + dhcp4_flag, dhcp4_start, dhcp4_end) -@api.route('/api/v1/network/', methods=['GET']) +@api.route('/api/v1/network/', methods=['GET', 'PUT', 'DELETE']) @authenticator -def api_net_info(network): - """ - Get information about a virtual client network with description NETWORK. - """ +def api_net_root(network): # Same as specifying /network?limit=NETWORK - return pvcapi.net_list(network) + if flask.request.method == 'GET': + return pvcapi.net_list(network) -@api.route('/api/v1/network//add', methods=['POST']) + if flask.request.method == 'PUT': + # Get network description + if 'description' in flask.request.values: + description = flask.request.values['description'] + else: + description = None + + # Get network domain + if 'domain' in flask.request.values: + domain = flask.request.values['domain'] + else: + domain = None + + # Get ipv4 network + if 'ip4_network' in flask.request.values: + ip4_network = flask.request.values['ip4_network'] + else: + ip4_network = None + + # Get ipv4 gateway + if 'ip4_gateway' in flask.request.values: + ip4_gateway = flask.request.values['ip4_gateway'] + else: + ip4_gateway = None + + # Get ipv6 network + if 'ip6_network' in flask.request.values: + ip6_network = flask.request.values['ip6_network'] + else: + ip6_network = None + + # Get ipv6 gateway + if 'ip6_gateway' in flask.request.values: + ip6_gateway = flask.request.values['ip6_gateway'] + else: + ip6_gateway = None + + # Get ipv4 DHCP flag + if 'dhcp4' in flask.request.values and flask.request.values['dhcp4']: + dhcp4_flag = True + else: + dhcp4_flag = False + + # Get ipv4 DHCP start + if 'dhcp4_start' in flask.request.values: + dhcp4_start = flask.request.values['dhcp4_start'] + else: + dhcp4_start = None + + # Get ipv4 DHCP end + if 'dhcp4_end' in flask.request.values: + dhcp4_end = flask.request.values['dhcp4_end'] + else: + dhcp4_end = None + + return pvcapi.net_modify(network, description, domain, + ip4_network, ip4_gateway, + ip6_network, ip6_gateway, + dhcp4_flag, dhcp4_start, dhcp4_end) + + if flask.request.method == 'DELETE': + return pvcapi.net_remove(network) + +@api.route('/api/v1/network//lease', methods=['GET', 'POST']) @authenticator -def api_net_add(network): - """ - Add a virtual client network with description NETWORK. - """ - # Get network VNI - if 'vni' in flask.request.values: - vni = flask.request.values['vni'] - else: - return flask.jsonify({"message":"ERROR: A VNI must be specified for the virtual network."}), 520 +def api_net_lease(network): + if flask.request.method == 'GET': + # Get name limit + if 'limit' in flask.request.values: + limit = flask.request.values['limit'] + else: + limit = None + + # Get static-only flag + if 'static' in flask.request.values and flask.request.values['static']: + flag_static = True + else: + flag_static = False + + return pvcapi.net_dhcp_list(network, limit. flag_static) - # Get network type - if 'nettype' in flask.request.values: - nettype = flask.request.values['nettype'] - if not 'managed' in nettype and not 'bridged' in nettype: - return flask.jsonify({"message":"ERROR: A valid nettype must be specified: 'managed' or 'bridged'."}), 520 - else: - return flask.jsonify({"message":"ERROR: A nettype must be specified for the virtual network."}), 520 + if flask.request.method == 'POST': + # Get lease macaddr + if 'macaddress' in flask.request.values: + macaddress = flask.request.values['macaddress'] + else: + return flask.jsonify({"message":"ERROR: An IP address must be specified for the lease."}), 400 + # Get lease ipaddress + if 'ipaddress' in flask.request.values: + ipaddress = flask.request.values['ipaddress'] + else: + return flask.jsonify({"message":"ERROR: An IP address must be specified for the lease."}), 400 + + # Get lease hostname + if 'hostname' in flask.request.values: + hostname = flask.request.values['hostname'] + else: + hostname = None + + return pvcapi.net_dhcp_add(network, ipaddress, lease, hostname) - # Get network domain - if 'domain' in flask.request.values: - domain = flask.request.values['domain'] - else: - domain = None - - # Get ipv4 network - if 'ip4_network' in flask.request.values: - ip4_network = flask.request.values['ip4_network'] - else: - ip4_network = None - - # Get ipv4 gateway - if 'ip4_gateway' in flask.request.values: - ip4_gateway = flask.request.values['ip4_gateway'] - else: - ip4_gateway = None - - # Get ipv6 network - if 'ip6_network' in flask.request.values: - ip6_network = flask.request.values['ip6_network'] - else: - ip6_network = None - - # Get ipv6 gateway - if 'ip6_gateway' in flask.request.values: - ip6_gateway = flask.request.values['ip6_gateway'] - else: - ip6_gateway = None - - # Get ipv4 DHCP flag - if 'flag_dhcp4' in flask.request.values: - dhcp4_flag = True - else: - dhcp4_flag = False - - # Get ipv4 DHCP start - if 'dhcp4_start' in flask.request.values: - dhcp4_start = flask.request.values['dhcp4_start'] - else: - dhcp4_start = None - - # Get ipv4 DHCP end - if 'dhcp4_end' in flask.request.values: - dhcp4_end = flask.request.values['dhcp4_end'] - else: - dhcp4_end = None - - return pvcapi.net_add(vni, network, nettype, domain, - ip4_network, ip4_gateway, ip6_network, ip6_gateway, - dhcp4_flag, dhcp4_start, dhcp4_end) - -@api.route('/api/v1/network//modify', methods=['POST']) +@api.route('/api/v1/network//lease/', methods=['GET', 'DELETE']) @authenticator -def api_net_modify(network): - """ - Modify a virtual client network with description NETWORK. - """ - # Get network VNI - if 'vni' in flask.request.values: - vni = flask.request.values['vni'] - else: - vni = None +def api_net_lease_root(network, lease): + if flask.request.method == 'GET': + # Same as specifying /network?limit=NETWORK + return pvcapi.net_dhcp_list(network, lease, False) - # Get network type - if 'nettype' in flask.request.values: - nettype = flask.request.values['nettype'] - else: - vni = None + if flask.request.method == 'DELETE': + return pvcapi.net_dhcp_remove(network, lease) - # Get network domain - if 'domain' in flask.request.values: - domain = flask.request.values['domain'] - else: - domain = None - - # Get ipv4 network - if 'ip4_network' in flask.request.values: - ip4_network = flask.request.values['ip4_network'] - else: - ip4_network = None - - # Get ipv4 gateway - if 'ip4_gateway' in flask.request.values: - ip4_gateway = flask.request.values['ip4_gateway'] - else: - ip4_gateway = None - - # Get ipv6 network - if 'ip6_network' in flask.request.values: - ip6_network = flask.request.values['ip6_network'] - else: - ip6_network = None - - # Get ipv6 gateway - if 'ip6_gateway' in flask.request.values: - ip6_gateway = flask.request.values['ip6_gateway'] - else: - ip6_gateway = None - - # Get ipv4 DHCP flag - if 'flag_dhcp4' in flask.request.values: - dhcp4_flag = True - else: - dhcp4_flag = False - - # Get ipv4 DHCP start - if 'dhcp4_start' in flask.request.values: - dhcp4_start = flask.request.values['dhcp4_start'] - else: - dhcp4_start = None - - # Get ipv4 DHCP end - if 'dhcp4_end' in flask.request.values: - dhcp4_end = flask.request.values['dhcp4_end'] - else: - dhcp4_end = None - - return pvcapi.net_modify(vni, network, nettype, domain, - ip4_network, ip4_gateway, ip6_network, ip6_gateway, - dhcp4_flag, dhcp4_start, dhcp4_end) - -@api.route('/api/v1/network//remove', methods=['POST']) -@authenticator -def api_net_remove(network): - """ - Remove a virtual client network with description NETWORK. - """ - return pvcapi.net_remove(network) - -@api.route('/api/v1/network//dhcp', methods=['GET']) -@authenticator -def api_net_dhcp(network): - """ - Return a list of DHCP leases in virtual client network with description NETWORK with limit LIMIT. - """ - # Get name limit - if 'limit' in flask.request.values: - limit = flask.request.values['limit'] - else: - limit = None - - # Get static-only flag - if 'flag_static' in flask.request.values: - flag_static = True - else: - flag_static = False - - return pvcapi.net_dhcp_list(network, limit. flag_static) - -@api.route('/api/v1/network//dhcp/', methods=['GET']) -@authenticator -def api_net_dhcp_info(network, lease): - """ - Get information about a DHCP lease for MAC address LEASE in virtual client network with description NETWORK. - """ - # Same as specifying /network?limit=NETWORK - return pvcapi.net_dhcp_list(network, lease, False) - -@api.route('/api/v1/network//dhcp//add', methods=['POST']) -@authenticator -def api_net_dhcp_add(network, lease): - """ - Add a static DHCP lease for MAC address LEASE to virtual client network with description NETWORK. - """ - # Get lease ipaddress - if 'ipaddress' in flask.request.values: - ipaddress = flask.request.values['ipaddress'] - else: - return flask.jsonify({"message":"ERROR: An IP address must be specified for the lease."}), 520 - - # Get lease hostname - if 'hostname' in flask.request.values: - hostname = flask.request.values['hostname'] - else: - hostname = None - - return pvcapi.net_dhcp_add(network, ipaddress, lease, hostname) - -@api.route('/api/v1/network//dhcp//remove', methods=['POST']) -@authenticator -def api_net_dhcp_remove(network, lease): - """ - Remove a static DHCP lease for MAC address LEASE from virtual client network with description NETWORK. - """ - return pvcapi.net_dhcp_remove(network, lease) - -@api.route('/api/v1/network//acl', methods=['GET']) +@api.route('/api/v1/network//acl', methods=['GET', 'POST']) @authenticator def api_net_acl(network): - """ - Return a list of network ACLs in network NETWORK with limit LIMIT. - """ - # Get name limit - if 'limit' in flask.request.values: - limit = flask.request.values['limit'] - else: - limit = None + if flask.request.method == 'GET': + # Get name limit + if 'limit' in flask.request.values: + limit = flask.request.values['limit'] + else: + limit = None + + # Get direction limit + if 'direction' in flask.request.values: + direction = flask.request.values['direction'] + if not 'in' in direction and not 'out' in direction: + return flash.jsonify({"message":"ERROR: Direction must be either 'in' or 'out'; for both, do not specify a direction."}), 400 + else: + direction = None + + return pvcapi.net_acl_list(network, limit, direction) - # Get direction limit - if 'direction' in flask.request.values: - direction = flask.request.values['direction'] - if not 'in' in direction and not 'out' in direction: - return flash.jsonify({"message":"ERROR: Direction must be either 'in' or 'out'; for both, do not specify a direction."}), 510 - else: - direction = None + if flask.request.method == 'POST': + # Get ACL description + if 'description' in flask.request.values: + description = flask.request.values['description'] + else: + return flask.jsonify({"message":"ERROR: A description must be provided."}), 400 + + # Get rule direction + if 'direction' in flask.request.values: + direction = flask.request.values['limit'] + if not 'in' in direction and not 'out' in direction: + return flask.jsonify({"message":"ERROR: Direction must be either 'in' or 'out'."}), 400 + else: + return flask.jsonify({"message":"ERROR: A direction must be specified for the ACL."}), 400 + + # Get rule data + if 'rule' in flask.request.values: + rule = flask.request.values['rule'] + else: + return flask.jsonify({"message":"ERROR: A valid NFT rule line must be specified for the ACL."}), 400 + + # Get order value + if 'order' in flask.request.values: + order = flask.request.values['order'] + else: + order = None + + return pvcapi.net_acl_add(network, direction, acl, rule, order) - return pvcapi.net_acl_list(network, limit, direction) - -@api.route('/api/v1/network//acl/', methods=['GET']) +@api.route('/api/v1/network//acl/', methods=['GET', 'DELETE']) @authenticator def api_net_acl_info(network, acl): - """ - Get information about a network access control entry with description ACL in virtual client network with description NETWORK. - """ - # Same as specifying /network?limit=NETWORK - return pvcapi.net_acl_list(network, acl, None) + if flask.request.method == 'GET': + # Same as specifying /network?limit=NETWORK + return pvcapi.net_acl_list(network, acl, None) -@api.route('/api/v1/network//acl//add', methods=['POST']) -@authenticator -def api_net_acl_add(network, acl): - """ - Add an access control list with description ACL to virtual client network with description NETWORK. - """ - # Get rule direction - if 'direction' in flask.request.values: - direction = flask.request.values['limit'] - if not 'in' in direction and not 'out' in direction: - return flask.jsonify({"message":"ERROR: Direction must be either 'in' or 'out'."}), 510 - else: - return flask.jsonify({"message":"ERROR: A direction must be specified for the ACL."}), 510 - - # Get rule data - if 'rule' in flask.request.values: - rule = flask.request.values['rule'] - else: - return flask.jsonify({"message":"ERROR: A valid NFT rule line must be specified for the ACL."}), 510 - - # Get order value - if 'order' in flask.request.values: - order = flask.request.values['order'] - else: - order = None - - return pvcapi.net_acl_add(network, direction, acl, rule, order) - -@api.route('/api/v1/network//acl//remove', methods=['POST']) -@authenticator -def api_net_acl_remove(network, acl): - """ - Remove an access control list with description ACL from virtual client network with description NETWORK. - """ - # Get rule direction - if 'direction' in flask.request.values: - direction = flask.request.values['limit'] - if not 'in' in direction and not 'out' in direction: - return flask.jsonify({"message":"ERROR: Direction must be either 'in' or 'out'."}), 510 - else: - return flask.jsonify({"message":"ERROR: A direction must be specified for the ACL."}), 510 - - return pvcapi.net_acl_remove(network, direction, acl) + if flask.request.method == 'DELETE': + # Get rule direction + if 'direction' in flask.request.values: + direction = flask.request.values['limit'] + if not 'in' in direction and not 'out' in direction: + return flask.jsonify({"message":"ERROR: Direction must be either 'in' or 'out'."}), 400 + else: + return flask.jsonify({"message":"ERROR: A direction must be specified for the ACL."}), 400 + + return pvcapi.net_acl_remove(network, direction, acl) # # Storage (Ceph) endpoints @@ -658,34 +609,22 @@ def api_net_acl_remove(network, acl): # @api.route('/api/v1/storage', methods=['GET']) def api_storage(): - """ - Manage the storage of the PVC cluster. - """ return flask.jsonify({"message":"Manage the storage of the PVC cluster."}), 200 @api.route('/api/v1/storage/ceph', methods=['GET']) @api.route('/api/v1/storage/ceph/status', methods=['GET']) @authenticator def api_ceph_status(): - """ - Get the current Ceph cluster status. - """ return pvcapi.ceph_status() @api.route('/api/v1/storage/ceph/df', methods=['GET']) @authenticator def api_ceph_radosdf(): - """ - Get the current Ceph cluster utilization. - """ return pvcapi.ceph_radosdf() @api.route('/api/v1/storage/ceph/osd', methods=['GET']) @authenticator def api_ceph_osd(): - """ - Get the list of OSDs in the Ceph storage cluster. - """ # Get name limit if 'limit' in flask.request.values: limit = flask.request.values['limit'] @@ -697,66 +636,51 @@ def api_ceph_osd(): @api.route('/api/v1/storage/ceph/osd/set', methods=['POST']) @authenticator def api_ceph_osd_set(): - """ - Set OSD option OPTION on the PVC Ceph storage cluster, e.g. 'noout' or 'noscrub'. - """ # Get OSD option if 'option' in flask.request.options: option = flask.request.options['option'] else: - return flask.jsonify({"message":"ERROR: An OSD option must be specified."}), 510 + return flask.jsonify({"message":"ERROR: An OSD option must be specified."}), 400 return pvcapi.ceph_osd_set(option) @api.route('/api/v1/storage/ceph/osd/unset', methods=['POST']) @authenticator def api_ceph_osd_unset(): - """ - Unset OSD option OPTION on the PVC Ceph storage cluster, e.g. 'noout' or 'noscrub'. - """ # Get OSD option if 'option' in flask.request.options: option = flask.request.options['option'] else: - return flask.jsonify({"message":"ERROR: An OSD option must be specified."}), 510 + return flask.jsonify({"message":"ERROR: An OSD option must be specified."}), 400 return pvcapi.ceph_osd_unset(option) @api.route('/api/v1/storage/ceph/osd/', methods=['GET']) @authenticator def api_ceph_osd_info(osd): - """ - Get information about an OSD with ID OSD. - """ # Same as specifying /osd?limit=OSD return pvcapi.ceph_osd_list(osd) @api.route('/api/v1/storage/ceph/osd//add', methods=['POST']) @authenticator def api_ceph_osd_add(node): - """ - Add a Ceph OSD to node NODE. - """ # Get OSD device if 'device' in flask.request.devices: device = flask.request.devices['device'] else: - return flask.jsonify({"message":"ERROR: A block device must be specified."}), 510 + return flask.jsonify({"message":"ERROR: A block device must be specified."}), 400 # Get OSD weight if 'weight' in flask.request.weights: weight = flask.request.weights['weight'] else: - return flask.jsonify({"message":"ERROR: An OSD weight must be specified."}), 510 + return flask.jsonify({"message":"ERROR: An OSD weight must be specified."}), 400 return pvcapi.ceph_osd_add(node, device, weight) @api.route('/api/v1/storage/ceph/osd//remove', methods=['POST']) @authenticator def api_ceph_osd_remove(osd): - """ - Remove a Ceph OSD with ID OSD. - """ # Verify yes-i-really-mean-it flag if not 'flag_yes_i_really_mean_it' in flask.request.values: return flask.jsonify({"message":"ERROR: This command can have unintended consequences and should not be automated; if you're sure you know what you're doing, resend with the argument 'flag_yes_i_really_mean_it'."}), 599 @@ -766,25 +690,16 @@ def api_ceph_osd_remove(osd): @api.route('/api/v1/storage/ceph/osd//in', methods=['POST']) @authenticator def api_ceph_osd_in(osd): - """ - Set in a Ceph OSD with ID OSD. - """ return pvcapi.ceph_osd_in(osd) @api.route('/api/v1/storage/ceph/osd//out', methods=['POST']) @authenticator def api_ceph_osd_out(osd): - """ - Set out a Ceph OSD with ID OSD. - """ return pvcapi.ceph_osd_out(osd) @api.route('/api/v1/storage/ceph/pool', methods=['GET']) @authenticator def api_ceph_pool(): - """ - Get the list of RBD pools in the Ceph storage cluster. - """ # Get name limit if 'limit' in flask.request.values: limit = flask.request.values['limit'] @@ -796,18 +711,12 @@ def api_ceph_pool(): @api.route('/api/v1/storage/ceph/pool/', methods=['GET']) @authenticator def api_ceph_pool_info(pool): - """ - Get information about an RBD pool with name POOL. - """ # Same as specifying /pool?limit=POOL return pvcapi.ceph_pool_list(pool) @api.route('/api/v1/storage/ceph/pool//add', methods=['POST']) @authenticator def api_ceph_pool_add(pool): - """ - Add a Ceph RBD pool with name POOL. - """ # Get placement groups if 'pgs' in flask.request.values: pgs = flask.request.values['pgs'] @@ -820,9 +729,6 @@ def api_ceph_pool_add(pool): @api.route('/api/v1/storage/ceph/pool//remove', methods=['POST']) @authenticator def api_ceph_pool_remove(pool): - """ - Remove a Ceph RBD pool with name POOL. - """ # Verify yes-i-really-mean-it flag if not 'flag_yes_i_really_mean_it' in flask.request.values: return flask.jsonify({"message":"ERROR: This command can have unintended consequences and should not be automated; if you're sure you know what you're doing, resend with the argument 'flag_yes_i_really_mean_it'."}), 599 @@ -832,9 +738,6 @@ def api_ceph_pool_remove(pool): @api.route('/api/v1/storage/ceph/volume', methods=['GET']) @authenticator def api_ceph_volume(): - """ - Get the list of RBD volumes in the Ceph storage cluster. - """ # Get pool limit if 'pool' in flask.request.values: pool = flask.request.values['pool'] @@ -852,40 +755,28 @@ def api_ceph_volume(): @api.route('/api/v1/storage/ceph/volume//', methods=['GET']) @authenticator def api_ceph_volume_info(pool, volume): - """ - Get information about an RBD volume with name VOLUME in RBD pool with name POOL. - """ # Same as specifying /volume?limit=VOLUME return pvcapi.ceph_osd_list(pool, osd) @api.route('/api/v1/storage/ceph/volume///add', methods=['POST']) @authenticator def api_ceph_volume_add(pool, volume): - """ - Add a Ceph RBD volume with name VOLUME to RBD pool with name POOL. - """ # Get volume size if 'size' in flask.request.values: size = flask.request.values['size'] else: - return flask.jsonify({"message":"ERROR: A volume size in bytes (or with an M/G/T suffix) must be specified."}), 510 + return flask.jsonify({"message":"ERROR: A volume size in bytes (or with an M/G/T suffix) must be specified."}), 400 return pvcapi.ceph_volume_add(pool, volume, size) @api.route('/api/v1/storage/ceph/volume///remove', methods=['POST']) @authenticator def api_ceph_volume_remove(pool, volume): - """ - Remove a Ceph RBD volume with name VOLUME from RBD pool with name POOL. - """ return pvcapi.ceph_volume_remove(pool, volume) @api.route('/api/v1/storage/ceph/volume/snapshot', methods=['GET']) @authenticator def api_ceph_volume_snapshot(): - """ - Get the list of RBD volume snapshots in the Ceph storage cluster. - """ # Get pool limit if 'pool' in flask.request.values: pool = flask.request.values['pool'] @@ -909,26 +800,17 @@ def api_ceph_volume_snapshot(): @api.route('/api/v1/storage/ceph/volume/snapshot///', methods=['GET']) @authenticator def api_ceph_volume_snapshot_info(pool, volume, snapshot): - """ - Get information about a snapshot with name SNAPSHOT of RBD volume with name VOLUME in RBD pool with name POOL. - """ # Same as specifying /snapshot?limit=VOLUME return pvcapi.ceph_snapshot_list(pool, volume, snapshot) @api.route('/api/v1/storage/ceph/volume/snapshot////add', methods=['POST']) @authenticator def api_ceph_volume_snapshot_add(pool, volume, snapshot): - """ - Add a Ceph RBD volume snapshot with name SNAPSHOT of RBD volume with name VOLUME in RBD pool with name POOL. - """ return pvcapi.ceph_volume_snapshot_add(pool, volume, snapshot) @api.route('/api/v1/storage/ceph/volume/snapshot////remove', methods=['POST']) @authenticator def api_ceph_volume_snapshot_remove(pool, volume, snapshot): - """ - Remove a Ceph RBD volume snapshot with name SNAPSHOT from RBD volume with name VOLUME in RBD pool with name POOL. - """ return pvcapi.ceph_volume_snapshot_remove(pool, volume, snapshot) # diff --git a/docs/manuals/api.md b/docs/manuals/api.md index dd690879..d5099173 100644 --- a/docs/manuals/api.md +++ b/docs/manuals/api.md @@ -277,21 +277,19 @@ Add a new virtual network to the cluster. `vni` must be a valid VNI, either a vL * Mandatory values: N/A * Optional values: N/A -Return a JSON document containing information about the virtual network with description ``. The output is identical to `/api/v1/network?limit=` without fuzzy regex matching. +Return a JSON document containing information about the virtual network ``. The output is identical to `/api/v1/network?limit=` without fuzzy regex matching. ###### `PUT` * Mandatory values: N/A - * Optional values: `vni`, `nettype` `domain`, `ip4_network`, `ip4_gateway`, `ip6_network`, `ip6_gateway`, `dhcp4`, `dhcp4_start`, `dhcp4_end` + * Optional values: `domain`, `ip4_network`, `ip4_gateway`, `ip6_network`, `ip6_gateway`, `dhcp4`, `dhcp4_start`, `dhcp4_end` -Modify the options of an existing virtual network with description ``. +Modify the options of an existing virtual network ``. All values are optional and are identical to the values for `add`. Only those values specified will be updated. -**NOTE:** Changing the `vni` or `nettype` of a virtual network is technically possible, but is not recommended. This would require updating all VMs in the network. It is usually advisable to create a new virtual network with the new VNI and type, move VMs to it, then finally remove the old virtual network. - ###### `DELETE` -Remove a virtual network with description ``. +Remove a virtual network ``. #### `/api/v1/network//lease` * Methods: `GET`, `POST` @@ -300,7 +298,7 @@ Remove a virtual network with description ``. * Mandatory values: N/A * Optional values: `limit`, `static` -Return a JSON document containing information about all active DHCP leases in virtual network with description ``. +Return a JSON document containing information about all active DHCP leases in virtual network ``. If `limit` is specified, return a JSON document containing information about all active DHCP leases with MAC addresses matching `limit` as fuzzy regex. @@ -310,7 +308,7 @@ If `static` is specified, only return static DHCP leases. * Mandatory values: `macaddress`, `ipaddress` * Optional values: `hostname` -Add a new static DHCP lease for MAC address `` in virtual network with description ``. +Add a new static DHCP lease for MAC address `` in virtual network ``. `ipaddress` must be a valid IP address in the specified `` IPv4 netblock, and ideally outside of the DHCPv4 range. @@ -323,13 +321,13 @@ Add a new static DHCP lease for MAC address `` in virtual network wi * Mandatory values: N/A * Optional values: N/A -Return a JSON document containing information about DHCP lease with MAC address `` in virtual network with description ``. The output is identical to `/api/v1/network//dhcp?limit=` without fuzzy regex matching. +Return a JSON document containing information about DHCP lease with MAC address `` in virtual network ``. The output is identical to `/api/v1/network//dhcp?limit=` without fuzzy regex matching. ###### `DELETE` * Mandatory values: N/A * Optional values: N/A -Remove a static DHCP lease for MAC address ` in virtual network with description ``. +Remove a static DHCP lease for MAC address ` in virtual network ``. #### `/api/v1/network//acl` * Methods: `GET`, `POST` @@ -338,17 +336,17 @@ Remove a static DHCP lease for MAC address ` in virtual network with des * Mandatory values: N/A * Optional values: `limit`, `direction` -Return a JSON document containing information about all active NFTables ACLs in virtual network with description ``. +Return a JSON document containing information about all active NFTables ACLs in virtual network ``. If `limit` is specified, return a JSON document containing information about all active NFTables ACLs with descriptions matching `limit` as fuzzy regex. If `direction` is specified and is one of `in` or `out`, return a JSON codument listing all active NFTables ACLs in the specified direction only. If `direction` is invalid, return a failure. ###### `POST` - * Mandatory values: `direction`, `rule` + * Mandatory values: `description`, `direction`, `rule` * Optional values: `order` -Add a new NFTables ACL with description `` in virtual network with description ``. +Add a new NFTables ACL with `description` in virtual network ``. `direction` must be one of `in` or `out`. @@ -363,15 +361,15 @@ Add a new NFTables ACL with description `` in virtual network with descript * Mandatory values: N/A * Optional values: N/A -Return a JSON document containing information about NFTables ACL with description `` in virtual network with description ``. The output is identical to `/api/v1/network//acl?limit=` without fuzzy regex matching. +Return a JSON document containing information about NFTables ACL with description `` in virtual network ``. The output is identical to `/api/v1/network//acl?limit=` without fuzzy regex matching. If `` is not valid, return an empty JSON document. ###### `DELETE` - * Mandatory values: N/A + * Mandatory values: `direction` * Optional values: N/A -Remove an NFTables ACL with description `` from virtual network with description ``. +Remove an NFTables ACL with description `` in direction `direction` from virtual network ``. ### Storage (Ceph) endpoints