2 # -*- coding: utf-8 -*-
5 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
6 # This file is part of openvim
9 # Licensed under the Apache License, Version 2.0 (the "License"); you may
10 # not use this file except in compliance with the License. You may obtain
11 # a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18 # License for the specific language governing permissions and limitations
21 # For those usages not covered by the Apache License, Version 2.0 please
22 # contact with: nfvlabs@tid.es
26 This module interact with the openvim database,
27 It implements general table management
28 and complex writings 'transactional' sures,
29 that is, or all is changed or nothing
32 __author__
="Alfonso Tierno"
33 __date__
="$10-jul-2014 12:07:15$"
37 import auxiliary_functions
as af
40 from netaddr
import IPNetwork
, IPSet
, IPRange
, all_matching_cidrs
42 HTTP_Bad_Request
= 400
43 HTTP_Unauthorized
= 401
45 HTTP_Method_Not_Allowed
= 405
46 HTTP_Request_Timeout
= 408
48 HTTP_Service_Unavailable
= 503
49 HTTP_Internal_Server_Error
= 500
53 def __init__(self
, vlan_range
, debug
="ERROR"):
54 '''vlan_range must be a tuple (vlan_ini, vlan_end) with available vlan values for networks
55 every dataplane network contain a unique value, regardless of it is used or not
58 self
.net_vlan_range
= vlan_range
59 self
.net_vlan_usedlist
= None
60 self
.net_vlan_lastused
= self
.net_vlan_range
[0] -1
62 self
.logger
= logging
.getLogger('vim.db')
63 self
.logger
.setLevel( getattr(logging
, debug
) )
66 def connect(self
, host
=None, user
=None, passwd
=None, database
=None):
67 '''Connect to the concrete data base.
68 The first time a valid host, user, passwd and database must be provided,
69 Following calls can skip this parameters
72 if host
is not None: self
.host
= host
73 if user
is not None: self
.user
= user
74 if passwd
is not None: self
.passwd
= passwd
75 if database
is not None: self
.database
= database
77 self
.con
= mdb
.connect(self
.host
, self
.user
, self
.passwd
, self
.database
)
78 self
.logger
.debug("connected to DB %s at %s@%s", self
.database
,self
.user
, self
.host
)
80 except mdb
.Error
as e
:
81 self
.logger
.error("Cannot connect to DB %s at %s@%s Error %d: %s", self
.database
, self
.user
, self
.host
, e
.args
[0], e
.args
[1])
84 def get_db_version(self
):
85 ''' Obtain the database schema version.
86 Return: (negative, text) if error or version 0.0 where schema_version table is missing
87 (version_int, version_text) if ok
89 cmd
= "SELECT version_int,version,openvim_ver FROM schema_version"
90 for retry_
in range(0,2):
93 self
.cur
= self
.con
.cursor()
94 self
.logger
.debug(cmd
)
96 rows
= self
.cur
.fetchall()
100 for row
in rows
: #look for the latest version
101 if row
[0]>highest_version_int
:
102 highest_version_int
, highest_version
= row
[0:2]
103 return highest_version_int
, highest_version
104 except (mdb
.Error
, AttributeError) as e
:
105 self
.logger
.error("get_db_version DB Exception %d: %s. Command %s",e
.args
[0], e
.args
[1], cmd
)
106 r
,c
= self
.format_error(e
)
107 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
109 def disconnect(self
):
110 '''disconnect from the data base'''
114 except mdb
.Error
as e
:
115 self
.logger
.error("while disconnecting from DB: Error %d: %s",e
.args
[0], e
.args
[1])
117 except AttributeError as e
: #self.con not defined
118 if e
[0][-5:] == "'con'": return -1, "Database internal error, no connection."
121 def format_error(self
, e
, func
, cmd
, command
=None, extra
=None):
122 '''Creates a text error base on the produced exception
125 func: name of the function that makes the call, for logging purposes
126 cmd: database command that produce the exception
127 command: if the intention is update or delete
128 extra: extra information to add to some commands
130 HTTP error in negative, formatted error text
133 self
.logger
.error("%s DB Exception %s. Command %s",func
, str(e
), cmd
)
134 if type(e
[0]) is str:
135 if e
[0][-5:] == "'con'": return -HTTP_Internal_Server_Error
, "DB Exception, no connection."
137 if e
.args
[0]==2006 or e
.args
[0]==2013 : #MySQL server has gone away (((or))) Exception 2013: Lost connection to MySQL server during query
140 return -HTTP_Request_Timeout
,"Database reconnection. Try Again"
141 fk
=e
.args
[1].find("foreign key constraint fails")
143 if command
=="update": return -HTTP_Bad_Request
, "tenant_id %s not found." % extra
144 elif command
=="delete": return -HTTP_Bad_Request
, "Resource is not free. There are %s that prevent its deletion." % extra
145 de
= e
.args
[1].find("Duplicate entry")
146 fk
= e
.args
[1].find("for key")
147 uk
= e
.args
[1].find("Unknown column")
148 wc
= e
.args
[1].find("in 'where clause'")
149 fl
= e
.args
[1].find("in 'field list'")
150 #print de, fk, uk, wc,fl
152 if fk
>=0: #error 1062
153 return -HTTP_Conflict
, "Value %s already in use for %s" % (e
.args
[1][de
+15:fk
], e
.args
[1][fk
+7:])
156 return -HTTP_Bad_Request
, "Field %s can not be used for filtering" % e
.args
[1][uk
+14:wc
]
158 return -HTTP_Bad_Request
, "Field %s does not exist" % e
.args
[1][uk
+14:wc
]
159 return -HTTP_Internal_Server_Error
, "Database internal Error %d: %s" % (e
.args
[0], e
.args
[1])
161 def __data2db_format(self
, data
):
162 '''convert data to database format. If data is None it return the 'Null' text,
163 otherwise it return the text surrounded by quotes ensuring internal quotes are escaped'''
168 return "'" + out
+ "'"
170 return '"' + out
+ '"'
172 return json
.dumps(out
)
174 def __get_used_net_vlan(self
):
175 #get used from database if needed
177 cmd
= "SELECT vlan FROM nets WHERE vlan>='%s' ORDER BY vlan LIMIT 25" % self
.net_vlan_lastused
179 self
.cur
= self
.con
.cursor()
180 self
.logger
.debug(cmd
)
181 self
.cur
.execute(cmd
)
182 vlan_tuple
= self
.cur
.fetchall()
183 #convert a tuple of tuples in a list of numbers
184 self
.net_vlan_usedlist
= []
186 self
.net_vlan_usedlist
.append(k
[0])
188 except (mdb
.Error
, AttributeError) as e
:
189 return self
.format_error(e
, "get_free_net_vlan", cmd
)
191 def get_free_net_vlan(self
):
192 '''obtain a vlan not used in any net'''
195 self
.logger
.debug("net_vlan_lastused:%d net_vlan_range:%d-%d net_vlan_usedlist:%s",
196 self
.net_vlan_lastused
, self
.net_vlan_range
[0], self
.net_vlan_range
[1], str(self
.net_vlan_usedlist
))
197 self
.net_vlan_lastused
+= 1
198 if self
.net_vlan_lastused
== self
.net_vlan_range
[1]:
199 #start from the begining
200 self
.net_vlan_lastused
= self
.net_vlan_range
[0]
201 self
.net_vlan_usedlist
= None
202 if self
.net_vlan_usedlist
is None \
203 or (len(self
.net_vlan_usedlist
)>0 and self
.net_vlan_lastused
>= self
.net_vlan_usedlist
[-1] and len(self
.net_vlan_usedlist
)==25):
204 r
= self
.__get
_used
_net
_vlan
()
206 self
.logger
.debug("new net_vlan_usedlist %s", str(self
.net_vlan_usedlist
))
207 if self
.net_vlan_lastused
in self
.net_vlan_usedlist
:
210 return self
.net_vlan_lastused
212 def get_table(self
, **sql_dict
):
213 ''' Obtain rows from a table.
214 Atribure sql_dir: dictionary with the following key: value
215 'SELECT': [list of fields to retrieve] (by default all)
216 'FROM': string of table name (Mandatory)
217 'WHERE': dict of key:values, translated to key=value AND ... (Optional)
218 'WHERE_NOT': dict of key:values, translated to key!=value AND ... (Optional)
219 'WHERE_OR': dict of key:values, translated to key=value OR ... (Optional)
220 'LIMIT': limit of number of rows (Optional)
221 Return: a list with dictionarys at each row
224 select_
= "SELECT " + ("*" if 'SELECT' not in sql_dict
else ",".join(map(str,sql_dict
['SELECT'])) )
225 #print 'select_', select_
226 from_
= "FROM " + str(sql_dict
['FROM'])
227 #print 'from_', from_
231 if 'WHERE' in sql_dict
and len(sql_dict
['WHERE']) > 0:
233 where_and
= " AND ".join(map( lambda x
: str(x
) + (" is Null" if w
[x
] is None else "='"+str(w
[x
])+"'"), w
.keys()) )
234 if 'WHERE_NOT' in sql_dict
and len(sql_dict
['WHERE_NOT']) > 0:
235 w
=sql_dict
['WHERE_NOT']
236 where_and_not
= " AND ".join(map( lambda x
: str(x
) + (" is not Null" if w
[x
] is None else "!='"+str(w
[x
])+"'"), w
.keys()) )
238 where_and
+= " AND " + where_and_not
240 where_and
= where_and_not
241 if 'WHERE_OR' in sql_dict
and len(sql_dict
['WHERE_OR']) > 0:
242 w
=sql_dict
['WHERE_OR']
243 where_or
= " OR ".join(map( lambda x
: str(x
) + (" is Null" if w
[x
] is None else "='"+str(w
[x
])+"'"), w
.keys()) )
245 if where_and
!=None and where_or
!=None:
246 where_
= "WHERE (" + where_and
+ ") OR " + where_or
247 elif where_and
!=None and where_or
==None:
248 where_
= "WHERE " + where_and
249 elif where_and
==None and where_or
!=None:
250 where_
= "WHERE " + where_or
253 #print 'where_', where_
254 limit_
= "LIMIT " + str(sql_dict
['LIMIT']) if 'LIMIT' in sql_dict
else ""
255 #print 'limit_', limit_
256 cmd
= " ".join( (select_
, from_
, where_
, limit_
) )
257 for retry_
in range(0,2):
260 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
261 self
.logger
.debug(cmd
)
262 self
.cur
.execute(cmd
)
263 rows
= self
.cur
.fetchall()
264 return self
.cur
.rowcount
, rows
265 except (mdb
.Error
, AttributeError) as e
:
266 r
,c
= self
.format_error(e
, "get_table", cmd
)
267 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
269 def new_tenant(self
, tenant_dict
):
270 ''' Add one row into a table.
272 tenant_dict: dictionary with the key: value to insert
273 It checks presence of uuid and add one automatically otherwise
274 Return: (result, uuid) where result can be 0 if error, or 1 if ok
276 for retry_
in range(0,2):
280 #create uuid if not provided
281 if 'uuid' not in tenant_dict
:
282 uuid
= tenant_dict
['uuid'] = str(myUuid
.uuid1()) # create_uuid
284 uuid
= str(tenant_dict
['uuid'])
285 #obtain tenant_id for logs
288 self
.cur
= self
.con
.cursor()
290 cmd
= "INSERT INTO uuids (uuid, used_at) VALUES ('%s','tenants')" % uuid
291 self
.logger
.debug(cmd
)
292 self
.cur
.execute(cmd
)
294 cmd
= "INSERT INTO tenants (" + \
295 ",".join(map(str, tenant_dict
.keys() )) + ") VALUES(" + \
296 ",".join(map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'",tenant_dict
.values() )) + ")"
297 self
.logger
.debug(cmd
)
298 self
.cur
.execute(cmd
)
299 inserted
= self
.cur
.rowcount
301 #del tenant_dict['uuid'] # not interested for the log
302 #cmd = "INSERT INTO logs (related,level,tenant_id,uuid,description) VALUES ('tenants','debug','%s','%s',\"new tenant %s\")" % (uuid, tenant_id, str(tenant_dict))
303 #self.logger.debug(cmd)
304 #self.cur.execute(cmd)
307 if inserted
== 0: return 0, uuid
309 self
.cur
= self
.con
.cursor()
310 #adding public flavors
311 cmd
= "INSERT INTO tenants_flavors(flavor_id,tenant_id) SELECT uuid as flavor_id,'"+ tenant_id
+ "' FROM flavors WHERE public = 'yes'"
312 self
.logger
.debug(cmd
)
313 self
.cur
.execute(cmd
)
314 self
.logger
.debug("attached public flavors: %s", str(self
.cur
.rowcount
))
315 #rows = self.cur.fetchall()
317 # cmd = "INSERT INTO tenants_flavors(flavor_id,tenant_id) VALUES('%s','%s')" % (row[0], tenant_id)
318 # self.cur.execute(cmd )
319 #adding public images
320 cmd
= "INSERT INTO tenants_images(image_id,tenant_id) SELECT uuid as image_id,'"+ tenant_id
+ "' FROM images WHERE public = 'yes'"
321 self
.logger
.debug(cmd
)
322 self
.cur
.execute(cmd
)
323 self
.logger
.debug("attached public images: %s", str(self
.cur
.rowcount
))
325 except (mdb
.Error
, AttributeError) as e
:
327 self
.logger
.warning("new_tenant DB Exception %d: %s. Command %s",e
.args
[0], e
.args
[1], cmd
)
330 r
,c
= self
.format_error(e
, "new_tenant", cmd
)
331 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
333 def new_row(self
, table
, INSERT
, add_uuid
=False, log
=False):
334 ''' Add one row into a table.
336 INSERT: dictionary with the key: value to insert
337 table: table where to insert
338 add_uuid: if True, it will crated an uuid key entry at INSERT if not provided
339 It checks presence of uuid and add one automatically otherwise
340 Return: (result, uuid) where result can be 0 if error, or 1 if ok
342 for retry_
in range(0,2):
346 #create uuid if not provided
347 if 'uuid' not in INSERT
:
348 uuid
= INSERT
['uuid'] = str(myUuid
.uuid1()) # create_uuid
350 uuid
= str(INSERT
['uuid'])
354 self
.cur
= self
.con
.cursor()
357 cmd
= "INSERT INTO uuids (uuid, used_at) VALUES ('%s','%s')" % (uuid
, table
)
358 self
.logger
.debug(cmd
)
359 self
.cur
.execute(cmd
)
361 cmd
= "INSERT INTO " + table
+" (" + \
362 ",".join(map(str, INSERT
.keys() )) + ") VALUES(" + \
363 ",".join(map(lambda x
: 'Null' if x
is None else "'"+str(x
)+"'", INSERT
.values() )) + ")"
364 self
.logger
.debug(cmd
)
365 self
.cur
.execute(cmd
)
366 nb_rows
= self
.cur
.rowcount
368 #if nb_rows > 0 and log:
369 # if add_uuid: del INSERT['uuid']
370 # #obtain tenant_id for logs
371 # if 'tenant_id' in INSERT:
372 # tenant_id = INSERT['tenant_id']
373 # del INSERT['tenant_id']
374 # elif table == 'tenants':
378 # if uuid is None: uuid_k = uuid_v = ""
379 # else: uuid_k=",uuid"; uuid_v=",'" + str(uuid) + "'"
380 # if tenant_id is None: tenant_k = tenant_v = ""
381 # else: tenant_k=",tenant_id"; tenant_v=",'" + str(tenant_id) + "'"
382 # cmd = "INSERT INTO logs (related,level%s%s,description) VALUES ('%s','debug'%s%s,\"new %s %s\")" \
383 # % (uuid_k, tenant_k, table, uuid_v, tenant_v, table[:-1], str(INSERT))
384 # self.logger.debug(cmd)
385 # self.cur.execute(cmd)
388 except (mdb
.Error
, AttributeError) as e
:
389 r
,c
= self
.format_error(e
, "new_row", cmd
)
390 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
392 def __remove_quotes(self
, data
):
393 '''remove single quotes ' of any string content of data dictionary'''
394 for k
,v
in data
.items():
397 data
[k
] = data
[k
].replace("'","_")
399 def _update_rows_internal(self
, table
, UPDATE
, WHERE
={}):
400 cmd
= "UPDATE " + table
+" SET " + \
401 ",".join(map(lambda x
: str(x
)+'='+ self
.__data
2db
_format
(UPDATE
[x
]), UPDATE
.keys() ));
403 cmd
+= " WHERE " + " and ".join(map(lambda x
: str(x
)+ (' is Null' if WHERE
[x
] is None else"='"+str(WHERE
[x
])+"'" ), WHERE
.keys() ))
404 self
.logger
.debug(cmd
)
405 self
.cur
.execute(cmd
)
406 nb_rows
= self
.cur
.rowcount
409 def update_rows(self
, table
, UPDATE
, WHERE
={}, log
=False):
410 ''' Update one or several rows into a table.
412 UPDATE: dictionary with the key-new_value pairs to change
413 table: table to be modified
414 WHERE: dictionary to filter target rows, key-value
415 log: if true, a log entry is added at logs table
416 Return: (result, None) where result indicates the number of updated files
418 for retry_
in range(0,2):
422 uuid
= WHERE
.get('uuid')
425 self
.cur
= self
.con
.cursor()
426 cmd
= "UPDATE " + table
+" SET " + \
427 ",".join(map(lambda x
: str(x
)+'='+ self
.__data
2db
_format
(UPDATE
[x
]), UPDATE
.keys() ));
429 cmd
+= " WHERE " + " and ".join(map(lambda x
: str(x
)+ (' is Null' if WHERE
[x
] is None else"='"+str(WHERE
[x
])+"'" ), WHERE
.keys() ))
430 self
.logger
.debug(cmd
)
431 self
.cur
.execute(cmd
)
432 nb_rows
= self
.cur
.rowcount
433 #if nb_rows > 0 and log:
435 # if uuid is None: uuid_k = uuid_v = ""
436 # else: uuid_k=",uuid"; uuid_v=",'" + str(uuid) + "'"
437 # cmd = "INSERT INTO logs (related,level%s,description) VALUES ('%s','debug'%s,\"updating %d entry %s\")" \
438 # % (uuid_k, table, uuid_v, nb_rows, (str(UPDATE)).replace('"','-') )
439 # self.logger.debug(cmd)
440 # self.cur.execute(cmd)
442 except (mdb
.Error
, AttributeError) as e
:
443 r
,c
= self
.format_error(e
, "update_rows", cmd
)
444 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
446 def get_host(self
, host_id
):
447 if af
.check_valid_uuid(host_id
):
448 where_filter
="uuid='" + host_id
+ "'"
450 where_filter
="name='" + host_id
+ "'"
451 for retry_
in range(0,2):
455 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
457 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 \
458 FROM hosts WHERE " + where_filter
459 self
.logger
.debug(cmd
)
460 self
.cur
.execute(cmd
)
461 if self
.cur
.rowcount
== 0 :
462 return 0, "host '" + str(host_id
) +"'not found."
463 elif self
.cur
.rowcount
> 1 :
464 return 0, "host '" + str(host_id
) +"' matches more than one result."
465 host
= self
.cur
.fetchone()
466 host_id
= host
['uuid']
468 cmd
= "SELECT id, numa_socket, hugepages, memory, admin_state_up FROM numas WHERE host_id = '" + str(host_id
) + "'"
469 self
.logger
.debug(cmd
)
470 self
.cur
.execute(cmd
)
471 host
['numas'] = self
.cur
.fetchall()
472 for numa
in host
['numas']:
473 #print "SELECT core_id, instance_id, status, thread_id, v_thread_id FROM resources_core WHERE numa_id = '" + str(numa['id']) + "'"
475 cmd
= "SELECT core_id, instance_id, status, thread_id, v_thread_id FROM resources_core WHERE numa_id = '" + str(numa
['id']) + "'"
476 self
.logger
.debug(cmd
)
477 self
.cur
.execute(cmd
)
478 numa
['cores'] = self
.cur
.fetchall()
479 for core
in numa
['cores']:
480 if core
['instance_id'] == None: del core
['instance_id'], core
['v_thread_id']
481 if core
['status'] == 'ok': del core
['status']
483 cmd
= "SELECT sum(consumed) as hugepages_consumed FROM resources_mem WHERE numa_id = '" + str(numa
['id']) + "' GROUP BY numa_id"
484 self
.logger
.debug(cmd
)
485 self
.cur
.execute(cmd
)
486 used
= self
.cur
.fetchone()
487 used_
= int(used
['hugepages_consumed']) if used
!= None else 0
488 numa
['hugepages_consumed'] = used_
490 #cmd = "CALL GetPortsFromNuma(%s)'" % str(numa['id'])
491 #self.cur.callproc('GetPortsFromNuma', (numa['id'],) )
492 #every time a Procedure is launched you need to close and open the cursor
493 #under Error 2014: Commands out of sync; you can't run this command now
495 #self.cur = self.con.cursor(mdb.cursors.DictCursor)
496 cmd
="SELECT Mbps, pci, status, Mbps_used, instance_id, if(id=root_id,'PF','VF') as type_,\
497 switch_port, switch_dpid, mac, source_name\
498 FROM resources_port WHERE numa_id=%d ORDER BY root_id, type_ DESC" % (numa
['id'])
499 self
.logger
.debug(cmd
)
500 self
.cur
.execute(cmd
)
501 ifaces
= self
.cur
.fetchall()
502 #The SQL query will ensure to have SRIOV interfaces from a port first
505 numa
['interfaces'] = []
507 if not iface
["instance_id"]:
508 del iface
["instance_id"]
509 if iface
['status'] == 'ok':
511 Mpbs_consumed
+= int(iface
["Mbps_used"])
512 del iface
["Mbps_used"]
513 if iface
["type_"]=='PF':
514 if not iface
["switch_dpid"]:
515 del iface
["switch_dpid"]
516 if not iface
["switch_port"]:
517 del iface
["switch_port"]
519 iface
["sriovs"] = sriovs
521 iface
["Mpbs_consumed"] = Mpbs_consumed
523 numa
['interfaces'].append(iface
)
527 del iface
["switch_port"]
528 del iface
["switch_dpid"]
533 #delete internal field
536 except (mdb
.Error
, AttributeError) as e
:
537 r
,c
= self
.format_error(e
, "get_host", cmd
)
538 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
543 uuid
= str( myUuid
.uuid1() )
544 if self
.check_uuid(uuid
)[0] == 0:
549 def check_uuid(self
, uuid
):
550 '''check in the database if this uuid is already present'''
552 cmd
= "SELECT * FROM uuids where uuid='" + str(uuid
) + "'"
554 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
555 self
.logger
.debug(cmd
)
556 self
.cur
.execute(cmd
)
557 rows
= self
.cur
.fetchall()
558 return self
.cur
.rowcount
, rows
559 except (mdb
.Error
, AttributeError) as e
:
560 return self
.format_error(e
, "check_uuid", cmd
)
562 def __get_next_ids(self
):
563 '''get next auto increment index of all table in the database'''
564 self
.cur
.execute("SELECT table_name,AUTO_INCREMENT FROM information_schema.tables WHERE AUTO_INCREMENT IS NOT NULL AND table_schema = DATABASE()")
565 rows
= self
.cur
.fetchall()
566 return self
.cur
.rowcount
, dict(rows
)
568 def edit_host(self
, host_id
, host_dict
):
570 for retry_
in range(0,2):
574 self
.cur
= self
.con
.cursor()
577 numa_list
= host_dict
.pop('numas', () )
579 self
._update
_rows
_internal
("hosts", host_dict
, {"uuid": host_id
})
581 where
= {"host_id": host_id
}
582 for numa_dict
in numa_list
:
583 where
["numa_socket"] = str(numa_dict
.pop('numa_socket'))
584 interface_list
= numa_dict
.pop('interfaces', () )
586 self
._update
_rows
_internal
("numas", numa_dict
, where
)
587 for interface
in interface_list
:
588 source_name
= str(interface
.pop("source_name") )
590 #get interface id from resources_port
591 cmd
= "SELECT rp.id as id FROM resources_port as rp join numas as n on n.id=rp.numa_id join hosts as h on h.uuid=n.host_id " +\
592 "WHERE host_id='%s' and rp.source_name='%s'" %(host_id
, source_name
)
593 self
.logger
.debug(cmd
)
594 self
.cur
.execute(cmd
)
595 row
= self
.cur
.fetchone()
596 if self
.cur
.rowcount
<=0:
597 return -HTTP_Bad_Request
, "Interface source_name='%s' from numa_socket='%s' not found" % (source_name
, str(where
["numa_socket"]))
598 interface_id
= row
[0]
599 self
._update
_rows
_internal
("resources_port", interface
, {"root_id": interface_id
})
600 return self
.get_host(host_id
)
601 except (mdb
.Error
, AttributeError) as e
:
602 r
,c
= self
.format_error(e
, "edit_host", cmd
)
603 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
605 def new_host(self
, host_dict
):
607 for retry_
in range(0,2):
611 self
.cur
= self
.con
.cursor()
613 result
, next_ids
= self
.__get
_next
_ids
()
614 #print "next_ids: " + str(next_ids)
615 if result
<= 0: return result
, "Internal DataBase error getting next id of tables"
617 #create uuid if not provided
618 if 'uuid' not in host_dict
:
619 uuid
= host_dict
['uuid'] = str(myUuid
.uuid1()) # create_uuid
620 else: #check uuid is valid
621 uuid
= str(host_dict
['uuid'])
622 # result, data = self.check_uuid(uuid)
624 # return -1, "UUID '%s' already in use" % uuid
627 cmd
= "INSERT INTO uuids (uuid, used_at) VALUES ('%s','hosts')" % uuid
628 self
.logger
.debug(cmd
)
629 result
= self
.cur
.execute(cmd
)
631 #insert in table host
632 numa_list
= host_dict
.pop('numas', [])
633 #get nonhupages and nonisolated cpus
636 for numa
in numa_list
:
637 mem_numa
= numa
.get('memory', 0) - numa
.get('hugepages',0)
639 host_dict
['RAM'] += mem_numa
640 for core
in numa
.get("cores", []):
641 if "status" in core
and core
["status"]=="noteligible":
643 host_dict
['RAM']*=1024 # from GB to MB
645 keys
= ",".join(host_dict
.keys())
646 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", host_dict
.values() ) )
647 cmd
= "INSERT INTO hosts (" + keys
+ ") VALUES (" + values
+ ")"
648 self
.logger
.debug(cmd
)
649 result
= self
.cur
.execute(cmd
)
650 #if result != 1: return -1, "Database Error while inserting at hosts table"
653 nb_numas
= nb_cores
= nb_ifaces
= 0
654 for numa_dict
in numa_list
:
656 interface_list
= numa_dict
.pop('interfaces', [])
657 core_list
= numa_dict
.pop('cores', [])
658 numa_dict
['id'] = next_ids
['numas']; next_ids
['numas'] += 1
659 numa_dict
['host_id'] = uuid
660 keys
= ",".join(numa_dict
.keys())
661 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", numa_dict
.values() ) )
662 cmd
= "INSERT INTO numas (" + keys
+ ") VALUES (" + values
+ ")"
663 self
.logger
.debug(cmd
)
664 result
= self
.cur
.execute(cmd
)
667 for core_dict
in core_list
:
669 core_dict
['numa_id'] = numa_dict
['id']
670 keys
= ",".join(core_dict
.keys())
671 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", core_dict
.values() ) )
672 cmd
= "INSERT INTO resources_core (" + keys
+ ") VALUES (" + values
+ ")"
673 self
.logger
.debug(cmd
)
674 result
= self
.cur
.execute(cmd
)
677 for port_dict
in interface_list
:
679 sriov_list
= port_dict
.pop('sriovs', [])
680 port_dict
['numa_id'] = numa_dict
['id']
681 port_dict
['id'] = port_dict
['root_id'] = next_ids
['resources_port']
682 next_ids
['resources_port'] += 1
683 switch_port
= port_dict
.get('switch_port', None)
684 switch_dpid
= port_dict
.get('switch_dpid', None)
685 keys
= ",".join(port_dict
.keys())
686 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", port_dict
.values() ) )
687 cmd
= "INSERT INTO resources_port (" + keys
+ ") VALUES (" + values
+ ")"
688 self
.logger
.debug(cmd
)
689 result
= self
.cur
.execute(cmd
)
691 #insert sriovs into port table
692 for sriov_dict
in sriov_list
:
693 sriov_dict
['switch_port'] = switch_port
694 sriov_dict
['switch_dpid'] = switch_dpid
695 sriov_dict
['numa_id'] = port_dict
['numa_id']
696 sriov_dict
['Mbps'] = port_dict
['Mbps']
697 sriov_dict
['root_id'] = port_dict
['id']
698 sriov_dict
['id'] = next_ids
['resources_port']
699 if "vlan" in sriov_dict
:
700 del sriov_dict
["vlan"]
701 next_ids
['resources_port'] += 1
702 keys
= ",".join(sriov_dict
.keys())
703 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", sriov_dict
.values() ) )
704 cmd
= "INSERT INTO resources_port (" + keys
+ ") VALUES (" + values
+ ")"
705 self
.logger
.debug(cmd
)
706 result
= self
.cur
.execute(cmd
)
709 #cmd = "INSERT INTO logs (related,level,uuid,description) VALUES ('hosts','debug','%s','new host: %d numas, %d theads, %d ifaces')" % (uuid, nb_numas, nb_cores, nb_ifaces)
710 #self.logger.debug(cmd)
711 #result = self.cur.execute(cmd)
715 self
.cur
= self
.con
.cursor()
716 self
.logger
.debug("callproc('UpdateSwitchPort', () )")
717 self
.cur
.callproc('UpdateSwitchPort', () )
719 self
.logger
.debug("getting host '%s'",str(host_dict
['uuid']))
720 return self
.get_host(host_dict
['uuid'])
721 except (mdb
.Error
, AttributeError) as e
:
722 r
,c
= self
.format_error(e
, "new_host", cmd
)
723 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
725 def new_flavor(self
, flavor_dict
, tenant_id
):
726 '''Add new flavor into the database. Create uuid if not provided
728 flavor_dict: flavor dictionary with the key: value to insert. Must be valid flavors columns
729 tenant_id: if not 'any', it matches this flavor/tenant inserting at tenants_flavors table
730 Return: (result, data) where result can be
731 negative: error at inserting. data contain text
732 1, inserted, data contain inserted uuid flavor
734 for retry_
in range(0,2):
738 self
.cur
= self
.con
.cursor()
740 #create uuid if not provided
741 if 'uuid' not in flavor_dict
:
742 uuid
= flavor_dict
['uuid'] = str(myUuid
.uuid1()) # create_uuid
743 else: #check uuid is valid
744 uuid
= str(flavor_dict
['uuid'])
745 # result, data = self.check_uuid(uuid)
747 # return -1, "UUID '%s' already in use" % uuid
750 cmd
= "INSERT INTO uuids (uuid, used_at) VALUES ('%s','flavors')" % uuid
751 self
.logger
.debug(cmd
)
752 self
.cur
.execute(cmd
)
754 #insert in table flavor
755 keys
= ",".join(flavor_dict
.keys())
756 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", flavor_dict
.values() ) )
757 cmd
= "INSERT INTO flavors (" + keys
+ ") VALUES (" + values
+ ")"
758 self
.logger
.debug(cmd
)
759 self
.cur
.execute(cmd
)
760 #if result != 1: return -1, "Database Error while inserting at flavors table"
762 #insert tenants_flavors
763 if tenant_id
!= 'any':
764 cmd
= "INSERT INTO tenants_flavors (tenant_id,flavor_id) VALUES ('%s','%s')" % (tenant_id
, uuid
)
765 self
.logger
.debug(cmd
)
766 self
.cur
.execute(cmd
)
769 #del flavor_dict['uuid']
770 #if 'extended' in flavor_dict: del flavor_dict['extended'] #remove two many information
771 #cmd = "INSERT INTO logs (related,level,uuid, tenant_id, description) VALUES ('flavors','debug','%s','%s',\"new flavor: %s\")" \
772 # % (uuid, tenant_id, str(flavor_dict))
773 #self.logger.debug(cmd)
774 #self.cur.execute(cmd)
778 except (mdb
.Error
, AttributeError) as e
:
779 r
,c
= self
.format_error(e
, "new_flavor", cmd
, "update", tenant_id
)
780 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
782 def new_image(self
, image_dict
, tenant_id
):
783 '''Add new image into the database. Create uuid if not provided
785 image_dict: image dictionary with the key: value to insert. Must be valid images columns
786 tenant_id: if not 'any', it matches this image/tenant inserting at tenants_images table
787 Return: (result, data) where result can be
788 negative: error at inserting. data contain text
789 1, inserted, data contain inserted uuid image
791 for retry_
in range(0,2):
795 self
.cur
= self
.con
.cursor()
797 #create uuid if not provided
798 if 'uuid' not in image_dict
:
799 uuid
= image_dict
['uuid'] = str(myUuid
.uuid1()) # create_uuid
800 else: #check uuid is valid
801 uuid
= str(image_dict
['uuid'])
802 # result, data = self.check_uuid(uuid)
804 # return -1, "UUID '%s' already in use" % uuid
807 cmd
= "INSERT INTO uuids (uuid, used_at) VALUES ('%s','images')" % uuid
808 self
.logger
.debug(cmd
)
809 self
.cur
.execute(cmd
)
811 #insert in table image
812 keys
= ",".join(image_dict
.keys())
813 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", image_dict
.values() ) )
814 cmd
= "INSERT INTO images (" + keys
+ ") VALUES (" + values
+ ")"
815 self
.logger
.debug(cmd
)
816 self
.cur
.execute(cmd
)
817 #if result != 1: return -1, "Database Error while inserting at images table"
819 #insert tenants_images
820 if tenant_id
!= 'any':
821 cmd
= "INSERT INTO tenants_images (tenant_id,image_id) VALUES ('%s','%s')" % (tenant_id
, uuid
)
822 self
.logger
.debug(cmd
)
823 self
.cur
.execute(cmd
)
826 #cmd = "INSERT INTO logs (related,level,uuid, tenant_id, description) VALUES ('images','debug','%s','%s',\"new image: %s path: %s\")" % (uuid, tenant_id, image_dict['name'], image_dict['path'])
827 #self.logger.debug(cmd)
828 #self.cur.execute(cmd)
832 except (mdb
.Error
, AttributeError) as e
:
833 r
,c
= self
.format_error(e
, "new_image", cmd
, "update", tenant_id
)
834 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
836 def delete_image_flavor(self
, item_type
, item_id
, tenant_id
):
837 '''deletes an image or flavor from database
838 item_type must be a 'image' or 'flavor'
840 tenant_id is the asociated tenant, can be 'any' with means all
841 If tenan_id is not any, it deletes from tenants_images/flavors,
842 which means this image/flavor is used by this tenant, and if success,
843 it tries to delete from images/flavors in case this is not public,
844 that only will success if image is private and not used by other tenants
845 If tenant_id is any, it tries to delete from both tables at the same transaction
846 so that image/flavor is completely deleted from all tenants or nothing
848 for retry_
in range(0,2):
851 result
= (-HTTP_Internal_Server_Error
, "internal error")
855 self
.cur
= self
.con
.cursor()
856 cmd
= "DELETE FROM tenants_%ss WHERE %s_id = '%s'" % (item_type
, item_type
, item_id
)
857 if tenant_id
!= 'any':
858 cmd
+= " AND tenant_id = '%s'" % tenant_id
859 self
.logger
.debug(cmd
)
860 self
.cur
.execute(cmd
)
861 deleted
= self
.cur
.rowcount
862 if tenant_id
== 'any': #delete from images/flavors in the SAME transaction
863 cmd
= "DELETE FROM %ss WHERE uuid = '%s'" % (item_type
, item_id
)
864 self
.logger
.debug(cmd
)
865 self
.cur
.execute(cmd
)
866 deleted
= self
.cur
.rowcount
869 cmd
= "DELETE FROM uuids WHERE uuid = '%s'" % item_id
870 self
.logger
.debug(cmd
)
871 self
.cur
.execute(cmd
)
873 #cmd = "INSERT INTO logs (related,level,uuid,tenant_id,description) \
874 # VALUES ('%ss','debug','%s','%s','delete %s completely')" % \
875 # (item_type, item_id, tenant_id, item_type)
876 #self.logger.debug(cmd)
877 #self.cur.execute(cmd)
878 return deleted
, "%s '%s' completely deleted" % (item_type
, item_id
)
879 return 0, "%s '%s' not found" % (item_type
, item_id
)
883 #cmd = "INSERT INTO logs (related,level,uuid,tenant_id,description) \
884 # VALUES ('%ss','debug','%s','%s','delete %s reference for this tenant')" % \
885 # (item_type, item_id, tenant_id, item_type)
886 #self.logger.debug(cmd)
887 #self.cur.execute(cmd)
891 #if tenant!=any delete from images/flavors in OTHER transaction. If fails is because dependencies so that not return error
894 self
.cur
= self
.con
.cursor()
896 #delete image/flavor if not public
897 cmd
= "DELETE FROM %ss WHERE uuid = '%s' AND public = 'no'" % (item_type
, item_id
)
898 self
.logger
.debug(cmd
)
899 self
.cur
.execute(cmd
)
900 deleted_item
= self
.cur
.rowcount
901 if deleted_item
== 1:
903 cmd
= "DELETE FROM uuids WHERE uuid = '%s'" % item_id
904 self
.logger
.debug(cmd
)
905 self
.cur
.execute(cmd
)
907 #cmd = "INSERT INTO logs (related,level,uuid,tenant_id,description) \
908 # VALUES ('%ss','debug','%s','%s','delete %s completely')" % \
909 # (item_type, item_id, tenant_id, item_type)
910 #self.logger.debug(cmd)
911 #self.cur.execute(cmd)
912 except (mdb
.Error
, AttributeError) as e
:
913 #print "delete_%s DB Exception %d: %s" % (item_type, e.args[0], e.args[1])
915 result
= self
.format_error(e
, "delete_"+item_type
, cmd
, "delete", "servers")
918 return 1, "%s '%s' from tenant '%s' %sdeleted" % \
919 (item_type
, item_id
, tenant_id
, "completely " if deleted_item
==1 else "")
921 return 0, "%s '%s' from tenant '%s' not found" % (item_type
, item_id
, tenant_id
)
923 if result
[0]!=-HTTP_Request_Timeout
or retry_
==1: return result
925 def delete_row(self
, table
, uuid
):
926 for retry_
in range(0,2):
931 self
.cur
= self
.con
.cursor()
932 cmd
= "DELETE FROM %s WHERE uuid = '%s'" % (table
, uuid
)
933 self
.logger
.debug(cmd
)
934 self
.cur
.execute(cmd
)
935 deleted
= self
.cur
.rowcount
938 if table
== 'tenants': tenant_str
=uuid
939 else: tenant_str
='Null'
940 self
.cur
= self
.con
.cursor()
941 cmd
= "DELETE FROM uuids WHERE uuid = '%s'" % uuid
942 self
.logger
.debug(cmd
)
943 self
.cur
.execute(cmd
)
945 #cmd = "INSERT INTO logs (related,level,uuid,tenant_id,description) VALUES ('%s','debug','%s','%s','delete %s')" % (table, uuid, tenant_str, table[:-1])
946 #self.logger.debug(cmd)
947 #self.cur.execute(cmd)
948 return deleted
, table
[:-1] + " '%s' %s" %(uuid
, "deleted" if deleted
==1 else "not found")
949 except (mdb
.Error
, AttributeError) as e
:
950 r
,c
= self
.format_error(e
, "delete_row", cmd
, "delete", 'instances' if table
=='hosts' or table
=='tenants' else 'dependencies')
951 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
953 def delete_row_by_key(self
, table
, key
, value
):
954 for retry_
in range(0,2):
959 self
.cur
= self
.con
.cursor()
960 cmd
= "DELETE FROM %s" % (table
)
963 cmd
+= " WHERE %s = '%s'" % (key
, value
)
965 cmd
+= " WHERE %s is null" % (key
)
968 self
.logger
.debug(cmd
)
969 self
.cur
.execute(cmd
)
970 deleted
= self
.cur
.rowcount
972 return -1, 'Not found'
975 except (mdb
.Error
, AttributeError) as e
:
976 r
,c
= self
.format_error(e
, "delete_row_by_key", cmd
, "delete", 'instances' if table
=='hosts' or table
=='tenants' else 'dependencies')
977 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
979 def delete_row_by_dict(self
, **sql_dict
):
980 ''' Deletes rows from a table.
981 Attribute sql_dir: dictionary with the following key: value
982 'FROM': string of table name (Mandatory)
983 'WHERE': dict of key:values, translated to key=value AND ... (Optional)
984 'WHERE_NOT': dict of key:values, translated to key<>value AND ... (Optional)
985 'WHERE_NOTNULL': (list or tuple of items that must not be null in a where ... (Optional)
986 'LIMIT': limit of number of rows (Optional)
987 Return: the (number of items deleted, descriptive test) if ok; (negative, descriptive text) if error
990 from_
= "FROM " + str(sql_dict
['FROM'])
991 #print 'from_', from_
992 if 'WHERE' in sql_dict
and len(sql_dict
['WHERE']) > 0:
994 where_
= "WHERE " + " AND ".join(map( lambda x
: str(x
) + (" is Null" if w
[x
] is None else "='"+str(w
[x
])+"'"), w
.keys()) )
996 if 'WHERE_NOT' in sql_dict
and len(sql_dict
['WHERE_NOT']) > 0:
997 w
=sql_dict
['WHERE_NOT']
998 where_2
= " AND ".join(map( lambda x
: str(x
) + (" is not Null" if w
[x
] is None else "<>'"+str(w
[x
])+"'"), w
.keys()) )
999 if len(where_
)==0: where_
= "WHERE " + where_2
1000 else: where_
= where_
+ " AND " + where_2
1001 if 'WHERE_NOTNULL' in sql_dict
and len(sql_dict
['WHERE_NOTNULL']) > 0:
1002 w
=sql_dict
['WHERE_NOTNULL']
1003 where_2
= " AND ".join(map( lambda x
: str(x
) + " is not Null", w
) )
1004 if len(where_
)==0: where_
= "WHERE " + where_2
1005 else: where_
= where_
+ " AND " + where_2
1006 #print 'where_', where_
1007 limit_
= "LIMIT " + str(sql_dict
['LIMIT']) if 'LIMIT' in sql_dict
else ""
1008 #print 'limit_', limit_
1009 cmd
= " ".join( ("DELETE", from_
, where_
, limit_
) )
1010 self
.logger
.debug(cmd
)
1011 for retry_
in range(0,2):
1015 self
.cur
= self
.con
.cursor()
1016 self
.cur
.execute(cmd
)
1017 deleted
= self
.cur
.rowcount
1018 return deleted
, "%d deleted from %s" % (deleted
, sql_dict
['FROM'][:-1] )
1019 except (mdb
.Error
, AttributeError) as e
:
1020 r
,c
= self
.format_error(e
, "delete_row_by_dict", cmd
, "delete", 'dependencies')
1021 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1024 def get_instance(self
, instance_id
):
1025 for retry_
in range(0,2):
1029 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1031 cmd
= "SELECT uuid, name, description, progress, host_id, flavor_id, image_id, status, last_error, "\
1032 "tenant_id, ram, vcpus, created_at FROM instances WHERE uuid='{}'".format(instance_id
)
1033 self
.logger
.debug(cmd
)
1034 self
.cur
.execute(cmd
)
1035 if self
.cur
.rowcount
== 0 : return 0, "instance '" + str(instance_id
) +"'not found."
1036 instance
= self
.cur
.fetchone()
1038 cmd
= "SELECT uuid as iface_id, net_id, mac as mac_address, ip_address, name, Mbps as bandwidth, "\
1039 "vpci, model FROM ports WHERE (type='instance:bridge' or type='instance:ovs') AND "\
1040 "instance_id= '{}'".format(instance_id
)
1041 self
.logger
.debug(cmd
)
1042 self
.cur
.execute(cmd
)
1043 if self
.cur
.rowcount
> 0 :
1044 instance
['networks'] = self
.cur
.fetchall()
1049 cmd
= "SELECT type, vpci, image_id, xml,dev FROM instance_devices WHERE instance_id = '%s' " % str(instance_id
)
1050 self
.logger
.debug(cmd
)
1051 self
.cur
.execute(cmd
)
1052 if self
.cur
.rowcount
> 0 :
1053 extended
['devices'] = self
.cur
.fetchall()
1056 cmd
= "SELECT id, numa_socket as source FROM numas WHERE host_id = '" + str(instance
['host_id']) + "'"
1057 self
.logger
.debug(cmd
)
1058 self
.cur
.execute(cmd
)
1059 host_numas
= self
.cur
.fetchall()
1060 #print 'host_numas', host_numas
1061 for k
in host_numas
:
1062 numa_id
= str(k
['id'])
1065 cmd
= "SELECT consumed FROM resources_mem WHERE instance_id = '%s' AND numa_id = '%s'" % ( instance_id
, numa_id
)
1066 self
.logger
.debug(cmd
)
1067 self
.cur
.execute(cmd
)
1068 if self
.cur
.rowcount
> 0:
1069 mem_dict
= self
.cur
.fetchone()
1070 numa_dict
['memory'] = mem_dict
['consumed']
1072 cursor2
= self
.con
.cursor()
1073 cmd
= "SELECT core_id, paired, MIN(v_thread_id) as v1, MAX(v_thread_id) as v2, COUNT(instance_id) as nb, MIN(thread_id) as t1, MAX(thread_id) as t2 FROM resources_core WHERE instance_id = '%s' AND numa_id = '%s' GROUP BY core_id,paired" % ( str(instance_id
), numa_id
)
1074 self
.logger
.debug(cmd
)
1075 cursor2
.execute(cmd
)
1076 core_list
= []; core_source
= []
1077 paired_list
= []; paired_source
= []
1078 thread_list
= []; thread_source
= []
1079 if cursor2
.rowcount
> 0:
1080 cores
= cursor2
.fetchall()
1082 if core
[4] == 2: #number of used threads from core
1083 if core
[3] == core
[2]: #only one thread asigned to VM, so completely core
1084 core_list
.append(core
[2])
1085 core_source
.append(core
[5])
1086 elif core
[1] == 'Y':
1087 paired_list
.append(core
[2:4])
1088 paired_source
.append(core
[5:7])
1090 thread_list
.extend(core
[2:4])
1091 thread_source
.extend(core
[5:7])
1094 thread_list
.append(core
[2])
1095 thread_source
.append(core
[5])
1096 if len(core_list
) > 0:
1097 numa_dict
['cores'] = len(core_list
)
1098 numa_dict
['cores-id'] = core_list
1099 numa_dict
['cores-source'] = core_source
1100 if len(paired_list
) > 0:
1101 numa_dict
['paired-threads'] = len(paired_list
)
1102 numa_dict
['paired-threads-id'] = paired_list
1103 numa_dict
['paired-threads-source'] = paired_source
1104 if len(thread_list
) > 0:
1105 numa_dict
['threads'] = len(thread_list
)
1106 numa_dict
['threads-id'] = thread_list
1107 numa_dict
['threads-source'] = thread_source
1109 #get dedicated ports and SRIOV
1110 cmd
= "SELECT port_id as iface_id, p.vlan as vlan, p.mac as mac_address, net_id, if(model='PF',\
1111 'yes',if(model='VF','no','yes:sriov')) as dedicated, rp.Mbps as bandwidth, name, vpci, \
1113 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
)
1114 self
.logger
.debug(cmd
)
1115 self
.cur
.execute(cmd
)
1116 if self
.cur
.rowcount
> 0:
1117 numa_dict
['interfaces'] = self
.cur
.fetchall()
1118 #print 'interfaces', numa_dict
1120 if len(numa_dict
) > 0 :
1121 numa_dict
['source'] = k
['source'] #numa socket
1122 numas
.append(numa_dict
)
1124 if len(numas
) > 0 : extended
['numas'] = numas
1125 if len(extended
) > 0 : instance
['extended'] = extended
1126 af
.DeleteNone(instance
)
1128 except (mdb
.Error
, AttributeError) as e
:
1129 r
,c
= self
.format_error(e
, "get_instance", cmd
)
1130 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1132 def get_numas(self
, requirements
, prefered_host_id
=None, only_of_ports
=True):
1133 '''Obtain a valid NUMA/HOST for deployment a VM
1134 requirements: contain requirement regarding:
1135 requirements['ram']: Non huge page memory in MB; 0 to skip
1136 requirements['vcpus']: Non isolated cpus; 0 to skip
1137 requirements['numa']: Requiremets to be fixed in ONE Numa node
1138 requirements['numa']['memory']: Huge page memory in GB at ; 0 for any
1139 requirements['numa']['proc_req_type']: Type of processor, cores or threads
1140 requirements['numa']['proc_req_nb']: Number of isolated cpus
1141 requirements['numa']['port_list']: Physical NIC ports list ; [] for any
1142 requirements['numa']['sriov_list']: Virtual function NIC ports list ; [] for any
1143 prefered_host_id: if not None return this host if it match
1144 only_of_ports: if True only those ports conected to the openflow (of) are valid,
1145 that is, with switch_port information filled; if False, all NIC ports are valid.
1146 Return a valid numa and host
1149 for retry_
in range(0,2):
1153 # #Find numas of prefered host
1154 # prefered_numas = ()
1155 # if prefered_host_id != None:
1156 # self.cur = self.con.cursor()
1157 # self.cur.execute("SELECT id FROM numas WHERE host_id='%s'" + prefered_host_id)
1158 # prefered_numas = self.cur.fetchall()
1161 #Find valid host for the ram and vcpus
1162 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1163 cmd
= "CALL GetHostByMemCpu(%s, %s)" % (str(requirements
['ram']), str(requirements
['vcpus']))
1164 self
.logger
.debug(cmd
)
1165 self
.cur
.callproc('GetHostByMemCpu', (str(requirements
['ram']), str(requirements
['vcpus'])) )
1166 valid_hosts
= self
.cur
.fetchall()
1168 self
.cur
= self
.con
.cursor()
1170 if len(valid_hosts
)<=0:
1171 error_text
= 'No room at data center. Can not find a host with %s MB memory and %s cpus available' % (str(requirements
['ram']), str(requirements
['vcpus']))
1172 #self.logger.debug(error_text)
1173 return -1, error_text
1175 #elif req_numa != None:
1176 #Find valid numa nodes for memory requirements
1177 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1178 cmd
= "CALL GetNumaByMemory(%s)" % str(requirements
['numa']['memory'])
1179 self
.logger
.debug(cmd
)
1180 self
.cur
.callproc('GetNumaByMemory', (requirements
['numa']['memory'],) )
1181 valid_for_memory
= self
.cur
.fetchall()
1183 self
.cur
= self
.con
.cursor()
1184 if len(valid_for_memory
)<=0:
1185 error_text
= 'No room at data center. Can not find a host with %s GB Hugepages memory available' % str(requirements
['numa']['memory'])
1186 #self.logger.debug(error_text)
1187 return -1, error_text
1189 #Find valid numa nodes for processor requirements
1190 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1191 if requirements
['numa']['proc_req_type'] == 'threads':
1192 cpu_requirement_text
='cpu-threads'
1193 cmd
= "CALL GetNumaByThread(%s)" % str(requirements
['numa']['proc_req_nb'])
1194 self
.logger
.debug(cmd
)
1195 self
.cur
.callproc('GetNumaByThread', (requirements
['numa']['proc_req_nb'],) )
1197 cpu_requirement_text
='cpu-cores'
1198 cmd
= "CALL GetNumaByCore(%s)" % str(requirements
['numa']['proc_req_nb'])
1199 self
.logger
.debug(cmd
)
1200 self
.cur
.callproc('GetNumaByCore', (requirements
['numa']['proc_req_nb'],) )
1201 valid_for_processor
= self
.cur
.fetchall()
1203 self
.cur
= self
.con
.cursor()
1204 if len(valid_for_processor
)<=0:
1205 error_text
= 'No room at data center. Can not find a host with %s %s available' % (str(requirements
['numa']['proc_req_nb']),cpu_requirement_text
)
1206 #self.logger.debug(error_text)
1207 return -1, error_text
1209 #Find the numa nodes that comply for memory and processor requirements
1210 #sorting from less to more memory capacity
1212 for m_numa
in valid_for_memory
:
1213 numa_valid_for_processor
= False
1214 for p_numa
in valid_for_processor
:
1215 if m_numa
['numa_id'] == p_numa
['numa_id']:
1216 numa_valid_for_processor
= True
1218 numa_valid_for_host
= False
1219 prefered_numa
= False
1220 for p_host
in valid_hosts
:
1221 if m_numa
['host_id'] == p_host
['uuid']:
1222 numa_valid_for_host
= True
1223 if p_host
['uuid'] == prefered_host_id
:
1224 prefered_numa
= True
1226 if numa_valid_for_host
and numa_valid_for_processor
:
1228 valid_numas
.insert(0, m_numa
['numa_id'])
1230 valid_numas
.append(m_numa
['numa_id'])
1231 if len(valid_numas
)<=0:
1232 error_text
= 'No room at data center. Can not find a host with %s MB hugepages memory and %s %s available in the same numa' %\
1233 (requirements
['numa']['memory'], str(requirements
['numa']['proc_req_nb']),cpu_requirement_text
)
1234 #self.logger.debug(error_text)
1235 return -1, error_text
1237 # print 'Valid numas list: '+str(valid_numas)
1239 #Find valid numa nodes for interfaces requirements
1240 #For each valid numa we will obtain the number of available ports and check if these are valid
1242 for numa_id
in valid_numas
:
1243 # print 'Checking '+str(numa_id)
1245 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1247 cmd
="CALL GetAvailablePorts(%s)" % str(numa_id
)
1248 self
.logger
.debug(cmd
)
1249 self
.cur
.callproc('GetAvailablePorts', (numa_id
,) )
1251 cmd
="CALL GetAllAvailablePorts(%s)" % str(numa_id
)
1252 self
.logger
.debug(cmd
)
1253 self
.cur
.callproc('GetAllAvailablePorts', (numa_id
,) )
1254 available_ports
= self
.cur
.fetchall()
1256 self
.cur
= self
.con
.cursor()
1258 #Set/reset reservations
1259 for port
in available_ports
:
1260 port
['Mbps_reserved'] = 0
1261 port
['SRIOV_reserved'] = 0
1263 #Try to allocate physical ports
1264 physical_ports_found
= True
1265 for iface
in requirements
['numa']['port_list']:
1266 # print '\t\tchecking iface: '+str(iface)
1268 for port
in available_ports
:
1269 # print '\t\t\tfor port: '+str(port)
1270 #If the port is not empty continue
1271 if port
['Mbps_free'] != port
['Mbps'] or port
['Mbps_reserved'] != 0:
1272 # print '\t\t\t\t Not empty port'
1274 #If the port speed is not enough continue
1275 if port
['Mbps'] < iface
['bandwidth']:
1276 # print '\t\t\t\t Not enough speed'
1279 #Otherwise this is a valid port
1280 port
['Mbps_reserved'] = port
['Mbps']
1281 port
['SRIOV_reserved'] = 0
1282 iface
['port_id'] = port
['port_id']
1283 iface
['vlan'] = None
1284 iface
['mac'] = port
['mac']
1285 iface
['switch_port'] = port
['switch_port']
1286 # print '\t\t\t\t Dedicated port found '+str(port['port_id'])
1290 #if all ports have been checked and no match has been found
1291 #this is not a valid numa
1293 # print '\t\t\t\t\tAll ports have been checked and no match has been found for numa '+str(numa_id)+'\n\n'
1294 physical_ports_found
= False
1297 #if there is no match continue checking the following numa
1298 if not physical_ports_found
:
1301 #Try to allocate SR-IOVs
1302 sriov_ports_found
= True
1303 for iface
in requirements
['numa']['sriov_list']:
1304 # print '\t\tchecking iface: '+str(iface)
1306 for port
in available_ports
:
1307 # print '\t\t\tfor port: '+str(port)
1308 #If there are not available SR-IOVs continue
1309 if port
['availableSRIOV'] - port
['SRIOV_reserved'] <= 0:
1310 # print '\t\t\t\t Not enough SR-IOV'
1312 #If the port free speed is not enough continue
1313 if port
['Mbps_free'] - port
['Mbps_reserved'] < iface
['bandwidth']:
1314 # print '\t\t\t\t Not enough speed'
1317 #Otherwise this is a valid port
1318 port
['Mbps_reserved'] += iface
['bandwidth']
1319 port
['SRIOV_reserved'] += 1
1320 # print '\t\t\t\t SR-IOV found '+str(port['port_id'])
1321 iface
['port_id'] = port
['port_id']
1322 iface
['vlan'] = None
1323 iface
['mac'] = port
['mac']
1324 iface
['switch_port'] = port
['switch_port']
1328 #if all ports have been checked and no match has been found
1329 #this is not a valid numa
1331 # print '\t\t\t\t\tAll ports have been checked and no match has been found for numa '+str(numa_id)+'\n\n'
1332 sriov_ports_found
= False
1335 #if there is no match continue checking the following numa
1336 if not sriov_ports_found
:
1340 if sriov_ports_found
and physical_ports_found
:
1345 error_text
= 'No room at data center. Can not find a host with the required hugepages, vcpus and interfaces'
1346 #self.logger.debug(error_text)
1347 return -1, error_text
1349 #self.logger.debug('Full match found in numa %s', str(numa_id))
1351 for numa
in valid_for_processor
:
1352 if numa_id
==numa
['numa_id']:
1353 host_id
=numa
['host_id']
1355 return 0, {'numa_id':numa_id
, 'host_id': host_id
, }
1356 except (mdb
.Error
, AttributeError) as e
:
1357 r
,c
= self
.format_error(e
, "get_numas", cmd
)
1358 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1360 def new_instance(self
, instance_dict
, nets
, ports_to_free
):
1361 for retry_
in range(0,2):
1365 self
.cur
= self
.con
.cursor()
1367 #create uuid if not provided
1368 if 'uuid' not in instance_dict
:
1369 uuid
= instance_dict
['uuid'] = str(myUuid
.uuid1()) # create_uuid
1370 else: #check uuid is valid
1371 uuid
= str(instance_dict
['uuid'])
1375 cmd
= "INSERT INTO uuids (uuid, root_uuid, used_at) VALUES ('%s','%s', 'instances')" % (uuid
, uuid
)
1376 self
.logger
.debug(cmd
)
1377 self
.cur
.execute(cmd
)
1379 #insert in table instance
1380 extended
= instance_dict
.pop('extended', None);
1381 bridgedifaces
= instance_dict
.pop('bridged-ifaces', () );
1383 keys
= ",".join(instance_dict
.keys())
1384 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", instance_dict
.values() ) )
1385 cmd
= "INSERT INTO instances (" + keys
+ ") VALUES (" + values
+ ")"
1386 self
.logger
.debug(cmd
)
1387 self
.cur
.execute(cmd
)
1388 #if result != 1: return -1, "Database Error while inserting at instances table"
1391 nb_bridge_ifaces
= nb_cores
= nb_ifaces
= nb_numas
= 0
1392 #insert bridged_ifaces
1394 for iface
in bridgedifaces
:
1395 #generate and insert a iface uuid
1396 if 'enable_dhcp' in iface
and iface
['enable_dhcp']:
1397 dhcp_first_ip
= iface
["dhcp_first_ip"]
1398 del iface
["dhcp_first_ip"]
1399 dhcp_last_ip
= iface
["dhcp_last_ip"]
1400 del iface
["dhcp_last_ip"]
1401 dhcp_cidr
= iface
["cidr"]
1403 del iface
["enable_dhcp"]
1404 used_dhcp_ips
= self
._get
_dhcp
_ip
_used
_list
(iface
["net_id"])
1405 iface
["ip_address"] = self
.get_free_ip_from_range(dhcp_first_ip
, dhcp_last_ip
,
1406 dhcp_cidr
, used_dhcp_ips
)
1408 iface
['uuid'] = str(myUuid
.uuid1()) # create_uuid
1409 cmd
= "INSERT INTO uuids (uuid, root_uuid, used_at) VALUES ('%s','%s', 'ports')" % (iface
['uuid'], uuid
)
1410 self
.logger
.debug(cmd
)
1411 self
.cur
.execute(cmd
)
1413 iface
['instance_id'] = uuid
1414 # iface['type'] = 'instance:bridge'
1415 if 'name' not in iface
: iface
['name']="br"+str(nb_bridge_ifaces
)
1416 iface
['Mbps']=iface
.pop('bandwidth', None)
1417 if 'mac_address' not in iface
:
1418 iface
['mac'] = af
.gen_random_mac()
1420 iface
['mac'] = iface
['mac_address']
1421 del iface
['mac_address']
1422 #iface['mac']=iface.pop('mac_address', None) #for leaving mac generation to libvirt
1423 keys
= ",".join(iface
.keys())
1424 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", iface
.values() ) )
1425 cmd
= "INSERT INTO ports (" + keys
+ ") VALUES (" + values
+ ")"
1426 self
.logger
.debug(cmd
)
1427 self
.cur
.execute(cmd
)
1428 nb_bridge_ifaces
+= 1
1430 if extended
is not None:
1431 if 'numas' not in extended
or extended
['numas'] is None: extended
['numas'] = ()
1432 for numa
in extended
['numas']:
1435 if 'cores' not in numa
or numa
['cores'] is None: numa
['cores'] = ()
1436 for core
in numa
['cores']:
1438 cmd
= "UPDATE resources_core SET instance_id='%s'%s%s WHERE id='%s'" \
1440 (",v_thread_id='" + str(core
['vthread']) + "'") if 'vthread' in core
else '', \
1441 (",paired='" + core
['paired'] + "'") if 'paired' in core
else '', \
1443 self
.logger
.debug(cmd
)
1444 self
.cur
.execute(cmd
)
1446 if 'interfaces' not in numa
or numa
['interfaces'] is None: numa
['interfaces'] = ()
1447 for iface
in numa
['interfaces']:
1448 #generate and insert an uuid; iface[id]=iface_uuid; iface[uuid]= net_id
1449 iface
['id'] = str(myUuid
.uuid1()) # create_uuid
1450 cmd
= "INSERT INTO uuids (uuid, root_uuid, used_at) VALUES ('%s','%s', 'ports')" % (iface
['id'], uuid
)
1451 self
.logger
.debug(cmd
)
1452 self
.cur
.execute(cmd
)
1454 mbps_
=("'"+str(iface
['Mbps_used'])+"'") if 'Mbps_used' in iface
and iface
['Mbps_used'] is not None else "Mbps"
1455 if iface
["dedicated"]=="yes":
1457 elif iface
["dedicated"]=="yes:sriov":
1458 iface_model
="VFnotShared"
1459 elif iface
["dedicated"]=="no":
1462 INSERT
=(iface
['mac_address'], iface
['switch_port'], iface
.get('vlan',None), 'instance:data', iface
['Mbps_used'], iface
['id'],
1463 uuid
, instance_dict
['tenant_id'], iface
.get('name',None), iface
.get('vpci',None), iface
.get('uuid',None), iface_model
)
1464 cmd
= "INSERT INTO ports (mac,switch_port,vlan,type,Mbps,uuid,instance_id,tenant_id,name,vpci,net_id, model) " + \
1465 " VALUES (" + ",".join(map(lambda x
: 'Null' if x
is None else "'"+str(x
)+"'", INSERT
)) + ")"
1466 self
.logger
.debug(cmd
)
1467 self
.cur
.execute(cmd
)
1469 nets
.append(iface
['uuid'])
1471 #discover if this port is not used by anyone
1472 cmd
= "SELECT source_name, mac FROM ( SELECT root_id, count(instance_id) as used FROM resources_port" \
1473 " WHERE root_id=(SELECT root_id from resources_port WHERE id='%s')"\
1474 " GROUP BY root_id ) AS A JOIN resources_port as B ON A.root_id=B.id AND A.used=0" % iface
['port_id']
1475 self
.logger
.debug(cmd
)
1476 self
.cur
.execute(cmd
)
1477 ports_to_free
+= self
.cur
.fetchall()
1479 cmd
= "UPDATE resources_port SET instance_id='%s', port_id='%s',Mbps_used=%s WHERE id='%s'" \
1480 % (uuid
, iface
['id'], mbps_
, iface
['port_id'])
1481 #if Mbps_used not suply, set the same value of 'Mpbs', that is the total
1482 self
.logger
.debug(cmd
)
1483 self
.cur
.execute(cmd
)
1485 if 'memory' in numa
and numa
['memory'] is not None and numa
['memory']>0:
1486 cmd
= "INSERT INTO resources_mem (numa_id, instance_id, consumed) VALUES ('%s','%s','%s')" % (numa
['numa_id'], uuid
, numa
['memory'])
1487 self
.logger
.debug(cmd
)
1488 self
.cur
.execute(cmd
)
1489 if 'devices' not in extended
or extended
['devices'] is None: extended
['devices'] = ()
1490 for device
in extended
['devices']:
1491 if 'vpci' in device
: vpci
= "'" + device
['vpci'] + "'"
1493 if 'image_id' in device
: image_id
= "'" + device
['image_id'] + "'"
1494 else: image_id
= 'Null'
1495 if 'xml' in device
: xml
= "'" + device
['xml'] + "'"
1497 if 'dev' in device
: dev
= "'" + device
['dev'] + "'"
1499 cmd
= "INSERT INTO instance_devices (type, instance_id, image_id, vpci, xml, dev) VALUES ('%s','%s', %s, %s, %s, %s)" % \
1500 (device
['type'], uuid
, image_id
, vpci
, xml
, dev
)
1501 self
.logger
.debug(cmd
)
1502 self
.cur
.execute(cmd
)
1504 #cmd = "INSERT INTO logs (related,level,uuid,description) VALUES ('instances','debug','%s','new instance: %d numas, %d theads, %d ifaces %d bridge_ifaces')" % (uuid, nb_numas, nb_cores, nb_ifaces, nb_bridge_ifaces)
1505 #self.logger.debug(cmd)
1506 #self.cur.execute(cmd)
1510 except (mdb
.Error
, AttributeError) as e
:
1511 r
,c
= self
.format_error(e
, "new_instance", cmd
)
1512 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1514 def get_free_ip_from_range(self
, first_ip
, last_ip
, cidr
, ip_used_list
):
1516 Calculate a free IP from a range given
1517 :param first_ip: First dhcp ip range
1518 :param last_ip: Last dhcp ip range
1519 :param cidr: net cidr
1520 :param ip_used_list: contain all used ips to avoid ip collisions
1524 ip_tools
= IPNetwork(cidr
)
1525 cidr_len
= ip_tools
.prefixlen
1526 ips
= IPNetwork(first_ip
+ '/' + str(cidr_len
))
1527 ip_used_list
.append(str(ips
[0])) # first ip
1528 ip_used_list
.append(str(ips
[1])) # gw ip
1529 ip_used_list
.append(str(ips
[-1])) # broadcast ip
1531 if str(vm_ip
) not in ip_used_list
:
1536 def _get_dhcp_ip_used_list(self
, net_id
):
1538 REtreive from DB all ips already used by the dhcp server for a given net
1542 WHERE
={'type': 'instance:ovs', 'net_id': net_id
}
1543 for retry_
in range(0, 2):
1545 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1546 select_
= "SELECT uuid, ip_address FROM ports "
1548 if WHERE
is None or len(WHERE
) == 0:
1551 where_
= "WHERE " + " AND ".join(
1552 map(lambda x
: str(x
) + (" is Null" if WHERE
[x
] is None else "='" + str(WHERE
[x
]) + "'"),
1554 limit_
= "LIMIT 100"
1555 cmd
= " ".join((select_
, where_
, limit_
))
1556 self
.logger
.debug(cmd
)
1557 self
.cur
.execute(cmd
)
1558 ports
= self
.cur
.fetchall()
1559 ip_address_list
= []
1561 ip_address_list
.append(port
['ip_address'])
1563 return ip_address_list
1566 def delete_instance(self
, instance_id
, tenant_id
, net_dataplane_list
, ports_to_free
, net_ovs_list
, logcause
="requested by http"):
1567 for retry_
in range(0,2):
1571 self
.cur
= self
.con
.cursor()
1573 cmd
= "SELECT uuid FROM instances WHERE uuid='%s' AND tenant_id='%s'" % (instance_id
, tenant_id
)
1574 self
.logger
.debug(cmd
)
1575 self
.cur
.execute(cmd
)
1576 if self
.cur
.rowcount
== 0 : return 0, "instance %s not found in tenant %s" % (instance_id
, tenant_id
)
1578 #delete bridged ifaces, instace_devices, resources_mem; done by database: it is automatic by Database; FOREIGN KEY DELETE CASCADE
1581 cmd
= "SELECT DISTINCT net_id from ports WHERE instance_id = '%s' AND net_id is not Null AND type='instance:data'" % instance_id
1582 self
.logger
.debug(cmd
)
1583 self
.cur
.execute(cmd
)
1584 net_list__
= self
.cur
.fetchall()
1585 for net
in net_list__
:
1586 net_dataplane_list
.append(net
[0])
1588 # get ovs manangement nets
1589 cmd
= "SELECT DISTINCT net_id, vlan, ip_address, mac FROM ports WHERE instance_id='{}' AND net_id is not Null AND "\
1590 "type='instance:ovs'".format(instance_id
)
1591 self
.logger
.debug(cmd
)
1592 self
.cur
.execute(cmd
)
1593 net_ovs_list
+= self
.cur
.fetchall()
1595 #get dataplane interfaces releases by this VM; both PF and VF with no other VF
1596 cmd
="SELECT source_name, mac FROM (SELECT root_id, count(instance_id) as used FROM resources_port WHERE instance_id='%s' GROUP BY root_id ) AS A" % instance_id \
1597 + " JOIN (SELECT root_id, count(instance_id) as used FROM resources_port GROUP BY root_id) AS B ON A.root_id=B.root_id AND A.used=B.used"\
1598 + " JOIN resources_port as C ON A.root_id=C.id"
1599 # cmd = "SELECT DISTINCT root_id FROM resources_port WHERE instance_id = '%s'" % instance_id
1600 self
.logger
.debug(cmd
)
1601 self
.cur
.execute(cmd
)
1602 ports_to_free
+= self
.cur
.fetchall()
1604 #update resources port
1605 cmd
= "UPDATE resources_port SET instance_id=Null, port_id=Null, Mbps_used='0' WHERE instance_id = '%s'" % instance_id
1606 self
.logger
.debug(cmd
)
1607 self
.cur
.execute(cmd
)
1609 # #filter dataplane ports used by this VM that now are free
1610 # for port in ports_list__:
1611 # cmd = "SELECT mac, count(instance_id) FROM resources_port WHERE root_id = '%s'" % port[0]
1612 # self.logger.debug(cmd)
1613 # self.cur.execute(cmd)
1614 # mac_list__ = self.cur.fetchone()
1615 # if mac_list__ and mac_list__[1]==0:
1616 # ports_to_free.append(mac_list__[0])
1619 #update resources core
1620 cmd
= "UPDATE resources_core SET instance_id=Null, v_thread_id=Null, paired='N' WHERE instance_id = '%s'" % instance_id
1621 self
.logger
.debug(cmd
)
1622 self
.cur
.execute(cmd
)
1624 #delete all related uuids
1625 cmd
= "DELETE FROM uuids WHERE root_uuid='%s'" % instance_id
1626 self
.logger
.debug(cmd
)
1627 self
.cur
.execute(cmd
)
1630 #cmd = "INSERT INTO logs (related,level,uuid,description) VALUES ('instances','debug','%s','delete instance %s')" % (instance_id, logcause)
1631 #self.logger.debug(cmd)
1632 #self.cur.execute(cmd)
1635 cmd
= "DELETE FROM instances WHERE uuid='%s' AND tenant_id='%s'" % (instance_id
, tenant_id
)
1636 self
.cur
.execute(cmd
)
1637 return 1, "instance %s from tenant %s DELETED" % (instance_id
, tenant_id
)
1639 except (mdb
.Error
, AttributeError) as e
:
1640 r
,c
= self
.format_error(e
, "delete_instance", cmd
)
1641 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1643 def get_ports(self
, WHERE
):
1644 ''' Obtain ports using the WHERE filtering.
1646 'where_': dict of key:values, translated to key=value AND ... (Optional)
1647 Return: a list with dictionarys at each row
1649 for retry_
in range(0,2):
1654 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1655 select_
= "SELECT uuid,'ACTIVE' as status,admin_state_up,name,net_id,\
1656 tenant_id,type,mac,vlan,switch_port,instance_id,Mbps FROM ports "
1658 if WHERE
is None or len(WHERE
) == 0: where_
= ""
1660 where_
= "WHERE " + " AND ".join(map( lambda x
: str(x
) + (" is Null" if WHERE
[x
] is None else "='"+str(WHERE
[x
])+"'"), WHERE
.keys()) )
1661 limit_
= "LIMIT 100"
1662 cmd
= " ".join( (select_
, where_
, limit_
) )
1663 # print "SELECT multiple de instance_ifaces, iface_uuid, external_ports" #print cmd
1664 self
.logger
.debug(cmd
)
1665 self
.cur
.execute(cmd
)
1666 ports
= self
.cur
.fetchall()
1667 if self
.cur
.rowcount
>0: af
.DeleteNone(ports
)
1668 return self
.cur
.rowcount
, ports
1669 # return self.get_table(FROM=from_, SELECT=select_,WHERE=where_,LIMIT=100)
1670 except (mdb
.Error
, AttributeError) as e
:
1671 r
,c
= self
.format_error(e
, "get_ports", cmd
)
1672 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1674 def check_target_net(self
, net_id
, tenant_id
, port_type
):
1675 '''check if valid attachement of a port into a target net
1677 net_id: target net uuid
1678 tenant_id: client where tenant belongs. Not used in this version
1679 port_type: string with the option 'instance:bridge', 'instance:data', 'external'
1681 (0,net_dict) if ok, where net_dict contain 'uuid','type','vlan', ...
1682 (negative,string-error) if error
1684 for retry_
in range(0,2):
1688 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1689 cmd
= "SELECT * FROM nets WHERE uuid='%s'" % net_id
1690 self
.logger
.debug(cmd
)
1691 self
.cur
.execute(cmd
)
1692 if self
.cur
.rowcount
== 0 : return -1, "network_id %s does not match any net" % net_id
1693 net
= self
.cur
.fetchone()
1696 except (mdb
.Error
, AttributeError) as e
:
1697 r
,c
= self
.format_error(e
, "check_target_net", cmd
)
1698 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1700 if tenant_id
is not None and tenant_id
is not "admin":
1701 if net
['tenant_id']==tenant_id
and net
['shared']=='false':
1702 return -1, "needed admin privileges to attach to the net %s" % net_id
1704 if (net
['type'] in ('p2p','data') and port_type
!= 'instance:data') or \
1705 (net
['type'] in ('bridge_data','bridge_man') and port_type
not in ('instance:bridge', 'instance:ovs')):
1706 return -1, "can not attach a port of type %s into a net of type %s" % (port_type
, net
['type'])
1707 if net
['type'] == 'ptp':
1709 nb_ports
, data
= self
.get_ports( {'net_id':net_id
} )
1716 return -1, "net of type p2p already contain two ports attached. No room for another"
1720 if __name__
== "__main__":