Added support in openstack connector for additional disks, either empty or based...
[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 new_flavor(self, flavor_data):
247 '''Adds a tenant flavor to VIM
248 flavor_data contains a dictionary with information, keys:
249 name: flavor name
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
261 disk: disk size
262 is_public:
263
264
265
266 #TODO to concrete
267 Returns the flavor identifier'''
268 raise vimconnNotImplemented( "Should have implemented this" )
269
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" )
274
275 def new_image(self,image_dict):
276 '''
277 Adds a tenant image to VIM
278 Returns:
279 200, image-id if the image is created
280 <0, message if there is an error
281 '''
282 raise vimconnNotImplemented( "Should have implemented this" )
283
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" )
288
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" )
292
293 def get_image_list(self, filter_dict={}):
294 '''Obtain tenant images from VIM
295 Filter_dict can be:
296 name: image name
297 id: image uuid
298 checksum: image checksum
299 location: image path
300 Returns the image list of dictionaries:
301 [{<the fields at Filter_dict plus some VIM specific>}, ...]
302 List can be empty
303 '''
304 raise vimconnNotImplemented( "Should have implemented this" )
305
306 def new_vminstance(self,name,description,start,image_id,flavor_id,net_list,cloud_config=None,disk_list=None):
307 '''Adds a VM instance to VIM
308 Params:
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:
312 name:
313 net_id: network uuid to connect
314 vpci: virtual vcpi to assign
315 model: interface model, virtio, e2000, ...
316 mac_address:
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
326 <0, error_text
327 '''
328 raise vimconnNotImplemented( "Should have implemented this" )
329
330 def get_vminstance(self,vm_id):
331 '''Returns the VM instance information from VIM'''
332 raise vimconnNotImplemented( "Should have implemented this" )
333
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" )
338
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
352 #
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)
355 interfaces:
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
361 '''
362 raise vimconnNotImplemented( "Should have implemented this" )
363
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" )
368
369 def get_vminstance_console(self,vm_id, console_type="vnc"):
370 '''
371 Get a console for the virtual machine
372 Params:
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
382 '''
383 raise vimconnNotImplemented( "Should have implemented this" )
384
385 #NOT USED METHODS in current version
386
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
390 '''
391 raise vimconnNotImplemented( "Should have implemented this" )
392
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" )
397
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" )
402
403 def get_processor_rankings(self):
404 '''Get the processor rankings in the VIM database'''
405 raise vimconnNotImplemented( "Should have implemented this" )
406
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" )
411
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" )
416
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" )
421
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" )
426
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" )
431