Modify openvim code structure, improve py package
[osm/openvim.git] / dhcp_thread.py
diff --git a/dhcp_thread.py b/dhcp_thread.py
deleted file mode 100644 (file)
index da7176b..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-# -*- coding: utf-8 -*-
-
-##
-# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
-# This file is part of openvim
-# All Rights Reserved.
-#
-# Licensed 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact with: nfvlabs@tid.es
-##
-
-'''
-This is thread that interact with the dhcp server to get the IP addresses 
-'''
-__author__="Pablo Montes, Alfonso Tierno"
-__date__ ="$4-Jan-2016 12:07:15$"
-
-
-
-import threading
-import time
-import Queue
-import paramiko
-import random
-import subprocess
-import logging
-
-#TODO: insert a logging system
-
-class dhcp_thread(threading.Thread):
-    def __init__(self, dhcp_params, db, db_lock, test, dhcp_nets, logger_name=None, debug=None):
-        '''Init a thread.
-        Arguments: thread_info must be a dictionary with:
-            'dhcp_params' dhcp server parameters with the following keys:
-                mandatory : user, host, port, key, ifaces(interface name list of the one managed by the dhcp)
-                optional:  password, key, port(22)
-            'db' 'db_lock': database class and lock for accessing it
-            'test': in test mode no acces to a server is done, and ip is invented
-        '''
-        threading.Thread.__init__(self)
-        self.dhcp_params = dhcp_params
-        self.db = db
-        self.db_lock = db_lock
-        self.test = test
-        self.dhcp_nets = dhcp_nets
-        self.ssh_conn = None
-        if logger_name:
-            self.logger_name = logger_name
-        else:
-            self.logger_name = "openvim.dhcp"
-        self.logger = logging.getLogger(self.logger_name)
-        if debug:
-            self.logger.setLevel(getattr(logging, debug))
-
-        self.mac_status ={} #dictionary of mac_address to retrieve information
-            #ip: None
-            #retries: 
-            #next_reading: time for the next trying to check ACTIVE status or IP
-            #created: time when it was added 
-            #active: time when the VM becomes into ACTIVE status
-            
-        
-        self.queueLock = threading.Lock()
-        self.taskQueue = Queue.Queue(2000)
-        
-    def ssh_connect(self):
-        try:
-            #Connect SSH
-            self.ssh_conn = paramiko.SSHClient()
-            self.ssh_conn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-            self.ssh_conn.load_system_host_keys()
-            self.ssh_conn.connect(self.dhcp_params["host"], port=self.dhcp_params.get("port", 22),
-                                  username=self.dhcp_params["user"], password=self.dhcp_params.get("password"),
-                                  key_filename=self.dhcp_params.get("key"), timeout=2)
-        except paramiko.ssh_exception.SSHException as e:
-            self.logger.error("ssh_connect ssh Exception " + str(e))
-        
-    def load_mac_from_db(self):
-        #TODO get macs to follow from the database
-        self.logger.debug("load macs from db")
-        self.db_lock.acquire()
-        r,c = self.db.get_table(SELECT=('mac','ip_address','nets.uuid as net_id', ),
-                                FROM='ports join nets on ports.net_id=nets.uuid', 
-                                WHERE_NOT={'ports.instance_id': None, 'nets.provider': None})
-        self.db_lock.release()
-        now = time.time()
-        self.mac_status ={}
-        if r<0:
-            self.logger.error("Error getting data from database: " + c)
-            return
-        for port in c:
-            if port["net_id"] in self.dhcp_nets:
-                self.mac_status[ port["mac"] ] = {"ip": port["ip_address"], "next_reading": now, "created": now, "retries":0}
-    
-    def insert_task(self, task, *aditional):
-        try:
-            self.queueLock.acquire()
-            task = self.taskQueue.put( (task,) + aditional, timeout=5) 
-            self.queueLock.release()
-            return 1, None
-        except Queue.Full:
-            return -1, "timeout inserting a task over dhcp_thread"
-
-    def run(self):
-        self.logger.debug("starting, nets: " + str(self.dhcp_nets))
-        next_iteration = time.time() + 10
-        while True:
-            self.load_mac_from_db()
-            while True:
-                try:
-                    self.queueLock.acquire()
-                    if not self.taskQueue.empty():
-                        task = self.taskQueue.get()
-                    else:
-                        task = None
-                    self.queueLock.release()
-
-                    if task is None:
-                        now=time.time()
-                        if now >= next_iteration:
-                            next_iteration = self.get_ip_from_dhcp()
-                        else:
-                            time.sleep(1)
-                        continue
-
-                    if task[0] == 'add':
-                        self.logger.debug("processing task add mac " + str(task[1]))
-                        now=time.time()
-                        self.mac_status[task[1] ] = {"ip": None, "next_reading": now, "created": now, "retries":0}
-                        next_iteration = now
-                    elif task[0] == 'del':
-                        self.logger.debug("processing task del mac " + str(task[1]))
-                        if task[1] in self.mac_status:
-                            del self.mac_status[task[1] ]
-                    elif task[0] == 'exit':
-                        self.logger.debug("processing task exit")
-                        self.terminate()
-                        return 0
-                    else:
-                        self.logger.error("unknown task: " + str(task))
-                except Exception as e:
-                    self.logger.critical("Unexpected exception at run: " + str(e), exc_info=True)
-          
-    def terminate(self):
-        try:
-            if self.ssh_conn:
-                self.ssh_conn.close()
-        except Exception as e:
-            self.logger.error("terminate Exception: " + str(e))
-        self.logger.debug("exit from dhcp_thread")
-
-    def get_ip_from_dhcp(self):
-        
-        now = time.time()
-        next_iteration= now + 40000 # >10 hores
-        
-        #print self.name, "Iteration" 
-        for mac_address in self.mac_status:
-            if now < self.mac_status[mac_address]["next_reading"]:
-                if self.mac_status[mac_address]["next_reading"] < next_iteration:
-                    next_iteration = self.mac_status[mac_address]["next_reading"]
-                continue
-            
-            if self.mac_status[mac_address].get("active") == None:
-                #check from db if already active
-                self.db_lock.acquire()
-                r,c = self.db.get_table(FROM="ports as p join instances as i on p.instance_id=i.uuid",
-                                        WHERE={"p.mac": mac_address, "i.status": "ACTIVE"})
-                self.db_lock.release()
-                if r>0:
-                    self.mac_status[mac_address]["active"] = now
-                    self.mac_status[mac_address]["next_reading"] = (int(now)/2 +1)* 2
-                    self.logger.debug("mac %s VM ACTIVE", mac_address)
-                    self.mac_status[mac_address]["retries"] = 0
-                else:
-                    #print self.name, "mac %s  VM INACTIVE" % (mac_address)
-                    if now - self.mac_status[mac_address]["created"] > 300:
-                        #modify Database to tell openmano that we can not get dhcp from the machine
-                        if not self.mac_status[mac_address].get("ip"):
-                            self.db_lock.acquire()
-                            r,c = self.db.update_rows("ports", {"ip_address": "0.0.0.0"}, {"mac": mac_address})
-                            self.db_lock.release()
-                            self.mac_status[mac_address]["ip"] = "0.0.0.0"
-                            self.logger.debug("mac %s >> set to 0.0.0.0 because of timeout", mac_address)
-                        self.mac_status[mac_address]["next_reading"] = (int(now)/60 +1)* 60
-                    else:
-                        self.mac_status[mac_address]["next_reading"] = (int(now)/6 +1)* 6
-                if self.mac_status[mac_address]["next_reading"] < next_iteration:
-                    next_iteration = self.mac_status[mac_address]["next_reading"]
-                continue
-            
-
-            if self.test:
-                if self.mac_status[mac_address]["retries"]>random.randint(10,100): #wait between 10 and 100 seconds to produce a fake IP
-                    content = self.get_fake_ip()
-                else:
-                    content = None
-            elif self.dhcp_params["host"]=="localhost":
-                try:
-                    command = ['get_dhcp_lease.sh',  mac_address]
-                    content = subprocess.check_output(command)
-                except Exception as e:
-                    self.logger.error("get_ip_from_dhcp subprocess Exception " + str(e))
-                    content = None
-            else:
-                try:
-                    if not self.ssh_conn:
-                        self.ssh_connect()
-                    command = 'get_dhcp_lease.sh ' +  mac_address
-                    (_, stdout, _) = self.ssh_conn.exec_command(command)
-                    content = stdout.read()
-                except paramiko.ssh_exception.SSHException as e:
-                    self.logger.error("get_ip_from_dhcp: ssh_Exception: " + srt(e))
-                    content = None
-                    self.ssh_conn = None
-                except Exception as e:
-                    self.logger.error("get_ip_from_dhcp: Exception: " + str(e))
-                    content = None
-                    self.ssh_conn = None
-
-            if content:
-                self.mac_status[mac_address]["ip"] = content
-                #modify Database
-                self.db_lock.acquire()
-                r,c = self.db.update_rows("ports", {"ip_address": content}, {"mac": mac_address})
-                self.db_lock.release()
-                if r<0:
-                    self.logger.error("Database update error: " + c)
-                else:
-                    self.mac_status[mac_address]["retries"] = 0
-                    self.mac_status[mac_address]["next_reading"] = (int(now)/3600 +1)* 36000 # 10 hores
-                    if self.mac_status[mac_address]["next_reading"] < next_iteration:
-                        next_iteration = self.mac_status[mac_address]["next_reading"]
-                    self.logger.debug("mac %s >> %s", mac_address, content)
-                    continue
-            #a fail has happen
-            self.mac_status[mac_address]["retries"] +=1
-            #next iteration is every 2sec at the beginning; every 5sec after a minute, every 1min after a 5min
-            if now - self.mac_status[mac_address]["active"] > 120:
-                #modify Database to tell openmano that we can not get dhcp from the machine
-                if not self.mac_status[mac_address].get("ip"):
-                    self.db_lock.acquire()
-                    r,c = self.db.update_rows("ports", {"ip_address": "0.0.0.0"}, {"mac": mac_address})
-                    self.db_lock.release()
-                    self.mac_status[mac_address]["ip"] = "0.0.0.0"
-                    self.logger.debug("mac %s >> set to 0.0.0.0 because of timeout", mac_address)
-            
-            if now - self.mac_status[mac_address]["active"] > 60:
-                self.mac_status[mac_address]["next_reading"] = (int(now)/6 +1)* 6
-            elif now - self.mac_status[mac_address]["active"] > 300:
-                self.mac_status[mac_address]["next_reading"] = (int(now)/60 +1)* 60
-            else:
-                self.mac_status[mac_address]["next_reading"] = (int(now)/2 +1)* 2
-                
-            if self.mac_status[mac_address]["next_reading"] < next_iteration:
-                next_iteration = self.mac_status[mac_address]["next_reading"]
-        return next_iteration    
-    
-    def get_fake_ip(self):
-        fake_ip = "192.168.{}.{}".format(random.randint(1,254), random.randint(1,254) )
-        while True:
-            #check not already provided
-            already_used = False
-            for mac_address in self.mac_status:
-                if self.mac_status[mac_address]["ip"] == fake_ip:
-                    already_used = True
-                    break
-            if not already_used:
-                return fake_ip
-
-
-#EXAMPLE of bash script that must be available at the DHCP server for "isc-dhcp-server" type
-#     $ cat ./get_dhcp_lease.sh
-#     #!/bin/bash
-#     awk '
-#     ($1=="lease" && $3=="{"){ lease=$2; active="no"; found="no" }
-#     ($1=="binding" && $2=="state" && $3=="active;"){ active="yes" }
-#     ($1=="hardware" && $2=="ethernet" && $3==tolower("'$1';")){ found="yes" }
-#     ($1=="client-hostname"){ name=$2 }
-#     ($1=="}"){ if (active=="yes" && found=="yes"){ target_lease=lease; target_name=name}}
-#     END{printf("%s", target_lease)} #print target_name
-#     ' /var/lib/dhcp/dhcpd.leases
-