Merge changes I392f2858,Iba0cab65,I16304baf,Ic5befeff,I77f648f4, ...
[osm/RO.git] / vimconn_openvim.py
1 # -*- coding: utf-8 -*-
2
3 ##
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
6 # All Rights Reserved.
7 #
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
11 #
12 # http://www.apache.org/licenses/LICENSE-2.0
13 #
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
18 # under the License.
19 #
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
22 ##
23
24 '''
25 vimconnector implements all the methods to interact with openvim using the openvim API.
26
27 For interacting with Openstack refer to osconnector.
28 '''
29 __author__="Alfonso Tierno, Gerardo Garcia"
30 __date__ ="$26-aug-2014 11:09:29$"
31
32 import vimconn
33 import requests
34 import json
35 import yaml
36 from openmano_schemas import id_schema, name_schema, nameshort_schema, description_schema, \
37 vlan1000_schema, integer0_schema
38 from jsonschema import validate as js_v, exceptions as js_e
39
40 '''contain the openvim virtual machine status to openmano status'''
41 vmStatus2manoFormat={'ACTIVE':'ACTIVE',
42 'PAUSED':'PAUSED',
43 'SUSPENDED': 'SUSPENDED',
44 'INACTIVE':'INACTIVE',
45 'CREATING':'BUILD',
46 'ERROR':'ERROR','DELETED':'DELETED'
47 }
48 netStatus2manoFormat={'ACTIVE':'ACTIVE','INACTIVE':'INACTIVE','BUILD':'BUILD','ERROR':'ERROR','DELETED':'DELETED', 'DOWN':'DOWN'
49 }
50
51
52 host_schema = {
53 "type":"object",
54 "properties":{
55 "id": id_schema,
56 "name": name_schema,
57 },
58 "required": ["id"]
59 }
60 image_schema = {
61 "type":"object",
62 "properties":{
63 "id": id_schema,
64 "name": name_schema,
65 },
66 "required": ["id","name"]
67 }
68 server_schema = {
69 "type":"object",
70 "properties":{
71 "id":id_schema,
72 "name": name_schema,
73 },
74 "required": ["id","name"]
75 }
76 new_host_response_schema = {
77 "title":"host response information schema",
78 "$schema": "http://json-schema.org/draft-04/schema#",
79 "type":"object",
80 "properties":{
81 "host": host_schema
82 },
83 "required": ["host"],
84 "additionalProperties": False
85 }
86
87 get_images_response_schema = {
88 "title":"openvim images response information schema",
89 "$schema": "http://json-schema.org/draft-04/schema#",
90 "type":"object",
91 "properties":{
92 "images":{
93 "type":"array",
94 "items": image_schema,
95 }
96 },
97 "required": ["images"],
98 "additionalProperties": False
99 }
100
101 get_hosts_response_schema = {
102 "title":"openvim hosts response information schema",
103 "$schema": "http://json-schema.org/draft-04/schema#",
104 "type":"object",
105 "properties":{
106 "hosts":{
107 "type":"array",
108 "items": host_schema,
109 }
110 },
111 "required": ["hosts"],
112 "additionalProperties": False
113 }
114
115 get_host_detail_response_schema = new_host_response_schema # TODO: Content is not parsed yet
116
117 get_server_response_schema = {
118 "title":"openvim server response information schema",
119 "$schema": "http://json-schema.org/draft-04/schema#",
120 "type":"object",
121 "properties":{
122 "servers":{
123 "type":"array",
124 "items": server_schema,
125 }
126 },
127 "required": ["servers"],
128 "additionalProperties": False
129 }
130
131 new_tenant_response_schema = {
132 "title":"tenant response information schema",
133 "$schema": "http://json-schema.org/draft-04/schema#",
134 "type":"object",
135 "properties":{
136 "tenant":{
137 "type":"object",
138 "properties":{
139 "id": id_schema,
140 "name": nameshort_schema,
141 "description":description_schema,
142 "enabled":{"type" : "boolean"}
143 },
144 "required": ["id"]
145 }
146 },
147 "required": ["tenant"],
148 "additionalProperties": False
149 }
150
151 new_network_response_schema = {
152 "title":"network response information schema",
153 "$schema": "http://json-schema.org/draft-04/schema#",
154 "type":"object",
155 "properties":{
156 "network":{
157 "type":"object",
158 "properties":{
159 "id":id_schema,
160 "name":name_schema,
161 "type":{"type":"string", "enum":["bridge_man","bridge_data","data", "ptp"]},
162 "shared":{"type":"boolean"},
163 "tenant_id":id_schema,
164 "admin_state_up":{"type":"boolean"},
165 "vlan":vlan1000_schema
166 },
167 "required": ["id"]
168 }
169 },
170 "required": ["network"],
171 "additionalProperties": False
172 }
173
174
175 # get_network_response_schema = {
176 # "title":"get network response information schema",
177 # "$schema": "http://json-schema.org/draft-04/schema#",
178 # "type":"object",
179 # "properties":{
180 # "network":{
181 # "type":"object",
182 # "properties":{
183 # "id":id_schema,
184 # "name":name_schema,
185 # "type":{"type":"string", "enum":["bridge_man","bridge_data","data", "ptp"]},
186 # "shared":{"type":"boolean"},
187 # "tenant_id":id_schema,
188 # "admin_state_up":{"type":"boolean"},
189 # "vlan":vlan1000_schema
190 # },
191 # "required": ["id"]
192 # }
193 # },
194 # "required": ["network"],
195 # "additionalProperties": False
196 # }
197
198
199 new_port_response_schema = {
200 "title":"port response information schema",
201 "$schema": "http://json-schema.org/draft-04/schema#",
202 "type":"object",
203 "properties":{
204 "port":{
205 "type":"object",
206 "properties":{
207 "id":id_schema,
208 },
209 "required": ["id"]
210 }
211 },
212 "required": ["port"],
213 "additionalProperties": False
214 }
215
216 get_flavor_response_schema = {
217 "title":"openvim flavors response information schema",
218 "$schema": "http://json-schema.org/draft-04/schema#",
219 "type":"object",
220 "properties":{
221 "flavor":{
222 "type":"object",
223 "properties":{
224 "id": id_schema,
225 "name": name_schema,
226 "extended": {"type":"object"},
227 },
228 "required": ["id", "name"],
229 }
230 },
231 "required": ["flavor"],
232 "additionalProperties": False
233 }
234
235 new_flavor_response_schema = {
236 "title":"flavor response information schema",
237 "$schema": "http://json-schema.org/draft-04/schema#",
238 "type":"object",
239 "properties":{
240 "flavor":{
241 "type":"object",
242 "properties":{
243 "id":id_schema,
244 },
245 "required": ["id"]
246 }
247 },
248 "required": ["flavor"],
249 "additionalProperties": False
250 }
251
252 new_image_response_schema = {
253 "title":"image response information schema",
254 "$schema": "http://json-schema.org/draft-04/schema#",
255 "type":"object",
256 "properties":{
257 "image":{
258 "type":"object",
259 "properties":{
260 "id":id_schema,
261 },
262 "required": ["id"]
263 }
264 },
265 "required": ["image"],
266 "additionalProperties": False
267 }
268
269 new_vminstance_response_schema = {
270 "title":"server response information schema",
271 "$schema": "http://json-schema.org/draft-04/schema#",
272 "type":"object",
273 "properties":{
274 "server":{
275 "type":"object",
276 "properties":{
277 "id":id_schema,
278 },
279 "required": ["id"]
280 }
281 },
282 "required": ["server"],
283 "additionalProperties": False
284 }
285
286 get_processor_rankings_response_schema = {
287 "title":"processor rankings information schema",
288 "$schema": "http://json-schema.org/draft-04/schema#",
289 "type":"object",
290 "properties":{
291 "rankings":{
292 "type":"array",
293 "items":{
294 "type":"object",
295 "properties":{
296 "model": description_schema,
297 "value": integer0_schema
298 },
299 "additionalProperties": False,
300 "required": ["model","value"]
301 }
302 },
303 "additionalProperties": False,
304 "required": ["rankings"]
305 }
306 }
307
308 class vimconnector(vimconn.vimconnector):
309 def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None,debug=True,config={}):
310 vimconn.vimconnector.__init__(self, uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, debug, config)
311 self.tenant = None
312 self.headers_req = {'content-type': 'application/json'}
313 if tenant_id:
314 self.tenant = tenant_id
315
316 def __setitem__(self,index, value):
317 '''Set individuals parameters
318 Throw TypeError, KeyError
319 '''
320 if index=='tenant_id':
321 self.tenant = value
322 elif index=='tenant_name':
323 self.tenant = None
324 vimconn.vimconnector.__setitem__(self,index, value)
325
326 def _get_my_tenant(self):
327 '''Obtain uuid of my tenant from name
328 '''
329 if self.tenant:
330 return self.tenant
331
332 vim_response = requests.get(self.url+'/tenants?name='+ self.tenant_name, headers = self.headers_req)
333 if vim_response.status_code != 200:
334 raise vimconn.vimconnectorException ("_get_my_tenant response " + str(vim_response.status_code))
335 tenant_list = vim_response.json()["tenants"]
336 if len(tenant_list) == 0:
337 raise vimconn.vimconnectorException ("No tenant found for name '%s'" % str(self.tenant_name))
338 elif len(tenant_list) > 1:
339 raise vimconn.vimconnectorException ("More that one tenant found for name '%s'" % str(self.tenant_name))
340 self.tenant = tenant_list[0]["id"]
341 return self.tenant
342
343 def _format_jsonerror(self,http_response):
344 try:
345 data = http_response.json()
346 return data["error"]["description"]
347 except:
348 return http_response.text
349
350 def _format_in(self, http_response, schema):
351 try:
352 client_data = http_response.json()
353 js_v(client_data, schema)
354 #print "Input data: ", str(client_data)
355 return True, client_data
356 except js_e.ValidationError, exc:
357 print "validate_in error, jsonschema exception ", exc.message, "at", exc.path
358 return False, ("validate_in error, jsonschema exception ", exc.message, "at", exc.path)
359
360 def _remove_extra_items(self, data, schema):
361 deleted=[]
362 if type(data) is tuple or type(data) is list:
363 for d in data:
364 a= self._remove_extra_items(d, schema['items'])
365 if a is not None: deleted.append(a)
366 elif type(data) is dict:
367 for k in data.keys():
368 if 'properties' not in schema or k not in schema['properties'].keys():
369 del data[k]
370 deleted.append(k)
371 else:
372 a = self._remove_extra_items(data[k], schema['properties'][k])
373 if a is not None: deleted.append({k:a})
374 if len(deleted) == 0: return None
375 elif len(deleted) == 1: return deleted[0]
376 else: return deleted
377
378 def new_host(self, host_data):
379 '''Adds a new host to VIM'''
380 '''Returns status code of the VIM response'''
381 print "VIMConnector: Adding a new host"
382 payload_req = host_data
383 try:
384 vim_response = requests.post(self.url_admin+'/hosts', headers = self.headers_req, data=payload_req)
385 except requests.exceptions.RequestException, e:
386 print "new_host Exception: ", e.args
387 return -vimconn.HTTP_Not_Found, str(e.args[0])
388 print vim_response
389 #print vim_response.status_code
390 if vim_response.status_code == 200:
391 #print vim_response.json()
392 #print json.dumps(vim_response.json(), indent=4)
393 res,http_content = self._format_in(vim_response, new_host_response_schema)
394 #print http_content
395 if res :
396 r = self._remove_extra_items(http_content, new_host_response_schema)
397 if r is not None: print "Warning: remove extra items ", r
398 #print http_content
399 host_id = http_content['host']['id']
400 #print "Host id: ",host_id
401 return vim_response.status_code,host_id
402 else: return -vimconn.HTTP_Bad_Request,http_content
403 else:
404 #print vim_response.text
405 jsonerror = self.__format_jsonerror(vim_response)
406 text = 'Error in VIM "%s": not possible to add new host. HTTP Response: %d. Error: %s' % (self.url_admin, vim_response.status_code, jsonerror)
407 #print text
408 return -vim_response.status_code,text
409
410 def new_external_port(self, port_data):
411 '''Adds a external port to VIM'''
412 '''Returns the port identifier'''
413 print "VIMConnector: Adding a new external port"
414 payload_req = port_data
415 try:
416 vim_response = requests.post(self.url_admin+'/ports', headers = self.headers_req, data=payload_req)
417 except requests.exceptions.RequestException, e:
418 print "new_external_port Exception: ", e.args
419 return -vimconn.HTTP_Not_Found, str(e.args[0])
420 print vim_response
421 #print vim_response.status_code
422 if vim_response.status_code == 200:
423 #print vim_response.json()
424 #print json.dumps(vim_response.json(), indent=4)
425 res, http_content = self.__format_in(vim_response, new_port_response_schema)
426 #print http_content
427 if res:
428 r = self._remove_extra_items(http_content, new_port_response_schema)
429 if r is not None: print "Warning: remove extra items ", r
430 #print http_content
431 port_id = http_content['port']['id']
432 print "Port id: ",port_id
433 return vim_response.status_code,port_id
434 else: return -vimconn.HTTP_Bad_Request,http_content
435 else:
436 #print vim_response.text
437 jsonerror = self._format_jsonerror(vim_response)
438 text = 'Error in VIM "%s": not possible to add new external port. HTTP Response: %d. Error: %s' % (self.url_admin, vim_response.status_code, jsonerror)
439 #print text
440 return -vim_response.status_code,text
441
442 def new_external_network(self,net_name,net_type):
443 '''Adds a external network to VIM (shared)'''
444 '''Returns the network identifier'''
445 print "VIMConnector: Adding external shared network to VIM (type " + net_type + "): "+ net_name
446
447 payload_req = '{"network":{"name": "' + net_name + '","shared":true,"type": "' + net_type + '"}}'
448 try:
449 vim_response = requests.post(self.url+'/networks', headers = self.headers_req, data=payload_req)
450 except requests.exceptions.RequestException, e:
451 print "new_external_network Exception: ", e.args
452 return -vimconn.HTTP_Not_Found, str(e.args[0])
453 print vim_response
454 #print vim_response.status_code
455 if vim_response.status_code == 200:
456 #print vim_response.json()
457 #print json.dumps(vim_response.json(), indent=4)
458 res,http_content = self._format_in(vim_response, new_network_response_schema)
459 #print http_content
460 if res:
461 r = self._remove_extra_items(http_content, new_network_response_schema)
462 if r is not None: print "Warning: remove extra items ", r
463 #print http_content
464 network_id = http_content['network']['id']
465 print "Network id: ",network_id
466 return vim_response.status_code,network_id
467 else: return -vimconn.HTTP_Bad_Request,http_content
468 else:
469 #print vim_response.text
470 jsonerror = self._format_jsonerror(vim_response)
471 text = 'Error in VIM "%s": not possible to add new external network. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
472 #print text
473 return -vim_response.status_code,text
474
475 def connect_port_network(self, port_id, network_id, admin=False):
476 '''Connects a external port to a network'''
477 '''Returns status code of the VIM response'''
478 print "VIMConnector: Connecting external port to network"
479
480 payload_req = '{"port":{"network_id":"' + network_id + '"}}'
481 if admin:
482 if self.url_admin==None:
483 return -vimconn.HTTP_Unauthorized, "datacenter cannot contain admin URL"
484 url= self.url_admin
485 else:
486 url= self.url
487 try:
488 vim_response = requests.put(url +'/ports/'+port_id, headers = self.headers_req, data=payload_req)
489 except requests.exceptions.RequestException, e:
490 print "connect_port_network Exception: ", e.args
491 return -vimconn.HTTP_Not_Found, str(e.args[0])
492 print vim_response
493 #print vim_response.status_code
494 if vim_response.status_code == 200:
495 #print vim_response.json()
496 #print json.dumps(vim_response.json(), indent=4)
497 res,http_content = self._format_in(vim_response, new_port_response_schema)
498 #print http_content
499 if res:
500 r = self._remove_extra_items(http_content, new_port_response_schema)
501 if r is not None: print "Warning: remove extra items ", r
502 #print http_content
503 port_id = http_content['port']['id']
504 print "Port id: ",port_id
505 return vim_response.status_code,port_id
506 else: return -vimconn.HTTP_Bad_Request,http_content
507 else:
508 print vim_response.text
509 jsonerror = self._format_jsonerror(vim_response)
510 text = 'Error in VIM "%s": not possible to connect external port to network. HTTP Response: %d. Error: %s' % (self.url_admin, vim_response.status_code, jsonerror)
511 print text
512 return -vim_response.status_code,text
513
514 def new_tenant(self,tenant_name,tenant_description):
515 '''Adds a new tenant to VIM'''
516 '''Returns the tenant identifier'''
517 print "VIMConnector: Adding a new tenant to VIM"
518 payload_dict = {"tenant": {"name":tenant_name,"description": tenant_description, "enabled": True}}
519 payload_req = json.dumps(payload_dict)
520 #print payload_req
521
522 try:
523 vim_response = requests.post(self.url+'/tenants', headers = self.headers_req, data=payload_req)
524 except requests.exceptions.RequestException, e:
525 print "new_tenant Exception: ", e.args
526 return -vimconn.HTTP_Not_Found, str(e.args[0])
527 #print vim_response
528 if vim_response.status_code == 200:
529 #print vim_response.json()
530 #print json.dumps(vim_response.json(), indent=4)
531 res,http_content = self._format_in(vim_response, new_tenant_response_schema)
532 #print http_content
533 if res:
534 r = self._remove_extra_items(http_content, new_tenant_response_schema)
535 if r is not None: print "Warning: remove extra items ", r
536 #print http_content
537 tenant_id = http_content['tenant']['id']
538 #print "Tenant id: ",tenant_id
539 return vim_response.status_code,tenant_id
540 else: return -vimconn.HTTP_Bad_Request,http_content
541 else:
542 #print vim_response.text
543 jsonerror = self._format_jsonerror(vim_response)
544 text = 'Error in VIM "%s": not possible to add new tenant. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
545 #print text
546 return -vim_response.status_code,text
547
548 def delete_tenant(self,tenant_id,):
549 '''Delete a tenant from VIM'''
550 '''Returns the tenant identifier'''
551 print "VIMConnector: Deleting a tenant from VIM"
552 try:
553 vim_response = requests.delete(self.url+'/tenants/'+tenant_id, headers = self.headers_req)
554 except requests.exceptions.RequestException, e:
555 print "delete_tenant Exception: ", e.args
556 return -vimconn.HTTP_Not_Found, str(e.args[0])
557 #print vim_response
558 if vim_response.status_code == 200:
559 return vim_response.status_code,tenant_id
560 else:
561 #print vim_response.text
562 jsonerror = self._format_jsonerror(vim_response)
563 text = 'Error in VIM "%s": not possible to delete tenant. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
564 #print text
565 return -vim_response.status_code,text
566
567 def new_tenant_network(self,net_name,net_type,public=False, **vim_specific):
568 '''Adds a tenant network to VIM'''
569 '''Returns the network identifier'''
570 try:
571 self._get_my_tenant()
572 except Exception as e:
573 return -vimconn.HTTP_Not_Found, str(e)
574 print "vim_specific", vim_specific
575 if net_type=="bridge":
576 net_type="bridge_data"
577 print "VIMConnector: Adding a new tenant network to VIM (tenant: " + str(self.tenant) + ", type: " + net_type + "): "+ net_name
578
579 payload_req = {"name": net_name, "type": net_type, "tenant_id": self.tenant, "shared": public}
580 payload_req.update(vim_specific)
581 try:
582 vim_response = requests.post(self.url+'/networks', headers = self.headers_req, data=json.dumps({"network": payload_req}) )
583 except requests.exceptions.RequestException, e:
584 print "new_tenant_network Exception: ", e.args
585 return -vimconn.HTTP_Not_Found, str(e.args[0])
586 print vim_response
587 #print vim_response.status_code
588 if vim_response.status_code == 200:
589 #print vim_response.json()
590 #print json.dumps(vim_response.json(), indent=4)
591 res,http_content = self._format_in(vim_response, new_network_response_schema)
592 #print http_content
593 if res:
594 r = self._remove_extra_items(http_content, new_network_response_schema)
595 if r is not None: print "Warning: remove extra items ", r
596 #print http_content
597 network_id = http_content['network']['id']
598 print "Tenant Network id: ",network_id
599 return vim_response.status_code,network_id
600 else: return -vimconn.HTTP_Bad_Request,http_content
601 else:
602 #print vim_response.text
603 jsonerror = self._format_jsonerror(vim_response)
604 text = 'Error in VIM "%s": not possible to add new tenant network. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
605 #print text
606 return -vim_response.status_code,text
607
608 def get_tenant_list(self, filter_dict={}):
609 '''Obtain tenants of VIM
610 Filter_dict can be:
611 name: network name
612 id: network uuid
613 Returns the network list of dictionaries
614 '''
615 print "VIMConnector.get_tenant_list: Getting tenants from VIM (filter: " + str(filter_dict) + "): "
616 filterquery=[]
617 filterquery_text=''
618 for k,v in filter_dict.iteritems():
619 filterquery.append(str(k)+'='+str(v))
620 if len(filterquery)>0:
621 filterquery_text='?'+ '&'.join(filterquery)
622 try:
623 print self.url+'/tenants'+filterquery_text
624 vim_response = requests.get(self.url+'/tenants'+filterquery_text, headers = self.headers_req)
625 except requests.exceptions.RequestException, e:
626 print "get_tenant_list Exception: ", e.args
627 return -vimconn.HTTP_Not_Found, str(e.args[0])
628 print vim_response
629 #print vim_response.status_code
630 if vim_response.status_code == 200:
631 #print vim_response.json()
632 #print json.dumps(vim_response.json(), indent=4)
633 #TODO: parse input datares,http_content = self._format_in(vim_response, new_network_response_schema)
634 #print http_content
635 return vim_response.status_code, vim_response.json()["tenants"]
636 else:
637 #print vim_response.text
638 jsonerror = self._format_jsonerror(vim_response)
639 text = 'Error in VIM "%s": not possible to get tenant list. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
640 #print text
641 return -vim_response.status_code,text
642
643 def get_network_list(self, filter_dict={}):
644 '''Obtain tenant networks of VIM
645 Filter_dict can be:
646 name: network name
647 id: network uuid
648 shared: boolean
649 tenant_id: tenant
650 admin_state_up: boolean
651 status: 'ACTIVE'
652 Returns the network list of dictionaries
653 '''
654
655 filter_dict["tenant_id"] = self._get_my_tenant()
656 print "VIMConnector.get_network_list: Getting tenant network from VIM (filter: " + str(filter_dict) + "): "
657 filterquery=[]
658 filterquery_text=''
659 for k,v in filter_dict.iteritems():
660 filterquery.append(str(k)+'='+str(v))
661 if len(filterquery)>0:
662 filterquery_text='?'+ '&'.join(filterquery)
663 try:
664 print self.url+'/networks'+filterquery_text
665 vim_response = requests.get(self.url+'/networks'+filterquery_text, headers = self.headers_req)
666 except requests.exceptions.RequestException, e:
667 print "get_network_list Exception: ", e.args
668 return -vimconn.HTTP_Not_Found, str(e.args[0])
669 print vim_response
670 #print vim_response.status_code
671 if vim_response.status_code == 200:
672 #print vim_response.json()
673 #print json.dumps(vim_response.json(), indent=4)
674 #TODO: parse input datares,http_content = self._format_in(vim_response, new_network_response_schema)
675 #print http_content
676 return vim_response.status_code, vim_response.json()["networks"]
677 else:
678 #print vim_response.text
679 jsonerror = self._format_jsonerror(vim_response)
680 text = 'Error in VIM "%s": not possible to get network list. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
681 #print text
682 return -vim_response.status_code,text
683
684 def get_tenant_network(self, net_id, tenant_id=None):
685 '''Obtain tenant networks of VIM'''
686 '''Returns the network information from a network id'''
687 if self.debug:
688 print "VIMconnector.get_tenant_network(): Getting tenant network %s from VIM" % net_id
689 filter_dict={"id": net_id}
690 if tenant_id:
691 filter_dict["tenant_id"] = tenant_id
692 r, net_list = self.get_network_list(filter_dict)
693 if r<0:
694 return r, net_list
695 if len(net_list)==0:
696 return -vimconn.HTTP_Not_Found, "Network '%s' not found" % net_id
697 elif len(net_list)>1:
698 return -vimconn.HTTP_Conflict, "Found more than one network with this criteria"
699 return 1, net_list[0]
700
701 def delete_tenant_network(self, net_id):
702 '''Deletes a tenant network from VIM'''
703 '''Returns the network identifier'''
704 try:
705 self._get_my_tenant()
706 except Exception as e:
707 return -vimconn.HTTP_Not_Found, str(e)
708 print "VIMConnector: Deleting a new tenant network from VIM tenant: " + self.tenant + ", id: " + net_id
709
710 try:
711 vim_response = requests.delete(self.url+'/networks/'+net_id, headers=self.headers_req)
712 except requests.exceptions.RequestException, e:
713 print "delete_tenant_network Exception: ", e.args
714 return -vimconn.HTTP_Not_Found, str(e.args[0])
715
716 print vim_response
717 #print vim_response.status_code
718 if vim_response.status_code == 200:
719 return vim_response.status_code,net_id
720 else:
721 #print vim_response.text
722 jsonerror = self._format_jsonerror(vim_response)
723 text = 'Error in VIM "%s": not possible to delete tenant network. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
724 #print text
725 return -vim_response.status_code,text
726
727 def refresh_tenant_network(self, net_id):
728 '''Refreshes the status of the tenant network'''
729 '''Returns: 0 if no error,
730 <0 if error'''
731 return 0
732
733 def get_tenant_flavor(self, flavor_id):
734 '''Obtain flavor details from the VIM
735 Returns the flavor dict details
736 '''
737 try:
738 self._get_my_tenant()
739 except Exception as e:
740 return -vimconn.HTTP_Not_Found, str(e)
741 print "VIMConnector: Getting flavor from VIM"
742 #print "VIM URL:",self.url
743 #print "Tenant id:",self.tenant
744 #print "Flavor:",flavor_data
745 try:
746 vim_response = requests.get(self.url+'/'+self.tenant+'/flavors/'+flavor_id, headers = self.headers_req)
747 except requests.exceptions.RequestException, e:
748 print "get_tenant_flavor Exception: ", e.args
749 return -vimconn.HTTP_Not_Found, str(e.args[0])
750 print vim_response
751 #print vim_response.status_code
752 if vim_response.status_code == 200:
753 #print vim_response.json()
754 #print json.dumps(vim_response.json(), indent=4)
755 res,http_content = self._format_in(vim_response, get_flavor_response_schema)
756 #print http_content
757 if res:
758 r = self._remove_extra_items(http_content, get_flavor_response_schema)
759 if r is not None: print "Warning: remove extra items ", r
760 #print http_content
761 flavor_id = http_content['flavor']['id']
762 print "Flavor id: ",flavor_id
763 return vim_response.status_code,flavor_id
764 else: return -vimconn.HTTP_Bad_Request,http_content
765
766 else:
767 #print vim_response.text
768 jsonerror = self._format_jsonerror(vim_response)
769 text = 'Error in VIM "%s": not possible to get flavor. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
770 #print text
771 return -vim_response.status_code,text
772
773 def new_tenant_flavor(self, flavor_data):
774 '''Adds a tenant flavor to VIM'''
775 '''Returns the flavor identifier'''
776 try:
777 self._get_my_tenant()
778 except Exception as e:
779 return -vimconn.HTTP_Not_Found, str(e)
780 print "VIMConnector: Adding a new flavor to VIM"
781 #print "VIM URL:",self.url
782 #print "Tenant id:",self.tenant
783 #print "Flavor:",flavor_data
784 payload_req = json.dumps({'flavor': flavor_data})
785 try:
786 vim_response = requests.post(self.url+'/'+self.tenant+'/flavors', headers = self.headers_req, data=payload_req)
787 except requests.exceptions.RequestException, e:
788 print "new_tenant_flavor Exception: ", e.args
789 return -vimconn.HTTP_Not_Found, str(e.args[0])
790 print vim_response
791 #print vim_response.status_code
792 if vim_response.status_code == 200:
793 #print vim_response.json()
794 #print json.dumps(vim_response.json(), indent=4)
795 res,http_content = self._format_in(vim_response, new_flavor_response_schema)
796 #print http_content
797 if res:
798 r = self._remove_extra_items(http_content, new_flavor_response_schema)
799 if r is not None: print "Warning: remove extra items ", r
800 #print http_content
801 flavor_id = http_content['flavor']['id']
802 print "Flavor id: ",flavor_id
803 return vim_response.status_code,flavor_id
804 else: return -vimconn.HTTP_Bad_Request,http_content
805
806 else:
807 #print vim_response.text
808 jsonerror = self._format_jsonerror(vim_response)
809 text = 'Error in VIM "%s": not possible to add new flavor. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
810 #print text
811 return -vim_response.status_code,text
812
813 def delete_tenant_flavor(self,flavor_id):
814 '''Deletes a tenant flavor from VIM'''
815 '''Returns the HTTP response code and a message indicating details of the success or fail'''
816 try:
817 self._get_my_tenant()
818 except Exception as e:
819 return -vimconn.HTTP_Not_Found, str(e)
820 print "VIMConnector: Deleting a flavor from VIM"
821 print "VIM URL:",self.url
822 print "Tenant id:",self.tenant
823 print "Flavor id:",flavor_id
824 #payload_req = flavor_data
825 try:
826 vim_response = requests.delete(self.url+'/'+self.tenant+'/flavors/'+flavor_id)
827 except requests.exceptions.RequestException, e:
828 print "delete_tenant_flavor Exception: ", e.args
829 return -vimconn.HTTP_Not_Found, str(e.args[0])
830 print vim_response
831 print vim_response.status_code
832 if vim_response.status_code == 200:
833 result = vim_response.json()["result"]
834 return 200,result
835 else:
836 #print vim_response.text
837 jsonerror = self._format_jsonerror(vim_response)
838 text = 'Error in VIM "%s": not possible to delete flavor. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
839 #print text
840 return -vim_response.status_code,text
841
842 def new_tenant_image(self,image_dict):
843 '''
844 Adds a tenant image to VIM
845 Returns:
846 200, image-id if the image is created
847 <0, message if there is an error
848 '''
849 try:
850 self._get_my_tenant()
851 except Exception as e:
852 return -vimconn.HTTP_Not_Found, str(e)
853 print "VIMConnector: Adding a new image to VIM", image_dict['location']
854 new_image_dict={'name': image_dict['name']}
855 if 'description' in image_dict and image_dict['description'] != None:
856 new_image_dict['description'] = image_dict['description']
857 if 'metadata' in image_dict and image_dict['metadata'] != None:
858 new_image_dict['metadata'] = yaml.load(image_dict['metadata'])
859 if 'location' in image_dict and image_dict['location'] != None:
860 new_image_dict['path'] = image_dict['location']
861 payload_req = json.dumps({"image":new_image_dict})
862 url=self.url + '/' + self.tenant + '/images'
863 try:
864 vim_response = requests.post(url, headers = self.headers_req, data=payload_req)
865 except requests.exceptions.RequestException, e:
866 print "new_tenant_image Exception: ", e.args
867 return -vimconn.HTTP_Not_Found, str(e.args[0])
868 print vim_response
869 #print vim_response.status_code
870 if vim_response.status_code == 200:
871 #print vim_response.json()
872 #print json.dumps(vim_response.json(), indent=4)
873 res,http_content = self._format_in(vim_response, new_image_response_schema)
874 #print http_content
875 if res:
876 r = self._remove_extra_items(http_content, new_image_response_schema)
877 if r is not None: print "Warning: remove extra items ", r
878 #print http_content
879 image_id = http_content['image']['id']
880 print "Image id: ",image_id
881 return vim_response.status_code,image_id
882 else: return -vimconn.HTTP_Bad_Request,http_content
883 else:
884 #print vim_response.text
885 jsonerror = self._format_jsonerror(vim_response)
886 text = 'Error in VIM "%s": not possible to add new image. HTTP Response: %d. Error: %s' % (url, vim_response.status_code, jsonerror)
887 #print text
888 return -vim_response.status_code,text
889
890 def delete_tenant_image(self, image_id):
891 '''Deletes a tenant image from VIM'''
892 '''Returns the HTTP response code and a message indicating details of the success or fail'''
893 try:
894 self._get_my_tenant()
895 except Exception as e:
896 return -vimconn.HTTP_Not_Found, str(e)
897 print "VIMConnector: Deleting an image from VIM"
898 #payload_req = flavor_data
899 url=self.url + '/'+ self.tenant +'/images/'+image_id
900 try:
901 vim_response = requests.delete(url)
902 except requests.exceptions.RequestException, e:
903 print "delete_tenant_image Exception url '%s': " % url, e.args
904 return -vimconn.HTTP_Not_Found, str(e.args[0])
905 print vim_response
906 print vim_response.status_code
907 if vim_response.status_code == 200:
908 result = vim_response.json()["result"]
909 return 200,result
910 else:
911 #print vim_response.text
912 jsonerror = self._format_jsonerror(vim_response)
913 text = 'Error in VIM "%s": not possible to delete image. HTTP Response: %d. Error: %s' % (url, vim_response.status_code, jsonerror)
914 #print text
915 return -vim_response.status_code,text
916
917 def new_tenant_vminstancefromJSON(self, vm_data):
918 '''Adds a VM instance to VIM'''
919 '''Returns the instance identifier'''
920 try:
921 self._get_my_tenant()
922 except Exception as e:
923 return -vimconn.HTTP_Not_Found, str(e)
924 print "VIMConnector: Adding a new VM instance from JSON to VIM"
925 payload_req = vm_data
926 try:
927 vim_response = requests.post(self.url+'/'+self.tenant+'/servers', headers = self.headers_req, data=payload_req)
928 except requests.exceptions.RequestException, e:
929 print "new_tenant_vminstancefromJSON Exception: ", e.args
930 return -vimconn.HTTP_Not_Found, str(e.args[0])
931 print vim_response
932 #print vim_response.status_code
933 if vim_response.status_code == 200:
934 #print vim_response.json()
935 #print json.dumps(vim_response.json(), indent=4)
936 res,http_content = self._format_in(vim_response, new_image_response_schema)
937 #print http_content
938 if res:
939 r = self._remove_extra_items(http_content, new_image_response_schema)
940 if r is not None: print "Warning: remove extra items ", r
941 #print http_content
942 vminstance_id = http_content['server']['id']
943 print "Tenant image id: ",vminstance_id
944 return vim_response.status_code,vminstance_id
945 else: return -vimconn.HTTP_Bad_Request,http_content
946 else:
947 #print vim_response.text
948 jsonerror = self._format_jsonerror(vim_response)
949 text = 'Error in VIM "%s": not possible to add new vm instance. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
950 #print text
951 return -vim_response.status_code,text
952
953 def new_tenant_vminstance(self,name,description,start,image_id,flavor_id,net_list):
954 '''Adds a VM instance to VIM
955 Params:
956 start: indicates if VM must start or boot in pause mode. Ignored
957 image_id,flavor_id: image and flavor uuid
958 net_list: list of interfaces, each one is a dictionary with:
959 name:
960 net_id: network uuid to connect
961 vpci: virtual vcpi to assign
962 model: interface model, virtio, e2000, ...
963 mac_address:
964 use: 'data', 'bridge', 'mgmt'
965 type: 'virtual', 'PF', 'VF', 'VFnotShared'
966 vim_id: filled/added by this function
967 #TODO ip, security groups
968 Returns >=0, the instance identifier
969 <0, error_text
970 '''
971 try:
972 self._get_my_tenant()
973 except Exception as e:
974 return -vimconn.HTTP_Not_Found, str(e)
975 print "VIMConnector: Adding a new VM instance to VIM"
976
977 # net_list = []
978 # for k,v in net_dict.items():
979 # print k,v
980 # net_list.append('{"name":"' + k + '", "uuid":"' + v + '"}')
981 # net_list_string = ', '.join(net_list)
982 virtio_net_list=[]
983 for net in net_list:
984 if not net.get("net_id"):
985 continue
986 net_dict={'uuid': net["net_id"]}
987 if net.get("type"): net_dict["type"] = net["type"]
988 if net.get("name"): net_dict["name"] = net["name"]
989 if net.get("vpci"): net_dict["vpci"] = net["vpci"]
990 if net.get("model"): net_dict["model"] = net["model"]
991 if net.get("mac_address"): net_dict["mac_address"] = net["mac_address"]
992 virtio_net_list.append(net_dict)
993 payload_dict={ "name": name,
994 "description": description,
995 "imageRef": image_id,
996 "flavorRef": flavor_id,
997 "networks": virtio_net_list
998 }
999 if start != None:
1000 payload_dict["start"] = start
1001 payload_req = json.dumps({"server": payload_dict})
1002 print self.url+'/'+self.tenant+'/servers'+payload_req
1003 try:
1004 vim_response = requests.post(self.url+'/'+self.tenant+'/servers', headers = self.headers_req, data=payload_req)
1005 except requests.exceptions.RequestException, e:
1006 print "new_tenant_vminstance Exception: ", e.args
1007 return -vimconn.HTTP_Not_Found, str(e.args[0])
1008 print vim_response
1009 #print vim_response.status_code
1010 if vim_response.status_code != 200:
1011 print vim_response.text
1012 jsonerror = self._format_jsonerror(vim_response)
1013 text = 'Error in VIM "%s": not possible to add new vm instance. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
1014 #print text
1015 return -vim_response.status_code,text
1016 #ok
1017 print vim_response.json()
1018 print json.dumps(vim_response.json(), indent=4)
1019 res,http_content = self._format_in(vim_response, new_vminstance_response_schema)
1020 #print http_content
1021 if not res:
1022 return -vimconn.HTTP_Bad_Request,http_content
1023 #r = self._remove_extra_items(http_content, new_vminstance_response_schema)
1024 #if r is not None: print "Warning: remove extra items ", r
1025 vminstance_id = http_content['server']['id']
1026 print json.dumps(http_content, indent=4)
1027 #connect data plane interfaces to network
1028 for net in net_list:
1029 if net["type"]=="virtual":
1030 if not net.get("net_id"):
1031 continue
1032 for iface in http_content['server']['networks']:
1033 if "name" in net:
1034 if net["name"]==iface["name"]:
1035 net["vim_id"] = iface['iface_id']
1036 break
1037 elif "net_id" in net:
1038 if net["net_id"]==iface["net_id"]:
1039 net["vim_id"] = iface['iface_id']
1040 break
1041 else: #dataplane
1042 for numa in http_content['server'].get('extended',{}).get('numas',() ):
1043 for iface in numa.get('interfaces',() ):
1044 if net['name'] == iface['name']:
1045 net['vim_id'] = iface['iface_id']
1046 #Code bellow is not needed, current openvim connect dataplane interfaces
1047 #if net.get("net_id"):
1048 ##connect dataplane interface
1049 # result, port_id = self.connect_port_network(iface['iface_id'], net["net_id"])
1050 # if result < 0:
1051 # error_text = "Error attaching port %s to network %s: %s." % (iface['iface_id'], net["net_id"], port_id)
1052 # print "new_tenant_vminstance: " + error_text
1053 # self.delete_tenant_vminstance(vminstance_id)
1054 # return result, error_text
1055 break
1056
1057 print "VM instance id: ",vminstance_id
1058 return vim_response.status_code,vminstance_id
1059
1060 def get_tenant_vminstance(self,vm_id):
1061 '''Returns the VM instance information from VIM'''
1062 try:
1063 self._get_my_tenant()
1064 except Exception as e:
1065 return -vimconn.HTTP_Not_Found, str(e)
1066 print "VIMConnector: Getting tenant VM instance information from VIM"
1067
1068 url = self.url+'/'+self.tenant+'/servers/'+vm_id
1069 print url
1070 try:
1071 vim_response = requests.get(url, headers = self.headers_req)
1072 except requests.exceptions.RequestException, e:
1073 print "get_tenant_vminstance Exception: ", e.args
1074 return -vimconn.HTTP_Not_Found, str(e.args[0])
1075 print vim_response
1076 #print vim_response.status_code
1077 if vim_response.status_code == 200:
1078 print vim_response.json()
1079 print json.dumps(vim_response.json(), indent=4)
1080 res,http_content = self._format_in(vim_response, new_vminstance_response_schema)
1081 #print http_content
1082 if res:
1083 print json.dumps(http_content, indent=4)
1084 return vim_response.status_code,http_content
1085 else: return -vimconn.HTTP_Bad_Request,http_content
1086 else:
1087 print vim_response.text
1088 jsonerror = self._format_jsonerror(vim_response)
1089 text = 'Error in VIM "%s": not possible to get vm instance. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
1090 #print text
1091 return -vim_response.status_code,text
1092
1093 def delete_tenant_vminstance(self, vm_id):
1094 '''Removes a VM instance from VIM'''
1095 '''Returns the instance identifier'''
1096 try:
1097 self._get_my_tenant()
1098 except Exception as e:
1099 return -vimconn.HTTP_Not_Found, str(e)
1100 print "VIMConnector: Delete a VM instance from VIM " + vm_id
1101
1102 try:
1103 vim_response = requests.delete(self.url+'/'+self.tenant+'/servers/'+vm_id, headers = self.headers_req)
1104 except requests.exceptions.RequestException, e:
1105 print "delete_tenant_vminstance Exception: ", e.args
1106 return -vimconn.HTTP_Not_Found, str(e.args[0])
1107
1108 #print vim_response.status_code
1109 if vim_response.status_code == 200:
1110 print json.dumps(vim_response.json(), indent=4)
1111 return vim_response.status_code, vm_id
1112 else:
1113 #print vim_response.text
1114 jsonerror = self._format_jsonerror(vim_response)
1115 text = 'Error in VIM "%s": not possible to delete vm instance. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
1116 #print text
1117 return -vim_response.status_code, text
1118
1119 def refresh_tenant_vms_and_nets(self, vmDict, netDict):
1120 '''Refreshes the status of the dictionaries of VM instances and nets passed as arguments. It modifies the dictionaries'''
1121 '''Returns:
1122 - result: 0 if all elements could be refreshed (even if its status didn't change)
1123 n>0, the number of elements that couldn't be refreshed,
1124 <0 if error (foreseen)
1125 - error_msg: text with reference to possible errors
1126 '''
1127 try:
1128 self._get_my_tenant()
1129 except Exception as e:
1130 return -vimconn.HTTP_Not_Found, str(e)
1131 #vms_refreshed = []
1132 #nets_refreshed = []
1133 vms_unrefreshed = []
1134 nets_unrefreshed = []
1135 for vm_id in vmDict:
1136 vmDict[vm_id]={'error_msg':None, 'vim_info':None}
1137 print "VIMConnector refresh_tenant_vms and nets: Getting tenant VM instance information from VIM"
1138
1139 url = self.url+'/'+self.tenant+'/servers/'+ vm_id
1140 print url
1141 try:
1142 vim_response = requests.get(url, headers = self.headers_req)
1143 except requests.exceptions.RequestException, e:
1144 print "VIMConnector refresh_tenant_elements. Exception: ", e.args
1145 vmDict[vm_id]['status'] = "VIM_ERROR"
1146 vmDict[vm_id]['error_msg'] = str(e)
1147 vms_unrefreshed.append(vm_id)
1148 continue
1149 #print vim_response
1150 #print vim_response.status_code
1151 if vim_response.status_code == 200:
1152 #print vim_response.json()
1153 #print json.dumps(vim_response.json(), indent=4)
1154 management_ip = False
1155 res,http_content = self._format_in(vim_response, new_vminstance_response_schema)
1156 if res:
1157 try:
1158 vmDict[vm_id]['status'] = vmStatus2manoFormat[ http_content['server']['status'] ]
1159 if http_content['server'].get('last_error'):
1160 vmDict[vm_id]['error_msg'] = http_content['server']['last_error']
1161 vmDict[vm_id]["vim_info"] = yaml.safe_dump(http_content['server'])
1162 vmDict[vm_id]["interfaces"]=[]
1163 #get interfaces info
1164 url2 = self.url+'/ports?device_id='+ vm_id
1165 try:
1166 vim_response2 = requests.get(url2, headers = self.headers_req)
1167 if vim_response.status_code == 200:
1168 client_data = vim_response2.json()
1169 for port in client_data.get("ports"):
1170 print "VACAport", port
1171 interface={}
1172 interface['vim_info'] = yaml.safe_dump(port)
1173 interface["mac_address"] = port.get("mac_address")
1174 interface["vim_net_id"] = port["network_id"]
1175 interface["vim_interface_id"] = port["id"]
1176 interface["ip_address"] = port.get("ip_address")
1177 if interface["ip_address"]:
1178 management_ip = True
1179 if interface["ip_address"] == "0.0.0.0":
1180 interface["ip_address"] = None
1181 vmDict[vm_id]["interfaces"].append(interface)
1182
1183 except Exception as e:
1184 print "VIMConnector refresh_tenant_elements. Port get %s: %s", (type(e).__name__, (str(e) if len(e.args)==0 else str(e.args[0])))
1185
1186 if vmDict[vm_id]['status'] == "ACTIVE" and not management_ip:
1187 vmDict[vm_id]['status'] = "ACTIVE:NoMgmtIP"
1188
1189 except Exception as e:
1190 vmDict[vm_id]['status'] = "VIM_ERROR"
1191 vmDict[vm_id]['error_msg'] = str(e)
1192 vms_unrefreshed.append(vm_id)
1193 else:
1194 vmDict[vm_id]['status'] = "VIM_ERROR"
1195 vmDict[vm_id]['error_msg'] = str(http_content)
1196 vms_unrefreshed.append(vm_id)
1197 else:
1198 #print vim_response.text
1199 jsonerror = self._format_jsonerror(vim_response)
1200 print 'VIMConnector refresh_tenant_vms_and_nets. Error in VIM "%s": not possible to get VM instance. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
1201 if vim_response.status_code == 404: # HTTP_Not_Found
1202 vmDict[vm_id]['status'] = "DELETED"
1203 else:
1204 vmDict[vm_id]['status'] = "VIM_ERROR"
1205 vmDict[vm_id]['error_msg'] = jsonerror
1206 vms_unrefreshed.append(vm_id)
1207
1208 #print "VMs refreshed: %s" % str(vms_refreshed)
1209 for net_id in netDict:
1210 netDict[net_id] = {'error_msg':None, 'vim_info':None}
1211 print "VIMConnector refresh_tenant_vms_and_nets: Getting tenant network from VIM (tenant: " + str(self.tenant) + "): "
1212 r,c = self.get_tenant_network(net_id)
1213 if r<0:
1214 print "VIMconnector refresh_tenant_network. Error getting net_id '%s' status: %s" % (net_id, c)
1215 if r==-vimconn.HTTP_Not_Found:
1216 netDict[net_id]['status'] = "DELETED" #TODO check exit status
1217 else:
1218 netDict[net_id]['status'] = "VIM_ERROR"
1219 netDict[net_id]['error_msg'] = c
1220 nets_unrefreshed.append(net_id)
1221 else:
1222 try:
1223 net_status = netStatus2manoFormat[ c['status'] ]
1224 if net_status == "ACTIVE" and not c['admin_state_up']:
1225 net_status = "DOWN"
1226 netDict[net_id]['status'] = net_status
1227 if c.get('last_error'):
1228 netDict[net_id]['error_msg'] = c['last_error']
1229 netDict[net_id]["vim_info"] = yaml.safe_dump(c)
1230 except Exception as e:
1231 netDict[net_id]['status'] = "VIM_ERROR"
1232 netDict[net_id]['error_msg'] = str(e)
1233 nets_unrefreshed.append(net_id)
1234
1235 #print "Nets refreshed: %s" % str(nets_refreshed)
1236
1237 error_msg=""
1238 if len(vms_unrefreshed)+len(nets_unrefreshed)>0:
1239 error_msg += "VMs unrefreshed: " + str(vms_unrefreshed) + "; nets unrefreshed: " + str(nets_unrefreshed)
1240 print error_msg
1241
1242 #return len(vms_unrefreshed)+len(nets_unrefreshed), error_msg, vms_refreshed, nets_refreshed
1243 return len(vms_unrefreshed)+len(nets_unrefreshed), error_msg
1244
1245 def action_tenant_vminstance(self, vm_id, action_dict):
1246 '''Send and action over a VM instance from VIM'''
1247 '''Returns the status'''
1248 try:
1249 self._get_my_tenant()
1250 except Exception as e:
1251 return -vimconn.HTTP_Not_Found, str(e)
1252 print "VIMConnector: Action over VM instance from VIM " + vm_id
1253
1254 try:
1255 if "console" in action_dict:
1256 return -vimconn.HTTP_Service_Unavailable, "getting console is not available at openvim"
1257
1258 vim_response = requests.post(self.url+'/'+self.tenant+'/servers/'+vm_id+"/action", headers = self.headers_req, data=json.dumps(action_dict) )
1259 except requests.exceptions.RequestException, e:
1260 print "action_tenant_vminstance Exception: ", e.args
1261 return -vimconn.HTTP_Not_Found, str(e.args[0])
1262
1263 #print vim_response.status_code
1264 if vim_response.status_code == 200:
1265 #print "vimconnector.action_tenant_vminstance():", json.dumps(vim_response.json(), indent=4)
1266 return vim_response.status_code, vm_id
1267 else:
1268 #print vim_response.text
1269 jsonerror = self._format_jsonerror(vim_response)
1270 text = 'Error in VIM "%s": action over vm instance. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
1271 #print text
1272 return vim_response.status_code, text
1273
1274 def host_vim2gui(self, host, server_dict):
1275 '''Transform host dictionary from VIM format to GUI format,
1276 and append to the server_dict
1277 '''
1278 if type(server_dict) is not dict:
1279 print 'vimconnector.host_vim2gui() ERROR, param server_dict must be a dictionary'
1280 return
1281 RAD={}
1282 occupation={}
1283 for numa in host['host']['numas']:
1284 RAD_item={}
1285 occupation_item={}
1286 #memory
1287 RAD_item['memory']={'size': str(numa['memory'])+'GB', 'eligible': str(numa['hugepages'])+'GB'}
1288 occupation_item['memory']= str(numa['hugepages_consumed'])+'GB'
1289 #cpus
1290 RAD_item['cpus']={}
1291 RAD_item['cpus']['cores'] = []
1292 RAD_item['cpus']['eligible_cores'] = []
1293 occupation_item['cores']=[]
1294 for _ in range(0, len(numa['cores']) / 2):
1295 RAD_item['cpus']['cores'].append( [] )
1296 for core in numa['cores']:
1297 RAD_item['cpus']['cores'][core['core_id']].append(core['thread_id'])
1298 if not 'status' in core: RAD_item['cpus']['eligible_cores'].append(core['thread_id'])
1299 if 'instance_id' in core: occupation_item['cores'].append(core['thread_id'])
1300 #ports
1301 RAD_item['ports']={}
1302 occupation_item['ports']={}
1303 for iface in numa['interfaces']:
1304 RAD_item['ports'][ iface['pci'] ] = 'speed:'+str(iface['Mbps'])+'M'
1305 occupation_item['ports'][ iface['pci'] ] = { 'occupied': str(100*iface['Mbps_consumed'] / iface['Mbps']) + "%" }
1306
1307 RAD[ numa['numa_socket'] ] = RAD_item
1308 occupation[ numa['numa_socket'] ] = occupation_item
1309 server_dict[ host['host']['name'] ] = {'RAD':RAD, 'occupation':occupation}
1310
1311 def get_hosts_info(self):
1312 '''Get the information of deployed hosts
1313 Returns the hosts content'''
1314 #obtain hosts list
1315 url=self.url+'/hosts'
1316 try:
1317 vim_response = requests.get(url)
1318 except requests.exceptions.RequestException, e:
1319 print "get_hosts_info Exception: ", e.args
1320 return -vimconn.HTTP_Not_Found, str(e.args[0])
1321 print "vim get", url, "response:", vim_response.status_code, vim_response.json()
1322 #print vim_response.status_code
1323 #print json.dumps(vim_response.json(), indent=4)
1324 if vim_response.status_code != 200:
1325 #TODO: get error
1326 print 'vimconnector.get_hosts_info error getting host list %d %s' %(vim_response.status_code, vim_response.json())
1327 return -vim_response.status_code, "Error getting host list"
1328
1329 res,hosts = self._format_in(vim_response, get_hosts_response_schema)
1330
1331 if res==False:
1332 print "vimconnector.get_hosts_info error parsing GET HOSTS vim response", hosts
1333 return vimconn.HTTP_Internal_Server_Error, hosts
1334 #obtain hosts details
1335 hosts_dict={}
1336 for host in hosts['hosts']:
1337 url=self.url+'/hosts/'+host['id']
1338 try:
1339 vim_response = requests.get(url)
1340 except requests.exceptions.RequestException, e:
1341 print "get_hosts_info Exception: ", e.args
1342 return -vimconn.HTTP_Not_Found, str(e.args[0])
1343 print "vim get", url, "response:", vim_response.status_code, vim_response.json()
1344 if vim_response.status_code != 200:
1345 print 'vimconnector.get_hosts_info error getting detailed host %d %s' %(vim_response.status_code, vim_response.json())
1346 continue
1347 res,host_detail = self._format_in(vim_response, get_host_detail_response_schema)
1348 if res==False:
1349 print "vimconnector.get_hosts_info error parsing GET HOSTS/%s vim response" % host['id'], host_detail
1350 continue
1351 #print 'host id '+host['id'], json.dumps(host_detail, indent=4)
1352 self.host_vim2gui(host_detail, hosts_dict)
1353 return 200, hosts_dict
1354
1355 def get_hosts(self, vim_tenant):
1356 '''Get the hosts and deployed instances
1357 Returns the hosts content'''
1358 #obtain hosts list
1359 url=self.url+'/hosts'
1360 try:
1361 vim_response = requests.get(url)
1362 except requests.exceptions.RequestException, e:
1363 print "get_hosts Exception: ", e.args
1364 return -vimconn.HTTP_Not_Found, str(e.args[0])
1365 print "vim get", url, "response:", vim_response.status_code, vim_response.json()
1366 #print vim_response.status_code
1367 #print json.dumps(vim_response.json(), indent=4)
1368 if vim_response.status_code != 200:
1369 #TODO: get error
1370 print 'vimconnector.get_hosts error getting host list %d %s' %(vim_response.status_code, vim_response.json())
1371 return -vim_response.status_code, "Error getting host list"
1372
1373 res,hosts = self._format_in(vim_response, get_hosts_response_schema)
1374
1375 if res==False:
1376 print "vimconnector.get_host error parsing GET HOSTS vim response", hosts
1377 return vimconn.HTTP_Internal_Server_Error, hosts
1378 #obtain instances from hosts
1379 for host in hosts['hosts']:
1380 url=self.url+'/' + vim_tenant + '/servers?hostId='+host['id']
1381 try:
1382 vim_response = requests.get(url)
1383 except requests.exceptions.RequestException, e:
1384 print "get_hosts Exception: ", e.args
1385 return -vimconn.HTTP_Not_Found, str(e.args[0])
1386 print "vim get", url, "response:", vim_response.status_code, vim_response.json()
1387 if vim_response.status_code != 200:
1388 print 'vimconnector.get_hosts error getting instances at host %d %s' %(vim_response.status_code, vim_response.json())
1389 continue
1390 res,servers = self._format_in(vim_response, get_server_response_schema)
1391 if res==False:
1392 print "vimconnector.get_host error parsing GET SERVERS/%s vim response" % host['id'], servers
1393 continue
1394 #print 'host id '+host['id'], json.dumps(host_detail, indent=4)
1395 host['instances'] = servers['servers']
1396 return 200, hosts['hosts']
1397
1398 def get_processor_rankings(self):
1399 '''Get the processor rankings in the VIM database'''
1400 url=self.url+'/processor_ranking'
1401 try:
1402 vim_response = requests.get(url)
1403 except requests.exceptions.RequestException, e:
1404 print "get_processor_rankings Exception: ", e.args
1405 return -vimconn.HTTP_Not_Found, str(e.args[0])
1406 print "vim get", url, "response:", vim_response.status_code, vim_response.json()
1407 #print vim_response.status_code
1408 #print json.dumps(vim_response.json(), indent=4)
1409 if vim_response.status_code != 200:
1410 #TODO: get error
1411 print 'vimconnector.get_processor_rankings error getting processor rankings %d %s' %(vim_response.status_code, vim_response.json())
1412 return -vim_response.status_code, "Error getting processor rankings"
1413
1414 res,rankings = self._format_in(vim_response, get_processor_rankings_response_schema)
1415 return res, rankings['rankings']
1416
1417 def get_image_id_from_path(self, path):
1418 '''Get the image id from image path in the VIM database'''
1419 '''Returns:
1420 0,"Image not found" if there are no images with that path
1421 1,image-id if there is one image with that path
1422 <0,message if there was an error (Image not found, error contacting VIM, more than 1 image with that path, etc.)
1423 '''
1424 try:
1425 self._get_my_tenant()
1426 except Exception as e:
1427 return -vimconn.HTTP_Not_Found, str(e)
1428 url=self.url + '/' + self.tenant + '/images?path='+path
1429 try:
1430 vim_response = requests.get(url)
1431 except requests.exceptions.RequestException, e:
1432 print "get_image_id_from_path url='%s'Exception: '%s'" % (url, str(e.args))
1433 return -vimconn.HTTP_Not_Found, str(e.args[0])
1434 print "vim get_image_id_from_path", url, "response:", vim_response.status_code, vim_response.json()
1435 #print vim_response.status_code
1436 #print json.dumps(vim_response.json(), indent=4)
1437 if vim_response.status_code != 200:
1438 #TODO: get error
1439 print 'vimconnector.get_image_id_from_path error getting image id from path. Error code: %d Description: %s' %(vim_response.status_code, vim_response.json())
1440 return -vim_response.status_code, "Error getting image id from path"
1441
1442 res,image = self._format_in(vim_response, get_images_response_schema)
1443 if not res:
1444 print "vimconnector.get_image_id_from_path error"
1445 return -vimconn.HTTP_Bad_Request, image
1446 if len(image['images'])==0:
1447 return 0,"Image not found"
1448 elif len(image['images'])>1:
1449 print "vimconnector.get_image_id_from_path error. More than one images with the path %s." %(path)
1450 return -vimconn.HTTP_Internal_Server_Error,"More than one images with that path"
1451 return 1, image['images'][0]['id']
1452
1453