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
="ERROR", config
={}):
89 self
.url_admin
= url_admin
90 self
.tenant_id
= tenant_id
91 self
.tenant_name
= tenant_name
95 self
.logger
= logging
.getLogger('openmano.vim')
96 self
.logger
.setLevel( getattr(logging
, log_level
) )
97 if not self
.url_admin
: #try to use normal url
98 self
.url_admin
= self
.url
100 def __getitem__(self
,index
):
101 if index
=='tenant_id':
102 return self
.tenant_id
103 if index
=='tenant_name':
104 return self
.tenant_name
111 elif index
=='passwd':
115 elif index
=='url_admin':
116 return self
.url_admin
117 elif index
=="config":
120 raise KeyError("Invalid key '%s'" %str
(index
))
122 def __setitem__(self
,index
, value
):
123 if index
=='tenant_id':
124 self
.tenant_id
= value
125 if index
=='tenant_name':
126 self
.tenant_name
= value
133 elif index
=='passwd':
137 elif index
=='url_admin':
138 self
.url_admin
= value
140 raise KeyError("Invalid key '%s'" %str
(index
))
142 def new_tenant(self
,tenant_name
,tenant_description
):
143 '''Adds a new tenant to VIM with this name and description,
144 returns the tenant identifier'''
145 raise vimconnNotImplemented( "Should have implemented this" )
147 def delete_tenant(self
,tenant_id
,):
148 '''Delete a tenant from VIM'''
149 '''Returns the tenant identifier'''
150 raise vimconnNotImplemented( "Should have implemented this" )
152 def get_tenant_list(self
, filter_dict
={}):
153 '''Obtain tenants of VIM
154 filter_dict can contain the following keys:
155 name: filter by tenant name
156 id: filter by tenant uuid/id
158 Returns the tenant list of dictionaries:
159 [{'name':'<name>, 'id':'<id>, ...}, ...]
161 raise vimconnNotImplemented( "Should have implemented this" )
163 def new_network(self
,net_name
, net_type
, ip_profile
=None, shared
=False):
164 '''Adds a tenant network to VIM
166 net_type can be 'bridge','data'.'ptp'. TODO: this need to be revised
167 ip_profile is a dict containing the IP parameters of the network
169 Returns the network identifier'''
170 raise vimconnNotImplemented( "Should have implemented this" )
172 def get_network_list(self
, filter_dict
={}):
173 '''Obtain tenant networks of VIM
179 admin_state_up: boolean
181 Returns the network list of dictionaries:
182 [{<the fields at Filter_dict plus some VIM specific>}, ...]
185 raise vimconnNotImplemented( "Should have implemented this" )
187 def get_network(self
, net_id
):
188 '''Obtain network details of net_id VIM network'
189 Return a dict with the fields at filter_dict (see get_network_list) plus some VIM specific>}, ...]'''
190 raise vimconnNotImplemented( "Should have implemented this" )
192 def delete_network(self
, net_id
):
193 '''Deletes a tenant network from VIM, provide the network id.
194 Returns the network identifier or raise an exception'''
195 raise vimconnNotImplemented( "Should have implemented this" )
197 def refresh_nets_status(self
, net_list
):
198 '''Get the status of the networks
199 Params: the list of network identifiers
200 Returns a dictionary with:
201 net_id: #VIM id of this network
202 status: #Mandatory. Text with one of:
203 # DELETED (not found at vim)
204 # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
205 # OTHER (Vim reported other status not understood)
206 # ERROR (VIM indicates an ERROR status)
207 # ACTIVE, INACTIVE, DOWN (admin down),
208 # BUILD (on building process)
210 error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
211 vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
214 raise vimconnNotImplemented( "Should have implemented this" )
216 def get_flavor(self
, flavor_id
):
217 '''Obtain flavor details from the VIM
218 Returns the flavor dict details {'id':<>, 'name':<>, other vim specific } #TODO to concrete
220 raise vimconnNotImplemented( "Should have implemented this" )
222 def new_flavor(self
, flavor_data
):
223 '''Adds a tenant flavor to VIM
224 flavor_data contains a dictionary with information, keys:
226 ram: memory (cloud type) in MBytes
227 vpcus: cpus (cloud type)
228 extended: EPA parameters
229 - numas: #items requested in same NUMA
230 memory: number of 1G huge pages memory
231 paired-threads|cores|threads: number of paired hyperthreads, complete cores OR individual threads
232 interfaces: # passthrough(PT) or SRIOV interfaces attached to this numa
233 - name: interface name
234 dedicated: yes|no|yes:sriov; for PT, SRIOV or only one SRIOV for the physical NIC
235 bandwidth: X Gbps; requested guarantee bandwidth
236 vpci: requested virtual PCI address
243 Returns the flavor identifier'''
244 raise vimconnNotImplemented( "Should have implemented this" )
246 def delete_flavor(self
, flavor_id
):
247 '''Deletes a tenant flavor from VIM identify by its id
248 Returns the used id or raise an exception'''
249 raise vimconnNotImplemented( "Should have implemented this" )
251 def new_image(self
,image_dict
):
253 Adds a tenant image to VIM
255 200, image-id if the image is created
256 <0, message if there is an error
258 raise vimconnNotImplemented( "Should have implemented this" )
260 def delete_image(self
, image_id
):
261 '''Deletes a tenant image from VIM'''
262 '''Returns the HTTP response code and a message indicating details of the success or fail'''
263 raise vimconnNotImplemented( "Should have implemented this" )
265 def get_image_id_from_path(self
, path
):
266 '''Get the image id from image path in the VIM database. Returns the image_id'''
267 raise vimconnNotImplemented( "Should have implemented this" )
269 def get_image_list(self
, filter_dict
={}):
270 '''Obtain tenant images from VIM
274 checksum: image checksum
276 Returns the image list of dictionaries:
277 [{<the fields at Filter_dict plus some VIM specific>}, ...]
280 raise vimconnNotImplemented( "Should have implemented this" )
282 def new_vminstance(self
,name
,description
,start
,image_id
,flavor_id
,net_list
,cloud_config
=None):
283 '''Adds a VM instance to VIM
285 start: indicates if VM must start or boot in pause mode. Ignored
286 image_id,flavor_id: image and flavor uuid
287 net_list: list of interfaces, each one is a dictionary with:
289 net_id: network uuid to connect
290 vpci: virtual vcpi to assign
291 model: interface model, virtio, e2000, ...
293 use: 'data', 'bridge', 'mgmt'
294 type: 'virtual', 'PF', 'VF', 'VFnotShared'
295 vim_id: filled/added by this function
296 cloud_config: can be a text script to be passed directly to cloud-init,
297 or an object to inject users and ssh keys with format:
298 key-pairs: [] list of keys to install to the default user
299 users: [{ name, key-pairs: []}] list of users to add with their key-pair
300 #TODO ip, security groups
301 Returns >=0, the instance identifier
304 raise vimconnNotImplemented( "Should have implemented this" )
306 def get_vminstance(self
,vm_id
):
307 '''Returns the VM instance information from VIM'''
308 raise vimconnNotImplemented( "Should have implemented this" )
310 def delete_vminstance(self
, vm_id
):
311 '''Removes a VM instance from VIM'''
312 '''Returns the instance identifier'''
313 raise vimconnNotImplemented( "Should have implemented this" )
315 def refresh_vms_status(self
, vm_list
):
316 '''Get the status of the virtual machines and their interfaces/ports
317 Params: the list of VM identifiers
318 Returns a dictionary with:
319 vm_id: #VIM id of this Virtual Machine
320 status: #Mandatory. Text with one of:
321 # DELETED (not found at vim)
322 # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
323 # OTHER (Vim reported other status not understood)
324 # ERROR (VIM indicates an ERROR status)
325 # ACTIVE, PAUSED, SUSPENDED, INACTIVE (not running),
326 # CREATING (on building process), ERROR
327 # ACTIVE:NoMgmtIP (Active but any of its interface has an IP address
329 error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
330 vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
332 - vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
333 mac_address: #Text format XX:XX:XX:XX:XX:XX
334 vim_net_id: #network id where this interface is connected
335 vim_interface_id: #interface/port VIM id
336 ip_address: #null, or text with IPv4, IPv6 address
338 raise vimconnNotImplemented( "Should have implemented this" )
340 def action_vminstance(self
, vm_id
, action_dict
):
341 '''Send and action over a VM instance from VIM
342 Returns the vm_id if the action was successfully sent to the VIM'''
343 raise vimconnNotImplemented( "Should have implemented this" )
345 def get_vminstance_console(self
,vm_id
, console_type
="vnc"):
347 Get a console for the virtual machine
349 vm_id: uuid of the VM
350 console_type, can be:
351 "novnc" (by default), "xvpvnc" for VNC types,
352 "rdp-html5" for RDP types, "spice-html5" for SPICE types
353 Returns dict with the console parameters:
354 protocol: ssh, ftp, http, https, ...
355 server: usually ip address
356 port: the http, ssh, ... port
357 suffix: extra text, e.g. the http path and query string
359 raise vimconnNotImplemented( "Should have implemented this" )
361 #NOT USED METHODS in current version
363 def host_vim2gui(self
, host
, server_dict
):
364 '''Transform host dictionary from VIM format to GUI format,
365 and append to the server_dict
367 raise vimconnNotImplemented( "Should have implemented this" )
369 def get_hosts_info(self
):
370 '''Get the information of deployed hosts
371 Returns the hosts content'''
372 raise vimconnNotImplemented( "Should have implemented this" )
374 def get_hosts(self
, vim_tenant
):
375 '''Get the hosts and deployed instances
376 Returns the hosts content'''
377 raise vimconnNotImplemented( "Should have implemented this" )
379 def get_processor_rankings(self
):
380 '''Get the processor rankings in the VIM database'''
381 raise vimconnNotImplemented( "Should have implemented this" )
383 def new_host(self
, host_data
):
384 '''Adds a new host to VIM'''
385 '''Returns status code of the VIM response'''
386 raise vimconnNotImplemented( "Should have implemented this" )
388 def new_external_port(self
, port_data
):
389 '''Adds a external port to VIM'''
390 '''Returns the port identifier'''
391 raise vimconnNotImplemented( "Should have implemented this" )
393 def new_external_network(self
,net_name
,net_type
):
394 '''Adds a external network to VIM (shared)'''
395 '''Returns the network identifier'''
396 raise vimconnNotImplemented( "Should have implemented this" )
398 def connect_port_network(self
, port_id
, network_id
, admin
=False):
399 '''Connects a external port to a network'''
400 '''Returns status code of the VIM response'''
401 raise vimconnNotImplemented( "Should have implemented this" )
403 def new_vminstancefromJSON(self
, vm_data
):
404 '''Adds a VM instance to VIM'''
405 '''Returns the instance identifier'''
406 raise vimconnNotImplemented( "Should have implemented this" )