diff options
author | Ted Trask <ttrask01@yahoo.com> | 2008-05-30 18:37:19 +0000 |
---|---|---|
committer | Ted Trask <ttrask01@yahoo.com> | 2008-05-30 18:37:19 +0000 |
commit | a280c3b1faa2847b6d4f850a55d0cd4ea8453283 (patch) | |
tree | 762cd65291ba792b83e462f746e41b7381bb9d66 | |
parent | 6c63347a6ae2f25de2bf8cf9aea93ea31a786418 (diff) | |
download | acf-alpine-baselayout-a280c3b1faa2847b6d4f850a55d0cd4ea8453283.tar.bz2 acf-alpine-baselayout-a280c3b1faa2847b6d4f850a55d0cd4ea8453283.tar.xz |
Updated interfaces to use new cfe model, add more iface families, add more flexibility to editing, show ip status, bring up/down interfaces, and general cleanup.
git-svn-id: svn://svn.alpinelinux.org/acf/alpine-baselayout/trunk@1191 ab2d0c66-481e-0410-8bed-d214d4d58bed
-rw-r--r-- | alpine-baselayout.roles | 6 | ||||
-rw-r--r-- | interfaces-controller.lua | 194 | ||||
-rw-r--r-- | interfaces-create-html.lsp | 49 | ||||
-rw-r--r-- | interfaces-editintfile-html.lsp | 27 | ||||
-rw-r--r-- | interfaces-model.lua | 478 | ||||
-rw-r--r-- | interfaces-read-html.lsp | 80 | ||||
-rw-r--r-- | interfaces-status-html.lsp | 27 | ||||
-rw-r--r-- | interfaces-update-html.lsp | 38 | ||||
-rw-r--r-- | interfaces.menu | 2 |
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 |