Merge "Unify code for scenario v0.2 v0.3"
[osm/RO.git] / vimconn.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 vimconn 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
31 import logging
32
33 #Error variables
34 HTTP_Bad_Request = 400
35 HTTP_Unauthorized = 401
36 HTTP_Not_Found = 404
37 HTTP_Method_Not_Allowed = 405
38 HTTP_Request_Timeout = 408
39 HTTP_Conflict = 409
40 HTTP_Not_Implemented = 501
41 HTTP_Service_Unavailable = 503
42 HTTP_Internal_Server_Error = 500
43
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
49
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)
54
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)
59
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)
64
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)
69
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)
74
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)
79
80 class vimconnector():
81 '''Abstract base class for all the VIM connector plugins
82 These plugins must implement a vimconnector class derived from this
83 and all these methods
84 '''
85 def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None, config={}):
86 """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 """
97 self.id = uuid
98 self.name = name
99 self.url = url
100 self.url_admin = url_admin
101 self.tenant_id = tenant_id
102 self.tenant_name = tenant_name
103 self.user = user
104 self.passwd = passwd
105 self.config = config
106 self.logger = logging.getLogger('openmano.vim')
107 if log_level:
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
111
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
117 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):
135 if index=='tenant_id':
136 self.tenant_id = value
137 if index=='tenant_name':
138 self.tenant_name = value
139 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))
153
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
159 """
160 raise vimconnNotImplemented( "Should have implemented this" )
161
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
166 """
167 raise vimconnNotImplemented( "Should have implemented this" )
168
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
174 <other VIM specific>
175 Returns the tenant list of dictionaries, and empty list if no tenant match all the filers:
176 [{'name':'<name>, 'id':'<id>, ...}, ...]
177 '''
178 raise vimconnNotImplemented( "Should have implemented this" )
179
180 def new_network(self,net_name, net_type, ip_profile=None, shared=False):
181 """Adds a tenant network to VIM
182 net_name is the name
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,
189 "dhcp": dhcp_schema
190
191 shared is a boolean
192 Returns the network identifier on success or raises and exeption on failure
193 """
194 raise vimconnNotImplemented( "Should have implemented this" )
195
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'
205 Returns the network list of dictionaries:
206 [{<the fields at Filter_dict plus some VIM specific>}, ...]
207 List can be empty
208 '''
209 raise vimconnNotImplemented( "Should have implemented this" )
210
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" )
215
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" )
220
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)
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)
236
237 '''
238 raise vimconnNotImplemented( "Should have implemented this" )
239
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
243 '''
244 raise vimconnNotImplemented( "Should have implemented this" )
245
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
252 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" )
275
276 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" )
280
281 def new_image(self,image_dict):
282 '''
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 '''
288 raise vimconnNotImplemented( "Should have implemented this" )
289
290 def delete_image(self, image_id):
291 '''Deletes a tenant image from VIM'''
292 '''Returns the HTTP response code and a message indicating details of the success or fail'''
293 raise vimconnNotImplemented( "Should have implemented this" )
294
295 def get_image_id_from_path(self, path):
296 """Get the image id from image path in the VIM database.
297 Returns the image_id or raises a vimconnNotFoundException
298 """
299 raise vimconnNotImplemented( "Should have implemented this" )
300
301 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
314 def new_vminstance(self,name,description,start,image_id,flavor_id,net_list,cloud_config=None,disk_list=None):
315 '''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
328 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
332 #TODO ip, security groups
333 Returns >=0, the instance identifier
334 <0, error_text
335 '''
336 raise vimconnNotImplemented( "Should have implemented this" )
337
338 def get_vminstance(self,vm_id):
339 '''Returns the VM instance information from VIM'''
340 raise vimconnNotImplemented( "Should have implemented this" )
341
342 def delete_vminstance(self, vm_id):
343 '''Removes a VM instance from VIM'''
344 '''Returns the instance identifier'''
345 raise vimconnNotImplemented( "Should have implemented this" )
346
347 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
369 '''
370 raise vimconnNotImplemented( "Should have implemented this" )
371
372 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" )
392
393 #NOT USED METHODS in current version
394
395 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 '''
399 raise vimconnNotImplemented( "Should have implemented this" )
400
401 def get_hosts_info(self):
402 '''Get the information of deployed hosts
403 Returns the hosts content'''
404 raise vimconnNotImplemented( "Should have implemented this" )
405
406 def get_hosts(self, vim_tenant):
407 '''Get the hosts and deployed instances
408 Returns the hosts content'''
409 raise vimconnNotImplemented( "Should have implemented this" )
410
411 def get_processor_rankings(self):
412 '''Get the processor rankings in the VIM database'''
413 raise vimconnNotImplemented( "Should have implemented this" )
414
415 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" )
424
425 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" )
439