From: Yao Le Date: Thu, 17 Sep 2020 04:25:47 +0000 (+0000) Subject: Implement Service RESTful API for hub X-Git-Tag: v1.0~12^2 X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=commitdiff_plain;h=3954387f75f2523ff3f30fec65828a6e722dd0fe;p=icn%2Fsdwan.git Implement Service RESTful API for hub The API handles service POST, GET and DELETE call Signed-off-by: Yao Le Change-Id: I2e75f1ae0d7a33b58c620f5637b36994fecc7381 --- diff --git a/platform/cnf/src/rest_v1/index.lua b/platform/cnf/src/rest_v1/index.lua index 3a11e92..97a5d96 100644 --- a/platform/cnf/src/rest_v1/index.lua +++ b/platform/cnf/src/rest_v1/index.lua @@ -8,6 +8,7 @@ function index() entry({"sdewan", "mwan3", ver}, call("help")).dependent = false entry({"sdewan", "firewall", ver}, call("help")).dependent = false entry({"sdewan", "ipsec", ver}, call("help")).dependent = false + entry({"sdewan", "service", ver}, call("help")).dependent = false end function help() diff --git a/platform/cnf/src/rest_v1/svc_rest.lua b/platform/cnf/src/rest_v1/svc_rest.lua new file mode 100644 index 0000000..06e9e6e --- /dev/null +++ b/platform/cnf/src/rest_v1/svc_rest.lua @@ -0,0 +1,185 @@ +-- Licensed to the public under the GNU General Public License v2. + +module("luci.controller.rest_v1.svc_rest", package.seeall) + +local uci = require "luci.model.uci" + +json = require "luci.jsonc" +io = require "io" +sys = require "luci.sys" +utils = require "luci.controller.rest_v1.utils" + +uci_conf = "service" + +function index() + ver = "v1" + configuration = "service" + entry({"sdewan", configuration, ver, "services"}, call("handle_request")).leaf = true +end + +-- Request Handler +function handle_request() + local method = utils.get_req_method() + if method == "GET" then + return get_service() + elseif method == "POST" then + return create_service() + elseif method == "DELETE" then + return delete_service() + else + utils.response_error(405, "Method Not Allowed") + end +end + +-- Post +function create_service() + local obj = utils.get_request_body_object() + if obj == nil then + return + end + if is_invalid(obj.port, obj.dport) then + utils.response_error(416, "Invalid Port Range") + elseif is_duplicated(obj.name, obj.port) then + utils.response_error(409, "Duplicated Service Configuration") + else + local count = 0 + local ns = "nslookup "..obj.fullname.." | tail -n2 | awk -F':' '{print $2}' | head -1" + local ip + local exec + while count < 6 do + exec = io.popen(ns) + ip = string.gsub(exec:read("*a"), "^%s*(.-)%s*$", "%1") + if ip ~= "NXDOMAIN" + then + break + end + os.execute("sleep " .. tonumber(5)) + count = count + 1 + end + if ip ~= "NXDOMAIN" then + exec:close() + local file = io.open("/etc/sdewan_svc.info", "a+") + file:write(obj.name, " ", obj.fullname, " ", obj.port, " ", obj.dport, " ", ip, " ", "0\n") + local comm = "iptables -t nat -I PREROUTING 2 -p tcp --dport "..obj.port.." -j DNAT --to-destination "..ip..":"..obj.dport + os.execute(comm) + file:close() + sync_info() + else + utils.response_error(408, "Timeout: waiting for service ready...") + end + end + luci.http.prepare_content("application/json") + luci.http.write_json(obj) +end + +-- Delete +function delete_service() + local uri_list = utils.get_URI_list(7) + local name = uri_list[#uri_list] + local info_file = io.open("/etc/sdewan_svc.info", "w") + local up_file = io.open("/etc/sdewan_svc.up", "r") + for line in up_file:lines() do + local message = split(line) + if name ~= message[1] then + info_file:write(line, "\n") + else + local comm = "iptables -t nat -D PREROUTING -p tcp --dport "..message[3].." -j DNAT --to-destination "..message[5]..":"..message[4] + os.execute(comm) + end + end + info_file:close() + up_file:close() + sync_info() +end + +-- Get +function get_service() + local uri_list = utils.get_URI_list() + local file = io.open("/etc/sdewan_svc.info", "r") + if #uri_list == 6 then + local objs = {} + objs["services"] = {} + for line in file:lines() do + local message = split(line) + local obj = {} + obj["name"] = message[1] + obj["fullname"] = message[2] + obj["port"] = message[3] + obj["dport"] = message[4] + table.insert(objs["services"], obj) + end + luci.http.prepare_content("application/json") + luci.http.write_json(objs) + elseif #uri_list == 7 then + local name = uri_list[#uri_list] + local no = true + for line in file:lines() do + local message = split(line) + if name == message[1] then + no = false + local obj = {} + obj["name"] = message[1] + obj["fullname"] = message[2] + obj["port"] = message[3] + obj["dport"] = message[4] + luci.http.prepare_content("application/json") + luci.http.write_json(obj) + break + end + end + if no then + utils.response_error(404, "Cannot find " .. "service" .. "[" .. name .. "]" ) + end + else + utils.response_error(400, "Bad request URI") + end + file:close() +end + +-- Sync and validate +function sync_info() + local in_file = io.open("/etc/sdewan_svc.info", "r") + local out_file = io.open("/etc/sdewan_svc.up", "w") + local content = in_file:read("*a") + out_file:write(content) + in_file:close() + out_file:close() +end + +function split(str) + local arr = {} + for w in string.gmatch(str, "%S+") do + table.insert(arr, w) + end + return arr +end + +function is_duplicated(name, port) + local file = io.open("/etc/sdewan_svc.info", "r") + local judge = false + for line in file:lines() do + local message = split(line) + if name == message[1] then + judge = true + break + end + if port == message[2] then + judge = true + break + end + end + file:close() + return judge +end + +function is_invalid(port, dport) + local judge = false + if not utils.is_integer_and_in_range(port, 0, 65535) then + judge = true + end + if not utils.is_integer_and_in_range(dport, 0, 65535) then + judge = true + end + return judge +end +