def do_set(self):
		""" real task """
		f = None
		content = ml_func.sudo(["grep " + self.cfg["time_zone"] + " /usr/share/zoneinfo/zone.tab"])
		if content[0]:
			f = content[1].split()[2]
		else:
			return (False, ["invalid time zone"])
		if f:
			ret = ml_func.sudo(["cp -f /usr/share/zoneinfo/" + f, "/etc/localtime"])
			if not ret[0]:
				return (False, ["set localtime failed"])
		else:
			return (False, ["invalid time zone"])
		if self.cfg["date"] and self.cfg["time"]:
			tb = self.cfg["date"] + " " + self.cfg["time"]
			ret = ml_func.sudo(["date -s ", '\"' + tb + '\"'])
		if self.cfg["time_server"]:
			f = open("/etc/ntp.conf", "w")
			f.writelines("server " + self.cfg["time_server"] + "\n")
			f.close()
			content = ml_func.sudo(["ntpd -qg"])
			if not content[0]:
				return (False, ["fail to start NTP service"])
		e = ml_func.sudo(["hwclock -w"])
		if not e[0]:
			return (False, ["fail to set date_time"])
		return (True, None)
	def do_get(self):
		""" real task """
		content = ml_func.sudo(["arp -an", "| grep -v PERM", "| grep -v incomplete"])
		if content[0]:
			lines = content[1].split("\n")
			for line in lines:
				i = re.search("\(.*\)", line)
				m = re.search("at .*? ", line)
				d = re.search("on .*", line)
				if i and m and d:
					self.cfg["ipv4_dynamic"].append({
						"interface":line[d.start()+3:d.end()],
						"ip":line[i.start()+1:i.end()-1],
						"mac":line[m.start()+3:m.end()-1]
					})
		content = ml_func.sudo(["ip -6 neigh show", "| grep -v PERMANENT", "| grep -v INCOMPLETE"])
		if content[0]:
			lines = content[1].split("\n")
			for line in lines:
				i = re.search("\A.*? ", line)
				m = re.search("lladdr .*? ", line)
				d = re.search("dev .*? ", line)
				if i and m and d:
					self.cfg["ipv6_dynamic"].append({
						"interface":line[d.start()+4:d.end()-1],
						"ip":line[i.start():i.end()-1],
						"mac":line[m.start()+7:m.end()-1]
					})
		return (True, None)
	def do_set(self):
		""" real task """
		ret = True
		emsg = []
		ml_func.sudo(["killall snmpd"])
		if self.cfg["enable"] == 1: 
			f = open("/tmp/snmpd.conf", "w")
			f.write("rocommunity "+ self.cfg["community"]+ "\n");
			f.write("rwcommunity "+ self.cfg["community"]+ "\n");
			f.write("sysLocation "+ self.cfg["system_location"]+ "\n");
			f.write("sysName "+ self.cfg["system_name"]+ "\n");
			f.write("sysDescr "+ self.cfg["system_name"]+ "\n");
			f.write("sysContact "+ self.cfg["system_contact"]+ "\n");
			f.close()
			e = ml_func.sudo(["mv", "/tmp/snmpd.conf", "/etc/snmp/snmpd.conf"])
			if not e[0]:
				ret = False
				emsg.append(e[1])
			e = ml_func.sudo(["snmpd -c", "/etc/snmp/snmpd.conf"])
			if not e[0]:
				ret = False
				emsg.append(e[1])
		if not ret:
			return (False, emsg)
		return (True, None)
def stop_traceroute(user = None, threadlock = None):
	"""
		Web UI calls stop_traceroute()
		return
			(True, None)
			(False, list)
	"""
	ml_func.sudo(["killall traceroute"], block=True)
	return (True, None)
def stop_arping(user = None, threadlock = None):
	"""
		Web UI calls stop_arping()
		return
			(True, None)
			(False, list)
	"""
	ml_func.sudo(["killall arping"], block=True)
	return (True, None)
def reload(user = None, threadlock = None):
	"""
		reload keepalived service
		return
			(True, None)
			(False, list)
	"""
	try:
		ml_func.sudo(["cat", "running/email.conf", "running/vrrpv2.conf", "running/slb.conf", "> /etc/keepalived/keepalived.conf"])
		ml_func.sudo(["/etc/rc.d/keepalived restart"])
	except Exception as e:
		return (False, [str(e)])
	return (True, None)
	def do_set(self):
		""" real task """
		status = True
		emsg = []
		for f in facility_list:
			e = ml_func.sudo(["sed -i '/" + f + "/d' /etc/rsyslog.conf"])
		e = ml_func.sudo(["echo '" + self.cfg["facility"] + "\t\t@" + self.cfg["server_ip"] + "' >> /etc/rsyslog.conf"])
		e = ml_func.sudo(["/etc/rc.d/rsyslogd restart"])
		if not e[0]:
			status = False
			emsg.append(e[1])
		if not status:
			return (False, emsg)
		return (True, None)
def start_arping(user = None, threadlock = None):
	"""
		Web UI calls start_arping()
		return
			(True, None)
			(False, list)
	"""
	e = ml_w_ip_address.get()
	if e[0]:
		for i in e[1]["ip"]:
			for p in i["ipv4"]:
				target = p["ipv4_address"]
				ml_func.sudo(["arping -U -c 10", target], block=True)
	return (True, None)
