v0.4.60: fixed bug when using ip profiles in openstack, improved logs in case od...
[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="ERROR", config={}):
86 self.id = uuid
87 self.name = name
88 self.url = url
89 self.url_admin = url_admin
90 self.tenant_id = tenant_id
91 self.tenant_name = tenant_name
92 self.user = user
93 self.passwd = passwd
94 self.config = config
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
99
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
105 elif index=='id':
106 return self.id
107 elif index=='name':
108 return self.name
109 elif index=='user':
110 return self.user
111 elif index=='passwd':
112 return self.passwd
113 elif index=='url':
114 return self.url
115 elif index=='url_admin':
116 return self.url_admin
117 elif index=="config":
118 return self.config
119 else:
120 raise KeyError("Invalid key '%s'" %str(index))
121
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
127 elif index=='id':
128 self.id = value
129 elif index=='name':
130 self.name = value
131 elif index=='user':
132 self.user = value
133 elif index=='passwd':
134 self.passwd = value
135 elif index=='url':
136 self.url = value
137 elif index=='url_admin':
138 self.url_admin = value
139 else:
140 raise KeyError("Invalid key '%s'" %str(index))
141
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" )
146
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" )
151
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
157 <other VIM specific>
158 Returns the tenant list of dictionaries:
159 [{'name':'<name>, 'id':'<id>, ...}, ...]
160 '''
161 raise vimconnNotImplemented( "Should have implemented this" )
162
163 def new_network(self,net_name, net_type, ip_profile=None, shared=False):
164 '''Adds a tenant network to VIM
165 net_name is the name
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
168 shared is a boolean
169 Returns the network identifier'''
170 raise vimconnNotImplemented( "Should have implemented this" )
171
172 def get_network_list(self, filter_dict={}):
173 '''Obtain tenant networks of VIM
174 Filter_dict can be:
175 name: network name
176 id: network uuid
177 shared: boolean
178 tenant_id: tenant
179 admin_state_up: boolean
180 status: 'ACTIVE'
181 Returns the network list of dictionaries:
182 [{<the fields at Filter_dict plus some VIM specific>}, ...]
183 List can be empty
184 '''
185 raise vimconnNotImplemented( "Should have implemented this" )
186
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" )
191
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" )
196
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)
209 #
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)
212
213 '''
214 raise vimconnNotImplemented( "Should have implemented this" )
215
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
219 '''
220 raise vimconnNotImplemented( "Should have implemented this" )
221
222 def new_flavor(self, flavor_data):
223 '''Adds a tenant flavor to VIM
224 flavor_data contains a dictionary with information, keys:
225 name: flavor name
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
237 disk: disk size
238 is_public:
239
240
241
242 #TODO to concrete
243 Returns the flavor identifier'''
244 raise vimconnNotImplemented( "Should have implemented this" )
245
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" )
250
251 def new_image(self,image_dict):
252 '''
253 Adds a tenant image to VIM
254 Returns:
255 200, image-id if the image is created
256 <0, message if there is an error
257 '''
258 raise vimconnNotImplemented( "Should have implemented this" )
259
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" )
264
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" )
268
269 def get_image_list(self, filter_dict={}):
270 '''Obtain tenant images from VIM
271 Filter_dict can be:
272 name: image name
273 id: image uuid
274 checksum: image checksum
275 location: image path
276 Returns the image list of dictionaries:
277 [{<the fields at Filter_dict plus some VIM specific>}, ...]
278 List can be empty
279 '''
280 raise vimconnNotImplemented( "Should have implemented this" )
281
282 def new_vminstance(self,name,description,start,image_id,flavor_id,net_list,cloud_config=None):
283 '''Adds a VM instance to VIM
284 Params:
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:
288 name:
289 net_id: network uuid to connect
290 vpci: virtual vcpi to assign
291 model: interface model, virtio, e2000, ...
292 mac_address:
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
302 <0, error_text
303 '''
304 raise vimconnNotImplemented( "Should have implemented this" )
305
306 def get_vminstance(self,vm_id):
307 '''Returns the VM instance information from VIM'''
308 raise vimconnNotImplemented( "Should have implemented this" )
309
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" )
314
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
328 #
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)
331 interfaces:
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
337 '''
338 raise vimconnNotImplemented( "Should have implemented this" )
339
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" )
344
345 def get_vminstance_console(self,vm_id, console_type="vnc"):
346 '''
347 Get a console for the virtual machine
348 Params:
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
358 '''
359 raise vimconnNotImplemented( "Should have implemented this" )
360
361 #NOT USED METHODS in current version
362
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
366 '''
367 raise vimconnNotImplemented( "Should have implemented this" )
368
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" )
373
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" )
378
379 def get_processor_rankings(self):
380 '''Get the processor rankings in the VIM database'''
381 raise vimconnNotImplemented( "Should have implemented this" )
382
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" )
387
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" )
392
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" )
397
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" )
402
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" )
407