blob: ad06dc8bc55d994588ec0c8a5aad955acad9b4fa [file] [log] [blame]
tierno7edb6752016-03-21 17:37:52 +01001# -*- 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'''
25vimconn implement an Abstract class for the vim connector plugins
26 with the definition of the method to be implemented.
27'''
28__author__="Alfonso Tierno"
29__date__ ="$16-oct-2015 11:09:29$"
30
tiernoae4a8d12016-07-08 12:30:39 +020031import logging
32
tierno7edb6752016-03-21 17:37:52 +010033#Error variables
34HTTP_Bad_Request = 400
35HTTP_Unauthorized = 401
36HTTP_Not_Found = 404
37HTTP_Method_Not_Allowed = 405
38HTTP_Request_Timeout = 408
39HTTP_Conflict = 409
tiernoae4a8d12016-07-08 12:30:39 +020040HTTP_Not_Implemented = 501
tierno7edb6752016-03-21 17:37:52 +010041HTTP_Service_Unavailable = 503
42HTTP_Internal_Server_Error = 500
43
tiernoae4a8d12016-07-08 12:30:39 +020044class vimconnException(Exception):
45 '''Common and base class Exception for all vimconnector exceptions'''
46 def __init__(self, message, http_code=HTTP_Bad_Request):
47 Exception.__init__(self, message)
48 self.http_code = http_code
49
50class vimconnConnectionException(vimconnException):
51 '''Connectivity error with the VIM'''
52 def __init__(self, message, http_code=HTTP_Service_Unavailable):
53 vimconnException.__init__(self, message, http_code)
54
55class vimconnUnexpectedResponse(vimconnException):
56 '''Get an wrong response from VIM'''
57 def __init__(self, message, http_code=HTTP_Service_Unavailable):
58 vimconnException.__init__(self, message, http_code)
59
60class vimconnAuthException(vimconnException):
61 '''Invalid credentials or authorization to perform this action over the VIM'''
62 def __init__(self, message, http_code=HTTP_Unauthorized):
63 vimconnException.__init__(self, message, http_code)
64
65class vimconnNotFoundException(vimconnException):
66 '''The item is not found at VIM'''
67 def __init__(self, message, http_code=HTTP_Not_Found):
68 vimconnException.__init__(self, message, http_code)
69
70class vimconnConflictException(vimconnException):
71 '''There is a conflict, e.g. more item found than one'''
72 def __init__(self, message, http_code=HTTP_Conflict):
73 vimconnException.__init__(self, message, http_code)
74
75class vimconnNotImplemented(vimconnException):
76 '''The method is not implemented by the connected'''
77 def __init__(self, message, http_code=HTTP_Not_Implemented):
78 vimconnException.__init__(self, message, http_code)
tierno7edb6752016-03-21 17:37:52 +010079
80class vimconnector():
81 '''Abstract base class for all the VIM connector plugins
tiernoae4a8d12016-07-08 12:30:39 +020082 These plugins must implement a vimconnector class derived from this
tierno7edb6752016-03-21 17:37:52 +010083 and all these methods
84 '''
tiernofe789902016-09-29 14:20:44 +000085 def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None, config={}):
tiernofb1987b2016-11-15 17:35:06 +000086 """Constructor of VIM
87 "uuid": id asigned to this VIM
88 "name": name assigned to this VIM, can be used for logging
89 "tenant_id", tenant_name: VIM tenant to be used
90 "url_admin": optional, url used for administrative tasks
91 "user", "passwd": credentials of the VIM user
92 "log_level": if must use a different log_level than the general one
93 "config": dictionary with extra VIM information. This contains a consolidate version of general VIM config at create
94 and particular VIM config at attach
95 Returns can raise an exception if some check is done and fails
96 """
tierno7edb6752016-03-21 17:37:52 +010097 self.id = uuid
98 self.name = name
99 self.url = url
100 self.url_admin = url_admin
tierno392f2852016-05-13 12:28:55 +0200101 self.tenant_id = tenant_id
102 self.tenant_name = tenant_name
tierno7edb6752016-03-21 17:37:52 +0100103 self.user = user
104 self.passwd = passwd
105 self.config = config
tierno73ad9e42016-09-12 18:11:11 +0200106 self.logger = logging.getLogger('openmano.vim')
tiernofe789902016-09-29 14:20:44 +0000107 if log_level:
108 self.logger.setLevel( getattr(logging, log_level) )
tiernoae4a8d12016-07-08 12:30:39 +0200109 if not self.url_admin: #try to use normal url
110 self.url_admin = self.url
tierno7edb6752016-03-21 17:37:52 +0100111
112 def __getitem__(self,index):
tierno392f2852016-05-13 12:28:55 +0200113 if index=='tenant_id':
114 return self.tenant_id
115 if index=='tenant_name':
116 return self.tenant_name
tierno7edb6752016-03-21 17:37:52 +0100117 elif index=='id':
118 return self.id
119 elif index=='name':
120 return self.name
121 elif index=='user':
122 return self.user
123 elif index=='passwd':
124 return self.passwd
125 elif index=='url':
126 return self.url
127 elif index=='url_admin':
128 return self.url_admin
129 elif index=="config":
130 return self.config
131 else:
132 raise KeyError("Invalid key '%s'" %str(index))
133
134 def __setitem__(self,index, value):
tierno392f2852016-05-13 12:28:55 +0200135 if index=='tenant_id':
136 self.tenant_id = value
137 if index=='tenant_name':
138 self.tenant_name = value
tierno7edb6752016-03-21 17:37:52 +0100139 elif index=='id':
140 self.id = value
141 elif index=='name':
142 self.name = value
143 elif index=='user':
144 self.user = value
145 elif index=='passwd':
146 self.passwd = value
147 elif index=='url':
148 self.url = value
149 elif index=='url_admin':
150 self.url_admin = value
151 else:
152 raise KeyError("Invalid key '%s'" %str(index))
tierno7edb6752016-03-21 17:37:52 +0100153
154 def new_tenant(self,tenant_name,tenant_description):
tiernofb1987b2016-11-15 17:35:06 +0000155 """Adds a new tenant to VIM with this name and description, this is done using admin_url if provided
156 "tenant_name": string max lenght 64
157 "tenant_description": string max length 256
158 returns the tenant identifier or raise exception
159 """
tiernoae4a8d12016-07-08 12:30:39 +0200160 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100161
162 def delete_tenant(self,tenant_id,):
tiernofb1987b2016-11-15 17:35:06 +0000163 """Delete a tenant from VIM
164 tenant_id: returned VIM tenant_id on "new_tenant"
165 Returns None on success. Raises and exception of failure. If tenant is not found raises vimconnNotFoundException
166 """
tiernoae4a8d12016-07-08 12:30:39 +0200167 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100168
tiernoae4a8d12016-07-08 12:30:39 +0200169 def get_tenant_list(self, filter_dict={}):
170 '''Obtain tenants of VIM
tiernofb1987b2016-11-15 17:35:06 +0000171 filter_dict dictionary that can contain the following keys:
tiernoae4a8d12016-07-08 12:30:39 +0200172 name: filter by tenant name
173 id: filter by tenant uuid/id
174 <other VIM specific>
tiernofb1987b2016-11-15 17:35:06 +0000175 Returns the tenant list of dictionaries, and empty list if no tenant match all the filers:
tiernoae4a8d12016-07-08 12:30:39 +0200176 [{'name':'<name>, 'id':'<id>, ...}, ...]
177 '''
178 raise vimconnNotImplemented( "Should have implemented this" )
179
garciadeblas9f8456e2016-09-05 05:02:59 +0200180 def new_network(self,net_name, net_type, ip_profile=None, shared=False):
tiernofb1987b2016-11-15 17:35:06 +0000181 """Adds a tenant network to VIM
garciadeblas9f8456e2016-09-05 05:02:59 +0200182 net_name is the name
183 net_type can be 'bridge','data'.'ptp'. TODO: this need to be revised
tiernofb1987b2016-11-15 17:35:06 +0000184 ip_profile is a dict containing the IP parameters of the network
185 "ip-version": {"type":"string", "enum":["IPv4","IPv6"]},
186 "subnet-address": ip_prefix_schema,
187 "gateway-address": ip_schema,
188 "dns-address": ip_schema,
189 "dhcp": dhcp_schema
190
tiernoae4a8d12016-07-08 12:30:39 +0200191 shared is a boolean
tiernofb1987b2016-11-15 17:35:06 +0000192 Returns the network identifier on success or raises and exeption on failure
193 """
tiernoae4a8d12016-07-08 12:30:39 +0200194 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100195
196 def get_network_list(self, filter_dict={}):
197 '''Obtain tenant networks of VIM
198 Filter_dict can be:
199 name: network name
200 id: network uuid
201 shared: boolean
202 tenant_id: tenant
203 admin_state_up: boolean
204 status: 'ACTIVE'
tiernoae4a8d12016-07-08 12:30:39 +0200205 Returns the network list of dictionaries:
206 [{<the fields at Filter_dict plus some VIM specific>}, ...]
207 List can be empty
tierno7edb6752016-03-21 17:37:52 +0100208 '''
tiernoae4a8d12016-07-08 12:30:39 +0200209 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100210
tiernoae4a8d12016-07-08 12:30:39 +0200211 def get_network(self, net_id):
212 '''Obtain network details of net_id VIM network'
213 Return a dict with the fields at filter_dict (see get_network_list) plus some VIM specific>}, ...]'''
214 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100215
tiernoae4a8d12016-07-08 12:30:39 +0200216 def delete_network(self, net_id):
217 '''Deletes a tenant network from VIM, provide the network id.
218 Returns the network identifier or raise an exception'''
219 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100220
tiernoae4a8d12016-07-08 12:30:39 +0200221 def refresh_nets_status(self, net_list):
222 '''Get the status of the networks
223 Params: the list of network identifiers
224 Returns a dictionary with:
225 net_id: #VIM id of this network
226 status: #Mandatory. Text with one of:
227 # DELETED (not found at vim)
228 # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
229 # OTHER (Vim reported other status not understood)
230 # ERROR (VIM indicates an ERROR status)
231 # ACTIVE, INACTIVE, DOWN (admin down),
232 # BUILD (on building process)
233 #
234 error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
235 vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
tierno7edb6752016-03-21 17:37:52 +0100236
tiernoae4a8d12016-07-08 12:30:39 +0200237 '''
238 raise vimconnNotImplemented( "Should have implemented this" )
239
240 def get_flavor(self, flavor_id):
tierno7edb6752016-03-21 17:37:52 +0100241 '''Obtain flavor details from the VIM
tiernoae4a8d12016-07-08 12:30:39 +0200242 Returns the flavor dict details {'id':<>, 'name':<>, other vim specific } #TODO to concrete
tierno7edb6752016-03-21 17:37:52 +0100243 '''
tiernoae4a8d12016-07-08 12:30:39 +0200244 raise vimconnNotImplemented( "Should have implemented this" )
tiernocf157a82017-01-30 14:07:06 +0100245
246 def get_flavor_id_from_data(self, flavor_dict):
247 """Obtain flavor id that match the flavor description
248 Returns the flavor_id or raises a vimconnNotFoundException
249 """
250 raise vimconnNotImplemented( "Should have implemented this" )
251
tiernoae4a8d12016-07-08 12:30:39 +0200252 def new_flavor(self, flavor_data):
253 '''Adds a tenant flavor to VIM
254 flavor_data contains a dictionary with information, keys:
255 name: flavor name
256 ram: memory (cloud type) in MBytes
257 vpcus: cpus (cloud type)
258 extended: EPA parameters
259 - numas: #items requested in same NUMA
260 memory: number of 1G huge pages memory
261 paired-threads|cores|threads: number of paired hyperthreads, complete cores OR individual threads
262 interfaces: # passthrough(PT) or SRIOV interfaces attached to this numa
263 - name: interface name
264 dedicated: yes|no|yes:sriov; for PT, SRIOV or only one SRIOV for the physical NIC
265 bandwidth: X Gbps; requested guarantee bandwidth
266 vpci: requested virtual PCI address
267 disk: disk size
268 is_public:
269
270
271
272 #TODO to concrete
273 Returns the flavor identifier'''
274 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100275
tiernoae4a8d12016-07-08 12:30:39 +0200276 def delete_flavor(self, flavor_id):
277 '''Deletes a tenant flavor from VIM identify by its id
278 Returns the used id or raise an exception'''
279 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100280
tiernoae4a8d12016-07-08 12:30:39 +0200281 def new_image(self,image_dict):
tierno7edb6752016-03-21 17:37:52 +0100282 '''
283 Adds a tenant image to VIM
284 Returns:
285 200, image-id if the image is created
286 <0, message if there is an error
287 '''
tiernoae4a8d12016-07-08 12:30:39 +0200288 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100289
tiernoae4a8d12016-07-08 12:30:39 +0200290 def delete_image(self, image_id):
tierno7edb6752016-03-21 17:37:52 +0100291 '''Deletes a tenant image from VIM'''
292 '''Returns the HTTP response code and a message indicating details of the success or fail'''
tiernoae4a8d12016-07-08 12:30:39 +0200293 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100294
tiernoae4a8d12016-07-08 12:30:39 +0200295 def get_image_id_from_path(self, path):
tiernocf157a82017-01-30 14:07:06 +0100296 """Get the image id from image path in the VIM database.
297 Returns the image_id or raises a vimconnNotFoundException
298 """
tiernoae4a8d12016-07-08 12:30:39 +0200299 raise vimconnNotImplemented( "Should have implemented this" )
300
garciadeblasb69fa9f2016-09-28 12:04:10 +0200301 def get_image_list(self, filter_dict={}):
302 '''Obtain tenant images from VIM
303 Filter_dict can be:
304 name: image name
305 id: image uuid
306 checksum: image checksum
307 location: image path
308 Returns the image list of dictionaries:
309 [{<the fields at Filter_dict plus some VIM specific>}, ...]
310 List can be empty
311 '''
312 raise vimconnNotImplemented( "Should have implemented this" )
313
montesmoreno0c8def02016-12-22 12:16:23 +0000314 def new_vminstance(self,name,description,start,image_id,flavor_id,net_list,cloud_config=None,disk_list=None):
tierno7edb6752016-03-21 17:37:52 +0100315 '''Adds a VM instance to VIM
316 Params:
317 start: indicates if VM must start or boot in pause mode. Ignored
318 image_id,flavor_id: image and flavor uuid
319 net_list: list of interfaces, each one is a dictionary with:
320 name:
321 net_id: network uuid to connect
322 vpci: virtual vcpi to assign
323 model: interface model, virtio, e2000, ...
324 mac_address:
325 use: 'data', 'bridge', 'mgmt'
326 type: 'virtual', 'PF', 'VF', 'VFnotShared'
327 vim_id: filled/added by this function
tiernoa4e1a6e2016-08-31 14:19:40 +0200328 cloud_config: can be a text script to be passed directly to cloud-init,
329 or an object to inject users and ssh keys with format:
330 key-pairs: [] list of keys to install to the default user
331 users: [{ name, key-pairs: []}] list of users to add with their key-pair
tierno7edb6752016-03-21 17:37:52 +0100332 #TODO ip, security groups
333 Returns >=0, the instance identifier
334 <0, error_text
335 '''
tiernoae4a8d12016-07-08 12:30:39 +0200336 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100337
tiernoae4a8d12016-07-08 12:30:39 +0200338 def get_vminstance(self,vm_id):
tierno7edb6752016-03-21 17:37:52 +0100339 '''Returns the VM instance information from VIM'''
tiernoae4a8d12016-07-08 12:30:39 +0200340 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100341
tiernoae4a8d12016-07-08 12:30:39 +0200342 def delete_vminstance(self, vm_id):
tierno7edb6752016-03-21 17:37:52 +0100343 '''Removes a VM instance from VIM'''
344 '''Returns the instance identifier'''
tiernoae4a8d12016-07-08 12:30:39 +0200345 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100346
tiernoae4a8d12016-07-08 12:30:39 +0200347 def refresh_vms_status(self, vm_list):
348 '''Get the status of the virtual machines and their interfaces/ports
349 Params: the list of VM identifiers
350 Returns a dictionary with:
351 vm_id: #VIM id of this Virtual Machine
352 status: #Mandatory. Text with one of:
353 # DELETED (not found at vim)
354 # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
355 # OTHER (Vim reported other status not understood)
356 # ERROR (VIM indicates an ERROR status)
357 # ACTIVE, PAUSED, SUSPENDED, INACTIVE (not running),
358 # CREATING (on building process), ERROR
359 # ACTIVE:NoMgmtIP (Active but any of its interface has an IP address
360 #
361 error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
362 vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
363 interfaces:
364 - vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
365 mac_address: #Text format XX:XX:XX:XX:XX:XX
366 vim_net_id: #network id where this interface is connected
367 vim_interface_id: #interface/port VIM id
368 ip_address: #null, or text with IPv4, IPv6 address
tierno7edb6752016-03-21 17:37:52 +0100369 '''
tiernoae4a8d12016-07-08 12:30:39 +0200370 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100371
tiernoae4a8d12016-07-08 12:30:39 +0200372 def action_vminstance(self, vm_id, action_dict):
373 '''Send and action over a VM instance from VIM
374 Returns the vm_id if the action was successfully sent to the VIM'''
375 raise vimconnNotImplemented( "Should have implemented this" )
376
377 def get_vminstance_console(self,vm_id, console_type="vnc"):
378 '''
379 Get a console for the virtual machine
380 Params:
381 vm_id: uuid of the VM
382 console_type, can be:
383 "novnc" (by default), "xvpvnc" for VNC types,
384 "rdp-html5" for RDP types, "spice-html5" for SPICE types
385 Returns dict with the console parameters:
386 protocol: ssh, ftp, http, https, ...
387 server: usually ip address
388 port: the http, ssh, ... port
389 suffix: extra text, e.g. the http path and query string
390 '''
391 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100392
tiernoae4a8d12016-07-08 12:30:39 +0200393#NOT USED METHODS in current version
394
tierno7edb6752016-03-21 17:37:52 +0100395 def host_vim2gui(self, host, server_dict):
396 '''Transform host dictionary from VIM format to GUI format,
397 and append to the server_dict
398 '''
tiernoae4a8d12016-07-08 12:30:39 +0200399 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100400
401 def get_hosts_info(self):
402 '''Get the information of deployed hosts
403 Returns the hosts content'''
tiernoae4a8d12016-07-08 12:30:39 +0200404 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100405
406 def get_hosts(self, vim_tenant):
407 '''Get the hosts and deployed instances
408 Returns the hosts content'''
tiernoae4a8d12016-07-08 12:30:39 +0200409 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100410
411 def get_processor_rankings(self):
412 '''Get the processor rankings in the VIM database'''
tiernoae4a8d12016-07-08 12:30:39 +0200413 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100414
tiernoae4a8d12016-07-08 12:30:39 +0200415 def new_host(self, host_data):
416 '''Adds a new host to VIM'''
417 '''Returns status code of the VIM response'''
418 raise vimconnNotImplemented( "Should have implemented this" )
419
420 def new_external_port(self, port_data):
421 '''Adds a external port to VIM'''
422 '''Returns the port identifier'''
423 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100424
tiernoae4a8d12016-07-08 12:30:39 +0200425 def new_external_network(self,net_name,net_type):
426 '''Adds a external network to VIM (shared)'''
427 '''Returns the network identifier'''
428 raise vimconnNotImplemented( "Should have implemented this" )
429
430 def connect_port_network(self, port_id, network_id, admin=False):
431 '''Connects a external port to a network'''
432 '''Returns status code of the VIM response'''
433 raise vimconnNotImplemented( "Should have implemented this" )
434
435 def new_vminstancefromJSON(self, vm_data):
436 '''Adds a VM instance to VIM'''
437 '''Returns the instance identifier'''
438 raise vimconnNotImplemented( "Should have implemented this" )
tierno7edb6752016-03-21 17:37:52 +0100439