1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 NFVO DB engine. It implements all the methods to interact with the Openmano Database
27 __author__
="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
28 __date__
="$28-aug-2014 10:05:01$"
37 HTTP_Bad_Request
= 400
38 HTTP_Unauthorized
= 401
40 HTTP_Method_Not_Allowed
= 405
41 HTTP_Request_Timeout
= 408
43 HTTP_Service_Unavailable
= 503
44 HTTP_Internal_Server_Error
= 500
46 tables_with_created_field
=["datacenters","instance_nets","instance_scenarios","instance_vms","instance_vnfs",
47 "interfaces","nets","nfvo_tenants","scenarios","sce_interfaces","sce_nets",
48 "sce_vnfs","tenants_datacenters","datacenter_tenants","vms","vnfs"]
55 def connect(self
, host
=None, user
=None, passwd
=None, database
=None):
56 '''Connect to specific data base.
57 The first time a valid host, user, passwd and database must be provided,
58 Following calls can skip this parameters
61 if host
is not None: self
.host
= host
62 if user
is not None: self
.user
= user
63 if passwd
is not None: self
.passwd
= passwd
64 if database
is not None: self
.database
= database
66 self
.con
= mdb
.connect(self
.host
, self
.user
, self
.passwd
, self
.database
)
67 print "DB: connected to %s@%s -> %s" % (self
.user
, self
.host
, self
.database
)
70 print "nfvo_db.connect Error connecting to DB %s@%s -> %s Error %d: %s" % (self
.user
, self
.host
, self
.database
, e
.args
[0], e
.args
[1])
73 def get_db_version(self
):
74 ''' Obtain the database schema version.
75 Return: (negative, text) if error or version 0.0 where schema_version table is missing
76 (version_int, version_text) if ok
78 cmd
= "SELECT version_int,version,openmano_ver FROM schema_version"
79 for retry_
in range(0,2):
82 self
.cur
= self
.con
.cursor()
85 rows
= self
.cur
.fetchall()
89 for row
in rows
: #look for the latest version
90 if row
[0]>highest_version_int
:
91 highest_version_int
, highest_version
= row
[0:2]
92 return highest_version_int
, highest_version
93 except (mdb
.Error
, AttributeError), e
:
95 print "get_db_version DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
96 r
,c
= self
.format_error(e
)
97 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
100 '''disconnect from specific data base'''
105 print "Error disconnecting from DB: Error %d: %s" % (e
.args
[0], e
.args
[1])
107 except AttributeError, e
: #self.con not defined
108 if e
[0][-5:] == "'con'": return -1, "Database internal error, no connection."
111 def format_error(self
, e
, command
=None, extra
=None):
112 if type(e
[0]) is str:
113 if e
[0][-5:] == "'con'": return -HTTP_Internal_Server_Error
, "DB Exception, no connection."
115 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
118 return -HTTP_Request_Timeout
,"Database reconnection. Try Again"
120 fk
=e
.args
[1].find("foreign key constraint fails")
122 if command
=="update": return -HTTP_Bad_Request
, "tenant_id %s not found." % extra
123 elif command
=="delete": return -HTTP_Bad_Request
, "Resource is not free. There are %s that prevent deleting it." % extra
124 de
= e
.args
[1].find("Duplicate entry")
125 fk
= e
.args
[1].find("for key")
126 uk
= e
.args
[1].find("Unknown column")
127 wc
= e
.args
[1].find("in 'where clause'")
128 fl
= e
.args
[1].find("in 'field list'")
129 #print de, fk, uk, wc,fl
131 if fk
>=0: #error 1062
132 return -HTTP_Conflict
, "Value %s already in use for %s" % (e
.args
[1][de
+15:fk
], e
.args
[1][fk
+7:])
135 return -HTTP_Bad_Request
, "Field %s can not be used for filtering" % e
.args
[1][uk
+14:wc
]
137 return -HTTP_Bad_Request
, "Field %s does not exist" % e
.args
[1][uk
+14:wc
]
138 return -HTTP_Internal_Server_Error
, "Database internal Error %d: %s" % (e
.args
[0], e
.args
[1])
140 def __str2db_format(self
, data
):
141 '''Convert string data to database format.
142 If data is None it returns the 'Null' text,
143 otherwise it returns the text surrounded by quotes ensuring internal quotes are escaped.
149 return "'" + out
+ "'"
151 return '"' + out
+ '"'
153 return json
.dumps(out
)
155 def __tuple2db_format_set(self
, data
):
156 '''Compose the needed text for a SQL SET, parameter 'data' is a pair tuple (A,B),
157 and it returns the text 'A="B"', where A is a field of a table and B is the value
158 If B is None it returns the 'A=Null' text, without surrounding Null by quotes
159 If B is not None it returns the text "A='B'" or 'A="B"' where B is surrounded by quotes,
160 and it ensures internal quotes of B are escaped.
163 return str(data
[0]) + "=Null"
166 return str(data
[0]) + "='" + out
+ "'"
168 return str(data
[0]) + '="' + out
+ '"'
170 return str(data
[0]) + '=' + json
.dumps(out
)
172 def __tuple2db_format_where(self
, data
):
173 '''Compose the needed text for a SQL WHERE, parameter 'data' is a pair tuple (A,B),
174 and it returns the text 'A="B"', where A is a field of a table and B is the value
175 If B is None it returns the 'A is Null' text, without surrounding Null by quotes
176 If B is not None it returns the text "A='B'" or 'A="B"' where B is surrounded by quotes,
177 and it ensures internal quotes of B are escaped.
180 return str(data
[0]) + " is Null"
182 # if type(data[1]) is tuple: #this can only happen in a WHERE_OR clause
186 # text.append(str(data[0]) + " is Null")
190 # text.append( str(data[0]) + "='" + out + "'" )
191 # elif '"' not in out:
192 # text.append( str(data[0]) + '="' + out + '"' )
194 # text.append( str(data[0]) + '=' + json.dumps(out) )
195 # return " OR ".join(text)
199 return str(data
[0]) + "='" + out
+ "'"
201 return str(data
[0]) + '="' + out
+ '"'
203 return str(data
[0]) + '=' + json
.dumps(out
)
205 def __tuple2db_format_where_not(self
, data
):
206 '''Compose the needed text for a SQL WHERE(not). parameter 'data' is a pair tuple (A,B),
207 and it returns the text 'A<>"B"', where A is a field of a table and B is the value
208 If B is None it returns the 'A is not Null' text, without surrounding Null by quotes
209 If B is not None it returns the text "A<>'B'" or 'A<>"B"' where B is surrounded by quotes,
210 and it ensures internal quotes of B are escaped.
213 return str(data
[0]) + " is not Null"
216 return str(data
[0]) + "<>'" + out
+ "'"
218 return str(data
[0]) + '<>"' + out
+ '"'
220 return str(data
[0]) + '<>' + json
.dumps(out
)
222 def __remove_quotes(self
, data
):
223 '''remove single quotes ' of any string content of data dictionary'''
224 for k
,v
in data
.items():
227 data
[k
] = data
[k
].replace("'","_")
229 def __update_rows(self
, table
, UPDATE
, WHERE
, log
=False, modified_time
=0):
230 ''' Update one or several rows into a table.
232 UPDATE: dictionary with the key: value to change
233 table: table where to update
234 WHERE: dictionary of elements to update
235 Return: (result, descriptive text) where result indicates the number of updated files, negative if error
238 uuid
= WHERE
['uuid'] if 'uuid' in WHERE
else None
239 values
= ",".join(map(self
.__tuple
2db
_format
_set
, UPDATE
.iteritems() ))
241 values
+= ",modified_at=%f" % modified_time
242 cmd
= "UPDATE " + table
+" SET " + values
+\
243 " WHERE " + " and ".join(map(self
.__tuple
2db
_format
_where
, WHERE
.iteritems() ))
245 self
.cur
.execute(cmd
)
246 nb_rows
= self
.cur
.rowcount
247 if nb_rows
> 0 and log
:
249 if uuid
is None: uuid_k
= uuid_v
= ""
250 else: uuid_k
=",uuid"; uuid_v
=",'" + str(uuid
) + "'"
251 cmd
= "INSERT INTO logs (related,level%s,description) VALUES ('%s','debug'%s,\"updating %d entry %s\")" \
252 % (uuid_k
, table
, uuid_v
, nb_rows
, (str(UPDATE
)).replace('"','-') )
254 self
.cur
.execute(cmd
)
255 return nb_rows
, "%d updated from %s" % (nb_rows
, table
[:-1] )
257 def _new_row_internal(self
, table
, INSERT
, tenant_id
=None, add_uuid
=False, root_uuid
=None, log
=False, created_time
=0):
258 ''' Add one row into a table. It DOES NOT begin or end the transaction, so self.con.cursor must be created
260 INSERT: dictionary with the key: value to insert
261 table: table where to insert
262 tenant_id: only useful for logs. If provided, logs will use this tenant_id
263 add_uuid: if True, it will create an uuid key entry at INSERT if not provided
264 It checks presence of uuid and add one automatically otherwise
265 Return: (result, uuid) where result can be 0 if error, or 1 if ok
269 #create uuid if not provided
270 if 'uuid' not in INSERT
:
271 uuid
= INSERT
['uuid'] = str(myUuid
.uuid1()) # create_uuid
273 uuid
= str(INSERT
['uuid'])
277 #defining root_uuid if not provided
278 if root_uuid
is None:
281 created_at
= created_time
283 created_at
=time
.time()
285 cmd
= "INSERT INTO uuids (uuid, root_uuid, used_at, created_at) VALUES ('%s','%s','%s', %f)" % (uuid
, root_uuid
, table
, created_at
)
287 self
.cur
.execute(cmd
)
289 cmd
= "INSERT INTO " + table
+" SET " + \
290 ",".join(map(self
.__tuple
2db
_format
_set
, INSERT
.iteritems() ))
292 cmd
+= ",created_at=%f" % created_time
294 self
.cur
.execute(cmd
)
295 nb_rows
= self
.cur
.rowcount
297 if nb_rows
> 0 and log
:
298 if add_uuid
: del INSERT
['uuid']
299 if uuid
is None: uuid_k
= uuid_v
= ""
300 else: uuid_k
=",uuid"; uuid_v
=",'" + str(uuid
) + "'"
301 if tenant_id
is None: tenant_k
= tenant_v
= ""
302 else: tenant_k
=",nfvo_tenant_id"; tenant_v
=",'" + str(tenant_id
) + "'"
303 cmd
= "INSERT INTO logs (related,level%s%s,description) VALUES ('%s','debug'%s%s,\"new %s %s\")" \
304 % (uuid_k
, tenant_k
, table
, uuid_v
, tenant_v
, table
[:-1], str(INSERT
).replace('"','-'))
306 self
.cur
.execute(cmd
)
309 def __get_rows(self
,table
,uuid
):
310 self
.cur
.execute("SELECT * FROM " + str(table
) +" where uuid='" + str(uuid
) + "'")
311 rows
= self
.cur
.fetchall()
312 return self
.cur
.rowcount
, rows
314 def new_row(self
, table
, INSERT
, tenant_id
=None, add_uuid
=False, log
=False, created_time
=0):
315 ''' Add one row into a table.
317 INSERT: dictionary with the key: value to insert
318 table: table where to insert
319 tenant_id: only useful for logs. If provided, logs will use this tenant_id
320 add_uuid: if True, it will create an uuid key entry at INSERT if not provided
321 It checks presence of uuid and add one automatically otherwise
322 Return: (result, uuid) where result can be 0 if error, or 1 if ok
324 if table
in tables_with_created_field
and created_time
==0:
325 created_time
=time
.time()
326 for retry_
in range(0,2):
329 self
.cur
= self
.con
.cursor()
330 return self
._new
_row
_internal
(table
, INSERT
, tenant_id
, add_uuid
, None, log
, created_time
)
332 except (mdb
.Error
, AttributeError), e
:
333 print "nfvo_db.new_row DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
334 r
,c
= self
.format_error(e
)
335 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
337 def update_rows(self
, table
, UPDATE
, WHERE
, log
=False, modified_time
=0):
338 ''' Update one or several rows into a table.
340 UPDATE: dictionary with the key: value to change
341 table: table where to update
342 WHERE: dictionary of elements to update
343 Return: (result, descriptive text) where result indicates the number of updated files
345 if table
in tables_with_created_field
and modified_time
==0:
346 modified_time
=time
.time()
347 for retry_
in range(0,2):
350 self
.cur
= self
.con
.cursor()
351 return self
.__update
_rows
(table
, UPDATE
, WHERE
, log
)
353 except (mdb
.Error
, AttributeError), e
:
354 print "nfvo_db.update_rows DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
355 r
,c
= self
.format_error(e
)
356 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
358 def delete_row(self
, table
, uuid
, tenant_id
=None, log
=True):
359 for retry_
in range(0,2):
363 self
.cur
= self
.con
.cursor()
364 cmd
= "DELETE FROM %s WHERE uuid = '%s'" % (table
, uuid
)
366 self
.cur
.execute(cmd
)
367 deleted
= self
.cur
.rowcount
370 if table
== 'tenants': tenant_str
=uuid
372 tenant_str
= tenant_id
375 self
.cur
= self
.con
.cursor()
376 cmd
= "DELETE FROM uuids WHERE root_uuid = '%s'" % uuid
378 self
.cur
.execute(cmd
)
381 cmd
= "INSERT INTO logs (related,level,uuid,nfvo_tenant_id,description) VALUES ('%s','debug','%s','%s','delete %s')" % (table
, uuid
, tenant_str
, table
[:-1])
383 self
.cur
.execute(cmd
)
384 return deleted
, table
[:-1] + " '%s' %s" %(uuid
, "deleted" if deleted
==1 else "not found")
385 except (mdb
.Error
, AttributeError), e
:
386 print "nfvo_db.delete_row DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
387 r
,c
= self
.format_error(e
, "delete", 'instances' if table
=='hosts' or table
=='tenants' else 'dependencies')
388 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
390 def delete_row_by_dict(self
, **sql_dict
):
391 ''' Deletes rows from a table.
392 Attribute sql_dir: dictionary with the following key: value
393 'FROM': string of table name (Mandatory)
394 'WHERE': dict of key:values, translated to key=value AND ... (Optional)
395 'WHERE_NOT': dict of key:values, translated to key<>value AND ... (Optional)
396 'LIMIT': limit of number of rows (Optional)
397 Return: the (number of items deleted, descriptive test) if ok; (negative, descriptive text) if error
400 from_
= "FROM " + str(sql_dict
['FROM'])
401 #print 'from_', from_
402 if 'WHERE' in sql_dict
and len(sql_dict
['WHERE']) > 0:
404 where_
= "WHERE " + " AND ".join(map(self
.__tuple
2db
_format
_where
, w
.iteritems()))
406 if 'WHERE_NOT' in sql_dict
and len(sql_dict
['WHERE_NOT']) > 0:
407 w
=sql_dict
['WHERE_NOT']
408 where_2
= " AND ".join(map(self
.__tuple
2db
_format
_where
_not
, w
.iteritems()))
409 if len(where_
)==0: where_
= "WHERE " + where_2
410 else: where_
= where_
+ " AND " + where_2
411 #print 'where_', where_
412 limit_
= "LIMIT " + str(sql_dict
['LIMIT']) if 'LIMIT' in sql_dict
else ""
413 #print 'limit_', limit_
414 cmd
= " ".join( ("DELETE", from_
, where_
, limit_
) )
416 for retry_
in range(0,2):
420 self
.cur
= self
.con
.cursor()
421 self
.cur
.execute(cmd
)
422 deleted
= self
.cur
.rowcount
423 return deleted
, "%d deleted from %s" % (deleted
, sql_dict
['FROM'][:-1] )
424 except (mdb
.Error
, AttributeError), e
:
425 print "nfvo_db.delete_row DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
426 r
,c
= self
.format_error(e
, "delete", 'dependencies')
427 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
429 def get_rows(self
,table
,uuid
):
430 '''get row from a table based on uuid'''
431 for retry_
in range(0,2):
434 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
435 self
.cur
.execute("SELECT * FROM " + str(table
) +" where uuid='" + str(uuid
) + "'")
436 rows
= self
.cur
.fetchall()
437 return self
.cur
.rowcount
, rows
438 except (mdb
.Error
, AttributeError), e
:
439 print "nfvo_db.get_rows DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
440 r
,c
= self
.format_error(e
)
441 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
443 def get_table(self
, **sql_dict
):
444 ''' Obtain rows from a table.
445 Attribute sql_dir: dictionary with the following key: value
446 'SELECT': list or tuple of fields to retrieve) (by default all)
447 'FROM': string of table name (Mandatory)
448 'WHERE': dict of key:values, translated to key=value (key is null) AND ... (Optional)
449 'WHERE_NOT': dict of key:values, translated to key<>value (key is not null) AND ... (Optional)
450 'WHERE_OR': dict of key:values, translated to key=value OR ... (Optional)
451 'WHERE_AND_OR: str 'AND' or 'OR'(by default) mark the priority to 'WHERE AND (WHERE_OR)' or (WHERE) OR WHERE_OR' (Optional
452 'LIMIT': limit of number of rows (Optional)
453 'ORDER_BY': list or tuple of fields to order
454 Return: a list with dictionaries at each row
457 select_
= "SELECT " + ("*" if 'SELECT' not in sql_dict
else ",".join(map(str,sql_dict
['SELECT'])) )
458 #print 'select_', select_
459 from_
= "FROM " + str(sql_dict
['FROM'])
460 #print 'from_', from_
463 w
=sql_dict
.get('WHERE')
465 where_and
= " AND ".join(map(self
.__tuple
2db
_format
_where
, w
.iteritems() ))
466 w
=sql_dict
.get('WHERE_NOT')
468 if where_and
: where_and
+= " AND "
469 where_and
+= " AND ".join(map(self
.__tuple
2db
_format
_where
_not
, w
.iteritems() ) )
470 w
=sql_dict
.get('WHERE_OR')
472 where_or
= " OR ".join(map(self
.__tuple
2db
_format
_where
, w
.iteritems() ))
473 if where_and
and where_or
:
474 if sql_dict
.get("WHERE_AND_OR") == "AND":
475 where_
= "WHERE " + where_and
+ " AND (" + where_or
+ ")"
477 where_
= "WHERE (" + where_and
+ ") OR " + where_or
478 elif where_and
and not where_or
:
479 where_
= "WHERE " + where_and
480 elif not where_and
and where_or
:
481 where_
= "WHERE " + where_or
484 #print 'where_', where_
485 limit_
= "LIMIT " + str(sql_dict
['LIMIT']) if 'LIMIT' in sql_dict
else ""
486 order_
= "ORDER BY " + ",".join(map(str,sql_dict
['SELECT'])) if 'ORDER_BY' in sql_dict
else ""
488 #print 'limit_', limit_
489 cmd
= " ".join( (select_
, from_
, where_
, limit_
, order_
) )
490 for retry_
in range(0,2):
493 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
495 self
.cur
.execute(cmd
)
496 rows
= self
.cur
.fetchall()
497 return self
.cur
.rowcount
, rows
498 except (mdb
.Error
, AttributeError), e
:
499 print "nfvo_db.get_table DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
500 r
,c
= self
.format_error(e
)
501 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
503 def get_table_by_uuid_name(self
, table
, uuid_name
, error_item_text
=None, allow_serveral
=False, WHERE_OR
={}, WHERE_AND_OR
="OR"):
504 ''' Obtain One row from a table based on name or uuid.
506 table: string of table name
507 uuid_name: name or uuid. If not uuid format is found, it is considered a name
508 allow_severeral: if False return ERROR if more than one row are founded
509 error_item_text: in case of error it identifies the 'item' name for a proper output text
510 'WHERE_OR': dict of key:values, translated to key=value OR ... (Optional)
511 'WHERE_AND_OR: str 'AND' or 'OR'(by default) mark the priority to 'WHERE AND (WHERE_OR)' or (WHERE) OR WHERE_OR' (Optional
512 Return: if allow_several==False, a dictionary with this row, or error if no item is found or more than one is found
513 if allow_several==True, a list of dictionaries with the row or rows, error if no item is found
516 if error_item_text
==None:
517 error_item_text
= table
518 what
= 'uuid' if utils
.check_valid_uuid(uuid_name
) else 'name'
519 cmd
= " SELECT * FROM %s WHERE %s='%s'" % (table
, what
, uuid_name
)
521 where_or
= " OR ".join(map(self
.__tuple
2db
_format
_where
, WHERE_OR
.iteritems() ))
522 if WHERE_AND_OR
== "AND":
523 cmd
+= " AND (" + where_or
+ ")"
525 cmd
+= " OR " + where_or
528 for retry_
in range(0,2):
531 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
533 self
.cur
.execute(cmd
)
534 number
= self
.cur
.rowcount
536 return -HTTP_Not_Found
, "No %s found with %s '%s'" %(error_item_text
, what
, uuid_name
)
537 elif number
>1 and not allow_serveral
:
538 return -HTTP_Bad_Request
, "More than one %s found with %s '%s'" %(error_item_text
, what
, uuid_name
)
540 rows
= self
.cur
.fetchall()
542 rows
= self
.cur
.fetchone()
544 except (mdb
.Error
, AttributeError), e
:
545 print "nfvo_db.get_table_by_uuid_name DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
546 r
,c
= self
.format_error(e
)
547 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
549 def get_uuid(self
, uuid
):
550 '''check in the database if this uuid is already present'''
551 for retry_
in range(0,2):
554 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
555 self
.cur
.execute("SELECT * FROM uuids where uuid='" + str(uuid
) + "'")
556 rows
= self
.cur
.fetchall()
557 return self
.cur
.rowcount
, rows
558 except (mdb
.Error
, AttributeError), e
:
559 print "nfvo_db.get_uuid DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
560 r
,c
= self
.format_error(e
)
561 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
563 def new_vnf_as_a_whole(self
,nfvo_tenant
,vnf_name
,vnf_descriptor
,VNFCDict
):
564 print "Adding new vnf to the NFVO database"
565 for retry_
in range(0,2):
566 created_time
= time
.time()
571 myVNFDict
["name"] = vnf_name
572 myVNFDict
["descriptor"] = vnf_descriptor
['vnf'].get('descriptor')
573 myVNFDict
["public"] = vnf_descriptor
['vnf'].get('public', "false")
574 myVNFDict
["description"] = vnf_descriptor
['vnf']['description']
575 myVNFDict
["class"] = vnf_descriptor
['vnf'].get('class',"MISC")
576 myVNFDict
["tenant_id"] = vnf_descriptor
['vnf'].get("tenant_id")
578 result
, vnf_id
= self
._new
_vnf
(myVNFDict
,nfvo_tenant
,created_time
)
580 return result
, "Error creating vnf in NFVO database: %s" %vnf_id
582 print "VNF %s added to NFVO DB. VNF id: %s" % (vnf_name
,vnf_id
)
584 print "Adding new vms to the NFVO database"
585 #For each vm, we must create the appropriate vm in the NFVO database.
587 for _
,vm
in VNFCDict
.iteritems():
588 #This code could make the name of the vms grow and grow.
589 #If we agree to follow this convention, we should check with a regex that the vnfc name is not including yet the vnf name
590 #vm['name'] = "%s-%s" % (vnf_name,vm['name'])
591 print "VM name: %s. Description: %s" % (vm
['name'], vm
['description'])
592 vm
["vnf_id"] = vnf_id
593 created_time
+= 0.00001
594 result
, vm_id
= self
._new
_vm
(vm
,nfvo_tenant
,vnf_id
,created_time
)
596 return result
, "Error creating vm in NFVO database: %s" %vm_id
598 print "Internal vm id in NFVO DB: %s" % vm_id
599 vmDict
[vm
['name']] = vm_id
601 #Collect the data interfaces of each VM/VNFC under the 'numas' field
603 for vm
in vnf_descriptor
['vnf']['VNFC']:
604 dataifacesDict
[vm
['name']] = {}
605 for numa
in vm
.get('numas', []):
606 for dataiface
in numa
.get('interfaces',[]):
607 utils
.convert_bandwidth(dataiface
)
608 dataifacesDict
[vm
['name']][dataiface
['name']] = {}
609 dataifacesDict
[vm
['name']][dataiface
['name']]['vpci'] = dataiface
['vpci']
610 dataifacesDict
[vm
['name']][dataiface
['name']]['bw'] = dataiface
['bandwidth']
611 dataifacesDict
[vm
['name']][dataiface
['name']]['model'] = "PF" if dataiface
['dedicated']=="yes" else ("VF" if dataiface
['dedicated']=="no" else "VFnotShared")
613 #Collect the bridge interfaces of each VM/VNFC under the 'bridge-ifaces' field
614 bridgeInterfacesDict
= {}
615 for vm
in vnf_descriptor
['vnf']['VNFC']:
616 if 'bridge-ifaces' in vm
:
617 bridgeInterfacesDict
[vm
['name']] = {}
618 for bridgeiface
in vm
['bridge-ifaces']:
619 utils
.convert_bandwidth(bridgeiface
)
620 bridgeInterfacesDict
[vm
['name']][bridgeiface
['name']] = {}
621 bridgeInterfacesDict
[vm
['name']][bridgeiface
['name']]['vpci'] = bridgeiface
.get('vpci',None)
622 bridgeInterfacesDict
[vm
['name']][bridgeiface
['name']]['mac'] = bridgeiface
.get('mac_address',None)
623 bridgeInterfacesDict
[vm
['name']][bridgeiface
['name']]['bw'] = bridgeiface
.get('bandwidth', None)
624 bridgeInterfacesDict
[vm
['name']][bridgeiface
['name']]['model'] = bridgeiface
.get('model', None)
626 #For each internal connection, we add it to the interfaceDict and we create the appropriate net in the NFVO database.
627 print "Adding new nets (VNF internal nets) to the NFVO database (if any)"
628 internalconnList
= []
629 if 'internal-connections' in vnf_descriptor
['vnf']:
630 for net
in vnf_descriptor
['vnf']['internal-connections']:
631 print "CODE TO BE CHECKED"
632 print "Net name: %s. Description: %s" % (net
['name'], net
['description'])
635 myNetDict
["name"] = net
['name']
636 myNetDict
["description"] = net
['description']
637 myNetDict
["type"] = net
['type']
638 myNetDict
["vnf_id"] = vnf_id
640 created_time
+= 0.00001
641 result
, net_id
= self
._new
_net
(myNetDict
,nfvo_tenant
,vnf_id
, created_time
)
643 return result
, "Error creating net in NFVO database: %s" %net_id
645 for element
in net
['elements']:
647 #ifaceItem["internal_name"] = "%s-%s-%s" % (net['name'],element['VNFC'], element['local_iface_name'])
648 ifaceItem
["internal_name"] = element
['local_iface_name']
649 #ifaceItem["vm_id"] = vmDict["%s-%s" % (vnf_name,element['VNFC'])]
650 ifaceItem
["vm_id"] = vmDict
[element
['VNFC']]
651 ifaceItem
["net_id"] = net_id
652 ifaceItem
["type"] = net
['type']
653 if ifaceItem
["type"] == "data":
654 ifaceItem
["vpci"] = dataifacesDict
[ element
['VNFC'] ][ element
['local_iface_name'] ]['vpci']
655 ifaceItem
["bw"] = dataifacesDict
[ element
['VNFC'] ][ element
['local_iface_name'] ]['bw']
656 ifaceItem
["model"] = dataifacesDict
[ element
['VNFC'] ][ element
['local_iface_name'] ]['model']
658 ifaceItem
["vpci"] = bridgeInterfacesDict
[ element
['VNFC'] ][ element
['local_iface_name'] ]['vpci']
659 ifaceItem
["mac"] = bridgeInterfacesDict
[ element
['VNFC'] ][ element
['local_iface_name'] ]['mac_address']
660 ifaceItem
["bw"] = bridgeInterfacesDict
[ element
['VNFC'] ][ element
['local_iface_name'] ]['bw']
661 ifaceItem
["model"] = bridgeInterfacesDict
[ element
['VNFC'] ][ element
['local_iface_name'] ]['model']
662 internalconnList
.append(ifaceItem
)
664 print "Internal net id in NFVO DB: %s" % net_id
666 print "Adding internal interfaces to the NFVO database (if any)"
667 for iface
in internalconnList
:
668 print "Iface name: %s" % iface
['internal_name']
669 created_time
+= 0.00001
670 result
, iface_id
= self
._new
_interface
(iface
,nfvo_tenant
,vnf_id
,created_time
)
672 return result
, "Error creating iface in NFVO database: %s" %iface
_id
673 print "Iface id in NFVO DB: %s" % iface_id
675 print "Adding external interfaces to the NFVO database"
676 for iface
in vnf_descriptor
['vnf']['external-connections']:
678 #myIfaceDict["internal_name"] = "%s-%s-%s" % (vnf_name,iface['VNFC'], iface['local_iface_name'])
679 myIfaceDict
["internal_name"] = iface
['local_iface_name']
680 #myIfaceDict["vm_id"] = vmDict["%s-%s" % (vnf_name,iface['VNFC'])]
681 myIfaceDict
["vm_id"] = vmDict
[iface
['VNFC']]
682 myIfaceDict
["external_name"] = iface
['name']
683 myIfaceDict
["type"] = iface
['type']
684 if iface
["type"] == "data":
685 myIfaceDict
["vpci"] = dataifacesDict
[ iface
['VNFC'] ][ iface
['local_iface_name'] ]['vpci']
686 myIfaceDict
["bw"] = dataifacesDict
[ iface
['VNFC'] ][ iface
['local_iface_name'] ]['bw']
687 myIfaceDict
["model"] = dataifacesDict
[ iface
['VNFC'] ][ iface
['local_iface_name'] ]['model']
689 myIfaceDict
["vpci"] = bridgeInterfacesDict
[ iface
['VNFC'] ][ iface
['local_iface_name'] ]['vpci']
690 myIfaceDict
["bw"] = bridgeInterfacesDict
[ iface
['VNFC'] ][ iface
['local_iface_name'] ]['bw']
691 myIfaceDict
["model"] = bridgeInterfacesDict
[ iface
['VNFC'] ][ iface
['local_iface_name'] ]['model']
692 myIfaceDict
["mac"] = bridgeInterfacesDict
[ iface
['VNFC'] ][ iface
['local_iface_name'] ]['mac']
693 print "Iface name: %s" % iface
['name']
694 created_time
+= 0.00001
695 result
, iface_id
= self
._new
_interface
(myIfaceDict
,nfvo_tenant
,vnf_id
,created_time
)
697 return result
, "Error creating iface in NFVO database: %s" %iface
_id
698 print "Iface id in NFVO DB: %s" % iface_id
702 except (mdb
.Error
, AttributeError), e
:
703 print "new_vnf_as_a_whole DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
704 r
,c
= self
.format_error(e
)
705 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
707 def _new_vnf(self
, vnf_dict
, tenant_id
, created_time
=0):
708 #return self.new_row('vnfs', vnf_dict, None, tenant_id, True, True)
709 return self
._new
_row
_internal
('vnfs', vnf_dict
, tenant_id
, add_uuid
=True, root_uuid
=None, log
=True, created_time
=created_time
)
711 def _new_vm(self
, vm_dict
, tenant_id
, vnf_id
= None, created_time
=0):
712 #return self.new_row('vms', vm_dict, tenant_id, True, True)
713 return self
._new
_row
_internal
('vms', vm_dict
, tenant_id
, add_uuid
=True, root_uuid
=vnf_id
, log
=True, created_time
=created_time
)
716 def _new_net(self
, net_dict
, tenant_id
, vnf_id
= None, created_time
=0):
717 #return self.new_row('nets', net_dict, tenant_id, True, True)
718 return self
._new
_row
_internal
('nets', net_dict
, tenant_id
, add_uuid
=True, root_uuid
=vnf_id
, log
=True, created_time
=created_time
)
720 def _new_interface(self
, interface_dict
, tenant_id
, vnf_id
= None, created_time
=0):
721 #return self.new_row('interfaces', interface_dict, tenant_id, True, True)
722 return self
._new
_row
_internal
('interfaces', interface_dict
, tenant_id
, add_uuid
=True, root_uuid
=vnf_id
, log
=True, created_time
=created_time
)
724 def new_scenario(self
, scenario_dict
):
725 for retry_
in range(0,2):
726 created_time
= time
.time()
729 self
.cur
= self
.con
.cursor()
730 tenant_id
= scenario_dict
.get('tenant_id')
732 INSERT_
={'tenant_id': tenant_id
,
733 'name': scenario_dict
['name'],
734 'description': scenario_dict
['description'],
735 'public': scenario_dict
.get('public', "false")}
737 r
,scenario_uuid
= self
._new
_row
_internal
('scenarios', INSERT_
, tenant_id
, True, None, True,created_time
)
739 print 'nfvo_db.new_scenario Error inserting at table scenarios: ' + scenario_uuid
740 return r
,scenario_uuid
742 for net
in scenario_dict
['nets'].values():
743 net_dict
={'scenario_id': scenario_uuid
}
744 net_dict
["name"] = net
["name"]
745 net_dict
["type"] = net
["type"]
746 net_dict
["description"] = net
.get("description")
747 net_dict
["external"] = net
.get("external", False)
749 #net["graph"]=yaml.safe_dump(net["graph"],default_flow_style=True,width=256)
750 #TODO, must be json because of the GUI, change to yaml
751 net_dict
["graph"]=json
.dumps(net
["graph"])
752 created_time
+= 0.00001
753 r
,net_uuid
= self
._new
_row
_internal
('sce_nets', net_dict
, tenant_id
, True, None, True, created_time
)
755 print 'nfvo_db.new_scenario Error inserting at table sce_vnfs: ' + net_uuid
759 for k
,vnf
in scenario_dict
['vnfs'].items():
760 INSERT_
={'scenario_id': scenario_uuid
,
762 'vnf_id': vnf
['uuid'],
763 #'description': scenario_dict['name']
764 'description': vnf
['description']
767 #INSERT_["graph"]=yaml.safe_dump(vnf["graph"],default_flow_style=True,width=256)
768 #TODO, must be json because of the GUI, change to yaml
769 INSERT_
["graph"]=json
.dumps(vnf
["graph"])
770 created_time
+= 0.00001
771 r
,scn_vnf_uuid
= self
._new
_row
_internal
('sce_vnfs', INSERT_
, tenant_id
, True, scenario_uuid
, True, created_time
)
773 print 'nfvo_db.new_scenario Error inserting at table sce_vnfs: ' + scn_vnf_uuid
774 return r
, scn_vnf_uuid
775 vnf
['scn_vnf_uuid']=scn_vnf_uuid
777 for iface
in vnf
['ifaces'].values():
779 if 'net_key' not in iface
:
781 iface
['net_id'] = scenario_dict
['nets'][ iface
['net_key'] ]['uuid']
782 INSERT_
={'sce_vnf_id': scn_vnf_uuid
,
783 'sce_net_id': iface
['net_id'],
784 'interface_id': iface
[ 'uuid' ]
786 created_time
+= 0.00001
787 r
,iface_uuid
= self
._new
_row
_internal
('sce_interfaces', INSERT_
, tenant_id
, True, scenario_uuid
, True, created_time
)
789 print 'nfvo_db.new_scenario Error inserting at table sce_vnfs: ' + iface_uuid
792 return 1, scenario_uuid
794 except (mdb
.Error
, AttributeError), e
:
795 print "nfvo_db.new_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
796 r
,c
= self
.format_error(e
)
797 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
799 def edit_scenario(self
, scenario_dict
):
800 for retry_
in range(0,2):
801 modified_time
= time
.time()
804 self
.cur
= self
.con
.cursor()
805 #check that scenario exist
806 tenant_id
= scenario_dict
.get('tenant_id')
807 scenario_uuid
= scenario_dict
['uuid']
809 where_text
= "uuid='%s'" % scenario_uuid
810 if not tenant_id
and tenant_id
!= "any":
811 where_text
+= " AND (tenant_id='%s' OR public='True')" % (tenant_id
)
812 self
.cur
.execute("SELECT * FROM scenarios WHERE "+ where_text
)
814 if self
.cur
.rowcount
==0:
815 return -HTTP_Bad_Request
, "No scenario found with this criteria " + where_text
816 elif self
.cur
.rowcount
>1:
817 return -HTTP_Bad_Request
, "More than one scenario found with this criteria " + where_text
821 topology
= scenario_dict
.pop("topology", None)
822 if topology
!= None and "nodes" in topology
:
823 nodes
= topology
.get("nodes",{})
825 if "name" in scenario_dict
: UPDATE_
["name"] = scenario_dict
["name"]
826 if "description" in scenario_dict
: UPDATE_
["description"] = scenario_dict
["description"]
828 WHERE_
={'tenant_id': tenant_id
, 'uuid': scenario_uuid
}
829 r
,c
= self
.__update
_rows
('scenarios', UPDATE_
, WHERE_
, modified_time
=modified_time
)
831 print 'nfvo_db.edit_scenario Error ' + c
+ ' updating table scenarios: ' + scenario_uuid
832 return r
,scenario_uuid
834 for node_id
, node
in nodes
.items():
836 #node["graph"] = yaml.safe_dump(node["graph"],default_flow_style=True,width=256)
837 #TODO, must be json because of the GUI, change to yaml
838 node
["graph"] = json
.dumps(node
["graph"])
839 WHERE_
={'scenario_id': scenario_uuid
, 'uuid': node_id
}
840 r
,c
= self
.__update
_rows
('sce_nets', node
, WHERE_
)
842 r
,c
= self
.__update
_rows
('sce_vnfs', node
, WHERE_
, modified_time
=modified_time
)
844 print 'nfvo_db.edit_scenario Error updating table sce_nets,sce_vnfs: ' + scenario_uuid
845 return r
, scenario_uuid
846 return 1, scenario_uuid
848 except (mdb
.Error
, AttributeError), e
:
849 print "nfvo_db.new_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
850 r
,c
= self
.format_error(e
)
851 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
853 # def get_instance_scenario(self, instance_scenario_id, tenant_id=None):
854 # '''Obtain the scenario instance information, filtering by one or serveral of the tenant, uuid or name
855 # instance_scenario_id is the uuid or the name if it is not a valid uuid format
856 # Only one scenario isntance must mutch the filtering or an error is returned
858 # print "1******************************************************************"
861 # self.cur = self.con.cursor(mdb.cursors.DictCursor)
864 # if tenant_id is not None: where_list.append( "tenant_id='" + tenant_id +"'" )
865 # if utils.check_valid_uuid(instance_scenario_id):
866 # where_list.append( "uuid='" + instance_scenario_id +"'" )
868 # where_list.append( "name='" + instance_scenario_id +"'" )
869 # where_text = " AND ".join(where_list)
870 # self.cur.execute("SELECT * FROM instance_scenarios WHERE "+ where_text)
871 # rows = self.cur.fetchall()
872 # if self.cur.rowcount==0:
873 # return -HTTP_Bad_Request, "No scenario instance found with this criteria " + where_text
874 # elif self.cur.rowcount>1:
875 # return -HTTP_Bad_Request, "More than one scenario instance found with this criteria " + where_text
876 # instance_scenario_dict = rows[0]
879 # self.cur.execute("SELECT uuid,vnf_id FROM instance_vnfs WHERE instance_scenario_id='"+ instance_scenario_dict['uuid'] + "'")
880 # instance_scenario_dict['instance_vnfs'] = self.cur.fetchall()
881 # for vnf in instance_scenario_dict['instance_vnfs']:
883 # self.cur.execute("SELECT uuid, vim_vm_id "+
884 # "FROM instance_vms "+
885 # "WHERE instance_vnf_id='" + vnf['uuid'] +"'"
887 # vnf['instance_vms'] = self.cur.fetchall()
889 # self.cur.execute("SELECT uuid, vim_net_id FROM instance_nets WHERE instance_scenario_id='"+ instance_scenario_dict['uuid'] + "'")
890 # instance_scenario_dict['instance_nets'] = self.cur.fetchall()
892 # #instance_interfaces
893 # self.cur.execute("SELECT uuid, vim_interface_id, instance_vm_id, instance_net_id FROM instance_interfaces WHERE instance_scenario_id='"+ instance_scenario_dict['uuid'] + "'")
894 # instance_scenario_dict['instance_interfaces'] = self.cur.fetchall()
896 # utils.convert_datetime2str(instance_scenario_dict)
897 # utils.convert_str2boolean(instance_scenario_dict, ('public','shared','external') )
898 # print "2******************************************************************"
899 # return 1, instance_scenario_dict
900 # except (mdb.Error, AttributeError), e:
901 # print "nfvo_db.get_instance_scenario DB Exception %d: %s" % (e.args[0], e.args[1])
902 # return self.format_error(e)
904 def get_scenario(self
, scenario_id
, tenant_id
=None, datacenter_id
=None):
905 '''Obtain the scenario information, filtering by one or serveral of the tenant, uuid or name
906 scenario_id is the uuid or the name if it is not a valid uuid format
907 if datacenter_id is provided, it supply aditional vim_id fields with the matching vim uuid
908 Only one scenario must mutch the filtering or an error is returned
910 for retry_
in range(0,2):
913 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
915 if utils
.check_valid_uuid(scenario_id
):
916 where_text
= "uuid='%s'" % scenario_id
918 where_text
= "name='%s'" % scenario_id
919 if not tenant_id
and tenant_id
!= "any":
920 where_text
+= " AND (tenant_id='%s' OR public='True')" % (tenant_id
)
921 cmd
= "SELECT * FROM scenarios WHERE "+ where_text
923 self
.cur
.execute(cmd
)
924 rows
= self
.cur
.fetchall()
925 if self
.cur
.rowcount
==0:
926 return -HTTP_Bad_Request
, "No scenario found with this criteria " + where_text
927 elif self
.cur
.rowcount
>1:
928 return -HTTP_Bad_Request
, "More than one scenario found with this criteria " + where_text
929 scenario_dict
= rows
[0]
932 cmd
= "SELECT uuid,name,vnf_id,description FROM sce_vnfs WHERE scenario_id='%s' ORDER BY created_at" % scenario_dict
['uuid']
933 self
.cur
.execute(cmd
)
934 scenario_dict
['vnfs'] = self
.cur
.fetchall()
935 for vnf
in scenario_dict
['vnfs']:
937 cmd
= "SELECT uuid,sce_net_id,interface_id FROM sce_interfaces WHERE sce_vnf_id='%s' ORDER BY created_at" %vnf
['uuid']
938 self
.cur
.execute(cmd
)
939 vnf
['interfaces'] = self
.cur
.fetchall()
941 cmd
= "SELECT vms.uuid as uuid, flavor_id, image_id, vms.name as name, vms.description as description " \
942 " FROM vnfs join vms on vnfs.uuid=vms.vnf_id " \
943 " WHERE vnfs.uuid='" + vnf
['vnf_id'] +"'" \
944 " ORDER BY vms.created_at"
945 self
.cur
.execute(cmd
)
946 vnf
['vms'] = self
.cur
.fetchall()
947 for vm
in vnf
['vms']:
948 if datacenter_id
!=None:
949 self
.cur
.execute("SELECT vim_id FROM datacenters_images WHERE image_id='%s' AND datacenter_id='%s'" %(vm
['image_id'],datacenter_id
))
950 if self
.cur
.rowcount
==1:
951 vim_image_dict
= self
.cur
.fetchone()
952 vm
['vim_image_id']=vim_image_dict
['vim_id']
953 self
.cur
.execute("SELECT vim_id FROM datacenters_flavors WHERE flavor_id='%s' AND datacenter_id='%s'" %(vm
['flavor_id'],datacenter_id
))
954 if self
.cur
.rowcount
==1:
955 vim_flavor_dict
= self
.cur
.fetchone()
956 vm
['vim_flavor_id']=vim_flavor_dict
['vim_id']
959 cmd
= "SELECT uuid,internal_name,external_name,net_id,type,vpci,mac,bw,model" \
961 " WHERE vm_id='%s'" \
962 " ORDER BY created_at" % vm
['uuid']
963 self
.cur
.execute(cmd
)
964 vm
['interfaces'] = self
.cur
.fetchall()
965 #nets every net of a vms
966 self
.cur
.execute("SELECT uuid,name,type,description FROM nets WHERE vnf_id='" + vnf
['vnf_id'] +"'" )
967 vnf
['nets'] = self
.cur
.fetchall()
969 cmd
= "SELECT uuid,name,type,external,description" \
970 " FROM sce_nets WHERE scenario_id='%s'" \
971 " ORDER BY created_at " % scenario_dict
['uuid']
972 self
.cur
.execute(cmd
)
973 scenario_dict
['nets'] = self
.cur
.fetchall()
975 for net
in scenario_dict
['nets']:
976 if str(net
['external']) == 'false':
978 WHERE_
=" WHERE name='%s'" % net
['name']
979 if datacenter_id
!=None:
980 WHERE_
+= " AND datacenter_id='%s'" % datacenter_id
981 self
.cur
.execute("SELECT vim_net_id FROM datacenter_nets" + WHERE_
)
982 d_net
= self
.cur
.fetchone()
983 if d_net
==None or datacenter_id
==None:
984 #print "nfvo_db.get_scenario() WARNING external net %s not found" % net['name']
987 net
['vim_id']=d_net
['vim_net_id']
989 utils
.convert_datetime2str(scenario_dict
)
990 utils
.convert_str2boolean(scenario_dict
, ('public','shared','external') )
991 return 1, scenario_dict
992 except (mdb
.Error
, AttributeError), e
:
993 print "nfvo_db.get_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
994 r
,c
= self
.format_error(e
)
995 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
997 def get_uuid_from_name(self
, table
, name
):
998 '''Searchs in table the name and returns the uuid
1000 for retry_
in range(0,2):
1003 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1004 where_text
= "name='" + name
+"'"
1005 self
.cur
.execute("SELECT * FROM " + table
+ " WHERE "+ where_text
)
1006 rows
= self
.cur
.fetchall()
1007 if self
.cur
.rowcount
==0:
1008 return 0, "Name %s not found in table %s" %(name
, table
)
1009 elif self
.cur
.rowcount
>1:
1010 return self
.cur
.rowcount
, "More than one VNF with name %s found in table %s" %(name
, table
)
1011 return self
.cur
.rowcount
, rows
[0]["uuid"]
1012 except (mdb
.Error
, AttributeError), e
:
1013 print "nfvo_db.get_uuid_from_name DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1014 r
,c
= self
.format_error(e
)
1015 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1017 def delete_scenario(self
, scenario_id
, tenant_id
=None):
1018 '''Deletes a scenario, filtering by one or several of the tenant, uuid or name
1019 scenario_id is the uuid or the name if it is not a valid uuid format
1020 Only one scenario must mutch the filtering or an error is returned
1022 for retry_
in range(0,2):
1025 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1028 if utils
.check_valid_uuid(scenario_id
):
1029 where_text
= "uuid='%s'" % scenario_id
1031 where_text
= "name='%s'" % scenario_id
1032 if not tenant_id
and tenant_id
!= "any":
1033 where_text
+= " AND (tenant_id='%s' OR public='True')" % tenant_id
1034 self
.cur
.execute("SELECT * FROM scenarios WHERE "+ where_text
)
1035 rows
= self
.cur
.fetchall()
1036 if self
.cur
.rowcount
==0:
1037 return -HTTP_Bad_Request
, "No scenario found with this criteria " + where_text
1038 elif self
.cur
.rowcount
>1:
1039 return -HTTP_Bad_Request
, "More than one scenario found with this criteria " + where_text
1040 scenario_uuid
= rows
[0]["uuid"]
1041 scenario_name
= rows
[0]["name"]
1044 self
.cur
.execute("DELETE FROM scenarios WHERE uuid='" + scenario_uuid
+ "'")
1046 return 1, scenario_uuid
+ " " + scenario_name
1047 except (mdb
.Error
, AttributeError), e
:
1048 print "nfvo_db.delete_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1049 r
,c
= self
.format_error(e
, "delete", "instances running")
1050 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1052 def new_instance_scenario_as_a_whole(self
,tenant_id
,instance_scenario_name
,instance_scenario_description
,scenarioDict
):
1053 print "Adding new instance scenario to the NFVO database"
1054 for retry_
in range(0,2):
1055 created_time
= time
.time()
1058 self
.cur
= self
.con
.cursor()
1060 datacenter_tenant_id
= scenarioDict
['datacenter_tenant_id']
1061 datacenter_id
= scenarioDict
['datacenter_id']
1062 INSERT_
={'tenant_id': tenant_id
,
1063 'datacenter_tenant_id': datacenter_tenant_id
,
1064 'name': instance_scenario_name
,
1065 'description': instance_scenario_description
,
1066 'scenario_id' : scenarioDict
['uuid'],
1067 'datacenter_id': datacenter_id
1069 r
,instance_uuid
= self
._new
_row
_internal
('instance_scenarios', INSERT_
, tenant_id
, True, None, True, created_time
)
1071 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_scenarios: ' + instance_uuid
1072 return r
, instance_uuid
1074 net_scene2instance
={}
1075 #instance_nets #nets interVNF
1076 for net
in scenarioDict
['nets']:
1077 INSERT_
={'vim_net_id': net
['vim_id'], 'external': net
['external'], 'instance_scenario_id':instance_uuid
} #, 'type': net['type']
1078 INSERT_
['datacenter_id'] = net
.get('datacenter_id', datacenter_id
)
1079 INSERT_
['datacenter_tenant_id'] = net
.get('datacenter_tenant_id', datacenter_tenant_id
)
1081 INSERT_
['sce_net_id'] = net
['uuid']
1082 created_time
+= 0.00001
1083 r
,instance_net_uuid
= self
._new
_row
_internal
('instance_nets', INSERT_
, tenant_id
, True, instance_uuid
, True, created_time
)
1085 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_nets: ' + instance_net_uuid
1086 return r
, instance_net_uuid
1087 net_scene2instance
[ net
['uuid'] ] = instance_net_uuid
1088 net
['uuid'] = instance_net_uuid
#overwrite scnario uuid by instance uuid
1091 for vnf
in scenarioDict
['vnfs']:
1092 INSERT_
={'instance_scenario_id': instance_uuid
, 'vnf_id': vnf
['vnf_id'] }
1093 INSERT_
['datacenter_id'] = vnf
.get('datacenter_id', datacenter_id
)
1094 INSERT_
['datacenter_tenant_id'] = vnf
.get('datacenter_tenant_id', datacenter_tenant_id
)
1096 INSERT_
['sce_vnf_id'] = vnf
['uuid']
1097 created_time
+= 0.00001
1098 r
,instance_vnf_uuid
= self
._new
_row
_internal
('instance_vnfs', INSERT_
, tenant_id
, True, instance_uuid
, True,created_time
)
1100 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_vnfs: ' + instance_vnf_uuid
1101 return r
, instance_vnf_uuid
1102 vnf
['uuid'] = instance_vnf_uuid
#overwrite scnario uuid by instance uuid
1104 #instance_nets #nets intraVNF
1105 for net
in vnf
['nets']:
1106 INSERT_
={'vim_net_id': net
['vim_id'], 'external': 'false', 'instance_scenario_id':instance_uuid
} #, 'type': net['type']
1107 INSERT_
['datacenter_id'] = net
.get('datacenter_id', datacenter_id
)
1108 INSERT_
['datacenter_tenant_id'] = net
.get('datacenter_tenant_id', datacenter_tenant_id
)
1110 INSERT_
['net_id'] = net
['uuid']
1111 created_time
+= 0.00001
1112 r
,instance_net_uuid
= self
._new
_row
_internal
('instance_nets', INSERT_
, tenant_id
, True, instance_uuid
, True,created_time
)
1114 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_nets: ' + instance_net_uuid
1115 return r
, instance_net_uuid
1116 net_scene2instance
[ net
['uuid'] ] = instance_net_uuid
1117 net
['uuid'] = instance_net_uuid
#overwrite scnario uuid by instance uuid
1120 for vm
in vnf
['vms']:
1121 INSERT_
={'instance_vnf_id': instance_vnf_uuid
, 'vm_id': vm
['uuid'], 'vim_vm_id': vm
['vim_id'] }
1122 created_time
+= 0.00001
1123 r
,instance_vm_uuid
= self
._new
_row
_internal
('instance_vms', INSERT_
, tenant_id
, True, instance_uuid
, True, created_time
)
1125 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_vms: ' + instance_vm_uuid
1126 return r
, instance_vm_uuid
1127 vm
['uuid'] = instance_vm_uuid
#overwrite scnario uuid by instance uuid
1129 #instance_interfaces
1130 for interface
in vm
['interfaces']:
1131 net_id
= interface
.get('net_id', None)
1133 #check if is connected to a inter VNFs net
1134 for iface
in vnf
['interfaces']:
1135 if iface
['interface_id'] == interface
['uuid']:
1136 net_id
= iface
.get('sce_net_id', None)
1140 interface_type
='external' if interface
['external_name'] is not None else 'internal'
1141 INSERT_
={'instance_vm_id': instance_vm_uuid
, 'instance_net_id': net_scene2instance
[net_id
],
1142 'interface_id': interface
['uuid'], 'vim_interface_id': interface
.get('vim_id'), 'type': interface_type
}
1143 #created_time += 0.00001
1144 r
,interface_uuid
= self
._new
_row
_internal
('instance_interfaces', INSERT_
, tenant_id
, True, instance_uuid
, True) #, created_time)
1146 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_interfaces: ' + interface_uuid
1147 return r
, interface_uuid
1148 interface
['uuid'] = interface_uuid
#overwrite scnario uuid by instance uuid
1152 return 1, instance_uuid
1154 except (mdb
.Error
, AttributeError), e
:
1155 print "new_instance_scenario_as_a_whole DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1156 r
,c
= self
.format_error(e
)
1157 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1159 def get_instance_scenario(self
, instance_id
, tenant_id
=None, verbose
=False):
1160 '''Obtain the instance information, filtering by one or several of the tenant, uuid or name
1161 instance_id is the uuid or the name if it is not a valid uuid format
1162 Only one instance must mutch the filtering or an error is returned
1164 for retry_
in range(0,2):
1167 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1170 if tenant_id
is not None: where_list
.append( "inst.tenant_id='" + tenant_id
+"'" )
1171 if utils
.check_valid_uuid(instance_id
):
1172 where_list
.append( "inst.uuid='" + instance_id
+"'" )
1174 where_list
.append( "inst.name='" + instance_id
+"'" )
1175 where_text
= " AND ".join(where_list
)
1176 command
= "SELECT inst.uuid as uuid,inst.name as name,inst.scenario_id as scenario_id, datacenter_id" +\
1177 " ,datacenter_tenant_id, s.name as scenario_name,inst.tenant_id as tenant_id" + \
1178 " ,inst.description as description,inst.created_at as created_at" +\
1179 " FROM instance_scenarios as inst join scenarios as s on inst.scenario_id=s.uuid"+\
1180 " WHERE " + where_text
1181 self
.cur
.execute(command
)
1182 rows
= self
.cur
.fetchall()
1183 if self
.cur
.rowcount
==0:
1184 return -HTTP_Bad_Request
, "No instance found with this criteria " + where_text
1185 elif self
.cur
.rowcount
>1:
1186 return -HTTP_Bad_Request
, "More than one instance found with this criteria " + where_text
1187 instance_dict
= rows
[0]
1190 cmd
= "SELECT iv.uuid as uuid,sv.vnf_id as vnf_id,sv.name as vnf_name, sce_vnf_id, datacenter_id, datacenter_tenant_id"\
1191 " FROM instance_vnfs as iv join sce_vnfs as sv on iv.sce_vnf_id=sv.uuid" \
1192 " WHERE iv.instance_scenario_id='%s'" \
1193 " ORDER BY iv.created_at " % instance_dict
['uuid']
1194 self
.cur
.execute(cmd
)
1195 instance_dict
['vnfs'] = self
.cur
.fetchall()
1196 for vnf
in instance_dict
['vnfs']:
1197 vnf_manage_iface_list
=[]
1199 cmd
= "SELECT iv.uuid as uuid, vim_vm_id, status, error_msg, vim_info, iv.created_at as created_at, name "\
1200 " FROM instance_vms as iv join vms on iv.vm_id=vms.uuid "\
1201 " WHERE instance_vnf_id='%s' ORDER BY iv.created_at" % vnf
['uuid']
1202 self
.cur
.execute(cmd
)
1203 vnf
['vms'] = self
.cur
.fetchall()
1204 for vm
in vnf
['vms']:
1205 vm_manage_iface_list
=[]
1206 #instance_interfaces
1207 cmd
= "SELECT vim_interface_id, instance_net_id, internal_name,external_name, mac_address, ip_address, vim_info, i.type as type "\
1208 " FROM instance_interfaces as ii join interfaces as i on ii.interface_id=i.uuid "\
1209 " WHERE instance_vm_id='%s' ORDER BY created_at" % vm
['uuid']
1210 self
.cur
.execute(cmd
)
1211 vm
['interfaces'] = self
.cur
.fetchall()
1212 for iface
in vm
['interfaces']:
1213 if iface
["type"] == "mgmt" and iface
["ip_address"]:
1214 vnf_manage_iface_list
.append(iface
["ip_address"])
1215 vm_manage_iface_list
.append(iface
["ip_address"])
1218 if vm_manage_iface_list
: vm
["ip_address"] = ",".join(vm_manage_iface_list
)
1219 if vnf_manage_iface_list
: vnf
["ip_address"] = ",".join(vnf_manage_iface_list
)
1222 #select_text = "instance_nets.uuid as uuid,sce_nets.name as net_name,instance_nets.vim_net_id as net_id,instance_nets.status as status,instance_nets.external as external"
1223 #from_text = "instance_nets join instance_scenarios on instance_nets.instance_scenario_id=instance_scenarios.uuid " + \
1224 # "join sce_nets on instance_scenarios.scenario_id=sce_nets.scenario_id"
1225 #where_text = "instance_nets.instance_scenario_id='"+ instance_dict['uuid'] + "'"
1226 cmd
= "SELECT uuid,vim_net_id,status,error_msg,vim_info,external, sce_net_id, net_id as vnf_net_id, datacenter_id, datacenter_tenant_id"\
1227 " FROM instance_nets" \
1228 " WHERE instance_scenario_id='%s' ORDER BY created_at" % instance_dict
['uuid']
1229 self
.cur
.execute(cmd
)
1230 instance_dict
['nets'] = self
.cur
.fetchall()
1232 utils
.convert_datetime2str(instance_dict
)
1233 utils
.convert_str2boolean(instance_dict
, ('public','shared','external') )
1234 return 1, instance_dict
1235 except (mdb
.Error
, AttributeError), e
:
1236 print "nfvo_db.get_instance_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1237 r
,c
= self
.format_error(e
)
1238 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1240 def delete_instance_scenario(self
, instance_id
, tenant_id
=None):
1241 '''Deletes a instance_Scenario, filtering by one or serveral of the tenant, uuid or name
1242 instance_id is the uuid or the name if it is not a valid uuid format
1243 Only one instance_scenario must mutch the filtering or an error is returned
1245 for retry_
in range(0,2):
1248 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1252 if tenant_id
is not None: where_list
.append( "tenant_id='" + tenant_id
+"'" )
1253 if utils
.check_valid_uuid(instance_id
):
1254 where_list
.append( "uuid='" + instance_id
+"'" )
1256 where_list
.append( "name='" + instance_id
+"'" )
1257 where_text
= " AND ".join(where_list
)
1258 self
.cur
.execute("SELECT * FROM instance_scenarios WHERE "+ where_text
)
1259 rows
= self
.cur
.fetchall()
1260 if self
.cur
.rowcount
==0:
1261 return -HTTP_Bad_Request
, "No instance scenario found with this criteria " + where_text
1262 elif self
.cur
.rowcount
>1:
1263 return -HTTP_Bad_Request
, "More than one instance scenario found with this criteria " + where_text
1264 instance_uuid
= rows
[0]["uuid"]
1265 instance_name
= rows
[0]["name"]
1268 self
.cur
.execute("DELETE FROM instance_scenarios WHERE uuid='" + instance_uuid
+ "'")
1270 return 1, instance_uuid
+ " " + instance_name
1271 except (mdb
.Error
, AttributeError), e
:
1272 print "nfvo_db.delete_instance_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1273 r
,c
= self
.format_error(e
, "delete", "No dependences can avoid deleting!!!!")
1274 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1276 def new_instance_scenario(self
, instance_scenario_dict
, tenant_id
):
1277 #return self.new_row('vnfs', vnf_dict, None, tenant_id, True, True)
1278 return self
._new
_row
_internal
('instance_scenarios', instance_scenario_dict
, tenant_id
, add_uuid
=True, root_uuid
=None, log
=True)
1280 def update_instance_scenario(self
, instance_scenario_dict
):
1284 def new_instance_vnf(self
, instance_vnf_dict
, tenant_id
, instance_scenario_id
= None):
1285 #return self.new_row('vms', vm_dict, tenant_id, True, True)
1286 return self
._new
_row
_internal
('instance_vnfs', instance_vnf_dict
, tenant_id
, add_uuid
=True, root_uuid
=instance_scenario_id
, log
=True)
1288 def update_instance_vnf(self
, instance_vnf_dict
):
1292 def delete_instance_vnf(self
, instance_vnf_id
):
1296 def new_instance_vm(self
, instance_vm_dict
, tenant_id
, instance_scenario_id
= None):
1297 #return self.new_row('vms', vm_dict, tenant_id, True, True)
1298 return self
._new
_row
_internal
('instance_vms', instance_vm_dict
, tenant_id
, add_uuid
=True, root_uuid
=instance_scenario_id
, log
=True)
1300 def update_instance_vm(self
, instance_vm_dict
):
1304 def delete_instance_vm(self
, instance_vm_id
):
1308 def new_instance_net(self
, instance_net_dict
, tenant_id
, instance_scenario_id
= None):
1309 return self
._new
_row
_internal
('instance_nets', instance_net_dict
, tenant_id
, add_uuid
=True, root_uuid
=instance_scenario_id
, log
=True)
1311 def update_instance_net(self
, instance_net_dict
):
1315 def delete_instance_net(self
, instance_net_id
):
1319 def new_instance_interface(self
, instance_interface_dict
, tenant_id
, instance_scenario_id
= None):
1320 return self
._new
_row
_internal
('instance_interfaces', instance_interface_dict
, tenant_id
, add_uuid
=True, root_uuid
=instance_scenario_id
, log
=True)
1322 def update_instance_interface(self
, instance_interface_dict
):
1326 def delete_instance_interface(self
, instance_interface_dict
):
1330 def update_datacenter_nets(self
, datacenter_id
, new_net_list
=[]):
1331 ''' Removes the old and adds the new net list at datacenter list for one datacenter.
1333 datacenter_id: uuid of the datacenter to act upon
1334 table: table where to insert
1335 new_net_list: the new values to be inserted. If empty it only deletes the existing nets
1336 Return: (Inserted items, Deleted items) if OK, (-Error, text) if error
1338 for retry_
in range(0,2):
1339 created_time
= time
.time()
1342 self
.cur
= self
.con
.cursor()
1343 cmd
="DELETE FROM datacenter_nets WHERE datacenter_id='%s'" % datacenter_id
1345 self
.cur
.execute(cmd
)
1346 deleted
= self
.cur
.rowcount
1347 for new_net
in new_net_list
:
1348 created_time
+= 0.00001
1349 self
._new
_row
_internal
('datacenter_nets', new_net
, tenant_id
=None, add_uuid
=True, created_time
=created_time
)
1350 return len (new_net_list
), deleted
1351 except (mdb
.Error
, AttributeError), e
:
1352 print "nfvo_db.update_datacenter_nets DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1353 r
,c
= self
.format_error(e
)
1354 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c