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
41 HTTP_Bad_Request
= 400
42 HTTP_Unauthorized
= 401
44 HTTP_Method_Not_Allowed
= 405
45 HTTP_Request_Timeout
= 408
47 HTTP_Service_Unavailable
= 503
48 HTTP_Internal_Server_Error
= 500
52 def __init__(self
, vlan_range
, debug
="ERROR"):
53 '''vlan_range must be a tuple (vlan_ini, vlan_end) with available vlan values for networks
54 every dataplane network contain a unique value, regardless of it is used or not
57 self
.net_vlan_range
= vlan_range
58 self
.net_vlan_usedlist
= None
59 self
.net_vlan_lastused
= self
.net_vlan_range
[0] -1
61 self
.logger
= logging
.getLogger('vim.db')
62 self
.logger
.setLevel( getattr(logging
, debug
) )
65 def connect(self
, host
=None, user
=None, passwd
=None, database
=None):
66 '''Connect to the concrete data base.
67 The first time a valid host, user, passwd and database must be provided,
68 Following calls can skip this parameters
71 if host
is not None: self
.host
= host
72 if user
is not None: self
.user
= user
73 if passwd
is not None: self
.passwd
= passwd
74 if database
is not None: self
.database
= database
76 self
.con
= mdb
.connect(self
.host
, self
.user
, self
.passwd
, self
.database
)
77 self
.logger
.debug("connected to DB %s at %s@%s", self
.database
,self
.user
, self
.host
)
79 except mdb
.Error
as e
:
80 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])
83 def get_db_version(self
):
84 ''' Obtain the database schema version.
85 Return: (negative, text) if error or version 0.0 where schema_version table is missing
86 (version_int, version_text) if ok
88 cmd
= "SELECT version_int,version,openvim_ver FROM schema_version"
89 for retry_
in range(0,2):
92 self
.cur
= self
.con
.cursor()
93 self
.logger
.debug(cmd
)
95 rows
= self
.cur
.fetchall()
99 for row
in rows
: #look for the latest version
100 if row
[0]>highest_version_int
:
101 highest_version_int
, highest_version
= row
[0:2]
102 return highest_version_int
, highest_version
103 except (mdb
.Error
, AttributeError) as e
:
104 self
.logger
.error("get_db_version DB Exception %d: %s. Command %s",e
.args
[0], e
.args
[1], cmd
)
105 r
,c
= self
.format_error(e
)
106 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
108 def disconnect(self
):
109 '''disconnect from the data base'''
113 except mdb
.Error
as e
:
114 self
.logger
.error("while disconnecting from DB: Error %d: %s",e
.args
[0], e
.args
[1])
116 except AttributeError as e
: #self.con not defined
117 if e
[0][-5:] == "'con'": return -1, "Database internal error, no connection."
120 def format_error(self
, e
, func
, cmd
, command
=None, extra
=None):
121 '''Creates a text error base on the produced exception
124 func: name of the function that makes the call, for logging purposes
125 cmd: database command that produce the exception
126 command: if the intention is update or delete
127 extra: extra information to add to some commands
129 HTTP error in negative, formatted error text
132 self
.logger
.error("%s DB Exception %s. Command %s",func
, str(e
), cmd
)
133 if type(e
[0]) is str:
134 if e
[0][-5:] == "'con'": return -HTTP_Internal_Server_Error
, "DB Exception, no connection."
136 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
139 return -HTTP_Request_Timeout
,"Database reconnection. Try Again"
140 fk
=e
.args
[1].find("foreign key constraint fails")
142 if command
=="update": return -HTTP_Bad_Request
, "tenant_id %s not found." % extra
143 elif command
=="delete": return -HTTP_Bad_Request
, "Resource is not free. There are %s that prevent its deletion." % extra
144 de
= e
.args
[1].find("Duplicate entry")
145 fk
= e
.args
[1].find("for key")
146 uk
= e
.args
[1].find("Unknown column")
147 wc
= e
.args
[1].find("in 'where clause'")
148 fl
= e
.args
[1].find("in 'field list'")
149 #print de, fk, uk, wc,fl
151 if fk
>=0: #error 1062
152 return -HTTP_Conflict
, "Value %s already in use for %s" % (e
.args
[1][de
+15:fk
], e
.args
[1][fk
+7:])
155 return -HTTP_Bad_Request
, "Field %s can not be used for filtering" % e
.args
[1][uk
+14:wc
]
157 return -HTTP_Bad_Request
, "Field %s does not exist" % e
.args
[1][uk
+14:wc
]
158 return -HTTP_Internal_Server_Error
, "Database internal Error %d: %s" % (e
.args
[0], e
.args
[1])
160 def __data2db_format(self
, data
):
161 '''convert data to database format. If data is None it return the 'Null' text,
162 otherwise it return the text surrounded by quotes ensuring internal quotes are escaped'''
167 return "'" + out
+ "'"
169 return '"' + out
+ '"'
171 return json
.dumps(out
)
173 def __get_used_net_vlan(self
):
174 #get used from database if needed
176 cmd
= "SELECT vlan FROM nets WHERE vlan>='%s' ORDER BY vlan LIMIT 25" % self
.net_vlan_lastused
178 self
.cur
= self
.con
.cursor()
179 self
.logger
.debug(cmd
)
180 self
.cur
.execute(cmd
)
181 vlan_tuple
= self
.cur
.fetchall()
182 #convert a tuple of tuples in a list of numbers
183 self
.net_vlan_usedlist
= []
185 self
.net_vlan_usedlist
.append(k
[0])
187 except (mdb
.Error
, AttributeError) as e
:
188 return self
.format_error(e
, "get_free_net_vlan", cmd
)
190 def get_free_net_vlan(self
):
191 '''obtain a vlan not used in any net'''
194 self
.logger
.debug("net_vlan_lastused:%d net_vlan_range:%d-%d net_vlan_usedlist:%s",
195 self
.net_vlan_lastused
, self
.net_vlan_range
[0], self
.net_vlan_range
[1], str(self
.net_vlan_usedlist
))
196 self
.net_vlan_lastused
+= 1
197 if self
.net_vlan_lastused
== self
.net_vlan_range
[1]:
198 #start from the begining
199 self
.net_vlan_lastused
= self
.net_vlan_range
[0]
200 self
.net_vlan_usedlist
= None
201 if self
.net_vlan_usedlist
is None \
202 or (len(self
.net_vlan_usedlist
)>0 and self
.net_vlan_lastused
>= self
.net_vlan_usedlist
[-1] and len(self
.net_vlan_usedlist
)==25):
203 r
= self
.__get
_used
_net
_vlan
()
205 self
.logger
.debug("new net_vlan_usedlist %s", str(self
.net_vlan_usedlist
))
206 if self
.net_vlan_lastused
in self
.net_vlan_usedlist
:
209 return self
.net_vlan_lastused
211 def get_table(self
, **sql_dict
):
212 ''' Obtain rows from a table.
213 Atribure sql_dir: dictionary with the following key: value
214 'SELECT': [list of fields to retrieve] (by default all)
215 'FROM': string of table name (Mandatory)
216 'WHERE': dict of key:values, translated to key=value AND ... (Optional)
217 'WHERE_NOT': dict of key:values, translated to key!=value AND ... (Optional)
218 'WHERE_OR': dict of key:values, translated to key=value OR ... (Optional)
219 'LIMIT': limit of number of rows (Optional)
220 Return: a list with dictionarys at each row
223 select_
= "SELECT " + ("*" if 'SELECT' not in sql_dict
else ",".join(map(str,sql_dict
['SELECT'])) )
224 #print 'select_', select_
225 from_
= "FROM " + str(sql_dict
['FROM'])
226 #print 'from_', from_
230 if 'WHERE' in sql_dict
and len(sql_dict
['WHERE']) > 0:
232 where_and
= " AND ".join(map( lambda x
: str(x
) + (" is Null" if w
[x
] is None else "='"+str(w
[x
])+"'"), w
.keys()) )
233 if 'WHERE_NOT' in sql_dict
and len(sql_dict
['WHERE_NOT']) > 0:
234 w
=sql_dict
['WHERE_NOT']
235 where_and_not
= " AND ".join(map( lambda x
: str(x
) + (" is not Null" if w
[x
] is None else "!='"+str(w
[x
])+"'"), w
.keys()) )
237 where_and
+= " AND " + where_and_not
239 where_and
= where_and_not
240 if 'WHERE_OR' in sql_dict
and len(sql_dict
['WHERE_OR']) > 0:
241 w
=sql_dict
['WHERE_OR']
242 where_or
= " OR ".join(map( lambda x
: str(x
) + (" is Null" if w
[x
] is None else "='"+str(w
[x
])+"'"), w
.keys()) )
244 if where_and
!=None and where_or
!=None:
245 where_
= "WHERE (" + where_and
+ ") OR " + where_or
246 elif where_and
!=None and where_or
==None:
247 where_
= "WHERE " + where_and
248 elif where_and
==None and where_or
!=None:
249 where_
= "WHERE " + where_or
252 #print 'where_', where_
253 limit_
= "LIMIT " + str(sql_dict
['LIMIT']) if 'LIMIT' in sql_dict
else ""
254 #print 'limit_', limit_
255 cmd
= " ".join( (select_
, from_
, where_
, limit_
) )
256 for retry_
in range(0,2):
259 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
260 self
.logger
.debug(cmd
)
261 self
.cur
.execute(cmd
)
262 rows
= self
.cur
.fetchall()
263 return self
.cur
.rowcount
, rows
264 except (mdb
.Error
, AttributeError) as e
:
265 r
,c
= self
.format_error(e
, "get_table", cmd
)
266 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
268 def new_tenant(self
, tenant_dict
):
269 ''' Add one row into a table.
271 tenant_dict: dictionary with the key: value to insert
272 It checks presence of uuid and add one automatically otherwise
273 Return: (result, uuid) where result can be 0 if error, or 1 if ok
275 for retry_
in range(0,2):
279 #create uuid if not provided
280 if 'uuid' not in tenant_dict
:
281 uuid
= tenant_dict
['uuid'] = str(myUuid
.uuid1()) # create_uuid
283 uuid
= str(tenant_dict
['uuid'])
284 #obtain tenant_id for logs
287 self
.cur
= self
.con
.cursor()
289 cmd
= "INSERT INTO uuids (uuid, used_at) VALUES ('%s','tenants')" % uuid
290 self
.logger
.debug(cmd
)
291 self
.cur
.execute(cmd
)
293 cmd
= "INSERT INTO tenants (" + \
294 ",".join(map(str, tenant_dict
.keys() )) + ") VALUES(" + \
295 ",".join(map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'",tenant_dict
.values() )) + ")"
296 self
.logger
.debug(cmd
)
297 self
.cur
.execute(cmd
)
298 inserted
= self
.cur
.rowcount
300 #del tenant_dict['uuid'] # not interested for the log
301 #cmd = "INSERT INTO logs (related,level,tenant_id,uuid,description) VALUES ('tenants','debug','%s','%s',\"new tenant %s\")" % (uuid, tenant_id, str(tenant_dict))
302 #self.logger.debug(cmd)
303 #self.cur.execute(cmd)
306 if inserted
== 0: return 0, uuid
308 self
.cur
= self
.con
.cursor()
309 #adding public flavors
310 cmd
= "INSERT INTO tenants_flavors(flavor_id,tenant_id) SELECT uuid as flavor_id,'"+ tenant_id
+ "' FROM flavors WHERE public = 'yes'"
311 self
.logger
.debug(cmd
)
312 self
.cur
.execute(cmd
)
313 self
.logger
.debug("attached public flavors: %s", str(self
.cur
.rowcount
))
314 #rows = self.cur.fetchall()
316 # cmd = "INSERT INTO tenants_flavors(flavor_id,tenant_id) VALUES('%s','%s')" % (row[0], tenant_id)
317 # self.cur.execute(cmd )
318 #adding public images
319 cmd
= "INSERT INTO tenants_images(image_id,tenant_id) SELECT uuid as image_id,'"+ tenant_id
+ "' FROM images WHERE public = 'yes'"
320 self
.logger
.debug(cmd
)
321 self
.cur
.execute(cmd
)
322 self
.logger
.debug("attached public images: %s", str(self
.cur
.rowcount
))
324 except (mdb
.Error
, AttributeError) as e
:
326 self
.logger
.warning("new_tenant DB Exception %d: %s. Command %s",e
.args
[0], e
.args
[1], cmd
)
329 r
,c
= self
.format_error(e
, "new_tenant", cmd
)
330 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
332 def new_row(self
, table
, INSERT
, add_uuid
=False, log
=False):
333 ''' Add one row into a table.
335 INSERT: dictionary with the key: value to insert
336 table: table where to insert
337 add_uuid: if True, it will crated an uuid key entry at INSERT if not provided
338 It checks presence of uuid and add one automatically otherwise
339 Return: (result, uuid) where result can be 0 if error, or 1 if ok
341 for retry_
in range(0,2):
345 #create uuid if not provided
346 if 'uuid' not in INSERT
:
347 uuid
= INSERT
['uuid'] = str(myUuid
.uuid1()) # create_uuid
349 uuid
= str(INSERT
['uuid'])
353 self
.cur
= self
.con
.cursor()
356 cmd
= "INSERT INTO uuids (uuid, used_at) VALUES ('%s','%s')" % (uuid
, table
)
357 self
.logger
.debug(cmd
)
358 self
.cur
.execute(cmd
)
360 cmd
= "INSERT INTO " + table
+" (" + \
361 ",".join(map(str, INSERT
.keys() )) + ") VALUES(" + \
362 ",".join(map(lambda x
: 'Null' if x
is None else "'"+str(x
)+"'", INSERT
.values() )) + ")"
363 self
.logger
.debug(cmd
)
364 self
.cur
.execute(cmd
)
365 nb_rows
= self
.cur
.rowcount
367 #if nb_rows > 0 and log:
368 # if add_uuid: del INSERT['uuid']
369 # #obtain tenant_id for logs
370 # if 'tenant_id' in INSERT:
371 # tenant_id = INSERT['tenant_id']
372 # del INSERT['tenant_id']
373 # elif table == 'tenants':
377 # if uuid is None: uuid_k = uuid_v = ""
378 # else: uuid_k=",uuid"; uuid_v=",'" + str(uuid) + "'"
379 # if tenant_id is None: tenant_k = tenant_v = ""
380 # else: tenant_k=",tenant_id"; tenant_v=",'" + str(tenant_id) + "'"
381 # cmd = "INSERT INTO logs (related,level%s%s,description) VALUES ('%s','debug'%s%s,\"new %s %s\")" \
382 # % (uuid_k, tenant_k, table, uuid_v, tenant_v, table[:-1], str(INSERT))
383 # self.logger.debug(cmd)
384 # self.cur.execute(cmd)
387 except (mdb
.Error
, AttributeError) as e
:
388 r
,c
= self
.format_error(e
, "new_row", cmd
)
389 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
391 def __remove_quotes(self
, data
):
392 '''remove single quotes ' of any string content of data dictionary'''
393 for k
,v
in data
.items():
396 data
[k
] = data
[k
].replace("'","_")
398 def _update_rows_internal(self
, table
, UPDATE
, WHERE
={}):
399 cmd
= "UPDATE " + table
+" SET " + \
400 ",".join(map(lambda x
: str(x
)+'='+ self
.__data
2db
_format
(UPDATE
[x
]), UPDATE
.keys() ));
402 cmd
+= " WHERE " + " and ".join(map(lambda x
: str(x
)+ (' is Null' if WHERE
[x
] is None else"='"+str(WHERE
[x
])+"'" ), WHERE
.keys() ))
403 self
.logger
.debug(cmd
)
404 self
.cur
.execute(cmd
)
405 nb_rows
= self
.cur
.rowcount
408 def update_rows(self
, table
, UPDATE
, WHERE
={}, log
=False):
409 ''' Update one or several rows into a table.
411 UPDATE: dictionary with the key-new_value pairs to change
412 table: table to be modified
413 WHERE: dictionary to filter target rows, key-value
414 log: if true, a log entry is added at logs table
415 Return: (result, None) where result indicates the number of updated files
417 for retry_
in range(0,2):
421 uuid
= WHERE
.get('uuid')
424 self
.cur
= self
.con
.cursor()
425 cmd
= "UPDATE " + table
+" SET " + \
426 ",".join(map(lambda x
: str(x
)+'='+ self
.__data
2db
_format
(UPDATE
[x
]), UPDATE
.keys() ));
428 cmd
+= " WHERE " + " and ".join(map(lambda x
: str(x
)+ (' is Null' if WHERE
[x
] is None else"='"+str(WHERE
[x
])+"'" ), WHERE
.keys() ))
429 self
.logger
.debug(cmd
)
430 self
.cur
.execute(cmd
)
431 nb_rows
= self
.cur
.rowcount
432 #if nb_rows > 0 and log:
434 # if uuid is None: uuid_k = uuid_v = ""
435 # else: uuid_k=",uuid"; uuid_v=",'" + str(uuid) + "'"
436 # cmd = "INSERT INTO logs (related,level%s,description) VALUES ('%s','debug'%s,\"updating %d entry %s\")" \
437 # % (uuid_k, table, uuid_v, nb_rows, (str(UPDATE)).replace('"','-') )
438 # self.logger.debug(cmd)
439 # self.cur.execute(cmd)
441 except (mdb
.Error
, AttributeError) as e
:
442 r
,c
= self
.format_error(e
, "update_rows", cmd
)
443 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
445 def get_host(self
, host_id
):
446 if af
.check_valid_uuid(host_id
):
447 where_filter
="uuid='" + host_id
+ "'"
449 where_filter
="name='" + host_id
+ "'"
450 for retry_
in range(0,2):
454 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
456 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 \
457 FROM hosts WHERE " + where_filter
458 self
.logger
.debug(cmd
)
459 self
.cur
.execute(cmd
)
460 if self
.cur
.rowcount
== 0 :
461 return 0, "host '" + str(host_id
) +"'not found."
462 elif self
.cur
.rowcount
> 1 :
463 return 0, "host '" + str(host_id
) +"' matches more than one result."
464 host
= self
.cur
.fetchone()
465 host_id
= host
['uuid']
467 cmd
= "SELECT id, numa_socket, hugepages, memory, admin_state_up FROM numas WHERE host_id = '" + str(host_id
) + "'"
468 self
.logger
.debug(cmd
)
469 self
.cur
.execute(cmd
)
470 host
['numas'] = self
.cur
.fetchall()
471 for numa
in host
['numas']:
472 #print "SELECT core_id, instance_id, status, thread_id, v_thread_id FROM resources_core WHERE numa_id = '" + str(numa['id']) + "'"
474 cmd
= "SELECT core_id, instance_id, status, thread_id, v_thread_id FROM resources_core WHERE numa_id = '" + str(numa
['id']) + "'"
475 self
.logger
.debug(cmd
)
476 self
.cur
.execute(cmd
)
477 numa
['cores'] = self
.cur
.fetchall()
478 for core
in numa
['cores']:
479 if core
['instance_id'] == None: del core
['instance_id'], core
['v_thread_id']
480 if core
['status'] == 'ok': del core
['status']
482 cmd
= "SELECT sum(consumed) as hugepages_consumed FROM resources_mem WHERE numa_id = '" + str(numa
['id']) + "' GROUP BY numa_id"
483 self
.logger
.debug(cmd
)
484 self
.cur
.execute(cmd
)
485 used
= self
.cur
.fetchone()
486 used_
= int(used
['hugepages_consumed']) if used
!= None else 0
487 numa
['hugepages_consumed'] = used_
489 #cmd = "CALL GetPortsFromNuma(%s)'" % str(numa['id'])
490 #self.cur.callproc('GetPortsFromNuma', (numa['id'],) )
491 #every time a Procedure is launched you need to close and open the cursor
492 #under Error 2014: Commands out of sync; you can't run this command now
494 #self.cur = self.con.cursor(mdb.cursors.DictCursor)
495 cmd
="SELECT Mbps, pci, status, Mbps_used, instance_id, if(id=root_id,'PF','VF') as type_,\
496 switch_port, switch_dpid, mac, source_name\
497 FROM resources_port WHERE numa_id=%d ORDER BY root_id, type_ DESC" % (numa
['id'])
498 self
.logger
.debug(cmd
)
499 self
.cur
.execute(cmd
)
500 ifaces
= self
.cur
.fetchall()
501 #The SQL query will ensure to have SRIOV interfaces from a port first
504 numa
['interfaces'] = []
506 if not iface
["instance_id"]:
507 del iface
["instance_id"]
508 if iface
['status'] == 'ok':
510 Mpbs_consumed
+= int(iface
["Mbps_used"])
511 del iface
["Mbps_used"]
512 if iface
["type_"]=='PF':
513 if not iface
["switch_dpid"]:
514 del iface
["switch_dpid"]
515 if not iface
["switch_port"]:
516 del iface
["switch_port"]
518 iface
["sriovs"] = sriovs
520 iface
["Mpbs_consumed"] = Mpbs_consumed
522 numa
['interfaces'].append(iface
)
526 del iface
["switch_port"]
527 del iface
["switch_dpid"]
532 #delete internal field
535 except (mdb
.Error
, AttributeError) as e
:
536 r
,c
= self
.format_error(e
, "get_host", cmd
)
537 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
542 uuid
= str( myUuid
.uuid1() )
543 if self
.check_uuid(uuid
)[0] == 0:
548 def check_uuid(self
, uuid
):
549 '''check in the database if this uuid is already present'''
551 cmd
= "SELECT * FROM uuids where uuid='" + str(uuid
) + "'"
553 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
554 self
.logger
.debug(cmd
)
555 self
.cur
.execute(cmd
)
556 rows
= self
.cur
.fetchall()
557 return self
.cur
.rowcount
, rows
558 except (mdb
.Error
, AttributeError) as e
:
559 return self
.format_error(e
, "check_uuid", cmd
)
561 def __get_next_ids(self
):
562 '''get next auto increment index of all table in the database'''
563 self
.cur
.execute("SELECT table_name,AUTO_INCREMENT FROM information_schema.tables WHERE AUTO_INCREMENT IS NOT NULL AND table_schema = DATABASE()")
564 rows
= self
.cur
.fetchall()
565 return self
.cur
.rowcount
, dict(rows
)
567 def edit_host(self
, host_id
, host_dict
):
569 for retry_
in range(0,2):
573 self
.cur
= self
.con
.cursor()
576 numa_list
= host_dict
.pop('numas', () )
578 self
._update
_rows
_internal
("hosts", host_dict
, {"uuid": host_id
})
580 where
= {"host_id": host_id
}
581 for numa_dict
in numa_list
:
582 where
["numa_socket"] = str(numa_dict
.pop('numa_socket'))
583 interface_list
= numa_dict
.pop('interfaces', () )
585 self
._update
_rows
_internal
("numas", numa_dict
, where
)
586 for interface
in interface_list
:
587 source_name
= str(interface
.pop("source_name") )
589 #get interface id from resources_port
590 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 " +\
591 "WHERE host_id='%s' and rp.source_name='%s'" %(host_id
, source_name
)
592 self
.logger
.debug(cmd
)
593 self
.cur
.execute(cmd
)
594 row
= self
.cur
.fetchone()
595 if self
.cur
.rowcount
<=0:
596 return -HTTP_Bad_Request
, "Interface source_name='%s' from numa_socket='%s' not found" % (source_name
, str(where
["numa_socket"]))
597 interface_id
= row
[0]
598 self
._update
_rows
_internal
("resources_port", interface
, {"root_id": interface_id
})
599 return self
.get_host(host_id
)
600 except (mdb
.Error
, AttributeError) as e
:
601 r
,c
= self
.format_error(e
, "edit_host", cmd
)
602 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
604 def new_host(self
, host_dict
):
606 for retry_
in range(0,2):
610 self
.cur
= self
.con
.cursor()
612 result
, next_ids
= self
.__get
_next
_ids
()
613 #print "next_ids: " + str(next_ids)
614 if result
<= 0: return result
, "Internal DataBase error getting next id of tables"
616 #create uuid if not provided
617 if 'uuid' not in host_dict
:
618 uuid
= host_dict
['uuid'] = str(myUuid
.uuid1()) # create_uuid
619 else: #check uuid is valid
620 uuid
= str(host_dict
['uuid'])
621 # result, data = self.check_uuid(uuid)
623 # return -1, "UUID '%s' already in use" % uuid
626 cmd
= "INSERT INTO uuids (uuid, used_at) VALUES ('%s','hosts')" % uuid
627 self
.logger
.debug(cmd
)
628 result
= self
.cur
.execute(cmd
)
630 #insert in table host
631 numa_list
= host_dict
.pop('numas', [])
632 #get nonhupages and nonisolated cpus
635 for numa
in numa_list
:
636 mem_numa
= numa
.get('memory', 0) - numa
.get('hugepages',0)
638 host_dict
['RAM'] += mem_numa
639 for core
in numa
.get("cores", []):
640 if "status" in core
and core
["status"]=="noteligible":
642 host_dict
['RAM']*=1024 # from GB to MB
644 keys
= ",".join(host_dict
.keys())
645 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", host_dict
.values() ) )
646 cmd
= "INSERT INTO hosts (" + keys
+ ") VALUES (" + values
+ ")"
647 self
.logger
.debug(cmd
)
648 result
= self
.cur
.execute(cmd
)
649 #if result != 1: return -1, "Database Error while inserting at hosts table"
652 nb_numas
= nb_cores
= nb_ifaces
= 0
653 for numa_dict
in numa_list
:
655 interface_list
= numa_dict
.pop('interfaces', [])
656 core_list
= numa_dict
.pop('cores', [])
657 numa_dict
['id'] = next_ids
['numas']; next_ids
['numas'] += 1
658 numa_dict
['host_id'] = uuid
659 keys
= ",".join(numa_dict
.keys())
660 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", numa_dict
.values() ) )
661 cmd
= "INSERT INTO numas (" + keys
+ ") VALUES (" + values
+ ")"
662 self
.logger
.debug(cmd
)
663 result
= self
.cur
.execute(cmd
)
666 for core_dict
in core_list
:
668 core_dict
['numa_id'] = numa_dict
['id']
669 keys
= ",".join(core_dict
.keys())
670 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", core_dict
.values() ) )
671 cmd
= "INSERT INTO resources_core (" + keys
+ ") VALUES (" + values
+ ")"
672 self
.logger
.debug(cmd
)
673 result
= self
.cur
.execute(cmd
)
676 for port_dict
in interface_list
:
678 sriov_list
= port_dict
.pop('sriovs', [])
679 port_dict
['numa_id'] = numa_dict
['id']
680 port_dict
['id'] = port_dict
['root_id'] = next_ids
['resources_port']
681 next_ids
['resources_port'] += 1
682 switch_port
= port_dict
.get('switch_port', None)
683 switch_dpid
= port_dict
.get('switch_dpid', None)
684 keys
= ",".join(port_dict
.keys())
685 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", port_dict
.values() ) )
686 cmd
= "INSERT INTO resources_port (" + keys
+ ") VALUES (" + values
+ ")"
687 self
.logger
.debug(cmd
)
688 result
= self
.cur
.execute(cmd
)
690 #insert sriovs into port table
691 for sriov_dict
in sriov_list
:
692 sriov_dict
['switch_port'] = switch_port
693 sriov_dict
['switch_dpid'] = switch_dpid
694 sriov_dict
['numa_id'] = port_dict
['numa_id']
695 sriov_dict
['Mbps'] = port_dict
['Mbps']
696 sriov_dict
['root_id'] = port_dict
['id']
697 sriov_dict
['id'] = next_ids
['resources_port']
698 if "vlan" in sriov_dict
:
699 del sriov_dict
["vlan"]
700 next_ids
['resources_port'] += 1
701 keys
= ",".join(sriov_dict
.keys())
702 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", sriov_dict
.values() ) )
703 cmd
= "INSERT INTO resources_port (" + keys
+ ") VALUES (" + values
+ ")"
704 self
.logger
.debug(cmd
)
705 result
= self
.cur
.execute(cmd
)
708 #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)
709 #self.logger.debug(cmd)
710 #result = self.cur.execute(cmd)
714 self
.cur
= self
.con
.cursor()
715 self
.logger
.debug("callproc('UpdateSwitchPort', () )")
716 self
.cur
.callproc('UpdateSwitchPort', () )
718 self
.logger
.debug("getting host '%s'",str(host_dict
['uuid']))
719 return self
.get_host(host_dict
['uuid'])
720 except (mdb
.Error
, AttributeError) as e
:
721 r
,c
= self
.format_error(e
, "new_host", cmd
)
722 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
724 def new_flavor(self
, flavor_dict
, tenant_id
):
725 '''Add new flavor into the database. Create uuid if not provided
727 flavor_dict: flavor dictionary with the key: value to insert. Must be valid flavors columns
728 tenant_id: if not 'any', it matches this flavor/tenant inserting at tenants_flavors table
729 Return: (result, data) where result can be
730 negative: error at inserting. data contain text
731 1, inserted, data contain inserted uuid flavor
733 for retry_
in range(0,2):
737 self
.cur
= self
.con
.cursor()
739 #create uuid if not provided
740 if 'uuid' not in flavor_dict
:
741 uuid
= flavor_dict
['uuid'] = str(myUuid
.uuid1()) # create_uuid
742 else: #check uuid is valid
743 uuid
= str(flavor_dict
['uuid'])
744 # result, data = self.check_uuid(uuid)
746 # return -1, "UUID '%s' already in use" % uuid
749 cmd
= "INSERT INTO uuids (uuid, used_at) VALUES ('%s','flavors')" % uuid
750 self
.logger
.debug(cmd
)
751 self
.cur
.execute(cmd
)
753 #insert in table flavor
754 keys
= ",".join(flavor_dict
.keys())
755 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", flavor_dict
.values() ) )
756 cmd
= "INSERT INTO flavors (" + keys
+ ") VALUES (" + values
+ ")"
757 self
.logger
.debug(cmd
)
758 self
.cur
.execute(cmd
)
759 #if result != 1: return -1, "Database Error while inserting at flavors table"
761 #insert tenants_flavors
762 if tenant_id
!= 'any':
763 cmd
= "INSERT INTO tenants_flavors (tenant_id,flavor_id) VALUES ('%s','%s')" % (tenant_id
, uuid
)
764 self
.logger
.debug(cmd
)
765 self
.cur
.execute(cmd
)
768 #del flavor_dict['uuid']
769 #if 'extended' in flavor_dict: del flavor_dict['extended'] #remove two many information
770 #cmd = "INSERT INTO logs (related,level,uuid, tenant_id, description) VALUES ('flavors','debug','%s','%s',\"new flavor: %s\")" \
771 # % (uuid, tenant_id, str(flavor_dict))
772 #self.logger.debug(cmd)
773 #self.cur.execute(cmd)
777 except (mdb
.Error
, AttributeError) as e
:
778 r
,c
= self
.format_error(e
, "new_flavor", cmd
, "update", tenant_id
)
779 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
781 def new_image(self
, image_dict
, tenant_id
):
782 '''Add new image into the database. Create uuid if not provided
784 image_dict: image dictionary with the key: value to insert. Must be valid images columns
785 tenant_id: if not 'any', it matches this image/tenant inserting at tenants_images table
786 Return: (result, data) where result can be
787 negative: error at inserting. data contain text
788 1, inserted, data contain inserted uuid image
790 for retry_
in range(0,2):
794 self
.cur
= self
.con
.cursor()
796 #create uuid if not provided
797 if 'uuid' not in image_dict
:
798 uuid
= image_dict
['uuid'] = str(myUuid
.uuid1()) # create_uuid
799 else: #check uuid is valid
800 uuid
= str(image_dict
['uuid'])
801 # result, data = self.check_uuid(uuid)
803 # return -1, "UUID '%s' already in use" % uuid
806 cmd
= "INSERT INTO uuids (uuid, used_at) VALUES ('%s','images')" % uuid
807 self
.logger
.debug(cmd
)
808 self
.cur
.execute(cmd
)
810 #insert in table image
811 keys
= ",".join(image_dict
.keys())
812 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", image_dict
.values() ) )
813 cmd
= "INSERT INTO images (" + keys
+ ") VALUES (" + values
+ ")"
814 self
.logger
.debug(cmd
)
815 self
.cur
.execute(cmd
)
816 #if result != 1: return -1, "Database Error while inserting at images table"
818 #insert tenants_images
819 if tenant_id
!= 'any':
820 cmd
= "INSERT INTO tenants_images (tenant_id,image_id) VALUES ('%s','%s')" % (tenant_id
, uuid
)
821 self
.logger
.debug(cmd
)
822 self
.cur
.execute(cmd
)
825 #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'])
826 #self.logger.debug(cmd)
827 #self.cur.execute(cmd)
831 except (mdb
.Error
, AttributeError) as e
:
832 r
,c
= self
.format_error(e
, "new_image", cmd
, "update", tenant_id
)
833 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
835 def delete_image_flavor(self
, item_type
, item_id
, tenant_id
):
836 '''deletes an image or flavor from database
837 item_type must be a 'image' or 'flavor'
839 tenant_id is the asociated tenant, can be 'any' with means all
840 If tenan_id is not any, it deletes from tenants_images/flavors,
841 which means this image/flavor is used by this tenant, and if success,
842 it tries to delete from images/flavors in case this is not public,
843 that only will success if image is private and not used by other tenants
844 If tenant_id is any, it tries to delete from both tables at the same transaction
845 so that image/flavor is completely deleted from all tenants or nothing
847 for retry_
in range(0,2):
850 result
= (-HTTP_Internal_Server_Error
, "internal error")
854 self
.cur
= self
.con
.cursor()
855 cmd
= "DELETE FROM tenants_%ss WHERE %s_id = '%s'" % (item_type
, item_type
, item_id
)
856 if tenant_id
!= 'any':
857 cmd
+= " AND tenant_id = '%s'" % tenant_id
858 self
.logger
.debug(cmd
)
859 self
.cur
.execute(cmd
)
860 deleted
= self
.cur
.rowcount
861 if tenant_id
== 'any': #delete from images/flavors in the SAME transaction
862 cmd
= "DELETE FROM %ss WHERE uuid = '%s'" % (item_type
, item_id
)
863 self
.logger
.debug(cmd
)
864 self
.cur
.execute(cmd
)
865 deleted
= self
.cur
.rowcount
868 cmd
= "DELETE FROM uuids WHERE uuid = '%s'" % item_id
869 self
.logger
.debug(cmd
)
870 self
.cur
.execute(cmd
)
872 #cmd = "INSERT INTO logs (related,level,uuid,tenant_id,description) \
873 # VALUES ('%ss','debug','%s','%s','delete %s completely')" % \
874 # (item_type, item_id, tenant_id, item_type)
875 #self.logger.debug(cmd)
876 #self.cur.execute(cmd)
877 return deleted
, "%s '%s' completely deleted" % (item_type
, item_id
)
878 return 0, "%s '%s' not found" % (item_type
, item_id
)
882 #cmd = "INSERT INTO logs (related,level,uuid,tenant_id,description) \
883 # VALUES ('%ss','debug','%s','%s','delete %s reference for this tenant')" % \
884 # (item_type, item_id, tenant_id, item_type)
885 #self.logger.debug(cmd)
886 #self.cur.execute(cmd)
890 #if tenant!=any delete from images/flavors in OTHER transaction. If fails is because dependencies so that not return error
893 self
.cur
= self
.con
.cursor()
895 #delete image/flavor if not public
896 cmd
= "DELETE FROM %ss WHERE uuid = '%s' AND public = 'no'" % (item_type
, item_id
)
897 self
.logger
.debug(cmd
)
898 self
.cur
.execute(cmd
)
899 deleted_item
= self
.cur
.rowcount
900 if deleted_item
== 1:
902 cmd
= "DELETE FROM uuids WHERE uuid = '%s'" % item_id
903 self
.logger
.debug(cmd
)
904 self
.cur
.execute(cmd
)
906 #cmd = "INSERT INTO logs (related,level,uuid,tenant_id,description) \
907 # VALUES ('%ss','debug','%s','%s','delete %s completely')" % \
908 # (item_type, item_id, tenant_id, item_type)
909 #self.logger.debug(cmd)
910 #self.cur.execute(cmd)
911 except (mdb
.Error
, AttributeError) as e
:
912 #print "delete_%s DB Exception %d: %s" % (item_type, e.args[0], e.args[1])
914 result
= self
.format_error(e
, "delete_"+item_type
, cmd
, "delete", "servers")
917 return 1, "%s '%s' from tenant '%s' %sdeleted" % \
918 (item_type
, item_id
, tenant_id
, "completely " if deleted_item
==1 else "")
920 return 0, "%s '%s' from tenant '%s' not found" % (item_type
, item_id
, tenant_id
)
922 if result
[0]!=-HTTP_Request_Timeout
or retry_
==1: return result
924 def delete_row(self
, table
, uuid
):
925 for retry_
in range(0,2):
930 self
.cur
= self
.con
.cursor()
931 cmd
= "DELETE FROM %s WHERE uuid = '%s'" % (table
, uuid
)
932 self
.logger
.debug(cmd
)
933 self
.cur
.execute(cmd
)
934 deleted
= self
.cur
.rowcount
937 if table
== 'tenants': tenant_str
=uuid
938 else: tenant_str
='Null'
939 self
.cur
= self
.con
.cursor()
940 cmd
= "DELETE FROM uuids WHERE uuid = '%s'" % uuid
941 self
.logger
.debug(cmd
)
942 self
.cur
.execute(cmd
)
944 #cmd = "INSERT INTO logs (related,level,uuid,tenant_id,description) VALUES ('%s','debug','%s','%s','delete %s')" % (table, uuid, tenant_str, table[:-1])
945 #self.logger.debug(cmd)
946 #self.cur.execute(cmd)
947 return deleted
, table
[:-1] + " '%s' %s" %(uuid
, "deleted" if deleted
==1 else "not found")
948 except (mdb
.Error
, AttributeError) as e
:
949 r
,c
= self
.format_error(e
, "delete_row", cmd
, "delete", 'instances' if table
=='hosts' or table
=='tenants' else 'dependencies')
950 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
952 def delete_row_by_key(self
, table
, key
, value
):
953 for retry_
in range(0,2):
958 self
.cur
= self
.con
.cursor()
959 cmd
= "DELETE FROM %s" % (table
)
962 cmd
+= " WHERE %s = '%s'" % (key
, value
)
964 cmd
+= " WHERE %s is null" % (key
)
967 self
.logger
.debug(cmd
)
968 self
.cur
.execute(cmd
)
969 deleted
= self
.cur
.rowcount
971 return -1, 'Not found'
974 except (mdb
.Error
, AttributeError) as e
:
975 r
,c
= self
.format_error(e
, "delete_row_by_key", cmd
, "delete", 'instances' if table
=='hosts' or table
=='tenants' else 'dependencies')
976 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
978 def delete_row_by_dict(self
, **sql_dict
):
979 ''' Deletes rows from a table.
980 Attribute sql_dir: dictionary with the following key: value
981 'FROM': string of table name (Mandatory)
982 'WHERE': dict of key:values, translated to key=value AND ... (Optional)
983 'WHERE_NOT': dict of key:values, translated to key<>value AND ... (Optional)
984 'WHERE_NOTNULL': (list or tuple of items that must not be null in a where ... (Optional)
985 'LIMIT': limit of number of rows (Optional)
986 Return: the (number of items deleted, descriptive test) if ok; (negative, descriptive text) if error
989 from_
= "FROM " + str(sql_dict
['FROM'])
990 #print 'from_', from_
991 if 'WHERE' in sql_dict
and len(sql_dict
['WHERE']) > 0:
993 where_
= "WHERE " + " AND ".join(map( lambda x
: str(x
) + (" is Null" if w
[x
] is None else "='"+str(w
[x
])+"'"), w
.keys()) )
995 if 'WHERE_NOT' in sql_dict
and len(sql_dict
['WHERE_NOT']) > 0:
996 w
=sql_dict
['WHERE_NOT']
997 where_2
= " AND ".join(map( lambda x
: str(x
) + (" is not Null" if w
[x
] is None else "<>'"+str(w
[x
])+"'"), w
.keys()) )
998 if len(where_
)==0: where_
= "WHERE " + where_2
999 else: where_
= where_
+ " AND " + where_2
1000 if 'WHERE_NOTNULL' in sql_dict
and len(sql_dict
['WHERE_NOTNULL']) > 0:
1001 w
=sql_dict
['WHERE_NOTNULL']
1002 where_2
= " AND ".join(map( lambda x
: str(x
) + " is not Null", w
) )
1003 if len(where_
)==0: where_
= "WHERE " + where_2
1004 else: where_
= where_
+ " AND " + where_2
1005 #print 'where_', where_
1006 limit_
= "LIMIT " + str(sql_dict
['LIMIT']) if 'LIMIT' in sql_dict
else ""
1007 #print 'limit_', limit_
1008 cmd
= " ".join( ("DELETE", from_
, where_
, limit_
) )
1009 self
.logger
.debug(cmd
)
1010 for retry_
in range(0,2):
1014 self
.cur
= self
.con
.cursor()
1015 self
.cur
.execute(cmd
)
1016 deleted
= self
.cur
.rowcount
1017 return deleted
, "%d deleted from %s" % (deleted
, sql_dict
['FROM'][:-1] )
1018 except (mdb
.Error
, AttributeError) as e
:
1019 r
,c
= self
.format_error(e
, "delete_row_by_dict", cmd
, "delete", 'dependencies')
1020 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1023 def get_instance(self
, instance_id
):
1024 for retry_
in range(0,2):
1028 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1030 cmd
= "SELECT uuid, name, description, progress, host_id, flavor_id, image_id, status, last_error, "\
1031 "tenant_id, ram, vcpus, created_at FROM instances WHERE uuid='{}'".format(instance_id
)
1032 self
.logger
.debug(cmd
)
1033 self
.cur
.execute(cmd
)
1034 if self
.cur
.rowcount
== 0 : return 0, "instance '" + str(instance_id
) +"'not found."
1035 instance
= self
.cur
.fetchone()
1037 cmd
= "SELECT uuid as iface_id, net_id, mac as mac_address, ip_address, name, Mbps as bandwidth, "\
1038 "vpci, model FROM ports WHERE (type='instance:bridge' or type='instance:ovs') AND "\
1039 "instance_id= '{}'".format(instance_id
)
1040 self
.logger
.debug(cmd
)
1041 self
.cur
.execute(cmd
)
1042 if self
.cur
.rowcount
> 0 :
1043 instance
['networks'] = self
.cur
.fetchall()
1048 cmd
= "SELECT type, vpci, image_id, xml,dev FROM instance_devices WHERE instance_id = '%s' " % str(instance_id
)
1049 self
.logger
.debug(cmd
)
1050 self
.cur
.execute(cmd
)
1051 if self
.cur
.rowcount
> 0 :
1052 extended
['devices'] = self
.cur
.fetchall()
1055 cmd
= "SELECT id, numa_socket as source FROM numas WHERE host_id = '" + str(instance
['host_id']) + "'"
1056 self
.logger
.debug(cmd
)
1057 self
.cur
.execute(cmd
)
1058 host_numas
= self
.cur
.fetchall()
1059 #print 'host_numas', host_numas
1060 for k
in host_numas
:
1061 numa_id
= str(k
['id'])
1064 cmd
= "SELECT consumed FROM resources_mem WHERE instance_id = '%s' AND numa_id = '%s'" % ( instance_id
, numa_id
)
1065 self
.logger
.debug(cmd
)
1066 self
.cur
.execute(cmd
)
1067 if self
.cur
.rowcount
> 0:
1068 mem_dict
= self
.cur
.fetchone()
1069 numa_dict
['memory'] = mem_dict
['consumed']
1071 cursor2
= self
.con
.cursor()
1072 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
)
1073 self
.logger
.debug(cmd
)
1074 cursor2
.execute(cmd
)
1075 core_list
= []; core_source
= []
1076 paired_list
= []; paired_source
= []
1077 thread_list
= []; thread_source
= []
1078 if cursor2
.rowcount
> 0:
1079 cores
= cursor2
.fetchall()
1081 if core
[4] == 2: #number of used threads from core
1082 if core
[3] == core
[2]: #only one thread asigned to VM, so completely core
1083 core_list
.append(core
[2])
1084 core_source
.append(core
[5])
1085 elif core
[1] == 'Y':
1086 paired_list
.append(core
[2:4])
1087 paired_source
.append(core
[5:7])
1089 thread_list
.extend(core
[2:4])
1090 thread_source
.extend(core
[5:7])
1093 thread_list
.append(core
[2])
1094 thread_source
.append(core
[5])
1095 if len(core_list
) > 0:
1096 numa_dict
['cores'] = len(core_list
)
1097 numa_dict
['cores-id'] = core_list
1098 numa_dict
['cores-source'] = core_source
1099 if len(paired_list
) > 0:
1100 numa_dict
['paired-threads'] = len(paired_list
)
1101 numa_dict
['paired-threads-id'] = paired_list
1102 numa_dict
['paired-threads-source'] = paired_source
1103 if len(thread_list
) > 0:
1104 numa_dict
['threads'] = len(thread_list
)
1105 numa_dict
['threads-id'] = thread_list
1106 numa_dict
['threads-source'] = thread_source
1108 #get dedicated ports and SRIOV
1109 cmd
= "SELECT port_id as iface_id, p.vlan as vlan, p.mac as mac_address, net_id, if(model='PF',\
1110 'yes',if(model='VF','no','yes:sriov')) as dedicated, rp.Mbps as bandwidth, name, vpci, \
1112 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
)
1113 self
.logger
.debug(cmd
)
1114 self
.cur
.execute(cmd
)
1115 if self
.cur
.rowcount
> 0:
1116 numa_dict
['interfaces'] = self
.cur
.fetchall()
1117 #print 'interfaces', numa_dict
1119 if len(numa_dict
) > 0 :
1120 numa_dict
['source'] = k
['source'] #numa socket
1121 numas
.append(numa_dict
)
1123 if len(numas
) > 0 : extended
['numas'] = numas
1124 if len(extended
) > 0 : instance
['extended'] = extended
1125 af
.DeleteNone(instance
)
1127 except (mdb
.Error
, AttributeError) as e
:
1128 r
,c
= self
.format_error(e
, "get_instance", cmd
)
1129 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1131 def get_numas(self
, requirements
, prefered_host_id
=None, only_of_ports
=True):
1132 '''Obtain a valid NUMA/HOST for deployment a VM
1133 requirements: contain requirement regarding:
1134 requirements['ram']: Non huge page memory in MB; 0 to skip
1135 requirements['vcpus']: Non isolated cpus; 0 to skip
1136 requirements['numa']: Requiremets to be fixed in ONE Numa node
1137 requirements['numa']['memory']: Huge page memory in GB at ; 0 for any
1138 requirements['numa']['proc_req_type']: Type of processor, cores or threads
1139 requirements['numa']['proc_req_nb']: Number of isolated cpus
1140 requirements['numa']['port_list']: Physical NIC ports list ; [] for any
1141 requirements['numa']['sriov_list']: Virtual function NIC ports list ; [] for any
1142 prefered_host_id: if not None return this host if it match
1143 only_of_ports: if True only those ports conected to the openflow (of) are valid,
1144 that is, with switch_port information filled; if False, all NIC ports are valid.
1145 Return a valid numa and host
1148 for retry_
in range(0,2):
1152 # #Find numas of prefered host
1153 # prefered_numas = ()
1154 # if prefered_host_id != None:
1155 # self.cur = self.con.cursor()
1156 # self.cur.execute("SELECT id FROM numas WHERE host_id='%s'" + prefered_host_id)
1157 # prefered_numas = self.cur.fetchall()
1160 #Find valid host for the ram and vcpus
1161 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1162 cmd
= "CALL GetHostByMemCpu(%s, %s)" % (str(requirements
['ram']), str(requirements
['vcpus']))
1163 self
.logger
.debug(cmd
)
1164 self
.cur
.callproc('GetHostByMemCpu', (str(requirements
['ram']), str(requirements
['vcpus'])) )
1165 valid_hosts
= self
.cur
.fetchall()
1167 self
.cur
= self
.con
.cursor()
1169 if len(valid_hosts
)<=0:
1170 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']))
1171 #self.logger.debug(error_text)
1172 return -1, error_text
1174 #elif req_numa != None:
1175 #Find valid numa nodes for memory requirements
1176 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1177 cmd
= "CALL GetNumaByMemory(%s)" % str(requirements
['numa']['memory'])
1178 self
.logger
.debug(cmd
)
1179 self
.cur
.callproc('GetNumaByMemory', (requirements
['numa']['memory'],) )
1180 valid_for_memory
= self
.cur
.fetchall()
1182 self
.cur
= self
.con
.cursor()
1183 if len(valid_for_memory
)<=0:
1184 error_text
= 'No room at data center. Can not find a host with %s GB Hugepages memory available' % str(requirements
['numa']['memory'])
1185 #self.logger.debug(error_text)
1186 return -1, error_text
1188 #Find valid numa nodes for processor requirements
1189 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1190 if requirements
['numa']['proc_req_type'] == 'threads':
1191 cpu_requirement_text
='cpu-threads'
1192 cmd
= "CALL GetNumaByThread(%s)" % str(requirements
['numa']['proc_req_nb'])
1193 self
.logger
.debug(cmd
)
1194 self
.cur
.callproc('GetNumaByThread', (requirements
['numa']['proc_req_nb'],) )
1196 cpu_requirement_text
='cpu-cores'
1197 cmd
= "CALL GetNumaByCore(%s)" % str(requirements
['numa']['proc_req_nb'])
1198 self
.logger
.debug(cmd
)
1199 self
.cur
.callproc('GetNumaByCore', (requirements
['numa']['proc_req_nb'],) )
1200 valid_for_processor
= self
.cur
.fetchall()
1202 self
.cur
= self
.con
.cursor()
1203 if len(valid_for_processor
)<=0:
1204 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
)
1205 #self.logger.debug(error_text)
1206 return -1, error_text
1208 #Find the numa nodes that comply for memory and processor requirements
1209 #sorting from less to more memory capacity
1211 for m_numa
in valid_for_memory
:
1212 numa_valid_for_processor
= False
1213 for p_numa
in valid_for_processor
:
1214 if m_numa
['numa_id'] == p_numa
['numa_id']:
1215 numa_valid_for_processor
= True
1217 numa_valid_for_host
= False
1218 prefered_numa
= False
1219 for p_host
in valid_hosts
:
1220 if m_numa
['host_id'] == p_host
['uuid']:
1221 numa_valid_for_host
= True
1222 if p_host
['uuid'] == prefered_host_id
:
1223 prefered_numa
= True
1225 if numa_valid_for_host
and numa_valid_for_processor
:
1227 valid_numas
.insert(0, m_numa
['numa_id'])
1229 valid_numas
.append(m_numa
['numa_id'])
1230 if len(valid_numas
)<=0:
1231 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' %\
1232 (requirements
['numa']['memory'], str(requirements
['numa']['proc_req_nb']),cpu_requirement_text
)
1233 #self.logger.debug(error_text)
1234 return -1, error_text
1236 # print 'Valid numas list: '+str(valid_numas)
1238 #Find valid numa nodes for interfaces requirements
1239 #For each valid numa we will obtain the number of available ports and check if these are valid
1241 for numa_id
in valid_numas
:
1242 # print 'Checking '+str(numa_id)
1244 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1246 cmd
="CALL GetAvailablePorts(%s)" % str(numa_id
)
1247 self
.logger
.debug(cmd
)
1248 self
.cur
.callproc('GetAvailablePorts', (numa_id
,) )
1250 cmd
="CALL GetAllAvailablePorts(%s)" % str(numa_id
)
1251 self
.logger
.debug(cmd
)
1252 self
.cur
.callproc('GetAllAvailablePorts', (numa_id
,) )
1253 available_ports
= self
.cur
.fetchall()
1255 self
.cur
= self
.con
.cursor()
1257 #Set/reset reservations
1258 for port
in available_ports
:
1259 port
['Mbps_reserved'] = 0
1260 port
['SRIOV_reserved'] = 0
1262 #Try to allocate physical ports
1263 physical_ports_found
= True
1264 for iface
in requirements
['numa']['port_list']:
1265 # print '\t\tchecking iface: '+str(iface)
1267 for port
in available_ports
:
1268 # print '\t\t\tfor port: '+str(port)
1269 #If the port is not empty continue
1270 if port
['Mbps_free'] != port
['Mbps'] or port
['Mbps_reserved'] != 0:
1271 # print '\t\t\t\t Not empty port'
1273 #If the port speed is not enough continue
1274 if port
['Mbps'] < iface
['bandwidth']:
1275 # print '\t\t\t\t Not enough speed'
1278 #Otherwise this is a valid port
1279 port
['Mbps_reserved'] = port
['Mbps']
1280 port
['SRIOV_reserved'] = 0
1281 iface
['port_id'] = port
['port_id']
1282 iface
['vlan'] = None
1283 iface
['mac'] = port
['mac']
1284 iface
['switch_port'] = port
['switch_port']
1285 # print '\t\t\t\t Dedicated port found '+str(port['port_id'])
1289 #if all ports have been checked and no match has been found
1290 #this is not a valid numa
1292 # print '\t\t\t\t\tAll ports have been checked and no match has been found for numa '+str(numa_id)+'\n\n'
1293 physical_ports_found
= False
1296 #if there is no match continue checking the following numa
1297 if not physical_ports_found
:
1300 #Try to allocate SR-IOVs
1301 sriov_ports_found
= True
1302 for iface
in requirements
['numa']['sriov_list']:
1303 # print '\t\tchecking iface: '+str(iface)
1305 for port
in available_ports
:
1306 # print '\t\t\tfor port: '+str(port)
1307 #If there are not available SR-IOVs continue
1308 if port
['availableSRIOV'] - port
['SRIOV_reserved'] <= 0:
1309 # print '\t\t\t\t Not enough SR-IOV'
1311 #If the port free speed is not enough continue
1312 if port
['Mbps_free'] - port
['Mbps_reserved'] < iface
['bandwidth']:
1313 # print '\t\t\t\t Not enough speed'
1316 #Otherwise this is a valid port
1317 port
['Mbps_reserved'] += iface
['bandwidth']
1318 port
['SRIOV_reserved'] += 1
1319 # print '\t\t\t\t SR-IOV found '+str(port['port_id'])
1320 iface
['port_id'] = port
['port_id']
1321 iface
['vlan'] = None
1322 iface
['mac'] = port
['mac']
1323 iface
['switch_port'] = port
['switch_port']
1327 #if all ports have been checked and no match has been found
1328 #this is not a valid numa
1330 # print '\t\t\t\t\tAll ports have been checked and no match has been found for numa '+str(numa_id)+'\n\n'
1331 sriov_ports_found
= False
1334 #if there is no match continue checking the following numa
1335 if not sriov_ports_found
:
1339 if sriov_ports_found
and physical_ports_found
:
1344 error_text
= 'No room at data center. Can not find a host with the required hugepages, vcpus and interfaces'
1345 #self.logger.debug(error_text)
1346 return -1, error_text
1348 #self.logger.debug('Full match found in numa %s', str(numa_id))
1350 for numa
in valid_for_processor
:
1351 if numa_id
==numa
['numa_id']:
1352 host_id
=numa
['host_id']
1354 return 0, {'numa_id':numa_id
, 'host_id': host_id
, }
1355 except (mdb
.Error
, AttributeError) as e
:
1356 r
,c
= self
.format_error(e
, "get_numas", cmd
)
1357 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1359 def new_instance(self
, instance_dict
, nets
, ports_to_free
):
1360 for retry_
in range(0,2):
1364 self
.cur
= self
.con
.cursor()
1366 #create uuid if not provided
1367 if 'uuid' not in instance_dict
:
1368 uuid
= instance_dict
['uuid'] = str(myUuid
.uuid1()) # create_uuid
1369 else: #check uuid is valid
1370 uuid
= str(instance_dict
['uuid'])
1374 cmd
= "INSERT INTO uuids (uuid, root_uuid, used_at) VALUES ('%s','%s', 'instances')" % (uuid
, uuid
)
1375 self
.logger
.debug(cmd
)
1376 self
.cur
.execute(cmd
)
1378 #insert in table instance
1379 extended
= instance_dict
.pop('extended', None);
1380 bridgedifaces
= instance_dict
.pop('bridged-ifaces', () );
1382 keys
= ",".join(instance_dict
.keys())
1383 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", instance_dict
.values() ) )
1384 cmd
= "INSERT INTO instances (" + keys
+ ") VALUES (" + values
+ ")"
1385 self
.logger
.debug(cmd
)
1386 self
.cur
.execute(cmd
)
1387 #if result != 1: return -1, "Database Error while inserting at instances table"
1390 nb_bridge_ifaces
= nb_cores
= nb_ifaces
= nb_numas
= 0
1391 #insert bridged_ifaces
1392 for iface
in bridgedifaces
:
1393 #generate and insert a iface uuid
1394 iface
['uuid'] = str(myUuid
.uuid1()) # create_uuid
1395 cmd
= "INSERT INTO uuids (uuid, root_uuid, used_at) VALUES ('%s','%s', 'ports')" % (iface
['uuid'], uuid
)
1396 self
.logger
.debug(cmd
)
1397 self
.cur
.execute(cmd
)
1399 iface
['instance_id'] = uuid
1400 # iface['type'] = 'instance:bridge'
1401 if 'name' not in iface
: iface
['name']="br"+str(nb_bridge_ifaces
)
1402 iface
['Mbps']=iface
.pop('bandwidth', None)
1403 if 'mac_address' not in iface
:
1404 iface
['mac'] = af
.gen_random_mac()
1406 iface
['mac'] = iface
['mac_address']
1407 del iface
['mac_address']
1408 #iface['mac']=iface.pop('mac_address', None) #for leaving mac generation to libvirt
1409 keys
= ",".join(iface
.keys())
1410 values
= ",".join( map(lambda x
: "Null" if x
is None else "'"+str(x
)+"'", iface
.values() ) )
1411 cmd
= "INSERT INTO ports (" + keys
+ ") VALUES (" + values
+ ")"
1412 self
.logger
.debug(cmd
)
1413 self
.cur
.execute(cmd
)
1414 nb_bridge_ifaces
+= 1
1416 if extended
is not None:
1417 if 'numas' not in extended
or extended
['numas'] is None: extended
['numas'] = ()
1418 for numa
in extended
['numas']:
1421 if 'cores' not in numa
or numa
['cores'] is None: numa
['cores'] = ()
1422 for core
in numa
['cores']:
1424 cmd
= "UPDATE resources_core SET instance_id='%s'%s%s WHERE id='%s'" \
1426 (",v_thread_id='" + str(core
['vthread']) + "'") if 'vthread' in core
else '', \
1427 (",paired='" + core
['paired'] + "'") if 'paired' in core
else '', \
1429 self
.logger
.debug(cmd
)
1430 self
.cur
.execute(cmd
)
1432 if 'interfaces' not in numa
or numa
['interfaces'] is None: numa
['interfaces'] = ()
1433 for iface
in numa
['interfaces']:
1434 #generate and insert an uuid; iface[id]=iface_uuid; iface[uuid]= net_id
1435 iface
['id'] = str(myUuid
.uuid1()) # create_uuid
1436 cmd
= "INSERT INTO uuids (uuid, root_uuid, used_at) VALUES ('%s','%s', 'ports')" % (iface
['id'], uuid
)
1437 self
.logger
.debug(cmd
)
1438 self
.cur
.execute(cmd
)
1440 mbps_
=("'"+str(iface
['Mbps_used'])+"'") if 'Mbps_used' in iface
and iface
['Mbps_used'] is not None else "Mbps"
1441 if iface
["dedicated"]=="yes":
1443 elif iface
["dedicated"]=="yes:sriov":
1444 iface_model
="VFnotShared"
1445 elif iface
["dedicated"]=="no":
1448 INSERT
=(iface
['mac_address'], iface
['switch_port'], iface
.get('vlan',None), 'instance:data', iface
['Mbps_used'], iface
['id'],
1449 uuid
, instance_dict
['tenant_id'], iface
.get('name',None), iface
.get('vpci',None), iface
.get('uuid',None), iface_model
)
1450 cmd
= "INSERT INTO ports (mac,switch_port,vlan,type,Mbps,uuid,instance_id,tenant_id,name,vpci,net_id, model) " + \
1451 " VALUES (" + ",".join(map(lambda x
: 'Null' if x
is None else "'"+str(x
)+"'", INSERT
)) + ")"
1452 self
.logger
.debug(cmd
)
1453 self
.cur
.execute(cmd
)
1455 nets
.append(iface
['uuid'])
1457 #discover if this port is not used by anyone
1458 cmd
= "SELECT source_name, mac FROM ( SELECT root_id, count(instance_id) as used FROM resources_port" \
1459 " WHERE root_id=(SELECT root_id from resources_port WHERE id='%s')"\
1460 " GROUP BY root_id ) AS A JOIN resources_port as B ON A.root_id=B.id AND A.used=0" % iface
['port_id']
1461 self
.logger
.debug(cmd
)
1462 self
.cur
.execute(cmd
)
1463 ports_to_free
+= self
.cur
.fetchall()
1465 cmd
= "UPDATE resources_port SET instance_id='%s', port_id='%s',Mbps_used=%s WHERE id='%s'" \
1466 % (uuid
, iface
['id'], mbps_
, iface
['port_id'])
1467 #if Mbps_used not suply, set the same value of 'Mpbs', that is the total
1468 self
.logger
.debug(cmd
)
1469 self
.cur
.execute(cmd
)
1471 if 'memory' in numa
and numa
['memory'] is not None and numa
['memory']>0:
1472 cmd
= "INSERT INTO resources_mem (numa_id, instance_id, consumed) VALUES ('%s','%s','%s')" % (numa
['numa_id'], uuid
, numa
['memory'])
1473 self
.logger
.debug(cmd
)
1474 self
.cur
.execute(cmd
)
1475 if 'devices' not in extended
or extended
['devices'] is None: extended
['devices'] = ()
1476 for device
in extended
['devices']:
1477 if 'vpci' in device
: vpci
= "'" + device
['vpci'] + "'"
1479 if 'image_id' in device
: image_id
= "'" + device
['image_id'] + "'"
1480 else: image_id
= 'Null'
1481 if 'xml' in device
: xml
= "'" + device
['xml'] + "'"
1483 if 'dev' in device
: dev
= "'" + device
['dev'] + "'"
1485 cmd
= "INSERT INTO instance_devices (type, instance_id, image_id, vpci, xml, dev) VALUES ('%s','%s', %s, %s, %s, %s)" % \
1486 (device
['type'], uuid
, image_id
, vpci
, xml
, dev
)
1487 self
.logger
.debug(cmd
)
1488 self
.cur
.execute(cmd
)
1490 #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)
1491 #self.logger.debug(cmd)
1492 #self.cur.execute(cmd)
1496 except (mdb
.Error
, AttributeError) as e
:
1497 r
,c
= self
.format_error(e
, "new_instance", cmd
)
1498 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1500 def delete_instance(self
, instance_id
, tenant_id
, net_dataplane_list
, ports_to_free
, net_ovs_list
, logcause
="requested by http"):
1501 for retry_
in range(0,2):
1505 self
.cur
= self
.con
.cursor()
1507 cmd
= "SELECT uuid FROM instances WHERE uuid='%s' AND tenant_id='%s'" % (instance_id
, tenant_id
)
1508 self
.logger
.debug(cmd
)
1509 self
.cur
.execute(cmd
)
1510 if self
.cur
.rowcount
== 0 : return 0, "instance %s not found in tenant %s" % (instance_id
, tenant_id
)
1512 #delete bridged ifaces, instace_devices, resources_mem; done by database: it is automatic by Database; FOREIGN KEY DELETE CASCADE
1515 cmd
= "SELECT DISTINCT net_id from ports WHERE instance_id = '%s' AND net_id is not Null AND type='instance:data'" % instance_id
1516 self
.logger
.debug(cmd
)
1517 self
.cur
.execute(cmd
)
1518 net_list__
= self
.cur
.fetchall()
1519 for net
in net_list__
:
1520 net_dataplane_list
.append(net
[0])
1522 # get ovs manangement nets
1523 cmd
= "SELECT DISTINCT net_id, vlan FROM ports WHERE instance_id='{}' AND net_id is not Null AND "\
1524 "type='instance:ovs'".format(instance_id
)
1525 self
.logger
.debug(cmd
)
1526 self
.cur
.execute(cmd
)
1527 net_ovs_list
+= self
.cur
.fetchall()
1529 #get dataplane interfaces releases by this VM; both PF and VF with no other VF
1530 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 \
1531 + " 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"\
1532 + " JOIN resources_port as C ON A.root_id=C.id"
1533 # cmd = "SELECT DISTINCT root_id FROM resources_port WHERE instance_id = '%s'" % instance_id
1534 self
.logger
.debug(cmd
)
1535 self
.cur
.execute(cmd
)
1536 ports_to_free
+= self
.cur
.fetchall()
1538 #update resources port
1539 cmd
= "UPDATE resources_port SET instance_id=Null, port_id=Null, Mbps_used='0' WHERE instance_id = '%s'" % instance_id
1540 self
.logger
.debug(cmd
)
1541 self
.cur
.execute(cmd
)
1543 # #filter dataplane ports used by this VM that now are free
1544 # for port in ports_list__:
1545 # cmd = "SELECT mac, count(instance_id) FROM resources_port WHERE root_id = '%s'" % port[0]
1546 # self.logger.debug(cmd)
1547 # self.cur.execute(cmd)
1548 # mac_list__ = self.cur.fetchone()
1549 # if mac_list__ and mac_list__[1]==0:
1550 # ports_to_free.append(mac_list__[0])
1553 #update resources core
1554 cmd
= "UPDATE resources_core SET instance_id=Null, v_thread_id=Null, paired='N' WHERE instance_id = '%s'" % instance_id
1555 self
.logger
.debug(cmd
)
1556 self
.cur
.execute(cmd
)
1558 #delete all related uuids
1559 cmd
= "DELETE FROM uuids WHERE root_uuid='%s'" % instance_id
1560 self
.logger
.debug(cmd
)
1561 self
.cur
.execute(cmd
)
1564 #cmd = "INSERT INTO logs (related,level,uuid,description) VALUES ('instances','debug','%s','delete instance %s')" % (instance_id, logcause)
1565 #self.logger.debug(cmd)
1566 #self.cur.execute(cmd)
1569 cmd
= "DELETE FROM instances WHERE uuid='%s' AND tenant_id='%s'" % (instance_id
, tenant_id
)
1570 self
.cur
.execute(cmd
)
1571 return 1, "instance %s from tenant %s DELETED" % (instance_id
, tenant_id
)
1573 except (mdb
.Error
, AttributeError) as e
:
1574 r
,c
= self
.format_error(e
, "delete_instance", cmd
)
1575 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1577 def get_ports(self
, WHERE
):
1578 ''' Obtain ports using the WHERE filtering.
1580 'where_': dict of key:values, translated to key=value AND ... (Optional)
1581 Return: a list with dictionarys at each row
1583 for retry_
in range(0,2):
1588 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1589 select_
= "SELECT uuid,'ACTIVE' as status,admin_state_up,name,net_id,\
1590 tenant_id,type,mac,vlan,switch_port,instance_id,Mbps FROM ports "
1592 if WHERE
is None or len(WHERE
) == 0: where_
= ""
1594 where_
= "WHERE " + " AND ".join(map( lambda x
: str(x
) + (" is Null" if WHERE
[x
] is None else "='"+str(WHERE
[x
])+"'"), WHERE
.keys()) )
1595 limit_
= "LIMIT 100"
1596 cmd
= " ".join( (select_
, where_
, limit_
) )
1597 # print "SELECT multiple de instance_ifaces, iface_uuid, external_ports" #print cmd
1598 self
.logger
.debug(cmd
)
1599 self
.cur
.execute(cmd
)
1600 ports
= self
.cur
.fetchall()
1601 if self
.cur
.rowcount
>0: af
.DeleteNone(ports
)
1602 return self
.cur
.rowcount
, ports
1603 # return self.get_table(FROM=from_, SELECT=select_,WHERE=where_,LIMIT=100)
1604 except (mdb
.Error
, AttributeError) as e
:
1605 r
,c
= self
.format_error(e
, "get_ports", cmd
)
1606 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1608 def check_target_net(self
, net_id
, tenant_id
, port_type
):
1609 '''check if valid attachement of a port into a target net
1611 net_id: target net uuid
1612 tenant_id: client where tenant belongs. Not used in this version
1613 port_type: string with the option 'instance:bridge', 'instance:data', 'external'
1615 (0,net_dict) if ok, where net_dict contain 'uuid','type','vlan', ...
1616 (negative,string-error) if error
1618 for retry_
in range(0,2):
1622 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1623 cmd
= "SELECT * FROM nets WHERE uuid='%s'" % net_id
1624 self
.logger
.debug(cmd
)
1625 self
.cur
.execute(cmd
)
1626 if self
.cur
.rowcount
== 0 : return -1, "network_id %s does not match any net" % net_id
1627 net
= self
.cur
.fetchone()
1630 except (mdb
.Error
, AttributeError) as e
:
1631 r
,c
= self
.format_error(e
, "check_target_net", cmd
)
1632 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1634 if tenant_id
is not None and tenant_id
is not "admin":
1635 if net
['tenant_id']==tenant_id
and net
['shared']=='false':
1636 return -1, "needed admin privileges to attach to the net %s" % net_id
1638 if (net
['type'] in ('p2p','data') and port_type
!= 'instance:data') or \
1639 (net
['type'] in ('bridge_data','bridge_man') and port_type
not in ('instance:bridge', 'instance:ovs')):
1640 return -1, "can not attach a port of type %s into a net of type %s" % (port_type
, net
['type'])
1641 if net
['type'] == 'ptp':
1643 nb_ports
, data
= self
.get_ports( {'net_id':net_id
} )
1650 return -1, "net of type p2p already contain two ports attached. No room for another"
1654 if __name__
== "__main__":