def start_ping(user = None, target = None, threadlock = None):
	"""
		Web UI calls start_ping()
		return
			(True, str)
			(False, list)
	"""
	if target is None:
		return (False, ["invalid target"])
	if ml_check.validate_ipv4(target):
		e = ml_func.sudo(["ping -W 3 -c 10", target], block=True)
	elif ml_check.validate_ipv6(target):
		e = ml_func.sudo(["ping6 -W 3 -c 10", target], block=True)
	else:
		return (False, ["invalid target"])
	return e
	def do_set(self):
		""" real task """
		e = ml_func.sudo(["ip -o -0 addr show"], ["| grep @"])
		if e[0]:
			lines = e[1].split("\n")
			for line in lines:
				m = re.search(":.*@", line)
				if m:
					e = ml_func.sudo(["ip link delete dev", line[m.start()+2:m.end()-1]])
		for vconfig in self.cfg['vconfig']:
			e = ml_func.sudo(["ip link add link", vconfig["interface"], "name", vconfig["interface"] + "." + str(vconfig["vlan_id"]), "type vlan id", str(vconfig["vlan_id"])])
			if not e[0]:
				return e
			e = ml_func.sudo(["ip link set dev", vconfig["interface"] + "." + str(vconfig["vlan_id"]), "up"])
			if not e[0]:
				return e
		return (True, None)
	def do_set(self):
		""" real task """
		status = True
		emsg = []
		for ip in self.cfg["ip"]:
			ml_func.sudo(["ip link set dev", ip["interface"], "down"])
			ml_func.sudo(["ip addr flush dev", ip["interface"]])
			#ml_func.sudo(["ip route flush table", table])
			#ml_func.sudo(["ip route flush cache"])
			e = ml_func.sudo(["ip link set dev", ip["interface"], "up"])
			if not e[0]:
				status = False
				emsg.append(e[1])
			for ipv4 in ip["ipv4"]:
				e = ml_func.sudo(["ip addr add", ipv4["ipv4_address"] + "/" + str(ipv4["ipv4_prefix"]), "dev", ip["interface"]])
				if not e[0]:
					status = False
					emsg.append(e[1])
			for ipv6 in ip["ipv6"]:
				e = ml_func.sudo(["ip addr add", ipv6["ipv6_address"] + "/" + str(ipv6["ipv6_prefix"]), "dev", ip["interface"]])
				if not e[0]:
					status = False
					emsg.append(e[1])
		if not status:
			return (False, emsg)
		else:
			return (True, None)
def save_startup_to_running(user = None, threadlock = None):
	"""
		Web UI calls save_running_to_startup()
		return
			(True, None)
			(False, list)
	"""
	status = True
	emsg = []
	e = ml_func.sudo(["rm -rf", ml_system.CFG_PATH])
	if not e[0]:
		status = False
		emsg.append(e[1])
	e = ml_func.sudo(["cp -rf", ml_system.CFG_STARTUP_PATH, ml_system.CFG_PATH])
	if not e[0]:
		status = False
		emsg.append(e[1])
	return (status, emsg)
def get(user = None, threadlock = None):
	"""
		Web UI calls get()
		return
			(True, cfg)
			(False, list)
	"""
	cfg = {}
	cfg.update({"version": ml_system.VERSION})
	cfg.update({"serial_number": ml_system.SERIAL_NUMBER})
	try:
		ut0 = ml_func.sudo(["uptime"])
		if ut0[0]:
			m = re.search("up .* user", ut0[1])
		else:
			return (False, ["Fail to get uptime"])
		if m:
			ut1 = m.group()
			m = re.search(".*,", ut1[3:-4])
		else:
			return (False, ["Fail to get uptime"])
		if m:
			ut2 = m.group()
			cfg.update({"uptime": ut2[:-1]})
		else:
			return (False, ["Fail to get uptime"])
		ret = ml_func.sudo(["cat /proc/sys/net/netfilter/nf_conntrack_count"])
		if ret[0]:
			cfg.update({"connections": int(ret[1])})
		else:
			cfg.update({"connections": 0})
		ups = ml_func.sudo(["ps -axo \%cpu="])
		if ups[0]:
			ua = 0.0
			for up in ups[1].split():
				ua += float(up)
			if ua > 100.0:
				ua = 100.0
			cfg.update({"cpu_usage": ua})
		else:
			return (False, ["Fail to get cpu usage"])
	except Exception as e:
		return (False, [str(e)])
	return (True, cfg)
	def do_set(self):
		""" real task """
		status = True
		emsg = []
		#ml_func.sudo(["ip route flush table ", table])
		ml_func.sudo(["ip route flush cache"])
		for ip in self.cfg["ipv4"] + self.cfg['ipv6']:
			e = ml_func.sudo(["ip link set dev ", ip["interface"], " up"])
			if not e[0]:
				status = False
				emsg.append(e[1])
			e = ml_func.sudo(["ip route add ", ip["destination"] + "/" + str(ip["prefix"]), " dev ", ip["interface"], " via ", ip["gateway"]])
			if not e[0]:
				status = False
				emsg.append(e[1])
		if not status:
			return (False, emsg)
		else:
			return (True, None)
def start_traceroute(user = None, target = None, threadlock = None):
	"""
		Web UI calls start_traceroute()
		return
			(True, str)
			(False, list)
	"""
	if target is None:
		return (False, ["invalid target"])
	e = ml_func.sudo(["traceroute -n", target], block=True)
	return e
	def do_set(self):
		""" real task """
		# ssh
		if self.cfg["ssh"]:
			e = ml_func.sudo(["/etc/rc.d/sshd restart"])
			if not e[0]:
				return e
		else:
			e = ml_func.sudo(["/etc/rc.d/sshd stop"])
			if not e[0]:
				return e
		# telnet
		if self.cfg["telnet"]:
			e = ml_func.sudo(["/etc/rc.d/xinetd restart"])
			if not e[0]:
				return e
		else:
			e = ml_func.sudo(["/etc/rc.d/xinetd stop"])
			if not e[0]:
				return e
		return (True, None)
