Empty disk support added to openvim
[osm/openvim.git] / osm_openvim / vim_db.py
index c34160d..5fc7c91 100644 (file)
@@ -37,7 +37,7 @@ import uuid as myUuid
 import auxiliary_functions as af
 import json
 import logging
-from netaddr import IPNetwork, IPSet, IPRange, all_matching_cidrs
+from netaddr import IPNetwork, IPAddress
 
 HTTP_Bad_Request = 400
 HTTP_Unauthorized = 401 
@@ -56,8 +56,7 @@ class vim_db():
         ''' 
         #initialization
         self.net_vlan_range = vlan_range
-        self.net_vlan_usedlist = None
-        self.net_vlan_lastused = self.net_vlan_range[0] -1
+        self.vlan_config = {}
         self.debug=debug
         if logger_name:
             self.logger_name = logger_name
@@ -176,43 +175,49 @@ class vim_db():
         else:
             return json.dumps(out)
     
-    def __get_used_net_vlan(self):
+    def __get_used_net_vlan(self, region=None):
         #get used from database if needed
+        vlan_region = self.vlan_config[region]
         try:
-            cmd = "SELECT vlan FROM nets WHERE vlan>='%s' ORDER BY vlan LIMIT 25" % self.net_vlan_lastused
+            cmd = "SELECT vlan FROM nets WHERE vlan>='{}' and region{} ORDER BY vlan LIMIT 25".format(
+                vlan_region["lastused"], "='"+region+"'" if region else " is NULL")
             with self.con:
                 self.cur = self.con.cursor()
                 self.logger.debug(cmd)
                 self.cur.execute(cmd)
                 vlan_tuple = self.cur.fetchall()
-                #convert a tuple of tuples in a list of numbers
-                self.net_vlan_usedlist = []
+                # convert a tuple of tuples in a list of numbers
+                vlan_region["usedlist"] = []
                 for k in vlan_tuple:
-                    self.net_vlan_usedlist.append(k[0])
-            return 0
+                    vlan_region["usedlist"].append(k[0])
         except (mdb.Error, AttributeError) as e:
             return self.format_error(e, "get_free_net_vlan", cmd)
     
-    def get_free_net_vlan(self):
+    def get_free_net_vlan(self, region=None):
         '''obtain a vlan not used in any net'''
-        
+        if region not in self.vlan_config:
+            self.vlan_config[region] = {
+                "usedlist": None,
+                "lastused": self.net_vlan_range[0] - 1
+            }
+        vlan_region = self.vlan_config[region]
+
         while True:
-            self.logger.debug("net_vlan_lastused:%d  net_vlan_range:%d-%d  net_vlan_usedlist:%s", 
-                            self.net_vlan_lastused, self.net_vlan_range[0], self.net_vlan_range[1], str(self.net_vlan_usedlist))
-            self.net_vlan_lastused += 1
-            if self.net_vlan_lastused ==  self.net_vlan_range[1]:
-                #start from the begining
-                self.net_vlan_lastused =  self.net_vlan_range[0]
-                self.net_vlan_usedlist = None
-            if self.net_vlan_usedlist is None \
-            or (len(self.net_vlan_usedlist)>0 and self.net_vlan_lastused >= self.net_vlan_usedlist[-1] and len(self.net_vlan_usedlist)==25):
-                r = self.__get_used_net_vlan()
-                if r<0: return r
-                self.logger.debug("new net_vlan_usedlist %s", str(self.net_vlan_usedlist))
-            if self.net_vlan_lastused in self.net_vlan_usedlist:
+            self.logger.debug("get_free_net_vlan() region[{}]={}, net_vlan_range:{}-{} ".format(region, vlan_region,
+                            self.net_vlan_range[0], self.net_vlan_range[1]))
+            vlan_region["lastused"] += 1
+            if vlan_region["lastused"] ==  self.net_vlan_range[1]:
+                # start from the begining
+                vlan_region["lastused"] =  self.net_vlan_range[0]
+                vlan_region["usedlist"] = None
+            if vlan_region["usedlist"] is None or \
+                    (len(vlan_region["usedlist"])==25 and vlan_region["lastused"] >= vlan_region["usedlist"][-1]):
+                self.__get_used_net_vlan(region)
+                self.logger.debug("new net_vlan_usedlist %s", str(vlan_region["usedlist"]))
+            if vlan_region["lastused"] in vlan_region["usedlist"]:
                 continue
             else:
-                return self.net_vlan_lastused
+                return vlan_region["lastused"]
                 
     def get_table(self, **sql_dict):
         ''' Obtain rows from a table.
