openmano first code upload
[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, url, url_admin=None, user=None, passwd=None,debug=True,config={}):
310 vimconn.vimconnector.__init__(self, uuid, name, tenant, url, url_admin, user, passwd, debug, config)
311
312 def _format_jsonerror(self,http_response):
313 try:
314 data = http_response.json()
315 return data["error"]["description"]
316 except:
317 return http_response.text
318
319 def _format_in(self, http_response, schema):
320 try:
321 client_data = http_response.json()
322 js_v(client_data, schema)
323 #print "Input data: ", str(client_data)
324 return True, client_data
325 except js_e.ValidationError, exc:
326 print "validate_in error, jsonschema exception ", exc.message, "at", exc.path
327 return False, ("validate_in error, jsonschema exception ", exc.message, "at", exc.path)
328
329 def _remove_extra_items(self, data, schema):
330 deleted=[]
331 if type(data) is tuple or type(data) is list:
332 for d in data:
333 a= self._remove_extra_items(d, schema['items'])
334 if a is not None: deleted.append(a)
335 elif type(data) is dict:
336 for k in data.keys():
337 if 'properties' not in schema or k not in schema['properties'].keys():
338 del data[k]
339 deleted.append(k)
340 else:
341 a = self._remove_extra_items(data[k], schema['properties'][k])
342 if a is not None: deleted.append({k:a})
343 if len(deleted) == 0: return None
344 elif len(deleted) == 1: return deleted[0]
345 else: return deleted
346
347 def new_host(self, host_data):
348 '''Adds a new host to VIM'''
349 '''Returns status code of the VIM response'''
350 print "VIMConnector: Adding a new host"
351 headers_req = {'content-type': 'application/json'}
352 payload_req = host_data
353 try:
354 vim_response = requests.post(self.url_admin+'/hosts', headers = headers_req, data=payload_req)
355 except requests.exceptions.RequestException, e:
356 print "new_host Exception: ", e.args
357 return -vimconn.HTTP_Not_Found, str(e.args[0])
358 print vim_response
359 #print vim_response.status_code
360 if vim_response.status_code == 200:
361 #print vim_response.json()
362 #print json.dumps(vim_response.json(), indent=4)
363 res,http_content = self._format_in(vim_response, new_host_response_schema)
364 #print http_content
365 if res :
366 r = self._remove_extra_items(http_content, new_host_response_schema)
367 if r is not None: print "Warning: remove extra items ", r
368 #print http_content
369 host_id = http_content['host']['id']
370 #print "Host id: ",host_id
371 return vim_response.status_code,host_id
372 else: return -vimconn.HTTP_Bad_Request,http_content
373 else:
374 #print vim_response.text
375 jsonerror = self.__format_jsonerror(vim_response)
376 text = 'Error in VIM "%s": not possible to add new host. HTTP Response: %d. Error: %s' % (self.url_admin, vim_response.status_code, jsonerror)
377 #print text
378 return -vim_response.status_code,text
379
380 def new_external_port(self, port_data):
381 '''Adds a external port to VIM'''
382 '''Returns the port identifier'''
383 print "VIMConnector: Adding a new external port"
384 headers_req = {'content-type': 'application/json'}
385 payload_req = port_data
386 try:
387 vim_response = requests.post(self.url_admin+'/ports', headers = headers_req, data=payload_req)
388 except requests.exceptions.RequestException, e:
389 print "new_external_port Exception: ", e.args
390 return -vimconn.HTTP_Not_Found, str(e.args[0])
391 print vim_response
392 #print vim_response.status_code
393 if vim_response.status_code == 200:
394 #print vim_response.json()
395 #print json.dumps(vim_response.json(), indent=4)
396 res, http_content = self.__format_in(vim_response, new_port_response_schema)
397 #print http_content
398 if res:
399 r = self._remove_extra_items(http_content, new_port_response_schema)
400 if r is not None: print "Warning: remove extra items ", r
401 #print http_content
402 port_id = http_content['port']['id']
403 print "Port id: ",port_id
404 return vim_response.status_code,port_id
405 else: return -vimconn.HTTP_Bad_Request,http_content
406 else:
407 #print vim_response.text
408 jsonerror = self._format_jsonerror(vim_response)
409 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)
410 #print text
411 return -vim_response.status_code,text
412
413 def new_external_network(self,net_name,net_type):
414 '''Adds a external network to VIM (shared)'''
415 '''Returns the network identifier'''
416 print "VIMConnector: Adding external shared network to VIM (type " + net_type + "): "+ net_name
417
418 headers_req = {'content-type': 'application/json'}
419 payload_req = '{"network":{"name": "' + net_name + '","shared":true,"type": "' + net_type + '"}}'
420 try:
421 vim_response = requests.post(self.url+'/networks', headers = headers_req, data=payload_req)
422 except requests.exceptions.RequestException, e:
423 print "new_external_network Exception: ", e.args
424 return -vimconn.HTTP_Not_Found, str(e.args[0])
425 print vim_response
426 #print vim_response.status_code
427 if vim_response.status_code == 200:
428 #print vim_response.json()
429 #print json.dumps(vim_response.json(), indent=4)
430 res,http_content = self._format_in(vim_response, new_network_response_schema)
431 #print http_content
432 if res:
433 r = self._remove_extra_items(http_content, new_network_response_schema)
434 if r is not None: print "Warning: remove extra items ", r
435 #print http_content
436 network_id = http_content['network']['id']
437 print "Network id: ",network_id
438 return vim_response.status_code,network_id
439 else: return -vimconn.HTTP_Bad_Request,http_content
440 else:
441 #print vim_response.text
442 jsonerror = self._format_jsonerror(vim_response)
443 text = 'Error in VIM "%s": not possible to add new external network. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
444 #print text
445 return -vim_response.status_code,text
446
447 def connect_port_network(self, port_id, network_id, admin=False):
448 '''Connects a external port to a network'''
449 '''Returns status code of the VIM response'''
450 print "VIMConnector: Connecting external port to network"
451
452 headers_req = {'content-type': 'application/json'}
453 payload_req = '{"port":{"network_id":"' + network_id + '"}}'
454 if admin:
455 if self.url_admin==None:
456 return -vimconn.HTTP_Unauthorized, "datacenter cannot contain admin URL"
457 url= self.url_admin
458 else:
459 url= self.url
460 try:
461 vim_response = requests.put(url +'/ports/'+port_id, headers = headers_req, data=payload_req)
462 except requests.exceptions.RequestException, e:
463 print "connect_port_network Exception: ", e.args
464 return -vimconn.HTTP_Not_Found, str(e.args[0])
465 print vim_response
466 #print vim_response.status_code
467 if vim_response.status_code == 200:
468 #print vim_response.json()
469 #print json.dumps(vim_response.json(), indent=4)
470 res,http_content = self._format_in(vim_response, new_port_response_schema)
471 #print http_content
472 if res:
473 r = self._remove_extra_items(http_content, new_port_response_schema)
474 if r is not None: print "Warning: remove extra items ", r
475 #print http_content
476 port_id = http_content['port']['id']
477 print "Port id: ",port_id
478 return vim_response.status_code,port_id
479 else: return -vimconn.HTTP_Bad_Request,http_content
480 else:
481 print vim_response.text
482 jsonerror = self._format_jsonerror(vim_response)
483 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)
484 print text
485 return -vim_response.status_code,text
486
487 def new_tenant(self,tenant_name,tenant_description):
488 '''Adds a new tenant to VIM'''
489 '''Returns the tenant identifier'''
490 print "VIMConnector: Adding a new tenant to VIM"
491 headers_req = {'content-type': 'application/json'}
492 payload_dict = {"tenant": {"name":tenant_name,"description": tenant_description, "enabled": True}}
493 payload_req = json.dumps(payload_dict)
494 #print payload_req
495
496 try:
497 vim_response = requests.post(self.url+'/tenants', headers = headers_req, data=payload_req)
498 except requests.exceptions.RequestException, e:
499 print "new_tenant Exception: ", e.args
500 return -vimconn.HTTP_Not_Found, str(e.args[0])
501 #print vim_response
502 if vim_response.status_code == 200:
503 #print vim_response.json()
504 #print json.dumps(vim_response.json(), indent=4)
505 res,http_content = self._format_in(vim_response, new_tenant_response_schema)
506 #print http_content
507 if res:
508 r = self._remove_extra_items(http_content, new_tenant_response_schema)
509 if r is not None: print "Warning: remove extra items ", r
510 #print http_content
511 tenant_id = http_content['tenant']['id']
512 #print "Tenant id: ",tenant_id
513 return vim_response.status_code,tenant_id
514 else: return -vimconn.HTTP_Bad_Request,http_content
515 else:
516 #print vim_response.text
517 jsonerror = self._format_jsonerror(vim_response)
518 text = 'Error in VIM "%s": not possible to add new tenant. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
519 #print text
520 return -vim_response.status_code,text
521
522 def delete_tenant(self,tenant_id,):
523 '''Delete a tenant from VIM'''
524 '''Returns the tenant identifier'''
525 print "VIMConnector: Deleting a tenant from VIM"
526 headers_req = {'content-type': 'application/json'}
527 try:
528 vim_response = requests.delete(self.url+'/tenants/'+tenant_id, headers = headers_req)
529 except requests.exceptions.RequestException, e:
530 print "delete_tenant Exception: ", e.args
531 return -vimconn.HTTP_Not_Found, str(e.args[0])
532 #print vim_response
533 if vim_response.status_code == 200:
534 return vim_response.status_code,tenant_id
535 else:
536 #print vim_response.text
537 jsonerror = self._format_jsonerror(vim_response)
538 text = 'Error in VIM "%s": not possible to delete tenant. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
539 #print text
540 return -vim_response.status_code,text
541
542 def new_tenant_network(self,net_name,net_type,public=False, **vim_specific):
543 '''Adds a tenant network to VIM'''
544 '''Returns the network identifier'''
545 print "vim_specific", vim_specific
546 if net_type=="bridge":
547 net_type="bridge_data"
548 print "VIMConnector: Adding a new tenant network to VIM (tenant: " + self.tenant + ", type: " + net_type + "): "+ net_name
549
550 headers_req = {'content-type': 'application/json'}
551 payload_req = {"name": net_name, "type": net_type, "tenant_id": self.tenant, "shared": public}
552 payload_req.update(vim_specific)
553 try:
554 vim_response = requests.post(self.url+'/networks', headers = headers_req, data=json.dumps({"network": payload_req}) )
555 except requests.exceptions.RequestException, e:
556 print "new_tenant_network Exception: ", e.args
557 return -vimconn.HTTP_Not_Found, str(e.args[0])
558 print vim_response
559 #print vim_response.status_code
560 if vim_response.status_code == 200:
561 #print vim_response.json()
562 #print json.dumps(vim_response.json(), indent=4)
563 res,http_content = self._format_in(vim_response, new_network_response_schema)
564 #print http_content
565 if res:
566 r = self._remove_extra_items(http_content, new_network_response_schema)
567 if r is not None: print "Warning: remove extra items ", r
568 #print http_content
569 network_id = http_content['network']['id']
570 print "Tenant Network id: ",network_id
571 return vim_response.status_code,network_id
572 else: return -vimconn.HTTP_Bad_Request,http_content
573 else:
574 #print vim_response.text
575 jsonerror = self._format_jsonerror(vim_response)
576 text = 'Error in VIM "%s": not possible to add new tenant network. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
577 #print text
578 return -vim_response.status_code,text
579
580 def get_tenant_list(self, filter_dict={}):
581 '''Obtain tenants of VIM
582 Filter_dict can be:
583 name: network name
584 id: network uuid
585 Returns the network list of dictionaries
586 '''
587 print "VIMConnector.get_tenant_list: Getting tenants from VIM (filter: " + str(filter_dict) + "): "
588 filterquery=[]
589 filterquery_text=''
590 for k,v in filter_dict.iteritems():
591 filterquery.append(str(k)+'='+str(v))
592 if len(filterquery)>0:
593 filterquery_text='?'+ '&'.join(filterquery)
594 headers_req = {'content-type': 'application/json'}
595 try:
596 print self.url+'/tenants'+filterquery_text
597 vim_response = requests.get(self.url+'/tenants'+filterquery_text, headers = headers_req)
598 except requests.exceptions.RequestException, e:
599 print "get_tenant_list Exception: ", e.args
600 return -vimconn.HTTP_Not_Found, str(e.args[0])
601 print vim_response
602 #print vim_response.status_code
603 if vim_response.status_code == 200:
604 #print vim_response.json()
605 #print json.dumps(vim_response.json(), indent=4)
606 #TODO: parse input datares,http_content = self._format_in(vim_response, new_network_response_schema)
607 #print http_content
608 return vim_response.status_code, vim_response.json()["tenants"]
609 else:
610 #print vim_response.text
611 jsonerror = self._format_jsonerror(vim_response)
612 text = 'Error in VIM "%s": not possible to get tenant list. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
613 #print text
614 return -vim_response.status_code,text
615
616 def get_network_list(self, filter_dict={}):
617 '''Obtain tenant networks of VIM
618 Filter_dict can be:
619 name: network name
620 id: network uuid
621 shared: boolean
622 tenant_id: tenant
623 admin_state_up: boolean
624 status: 'ACTIVE'
625 Returns the network list of dictionaries
626 '''
627 print "VIMConnector.get_network_list: Getting tenant network from VIM (filter: " + str(filter_dict) + "): "
628 filterquery=[]
629 filterquery_text=''
630 for k,v in filter_dict.iteritems():
631 filterquery.append(str(k)+'='+str(v))
632 if len(filterquery)>0:
633 filterquery_text='?'+ '&'.join(filterquery)
634 headers_req = {'content-type': 'application/json'}
635 try:
636 print self.url+'/networks'+filterquery_text
637 vim_response = requests.get(self.url+'/networks'+filterquery_text, headers = headers_req)
638 except requests.exceptions.RequestException, e:
639 print "get_network_list Exception: ", e.args
640 return -vimconn.HTTP_Not_Found, str(e.args[0])
641 print vim_response
642 #print vim_response.status_code
643 if vim_response.status_code == 200:
644 #print vim_response.json()
645 #print json.dumps(vim_response.json(), indent=4)
646 #TODO: parse input datares,http_content = self._format_in(vim_response, new_network_response_schema)
647 #print http_content
648 return vim_response.status_code, vim_response.json()["networks"]
649 else:
650 #print vim_response.text
651 jsonerror = self._format_jsonerror(vim_response)
652 text = 'Error in VIM "%s": not possible to get network list. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
653 #print text
654 return -vim_response.status_code,text
655
656 def get_tenant_network(self, net_id, tenant_id=None):
657 '''Obtain tenant networks of VIM'''
658 '''Returns the network information from a network id'''
659 if self.debug:
660 print "VIMconnector.get_tenant_network(): Getting tenant network %s from VIM" % net_id
661 filter_dict={"id": net_id}
662 if tenant_id:
663 filter_dict["tenant_id"] = tenant_id
664 r, net_list = self.get_network_list(filter_dict)
665 if r<0:
666 return r, net_list
667 if len(net_list)==0:
668 return -vimconn.HTTP_Not_Found, "Network '%s' not found" % net_id
669 elif len(net_list)>1:
670 return -vimconn.HTTP_Conflict, "Found more than one network with this criteria"
671 return 1, net_list[0]
672
673 def delete_tenant_network(self, net_id):
674 '''Deletes a tenant network from VIM'''
675 '''Returns the network identifier'''
676 print "VIMConnector: Deleting a new tenant network from VIM tenant: " + self.tenant + ", id: " + net_id
677
678 headers_req = {'content-type': 'application/json'}
679 try:
680 vim_response = requests.delete(self.url+'/networks/'+net_id, headers=headers_req)
681 except requests.exceptions.RequestException, e:
682 print "delete_tenant_network Exception: ", e.args
683 return -vimconn.HTTP_Not_Found, str(e.args[0])
684
685 print vim_response
686 #print vim_response.status_code
687 if vim_response.status_code == 200:
688 return vim_response.status_code,net_id
689 else:
690 #print vim_response.text
691 jsonerror = self._format_jsonerror(vim_response)
692 text = 'Error in VIM "%s": not possible to delete tenant network. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
693 #print text
694 return -vim_response.status_code,text
695
696 def refresh_tenant_network(self, net_id):
697 '''Refreshes the status of the tenant network'''
698 '''Returns: 0 if no error,
699 <0 if error'''
700 return 0
701
702 def get_tenant_flavor(self, flavor_id):
703 '''Obtain flavor details from the VIM
704 Returns the flavor dict details
705 '''
706 print "VIMConnector: Getting flavor from VIM"
707 #print "VIM URL:",self.url
708 #print "Tenant id:",self.tenant
709 #print "Flavor:",flavor_data
710 headers_req = {'content-type': 'application/json'}
711 try:
712 vim_response = requests.get(self.url+'/'+self.tenant+'/flavors/'+flavor_id, headers = headers_req)
713 except requests.exceptions.RequestException, e:
714 print "get_tenant_flavor Exception: ", e.args
715 return -vimconn.HTTP_Not_Found, str(e.args[0])
716 print vim_response
717 #print vim_response.status_code
718 if vim_response.status_code == 200:
719 #print vim_response.json()
720 #print json.dumps(vim_response.json(), indent=4)
721 res,http_content = self._format_in(vim_response, get_flavor_response_schema)
722 #print http_content
723 if res:
724 r = self._remove_extra_items(http_content, get_flavor_response_schema)
725 if r is not None: print "Warning: remove extra items ", r
726 #print http_content
727 flavor_id = http_content['flavor']['id']
728 print "Flavor id: ",flavor_id
729 return vim_response.status_code,flavor_id
730 else: return -vimconn.HTTP_Bad_Request,http_content
731
732 else:
733 #print vim_response.text
734 jsonerror = self._format_jsonerror(vim_response)
735 text = 'Error in VIM "%s": not possible to get flavor. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
736 #print text
737 return -vim_response.status_code,text
738
739 def new_tenant_flavor(self, flavor_data):
740 '''Adds a tenant flavor to VIM'''
741 '''Returns the flavor identifier'''
742 print "VIMConnector: Adding a new flavor to VIM"
743 #print "VIM URL:",self.url
744 #print "Tenant id:",self.tenant
745 #print "Flavor:",flavor_data
746 headers_req = {'content-type': 'application/json'}
747 payload_req = json.dumps({'flavor': flavor_data})
748 try:
749 vim_response = requests.post(self.url+'/'+self.tenant+'/flavors', headers = headers_req, data=payload_req)
750 except requests.exceptions.RequestException, e:
751 print "new_tenant_flavor Exception: ", e.args
752 return -vimconn.HTTP_Not_Found, str(e.args[0])
753 print vim_response
754 #print vim_response.status_code
755 if vim_response.status_code == 200:
756 #print vim_response.json()
757 #print json.dumps(vim_response.json(), indent=4)
758 res,http_content = self._format_in(vim_response, new_flavor_response_schema)
759 #print http_content
760 if res:
761 r = self._remove_extra_items(http_content, new_flavor_response_schema)
762 if r is not None: print "Warning: remove extra items ", r
763 #print http_content
764 flavor_id = http_content['flavor']['id']
765 print "Flavor id: ",flavor_id
766 return vim_response.status_code,flavor_id
767 else: return -vimconn.HTTP_Bad_Request,http_content
768
769 else:
770 #print vim_response.text
771 jsonerror = self._format_jsonerror(vim_response)
772 text = 'Error in VIM "%s": not possible to add new flavor. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
773 #print text
774 return -vim_response.status_code,text
775
776 def delete_tenant_flavor(self,flavor_id):
777 '''Deletes a tenant flavor from VIM'''
778 '''Returns the HTTP response code and a message indicating details of the success or fail'''
779 print "VIMConnector: Deleting a flavor from VIM"
780 print "VIM URL:",self.url
781 print "Tenant id:",self.tenant
782 print "Flavor id:",flavor_id
783 #headers_req = {'content-type': 'application/json'}
784 #payload_req = flavor_data
785 try:
786 vim_response = requests.delete(self.url+'/'+self.tenant+'/flavors/'+flavor_id)
787 except requests.exceptions.RequestException, e:
788 print "delete_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 result = vim_response.json()["result"]
794 return 200,result
795 else:
796 #print vim_response.text
797 jsonerror = self._format_jsonerror(vim_response)
798 text = 'Error in VIM "%s": not possible to delete flavor. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
799 #print text
800 return -vim_response.status_code,text
801
802 def new_tenant_image(self,image_dict):
803 '''
804 Adds a tenant image to VIM
805 Returns:
806 200, image-id if the image is created
807 <0, message if there is an error
808 '''
809 print "VIMConnector: Adding a new image to VIM", image_dict['location']
810 headers_req = {'content-type': 'application/json'}
811 new_image_dict={'name': image_dict['name']}
812 if 'description' in image_dict and image_dict['description'] != None:
813 new_image_dict['description'] = image_dict['description']
814 if 'metadata' in image_dict and image_dict['metadata'] != None:
815 new_image_dict['metadata'] = yaml.load(image_dict['metadata'])
816 if 'location' in image_dict and image_dict['location'] != None:
817 new_image_dict['path'] = image_dict['location']
818 payload_req = json.dumps({"image":new_image_dict})
819 url=self.url + '/' + self.tenant + '/images'
820 try:
821 vim_response = requests.post(url, headers = headers_req, data=payload_req)
822 except requests.exceptions.RequestException, e:
823 print "new_tenant_image Exception: ", e.args
824 return -vimconn.HTTP_Not_Found, str(e.args[0])
825 print vim_response
826 #print vim_response.status_code
827 if vim_response.status_code == 200:
828 #print vim_response.json()
829 #print json.dumps(vim_response.json(), indent=4)
830 res,http_content = self._format_in(vim_response, new_image_response_schema)
831 #print http_content
832 if res:
833 r = self._remove_extra_items(http_content, new_image_response_schema)
834 if r is not None: print "Warning: remove extra items ", r
835 #print http_content
836 image_id = http_content['image']['id']
837 print "Image id: ",image_id
838 return vim_response.status_code,image_id
839 else: return -vimconn.HTTP_Bad_Request,http_content
840 else:
841 #print vim_response.text
842 jsonerror = self._format_jsonerror(vim_response)
843 text = 'Error in VIM "%s": not possible to add new image. HTTP Response: %d. Error: %s' % (url, vim_response.status_code, jsonerror)
844 #print text
845 return -vim_response.status_code,text
846
847 def delete_tenant_image(self, image_id):
848 '''Deletes a tenant image from VIM'''
849 '''Returns the HTTP response code and a message indicating details of the success or fail'''
850 print "VIMConnector: Deleting an image from VIM"
851 #headers_req = {'content-type': 'application/json'}
852 #payload_req = flavor_data
853 url=self.url + '/'+ self.tenant +'/images/'+image_id
854 try:
855 vim_response = requests.delete(url)
856 except requests.exceptions.RequestException, e:
857 print "delete_tenant_image Exception url '%s': " % url, e.args
858 return -vimconn.HTTP_Not_Found, str(e.args[0])
859 print vim_response
860 print vim_response.status_code
861 if vim_response.status_code == 200:
862 result = vim_response.json()["result"]
863 return 200,result
864 else:
865 #print vim_response.text
866 jsonerror = self._format_jsonerror(vim_response)
867 text = 'Error in VIM "%s": not possible to delete image. HTTP Response: %d. Error: %s' % (url, vim_response.status_code, jsonerror)
868 #print text
869 return -vim_response.status_code,text
870
871 def new_tenant_vminstancefromJSON(self, vm_data):
872 '''Adds a VM instance to VIM'''
873 '''Returns the instance identifier'''
874 print "VIMConnector: Adding a new VM instance from JSON to VIM"
875 headers_req = {'content-type': 'application/json'}
876 payload_req = vm_data
877 try:
878 vim_response = requests.post(self.url+'/'+self.tenant+'/servers', headers = headers_req, data=payload_req)
879 except requests.exceptions.RequestException, e:
880 print "new_tenant_vminstancefromJSON Exception: ", e.args
881 return -vimconn.HTTP_Not_Found, str(e.args[0])
882 print vim_response
883 #print vim_response.status_code
884 if vim_response.status_code == 200:
885 #print vim_response.json()
886 #print json.dumps(vim_response.json(), indent=4)
887 res,http_content = self._format_in(vim_response, new_image_response_schema)
888 #print http_content
889 if res:
890 r = self._remove_extra_items(http_content, new_image_response_schema)
891 if r is not None: print "Warning: remove extra items ", r
892 #print http_content
893 vminstance_id = http_content['server']['id']
894 print "Tenant image id: ",vminstance_id
895 return vim_response.status_code,vminstance_id
896 else: return -vimconn.HTTP_Bad_Request,http_content
897 else:
898 #print vim_response.text
899 jsonerror = self._format_jsonerror(vim_response)
900 text = 'Error in VIM "%s": not possible to add new vm instance. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
901 #print text
902 return -vim_response.status_code,text
903
904 def new_tenant_vminstance(self,name,description,start,image_id,flavor_id,net_list):
905 '''Adds a VM instance to VIM
906 Params:
907 start: indicates if VM must start or boot in pause mode. Ignored
908 image_id,flavor_id: image and flavor uuid
909 net_list: list of interfaces, each one is a dictionary with:
910 name:
911 net_id: network uuid to connect
912 vpci: virtual vcpi to assign
913 model: interface model, virtio, e2000, ...
914 mac_address:
915 use: 'data', 'bridge', 'mgmt'
916 type: 'virtual', 'PF', 'VF', 'VFnotShared'
917 vim_id: filled/added by this function
918 #TODO ip, security groups
919 Returns >=0, the instance identifier
920 <0, error_text
921 '''
922 print "VIMConnector: Adding a new VM instance to VIM"
923 headers_req = {'content-type': 'application/json'}
924
925 # net_list = []
926 # for k,v in net_dict.items():
927 # print k,v
928 # net_list.append('{"name":"' + k + '", "uuid":"' + v + '"}')
929 # net_list_string = ', '.join(net_list)
930 virtio_net_list=[]
931 for net in net_list:
932 if not net.get("net_id"):
933 continue
934 net_dict={'uuid': net["net_id"]}
935 if net.get("type"): net_dict["type"] = net["type"]
936 if net.get("name"): net_dict["name"] = net["name"]
937 if net.get("vpci"): net_dict["vpci"] = net["vpci"]
938 if net.get("model"): net_dict["model"] = net["model"]
939 if net.get("mac_address"): net_dict["mac_address"] = net["mac_address"]
940 virtio_net_list.append(net_dict)
941 payload_dict={ "name": name,
942 "description": description,
943 "imageRef": image_id,
944 "flavorRef": flavor_id,
945 "networks": virtio_net_list
946 }
947 if start != None:
948 payload_dict["start"] = start
949 payload_req = json.dumps({"server": payload_dict})
950 print self.url+'/'+self.tenant+'/servers'+payload_req
951 try:
952 vim_response = requests.post(self.url+'/'+self.tenant+'/servers', headers = headers_req, data=payload_req)
953 except requests.exceptions.RequestException, e:
954 print "new_tenant_vminstance Exception: ", e.args
955 return -vimconn.HTTP_Not_Found, str(e.args[0])
956 print vim_response
957 #print vim_response.status_code
958 if vim_response.status_code != 200:
959 print vim_response.text
960 jsonerror = self._format_jsonerror(vim_response)
961 text = 'Error in VIM "%s": not possible to add new vm instance. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
962 #print text
963 return -vim_response.status_code,text
964 #ok
965 print vim_response.json()
966 print json.dumps(vim_response.json(), indent=4)
967 res,http_content = self._format_in(vim_response, new_vminstance_response_schema)
968 #print http_content
969 if not res:
970 return -vimconn.HTTP_Bad_Request,http_content
971 #r = self._remove_extra_items(http_content, new_vminstance_response_schema)
972 #if r is not None: print "Warning: remove extra items ", r
973 vminstance_id = http_content['server']['id']
974 print json.dumps(http_content, indent=4)
975 #connect data plane interfaces to network
976 for net in net_list:
977 if net["type"]=="virtual":
978 if not net.get("net_id"):
979 continue
980 for iface in http_content['server']['networks']:
981 if "name" in net:
982 if net["name"]==iface["name"]:
983 net["vim_id"] = iface['iface_id']
984 break
985 elif "net_id" in net:
986 if net["net_id"]==iface["net_id"]:
987 net["vim_id"] = iface['iface_id']
988 break
989 else: #dataplane
990 for numa in http_content['server'].get('extended',{}).get('numas',() ):
991 for iface in numa.get('interfaces',() ):
992 if net['name'] == iface['name']:
993 net['vim_id'] = iface['iface_id']
994 #Code bellow is not needed, current openvim connect dataplane interfaces
995 #if net.get("net_id"):
996 ##connect dataplane interface
997 # result, port_id = self.connect_port_network(iface['iface_id'], net["net_id"])
998 # if result < 0:
999 # error_text = "Error attaching port %s to network %s: %s." % (iface['iface_id'], net["net_id"], port_id)
1000 # print "new_tenant_vminstance: " + error_text
1001 # self.delete_tenant_vminstance(vminstance_id)
1002 # return result, error_text
1003 break
1004
1005 print "VM instance id: ",vminstance_id
1006 return vim_response.status_code,vminstance_id
1007
1008 def get_tenant_vminstance(self,vm_id):
1009 '''Returns the VM instance information from VIM'''
1010 print "VIMConnector: Getting tenant VM instance information from VIM"
1011 headers_req = {'content-type': 'application/json'}
1012
1013 url = self.url+'/'+self.tenant+'/servers/'+vm_id
1014 print url
1015 try:
1016 vim_response = requests.get(url, headers = headers_req)
1017 except requests.exceptions.RequestException, e:
1018 print "get_tenant_vminstance Exception: ", e.args
1019 return -vimconn.HTTP_Not_Found, str(e.args[0])
1020 print vim_response
1021 #print vim_response.status_code
1022 if vim_response.status_code == 200:
1023 print vim_response.json()
1024 print json.dumps(vim_response.json(), indent=4)
1025 res,http_content = self._format_in(vim_response, new_vminstance_response_schema)
1026 #print http_content
1027 if res:
1028 print json.dumps(http_content, indent=4)
1029 return vim_response.status_code,http_content
1030 else: return -vimconn.HTTP_Bad_Request,http_content
1031 else:
1032 print vim_response.text
1033 jsonerror = self._format_jsonerror(vim_response)
1034 text = 'Error in VIM "%s": not possible to get vm instance. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
1035 #print text
1036 return -vim_response.status_code,text
1037
1038 def delete_tenant_vminstance(self, vm_id):
1039 '''Removes a VM instance from VIM'''
1040 '''Returns the instance identifier'''
1041 print "VIMConnector: Delete a VM instance from VIM " + vm_id
1042 headers_req = {'content-type': 'application/json'}
1043
1044 try:
1045 vim_response = requests.delete(self.url+'/'+self.tenant+'/servers/'+vm_id, headers = headers_req)
1046 except requests.exceptions.RequestException, e:
1047 print "delete_tenant_vminstance Exception: ", e.args
1048 return -vimconn.HTTP_Not_Found, str(e.args[0])
1049
1050 #print vim_response.status_code
1051 if vim_response.status_code == 200:
1052 print json.dumps(vim_response.json(), indent=4)
1053 return vim_response.status_code, vm_id
1054 else:
1055 #print vim_response.text
1056 jsonerror = self._format_jsonerror(vim_response)
1057 text = 'Error in VIM "%s": not possible to delete vm instance. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
1058 #print text
1059 return -vim_response.status_code, text
1060
1061 def refresh_tenant_vms_and_nets(self, vmDict, netDict):
1062 '''Refreshes the status of the dictionaries of VM instances and nets passed as arguments. It modifies the dictionaries'''
1063 '''Returns:
1064 - result: 0 if all elements could be refreshed (even if its status didn't change)
1065 n>0, the number of elements that couldn't be refreshed,
1066 <0 if error (foreseen)
1067 - error_msg: text with reference to possible errors
1068 '''
1069 #vms_refreshed = []
1070 #nets_refreshed = []
1071 vms_unrefreshed = []
1072 nets_unrefreshed = []
1073 for vm_id in vmDict:
1074 vmDict[vm_id]={'error_msg':None, 'vim_info':None}
1075 print "VIMConnector refresh_tenant_vms and nets: Getting tenant VM instance information from VIM"
1076 headers_req = {'content-type': 'application/json'}
1077
1078 url = self.url+'/'+self.tenant+'/servers/'+ vm_id
1079 print url
1080 try:
1081 vim_response = requests.get(url, headers = headers_req)
1082 except requests.exceptions.RequestException, e:
1083 print "VIMConnector refresh_tenant_elements. Exception: ", e.args
1084 vmDict[vm_id]['status'] = "VIM_ERROR"
1085 vmDict[vm_id]['error_msg'] = str(e)
1086 vms_unrefreshed.append(vm_id)
1087 continue
1088 #print vim_response
1089 #print vim_response.status_code
1090 if vim_response.status_code == 200:
1091 #print vim_response.json()
1092 #print json.dumps(vim_response.json(), indent=4)
1093 management_ip = False
1094 res,http_content = self._format_in(vim_response, new_vminstance_response_schema)
1095 if res:
1096 try:
1097 vmDict[vm_id]['status'] = vmStatus2manoFormat[ http_content['server']['status'] ]
1098 if http_content['server'].get('last_error'):
1099 vmDict[vm_id]['error_msg'] = http_content['server']['last_error']
1100 vmDict[vm_id]["vim_info"] = yaml.safe_dump(http_content['server'])
1101 vmDict[vm_id]["interfaces"]=[]
1102 #get interfaces info
1103 url2 = self.url+'/ports?device_id='+ vm_id
1104 try:
1105 vim_response2 = requests.get(url2, headers = headers_req)
1106 if vim_response.status_code == 200:
1107 client_data = vim_response2.json()
1108 for port in client_data.get("ports"):
1109 print "VACAport", port
1110 interface={}
1111 interface['vim_info'] = yaml.safe_dump(port)
1112 interface["mac_address"] = port.get("mac_address")
1113 interface["vim_net_id"] = port["network_id"]
1114 interface["vim_interface_id"] = port["id"]
1115 interface["ip_address"] = port.get("ip_address")
1116 if interface["ip_address"]:
1117 management_ip = True
1118 if interface["ip_address"] == "0.0.0.0":
1119 interface["ip_address"] = None
1120 vmDict[vm_id]["interfaces"].append(interface)
1121
1122 except Exception as e:
1123 print "VIMConnector refresh_tenant_elements. Port get %s: %s", (type(e).__name__, (str(e) if len(e.args)==0 else str(e.args[0])))
1124
1125 if vmDict[vm_id]['status'] == "ACTIVE" and not management_ip:
1126 vmDict[vm_id]['status'] = "ACTIVE:NoMgmtIP"
1127
1128 except Exception as e:
1129 vmDict[vm_id]['status'] = "VIM_ERROR"
1130 vmDict[vm_id]['error_msg'] = str(e)
1131 vms_unrefreshed.append(vm_id)
1132 else:
1133 vmDict[vm_id]['status'] = "VIM_ERROR"
1134 vmDict[vm_id]['error_msg'] = str(http_content)
1135 vms_unrefreshed.append(vm_id)
1136 else:
1137 #print vim_response.text
1138 jsonerror = self._format_jsonerror(vim_response)
1139 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)
1140 if vim_response.status_code == 404: # HTTP_Not_Found
1141 vmDict[vm_id]['status'] = "DELETED"
1142 else:
1143 vmDict[vm_id]['status'] = "VIM_ERROR"
1144 vmDict[vm_id]['error_msg'] = jsonerror
1145 vms_unrefreshed.append(vm_id)
1146
1147 #print "VMs refreshed: %s" % str(vms_refreshed)
1148 for net_id in netDict:
1149 netDict[net_id] = {'error_msg':None, 'vim_info':None}
1150 print "VIMConnector refresh_tenant_vms_and_nets: Getting tenant network from VIM (tenant: " + str(self.tenant) + "): "
1151 headers_req = {'content-type': 'application/json'}
1152 r,c = self.get_tenant_network(net_id)
1153 if r<0:
1154 print "VIMconnector refresh_tenant_network. Error getting net_id '%s' status: %s" % (net_id, c)
1155 if r==-vimconn.HTTP_Not_Found:
1156 netDict[net_id]['status'] = "DELETED" #TODO check exit status
1157 else:
1158 netDict[net_id]['status'] = "VIM_ERROR"
1159 netDict[net_id]['error_msg'] = c
1160 nets_unrefreshed.append(net_id)
1161 else:
1162 try:
1163 net_status = netStatus2manoFormat[ c['status'] ]
1164 if net_status == "ACTIVE" and not c['admin_state_up']:
1165 net_status = "DOWN"
1166 netDict[net_id]['status'] = net_status
1167 if c.get('last_error'):
1168 netDict[net_id]['error_msg'] = c['last_error']
1169 netDict[net_id]["vim_info"] = yaml.safe_dump(c)
1170 except Exception as e:
1171 netDict[net_id]['status'] = "VIM_ERROR"
1172 netDict[net_id]['error_msg'] = str(e)
1173 nets_unrefreshed.append(net_id)
1174
1175 #print "Nets refreshed: %s" % str(nets_refreshed)
1176
1177 error_msg=""
1178 if len(vms_unrefreshed)+len(nets_unrefreshed)>0:
1179 error_msg += "VMs unrefreshed: " + str(vms_unrefreshed) + "; nets unrefreshed: " + str(nets_unrefreshed)
1180 print error_msg
1181
1182 #return len(vms_unrefreshed)+len(nets_unrefreshed), error_msg, vms_refreshed, nets_refreshed
1183 return len(vms_unrefreshed)+len(nets_unrefreshed), error_msg
1184
1185 def action_tenant_vminstance(self, vm_id, action_dict):
1186 '''Send and action over a VM instance from VIM'''
1187 '''Returns the status'''
1188 print "VIMConnector: Action over VM instance from VIM " + vm_id
1189 headers_req = {'content-type': 'application/json'}
1190
1191 try:
1192 if "console" in action_dict:
1193 return -vimconn.HTTP_Service_Unavailable, "getting console is not available at openvim"
1194
1195 vim_response = requests.post(self.url+'/'+self.tenant+'/servers/'+vm_id+"/action", headers = headers_req, data=json.dumps(action_dict) )
1196 except requests.exceptions.RequestException, e:
1197 print "action_tenant_vminstance Exception: ", e.args
1198 return -vimconn.HTTP_Not_Found, str(e.args[0])
1199
1200 #print vim_response.status_code
1201 if vim_response.status_code == 200:
1202 #print "vimconnector.action_tenant_vminstance():", json.dumps(vim_response.json(), indent=4)
1203 return vim_response.status_code, vm_id
1204 else:
1205 #print vim_response.text
1206 jsonerror = self._format_jsonerror(vim_response)
1207 text = 'Error in VIM "%s": action over vm instance. HTTP Response: %d. Error: %s' % (self.url, vim_response.status_code, jsonerror)
1208 #print text
1209 return vim_response.status_code, text
1210
1211 def host_vim2gui(self, host, server_dict):
1212 '''Transform host dictionary from VIM format to GUI format,
1213 and append to the server_dict
1214 '''
1215 if type(server_dict) is not dict:
1216 print 'vimconnector.host_vim2gui() ERROR, param server_dict must be a dictionary'
1217 return
1218 RAD={}
1219 occupation={}
1220 for numa in host['host']['numas']:
1221 RAD_item={}
1222 occupation_item={}
1223 #memory
1224 RAD_item['memory']={'size': str(numa['memory'])+'GB', 'eligible': str(numa['hugepages'])+'GB'}
1225 occupation_item['memory']= str(numa['hugepages_consumed'])+'GB'
1226 #cpus
1227 RAD_item['cpus']={}
1228 RAD_item['cpus']['cores'] = []
1229 RAD_item['cpus']['eligible_cores'] = []
1230 occupation_item['cores']=[]
1231 for _ in range(0, len(numa['cores']) / 2):
1232 RAD_item['cpus']['cores'].append( [] )
1233 for core in numa['cores']:
1234 RAD_item['cpus']['cores'][core['core_id']].append(core['thread_id'])
1235 if not 'status' in core: RAD_item['cpus']['eligible_cores'].append(core['thread_id'])
1236 if 'instance_id' in core: occupation_item['cores'].append(core['thread_id'])
1237 #ports
1238 RAD_item['ports']={}
1239 occupation_item['ports']={}
1240 for iface in numa['interfaces']:
1241 RAD_item['ports'][ iface['pci'] ] = 'speed:'+str(iface['Mbps'])+'M'
1242 occupation_item['ports'][ iface['pci'] ] = { 'occupied': str(100*iface['Mbps_consumed'] / iface['Mbps']) + "%" }
1243
1244 RAD[ numa['numa_socket'] ] = RAD_item
1245 occupation[ numa['numa_socket'] ] = occupation_item
1246 server_dict[ host['host']['name'] ] = {'RAD':RAD, 'occupation':occupation}
1247
1248 def get_hosts_info(self):
1249 '''Get the information of deployed hosts
1250 Returns the hosts content'''
1251 #obtain hosts list
1252 url=self.url+'/hosts'
1253 try:
1254 vim_response = requests.get(url)
1255 except requests.exceptions.RequestException, e:
1256 print "get_hosts_info Exception: ", e.args
1257 return -vimconn.HTTP_Not_Found, str(e.args[0])
1258 print "vim get", url, "response:", vim_response.status_code, vim_response.json()
1259 #print vim_response.status_code
1260 #print json.dumps(vim_response.json(), indent=4)
1261 if vim_response.status_code != 200:
1262 #TODO: get error
1263 print 'vimconnector.get_hosts_info error getting host list %d %s' %(vim_response.status_code, vim_response.json())
1264 return -vim_response.status_code, "Error getting host list"
1265
1266 res,hosts = self._format_in(vim_response, get_hosts_response_schema)
1267
1268 if res==False:
1269 print "vimconnector.get_hosts_info error parsing GET HOSTS vim response", hosts
1270 return vimconn.HTTP_Internal_Server_Error, hosts
1271 #obtain hosts details
1272 hosts_dict={}
1273 for host in hosts['hosts']:
1274 url=self.url+'/hosts/'+host['id']
1275 try:
1276 vim_response = requests.get(url)
1277 except requests.exceptions.RequestException, e:
1278 print "get_hosts_info Exception: ", e.args
1279 return -vimconn.HTTP_Not_Found, str(e.args[0])
1280 print "vim get", url, "response:", vim_response.status_code, vim_response.json()
1281 if vim_response.status_code != 200:
1282 print 'vimconnector.get_hosts_info error getting detailed host %d %s' %(vim_response.status_code, vim_response.json())
1283 continue
1284 res,host_detail = self._format_in(vim_response, get_host_detail_response_schema)
1285 if res==False:
1286 print "vimconnector.get_hosts_info error parsing GET HOSTS/%s vim response" % host['id'], host_detail
1287 continue
1288 #print 'host id '+host['id'], json.dumps(host_detail, indent=4)
1289 self.host_vim2gui(host_detail, hosts_dict)
1290 return 200, hosts_dict
1291
1292 def get_hosts(self, vim_tenant):
1293 '''Get the hosts and deployed instances
1294 Returns the hosts content'''
1295 #obtain hosts list
1296 url=self.url+'/hosts'
1297 try:
1298 vim_response = requests.get(url)
1299 except requests.exceptions.RequestException, e:
1300 print "get_hosts Exception: ", e.args
1301 return -vimconn.HTTP_Not_Found, str(e.args[0])
1302 print "vim get", url, "response:", vim_response.status_code, vim_response.json()
1303 #print vim_response.status_code
1304 #print json.dumps(vim_response.json(), indent=4)
1305 if vim_response.status_code != 200:
1306 #TODO: get error
1307 print 'vimconnector.get_hosts error getting host list %d %s' %(vim_response.status_code, vim_response.json())
1308 return -vim_response.status_code, "Error getting host list"
1309
1310 res,hosts = self._format_in(vim_response, get_hosts_response_schema)
1311
1312 if res==False:
1313 print "vimconnector.get_host error parsing GET HOSTS vim response", hosts
1314 return vimconn.HTTP_Internal_Server_Error, hosts
1315 #obtain instances from hosts
1316 for host in hosts['hosts']:
1317 url=self.url+'/' + vim_tenant + '/servers?hostId='+host['id']
1318 try:
1319 vim_response = requests.get(url)
1320 except requests.exceptions.RequestException, e:
1321 print "get_hosts Exception: ", e.args
1322 return -vimconn.HTTP_Not_Found, str(e.args[0])
1323 print "vim get", url, "response:", vim_response.status_code, vim_response.json()
1324 if vim_response.status_code != 200:
1325 print 'vimconnector.get_hosts error getting instances at host %d %s' %(vim_response.status_code, vim_response.json())
1326 continue
1327 res,servers = self._format_in(vim_response, get_server_response_schema)
1328 if res==False:
1329 print "vimconnector.get_host error parsing GET SERVERS/%s vim response" % host['id'], servers
1330 continue
1331 #print 'host id '+host['id'], json.dumps(host_detail, indent=4)
1332 host['instances'] = servers['servers']
1333 return 200, hosts['hosts']
1334
1335 def get_processor_rankings(self):
1336 '''Get the processor rankings in the VIM database'''
1337 url=self.url+'/processor_ranking'
1338 try:
1339 vim_response = requests.get(url)
1340 except requests.exceptions.RequestException, e:
1341 print "get_processor_rankings 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 #print vim_response.status_code
1345 #print json.dumps(vim_response.json(), indent=4)
1346 if vim_response.status_code != 200:
1347 #TODO: get error
1348 print 'vimconnector.get_processor_rankings error getting processor rankings %d %s' %(vim_response.status_code, vim_response.json())
1349 return -vim_response.status_code, "Error getting processor rankings"
1350
1351 res,rankings = self._format_in(vim_response, get_processor_rankings_response_schema)
1352 return res, rankings['rankings']
1353
1354 def get_image_id_from_path(self, path):
1355 '''Get the image id from image path in the VIM database'''
1356 '''Returns:
1357 0,"Image not found" if there are no images with that path
1358 1,image-id if there is one image with that path
1359 <0,message if there was an error (Image not found, error contacting VIM, more than 1 image with that path, etc.)
1360 '''
1361 url=self.url + '/' + self.tenant + '/images?path='+path
1362 try:
1363 vim_response = requests.get(url)
1364 except requests.exceptions.RequestException, e:
1365 print "get_image_id_from_path url='%s'Exception: '%s'" % (url, str(e.args))
1366 return -vimconn.HTTP_Not_Found, str(e.args[0])
1367 print "vim get_image_id_from_path", url, "response:", vim_response.status_code, vim_response.json()
1368 #print vim_response.status_code
1369 #print json.dumps(vim_response.json(), indent=4)
1370 if vim_response.status_code != 200:
1371 #TODO: get error
1372 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())
1373 return -vim_response.status_code, "Error getting image id from path"
1374
1375 res,image = self._format_in(vim_response, get_images_response_schema)
1376 if not res:
1377 print "vimconnector.get_image_id_from_path error"
1378 return -vimconn.HTTP_Bad_Request, image
1379 if len(image['images'])==0:
1380 return 0,"Image not found"
1381 elif len(image['images'])>1:
1382 print "vimconnector.get_image_id_from_path error. More than one images with the path %s." %(path)
1383 return -vimconn.HTTP_Internal_Server_Error,"More than one images with that path"
1384 return 1, image['images'][0]['id']
1385
1386