def start_telnetd(user = None, threadlock = None):
	"""
		Web UI calls start_telnetd()
		return
			(True, None)
			(False, list)
	"""
	e = ml_func.sudo(["/etc/rc.d/xinetd restart"])
	if not e[0]:
		return e
	else:
		return (True, None)
def stop_sshd(user = None, threadlock = None):
	"""
		Web UI calls stop_sshd()
		return
			(True, None)
			(False, list)
	"""
	e = ml_func.sudo(["/etc/rc.d/sshd stop"])
	if not e[0]:
		return e
	else:
		return (True, None)
	def do_set(self):
		""" real task """
		status = True
		emsg = []
		content = ml_func.sudo(["brctl show"])
		if content[0]:
			lines = content[1].split("\n")
			lines.remove(lines[0])
			for line in lines:
				b = re.search(".*?\t", line)
				if b:
					ret = ml_func.sudo(["brctl delbr", line[0:b.end()-1]])
					if not ret[0]:
						return (False, ["Fail to delete bridges"])
		for br in self.cfg['br']:
			ret = ml_func.sudo(["brctl addbr", br["name"]])
			if not ret[0]:
				return (False, ["Fail to add bridge " + br["name"]])
			buf = ["brctl addif", br["name"]]
			for interface in br["interface"]:
				sbuf = buf[:]
				sbuf.append(interface)
				ret = ml_func.sudo(sbuf)
				if not ret[0]:
					return (False, ["Fail to add interface " + br["interface"] + " to bridge " + br["name"]])
			if br["STP"]:
				stp = "on"
			else:
				stp = "off"
			ret = ml_func.sudo(["brctl stp", br["name"], stp])
			if not ret[0]:
				status = False
				emsg.append("Fail to set STP mode")
			ret = ml_func.sudo(["brctl sethello", br["name"], str(br["hello_time"])])
			if not ret[0]:
				status = False
				emsg.append("Fail to set hello time")
			ret = ml_func.sudo(["brctl setmaxage", br["name"], str(br["max_message_age"])])
			if not ret[0]:
				status = False
				emsg.append("Fail to set max message age")
			ret = ml_func.sudo(["brctl setfd", br["name"], str(br["forward_delay"])])
			if not ret[0]:
				status = False
				emsg.append("Fail to set forward delay")
		if not status:
			return (False, emsg)
		return (True, None)
	def do_set(self):
		""" real task """
		status = True
		emsg = []

		content = ml_func.sudo(["arp -an", "| grep PERM"])
		if content[0]:
			lines = content[1].split("\n")
			for line in lines:
				m = re.search("\(.*\)", line)
				if m:
					ret = ml_func.sudo(["arp -d ", line[m.start()+1:m.end()-1]])
					if not ret[0]:
						return ret
		for ipv4 in self.cfg["ipv4_static"]:
			ret = ml_func.sudo(["arp -i", ipv4["interface"], "-s", ipv4["ip"], ipv4["mac"]])
			if not ret[0]:
				status = False
				emsg.append(ret[1])
		del self.cfg["ipv4_dynamic"][:]
		content = ml_func.sudo(["ip -6 neigh show", "| grep PERMANENT"])
		if content[0]:
			lines = content[1].split("\n")
			for line in lines:
				if len(line.split()) >= 3:
					ret = ml_func.sudo(["ip -6 neigh del", line.split()[0], "dev", line.split()[2]])
					if not ret[0]:
						return ret
		for ipv6 in self.cfg["ipv6_static"]:
			ret = ml_func.sudo(["ip -6 neigh add", ipv6["ip"], "lladdr", ipv6["mac"], "dev", ipv6["interface"]])
			#if not ret[0]:
			#	status = False
			#	emsg.append(ret[1])
		del self.cfg["ipv6_dynamic"][:]

		if not status:
			return (False, emsg)
		else:
			return (True, None)
	def do_set(self):
		""" real task """
		# please install ecdysis
		if self.cfg["enable"]:
			ret = ml_func.sudo(["cp -f nat64-config.sample nat64-config.sh"])
			if "0.0.0.0" != self.cfg["ipv4"]:
				ret = ml_func.sudo(["sed -i 's/#IPV4_ADDR/IPV4_ADDR/' nat64-config.sh"])
				ret = ml_func.sudo(["sed -i 's/XTERA-IPV4/" + self.cfg["ipv4"] + "/' nat64-config.sh"])
			ret = ml_func.sudo(["sed -i 's/XTERA-IPV6/" + self.cfg["ipv6"] + "/' nat64-config.sh"])
			ret = ml_func.sudo(["sed -i 's/XTERA-PREFIX/" + str(self.cfg["ipv6_prefix"]) + "/' nat64-config.sh"])
			ret = ml_func.sudo(["mv -f nat64-config.sh /bin"])
			if not ret[0]:
				return (False, ["fail to parse nat64 script"])
			try:
				os.chmod("/bin/nat64-config.sh",
					stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
					stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH
				)
			except Exception as e:
				return (False, [str(e)])
			ml_func.sudo(["nat64-config.sh"])
		else:
			ml_func.sudo(["ifconfig nat64 down"])
			ml_func.sudo(["rmmod nf_nat64"])
		return (True, None)
	def do_set(self):
		""" real task """
		# clear all connection limit rules
		ml_func.sudo(["iptables -t mangle -F"])
		for cl4 in self.cfg["ipv4"]:
			src = "-s " + cl4["source_ip"]
			dst = "-d " + cl4["destination_ip"]
			protocol = ""
			if "TCP" == cl4["protocol"]:
				protocol = "-p tcp --tcp-flags FIN,SYN,RST,ACK SYN"
			elif "UDP" == cl4["protocol"]:
				protocol = "-p udp"
			else:
				return (False, ["invalid protocol - " + cl4["protocol"]])
			limit = "-m limit "
			if cl4["limit_rate"] >= 0:
				limit += "--limit " + str(cl4["limit_rate"])
				if "day" == cl4["limit_rate_unit"]:
					limit += "/d "
				elif "hour" == cl4["limit_rate_unit"]:
					limit += "/h "
				elif "minute" == cl4["limit_rate_unit"]:
					limit += "/m "
				elif "second" == cl4["limit_rate_unit"]:
					limit += "/s "
				else:
					return (False, ["invalid limit rate unit - " + cl4["limit_rate_unit"]])
			if cl4["limit_burst"] >= 0:
				limit += "--limit-burst " + str(cl4["limit_burst"])
			ret = ml_func.sudo(["iptables -t mangle -A PREROUTING", src, dst, protocol, limit, "-j ACCEPT"])
			if not ret[0]:
				return (False, ["fail to set connection limit rule"])
			ret = ml_func.sudo(["iptables -t mangle -A PREROUTING", src, dst, protocol, "-j DROP"])
			if not ret[0]:
				return (False, ["fail to set connection limit rule"])
		for cl6 in self.cfg["ipv6"]:
			src = "-s " + cl6["source_ip"]
			dst = "-d " + cl6["destination_ip"]
			protocol = ""
			if "TCP" == cl6["protocol"]:
				protocol = "-p tcp --tcp-flags FIN,SYN,RST,ACK SYN"
			elif "UDP" == cl6["protocol"]:
				protocol = "-p udp"
			else:
				return (False, ["invalid protocol - " + cl6["protocol"]])
			limit = "-m limit "
			if cl6["limit_rate"] >= 0:
				limit += "--limit " + str(cl6["limit_rate"])
				if "day" == cl6["limit_rate_unit"]:
					limit += "/d "
				elif "hour" == cl6["limit_rate_unit"]:
					limit += "/h "
				elif "minute" == cl6["limit_rate_unit"]:
					limit += "/m "
				elif "second" == cl6["limit_rate_unit"]:
					limit += "/s "
				else:
					return (False, ["invalid limit rate unit - " + cl6["limit_rate_unit"]])
			if cl6["limit_burst"] >= 0:
				limit += "--limit-burst " + str(cl6["limit_burst"])
			ret = ml_func.sudo(["ip6tables -t mangle -A PREROUTING", src, dst, protocol, limit, "-j ACCEPT"])
			if not ret[0]:
				return (False, ["fail to set connection limit rule"])
			ret = ml_func.sudo(["ip6tables -t mangle -A PREROUTING", src, dst, protocol, "-j DROP"])
			if not ret[0]:
				return (False, ["fail to set connection limit rule"])
		return (True, None)
