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$"
32 from utils
import auxiliary_functions
as af
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 af
.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 af
.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 af
.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'],'description': scenario_dict
['description']}
735 r
,scenario_uuid
= self
._new
_row
_internal
('scenarios', INSERT_
, tenant_id
, True, None, True,created_time
)
737 print 'nfvo_db.new_scenario Error inserting at table scenarios: ' + scenario_uuid
738 return r
,scenario_uuid
740 for net
in scenario_dict
['nets'].values():
741 net_dict
={'scenario_id': scenario_uuid
}
742 net_dict
["name"] = net
["name"]
743 net_dict
["type"] = net
["type"]
744 net_dict
["description"] = net
.get("description")
745 net_dict
["external"] = net
.get("external", False)
747 #net["graph"]=yaml.safe_dump(net["graph"],default_flow_style=True,width=256)
748 #TODO, must be json because of the GUI, change to yaml
749 net_dict
["graph"]=json
.dumps(net
["graph"])
750 created_time
+= 0.00001
751 r
,net_uuid
= self
._new
_row
_internal
('sce_nets', net_dict
, tenant_id
, True, None, True, created_time
)
753 print 'nfvo_db.new_scenario Error inserting at table sce_vnfs: ' + net_uuid
757 for k
,vnf
in scenario_dict
['vnfs'].items():
758 INSERT_
={'scenario_id': scenario_uuid
,
760 'vnf_id': vnf
['uuid'],
761 #'description': scenario_dict['name']
762 'description': vnf
['description']
765 #INSERT_["graph"]=yaml.safe_dump(vnf["graph"],default_flow_style=True,width=256)
766 #TODO, must be json because of the GUI, change to yaml
767 INSERT_
["graph"]=json
.dumps(vnf
["graph"])
768 created_time
+= 0.00001
769 r
,scn_vnf_uuid
= self
._new
_row
_internal
('sce_vnfs', INSERT_
, tenant_id
, True, scenario_uuid
, True, created_time
)
771 print 'nfvo_db.new_scenario Error inserting at table sce_vnfs: ' + scn_vnf_uuid
772 return r
, scn_vnf_uuid
773 vnf
['scn_vnf_uuid']=scn_vnf_uuid
775 for iface
in vnf
['ifaces'].values():
777 if 'net_key' not in iface
:
779 iface
['net_id'] = scenario_dict
['nets'][ iface
['net_key'] ]['uuid']
780 INSERT_
={'sce_vnf_id': scn_vnf_uuid
,
781 'sce_net_id': iface
['net_id'],
782 'interface_id': iface
[ 'uuid' ]
784 created_time
+= 0.00001
785 r
,iface_uuid
= self
._new
_row
_internal
('sce_interfaces', INSERT_
, tenant_id
, True, scenario_uuid
, True, created_time
)
787 print 'nfvo_db.new_scenario Error inserting at table sce_vnfs: ' + iface_uuid
790 return 1, scenario_uuid
792 except (mdb
.Error
, AttributeError), e
:
793 print "nfvo_db.new_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
794 r
,c
= self
.format_error(e
)
795 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
797 def edit_scenario(self
, scenario_dict
):
798 for retry_
in range(0,2):
799 modified_time
= time
.time()
802 self
.cur
= self
.con
.cursor()
803 #check that scenario exist
804 tenant_id
= scenario_dict
.get('tenant_id')
805 scenario_uuid
= scenario_dict
['uuid']
807 where_text
= "uuid='%s'" % scenario_uuid
808 if not tenant_id
and tenant_id
!= "any":
809 where_text
+= " AND (tenant_id='%s' OR public='True')" % (tenant_id
)
810 self
.cur
.execute("SELECT * FROM scenarios WHERE "+ where_text
)
812 if self
.cur
.rowcount
==0:
813 return -HTTP_Bad_Request
, "No scenario found with this criteria " + where_text
814 elif self
.cur
.rowcount
>1:
815 return -HTTP_Bad_Request
, "More than one scenario found with this criteria " + where_text
819 topology
= scenario_dict
.pop("topology", None)
820 if topology
!= None and "nodes" in topology
:
821 nodes
= topology
.get("nodes",{})
823 if "name" in scenario_dict
: UPDATE_
["name"] = scenario_dict
["name"]
824 if "description" in scenario_dict
: UPDATE_
["description"] = scenario_dict
["description"]
826 WHERE_
={'tenant_id': tenant_id
, 'uuid': scenario_uuid
}
827 r
,c
= self
.__update
_rows
('scenarios', UPDATE_
, WHERE_
, modified_time
=modified_time
)
829 print 'nfvo_db.edit_scenario Error ' + c
+ ' updating table scenarios: ' + scenario_uuid
830 return r
,scenario_uuid
832 for node_id
, node
in nodes
.items():
834 #node["graph"] = yaml.safe_dump(node["graph"],default_flow_style=True,width=256)
835 #TODO, must be json because of the GUI, change to yaml
836 node
["graph"] = json
.dumps(node
["graph"])
837 WHERE_
={'scenario_id': scenario_uuid
, 'uuid': node_id
}
838 r
,c
= self
.__update
_rows
('sce_nets', node
, WHERE_
)
840 r
,c
= self
.__update
_rows
('sce_vnfs', node
, WHERE_
, modified_time
=modified_time
)
842 print 'nfvo_db.edit_scenario Error updating table sce_nets,sce_vnfs: ' + scenario_uuid
843 return r
, scenario_uuid
844 return 1, scenario_uuid
846 except (mdb
.Error
, AttributeError), e
:
847 print "nfvo_db.new_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
848 r
,c
= self
.format_error(e
)
849 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
851 # def get_instance_scenario(self, instance_scenario_id, tenant_id=None):
852 # '''Obtain the scenario instance information, filtering by one or serveral of the tenant, uuid or name
853 # instance_scenario_id is the uuid or the name if it is not a valid uuid format
854 # Only one scenario isntance must mutch the filtering or an error is returned
856 # print "1******************************************************************"
859 # self.cur = self.con.cursor(mdb.cursors.DictCursor)
862 # if tenant_id is not None: where_list.append( "tenant_id='" + tenant_id +"'" )
863 # if af.check_valid_uuid(instance_scenario_id):
864 # where_list.append( "uuid='" + instance_scenario_id +"'" )
866 # where_list.append( "name='" + instance_scenario_id +"'" )
867 # where_text = " AND ".join(where_list)
868 # self.cur.execute("SELECT * FROM instance_scenarios WHERE "+ where_text)
869 # rows = self.cur.fetchall()
870 # if self.cur.rowcount==0:
871 # return -HTTP_Bad_Request, "No scenario instance found with this criteria " + where_text
872 # elif self.cur.rowcount>1:
873 # return -HTTP_Bad_Request, "More than one scenario instance found with this criteria " + where_text
874 # instance_scenario_dict = rows[0]
877 # self.cur.execute("SELECT uuid,vnf_id FROM instance_vnfs WHERE instance_scenario_id='"+ instance_scenario_dict['uuid'] + "'")
878 # instance_scenario_dict['instance_vnfs'] = self.cur.fetchall()
879 # for vnf in instance_scenario_dict['instance_vnfs']:
881 # self.cur.execute("SELECT uuid, vim_vm_id "+
882 # "FROM instance_vms "+
883 # "WHERE instance_vnf_id='" + vnf['uuid'] +"'"
885 # vnf['instance_vms'] = self.cur.fetchall()
887 # self.cur.execute("SELECT uuid, vim_net_id FROM instance_nets WHERE instance_scenario_id='"+ instance_scenario_dict['uuid'] + "'")
888 # instance_scenario_dict['instance_nets'] = self.cur.fetchall()
890 # #instance_interfaces
891 # 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'] + "'")
892 # instance_scenario_dict['instance_interfaces'] = self.cur.fetchall()
894 # af.convert_datetime2str(instance_scenario_dict)
895 # af.convert_str2boolean(instance_scenario_dict, ('public','shared','external') )
896 # print "2******************************************************************"
897 # return 1, instance_scenario_dict
898 # except (mdb.Error, AttributeError), e:
899 # print "nfvo_db.get_instance_scenario DB Exception %d: %s" % (e.args[0], e.args[1])
900 # return self.format_error(e)
902 def get_scenario(self
, scenario_id
, tenant_id
=None, datacenter_id
=None):
903 '''Obtain the scenario information, filtering by one or serveral of the tenant, uuid or name
904 scenario_id is the uuid or the name if it is not a valid uuid format
905 if datacenter_id is provided, it supply aditional vim_id fields with the matching vim uuid
906 Only one scenario must mutch the filtering or an error is returned
908 for retry_
in range(0,2):
911 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
913 if af
.check_valid_uuid(scenario_id
):
914 where_text
= "uuid='%s'" % scenario_id
916 where_text
= "name='%s'" % scenario_id
917 if not tenant_id
and tenant_id
!= "any":
918 where_text
+= " AND (tenant_id='%s' OR public='True')" % (tenant_id
)
919 cmd
= "SELECT * FROM scenarios WHERE "+ where_text
921 self
.cur
.execute(cmd
)
922 rows
= self
.cur
.fetchall()
923 if self
.cur
.rowcount
==0:
924 return -HTTP_Bad_Request
, "No scenario found with this criteria " + where_text
925 elif self
.cur
.rowcount
>1:
926 return -HTTP_Bad_Request
, "More than one scenario found with this criteria " + where_text
927 scenario_dict
= rows
[0]
930 cmd
= "SELECT uuid,name,vnf_id,description FROM sce_vnfs WHERE scenario_id='%s' ORDER BY created_at" % scenario_dict
['uuid']
931 self
.cur
.execute(cmd
)
932 scenario_dict
['vnfs'] = self
.cur
.fetchall()
933 for vnf
in scenario_dict
['vnfs']:
935 cmd
= "SELECT uuid,sce_net_id,interface_id FROM sce_interfaces WHERE sce_vnf_id='%s' ORDER BY created_at" %vnf
['uuid']
936 self
.cur
.execute(cmd
)
937 vnf
['interfaces'] = self
.cur
.fetchall()
939 cmd
= "SELECT vms.uuid as uuid, flavor_id, image_id, vms.name as name, vms.description as description " \
940 " FROM vnfs join vms on vnfs.uuid=vms.vnf_id " \
941 " WHERE vnfs.uuid='" + vnf
['vnf_id'] +"'" \
942 " ORDER BY vms.created_at"
943 self
.cur
.execute(cmd
)
944 vnf
['vms'] = self
.cur
.fetchall()
945 for vm
in vnf
['vms']:
946 if datacenter_id
!=None:
947 self
.cur
.execute("SELECT vim_id FROM datacenters_images WHERE image_id='%s' AND datacenter_id='%s'" %(vm
['image_id'],datacenter_id
))
948 if self
.cur
.rowcount
==1:
949 vim_image_dict
= self
.cur
.fetchone()
950 vm
['vim_image_id']=vim_image_dict
['vim_id']
951 self
.cur
.execute("SELECT vim_id FROM datacenters_flavors WHERE flavor_id='%s' AND datacenter_id='%s'" %(vm
['flavor_id'],datacenter_id
))
952 if self
.cur
.rowcount
==1:
953 vim_flavor_dict
= self
.cur
.fetchone()
954 vm
['vim_flavor_id']=vim_flavor_dict
['vim_id']
957 cmd
= "SELECT uuid,internal_name,external_name,net_id,type,vpci,mac,bw,model" \
959 " WHERE vm_id='%s'" \
960 " ORDER BY created_at" % vm
['uuid']
961 self
.cur
.execute(cmd
)
962 vm
['interfaces'] = self
.cur
.fetchall()
963 #nets every net of a vms
964 self
.cur
.execute("SELECT uuid,name,type,description FROM nets WHERE vnf_id='" + vnf
['vnf_id'] +"'" )
965 vnf
['nets'] = self
.cur
.fetchall()
967 cmd
= "SELECT uuid,name,type,external,description" \
968 " FROM sce_nets WHERE scenario_id='%s'" \
969 " ORDER BY created_at " % scenario_dict
['uuid']
970 self
.cur
.execute(cmd
)
971 scenario_dict
['nets'] = self
.cur
.fetchall()
973 for net
in scenario_dict
['nets']:
974 if str(net
['external']) == 'false':
976 WHERE_
=" WHERE name='%s'" % net
['name']
977 if datacenter_id
!=None:
978 WHERE_
+= " AND datacenter_id='%s'" % datacenter_id
979 self
.cur
.execute("SELECT vim_net_id FROM datacenter_nets" + WHERE_
)
980 d_net
= self
.cur
.fetchone()
981 if d_net
==None or datacenter_id
==None:
982 #print "nfvo_db.get_scenario() WARNING external net %s not found" % net['name']
985 net
['vim_id']=d_net
['vim_net_id']
987 af
.convert_datetime2str(scenario_dict
)
988 af
.convert_str2boolean(scenario_dict
, ('public','shared','external') )
989 return 1, scenario_dict
990 except (mdb
.Error
, AttributeError), e
:
991 print "nfvo_db.get_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
992 r
,c
= self
.format_error(e
)
993 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
995 def get_uuid_from_name(self
, table
, name
):
996 '''Searchs in table the name and returns the uuid
998 for retry_
in range(0,2):
1001 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1002 where_text
= "name='" + name
+"'"
1003 self
.cur
.execute("SELECT * FROM " + table
+ " WHERE "+ where_text
)
1004 rows
= self
.cur
.fetchall()
1005 if self
.cur
.rowcount
==0:
1006 return 0, "Name %s not found in table %s" %(name
, table
)
1007 elif self
.cur
.rowcount
>1:
1008 return self
.cur
.rowcount
, "More than one VNF with name %s found in table %s" %(name
, table
)
1009 return self
.cur
.rowcount
, rows
[0]["uuid"]
1010 except (mdb
.Error
, AttributeError), e
:
1011 print "nfvo_db.get_uuid_from_name DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1012 r
,c
= self
.format_error(e
)
1013 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1015 def delete_scenario(self
, scenario_id
, tenant_id
=None):
1016 '''Deletes a scenario, filtering by one or several of the tenant, uuid or name
1017 scenario_id is the uuid or the name if it is not a valid uuid format
1018 Only one scenario must mutch the filtering or an error is returned
1020 for retry_
in range(0,2):
1023 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1026 if af
.check_valid_uuid(scenario_id
):
1027 where_text
= "uuid='%s'" % scenario_id
1029 where_text
= "name='%s'" % scenario_id
1030 if not tenant_id
and tenant_id
!= "any":
1031 where_text
+= " AND (tenant_id='%s' OR public='True')" % tenant_id
1032 self
.cur
.execute("SELECT * FROM scenarios WHERE "+ where_text
)
1033 rows
= self
.cur
.fetchall()
1034 if self
.cur
.rowcount
==0:
1035 return -HTTP_Bad_Request
, "No scenario found with this criteria " + where_text
1036 elif self
.cur
.rowcount
>1:
1037 return -HTTP_Bad_Request
, "More than one scenario found with this criteria " + where_text
1038 scenario_uuid
= rows
[0]["uuid"]
1039 scenario_name
= rows
[0]["name"]
1042 self
.cur
.execute("DELETE FROM scenarios WHERE uuid='" + scenario_uuid
+ "'")
1044 return 1, scenario_uuid
+ " " + scenario_name
1045 except (mdb
.Error
, AttributeError), e
:
1046 print "nfvo_db.delete_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1047 r
,c
= self
.format_error(e
, "delete", "instances running")
1048 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1050 def new_instance_scenario_as_a_whole(self
,tenant_id
,instance_scenario_name
,instance_scenario_description
,scenarioDict
):
1051 print "Adding new instance scenario to the NFVO database"
1052 for retry_
in range(0,2):
1053 created_time
= time
.time()
1056 self
.cur
= self
.con
.cursor()
1058 datacenter_tenant_id
= scenarioDict
['datacenter_tenant_id']
1059 datacenter_id
= scenarioDict
['datacenter_id']
1060 INSERT_
={'tenant_id': tenant_id
,
1061 'datacenter_tenant_id': datacenter_tenant_id
,
1062 'name': instance_scenario_name
,
1063 'description': instance_scenario_description
,
1064 'scenario_id' : scenarioDict
['uuid'],
1065 'datacenter_id': datacenter_id
1067 r
,instance_uuid
= self
._new
_row
_internal
('instance_scenarios', INSERT_
, tenant_id
, True, None, True, created_time
)
1069 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_scenarios: ' + instance_uuid
1070 return r
, instance_uuid
1072 net_scene2instance
={}
1073 #instance_nets #nets interVNF
1074 for net
in scenarioDict
['nets']:
1075 INSERT_
={'vim_net_id': net
['vim_id'], 'external': net
['external'], 'instance_scenario_id':instance_uuid
} #, 'type': net['type']
1076 INSERT_
['datacenter_id'] = net
.get('datacenter_id', datacenter_id
)
1077 INSERT_
['datacenter_tenant_id'] = net
.get('datacenter_tenant_id', datacenter_tenant_id
)
1079 INSERT_
['sce_net_id'] = net
['uuid']
1080 created_time
+= 0.00001
1081 r
,instance_net_uuid
= self
._new
_row
_internal
('instance_nets', INSERT_
, tenant_id
, True, instance_uuid
, True, created_time
)
1083 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_nets: ' + instance_net_uuid
1084 return r
, instance_net_uuid
1085 net_scene2instance
[ net
['uuid'] ] = instance_net_uuid
1086 net
['uuid'] = instance_net_uuid
#overwrite scnario uuid by instance uuid
1089 for vnf
in scenarioDict
['vnfs']:
1090 INSERT_
={'instance_scenario_id': instance_uuid
, 'vnf_id': vnf
['vnf_id'] }
1091 INSERT_
['datacenter_id'] = vnf
.get('datacenter_id', datacenter_id
)
1092 INSERT_
['datacenter_tenant_id'] = vnf
.get('datacenter_tenant_id', datacenter_tenant_id
)
1094 INSERT_
['sce_vnf_id'] = vnf
['uuid']
1095 created_time
+= 0.00001
1096 r
,instance_vnf_uuid
= self
._new
_row
_internal
('instance_vnfs', INSERT_
, tenant_id
, True, instance_uuid
, True,created_time
)
1098 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_vnfs: ' + instance_vnf_uuid
1099 return r
, instance_vnf_uuid
1100 vnf
['uuid'] = instance_vnf_uuid
#overwrite scnario uuid by instance uuid
1102 #instance_nets #nets intraVNF
1103 for net
in vnf
['nets']:
1104 INSERT_
={'vim_net_id': net
['vim_id'], 'external': 'false', 'instance_scenario_id':instance_uuid
} #, 'type': net['type']
1105 INSERT_
['datacenter_id'] = net
.get('datacenter_id', datacenter_id
)
1106 INSERT_
['datacenter_tenant_id'] = net
.get('datacenter_tenant_id', datacenter_tenant_id
)
1108 INSERT_
['net_id'] = net
['uuid']
1109 created_time
+= 0.00001
1110 r
,instance_net_uuid
= self
._new
_row
_internal
('instance_nets', INSERT_
, tenant_id
, True, instance_uuid
, True,created_time
)
1112 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_nets: ' + instance_net_uuid
1113 return r
, instance_net_uuid
1114 net_scene2instance
[ net
['uuid'] ] = instance_net_uuid
1115 net
['uuid'] = instance_net_uuid
#overwrite scnario uuid by instance uuid
1118 for vm
in vnf
['vms']:
1119 INSERT_
={'instance_vnf_id': instance_vnf_uuid
, 'vm_id': vm
['uuid'], 'vim_vm_id': vm
['vim_id'] }
1120 created_time
+= 0.00001
1121 r
,instance_vm_uuid
= self
._new
_row
_internal
('instance_vms', INSERT_
, tenant_id
, True, instance_uuid
, True, created_time
)
1123 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_vms: ' + instance_vm_uuid
1124 return r
, instance_vm_uuid
1125 vm
['uuid'] = instance_vm_uuid
#overwrite scnario uuid by instance uuid
1127 #instance_interfaces
1128 for interface
in vm
['interfaces']:
1129 net_id
= interface
.get('net_id', None)
1131 #check if is connected to a inter VNFs net
1132 for iface
in vnf
['interfaces']:
1133 if iface
['interface_id'] == interface
['uuid']:
1134 net_id
= iface
.get('sce_net_id', None)
1138 interface_type
='external' if interface
['external_name'] is not None else 'internal'
1139 INSERT_
={'instance_vm_id': instance_vm_uuid
, 'instance_net_id': net_scene2instance
[net_id
],
1140 'interface_id': interface
['uuid'], 'vim_interface_id': interface
.get('vim_id'), 'type': interface_type
}
1141 #created_time += 0.00001
1142 r
,interface_uuid
= self
._new
_row
_internal
('instance_interfaces', INSERT_
, tenant_id
, True, instance_uuid
, True) #, created_time)
1144 print 'nfvo_db.new_instance_scenario_as_a_whole() Error inserting at table instance_interfaces: ' + interface_uuid
1145 return r
, interface_uuid
1146 interface
['uuid'] = interface_uuid
#overwrite scnario uuid by instance uuid
1150 return 1, instance_uuid
1152 except (mdb
.Error
, AttributeError), e
:
1153 print "new_instance_scenario_as_a_whole DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1154 r
,c
= self
.format_error(e
)
1155 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1157 def get_instance_scenario(self
, instance_id
, tenant_id
=None, verbose
=False):
1158 '''Obtain the instance information, filtering by one or several of the tenant, uuid or name
1159 instance_id is the uuid or the name if it is not a valid uuid format
1160 Only one instance must mutch the filtering or an error is returned
1162 for retry_
in range(0,2):
1165 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1168 if tenant_id
is not None: where_list
.append( "inst.tenant_id='" + tenant_id
+"'" )
1169 if af
.check_valid_uuid(instance_id
):
1170 where_list
.append( "inst.uuid='" + instance_id
+"'" )
1172 where_list
.append( "inst.name='" + instance_id
+"'" )
1173 where_text
= " AND ".join(where_list
)
1174 command
= "SELECT inst.uuid as uuid,inst.name as name,inst.scenario_id as scenario_id, datacenter_id" +\
1175 " ,datacenter_tenant_id, s.name as scenario_name,inst.tenant_id as tenant_id" + \
1176 " ,inst.description as description,inst.created_at as created_at" +\
1177 " FROM instance_scenarios as inst join scenarios as s on inst.scenario_id=s.uuid"+\
1178 " WHERE " + where_text
1179 self
.cur
.execute(command
)
1180 rows
= self
.cur
.fetchall()
1181 if self
.cur
.rowcount
==0:
1182 return -HTTP_Bad_Request
, "No instance found with this criteria " + where_text
1183 elif self
.cur
.rowcount
>1:
1184 return -HTTP_Bad_Request
, "More than one instance found with this criteria " + where_text
1185 instance_dict
= rows
[0]
1188 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"\
1189 " FROM instance_vnfs as iv join sce_vnfs as sv on iv.sce_vnf_id=sv.uuid" \
1190 " WHERE iv.instance_scenario_id='%s'" \
1191 " ORDER BY iv.created_at " % instance_dict
['uuid']
1192 self
.cur
.execute(cmd
)
1193 instance_dict
['vnfs'] = self
.cur
.fetchall()
1194 for vnf
in instance_dict
['vnfs']:
1195 vnf_manage_iface_list
=[]
1197 cmd
= "SELECT iv.uuid as uuid, vim_vm_id, status, error_msg, vim_info, iv.created_at as created_at, name "\
1198 " FROM instance_vms as iv join vms on iv.vm_id=vms.uuid "\
1199 " WHERE instance_vnf_id='%s' ORDER BY iv.created_at" % vnf
['uuid']
1200 self
.cur
.execute(cmd
)
1201 vnf
['vms'] = self
.cur
.fetchall()
1202 for vm
in vnf
['vms']:
1203 vm_manage_iface_list
=[]
1204 #instance_interfaces
1205 cmd
= "SELECT vim_interface_id, instance_net_id, internal_name,external_name, mac_address, ip_address, vim_info, i.type as type "\
1206 " FROM instance_interfaces as ii join interfaces as i on ii.interface_id=i.uuid "\
1207 " WHERE instance_vm_id='%s' ORDER BY created_at" % vm
['uuid']
1208 self
.cur
.execute(cmd
)
1209 vm
['interfaces'] = self
.cur
.fetchall()
1210 for iface
in vm
['interfaces']:
1211 if iface
["type"] == "mgmt" and iface
["ip_address"]:
1212 vnf_manage_iface_list
.append(iface
["ip_address"])
1213 vm_manage_iface_list
.append(iface
["ip_address"])
1216 if vm_manage_iface_list
: vm
["ip_address"] = ",".join(vm_manage_iface_list
)
1217 if vnf_manage_iface_list
: vnf
["ip_address"] = ",".join(vnf_manage_iface_list
)
1220 #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"
1221 #from_text = "instance_nets join instance_scenarios on instance_nets.instance_scenario_id=instance_scenarios.uuid " + \
1222 # "join sce_nets on instance_scenarios.scenario_id=sce_nets.scenario_id"
1223 #where_text = "instance_nets.instance_scenario_id='"+ instance_dict['uuid'] + "'"
1224 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"\
1225 " FROM instance_nets" \
1226 " WHERE instance_scenario_id='%s' ORDER BY created_at" % instance_dict
['uuid']
1227 self
.cur
.execute(cmd
)
1228 instance_dict
['nets'] = self
.cur
.fetchall()
1230 af
.convert_datetime2str(instance_dict
)
1231 af
.convert_str2boolean(instance_dict
, ('public','shared','external') )
1232 return 1, instance_dict
1233 except (mdb
.Error
, AttributeError), e
:
1234 print "nfvo_db.get_instance_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1235 r
,c
= self
.format_error(e
)
1236 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1238 def delete_instance_scenario(self
, instance_id
, tenant_id
=None):
1239 '''Deletes a instance_Scenario, filtering by one or serveral of the tenant, uuid or name
1240 instance_id is the uuid or the name if it is not a valid uuid format
1241 Only one instance_scenario must mutch the filtering or an error is returned
1243 for retry_
in range(0,2):
1246 self
.cur
= self
.con
.cursor(mdb
.cursors
.DictCursor
)
1250 if tenant_id
is not None: where_list
.append( "tenant_id='" + tenant_id
+"'" )
1251 if af
.check_valid_uuid(instance_id
):
1252 where_list
.append( "uuid='" + instance_id
+"'" )
1254 where_list
.append( "name='" + instance_id
+"'" )
1255 where_text
= " AND ".join(where_list
)
1256 self
.cur
.execute("SELECT * FROM instance_scenarios WHERE "+ where_text
)
1257 rows
= self
.cur
.fetchall()
1258 if self
.cur
.rowcount
==0:
1259 return -HTTP_Bad_Request
, "No instance scenario found with this criteria " + where_text
1260 elif self
.cur
.rowcount
>1:
1261 return -HTTP_Bad_Request
, "More than one instance scenario found with this criteria " + where_text
1262 instance_uuid
= rows
[0]["uuid"]
1263 instance_name
= rows
[0]["name"]
1266 self
.cur
.execute("DELETE FROM instance_scenarios WHERE uuid='" + instance_uuid
+ "'")
1268 return 1, instance_uuid
+ " " + instance_name
1269 except (mdb
.Error
, AttributeError), e
:
1270 print "nfvo_db.delete_instance_scenario DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1271 r
,c
= self
.format_error(e
, "delete", "No dependences can avoid deleting!!!!")
1272 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c
1274 def new_instance_scenario(self
, instance_scenario_dict
, tenant_id
):
1275 #return self.new_row('vnfs', vnf_dict, None, tenant_id, True, True)
1276 return self
._new
_row
_internal
('instance_scenarios', instance_scenario_dict
, tenant_id
, add_uuid
=True, root_uuid
=None, log
=True)
1278 def update_instance_scenario(self
, instance_scenario_dict
):
1282 def new_instance_vnf(self
, instance_vnf_dict
, tenant_id
, instance_scenario_id
= None):
1283 #return self.new_row('vms', vm_dict, tenant_id, True, True)
1284 return self
._new
_row
_internal
('instance_vnfs', instance_vnf_dict
, tenant_id
, add_uuid
=True, root_uuid
=instance_scenario_id
, log
=True)
1286 def update_instance_vnf(self
, instance_vnf_dict
):
1290 def delete_instance_vnf(self
, instance_vnf_id
):
1294 def new_instance_vm(self
, instance_vm_dict
, tenant_id
, instance_scenario_id
= None):
1295 #return self.new_row('vms', vm_dict, tenant_id, True, True)
1296 return self
._new
_row
_internal
('instance_vms', instance_vm_dict
, tenant_id
, add_uuid
=True, root_uuid
=instance_scenario_id
, log
=True)
1298 def update_instance_vm(self
, instance_vm_dict
):
1302 def delete_instance_vm(self
, instance_vm_id
):
1306 def new_instance_net(self
, instance_net_dict
, tenant_id
, instance_scenario_id
= None):
1307 return self
._new
_row
_internal
('instance_nets', instance_net_dict
, tenant_id
, add_uuid
=True, root_uuid
=instance_scenario_id
, log
=True)
1309 def update_instance_net(self
, instance_net_dict
):
1313 def delete_instance_net(self
, instance_net_id
):
1317 def new_instance_interface(self
, instance_interface_dict
, tenant_id
, instance_scenario_id
= None):
1318 return self
._new
_row
_internal
('instance_interfaces', instance_interface_dict
, tenant_id
, add_uuid
=True, root_uuid
=instance_scenario_id
, log
=True)
1320 def update_instance_interface(self
, instance_interface_dict
):
1324 def delete_instance_interface(self
, instance_interface_dict
):
1328 def update_datacenter_nets(self
, datacenter_id
, new_net_list
=[]):
1329 ''' Removes the old and adds the new net list at datacenter list for one datacenter.
1331 datacenter_id: uuid of the datacenter to act upon
1332 table: table where to insert
1333 new_net_list: the new values to be inserted. If empty it only deletes the existing nets
1334 Return: (Inserted items, Deleted items) if OK, (-Error, text) if error
1336 for retry_
in range(0,2):
1337 created_time
= time
.time()
1340 self
.cur
= self
.con
.cursor()
1341 cmd
="DELETE FROM datacenter_nets WHERE datacenter_id='%s'" % datacenter_id
1343 self
.cur
.execute(cmd
)
1344 deleted
= self
.cur
.rowcount
1345 for new_net
in new_net_list
:
1346 created_time
+= 0.00001
1347 self
._new
_row
_internal
('datacenter_nets', new_net
, tenant_id
=None, add_uuid
=True, created_time
=created_time
)
1348 return len (new_net_list
), deleted
1349 except (mdb
.Error
, AttributeError), e
:
1350 print "nfvo_db.update_datacenter_nets DB Exception %d: %s" % (e
.args
[0], e
.args
[1])
1351 r
,c
= self
.format_error(e
)
1352 if r
!=-HTTP_Request_Timeout
or retry_
==1: return r
,c