@@ -467,16 +472,19 @@ class vim_db():
                 with self.con:
                     self.cur = self.con.cursor(mdb.cursors.DictCursor)
                     #get HOST
-                    cmd = "SELECT uuid, user, name, ip_name, description, ranking, admin_state_up, DATE_FORMAT(created_at,'%Y-%m-%dT%H:%i:%s') as created_at \
-                        FROM hosts WHERE " + where_filter
+                    cmd = "SELECT uuid, user, password, keyfile, name, ip_name, description, ranking, admin_state_up, "\
+                          "DATE_FORMAT(created_at,'%Y-%m-%dT%H:%i:%s') as created_at "\
+                          "FROM hosts WHERE " + where_filter
                     self.logger.debug(cmd) 
                     self.cur.execute(cmd)
-                    if self.cur.rowcount == 0 : 
+                    if self.cur.rowcount == 0:
                         return 0, "host '" + str(host_id) +"'not found."
                     elif self.cur.rowcount > 1 : 
                         return 0, "host '" + str(host_id) +"' matches more than one result."
                     host = self.cur.fetchone()
                     host_id = host['uuid']
+                    if host.get("password"):
+                        host["password"] = "*****"
                     #get numa
                     cmd = "SELECT id, numa_socket, hugepages, memory, admin_state_up FROM numas WHERE host_id = '" + str(host_id) + "'"
                     self.logger.debug(cmd)
@@ -499,20 +507,20 @@ class vim_db():
                         used = self.cur.fetchone()
                         used_= int(used['hugepages_consumed']) if used != None else 0
                         numa['hugepages_consumed'] = used_
-                        #get ports
-                        #cmd = "CALL GetPortsFromNuma(%s)'" % str(numa['id'])
-                        #self.cur.callproc('GetPortsFromNuma', (numa['id'],) )
-                        #every time a Procedure is launched you need to close and open the cursor 
-                        #under Error 2014: Commands out of sync; you can't run this command now
-                        #self.cur.close()   
-                        #self.cur = self.con.cursor(mdb.cursors.DictCursor)
-                        cmd="SELECT Mbps, pci, status, Mbps_used, instance_id, if(id=root_id,'PF','VF') as type_,\
-                             switch_port, switch_dpid, mac, source_name\
-                             FROM resources_port WHERE numa_id=%d ORDER BY root_id, type_ DESC" %  (numa['id'])
+                        # get ports
+                        # cmd = "CALL GetPortsFromNuma(%s)'" % str(numa['id'])
+                        # self.cur.callproc('GetPortsFromNuma', (numa['id'],) )
+                        # every time a Procedure is launched you need to close and open the cursor
+                        # under Error 2014: Commands out of sync; you can't run this command now
+                        # self.cur.close()
+                        # self.cur = self.con.cursor(mdb.cursors.DictCursor)
+                        cmd = "SELECT Mbps, pci, status, Mbps_used, instance_id, if(id=root_id,'PF','VF') as type_, "\
+                              "switch_port, switch_dpid, switch_mac, mac, source_name "\
+                              "FROM resources_port WHERE numa_id={} ORDER BY root_id, type_ DESC".format(numa['id'])
                         self.logger.debug(cmd)
                         self.cur.execute(cmd)
                         ifaces = self.cur.fetchall()
