From 4e94331d1a1b0388b60ae2154ef85f352176b02a Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Fri, 5 Jul 2019 21:39:04 -0400 Subject: [PATCH] Implement API for network functions --- client-api/api.py | 184 +++++++++++++++++++++++++++++++++-- client-api/api_lib/pvcapi.py | 138 +++++++++++++++++++++----- 2 files changed, 288 insertions(+), 34 deletions(-) diff --git a/client-api/api.py b/client-api/api.py index 2ce2e6ae..fdf6adb8 100755 --- a/client-api/api.py +++ b/client-api/api.py @@ -298,21 +298,147 @@ def api_net_add(network): """ Add a virtual client network with description NETWORK. """ - return pvcapi.net_add() + # 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 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 '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']) def api_net_modify(network): """ Modify a virtual client network with description NETWORK. """ - return pvcapi.net_modify() + # Get network VNI + if 'vni' in flask.request.values: + vni = flask.request.values['vni'] + else: + vni = None + + # Get network type + if 'nettype' in flask.request.values: + nettype = flask.request.values['nettype'] + else: + vni = 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 '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']) def api_net_remove(network): """ Remove a virtual client network with description NETWORK. """ - return pvcapi.net_remove() + return pvcapi.net_remove(network) @api.route('/api/v1/network//dhcp', methods=['GET']) def api_net_dhcp(network): @@ -346,14 +472,26 @@ def api_net_dhcp_add(network, lease): """ Add a static DHCP lease for MAC address LEASE to virtual client network with description NETWORK. """ - return pvcapi.net_dhcp_add() + # 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']) 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() + return pvcapi.net_dhcp_remove(network, lease) @api.route('/api/v1/network//acl', methods=['GET']) def api_net_acl(network): @@ -369,8 +507,8 @@ def api_net_acl(network): # Get direction limit if 'direction' in flask.request.values: direction = flask.request.values['direction'] - if not 'in' in direction or not 'out' in direction: - return "Error: Direction must be either 'in' or 'out'; for both, do not specify a direction.\n", 510 + 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 @@ -389,14 +527,42 @@ def api_net_acl_add(network, acl): """ Add an access control list with description ACL to virtual client network with description NETWORK. """ - return pvcapi.net_acl_add() + # 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']) def api_net_acl_remove(network, acl): """ Remove an access control list with description ACL from virtual client network with description NETWORK. """ - return pvcapi.net_acl_remove() + # 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) # # Ceph endpoints diff --git a/client-api/api_lib/pvcapi.py b/client-api/api_lib/pvcapi.py index 61ce0fc9..e972e8b9 100755 --- a/client-api/api_lib/pvcapi.py +++ b/client-api/api_lib/pvcapi.py @@ -364,23 +364,64 @@ def net_list(limit=None): pvc_common.stopZKConnection(zk_conn) return flask.jsonify(retdata), retcode -def net_add(): +def net_add(vni, description, nettype, domain, + ip4_network, ip4_gateway, ip6_network, ip6_gateway, + dhcp4_flag, dhcp4_start, dhcp4_end): """ Add a virtual client network to the PVC cluster. """ - return '', 200 + zk_conn = pvc_common.startZKConnection(zk_host) + retflag, retmsg = pvc_network.add_network(zk_conn, vni, description, nettype, domain, + ip4_network, ip4_gateway, ip6_network, ip6_gateway, + dhcp4_flag, dhcp4_start, dhcp4_end) + if retflag: + retcode = 200 + else: + retcode = 510 -def net_modify(): + pvc_common.stopZKConnection(zk_conn) + output = { + 'message': retmsg.replace('\"', '\'') + } + return flask.jsonify(output), retcode + +def net_modify(vni, description, nettype, domain, + ip4_network, ip4_gateway, ip6_network, ip6_gateway, + dhcp4_flag, dhcp4_start, dhcp4_end): """ Modify a virtual client network in the PVC cluster. """ - return '', 200 + zk_conn = pvc_common.startZKConnection(zk_host) + retflag, retmsg = pvc_network.add_network(zk_conn, vni, description, nettype, domain, + ip4_network, ip4_gateway, ip6_network, ip6_gateway, + dhcp4_flag, dhcp4_start, dhcp4_end) + if retflag: + retcode = 200 + else: + retcode = 510 -def net_remove(): + pvc_common.stopZKConnection(zk_conn) + output = { + 'message': retmsg.replace('\"', '\'') + } + return flask.jsonify(output), retcode + +def net_remove(description): """ Remove a virtual client network from the PVC cluster. """ - return '', 200 + zk_conn = pvc_common.startZKConnection(zk_host) + retflag, retmsg = pvc_network.remove_network(zk_conn, description) + if retflag: + retcode = 200 + else: + retcode = 510 + + pvc_common.stopZKConnection(zk_conn) + output = { + 'message': retmsg.replace('\"', '\'') + } + return flask.jsonify(output), retcode def net_dhcp_list(network, limit=None, static=False): """ @@ -396,43 +437,90 @@ def net_dhcp_list(network, limit=None, static=False): pvc_common.stopZKConnection(zk_conn) return flask.jsonify(retdata), retcode -def net_dhcp_add(): +def net_dhcp_add(network, ipaddress, macaddress, hostname): """ Add a static DHCP lease to a virtual client network. """ - return '', 200 - -def net_dhcp_remove(): - """ - Remove a static DHCP lease from a virtual client network. - """ - return '', 200 - -def net_acl_list(network, limit=None, direction=None): - """ - Return a list of network ACLs in network NETWORK with limit LIMIT. - """ zk_conn = pvc_common.startZKConnection(zk_host) - retflag, retdata = pvc_network.get_list_acl(zk_conn, network, limit, direction) + retflag, retmsg = pvc_network.add_dhcp_reservation(zk_conn, network, ipaddress, macaddress, hostname) if retflag: retcode = 200 else: retcode = 510 pvc_common.stopZKConnection(zk_conn) - return flask.jsonify(retdata), retcode + output = { + 'message': retmsg.replace('\"', '\'') + } + return flask.jsonify(output), retcode -def net_acl_add(): +def net_dhcp_remove(network, macaddress): + """ + Remove a static DHCP lease from a virtual client network. + """ + zk_conn = pvc_common.startZKConnection(zk_host) + retflag, retmsg = pvc_network.remove_dhcp_reservation(zk_conn, network, macaddress) + if retflag: + retcode = 200 + else: + retcode = 510 + + pvc_common.stopZKConnection(zk_conn) + output = { + 'message': retmsg.replace('\"', '\'') + } + return flask.jsonify(output), retcode + +def net_acl_list(network, limit=None, direction=None): + """ + Return a list of network ACLs in network NETWORK with limit LIMIT. + """ + zk_conn = pvc_common.startZKConnection(zk_host) + retflag, retmsg = pvc_network.get_list_acl(zk_conn, network, limit, direction) + if retflag: + retcode = 200 + else: + retcode = 510 + + pvc_common.stopZKConnection(zk_conn) + output = { + 'message': retmsg.replace('\"', '\'') + } + return flask.jsonify(output), retcode + +def net_acl_add(network, direction, description, rule, order): """ Add an ACL to a virtual client network. """ - return '', 200 + zk_conn = pvc_common.startZKConnection(zk_host) + retflag, retmsg = pvc_network.add_acl(zk_conn, network, direction, description, rule, order) + if retflag: + retcode = 200 + else: + retcode = 510 -def net_acl_remove(): + pvc_common.stopZKConnection(zk_conn) + output = { + 'message': retmsg.replace('\"', '\'') + } + return flask.jsonify(output), retcode + +def net_acl_remove(network, direction, description): """ Remove an ACL from a virtual client network. """ - return '', 200 + zk_conn = pvc_common.startZKConnection(zk_host) + retflag, retmsg = pvc_network.remove_acl(zk_conn, network, description, direction) + if retflag: + retcode = 200 + else: + retcode = 510 + + pvc_common.stopZKConnection(zk_conn) + output = { + 'message': retmsg.replace('\"', '\'') + } + return flask.jsonify(output), retcode # # Ceph functions