Merge pull request #4332 from TDT-AG/pr/20200730-luci-app-dockerman
luci-app-dockerman: improvements
This commit is contained in:
commit
d59600cdf6
5 changed files with 75 additions and 50 deletions
|
@ -12,7 +12,7 @@ function index()
|
||||||
e.dependent = false
|
e.dependent = false
|
||||||
e.acl_depends = { "luci-app-dockerman" }
|
e.acl_depends = { "luci-app-dockerman" }
|
||||||
|
|
||||||
entry({"admin", "docker", "overview"},cbi("dockerman/overview"),_("Overview"),0).leaf=true
|
entry({"admin", "docker", "overview"},cbi("dockerman/overview"),_("Overview"), 1).leaf=true
|
||||||
|
|
||||||
local remote = luci.model.uci.cursor():get_bool("dockerd", "globals", "remote_endpoint")
|
local remote = luci.model.uci.cursor():get_bool("dockerd", "globals", "remote_endpoint")
|
||||||
if remote then
|
if remote then
|
||||||
|
@ -32,11 +32,11 @@ function index()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
entry({"admin", "docker", "containers"}, form("dockerman/containers"), _("Containers"),1).leaf=true
|
entry({"admin", "docker", "containers"}, form("dockerman/containers"), _("Containers"), 2).leaf=true
|
||||||
entry({"admin", "docker", "images"}, form("dockerman/images"), _("Images"),2).leaf=true
|
entry({"admin", "docker", "images"}, form("dockerman/images"), _("Images"), 3).leaf=true
|
||||||
entry({"admin", "docker", "networks"}, form("dockerman/networks"), _("Networks"),3).leaf=true
|
entry({"admin", "docker", "networks"}, form("dockerman/networks"), _("Networks"), 4).leaf=true
|
||||||
entry({"admin", "docker", "volumes"}, form("dockerman/volumes"), _("Volumes"),4).leaf=true
|
entry({"admin", "docker", "volumes"}, form("dockerman/volumes"), _("Volumes"), 5).leaf=true
|
||||||
entry({"admin", "docker", "events"}, call("action_events"), _("Events"),5)
|
entry({"admin", "docker", "events"}, call("action_events"), _("Events"), 6)
|
||||||
|
|
||||||
entry({"admin", "docker", "newcontainer"}, form("dockerman/newcontainer")).leaf=true
|
entry({"admin", "docker", "newcontainer"}, form("dockerman/newcontainer")).leaf=true
|
||||||
entry({"admin", "docker", "newnetwork"}, form("dockerman/newnetwork")).leaf=true
|
entry({"admin", "docker", "newnetwork"}, form("dockerman/newnetwork")).leaf=true
|
||||||
|
@ -64,12 +64,24 @@ function action_events()
|
||||||
|
|
||||||
if events.code == 200 then
|
if events.code == 200 then
|
||||||
for _, v in ipairs(events.body) do
|
for _, v in ipairs(events.body) do
|
||||||
|
local date = "unknown"
|
||||||
|
if v and v.time then
|
||||||
|
date = os.date("%Y-%m-%d %H:%M:%S", v.time)
|
||||||
|
end
|
||||||
|
|
||||||
|
local name = v.Actor.Attributes.name or "unknown"
|
||||||
|
local action = v.Action or "unknown"
|
||||||
|
|
||||||
if v and v.Type == "container" then
|
if v and v.Type == "container" then
|
||||||
logs = (logs ~= "" and (logs .. "\n") or logs) .. "[" .. os.date("%Y-%m-%d %H:%M:%S", v.time) .."] "..v.Type.. " " .. (v.Action or "null") .. " Container ID:".. (v.Actor.ID or "null") .. " Container Name:" .. (v.Actor.Attributes.name or "null")
|
local id = v.Actor.ID or "unknown"
|
||||||
|
logs = logs .. string.format("[%s] %s %s Container ID: %s Container Name: %s\n", date, v.Type, action, id, name)
|
||||||
elseif v.Type == "network" then
|
elseif v.Type == "network" then
|
||||||
logs = (logs ~= "" and (logs .. "\n") or logs) .. "[" .. os.date("%Y-%m-%d %H:%M:%S", v.time) .."] "..v.Type.. " " .. v.Action .. " Container ID:"..( v.Actor.Attributes.container or "null" ) .. " Network Name:" .. (v.Actor.Attributes.name or "null") .. " Network type:".. v.Actor.Attributes.type or ""
|
local container = v.Actor.Attributes.container or "unknown"
|
||||||
|
local network = v.Actor.Attributes.type or "unknown"
|
||||||
|
logs = logs .. string.format("[%s] %s %s Container ID: %s Network Name: %s Network type: %s\n", date, v.Type, action, container, name, network)
|
||||||
elseif v.Type == "image" then
|
elseif v.Type == "image" then
|
||||||
logs = (logs ~= "" and (logs .. "\n") or logs) .. "[" .. os.date("%Y-%m-%d %H:%M:%S", v.time) .."] "..v.Type.. " " .. v.Action .. " Image:".. (v.Actor.ID or "null").. " Image Name:" .. (v.Actor.Attributes.name or "null")
|
local id = v.Actor.ID or "unknown"
|
||||||
|
logs = logs .. string.format("[%s] %s %s Image: %s Image name: %s\n", date, v.Type, action, id, name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -704,11 +704,14 @@ elseif action == "console" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local kill_ttyd = 'netstat -lnpt | grep ":7682[ \t].*ttyd$" | awk \'{print $NF}\' | awk -F\'/\' \'{print "kill -9 " $1}\' | sh > /dev/null'
|
local pid = luci.util.trim(luci.util.exec("netstat -lnpt | grep :7682 | grep ttyd | tr -s ' ' | cut -d ' ' -f7 | cut -d'/' -f1"))
|
||||||
luci.util.exec(kill_ttyd)
|
if pid and pid ~= "" then
|
||||||
|
luci.util.exec("kill -9 " .. pid)
|
||||||
|
end
|
||||||
|
|
||||||
local hosts
|
local hosts
|
||||||
local uci = (require "luci.model.uci").cursor()
|
local uci = require "luci.model.uci".cursor()
|
||||||
local remote = uci:get_bool("dockerd", "globals", "remote_endpoint")
|
local remote = uci:get_bool("dockerd", "globals", "remote_endpoint") or false
|
||||||
local host = nil
|
local host = nil
|
||||||
local port = nil
|
local port = nil
|
||||||
local socket = nil
|
local socket = nil
|
||||||
|
@ -717,18 +720,25 @@ elseif action == "console" then
|
||||||
host = uci:get("dockerd", "globals", "remote_host") or nil
|
host = uci:get("dockerd", "globals", "remote_host") or nil
|
||||||
port = uci:get("dockerd", "globals", "remote_port") or nil
|
port = uci:get("dockerd", "globals", "remote_port") or nil
|
||||||
else
|
else
|
||||||
socket = uci:get("dockerd", "globals", "socket_path") or nil
|
socket = uci:get("dockerd", "globals", "socket_path") or "/var/run/docker.sock"
|
||||||
end
|
end
|
||||||
|
|
||||||
if remote and host and port then
|
if remote and host and port then
|
||||||
hosts = host .. ':'.. port
|
hosts = host .. ':'.. port
|
||||||
elseif socket_path then
|
elseif socket then
|
||||||
hosts = socket_path
|
hosts = socket
|
||||||
else
|
else
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local start_cmd = cmd_ttyd .. ' -d 2 --once -p 7682 '.. cmd_docker .. ' -H "'.. hosts ..'" exec -it ' .. (uid and uid ~= "" and (" -u ".. uid .. ' ') or "").. container_id .. ' ' .. cmd .. ' &'
|
if uid and uid ~= "" then
|
||||||
|
uid = "-u " .. uid
|
||||||
|
else
|
||||||
|
uid = ""
|
||||||
|
end
|
||||||
|
|
||||||
|
local start_cmd = string.format('%s -d 2 --once -p 7682 %s -H "unix://%s" exec -it %s %s %s&', cmd_ttyd, cmd_docker, hosts, uid, container_id, cmd)
|
||||||
|
|
||||||
os.execute(start_cmd)
|
os.execute(start_cmd)
|
||||||
|
|
||||||
o = s:option(DummyValue, "console")
|
o = s:option(DummyValue, "console")
|
||||||
|
|
|
@ -45,13 +45,12 @@ function get_containers()
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, v in ipairs(containers) do
|
for i, v in ipairs(containers) do
|
||||||
local index = v.Created .. v.Id
|
local index = v.Id
|
||||||
|
|
||||||
data[index]={}
|
data[index]={}
|
||||||
data[index]["_selected"] = 0
|
data[index]["_selected"] = 0
|
||||||
data[index]["_id"] = v.Id:sub(1,12)
|
data[index]["_id"] = v.Id:sub(1,12)
|
||||||
data[index]["name"] = v.Names[1]:sub(2)
|
data[index]["_name"] = v.Names[1]:sub(2)
|
||||||
data[index]["_name"] = '<a href='..luci.dispatcher.build_url("admin/docker/container/"..v.Id)..' class="dockerman_link" title="'..translate("Container detail")..'">'.. v.Names[1]:sub(2).."</a>"
|
|
||||||
data[index]["_status"] = v.Status
|
data[index]["_status"] = v.Status
|
||||||
|
|
||||||
if v.Status:find("^Up") then
|
if v.Status:find("^Up") then
|
||||||
|
@ -104,7 +103,11 @@ if s.err then
|
||||||
end
|
end
|
||||||
|
|
||||||
s = m:section(Table, container_list, translate("Containers"))
|
s = m:section(Table, container_list, translate("Containers"))
|
||||||
s.nodescr=true
|
s.addremove = false
|
||||||
|
s.sectionhead = translate("Containers")
|
||||||
|
s.sortable = false
|
||||||
|
s.template = "cbi/tblsection"
|
||||||
|
s.extedit = luci.dispatcher.build_url("admin", "docker", "container","%s")
|
||||||
|
|
||||||
o = s:option(Flag, "_selected","")
|
o = s:option(Flag, "_selected","")
|
||||||
o.disabled = 0
|
o.disabled = 0
|
||||||
|
@ -142,7 +145,7 @@ local start_stop_remove = function(m,cmd)
|
||||||
|
|
||||||
for k in pairs(container_list) do
|
for k in pairs(container_list) do
|
||||||
if container_list[k]._selected == 1 then
|
if container_list[k]._selected == 1 then
|
||||||
container_selected[#container_selected + 1] = container_list[k].name
|
container_selected[#container_selected + 1] = container_list[k]._name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -175,7 +178,7 @@ s.rowcolors=false
|
||||||
s.template="cbi/nullsection"
|
s.template="cbi/nullsection"
|
||||||
|
|
||||||
o = s:option(Button, "_new")
|
o = s:option(Button, "_new")
|
||||||
o.inputtitle= translate("New")
|
o.inputtitle= translate("Add")
|
||||||
o.template = "dockerman/cbi/inlinebutton"
|
o.template = "dockerman/cbi/inlinebutton"
|
||||||
o.inputstyle = "add"
|
o.inputstyle = "add"
|
||||||
o.forcewrite = true
|
o.forcewrite = true
|
||||||
|
|
|
@ -24,41 +24,41 @@ s = m:section(SimpleSection, translate("New Network"))
|
||||||
s.addremove = true
|
s.addremove = true
|
||||||
s.anonymous = true
|
s.anonymous = true
|
||||||
|
|
||||||
o = s:option(Value, "name", translate("Network Name"))
|
o = s:option(Value, "name",
|
||||||
|
translate("Network Name"),
|
||||||
|
translate("Name of the network that can be selected during container creation"))
|
||||||
o.rmempty = true
|
o.rmempty = true
|
||||||
|
|
||||||
o = s:option(ListValue, "dirver", translate("Driver"))
|
o = s:option(ListValue, "driver", translate("Driver"))
|
||||||
o.rmempty = true
|
o.rmempty = true
|
||||||
o:value("bridge", "bridge")
|
o:value("bridge", translate("Bridge device"))
|
||||||
o:value("macvlan", "macvlan")
|
o:value("macvlan", translate("MAC VLAN"))
|
||||||
o:value("ipvlan", "ipvlan")
|
o:value("ipvlan", translate("IP VLAN"))
|
||||||
o:value("overlay", "overlay")
|
o:value("overlay", translate("Overlay network"))
|
||||||
|
|
||||||
o = s:option(Value, "parent", translate("Parent Interface"))
|
o = s:option(Value, "parent", translate("Base device"))
|
||||||
o.rmempty = true
|
o.rmempty = true
|
||||||
o:depends("dirver", "macvlan")
|
o:depends("driver", "macvlan")
|
||||||
local interfaces = luci.sys and luci.sys.net and luci.sys.net.devices() or {}
|
local interfaces = luci.sys and luci.sys.net and luci.sys.net.devices() or {}
|
||||||
for _, v in ipairs(interfaces) do
|
for _, v in ipairs(interfaces) do
|
||||||
o:value(v, v)
|
o:value(v, v)
|
||||||
end
|
end
|
||||||
o.default="br-lan"
|
|
||||||
o.placeholder="br-lan"
|
|
||||||
|
|
||||||
o = s:option(Value, "macvlan_mode", translate("Macvlan Mode"))
|
o = s:option(ListValue, "macvlan_mode", translate("Mode"))
|
||||||
o.rmempty = true
|
o.rmempty = true
|
||||||
o:depends("dirver", "macvlan")
|
o:depends("driver", "macvlan")
|
||||||
o.default="bridge"
|
o.default="bridge"
|
||||||
o:value("bridge", "bridge")
|
o:value("bridge", translate("Bridge (Support direct communication between MAC VLANs)"))
|
||||||
o:value("private", "private")
|
o:value("private", translate("Private (Prevent communication between MAC VLANs)"))
|
||||||
o:value("vepa", "vepa")
|
o:value("vepa", translate("VEPA (Virtual Ethernet Port Aggregator)"))
|
||||||
o:value("passthru", "passthru")
|
o:value("passthru", translate("Pass-through (Mirror physical device to single MAC VLAN)"))
|
||||||
|
|
||||||
o = s:option(Value, "ipvlan_mode", translate("Ipvlan Mode"))
|
o = s:option(ListValue, "ipvlan_mode", translate("Ipvlan Mode"))
|
||||||
o.rmempty = true
|
o.rmempty = true
|
||||||
o:depends("dirver", "ipvlan")
|
o:depends("driver", "ipvlan")
|
||||||
o.default="l3"
|
o.default="l3"
|
||||||
o:value("l2", "l2")
|
o:value("l2", translate("L2 bridge"))
|
||||||
o:value("l3", "l3")
|
o:value("l3", translate("L3 bridge"))
|
||||||
|
|
||||||
o = s:option(Flag, "ingress",
|
o = s:option(Flag, "ingress",
|
||||||
translate("Ingress"),
|
translate("Ingress"),
|
||||||
|
@ -67,7 +67,7 @@ o.rmempty = true
|
||||||
o.disabled = 0
|
o.disabled = 0
|
||||||
o.enabled = 1
|
o.enabled = 1
|
||||||
o.default = 0
|
o.default = 0
|
||||||
o:depends("dirver", "overlay")
|
o:depends("driver", "overlay")
|
||||||
|
|
||||||
o = s:option(DynamicList, "options", translate("Options"))
|
o = s:option(DynamicList, "options", translate("Options"))
|
||||||
o.rmempty = true
|
o.rmempty = true
|
||||||
|
@ -75,14 +75,14 @@ o.placeholder="com.docker.network.driver.mtu=1500"
|
||||||
|
|
||||||
o = s:option(Flag, "internal", translate("Internal"), translate("Restrict external access to the network"))
|
o = s:option(Flag, "internal", translate("Internal"), translate("Restrict external access to the network"))
|
||||||
o.rmempty = true
|
o.rmempty = true
|
||||||
o:depends("dirver", "overlay")
|
o:depends("driver", "overlay")
|
||||||
o.disabled = 0
|
o.disabled = 0
|
||||||
o.enabled = 1
|
o.enabled = 1
|
||||||
o.default = 0
|
o.default = 0
|
||||||
|
|
||||||
if nixio.fs.access("/etc/config/network") and nixio.fs.access("/etc/config/firewall")then
|
if nixio.fs.access("/etc/config/network") and nixio.fs.access("/etc/config/firewall")then
|
||||||
o = s:option(Flag, "op_macvlan", translate("Create macvlan interface"), translate("Auto create macvlan interface in Openwrt"))
|
o = s:option(Flag, "op_macvlan", translate("Create macvlan interface"), translate("Auto create macvlan interface in Openwrt"))
|
||||||
o:depends("dirver", "macvlan")
|
o:depends("driver", "macvlan")
|
||||||
o.disabled = 0
|
o.disabled = 0
|
||||||
o.enabled = 1
|
o.enabled = 1
|
||||||
o.default = 1
|
o.default = 1
|
||||||
|
@ -128,7 +128,7 @@ o:depends("ipv6", 1)
|
||||||
m.handle = function(self, state, data)
|
m.handle = function(self, state, data)
|
||||||
if state == FORM_VALID then
|
if state == FORM_VALID then
|
||||||
local name = data.name
|
local name = data.name
|
||||||
local driver = data.dirver
|
local driver = data.driver
|
||||||
|
|
||||||
local internal = data.internal == 1 and true or false
|
local internal = data.internal == 1 and true or false
|
||||||
|
|
||||||
|
|
|
@ -99,8 +99,8 @@ o.rmempty = false
|
||||||
|
|
||||||
o = s:option(Value, "socket_path",
|
o = s:option(Value, "socket_path",
|
||||||
translate("Docker Socket Path"))
|
translate("Docker Socket Path"))
|
||||||
o.default = "unix://var/run/docker.sock"
|
o.default = "unix:///var/run/docker.sock"
|
||||||
o.placeholder = "unix://var/run/docker.sock"
|
o.placeholder = "unix:///var/run/docker.sock"
|
||||||
o:depends("remote_endpoint", 1)
|
o:depends("remote_endpoint", 1)
|
||||||
|
|
||||||
o = s:option(Value, "remote_host",
|
o = s:option(Value, "remote_host",
|
||||||
|
@ -146,7 +146,7 @@ if nixio.fs.access("/usr/bin/dockerd") then
|
||||||
o = s:option(DynamicList, "hosts",
|
o = s:option(DynamicList, "hosts",
|
||||||
translate("Client connection"),
|
translate("Client connection"),
|
||||||
translate('Specifies where the Docker daemon will listen for client connections'))
|
translate('Specifies where the Docker daemon will listen for client connections'))
|
||||||
o:value("unix://var/run/docker.sock", "unix://var/run/docker.sock")
|
o:value("unix:///var/run/docker.sock", "unix:///var/run/docker.sock")
|
||||||
o:value("tcp://0.0.0.0:2375", "tcp://0.0.0.0:2375")
|
o:value("tcp://0.0.0.0:2375", "tcp://0.0.0.0:2375")
|
||||||
o.rmempty = true
|
o.rmempty = true
|
||||||
o:depends("remote_endpoint", 0)
|
o:depends("remote_endpoint", 0)
|
||||||
|
|
Loading…
Reference in a new issue