def get(user = None, threadlock = None):
	"""
		Web UI calls get()
		return
			(True, cfg)
			(False, list)
	"""
	cfg = {"port":[]}
	try:
		interfaces = []
		# get all interfaces
		ret_pis = ml_func.sudo(["ifconfig -a -s"])
		if ret_pis[0]:
			pis = ret_pis[1].split("\n")
			if len(pis) > 1:
				pis.remove(pis[0])
				for pi in pis:
					m = re.match("(\w+) ", pi)
					if m:
						if m.group(1) != "lo":
							interfaces.append(m.group(1))
		else:
			return (False, ["Fail to get port"])
		for i in interfaces:
			port = {"interface":i}
			# get every interface's speed/duplex
			ret_pe = ml_func.sudo(["ethtool", i, "| grep Speed"])
			if ret_pe[0]:
				s = ret_pe[1].split()[1]
				m = re.match("(\d+)", s)
				if m:
					speed = m.group()
				else:
					speed = "Unknown" 
			else:
				return (False, ["Fail to get port speed of " + i])
			ret_pe = ml_func.sudo(["ethtool", i, "| grep Duplex"])
			if ret_pe[0]:
				duplex = ret_pe[1].split()[1]
			else:
				return (False, ["Fail to get port duplex of " + i])
			port.update({"status": speed + "/" + duplex})
			# get every interface's RX, TX, and "Down" status.
			port.update({"RX":{}, "TX":{}})
			ret_pi = ml_func.sudo(["ifconfig", i])
			if ret_pi[0]:
				raw = ret_pi[1].split("\n")
				m = re.search("UP", raw[0])
				if m is None:
					port.update({"status":"Down"})
				for r in raw:
					m = re.search("RX packets\s+(\d+)\s+bytes\s+(\d+)", r)
					if m:
						port["RX"].update({"packets":m.group(1)})
						port["RX"].update({"bytes":m.group(2)})
					m = re.search("TX packets\s+(\d+)\s+bytes\s+(\d+)", r)
					if m:
						port["TX"].update({"packets":m.group(1)})
						port["TX"].update({"bytes":m.group(2)})
			else:
				return (False, ["Fail to get port " + i])
			cfg["port"].append(port)
	except Exception as e:
		return (False, [str(e)])
	return (True, cfg)
	def do_set(self):
		""" real task """
		mark = 1
		sbuf = ""
		ml_func.sudo(["/sbin/iptables -t filter -F FORWARD"])
		ml_func.sudo(["/sbin/ip6tables -t filter -F FORWARD"])
		ml_func.sudo(["/sbin/iptables -t mangle -F PREROUTING"])
		ml_func.sudo(["/sbin/ip6tables -t mangle -F PREROUTING"])
		# check fields
		if self.cfg.has_key("policy"):
			if self.cfg["policy"].has_key("ipv4"):
				for policy in self.cfg["policy"]["ipv4"]:
					if label_get(policy["source_ip"], self.cfg["ip"]["ipv4"]) == None:
						return (False, ["source ip - " + policy["source_ip"] + " does not exist"])
					if label_get(policy["destination_ip"], self.cfg["ip"]["ipv4"]) == None:
						return (False, ["destination ip - " + policy["destination_ip"] + " does not exist"])
					if label_get(policy["service_group"], self.cfg["service_group"]["ipv4"]) == None:
						return (False, ["service group - " + policy["service_group"] + " does not exist"])
					if policy["action"] == "VIP":
						if label_get(policy["real_server_group"], self.cfg["real_server_group"]["ipv4"]) == None:
							return (False, ["real server group - " + policy["real_server_group"] + " does not exist"])
						if label_get(policy["fallback_server"], self.cfg["fallback_server"]["ipv4"]) == None:
							return (False, ["fallback server - " + policy["fallback_server"] + " does not exist"])
						if label_get(policy["property"], self.cfg["property"]) == None:
							return (False, ["property - " + policy["property"] + " does not exist"])
						# add firewall mark
						src = ""
						for s in label_get(policy["source_ip"], self.cfg["ip"]["ipv4"])["ip_address"]:
							if s != "ANY" and s != "":
								src = " -s " + s
							dst = ""
							for d in label_get(policy["destination_ip"], self.cfg["ip"]["ipv4"])["ip_address"]:
								if d != "ANY" and d != "":
									dst = " -d " + d
								service = label_get(policy["service_group"], self.cfg["service_group"]["ipv4"])
								protocol = ""
								if service["protocol"] == "TCP":
									protocol = " -p tcp "
								elif service["protocol"] == "UDP":
									protocol = " -p udp "
								elif service["protocol"] == "BOTH":
									protocol = ""
								else:
									return (False, ["unknown protocol - " + service["protocol"]])
								port = ""
								if len(service["application_port"]) > 0:
									port = " -m multiport --dports "
									for p in service["application_port"]:
										try:
											port += str(p) + ","
										except Exception as e:
											return (False, [str(e)])
									port = port[:-1]
								ml_func.sudo(["/sbin/iptables -t mangle -A PREROUTING", src, dst, protocol, port, "-j MARK --set-mark " + str(mark)])
						# add keepalived
						sbuf += "{0}virtual_server fwmark %d {{\n".format(" "*0) % (mark)
						proper = label_get(policy["property"], self.cfg["property"])
						if proper["health_check_interval"] >= 0:
							sbuf += "{0}delay_loop %d\n".format(" "*4) % (proper["health_check_interval"])
						if bm_get(proper["balance_mode"]) == None:
							return (False, ["unknown balance mode - " + proper["balance_mode"]])
						sbuf += "{0}lb_algo %s\n".format(" "*4) % (bm_get(proper["balance_mode"]))
						if fm_get(proper["forward_method"]) == None:
							return (False, ["unknown forward method - " + proper["forward_method"]])
						sbuf += "{0}lb_kind %s\n".format(" "*4) % (fm_get(proper["forward_method"]))
						if proper["persistence"] >= 0:
							sbuf += "{0}persistence_timeout %d\n".format(" "*4) % (proper["persistence"])
						sbuf += "{0}persistence_granularity %s\n".format(" "*4) % (proper["ipv4_netmask"])
						if policy["fallback_server"] != "NA":
							sbuf += "{0}sorry_server %s 0\n".format(" "*4) % (label_get(policy["fallback_server"], self.cfg["fallback_server"]["ipv4"])["ip_address"])
						real_server = label_get(policy["real_server_group"], self.cfg["real_server_group"]["ipv4"])
						sbuf += "{0}real_server %s 0 {{\n".format(" "*4) % (real_server["ip_address"])
						if real_server["maintenance_mode"]:
							sbuf += "{0}weight 0\n".format(" "*8)
						elif real_server["weight"] >= 0:
							sbuf += "{0}weight %d\n".format(" "*8) % (real_server["weight"])
						if real_server["health_check"] != "NA":
							ret = hc_get(real_server)
							if ret[0]:
								for s in ret[1]:
									sbuf += "{0}%s\n".format(" "*8) % (s)
							else:
								return ret
						sbuf += "{0}}}\n".format(" "*4)
						sbuf += "{0}}}\n".format(" "*0)
					elif policy["action"] == "Accept" or policy["action"] == "Deny":
						src = ""
						for s in label_get(policy["source_ip"], self.cfg["ip"]["ipv4"])["ip_address"]:
							if s != "ANY" and s != "":
								src = " -s " + s
							dst = ""
							for d in label_get(policy["destination_ip"], self.cfg["ip"]["ipv4"])["ip_address"]:
								if d != "ANY" and d != "":
									dst = " -d " + d
								service = label_get(policy["service_group"], self.cfg["service_group"]["ipv4"])
								protocol = ""
								if service["protocol"] == "TCP":
									protocol = " -p tcp "
								elif service["protocol"] == "UDP":
									protocol = " -p udp "
								elif service["protocol"] == "BOTH":
									return (False, ["not support protocol - " + service["protocol"]])
								else:
									return (False, ["unknown protocol - " + service["protocol"]])
								port = ""
								if len(service["application_port"]) > 0:
									port = " -m multiport --dports "
									for p in service["application_port"]:
										try:
											port += str(p) + ","
										except Exception as e:
											return (False, [str(e)])
									port = port[:-1]
								if policy["action"] == "Accept":
									action = "-j ACCEPT"
								elif policy["action"] == "Deny":
									action = "-j DROP"
								ml_func.sudo(["/sbin/iptables -t filter -I FORWARD", src, dst, protocol, port, action])
					else:
						return (False, ["unknown policy action - " + policy["action"]])
					mark += 1
			if self.cfg["policy"].has_key("ipv6"):
				for policy in self.cfg["policy"]["ipv6"]:
					if label_get(policy["source_ip"], self.cfg["ip"]["ipv6"]) == None:
						return (False, ["source ip - " + policy["source_ip"] + " does not exist"])
					if label_get(policy["destination_ip"], self.cfg["ip"]["ipv6"]) == None:
						return (False, ["destination ip - " + policy["destination_ip"] + " does not exist"])
					if label_get(policy["service_group"], self.cfg["service_group"]["ipv6"]) == None:
						return (False, ["service group - " + policy["service_group"] + " does not exist"])
					if policy["action"] == "VIP":
						if label_get(policy["real_server_group"], self.cfg["real_server_group"]["ipv6"]) == None:
							return (False, ["real server group - " + policy["real_server_group"] + " does not exist"])
						if label_get(policy["fallback_server"], self.cfg["fallback_server"]["ipv6"]) == None:
							return (False, ["fallback server - " + policy["fallback_server"] + " does not exist"])
						if label_get(policy["property"], self.cfg["property"]) == None:
							return (False, ["property - " + policy["property"] + " does not exist"])
						# add firewall mark
						src = ""
						for s in label_get(policy["source_ip"], self.cfg["ip"]["ipv6"])["ip_address"]:
							if s != "ANY" and s != "":
								src = " -s " + s
							dst = ""
							for d in label_get(policy["destination_ip"], self.cfg["ip"]["ipv6"])["ip_address"]:
								if d != "ANY" and d != "":
									dst = " -d " + d
								service = label_get(policy["service_group"], self.cfg["service_group"]["ipv6"])
								protocol = ""
								if service["protocol"] == "TCP":
									protocol = " -p tcp "
								elif service["protocol"] == "UDP":
									protocol = " -p udp "
								elif service["protocol"] == "BOTH":
									protocol = ""
								else:
									return (False, ["unknown protocol - " + service["protocol"]])
								port = ""
								if len(service["application_port"]) > 0:
									port = " -m multiport --dports "
									for p in service["application_port"]:
										try:
											port += str(p) + ","
										except Exception as e:
											return (False, [str(e)])
									port = port[:-1]
								ml_func.sudo(["/sbin/ip6tables -t mangle -A PREROUTING", src, dst, protocol, port, "-j MARK --set-mark " + str(mark)])
						# add keepalived
						sbuf += "{0}virtual_server fwmark %d {{\n".format(" "*0) % (mark)
						proper = label_get(policy["property"], self.cfg["property"])
						if proper["health_check_interval"] >= 0:
							sbuf += "{0}delay_loop %d\n".format(" "*4) % (proper["health_check_interval"])
						if bm_get(proper["balance_mode"]) == None:
							return (False, ["unknown balance mode - " + proper["balance_mode"]])
						sbuf += "{0}lb_algo %s\n".format(" "*4) % (bm_get(proper["balance_mode"]))
						if fm_get(proper["forward_method"]) == None:
							return (False, ["unknown forward method - " + proper["forward_method"]])
						sbuf += "{0}lb_kind %s\n".format(" "*4) % (fm_get(proper["forward_method"]))
						if proper["persistence"] >= 0:
							sbuf += "{0}persistence_timeout %d\n".format(" "*4) % (proper["persistence"])
						sbuf += "{0}persistence_granularity %s\n".format(" "*4) % (proper["ipv6_prefix"])
						if policy["fallback_server"] != "NA":
							sbuf += "{0}sorry_server %s 0\n".format(" "*4) % (label_get(policy["fallback_server"], self.cfg["fallback_server"]["ipv6"])["ip_address"])
						real_server = label_get(policy["real_server_group"], self.cfg["real_server_group"]["ipv6"])
						sbuf += "{0}real_server %s 0 {{\n".format(" "*4) % (real_server["ip_address"])
						if real_server["maintenance_mode"]:
							sbuf += "{0}weight 0\n".format(" "*8)
						elif real_server["weight"] >= 0:
							sbuf += "{0}weight %d\n".format(" "*8) % (real_server["weight"])
						if real_server["health_check"] != "NA":
							ret = hc_get(real_server)
							if ret[0]:
								for s in ret[1]:
									sbuf += "{0}%s\n".format(" "*8) % (s)
							else:
								return ret
						sbuf += "{0}}}\n".format(" "*4)
						sbuf += "{0}}}\n".format(" "*0)
					elif policy["action"] == "Accept" or policy["action"] == "Deny":
						src = ""
						for s in label_get(policy["source_ip"], self.cfg["ip"]["ipv6"])["ip_address"]:
							if s != "ANY" and s != "":
								src = " -s " + s
							dst = ""
							for d in label_get(policy["destination_ip"], self.cfg["ip"]["ipv6"])["ip_address"]:
								if d != "ANY" and d != "":
									dst = " -d " + d
								service = label_get(policy["service_group"], self.cfg["service_group"]["ipv6"])
								protocol = ""
								if service["protocol"] == "TCP":
									protocol = " -p tcp "
								elif service["protocol"] == "UDP":
									protocol = " -p udp "
								elif service["protocol"] == "BOTH":
									return (False, ["not support protocol - " + service["protocol"]])
								else:
									return (False, ["unknown protocol - " + service["protocol"]])
								port = ""
								if len(service["application_port"]) > 0:
									port = " -m multiport --dports "
									for p in service["application_port"]:
										try:
											port += str(p) + ","
										except Exception as e:
											return (False, [str(e)])
									port = port[:-1]
								if policy["action"] == "Accept":
									action = "-j ACCEPT"
								elif policy["action"] == "Deny":
									action = "-j DROP"
								ml_func.sudo(["/sbin/ip6tables -t filter -I FORWARD", src, dst, protocol, port, action])
					else:
						return (False, ["unknown policy action - " + policy["action"]])
					mark += 1
		# update conf file
		try:
			file = open("running/slb.conf", "w")
			file.write(sbuf)
			file.close()
		except Exception as e:
			return (False, [str(e)])
		# reload service
		return (True, None)
	def do_set(self):
		""" real task """
		# generate conf file content
		gbuf = ""
		ibuf = ""
		if self.cfg.has_key("group"):
			for group in self.cfg["group"]:
				if group.has_key("group-name"):
					gbuf += "{0}vrrp_sync_group %s {{\n".format(" "*0) % (group["group-name"])
					gbuf += "{0}group {{\n".format(" "*4)
					if group.has_key("instance"):
						for instance in group["instance"]:
							if instance.has_key("instance-name"):
								gbuf += "{0}%s\n".format(" "*8) % (instance["instance-name"])
								ibuf += "{0}vrrp_instance %s {{\n".format(" "*0) % (instance["instance-name"])
								if instance.has_key("priority") and 255 == instance["priority"]:
									ibuf += "{0}state %s\n".format(" "*4) % ("MASTER")
								else:
									ibuf += "{0}state %s\n".format(" "*4) % ("BACKUP")
								if instance.has_key("interface"):
									ibuf += "{0}interface %s\n".format(" "*4) % (instance["interface"])
								if instance.has_key("additional_track_interface"):
									ibuf += "{0}track_interface {{\n".format(" "*4)
									for track in instance["additional_track_interface"]:
										if track.has_key("interface"):
											ibuf += "{0}%s\n".format(" "*8) % (track["interface"])
									ibuf += "{0}}}\n".format(" "*4)
								if instance.has_key("delay-gratuitous-arp"):
									ibuf += "{0}garp_master_delay %d\n".format(" "*4) % (instance["delay-gratuitous-arp"])
								if instance.has_key("virtual-router-id"):
									ibuf += "{0}virtual_router_id %d\n".format(" "*4) % (instance["virtual-router-id"])
								if instance.has_key("priority"):
									ibuf += "{0}priority %d\n".format(" "*4) % (instance["priority"])
								if instance.has_key("advertisement-interval"):
									ibuf += "{0}advert_int %d\n".format(" "*4) % (instance["advertisement-interval"])
								if instance.has_key("ipv4_vip") or instance.has_key("ipv6_vip"):
									ibuf += "{0}virtual_ipaddress {{\n".format(" "*4)
								if instance.has_key("ipv4_vip"):
									for ipv4_vip in instance["ipv4_vip"]:
										if ipv4_vip.has_key("ipv4"):
											ibuf += "{0}%s\n".format(" "*8) % (ipv4_vip["ipv4"])
								if instance.has_key("ipv6_vip"):
									for ipv6_vip in instance["ipv6_vip"]:
										if ipv6_vip.has_key("ipv6"):
											ibuf += "{0}%s\n".format(" "*8) % (ipv6_vip["ipv6"])
								if instance.has_key("ipv4_vip") or instance.has_key("ipv6_vip"):
									ibuf += "{0}}}\n".format(" "*4)
								if instance.has_key("preempt"):
									if not instance["preempt"]:
										ibuf += "{0}nopreempt\n".format(" "*4)
								#ibuf += "{0}preempt_delay %d\n".format(" "*4) % (300)
								ibuf += "{0}}}\n".format(" "*0)
					gbuf += "{0}}}\n".format(" "*4)
					gbuf += "{0}}}\n".format(" "*0)
		# update conf file
		try:
			file = open("keepalived.conf", "w")
			file.write(gbuf)
			file.write(ibuf)
			file.close()
		except Exception as e:
			return (False, [str(e)])
		# reload service
		try:
			ml_func.sudo(["/etc/rc.d/keepalived restart"])
		except Exception as e:
			return (False, [str(e)])

		return (True, None)
	def do_set(self):
		""" real task """
		status = True
		admin_password = ""
		monitor_password = ""
		users = ml_func.sudo(["awk -F: '{print $1}' /etc/passwd"])
		if not users[0]:
			return (False, ["fail to read /etc/passwd"])
		# SLB users cannot duplicate or exist in system users
		for user in users[1].split():
			try:
				ret_uid = ml_func.sudo(["id -u", user])
				if ret_uid[0]:
					uid = int(ret_uid[1].strip())
				else:
					continue
			except Exception as e:
				continue
			if uid < 1000:
				for u in self.cfg["user"]:
					if u["name"] == user:
						return (False, ["not allow account name " + user])
		name_list = []
		for u in self.cfg["user"]:
			if u["name"] in name_list:
				return (False, ["detected duplicate account name " + u["name"]])
			name_list.append(u["name"])
		# admin and monitor accounts must exist and can not change group
		if "admin" not in name_list or "monitor" not in name_list:
			return (False, ["not allow to delete default accounts"])
		for u in self.cfg["user"]:
			if u["name"] == "admin":
				admin_password = u["password"]
				if u["group"] != "admin":
					return (False, ["not allow to change default group of admin"])
			if u["name"] == "monitor":
				monitor_password = u["password"]
				if u["group"] != "monitor":
					return (False, ["not allow to change default group of monitor"])
		# delete all SLB users (UID >= 1000)
		for user in users[1].split():
			if user == "admin" or user == "monitor":
				continue
			try:
				ret_uid = ml_func.sudo(["id -u", user])
				if ret_uid[0]:
					uid = int(ret_uid[1].strip())
				else:
					continue
			except Exception as e:
				continue
			if uid >= 1000:
				ret_del = ml_func.sudo(["userdel -r", user])
				if not ret_del[0]:
					status = False
		if not status:
			return (False, ["fail to delete users"])
		e = ml_func.sudo(["userdel -r", "monitor"])
		e = ml_func.sudo(["userdel -r", "admin"])
		# delete all SLB groups
		e = ml_func.sudo(["groupdel", "monitor"])
		e = ml_func.sudo(["groupdel", "admin"])
		# add SLB users and groups
		e = ml_func.sudo(["useradd -m", "admin", "-s /bin/ml_c_cli_command.py"])
		if not e[0]:
			return (False, ["fail to add admin"])
		e = ml_func.sudo(["echo admin:" + admin_password + "| chpasswd"])
		print "echo admin:" + admin_password + "| chpasswd"
		if not e[0]:
			return (False, ["fail to set admin password"])
		e = ml_func.sudo(["useradd -m", "monitor", "-s /bin/ml_c_cli_command.py"])
		if not e[0]:
			return (False, ["fail to add monitor"])
		e = ml_func.sudo(["echo monitor:" + monitor_password + "| chpasswd"])
		print "echo monitor:" + monitor_password + "| chpasswd"
		if not e[0]:
			return (False, ["fail to set monitor password"])
		for new_user in self.cfg["user"]:
			if new_user["name"] == "admin" or new_user["name"] == "monitor":
				continue
			ret_new = ml_func.sudo(["useradd -m", new_user["name"], "-G", new_user["group"], "-s /bin/ml_c_cli_command.py"])
			if ret_new[0]:
				ret_password = ml_func.sudo(["echo", new_user["name"] + ":" + new_user["password"], "| chpasswd"])
				if not ret_password[0]:
					status = False
			else:
				status = False
		if not status:
			return (False, ["fail to add users"])
		return (True, None)