-                        #The SQL query will ensure to have SRIOV interfaces from a port first
+                        # The SQL query will ensure to have SRIOV interfaces from a port first
                         sriovs=[]
                         Mpbs_consumed = 0
                         numa['interfaces'] = []
@@ -528,6 +536,8 @@ class vim_db():
                                     del iface["switch_dpid"]
                                 if not iface["switch_port"]:
                                     del iface["switch_port"]
+                                if not iface["switch_mac"]:
+                                    del iface["switch_mac"]
                                 if sriovs:
                                     iface["sriovs"] = sriovs
                                 if Mpbs_consumed:
@@ -539,6 +549,7 @@ class vim_db():
                             else: #VF, SRIOV
                                 del iface["switch_port"]
                                 del iface["switch_dpid"]
+                                del iface["switch_mac"]
                                 del iface["type_"]
                                 del iface["Mbps"]
                                 sriovs.append(iface)
@@ -1059,7 +1070,7 @@ class vim_db():
                     #get extended
                     extended = {}
                     #get devices
-                    cmd = "SELECT type, vpci, image_id, xml,dev FROM instance_devices WHERE instance_id = '%s' " %  str(instance_id)
+                    cmd = "SELECT type, vpci, image_id, xml, dev, image_size FROM instance_devices WHERE instance_id = '%s' " %  str(instance_id)
                     self.logger.debug(cmd)
                     self.cur.execute(cmd)
                     if self.cur.rowcount > 0 :
@@ -1121,7 +1132,7 @@ class vim_db():
 
                         #get dedicated ports and SRIOV
                         cmd = "SELECT port_id as iface_id, p.vlan as vlan, p.mac as mac_address, net_id, if(model='PF',\
-                            'yes',if(model='VF','no','yes:sriov')) as dedicated, rp.Mbps as bandwidth, name, vpci, \
+                            'yes',if(model='VF','no','yes:sriov')) as dedicated, p.Mbps as bandwidth, name, vpci, \
                             pci as source \
                             FROM resources_port as rp join ports as p on port_id=uuid  WHERE p.instance_id = '%s' AND numa_id = '%s' and p.type='instance:data'" % (instance_id, numa_id) 
                         self.logger.debug(cmd)
@@ -1509,8 +1520,10 @@ class vim_db():
                             else:                    xml = 'Null'
                             if 'dev' in device: dev = "'" + device['dev'] + "'"
                             else:                    dev = 'Null'
-                            cmd = "INSERT INTO instance_devices (type, instance_id, image_id, vpci, xml, dev) VALUES ('%s','%s', %s, %s, %s, %s)" % \
-                                (device['type'], uuid, image_id, vpci, xml, dev)
+                            if 'image_size' in device: size = device['image_size']
+                            else:                    size = 0
+                            cmd = "INSERT INTO instance_devices (type, instance_id, image_id, vpci, xml, dev, image_size) VALUES ('%s','%s', %s, %s, %s, %s, %s)" % \
+                                (device['type'], uuid, image_id, vpci, xml, dev, str(size))
                             self.logger.debug(cmd)
                             self.cur.execute(cmd)
                     ##inserting new log
@@ -1533,15 +1546,15 @@ class vim_db():
         :param ip_used_list: contain all used ips to avoid ip collisions
         :return:
         """
-
         ip_tools = IPNetwork(cidr)
         cidr_len = ip_tools.prefixlen
         ips = IPNetwork(first_ip + '/' + str(cidr_len))
-        ip_used_list.append(str(ips[0])) # first ip
-        ip_used_list.append(str(ips[1])) # gw ip
-        ip_used_list.append(str(ips[-1])) # broadcast ip
+
+        ip_used_list.append(str(ips[1]))  # gw ip
+        ip_used_list.append(str(ips[-1]))  # broadcast ip
+
         for vm_ip in ips:
-            if str(vm_ip) not in ip_used_list:
+            if str(vm_ip) not in ip_used_list and IPAddress(first_ip) <= IPAddress(vm_ip) <= IPAddress(last_ip):
                 return vm_ip
 
         return None