1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 vimconn implement an Abstract class for the vim connector plugins
26 with the definition of the method to be implemented.
28 __author__
="Alfonso Tierno"
29 __date__
="$16-oct-2015 11:09:29$"
34 HTTP_Bad_Request
= 400
35 HTTP_Unauthorized
= 401
37 HTTP_Method_Not_Allowed
= 405
38 HTTP_Request_Timeout
= 408
40 HTTP_Not_Implemented
= 501
41 HTTP_Service_Unavailable
= 503
42 HTTP_Internal_Server_Error
= 500
44 class 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
50 class 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
)
55 class 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
)
60 class 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
)
65 class 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
)
70 class 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
)
75 class 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
)
81 '''Abstract base class for all the VIM connector plugins
82 These plugins must implement a vimconnector class derived from this
85 def __init__(self
, uuid
, name
, tenant_id
, tenant_name
, url
, url_admin
=None, user
=None, passwd
=None, log_level
=None, config
={}):
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
100 self
.url_admin
= url_admin
101 self
.tenant_id
= tenant_id
102 self
.tenant_name
= tenant_name
106 self
.logger
= logging
.getLogger('openmano.vim')
108 self
.logger
.setLevel( getattr(logging
, log_level
) )
109 if not self
.url_admin
: #try to use normal url
110 self
.url_admin
= self
.url
112 def __getitem__(self
,index
):
113 if index
=='tenant_id':
114 return self
.tenant_id
115 if index
=='tenant_name':
116 return self
.tenant_name
123 elif index
=='passwd':
127 elif index
=='url_admin':
128 return self
.url_admin
129 elif index
=="config":
132 raise KeyError("Invalid key '%s'" %str
(index
))
134 def __setitem__(self
,index
, value
):
135 if index
=='tenant_id':
136 self
.tenant_id
= value
137 if index
=='tenant_name':
138 self
.tenant_name
= value
145 elif index
=='passwd':
149 elif index
=='url_admin':
150 self
.url_admin
= value
152 raise KeyError("Invalid key '%s'" %str
(index
))
154 def new_tenant(self
,tenant_name
,tenant_description
):
155 """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
160 raise vimconnNotImplemented( "Should have implemented this" )
162 def delete_tenant(self
,tenant_id
,):
163 """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
167 raise vimconnNotImplemented( "Should have implemented this" )
169 def get_tenant_list(self
, filter_dict
={}):
170 '''Obtain tenants of VIM
171 filter_dict dictionary that can contain the following keys:
172 name: filter by tenant name
173 id: filter by tenant uuid/id
175 Returns the tenant list of dictionaries, and empty list if no tenant match all the filers:
176 [{'name':'<name>, 'id':'<id>, ...}, ...]
178 raise vimconnNotImplemented( "Should have implemented this" )
180 def new_network(self
,net_name
, net_type
, ip_profile
=None, shared
=False):
181 """Adds a tenant network to VIM
183 net_type can be 'bridge','data'.'ptp'. TODO: this need to be revised
184 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,
192 Returns the network identifier on success or raises and exeption on failure
194 raise vimconnNotImplemented( "Should have implemented this" )
196 def get_network_list(self
, filter_dict
={}):
197 '''Obtain tenant networks of VIM
203 admin_state_up: boolean
205 Returns the network list of dictionaries:
206 [{<the fields at Filter_dict plus some VIM specific>}, ...]
209 raise vimconnNotImplemented( "Should have implemented this" )
211 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" )
216 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" )
221 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)
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)
238 raise vimconnNotImplemented( "Should have implemented this" )
240 def get_flavor(self
, flavor_id
):
241 '''Obtain flavor details from the VIM
242 Returns the flavor dict details {'id':<>, 'name':<>, other vim specific } #TODO to concrete
244 raise vimconnNotImplemented( "Should have implemented this" )
246 def new_flavor(self
, flavor_data
):
247 '''Adds a tenant flavor to VIM
248 flavor_data contains a dictionary with information, keys:
250 ram: memory (cloud type) in MBytes
251 vpcus: cpus (cloud type)
252 extended: EPA parameters
253 - numas: #items requested in same NUMA
254 memory: number of 1G huge pages memory
255 paired-threads|cores|threads: number of paired hyperthreads, complete cores OR individual threads
256 interfaces: # passthrough(PT) or SRIOV interfaces attached to this numa
257 - name: interface name
258 dedicated: yes|no|yes:sriov; for PT, SRIOV or only one SRIOV for the physical NIC
259 bandwidth: X Gbps; requested guarantee bandwidth
260 vpci: requested virtual PCI address
267 Returns the flavor identifier'''
268 raise vimconnNotImplemented( "Should have implemented this" )
270 def delete_flavor(self
, flavor_id
):
271 '''Deletes a tenant flavor from VIM identify by its id
272 Returns the used id or raise an exception'''
273 raise vimconnNotImplemented( "Should have implemented this" )
275 def new_image(self
,image_dict
):
277 Adds a tenant image to VIM
279 200, image-id if the image is created
280 <0, message if there is an error
282 raise vimconnNotImplemented( "Should have implemented this" )
284 def delete_image(self
, image_id
):
285 '''Deletes a tenant image from VIM'''
286 '''Returns the HTTP response code and a message indicating details of the success or fail'''
287 raise vimconnNotImplemented( "Should have implemented this" )
289 def get_image_id_from_path(self
, path
):
290 '''Get the image id from image path in the VIM database. Returns the image_id'''
291 raise vimconnNotImplemented( "Should have implemented this" )
293 def get_image_list(self
, filter_dict
={}):
294 '''Obtain tenant images from VIM
298 checksum: image checksum
300 Returns the image list of dictionaries:
301 [{<the fields at Filter_dict plus some VIM specific>}, ...]
304 raise vimconnNotImplemented( "Should have implemented this" )
306 def new_vminstance(self
,name
,description
,start
,image_id
,flavor_id
,net_list
,cloud_config
=None):
307 '''Adds a VM instance to VIM
309 start: indicates if VM must start or boot in pause mode. Ignored
310 image_id,flavor_id: image and flavor uuid
311 net_list: list of interfaces, each one is a dictionary with:
313 net_id: network uuid to connect
314 vpci: virtual vcpi to assign
315 model: interface model, virtio, e2000, ...
317 use: 'data', 'bridge', 'mgmt'
318 type: 'virtual', 'PF', 'VF', 'VFnotShared'
319 vim_id: filled/added by this function
320 cloud_config: can be a text script to be passed directly to cloud-init,
321 or an object to inject users and ssh keys with format:
322 key-pairs: [] list of keys to install to the default user
323 users: [{ name, key-pairs: []}] list of users to add with their key-pair
324 #TODO ip, security groups
325 Returns >=0, the instance identifier
328 raise vimconnNotImplemented( "Should have implemented this" )
330 def get_vminstance(self
,vm_id
):
331 '''Returns the VM instance information from VIM'''
332 raise vimconnNotImplemented( "Should have implemented this" )
334 def delete_vminstance(self
, vm_id
):
335 '''Removes a VM instance from VIM'''
336 '''Returns the instance identifier'''
337 raise vimconnNotImplemented( "Should have implemented this" )
339 def refresh_vms_status(self
, vm_list
):
340 '''Get the status of the virtual machines and their interfaces/ports
341 Params: the list of VM identifiers
342 Returns a dictionary with:
343 vm_id: #VIM id of this Virtual Machine
344 status: #Mandatory. Text with one of:
345 # DELETED (not found at vim)
346 # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
347 # OTHER (Vim reported other status not understood)
348 # ERROR (VIM indicates an ERROR status)
349 # ACTIVE, PAUSED, SUSPENDED, INACTIVE (not running),
350 # CREATING (on building process), ERROR
351 # ACTIVE:NoMgmtIP (Active but any of its interface has an IP address
353 error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
354 vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
356 - vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
357 mac_address: #Text format XX:XX:XX:XX:XX:XX
358 vim_net_id: #network id where this interface is connected
359 vim_interface_id: #interface/port VIM id
360 ip_address: #null, or text with IPv4, IPv6 address
362 raise vimconnNotImplemented( "Should have implemented this" )
364 def action_vminstance(self
, vm_id
, action_dict
):
365 '''Send and action over a VM instance from VIM
366 Returns the vm_id if the action was successfully sent to the VIM'''
367 raise vimconnNotImplemented( "Should have implemented this" )
369 def get_vminstance_console(self
,vm_id
, console_type
="vnc"):
371 Get a console for the virtual machine
373 vm_id: uuid of the VM
374 console_type, can be:
375 "novnc" (by default), "xvpvnc" for VNC types,
376 "rdp-html5" for RDP types, "spice-html5" for SPICE types
377 Returns dict with the console parameters:
378 protocol: ssh, ftp, http, https, ...
379 server: usually ip address
380 port: the http, ssh, ... port
381 suffix: extra text, e.g. the http path and query string
383 raise vimconnNotImplemented( "Should have implemented this" )
385 #NOT USED METHODS in current version
387 def host_vim2gui(self
, host
, server_dict
):
388 '''Transform host dictionary from VIM format to GUI format,
389 and append to the server_dict
391 raise vimconnNotImplemented( "Should have implemented this" )
393 def get_hosts_info(self
):
394 '''Get the information of deployed hosts
395 Returns the hosts content'''
396 raise vimconnNotImplemented( "Should have implemented this" )
398 def get_hosts(self
, vim_tenant
):
399 '''Get the hosts and deployed instances
400 Returns the hosts content'''
401 raise vimconnNotImplemented( "Should have implemented this" )
403 def get_processor_rankings(self
):
404 '''Get the processor rankings in the VIM database'''
405 raise vimconnNotImplemented( "Should have implemented this" )
407 def new_host(self
, host_data
):
408 '''Adds a new host to VIM'''
409 '''Returns status code of the VIM response'''
410 raise vimconnNotImplemented( "Should have implemented this" )
412 def new_external_port(self
, port_data
):
413 '''Adds a external port to VIM'''
414 '''Returns the port identifier'''
415 raise vimconnNotImplemented( "Should have implemented this" )
417 def new_external_network(self
,net_name
,net_type
):
418 '''Adds a external network to VIM (shared)'''
419 '''Returns the network identifier'''
420 raise vimconnNotImplemented( "Should have implemented this" )
422 def connect_port_network(self
, port_id
, network_id
, admin
=False):
423 '''Connects a external port to a network'''
424 '''Returns status code of the VIM response'''
425 raise vimconnNotImplemented( "Should have implemented this" )
427 def new_vminstancefromJSON(self
, vm_data
):
428 '''Adds a VM instance to VIM'''
429 '''Returns the instance identifier'''
430 raise vimconnNotImplemented( "Should have implemented this" )