def get(user = None, threadlock = None):
	"""
		Web UI calls get()
		return
			(True, cfg)
			(False, list)
	"""
	cfg = {"vips":[]}
	try:
		rr0 = ml_func.sudo(["ipvsadm -ln --rate"])
		if not rr0[0]:
			return (False, ["ipvsadm fails"])
		data = rr0[1].split("\n")
		#print data
		if "" in data:
			#print "take null lines out"
			data.remove("")
		#print "pass d-zone"
		if len(data) <= 3:
			return (True, cfg)
		for line in data[3:]:
			tokens = line.split()
			if tokens[0] == "->":
				rip = {}
				if "]:" in tokens[1]:
					address = tokens[1].split("]:")[0].strip("[")
					port = tokens[1].split("]:")[1]
				else:
					address = tokens[1].split(":")[0]
					port = tokens[1].split(":")[1]
				rip.update({
					"rip": address,
					"port": port,
					"connections/sec": tokens[2],
					"inbound_packets/sec": tokens[3],
					"outbound_packets/sec": tokens[4],
					"inbound_bytes/sec": tokens[5],
					"outbound_bytes/sec": tokens[6]
				})
				if "rips" in vip.keys():
					vip["rips"].append(rip)
				else:
					return (False, ["fail to parse rip from ipvsadm output"])
			else:
				if len(tokens) != 7:
					return (False, ["fail to parse vip from ipvsadm output"])
				vip = {}
				if "]:" in tokens[1]:
					address = tokens[1].split("]:")[0].strip("[")
					port = tokens[1].split("]:")[1]
				else:
					address = tokens[1].split(":")[0]
					port = tokens[1].split(":")[1]
				vip.update({
					"vip": address,
					"port": port,
					"connections/sec": tokens[2],
					"inbound_packets/sec": tokens[3],
					"outbound_packets/sec": tokens[4],
					"inbound_bytes/sec": tokens[5],
					"outbound_bytes/sec": tokens[6],
					"rips": []
				})
				cfg["vips"].append(vip)
	except Exception as e:
		return (False, [str(e)])
	return (True, cfg)
