summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--alpine-baselayout.roles6
-rw-r--r--interfaces-controller.lua194
-rw-r--r--interfaces-create-html.lsp49
-rw-r--r--interfaces-editintfile-html.lsp27
-rw-r--r--interfaces-model.lua478
-rw-r--r--interfaces-read-html.lsp80
-rw-r--r--interfaces-status-html.lsp27
-rw-r--r--interfaces-update-html.lsp38
-rw-r--r--interfaces.menu2
9 files changed, 524 insertions, 377 deletions
diff --git a/alpine-baselayout.roles b/alpine-baselayout.roles
index 22dd03f..9e0e086 100644
--- a/alpine-baselayout.roles
+++ b/alpine-baselayout.roles
@@ -1,5 +1,5 @@
-CREATE=interfaces:create
-READ=health:storage,health:proc,health:network,health:modules,interfaces:read,logfiles:status,logfiles:view,logfiles:download,syslog:status,syslog:basicstatus
-UPDATE=interfaces:update,skins:update,skins:read,syslog:startstop,syslog:config,syslog:expert,interfaces:config
+CREATE=interfaces:create,interfaces:editintfile
+READ=health:storage,health:proc,health:network,health:modules,interfaces:status,interfaces:read,logfiles:status,logfiles:view,logfiles:download,syslog:status,syslog:basicstatus
+UPDATE=interfaces:update,interfaces:ifup,interfaces:ifdown,skins:update,skins:read,syslog:startstop,syslog:config,syslog:expert
DELETE=interfaces:delete,logfiles:delete
ALL=health:system,hostname:read
diff --git a/interfaces-controller.lua b/interfaces-controller.lua
index d2866db..1a3a725 100644
--- a/interfaces-controller.lua
+++ b/interfaces-controller.lua
@@ -4,166 +4,132 @@ module (..., package.seeall)
default_action = "read"
-read = function (self )
- local iface = self.model.get_all_interfaces()
- local status = self.model.get_status()
- -- these actions are available for each interface
- -- **FIXME** This is technically wrong. The controller should pass
- -- the "script" "prefix" "controller" "action" as separate fields,
- -- since the view could be a cli, not a web interface. the VIEW
- -- should make a uri from these these elements.
- local actions = { link = self.conf.script .. self.conf.prefix ..
- self.conf.controller .. "/",
- action = { "create", "read", "update", "delete" } }
- return ( { actions = actions, iface = iface, status=status } )
+status = function (self)
+ return self.model.get_status()
end
-config = function (self )
- local config = read(self)
- for k,v in pairs(config.iface) do
- v['edit']=cfe(
- {name="edit",
- label="Edit this record",
- value="Edit",
- type="link",
- })
+read = function (self)
+ local cmdresult
+ if self.sessiondata.cmdresult then
+ cmdresult = self.sessiondata.cmdresult
end
- return ( config )
+ self.sessiondata.cmdresult = nil
+
+ local retval = self.model.get_all_interfaces()
+ retval.value.cmdresult = cmdresult
+ return retval
end
-- Accepts form info
-- Returns a cfe object (the form)
update = function(self)
- local iface = self.clientdata.iface or ""
- local result
- local data
+ local name = self.clientdata.name or ""
-- If interface is not found, return to list
- result, data = self.model.get_iface_by_name ( iface )
- if result == false then
+ local data = self.model.get_iface_by_name ( name )
+ if data.value.name.value == "" then
redirect(self)
end
- -- If the "cmd" button was used, then attempt to do the update
- if self.clientdata.cmd then
+ -- If the "Save" button was used, then attempt to do the update
+ if self.clientdata.Save then
-- update the iface info the form gave us
- for k,v in pairs (data) do
- if self.clientdata[k] then
- data[k].value = self.clientdata[k]
+ for k,v in pairs (data.value) do
+ if v.type == "boolean" then
+ if self.clientdata[k] then
+ v.value = true
+ else
+ v.value = false
+ end
+ elseif self.clientdata[k] then
+ v.value = self.clientdata[k]
end
end
- result, data = self.model.update_iface_by_name ( data, data.name.value )
+ data = self.model.update_iface ( data )
-- If validation worked then return to list
- if result == true then
- redirect(self)
+ if not data.errtxt then
+ data.descr = "Updated Interface"
end
end
- -- If the "cmddelete" button was used, then attempt to delete the interface
- if self.clientdata.cmddelete then
- self.conf.action = "delete?iface=" .. tostring(self.clientdata.name)
- self.conf.type = "redir"
- error (self.conf)
- end
-
- -- Hide the 'name' field
- data.name.type="hidden"
-
-- If we reach this point in the function, then we are providing a form
-- for the user to edit (either first time in, or validation failed)
+ data.type = "form"
+ data.option = "Save"
+ data.label = "Update Interface"
- -- Add a command button
- data.cmd = cfe({type="action", value="Save", name="cmd", label="Save/Apply above settings"})
-
- -- Add a delete button
- data.cmddelete = cfe({type="action", value="Delete", name="cmddelete", label="Delete this record"})
-
- return ( cfe ({type="form",
- option={ script=self.conf.script,
- prefix=self.conf.prefix,
- controller = self.conf.controller,
- action = "update",
- extra = "?iface=" .. data.name.value },
- value = data,
- clientdata=clientdata,
- } ) )
+ return data
end
-
-
delete = function(self)
- local iface = self.clientdata.iface or ""
- local result
- local data
+ local name = self.clientdata.name or ""
- -- If the interface doesn't exist, return to the list now
- result, data = self.model.get_iface_by_name ( iface )
- if result == false then
- redirect(self)
- end
-
+ -- Attempt to delete the iface
+ local cmdresult = self.model.delete_iface_by_name (name)
+ self.sessiondata.cmdresult = cmdresult
+ redirect_to_referrer(self)
+end
- -- If the cmd button was pressed, then commit the change
- if self.clientdata.cmd then
- if self.clientdata.cmd == "delete" then
- self.model.delete_iface_by_name (iface)
- end
- redirect(self)
- end
+ifup = function(self)
+ local name = self.clientdata.name or ""
- -- Otherwise, return a form
- local me = {}
- me.iface = cfe({name="iface", type="hidden", value = (self.clientdata.iface or "") })
- me.action1 = cfe({name="cmd", type="action", value="delete", label="action"})
- me.action2 = cfe({name="cmd", type="action", value="cancel", label="action"})
-
- return ( cfe ({type="form",
- option={ script=self.conf.script,
- prefix=self.conf.prefix,
- controller = self.conf.controller,
- action = "delete",
- extra = "?iface=" .. (self.clientdata.iface or "") },
- value = me,
- clientdata=clientdata,
- iface=iface,
- } ) )
+ -- Attempt to delete the iface
+ local cmdresult = self.model.ifup_by_name (name)
+ self.sessiondata.cmdresult = cmdresult
+ redirect_to_referrer(self)
end
+ifdown = function(self)
+ local name = self.clientdata.name or ""
+ -- Attempt to delete the iface
+ local cmdresult = self.model.ifdown_by_name (name)
+ self.sessiondata.cmdresult = cmdresult
+ redirect_to_referrer(self)
+end
create = function(self)
- local iface = self.clientdata.iface or ""
- local index = 0
- local result, data = self.model.get_iface_by_name ()
+ local data = self.model.get_iface (self.clientdata.family, self.clientdata.method)
- -- If the "cmd" button was used, then attempt to do the insert
- if self.clientdata.cmd then
- for k,v in pairs (data) do
+ -- If the "Create" button was used, then attempt to do the insert
+ if self.clientdata.Create then
+ for k,v in pairs (data.value) do
if self.clientdata[k] then
- data[k].value = self.clientdata[k]
+ v.value = self.clientdata[k]
end
end
- result, data = self.model.create_iface_by_name ( iface, data )
- if result then
- redirect(self)
+ data = self.model.create_iface ( data )
+ if not data.errtxt then
+ data.descr = "Created Interface"
+ redirect(self, "update?name="..data.value.name.value)
+ elseif data.value.method.value == "" then
+ data.value.method.errtxt = "Must define method"
end
end
-- If we reach this point in the function, we are providing a form
+ data.type = "form"
+ data.option = "Create"
+ data.label = "Create Interface"
- -- Add a command button
- data.cmd = cfe({type="action", value="save", label="action"})
-
- return ( cfe ({type="form",
- option={ script=self.conf.script,
- prefix=self.conf.prefix,
- controller = self.conf.controller,
- action = "create",
- extra = "?iface=" .. iface or "" },
- value = data} ) )
+ return data
end
+editintfile = function(self)
+ local data = self.model.get_file()
+
+ if self.clientdata.Save then
+ data.value.filecontent.value = self.clientdata.filecontent
+ data = self.model.write_file(data)
+ data.descr = "Saved file"
+ end
+ data.type = "form"
+ data.option = "Save"
+ data.label = "Edit Interfaces file"
+
+ return data
+end
diff --git a/interfaces-create-html.lsp b/interfaces-create-html.lsp
index 169cc76..5ce1d0f 100644
--- a/interfaces-create-html.lsp
+++ b/interfaces-create-html.lsp
@@ -1,37 +1,16 @@
<? local form = ...
- require ("html") ?>
-<h1>Create Interface</h1>
+require("viewfunctions")
+?>
+<?
+--[[ DEBUG INFORMATION
+io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
+io.write(html.cfe_unpack(form))
+io.write("</span>")
+--]]
+?>
-<form action="<?= form.option.script .. "/" .. form.option.prefix ..
- form.option.controller .. "/" .. form.option.action ..
- form.option.extra ?>" method="POST">
-<table>
-
-<? local myform = form.value
-
--- We redefine the list of tags from the model (iface_tags) because
--- the VIEW can choose the order to display the data. The Controller
--- does not care what order the data is presented.
-
--- In this case, we don do show "name"
-local tags = { "name", "comment", "method", "address", "netmask", "gateway",
- "hostname", "provider", "pre-up", "up", "down", "post-down", "cmd" }
-
-for i,v in pairs(tags) do
- local val = myform[v] ?>
-<dt><? if (val.label) then io.write(val.label) else io.write (v) end ?></dt>
- <? if val.name == "" then
- val.name = v
- end
-
- if val.type == "longtext" then
- val.cols = 60
- val.rows = 3
- end
-
- ?>
- <dd><?= html.form[val.type](val) ?></dd>
-</td></tr>
-<? end ?>
-</table>
-</form>
+<h1><?= form.label ?></h1>
+<?
+ local order = {"name", "comment", "auto", "family", "method", "pre-up", "up", "down", "post-down"}
+ displayform(form, order)
+?>
diff --git a/interfaces-editintfile-html.lsp b/interfaces-editintfile-html.lsp
new file mode 100644
index 0000000..4b1f80b
--- /dev/null
+++ b/interfaces-editintfile-html.lsp
@@ -0,0 +1,27 @@
+<? local form = ...
+require("viewfunctions")
+?>
+<?
+--[[ DEBUG INFORMATION
+io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
+io.write(html.cfe_unpack(form))
+io.write("</span>")
+--]]
+?>
+
+<h1>File Details</h1>
+<DL>
+<? displayitem(form.value.filename) ?>
+<? displayitem(form.value.filesize) ?>
+<? displayitem(form.value.mtime) ?>
+</DL>
+
+<h1><?= form.label ?></h1>
+<? if form.descr then ?><P CLASS='descr'><?= string.gsub(form.descr, "\n", "<BR>") ?></P><? end ?>
+<? if form.errtxt then ?><P CLASS='error'><?= string.gsub(form.errtxt, "\n", "<BR>") ?></P><? end ?>
+<form action="" method="POST">
+<textarea name="filecontent">
+<?= form.value.filecontent.value ?>
+</textarea>
+<DL><DT><input class="submit" type="submit" name="<?= form.option ?>" value="Save"></DT></DL>
+</form>
diff --git a/interfaces-model.lua b/interfaces-model.lua
index 57949a3..776cd6f 100644
--- a/interfaces-model.lua
+++ b/interfaces-model.lua
@@ -11,23 +11,63 @@ module (..., package.seeall)
-- directory for all we know) The public module functions are defined
-- further below
-local iface = { tags = { "name", "comment", "method", "address",
- "netmask", "gateway", "hostname", "provider",
- "pre-up", "up", "down", "post-down" },
- methods = { "dhcp", "static", "ppp", "loopback", "manual" },
- label = { ['name']="Interface names" ,
- ['comment']="Comments",
- ['method']="Method",
- ['address']="Address",
- ['netmask']="Netmask",
- ['gateway']="Gateway",
- ['hostname']="Hostname",
- ['provider']="Provider",
- ['pre-up']="'pre-up' actions",
- ['up']="'up' actions",
- ['down']="'down' actions",
- ['post-down']="'post-down' actions",
- },
+local iface = { tags = { comment = {type="longtext", label="Comments"},
+ auto = {type="boolean", value=false, label="Auto bring-up"},
+ name = {label="Interface Name"},
+ family = {type="select", label="Address Family", option={"inet", "ipx", "inet6"}},
+ ['pre-up'] = {type="longtext", label="'pre-up' actions"},
+ up = {type="longtext", label="'up' actions"},
+ down = {type="longtext", label="'down' actions"},
+ ['post-down'] = {type="longtext", label="'post-down' actions"} },
+ method_tag = {type="select", label="Method"},
+ family_methods = { inet = {"loopback", "static", "manual",
+ "dhcp", "bootp", "ppp", "wvdial"},
+ ipx = {"static", "dynamic"},
+ inet6 = {"loopback", "static", "manual", "v4tunnel"} },
+ method_options = {inet = {loopback = {},
+ static = {address = {label="Address"},
+ netmask = {label="Netmask"},
+ broadcast = {label="Broadcast address"},
+ network = {label="Network address"},
+ metric = {label="Routing metric"},
+ gateway = {label="Default gateway"},
+ pointopoint = {label="Point-to-point address"},
+ media = {label="Medium type"},
+ hwaddress = {label="Hardware address"},
+ mtu = {label="MTU size"} },
+ manual = {},
+ dhcp = {hostname = {label="Hostname"},
+ leasehours = {label="Preferred lease time (hours)"},
+ leasetime = {label="Preferred lease time (seconds)"},
+ vendor = {label="Vendor class identifier"},
+ client = {label="Client identifier"},
+ hwaddress = {label="Hardware address"} },
+ bootp = {bootfile = {label="Boot file"},
+ server = {label="Server address"},
+ hwaddr = {label="Hardware address"} },
+ ppp = {provider = {label="Provider name"} },
+ wvdial = {provider = {label="Provider name"} },
+ },
+ ipx = { static = {frame = {label="Ethernet frame type"},
+ netnum = {label="Network number"} },
+ dynamic = {frame = {label="Ethernet frame type"} },
+ },
+ inet6 ={loopback = {},
+ static = {address = {label="Address"},
+ netmask = {label="Netmask"},
+ gateway = {label="Default gateway"},
+ media = {label="Medium type"},
+ hwaddress = {label="Hardware address"},
+ mtu = {label="MTU size"} },
+ manual = {},
+ v4tunnel = {address = {label="Address"},
+ netmask = {label="Netmask"},
+ endpoint = {label="Endpoint address"},
+ ['local'] = {label="Local address"},
+ gateway = {label="Default gateway"},
+ ttl = {label="TTL setting"} },
+ },
+ },
-- lowlevel functions will insert file and array here
}
@@ -35,7 +75,7 @@ local iface = { tags = { "name", "comment", "method", "address",
-- Lowlevel functions - they do things directly to iface.
local filename = "/etc/network/interfaces"
iface.read_file = function ()
- iface.file = cfe { name=filename, filename=filename }
+ iface.file = cfe({ type="longtext", label=filename })
local file = io.open(filename)
local rc = false
if file then
@@ -50,44 +90,52 @@ end
iface.write_file = function ()
local rc = false
- local file = io.open ( iface.file.name, "w")
+ local file = io.open ( iface.file.label, "w")
if file then
file:write ( iface.file.value )
file:close()
rc = true
end
return rc
- end
+end
-function iface.iface_type ( )
+iface.iface_type = function (family, method)
local f = {}
- for k,v in pairs(iface.tags) do
- f[v] = cfe { name = v, label = (iface.label[v] or "") }
+ for name,table in pairs(iface.tags) do
+ f[name] = cfe(table)
end
+ f.family.value = family or ""
+ if family and iface.family_methods[family] then
+ f.method = cfe(iface.method_tag)
+ f.method.option = iface.family_methods[family]
+ f.method.value = method or ""
- for k,v in pairs ({"comment", "pre-up", "up", "down", "post-down"}) do
- f[v].type ="longtext"
+ if method and iface.method_options[family][method] then
+ for name,table in pairs(iface.method_options[family][method]) do
+ f[name] = cfe(table)
+ end
+ elseif method then
+ f.method.errtxt = "Invalid method"
+ end
+ elseif family then
+ f.family.errtxt = "Invalid family"
end
-
- f.method.type = "select"
- f.method.option = iface.methods
- return (f)
+
+ return cfe({ type="group", value=f, label="Interface description" })
end
-- return true or false + the index of iface.array matching "name"
-function iface.index (name)
- if name== nil or #name == 0 then
- return true, 0
- end
-
- if iface.array == nil then
- iface.unpack_interfaces ()
- end
+iface.index = function (name)
+ if name and #name > 0 then
+ if iface.array == nil then
+ iface.unpack_interfaces ()
+ end
- for k,v in ipairs(iface.array) do
- if name == v.name.value then
- return true, k
+ for k,v in ipairs(iface.array) do
+ if name == v.value.name.value then
+ return true, k
+ end
end
end
@@ -95,7 +143,7 @@ function iface.index (name)
end
-function iface.append ( self, value, prefix )
+iface.append = function (self, value, prefix)
self = self or ""
-- if we already have some values, then append a newline
if #self > 0 then self = self .. "\n" end
@@ -105,176 +153,254 @@ function iface.append ( self, value, prefix )
return self .. str
end
-function iface.expand ( self, prefix )
+iface.expand = function (self, prefix)
if #self == 0 then
return ""
end
-- force the string to end in a single linefeed
self = string.gsub (self, "\r", "")
self = string.gsub (self, "[\n]*$", "\n")
- local str = ""
- for line in string.gmatch ( self, ".-\n") do
+ local strings = {}
+ for line in string.gmatch(self, "(.-)\n") do
if #line > 0 then
- str = str .. prefix .. " " .. line
+ strings[#strings+1] = prefix .. " " .. line
end
end
- return str
+ return table.concat(strings, "\n")
end
-function iface.unpack_interfaces ()
+iface.unpack_interfaces = function ()
if iface.array == nil then
iface.read_file()
iface.array = {}
- end
-
- -- call it array so we don't have to call it iface.array everywhere
- local array = iface.array
- local count = 0
- array[count] = iface.iface_type()
-
- for line in string.gmatch ( iface.file.value, ".-\n") do
- -- strip leading spaces, tabs
- line = string.gsub (line, "^[%s]*", "")
- line = string.gsub (line, "\n*$", "")
- -- it can be #, auto, iface, or a parameter
- if string.match(line, "^#") then
- array[count].comment.value =
- iface.append(array[count].comment.value, line , "#%s*" )
- elseif string.match(line, "^auto") then
- -- do nothing
- elseif string.match(line, "^iface") then
- count = count + 1
- array[count] = iface.iface_type()
- -- iface <name> [inet | ipx] <method> -- we assume inet
- array[count].name.value,
- array[count].method.value =
- string.match(line, "%w+%s+(%w+)%s+%w+%s+(%w+)")
- else -- it must be some kind of parameter
- local param, val =
- string.match(line, "(%S+)%s*(.*)$")
- if (param) then
- if not (array[count][param]) then array[count][param] = {} end
- array[count][param].value =
- iface.append (array[count][param].value, val)
+ -- call it array so we don't have to call it iface.array everywhere
+ local array = iface.array
+ local comment = ""
+ local auto = {}
+
+ for line in string.gmatch ( iface.file.value, ".-\n") do
+ -- strip leading spaces, tabs
+ line = string.gsub (line, "^[%s]*", "")
+ line = string.gsub (line, "\n*$", "")
+ -- it can be #, auto, iface, or a parameter
+ if string.match(line, "^#") then
+ comment = iface.append(comment, line , "#%s*" )
+ elseif string.match(line, "^auto") then
+ local name = string.match(line, "auto%s+(%w+)")
+ auto[name] = true
+ elseif string.match(line, "^iface") then
+ local name, family, method = string.match(line, "%w+%s+(%w+)%s+(%w+)%s+(%w+)")
+ array[#array + 1] = iface.iface_type(family, method)
+ local interface = array[#array].value
+ interface.comment.value = comment
+ comment = ""
+ -- iface <name> [inet | ipx] <method> -- we assume inet
+ interface.name.value = name
+ elseif #array then
+ -- it must be some kind of parameter
+ local param, val =
+ string.match(line, "(%S+)%s*(.*)$")
+ if (param) then
+ local interface = array[#array].value
+ if not (interface[param]) then
+ interface[param] = cfe({label=param, errtxt = "Unknown parameter"})
+ end
+ interface[param].value =
+ iface.append (interface[param].value, val)
+ end
+ end
+ end
+ for i,int in ipairs(array) do
+ if auto[int.value.name.value] then
+ int.value.auto.value = true
end
end
end
- -- now move the comments to go with the interface
- for n = count,1,-1 do
- array[n].comment.value = array[n-1].comment.value
- end
-
- return array
+ return cfe({ type="list", value=iface.array, label="Interfaces" })
end
-function iface.pack_interfaces()
+iface.pack_interfaces = function ()
local str = ""
- for n = 1,#iface.array,1 do
- local me = iface.array[n]
- for k,v in pairs (iface.tags) do
- if v == "comment" then
- str = str .. "\n" .. iface.expand ( me[v].value, "#")
- elseif v == "method" then
- str = str .. string.format ("\nauto %s\niface %s inet %s\n",
- me.name.value, me.name.value,
- me.method.value)
- elseif v == "name" then
- -- nothing
- else
- str = str .. iface.expand( me[v].value, "\t" .. v)
+ local strings = {}
+ for n,int in ipairs(iface.array) do
+ local me = int.value
+ if me.comment.value ~= "" then
+ strings[#strings+1] = iface.expand(me.comment.value, "#")
+ end
+ if me.auto.value then
+ strings[#strings+1] = "auto " .. me.name.value
+ end
+ strings[#strings+1] = string.format("iface %s %s %s", me.name.value,
+ me.family.value, me.method.value)
+ for name,entry in pairs(me) do
+ if name~="comment" and name~="name" and name~="family" and name~="method" and name~="auto"
+ and entry.value ~= "" then
+ strings[#strings+1] = iface.expand(entry.value, "\t"..name)
end
end
+ strings[#strings+1] = ""
end
- return str
+
+ return table.concat(strings, "\n")
end
-function iface.commit()
+iface.commit = function ()
iface.file.value = iface.pack_interfaces()
return iface.write_file()
end
-function iface.add_after ( name, def )
- -- if the new if.name is already in the table, then fail
- local rc, idx = iface.index(def.name.value)
- if idx > 0 then
- def.name.errtxt = "This interface is already defined"
- return false, def
+iface.add_after = function (def, name)
+ -- if the new def.name is already in the table, then fail
+ local rc, idx = iface.index(def.value.name.value)
+ if rc == true then
+ def.value.name.errtxt = "This interface is already defined"
+ rc = false
+ else
+ rc, def = iface.validate( def )
end
- -- if the name to insert after doesn't exist, just fail
- rc, idx = iface.index(name)
- if rc == false then
- return false, def
+ -- if the name to insert after doesn't exist, just add it to the end
+ if rc then
+ rc, idx = iface.index(name)
+ if rc == false then
+ idx = #iface.array
+ end
+ table.insert( iface.array, idx+1, def )
+ rc = iface.commit()
end
- rc, def = iface.validate (def)
if rc == false then
- return rc, def
+ def.errtxt = "Failed to create interface"
end
-
- table.insert( iface.array, idx+1, def )
- return iface.commit() , def
+
+ return def
end
-function iface.read ( name )
- -- if the name is blank, then return an empty def
- local rc, idx = iface.index(name or "")
- if name == nil or #name == 0 or rc == false then
- return rc, iface.iface_type()
+iface.read = function (name)
+ -- if the name is blank, then return nil
+ iface.unpack_interfaces()
+ local rc, idx = iface.index(name)
+ if rc == false then
+ return nil
end
- return iface.commit(), iface.array[idx]
+ return iface.array[idx]
end
-function iface.update ( def)
+iface.update = function (def)
-- if the def by that name doesn't exist, fail
- local rc, idx = iface.index(def.name.value or "" )
- if idx == 0 then
- def.name.errtxt = "This is an invalid interface name"
- return false, def
+ local rc, idx = iface.index(def.value.name.value or "" )
+ if rc == false then
+ def.value.name.errtxt = "This is an invalid interface name"
+ else
+ rc, def = iface.validate ( def )
end
-
- rc, def = iface.validate ( def )
+
+ if rc then
+ iface.array[idx] = def
+ rc = iface.commit()
+ end
+
if rc == false then
- return rc, def
+ def.errtxt = "Failed to update interface"
end
- iface.array[idx] = def
- return iface.commit(), def
+ return def
end
-function iface.delete (name )
- local rc, idx = iface.index(name or "" )
- if idx == 0 then
- rc = false
- else
+iface.delete = function (name)
+ local rc, idx = iface.index(name)
+ if rc then
table.remove (iface.array, idx )
+ rc = iface.commit()
+ end
+ local value
+ if rc then
+ value = "Interface deleted"
+ else
+ value = "Interface not found"
end
- return iface.commit()
+ return cfe({ value=value, label="Delete result" })
end
-iface.validate = function ( def )
- if #def.name.value == 0 then
- iface.name.errtxt = "The interface must have a name"
- end
- def.method.errtxt = "Method specified is invalid"
- for k,v in pairs (iface.methods) do
- if def.method.value == v then
- def.method.errtxt = ""
+iface.validate = function (def)
+ local success = true
+ -- since the structure is different depending on the family and method ...
+ local method = ""
+ if def.value.method then method = def.value.method.value end
+ local newdef = iface.iface_type(def.value.family.value, method)
+ for name,option in pairs(newdef.value) do
+ if option.errtxt then
+ success = false
+ end
+ if def.value[name] then
+ option.value = def.value[name].value
end
end
+
+ -- Now, start to validate (family and method already validated)
+ if #newdef.value.name.value == 0 then
+ newdef.value.name.errtxt = "The interface must have a name"
+ success = false
+ end
-- More validation tests go here ---
--
- local rc = true
- for k,v in pairs(def) do
- if def[k].errtxt then result = false end
+
+ if not success then
+ newdef.errtxt = "Failed validation"
+ end
+
+ return success, newdef
+end
+
+iface.ifup = function (name)
+ name = name or ""
+ local cmd = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin ifup "..name
+ local f = io.popen(cmd)
+ local cmdresult = f:read("*a")
+ f:close()
+
+ if cmdresult == "" then
+ cmdresult = "Interface up"
end
- return result, def
+ return cfe({ type="longtext", value=cmdresult, label="ifup "..name })
+end
+
+iface.ifdown = function (name)
+ name = name or ""
+ local cmd = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin ifdown "..name
+ local f = io.popen(cmd)
+ local cmdresult = f:read("*a")
+ f:close()
+
+ if cmdresult == "" then
+ cmdresult = "Interface down"
+ end
+
+ return cfe({ type="longtext", value=cmdresult, label="ifdown "..name })
+end
+
+iface.ipaddr = function ()
+ local cmd = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin ip addr"
+ local f = io.popen(cmd)
+ local cmdresult = f:read("*a")
+ f:close()
+
+ return cfe({ type="longtext", value=cmdresult, label="ip addr" })
+end
+
+iface.iproute = function ()
+ local cmd = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin ip route"
+ local f = io.popen(cmd)
+ local cmdresult = f:read("*a")
+ f:close()
+
+ return cfe({ type="longtext", value=cmdresult, label="ip route" })
end
-------------------------------------------------------------------------------
@@ -285,22 +411,54 @@ get_all_interfaces = iface.unpack_interfaces
get_iface_by_name = iface.read
-create_iface_by_name = iface.add_after
+get_iface = iface.iface_type
-update_iface_by_name = function (def, name )
- -- make sure name we think we are updating is name we are updating
- def.name.value = name
- return iface.update (def)
-end
+create_iface = iface.add_after
+
+update_iface = iface.update
delete_iface_by_name = iface.delete
-get_status = function ()
- local status = {}
- status.interfacesfile = cfe({
- name="interfacesfile",
+ifup_by_name = iface.ifup
+
+ifdown_by_name = iface.ifdown
+
+get_status = function ()
+ local interfacesfile = cfe({
label="Interfaces file",
value=filename,
})
- return status
+ if not fs.is_file(filename) then
+ interfacesfile.errtxt = "File not found"
+ end
+ return cfe({ type="group", value={filename=interfacesfile, ipaddr=iface.ipaddr(), iproute=iface.iproute()}, label="Status" })
+end
+
+get_file = function ()
+ if not iface.file then
+ iface.read_file()
+ end
+
+ local file = cfe({ value=filename, label="Interfaces file" })
+ local filesize = cfe({ value="0", label="File size" })
+ local mtime = cfe({ value="---", label="File date" })
+ local filedetails = fs.stat(filename)
+ if filedetails then
+ filesize.value = filedetails.size
+ mtime.value = filedetails.mtime
+ else
+ file.errtxt = "File not found"
+ end
+
+ return cfe({ type="group", value={filename=file, filecontent=iface.file, filesize=filesize, mtime=mtime}, label="Interfaces file details" })
+end
+
+write_file = function (newfile)
+ if not iface.file then
+ iface.read_file()
+ end
+ iface.file.value = newfile.value.filecontent.value
+ iface.write_file()
+
+ return get_file()
end
diff --git a/interfaces-read-html.lsp b/interfaces-read-html.lsp
index 505cbf6..33ab30f 100644
--- a/interfaces-read-html.lsp
+++ b/interfaces-read-html.lsp
@@ -1,47 +1,67 @@
-<? local form = ...
+<? local view, viewlibrary, pageinfo, session = ...
require("viewfunctions")
?>
<?
--[[ DEBUG INFORMATION
io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
-io.write(html.cfe_unpack(form))
+io.write(html.cfe_unpack(view))
io.write("</span>")
--]]
?>
-<H1>SYSTEM INFO</H1>
+<? showoption = function(option)
+ if option.errtxt or option.value ~= "" then ?>
+ <TR><TD WIDTH='120px' STYLE='font-weight:bold;border:none;'><?= option.label ?></TD>
+ <TD STYLE='border:none;'<? if option.errtxt then io.write("class='error'") end ?>>
+ <?= string.gsub(tostring(option.value), "\n", "<BR>") ?>
+ <? if option.errtxt then io.write("<BR>"..option.errtxt) end ?>
+ </TD></TR>
+ <? end ?>
+<? end ?>
+
+<? if view.value.cmdresult then ?>
+<H1>Command Result</H1>
<DL>
-<?
-local myform = form.status
-local tags = { "interfacesfile" }
-displayinfo(myform,tags,"viewonly")
-?>
+<?= view.value.cmdresult.value ?>
</DL>
+<? end ?>
+
+<? if viewlibrary and viewlibrary.dispatch_component then
+ viewlibrary.dispatch_component("status")
+end ?>
-<H2>Configured interfaces</H2>
+<H1>Configured interfaces</H1>
<DL>
-<?
-local myform = form.iface
-for k,v in pairs(myform) do
- local myform=v
- if (myform.name.value ~= "") then
- io.write("<DT><IMG SRC='/skins/static/tango/16x16/devices/network-wired.png' width='16' height='16'> " .. (myform.name.value or '') .. "</DT><DD>")
- io.write("<TABLE STYLE='margin-bottom:10px'>")
--- io.write("<TR><TD COLSPAN=2 STYLE='font-weight:bold;border:none;'><IMG SRC='/skins/static/tango/16x16/devices/network-wired.png' width='16' height='16'> " .. (myform.name.value or '') .. "</TD></TR>")
+<? for i,entry in ipairs(view.value) do
+ local interface = entry.value ?>
+ <DT><IMG SRC='/skins/static/tango/16x16/devices/network-wired.png' width='16' height='16'> <?= interface.name.value ?></DT><DD>
+ <TABLE STYLE='margin-bottom:10px'>
- local tags = {"method", "address", "netmask", "gateway", "provider", "hostname", "pre-up", "up", "down", "post-down", "comment", }
- for k1,v1 in pairs(tags) do
- if (myform[v1]['value'] ~= "") then
- io.write("<TR><TD WIDTH='120px' STYLE='font-weight:bold;border:none;'>" .. myform[v1]['label'] .. "</TD>")
- io.write("<TD STYLE='border:none;'>" .. string.gsub(myform[v1]['value'], "\n", "<BR>") .. "</TD></TR>")
- end
+ <?
+ showoption(interface.family)
+ if interface.method then showoption(interface.method) end
+ for name,option in pairs(interface) do
+ if name~="name" and name~="family" and name~="method" then
+ showoption(option)
end
- io.write("</TABLE>")
- end
-
-end
-io.write("</DD>")
-?>
+ end ?>
+ <TR>
+ <? if session.permissions.interfaces.update then ?>
+ <A HREF='update?name=<?= interface.name.value ?>'>Edit </A>
+ <? end
+ if session.permissions.interfaces.delete then ?>
+ <A HREF='delete?name=<?= interface.name.value ?>'>Delete </A>
+ <? end
+ if session.permissions.interfaces.ifup then ?>
+ <A HREF='ifup?name=<?= interface.name.value ?>'>ifup </A>
+ <? end
+ if session.permissions.interfaces.ifdown then ?>
+ <A HREF='ifdown?name=<?= interface.name.value ?>'>ifdown </A>
+ <? end ?>
+ </TR>
+ </TABLE>
+<? end ?>
+</DD>
</DL>
<?
@@ -51,5 +71,3 @@ io.write(html.cfe_unpack(form))
io.write("</span>")
--]]
?>
-
-
diff --git a/interfaces-status-html.lsp b/interfaces-status-html.lsp
new file mode 100644
index 0000000..52237b1
--- /dev/null
+++ b/interfaces-status-html.lsp
@@ -0,0 +1,27 @@
+<? local view = ... ?>
+<?
+--[[ DEBUG INFORMATION
+io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
+io.write(html.cfe_unpack(view))
+io.write("</span>")
+--]]
+?>
+
+<H1>SYSTEM INFO</H1>
+<DL>
+<?
+displayitem(view.value.filename)
+displayitem(view.value.ipaddr)
+displayitem(view.value.iproute)
+?>
+</DL>
+
+<?
+--[[ DEBUG INFORMATION
+io.write("<H1>DEBUGGING</H1><span style='color:red'><H2>DEBUG INFO: CFE</H2>")
+io.write(html.cfe_unpack(form))
+io.write("</span>")
+--]]
+?>
+
+
diff --git a/interfaces-update-html.lsp b/interfaces-update-html.lsp
index 5c33872..453afe9 100644
--- a/interfaces-update-html.lsp
+++ b/interfaces-update-html.lsp
@@ -9,37 +9,9 @@ io.write("</span>")
--]]
?>
-<h1>Update Interface <?= form.value.name.value ?></h1>
-
-<form action="<?= form.option.script .. "/" .. form.option.prefix ..
- form.option.controller .. "/" .. form.option.action ..
- form.option.extra ?>" method="POST">
-
-<DL>
-<?
-
--- We redefine the list of tags from the model (iface_tags) because
--- the VIEW can choose the order to display the data. The Controller
--- does not care what order the data is presented.
-
--- In this case, we don't show "name" - since its already known
-local tags = { "comment", "method", "address", "netmask", "gateway",
- "hostname", "provider", "pre-up", "up", "down", "post-down", "cmd" }
-local myform = form.value
-displayinfo(myform,tags)
--- Add the 'name' filed (but don't show it because it's {type='hidden'}
-io.write(html.form[myform.name.type](myform.name))
-?>
-</DL>
-
-<H2>Other actions</H2>
-<DL>
-<?
-local tags = { "cmddelete", }
-local myform = form.value
-displayinfo(myform,tags)
+<h1><?= form.label ?> - <?= form.value.name.value ?></h1>
+<?
+ form.value.name.contenteditable = false
+ local order = {"name", "comment", "auto", "family", "method", "pre-up", "up", "down", "post-down"}
+ displayform(form, order)
?>
-</DL>
-
-</form>
-
diff --git a/interfaces.menu b/interfaces.menu
index 9bf62b2..8865442 100644
--- a/interfaces.menu
+++ b/interfaces.menu
@@ -1,5 +1,5 @@
# Prefix and controller are already known at this point
# Cat Group Tab Action
System Interfaces Status read
-System Interfaces Edit_interfaces config
System Interfaces Create_New_interface create
+System Interfaces Expert editintfile