class HaproxyStats: socket_path = "/var/lib/haproxy/stats" ssh = None def __init__(self, host): self.ssh = Ssh(host) def getStats(self): stats = {} com = "echo 'show stat' | socat stdio unix-connect:" + self.socket_path (ret, content) = self.ssh.commandAsRoot(com) if ret == 0 and content: lines = content.splitlines() params = lines[0].strip("# ").split(",") for i in range(1, len(lines)): cols = lines[i].split(",") values = {} for j in range(0, len(cols)): if params[j]: values[params[j]] = cols[j] name = cols[0] + "/" + cols[1] stats[name] = values return stats def socketCommand(self, com): com = "echo '" + com + "' | socat stdio unix-connect:" + self.socket_path (ret, content) = self.ssh.commandAsRoot(com) if ret == 0: if content: return content return "[comannd sent]" return "[socket command error]: " + content
class IptablesStats(): tables = {} ssh = None forward_chain = None interfaces = [] message = "" def __init__(self, host, stat_str): self.ssh = Ssh(host) self.tables = self.getTables(stat_str) self.getInterfaces() self.forward_chain = self.getChain("FORWARD") def isTableHeader(self,key): if key == "table:" or key == "Table:" or key == "テーブル:": return True return False def getMessage(self): return self.message; def getTables(self,stat_str): lines = stat_str.splitlines() tables = {} tablename = "none" chainname = "" for line in lines: columns = line.strip().split() if len(columns) == 0: continue # label if columns[0] == "num": continue if self.isTableHeader(columns[0]): tablename = columns[1] tables[tablename] = iptables_table() tables[tablename].chains = {} continue if columns[0] == "Chain": chainname = columns[1] tables[tablename].chains[chainname] = iptables_chain() tables[tablename].chains[chainname].policy = columns[3].strip("()") tables[tablename].chains[chainname].rules = [] continue # the line must be a rule: if len(columns) >= 6: rule = iptables_rule() rule.num = columns[0] rule.target = columns[1] rule.prot = columns[2] rule.opt = columns[3] rule.source = columns[4] rule.destination = columns[5] if len(columns) >= 7: for i in range(6, len(columns)): if rule.misc: rule.misc += " " rule.misc += columns[i] tables[tablename].chains[chainname].rules.append(rule) return tables def octet2int(self, ip): intIp = [] for oct in ip.split('.'): intIp.append(int(oct)) return intIp def mask2Bits(self, mask): intMask = self.octet2int(mask) bits = 0 for i in range(0, len(intMask)): binary = bin(intMask[i]) bits += len(binary.strip('0b')) return bits def bits2Mask(self, bits): b = bits mask = "" for i in range(0, 4): if b >= 8: val = 255 else: x = 128 val = 0 for j in range(0, b): val += x x /= 2 mask += str(val) if i < 3: mask += "." b -= 8 return mask def getInterfaces(self): com = "ip route" self.interfaces = [] (ret, content) = self.ssh.commandAsRoot(com) if ret == 0: self.message = content lines = content.splitlines() for line in lines: columns = line.split() if columns[0] == 'default': continue iface = interface() sn = columns[0].split('/') iface.subnet = sn[0] iface.mask = sn[1] iface.name = columns[2] self.interfaces.append(iface) def getChain(self, chain): com = "iptables -vnx --line-numbers -L " + chain chain = iptables_chain() (ret, content) = self.ssh.commandAsRoot(com) if ret == 0: lines = content.splitlines() for line in lines: columns = line.strip().split() if len(columns) == 0: continue # label if columns[0] == "num": continue if columns[0] == "Chain": chain.policy = columns[3].strip("()") chain.rules = [] continue # the line must be a rule: if len(columns) >= 6: rule = iptables_rule() rule.num = columns[0] rule.pkts = columns[1] rule.bytes = columns[2] rule.target = columns[3] rule.prot = columns[4] rule.opt = columns[5] rule.ifin = columns[6] rule.ifout = columns[7] rule.source = columns[8] rule.destination = columns[9] if len(columns) >= 11: for i in range(10, len(columns)): if rule.misc: rule.misc += " " rule.misc += columns[i] miscItem = columns[i].split(":") if len(miscItem) == 2: if miscItem[0] == "dpt": rule.dport = miscItem[1] if miscItem[0] == "spt": rule.sport = miscItem[1] if i > 10 and columns[i-1] == "state": rule.state = columns[i] chain.rules.append(rule) return chain
class HaproxyConfig(): data = haproxy_cfg() cfg_tmp_path = "/etc/haproxy/haproxy_tmp.cfg" loadflag_path = "/etc/haproxy/haproxy_ctl_not_config_loaded" ssh = None def __init__(self,host): self.ssh = Ssh(host) self.data = self.load() def setLoaded(self,loaded): if loaded and not self.isLoaded(): com = "rm -f " + self.loadflag_path self.ssh.commandAsRoot(com) if not loaded and self.isLoaded(): com = "touch " + self.loadflag_path self.ssh.commandAsRoot(com) def isLoaded(self): if os.path.exists(self.loadflag_path): return False return True def isSectionHeader(self,key): if key == "global" or key == "defaults" or key == "frontend" or key == "backend": return True return False def getSections(self,conf): lines = conf.splitlines() item_list = [] sections = [] sec = section() for line in lines: columns = line.strip().split() if len(columns) > 0 and columns[0][0] == '#': continue if len(columns) == 0: continue if self.isSectionHeader(columns[0]): if sec.name: sections.append(sec) sec = section() sec.name = columns[0] for i in range(1,len(columns)): sec.attributes.append(columns[i]) continue if sec.name: values = [] for i in range(0,len(columns)): values.append(columns[i]) sec.params.append(values) if sec.name: sections.append(sec) return sections def load(self): cfg = haproxy_cfg() com = "cat " + cfg.cfg_path (ret,content) = self.ssh.commandAsRoot(com) if ret == 0: cfg.sections = self.getSections(content) return cfg def writeConf(self, line): com = "echo '" + line + "' >>" + self.cfg_tmp_path self.ssh.commandAsRoot(com) def save(self): if not self.data.edit: return "edit flag not set" com = "echo '# config written by haproxy_ctl' > " + self.cfg_tmp_path self.ssh.commandAsRoot(com) for s in self.data.sections: line = s.name for a in s.attributes: line += " " + a self.writeConf(line) for p in s.params: line = " " for v in p: line += " " + v self.writeConf(line) com = "cat " + self.cfg_tmp_path + " > " + self.data.cfg_path (ret,content) = self.ssh.commandAsRoot(com) if ret != 0: return content self.setLoaded(False) return ""
class Service(): state = None ssh = None name = None content = None os_version = "el6" def __init__(self,name,host): self.name = name self.ssh = Ssh(host) self.os_version = self.getOSVersion() self.state = self.getStatus() def getOSVersion(self): com = "uname -r" (ret, val) = self.ssh.commandAsRoot(com) if val.find("el6") > -1: return "el6" elif val.find("el7") > -1: return "el7" else: return "unknown" def getStatus(self): if self.os_version == "el7": if self.name == "iptables": com = "iptables -V" (ret, self.content) = self.ssh.commandAsRoot(com) if ret == 0: (ret, content) = self.ssh.commandAsRoot("iptables -L") self.content = "table: filter\r" + content (ret, content) = self.ssh.commandAsRoot("iptables -L -t nat") self.content += "\rtable: nat\r" + content (ret, content) = self.ssh.commandAsRoot("iptables -L -t mangle") self.content += "\rtable: mangle\r" + content return "running" if ret == 3: return "stopped" return "unknown :" + str(ret) return "OS(el7) not supported." com = "service " + self.name +" status" (ret, self.content) = self.ssh.commandAsRoot(com) ret = ret >> 8; if ret == 0: return "running" if ret == 3: return "stopped" return "unknown :" + str(ret) def start(self): com = "service " + self.name +" start" (ret, self.content) = self.ssh.commandAsRoot(com) if ret: self.state = self.getStatus() return "cannot start " + self.name +":" + self.content self.state = "running" return "" def stop(self): com = "service " + self.name +" stop" (ret, self.content) = self.ssh.commandAsRoot(com) if ret: self.state = self.getStatus() return "cannot stop " + self.name +":" + self.content self.state = "stopped" return "" def reload(self): com = "service " + self.name +" reload" (ret, self.content) = self.ssh.commandAsRoot(com) if ret: self.state = self.getStatus() return "cannot reload " + self.name +":" + self.content self.state = "running" return "" def getMessage(self): return self.content
class HaproxyHttpLog(): log_path = "/var/log/haproxy.log" ssh = None def __init__(self,host): self.ssh = Ssh(host) def getLogLineCount(self): com = "wc -l " + self.log_path (ret,content) = self.ssh.command(com) count = 0 if ret == 0 and content: count = int(content.splitlines()[0].strip().split()[0]) return count def getMilisec(self,timestr): cols = timestr.split(':') sec = 0 if len(cols) > 3: sec += int(cols[1])*60*60*1000 sec += int(cols[2])*60*1000 sec += int(cols[3].split('.')[0])*1000 sec += int(cols[3].split('.')[1]) return sec def getDuration(self, first, last): if first == last: return 0 msec = self.getMilisec(last) - self.getMilisec(first) return msec def getHowLong(self, to, fm): msec = self.getDuration(to, fm) sec = msec/1000 if sec < 60: return str(sec) + " sec. ago" min = sec/60 if min < 60: return str(min) + " min. ago" hour = min/60 return str(hour) + " hr ago" def getServerLastTimestamp(self, server): com = "grep " + server + " " + self.log_path + " | grep HTTP | tail -1" (ret,content) = self.ssh.commandAsRoot(com) timestamp = "N/A" if ret == 0 and content: columns = content.splitlines()[0].strip().split() if len(columns) > 6: timestamp = columns[6].strip("[]") return timestamp def getLog(self, startLogLine, servers): totalLines = self.getLogLineCount() if totalLines - int(startLogLine) > 10000: startLogLine = str(totalLines - 10000) if int(startLogLine) > 0: startLogLine = str(int(startLogLine) - 1) data = http_data() for s in servers: data.server_data[s] = http_server_data() com = "tail -n +" + startLogLine + " " + self.log_path (ret,content) = self.ssh.command(com) endLogLine = startLogLine if ret == 0 and content: lines = content.splitlines() last_conn_str = None # counting for line in lines: cols = line.strip().split() if len(cols) > 6 and data.timestamp_first == "N/A": data.timestamp_first = cols[6].strip("[]") continue data.acc_cnt += 1 if len(cols) > 6: data.timestamp_last = cols[6].strip("[]") if len(cols) > 8 and data.server_data.has_key(cols[8]): data.server_data[cols[8]].acc_cnt += 1 data.server_data[cols[8]].timestamp_last = cols[6].strip("[]") if len(cols) > 15: data.server_data[cols[8]].last_conn_str = cols[15] if len(cols) > 15: last_conn_str = cols[15] if data.timestamp_last == "N/A": now = datetime.datetime.now() data.timestamp_last = now.strftime("%d/%b/%Y:%H:%M:%S") + ".%03d" % (now.microsecond / 1000) # durations and throughput data.duration_millisec = self.getMilisec(data.timestamp_last) - self.getMilisec(data.timestamp_first) if data.duration_millisec > 0: data.acc_per_sec = float(data.acc_cnt) / float(data.duration_millisec) * 1000 # last conn state if last_conn_str: conn = last_conn_str.split("/") if len(conn) > 1: data.fe_conn_cnt = conn[1] if len(conn) > 2: data.be_conn_cnt = conn[2] # per server data for s in servers: if data.duration_millisec > 0: data.server_data[s].acc_per_sec = float(data.server_data[s].acc_cnt) / float(data.duration_millisec) * 1000 if data.server_data[s].last_conn_str: conn = data.server_data[s].last_conn_str.split("/") if len(conn) > 3: data.server_data[s].conn_cnt = conn[3] if len(conn) > 4: data.server_data[s].retry_cnt = conn[4] if data.server_data[s].timestamp_last == "N/A": data.server_data[s].timestamp_last = self.getServerLastTimestamp(s) # update current log line endLogLine = int(startLogLine) + len(lines) return (str(endLogLine), data) def getLastLog(self): com = "tail -1 " + self.log_path (ret,content) = self.ssh.command(com) data = http_data() if ret == 0 and content: columns = content.splitlines()[0].strip().split() if len(columns) > 6: data.timestamp = columns[6].strip("[]") if len(columns) > 15: conn = columns[15].split("/") if len(conn) > 1: data.fe_conn_cnt = conn[1] if len(conn) > 2: data.be_conn_cnt = conn[2] return data
com += " -o " + req['ifout'] # destination if req['destination'] != "" and req['destination'] != "0.0.0.0/0": com += " -d " + req['destination'] # sport if req['sport'] != "": com += " --sport " + req['sport'] # dport if req['dport'] != "": com += " --dport " + req['dport'] # state if req['state'] != "": com += " -m state --state " + req['state'] # do command (ret, msg) = ssh.commandAsRoot(com) if ret != 0: message += "iptables : " + msg else: # redirect GET: print ("Location: iptables_ctl.py?lang=" + req['lang'] + "&host=" + req['host'] + "&tab_id=" + req['tab_id'] + "\n\n") exit(0) ### render html ##### ### <html><head>--</head> #### renderHead(loc.str('menu_iptables'), "", "iptables/iptables.js") print("<body onLoad='setRefreshTimerAndScroll(" + req["refresh"] + "," + req["y_scroll"] + ")'>") Menu(req['tab_id'], loc).render()
form = cgi.FieldStorage() req = { 'refresh':"0", 'service_action':"none" ,'y_scroll':"0", 'lang':"en", 'tab_id' : "-99", 'host': "localhost", 'cmd': "ls" } for key in req.keys(): if form.has_key(key): req[key] = form[key].value loc = Localize(req['lang']) if loc.message: message = loc.message if req['cmd']: ssh = Ssh(req['host']) com = req['cmd'] (ret,content) = ssh.commandAsRoot(com) if ret == 0 and content: message = "" lines = content.splitlines() for i in range(1,len(lines)): message += lines[i] + "<br>" else: if ret != 0: message = "[error] Command failed." else: message = "[no output]" ### render html ##### ### <html><head>--</head> #### renderHead(loc.str('menu_remote'), "", "remote.js")