def get(user = None, threadlock = None):
	"""
		Web UI calls get()
		return
			(True, cfg)
			(False, list)
	"""
	cfg = {"vips":[]}
	try:
		rp0 = ml_func.sudo(["ipvsadm -ln --persistent-conn"])
		if not rp0[0]:
			return (False, ["ipvsadm fails"])
		data = rp0[1].split("\n")
		if "" in data:
			data.remove("")
		if len(data) <= 3:
			return (True, cfg)
		for line in data[3:]:
			tokens = line.split()
			if tokens[0] == "->":
				if len(tokens) != 6:
					return (False, ["fail to parse rip from ipvsadm output"])
				rip = {}
				if "]:" in tokens[1]:
					address = tokens[1].split("]:")[0].strip("[")
				else:
					address = tokens[1].split(":")[0]
				rip.update({
					"rip": address,
					"weight": tokens[2],
					"persistent": tokens[3],
					"active": tokens[4],
					"inactive": tokens[5]
				})
				if "rips" in vip.keys():
					vip["rips"].append(rip)
				else:
					return (False, ["fail to parse rip from ipvsadm output"])
			else:
				if len(tokens) != 5:
					return (False, ["fail to parse vip from ipvsadm output"])
				vip = {}
				if "]:" in tokens[1]:
					address = tokens[1].split("]:")[0].strip("[")
					netmask = 0
					prefix = 64
				else:
					address = tokens[1].split(":")[0]
					netmask = 24
					prefix = 0
				vip.update({
					"vip": address,
					"persistent": tokens[4],
					"netmask": netmask,
					"prefix": prefix,
					"rips": []
				})
				cfg["vips"].append(vip)
	except Exception as e:
		return (False, [str(e)])
	return (True, cfg)