#! /usr/bin/python3
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.



 

import web
import socket, struct
import cloud_utils
from cloud_utils import Command
urls = ("/ipallocator", "ipallocator")
app = web.application(urls, globals())

augtool = Command("augtool")
service = Command("service")
class dhcp:
	_instance = None
	def __init__(self):
		self.availIP=[]
		self.router=None
		self.netmask=None
		self.initialized=False

		options = augtool.match("/files/etc/dnsmasq.conf/dhcp-option").stdout.decode('utf-8').strip()
		for option in options.splitlines():
			if option.find("option:router") != -1:
				self.router = option.split("=")[1].strip().split(",")[1]
				print(self.router)

		dhcp_range = augtool.get("/files/etc/dnsmasq.conf/dhcp-range").stdout.decode('utf-8').strip()
		dhcp_start = dhcp_range.split("=")[1].strip().split(",")[0]
		dhcp_end = dhcp_range.split("=")[1].strip().split(",")[1]
		self.netmask = dhcp_range.split("=")[1].strip().split(",")[2]
		print(dhcp_start, dhcp_end, self.netmask)

 		start_ip_num = self.ipToNum(dhcp_start);
		end_ip_num =  self.ipToNum(dhcp_end)
		print(start_ip_num, end_ip_num)
	
		for ip in range(start_ip_num, end_ip_num + 1):
			self.availIP.append(ip)	
		print(self.availIP[0], self.availIP[len(self.availIP) - 1])	
		
		#load the ip already allocated
		self.reloadAllocatedIP()

	def ipToNum(self, ip):
		return struct.unpack("!I", socket.inet_aton(ip))[0]

	def numToIp(self, num):
		return socket.inet_ntoa(struct.pack('!I', num))

	def getFreeIP(self):
		if len(self.availIP) > 0:
			ip = self.numToIp(self.availIP[0])
			self.availIP.remove(self.availIP[0])	
			return ip
		else:
			return None

	def getNetmask(self):
		return self.netmask

	def getRouter(self):
		return self.router

	def getInstance():
		if not dhcp._instance:
			dhcp._instance = dhcp()
		return dhcp._instance
	getInstance = staticmethod(getInstance)

	def reloadAllocatedIP(self):
		dhcp_hosts = augtool.match("/files/etc/dnsmasq.conf/dhcp-host").stdout.decode('utf-8').strip().splitlines()
		
		for host in dhcp_hosts:
			if host.find("dhcp-host") != -1:
				allocatedIP = self.ipToNum(host.split("=")[1].strip().split(",")[1])
				if allocatedIP in self.availIP:	
					self.availIP.remove(allocatedIP)
		
	def allocateIP(self, mac):
		newIP = self.getFreeIP()
		dhcp_host = augtool.match("/files/etc/dnsmasq.conf/dhcp-host").stdout.decode('utf-8').strip()
		cnt = len(dhcp_host.splitlines()) + 1
		script = """set %s %s
			    save"""%("/files/etc/dnsmasq.conf/dhcp-host[" + str(cnt) + "]", str(mac) + "," + newIP)
		augtool < script
		#reset dnsmasq
		service("dnsmasq", "restart", stdout=None, stderr=None)
		return newIP

	def releaseIP(self, ip):
		dhcp_host = augtool.match("/files/etc/dnsmasq.conf/dhcp-host").stdout.decode('utf-8').strip()
		path = None
		for host in dhcp_host.splitlines():
			if host.find(ip) != -1:
				path = host.split("=")[0].strip()
				
		if path == None:
			print("Can't find " + str(ip) + " in conf file")
			return None

		print(path)
		script = """rm %s
			    save"""%(path)
		augtool < script
		
		self.availIP.remove(ip)
		
		#reset dnsmasq
		service("dnsmasq", "restart", stdout=None, stderr=None)

class ipallocator:
	def GET(self):
		try:
			user_data = web.input()
			command = user_data.command
			print("Processing: " + command)

			dhcpInit = dhcp.getInstance()

			if command == "getIpAddr":
				mac = user_data.mac
				zone_id = user_data.dc
				pod_id = user_data.pod
				print(mac, zone_id, pod_id)
				freeIP = dhcpInit.allocateIP(mac)
				if not freeIP:
					return "0,0,0"
				print("Find an available IP: " + freeIP)
		
				return freeIP + "," + dhcpInit.getNetmask() + "," + dhcpInit.getRouter()
			elif command == "releaseIpAddr":
				ip = user_data.ip
				zone_id = user_data.dc
				pod_id = user_data.pod
				dhcpInit.releaseIP(ip)
		except:
			return None

if __name__ == "__main__":
	app.run()
