summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Havela <mika.havela@gmail.com>2008-04-02 07:04:27 +0000
committerMika Havela <mika.havela@gmail.com>2008-04-02 07:04:27 +0000
commitafbf9fc47c20d102f516261679b3653bd05fd9fc (patch)
treea0de81813663e16ba93fc40c294e64d76b639ff5
downloadacf-quagga-afbf9fc47c20d102f516261679b3653bd05fd9fc.tar.bz2
acf-quagga-afbf9fc47c20d102f516261679b3653bd05fd9fc.tar.xz
First commit on quagga. Don't expect anything to work.v0.1
git-svn-id: svn://svn.alpinelinux.org/acf/quagga/trunk@874 ab2d0c66-481e-0410-8bed-d214d4d58bed
-rw-r--r--Makefile47
-rw-r--r--config.mk10
-rw-r--r--quagga-controller.lua109
-rw-r--r--quagga-model.lua187
-rw-r--r--quagga-status-html.lsp95
-rw-r--r--quagga.menu3
6 files changed, 451 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b5e68a3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,47 @@
+APP_NAME=quagga
+PACKAGE=acf-$(APP_NAME)
+VERSION=0.1
+
+APP_DIST=\
+ quagga-controller.lua \
+ quagga-model.lua \
+ quagga-status-html.lsp \
+ quagga.menu \
+
+
+EXTRA_DIST=README Makefile config.mk
+
+DISTFILES=$(APP_DIST) $(EXTRA_DIST)
+
+TAR=tar
+
+P=$(PACKAGE)-$(VERSION)
+tarball=$(P).tar.bz2
+install_dir=$(DESTDIR)/$(appdir)/$(APP_NAME)
+
+all:
+clean:
+ rm -rf $(tarball) $(P)
+
+dist: $(tarball)
+
+install:
+ mkdir -p "$(install_dir)"
+ cp -a $(APP_DIST) "$(install_dir)"
+
+$(tarball): $(DISTFILES)
+ rm -rf $(P)
+ mkdir -p $(P)
+ cp $(DISTFILES) $(P)
+ $(TAR) -jcf $@ $(P)
+ rm -rf $(P)
+
+# target that creates a tar package, unpacks is and install from package
+dist-install: $(tarball)
+ $(TAR) -jxf $(tarball)
+ $(MAKE) -C $(P) install DESTDIR=$(DESTDIR)
+ rm -rf $(P)
+
+include config.mk
+
+.PHONY: all clean dist install dist-install
diff --git a/config.mk b/config.mk
new file mode 100644
index 0000000..45f4d21
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,10 @@
+prefix=/usr
+datadir=${prefix}/share
+sysconfdir=${prefix}/etc
+localstatedir=${prefix}/var
+acfdir=${datadir}/acf
+wwwdir=${acfdir}/www
+cgibindir=${acfdir}/cgi-bin
+appdir=${acfdir}/app
+acflibdir=${acfdir}/lib
+sessionsdir=${localstatedir}/lib/acf/sessions
diff --git a/quagga-controller.lua b/quagga-controller.lua
new file mode 100644
index 0000000..f59ac0a
--- /dev/null
+++ b/quagga-controller.lua
@@ -0,0 +1,109 @@
+module(..., package.seeall)
+
+-- This is the object/text used when we want to add a new record
+
+require("format")
+
+local newrecordtxt = "[New]"
+
+local list_redir = function (self)
+ self.conf.action = "status"
+ self.conf.type = "redir"
+ error (self.conf)
+end
+
+mvc = {}
+mvc.on_load = function(self, parent)
+ if (self.worker[self.conf.action] == nil ) or ( self.conf.action == "init" ) then
+ self.worker[self.conf.action] = list_redir(self)
+ end
+end
+
+local function displaycmdmanagement(disablestart,disablestop,disablerestart)
+ -- Add a management buttons
+ local management = {}
+ management.start = cfe({ name="cmdmanagement",
+ label="Program control-panel",
+ value="Start",
+ type="submit",
+ })
+ management.stop = cfe({ name="cmdmanagement",
+ label="Program control-panel",
+ value="Stop",
+ type="submit",
+ })
+ management.restart = cfe({ name="cmdmanagement",
+ label="Program control-panel",
+ value="Restart",
+ type="submit",
+ })
+
+ -- Disable management buttons based on if the process is running or not
+ if (disablestart) then management.start.disabled = "yes" end
+ if (disablestop) then management.stop.disabled = "yes" end
+ if (disablerestart) then management.restart.disabled = "yes" end
+
+ return management
+end
+
+-- ################################################################################
+-- PUBLIC FUNCTIONS
+function status(self)
+ return { status=self.model.getstatus() }
+end
+
+expert = function (self)
+ local modifications = self.clientdata.filecontent or ""
+ if ( self.clientdata.cmdsave ) then
+ modifications = self.model:update_filecontent(modifications)
+ end
+ local url = ENV["SCRIPT_NAME"] .. self.conf.prefix .. self.conf.controller
+
+ -- Start/Stop/Restart process
+ local cmdmanagement
+ if ( self.clientdata.cmdmanagement) then
+ cmdmanagement = cfe({
+ name="cmdmanagement",
+ label="Previous action result",
+ action=cfe({
+ name="cmdmanagement",
+ value=string.lower(self.clientdata.cmdmanagement), -- This row contains start/stop/restart (one of these commands)
+ }),
+ })
+ local actionresult, cmdmanagement = self.model:startstop_service( cmdmanagement.action )
+ end
+
+ local status=self.model.getstatus()
+ local file = self.model:get_filedetails()
+
+ -- Add buttons
+ file.cmdsave = cfe ({
+ name="cmdsave",
+ label="Apply settings",
+ value="Apply",
+ type="submit",
+ })
+ if (self.clientdata.cmdsave) then
+ file.cmdsave.descr="* Changes has been saved!"
+ end
+
+
+ -- Management buttons
+ local disablestart,disablestop,disablerestart
+ -- Disable management buttons based on if the process is running or not
+ if (string.lower(status.status.value) == "enabled" ) then
+ disablestart = "yes"
+ else
+ disablestop = "yes"
+ end
+ -- Display management buttons
+ management = displaycmdmanagement(disablestart,disablestop,disablerestart)
+
+ return ( {
+ status = status,
+ file = file,
+ modifications = modifications,
+ management = management,
+ cmdmanagement = cmdmanagement,
+ url = url, } )
+end
diff --git a/quagga-model.lua b/quagga-model.lua
new file mode 100644
index 0000000..c9ef9d1
--- /dev/null
+++ b/quagga-model.lua
@@ -0,0 +1,187 @@
+module(..., package.seeall)
+
+require("fs")
+require("procps")
+require("getopts")
+require("format")
+require("daemoncontrol")
+require("validator")
+
+local configfile = "/etc/quagga/bgpd.conf"
+local processname = "bgpd"
+local baseurl = "/etc/quagga/"
+
+local descr = {
+ Type = {
+ ['incomplete']="The protocol address is being resolved",
+ ['negative']="This protocol address is not available",
+ ['cached']="Protocol address was resolved successfully",
+ ['route']="This is a dynamic shortcut",
+ ['dynamic']="This entry is from a node that connected to us",
+ ['local']="Local interface address",
+ ['static']="Static mapping from configuration file (e.g. address of core)",
+ },
+ Flags= {
+-- ['up']="Connection is fully usable",
+ ['lower-up']="ipsec connections is up, but registration is not yet done",
+ },
+}
+
+local function get_version()
+ local cmd_output_result, cmd_output_error
+ local cmd = "/sbin/apk_version -vs " .. processname .." 2>/dev/null"
+ local f = io.popen( cmd )
+ local cmdresult = f:read("*l")
+ if (cmdresult) and (#cmdresult > 0) then
+ cmd_output_result = string.match(cmdresult,"^%S*") or "Unknown"
+ else
+ cmd_output_error = "Program not installed"
+ end
+ f:close()
+ return cmd_output_result,cmd_output_error
+end
+
+local function autostarts()
+ local cmd_output_result, cmd_output_error
+ local cmd = "/sbin/rc_status | egrep '^S' | egrep '" .. processname .."' 2>/dev/null"
+ local f = io.popen( cmd )
+ local cmdresult = f:read("*a")
+ if (cmdresult) and (#cmdresult > 0) then
+ cmd_output_result = "Process will autostart at next boot (at sequence '" .. string.match(cmdresult,"^%a+(%d%d)") .. "')"
+ else
+ cmd_output_error = "Not programmed to autostart"
+ end
+ f:close()
+ return cmd_output_result,cmd_output_error
+end
+
+local function opennhrpctl_show()
+ local cmd_output_result={}
+ local cmd_output_result_table={}
+ local cmd_output_error, opennhrpstatus
+ local cmd = "/usr/sbin/opennhrpctl show 2>/dev/null"
+ local f = io.popen( cmd )
+ for line in f:lines() do
+ if string.find(line, "^Status:") then
+ opennhrpstatus=line
+ else
+ table.insert(cmd_output_result, line)
+ end
+ end
+ f:close()
+ local cnt = 0
+ for k,v in pairs(cmd_output_result) do
+ if string.find(v,"^Interface") then
+ cnt = cnt + 1
+ cmd_output_result_table[cnt] = {}
+ end
+ if ( cnt > 0 ) and (v ~= "") then
+ local k = string.match(v,"^(.-):%s?.*")
+ cmd_output_result_table[cnt][k]=cfe({value=string.match(v,"^.-:%s?(.*)")})
+ local statusdescription = string.lower(string.match(v,"^.-:%s?(.*)"))
+ if (type(descr[k]) == "table") then
+ cmd_output_result_table[cnt][k]['descr']=descr[k][statusdescription]
+ end
+ end
+ end
+
+ local peers_list = {}
+ for k,v in pairs(cmd_output_result_table) do
+ if (v.Interface.value) and not (peers_list[v.Interface.value]) then
+ peers_list[v.Interface.value] = {}
+ end
+ table.insert(peers_list[v.Interface.value], v)
+ end
+
+ return peers_list,opennhrpstatus,cmd_output_error
+end
+
+
+function process_status_text(procname)
+ local t = procps.pidof(procname)
+ if (t) and (#t > 0) then
+ return "Enabled"
+ else
+ return "Disabled"
+ end
+end
+
+-- ################################################################################
+-- PUBLIC FUNCTIONS
+
+function startstop_service ( self, action )
+ local cmd = action.value
+ local cmdresult,cmdmessage,cmderror,cmdaction = daemoncontrol.daemoncontrol(processname, cmd)
+ action.descr=cmdmessage
+ action.errtxt=cmderror
+ -- Reporting back (true|false, the original acition)
+ return cmdresult,action
+end
+
+function getstatus()
+ local status = {}
+ local value, errtxt = get_version()
+ status.version = cfe({ name = "version",
+ label="Program version",
+ value=value,
+ errtxt=errtxt,
+ })
+
+ status.status = cfe({ name="status",
+ label="Program status",
+ value=process_status_text(processname),
+ })
+ local autostart_sequense, autostart_errtxt = autostarts()
+ status.autostart = cfe({ name="autostart",
+ label="Autostart sequence",
+ value=autostart_sequense,
+ errtxt=autostart_errtxt,
+ })
+
+ local opennhrpctl_show, opennhrpctl_status = opennhrpctl_show()
+ status.stats = cfe({ name="stats",
+ label="Programstatus reports",
+ value=opennhrpctl_status,
+ })
+
+ status.show = cfe({ name="show",
+ label="Peers",
+ option=opennhrpctl_show,
+ })
+
+ return status
+end
+
+function get_filedetails()
+ local path = configfile
+ local filedetails = fs.stat(path)
+ local file = {}
+
+ file["filename"] = cfe({
+ name="filename",
+ label="File name",
+ value=path,
+ })
+ file["filesize"] = cfe({
+ name="filesize",
+ label="File size",
+ value=filedetails.size or 0,
+ })
+ file["mtime"] = cfe({
+ name="mtime",
+ label="File date",
+ value=filedetails.mtime or "---",
+ })
+ file["filecontent"] = cfe({
+ type="longtext",
+ name="filecontent",
+ label="File content",
+ value=fs.read_file(path),
+ })
+ return file
+end
+function update_filecontent (self, modifications)
+ local path = configfile
+ local file_result,err = fs.write_file(path, format.dostounix(modifications))
+ return file_result
+end
diff --git a/quagga-status-html.lsp b/quagga-status-html.lsp
new file mode 100644
index 0000000..765de12
--- /dev/null
+++ b/quagga-status-html.lsp
@@ -0,0 +1,95 @@
+<? local form = ... ?>
+<?
+--[[ 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>")
+--]]
+?>
+
+<?
+function informationform(myform,tags)
+ for k,v in pairs(tags) do
+ if (myform[v]) then
+ local val = myform[v]
+ io.write("\t<DT")
+ if (#val.errtxt > 0) then io.write(" class='error'") end
+ io.write(">" .. val.label .. "</DT>\n")
+
+ io.write("\t\t<DD>" .. val.value .. "\n")
+ if (val.descr) and (#val.descr > 0) then io.write("\t\t<P CLASS='descr'>" .. string.gsub(val.descr, "\n", "<BR>") .. "</P>\n") end
+ if (#val.errtxt > 0) then io.write("\t\t<P CLASS='error'>" .. string.gsub(val.errtxt, "\n", "<BR>") .. "</P>\n") end
+ io.write("\t\t</DD>\n")
+ end
+ end
+end
+?>
+
+<H1>SYSTEM INFO</H1>
+<DL>
+<?
+local myform = form.status
+local tags = { "status", "version", "autostart", }
+informationform(myform,tags)
+?>
+</DL>
+
+<H2>PROGRAM SPECIFIC OPTIONS/INFORMATION</H2>
+<DL>
+<?
+
+local myform = form.status.show
+io.write("\t<DT")
+if (#myform.errtxt > 0) then io.write(" class='error'") end
+io.write(">" .. myform.label .. "</DT>\n")
+io.write("\t\t<DD>\n")
+for k,v in pairs(myform.option or {}) do
+ io.write("\t\t\t<TABLE STYLE='margin-bottom:10px;'>")
+ io.write("\n\t\t\t<TR><TD STYLE='font-weight:bold;'><IMG SRC='/static/tango/16x16/places/network-server.png' width='16' height='16' alt> " .. k .. "</TD><TD></TD></TR>\n")
+ for k1,v1 in pairs(v) do
+ io.write("\n\t\t\t<TR STYLE='padding-bottom:10px;'><TD WIDTH='150px' STYLE='font-weight:bold;padding-left:20px;'><IMG SRC='/static/tango/16x16/status/")
+
+ if (v1) and (string.lower(v1['Type']['value']) == "incomplete") then
+ io.write("network-error")
+ elseif (v1) and (string.lower(v1['Type']['value']) == "negative") then
+ io.write("network-offline")
+ elseif (v1) and (string.lower(v1['Flags']['value']) == "up") then
+ io.write("network-idle")
+ elseif (v1) and (string.lower(v1['Flags']['value']) == "used up") then
+ io.write("network-transmit-receive")
+ elseif (v1) and (string.lower(v1['Flags']['value']) == "used up") then
+ io.write("network-offline")
+ else
+ io.write("network-error")
+ end
+ io.write(".png' width='16' height='16' title='" .. (v1['Type']['descr'] or "") .. "'> " .. v1["Protocol-Address"]['value'] .. "</TD><TD STYLE='font-weight:bold;'></TD></TR>\n")
+ for k2,v2 in pairs(v1) do
+
+---[[
+ if (k2) and not ((string.lower(k2) == "protocol-address") or
+ (string.lower(k2) == "interface")) then
+ io.write("<TR><TD STYLE='font-weight:bold;padding-left:40px;'>"..k2.."</TD><TD>"..v2['value'])
+ if (v2['descr']) and (#v2['descr'] > 0) then
+ io.write(" <I>(" .. (v2['descr'] or "") .. ")</I>")
+ end
+ io.write("</TD></TR>\n")
+ end
+--]]
+ end
+
+ end
+
+ io.write("\t\t\t</TABLE>")
+end
+io.write("\t\t</DD>\n")
+?>
+</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/quagga.menu b/quagga.menu
new file mode 100644
index 0000000..f999729
--- /dev/null
+++ b/quagga.menu
@@ -0,0 +1,3 @@
+#CAT GROUP/DESC TAB ACTION
+Networking 46BGP Status status
+