4 # Copyright 2016 RIFT.IO Inc
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
23 from keystoneclient
import v3
as ksclientv3
24 from keystoneclient
.v2_0
import client
as ksclientv2
25 from novaclient
import client
as nova_client
26 from neutronclient
.neutron
import client
as ntclient
27 from glanceclient
.v2
import client
as glclient
28 from ceilometerclient
import client
as ceilo_client
29 from cinderclient
.v2
import client
as cinder_client
32 import novaclient
.exceptions
as NovaException
33 import keystoneclient
.exceptions
as KeystoneExceptions
34 import neutronclient
.common
.exceptions
as NeutronException
35 import glanceclient
.exc
as GlanceException
36 import cinderclient
.exceptions
as CinderException
38 logger
= logging
.getLogger('rwcal.openstack.drv')
39 logger
.setLevel(logging
.DEBUG
)
41 class ValidationError(Exception):
45 class KeystoneDriver(object):
47 Driver base-class for keystoneclient APIs
49 def __init__(self
, ksclient
):
51 Constructor for KeystoneDriver base class
55 self
.ksclient
= ksclient
57 def get_username(self
):
59 Returns the username associated with keystoneclient connection
63 def get_password(self
):
65 Returns the password associated with keystoneclient connection
69 def get_tenant_name(self
):
71 Returns the tenant name associated with keystoneclient connection
73 return self
._tenant
_name
75 def get_user_domain_name(self
):
77 Returns None as this field does not exist for v2.
81 def get_project_domain_name(self
):
83 Returns None as this field does not exist for v2.
87 def _get_keystone_connection(self
):
89 Returns object of class python-keystoneclient class
91 if not hasattr(self
, '_keystone_connection'):
92 self
._keystone
_connection
= self
.ksclient(**self
._get
_keystone
_credentials
())
93 return self
._keystone
_connection
95 def is_auth_token_valid(self
, token_expiry
, time_fmt
):
97 Performs validity on auth_token
99 token_expiry (string): Expiry time for token
100 time_fmt (string) : Format for expiry string in auth_ref
103 True/False (Boolean): (auth_token is valid or auth_token is invalid)
107 import dateutil
.parser
109 now
= datetime
.datetime
.timetuple(datetime
.datetime
.utcnow())
110 expires_at
= dateutil
.parser
.parse(token_expiry
)
111 t_now
= time
.mktime(now
)
112 t_expiry
= time
.mktime(expires_at
.timetuple())
114 if (t_expiry
<= t_now
) or ((t_expiry
- t_now
) < 300 ):
115 ### Token has expired or about to expire (5 minute)
116 delattr(self
, '_keystone_connection')
120 except Exception as e
:
121 logger
.error("Received except %s during auth_token validity check" %str
(e
))
122 logger
.info("Can not validate the auth_token. Assuming invalid")
126 def get_service_endpoint(self
, service_type
, endpoint_type
):
128 Returns requested type of endpoint for requested service type
130 service_type (string): Service Type (e.g. computev3, image, network)
131 endpoint_type(string): Endpoint Type (e.g. publicURL,adminURL,internalURL)
133 service_endpoint(string): Service endpoint string
135 endpoint_kwargs
= {'service_type' : service_type
,
136 'endpoint_type' : endpoint_type
}
138 ksconn
= self
._get
_keystone
_connection
()
139 service_endpoint
= ksconn
.service_catalog
.url_for(**endpoint_kwargs
)
140 except (KeystoneExceptions
.Unauthorized
, KeystoneExceptions
.AuthorizationFailure
) as e
:
142 except Exception as e
:
143 logger
.error("OpenstackDriver: Service Catalog discovery operation failed for service_type: %s, endpoint_type: %s. Exception: %s" %(service_type
, endpoint_type
, str(e
)))
145 return service_endpoint
148 def get_raw_token(self
):
150 Returns a valid raw_auth_token string
152 Returns (string): raw_auth_token string
154 ksconn
= self
._get
_keystone
_connection
()
156 raw_token
= ksconn
.get_raw_token_from_identity_service(auth_url
= self
._auth
_url
,
157 token
= self
.get_auth_token())
158 except KeystoneExceptions
.AuthorizationFailure
as e
:
159 logger
.error("OpenstackDriver: get_raw_token_from_identity_service Failure. Exception: %s" %(str(e
)))
162 except Exception as e
:
163 logger
.error("OpenstackDriver: Could not retrieve raw_token. Exception: %s" %(str(e
)))
167 def get_tenant_id(self
):
169 Returns tenant_id for the project/tenant. Tenant name is provided during
172 Returns (string): Tenant ID
174 ksconn
= self
._get
_keystone
_connection
()
175 return ksconn
.tenant_id
177 def get_security_mode(self
):
179 Returns certificate_validation policy in case of SSL/TLS connection.
180 This policy is provided during class instantiation
183 The boolean returned are designed to match the python-client class instantiation ("insecure") value.
184 for nova/neutron/glance/keystone clients
186 True: No certificate validation required -- Insecure mode
187 False: Certificate validation required -- Secure mode
189 return self
._insecure
191 def tenant_list(self
):
193 Returns list of tenants
197 def tenant_create(self
, name
):
203 def tenant_delete(self
, tenant_id
):
205 Deletes a tenant identified by tenant_id
209 def roles_list(self
):
212 def roles_create(self
):
215 def roles_delete(self
):
218 class KeystoneDriverV2(KeystoneDriver
):
220 Driver class for keystoneclient V2 APIs
222 def __init__(self
, username
, password
, auth_url
,tenant_name
, insecure
, region
):
224 Constructor for KeystoneDriverV3 class
226 username (string) : Username
227 password (string) : Password
228 auth_url (string) : Authentication URL
229 tenant_name(string): Tenant Name
230 region (string) : Region name
233 self
._username
= username
234 self
._password
= password
235 self
._auth
_url
= auth_url
236 self
._tenant
_name
= tenant_name
237 self
._insecure
= insecure
238 self
._region
= region
239 super(KeystoneDriverV2
, self
).__init
__(ksclientv2
.Client
)
241 def _get_keystone_credentials(self
):
243 Returns the dictionary of kwargs required to instantiate python-keystoneclient class
246 #creds['user_domain'] = self._domain_name
247 creds
['username'] = self
._username
248 creds
['password'] = self
._password
249 creds
['auth_url'] = self
._auth
_url
250 creds
['tenant_name'] = self
._tenant
_name
251 creds
['insecure'] = self
.get_security_mode()
252 creds
['region_name'] = self
._region
255 def get_auth_token(self
):
257 Returns a valid auth_token
259 Returns (string): auth_token string
261 ksconn
= self
._get
_keystone
_connection
()
262 return ksconn
.auth_token
264 def is_auth_token_valid(self
):
266 Performs validity on auth_token
270 True/False (Boolean): (auth_token is valid or auth_token is invalid)
272 ksconn
= self
._get
_keystone
_connection
()
273 result
= super(KeystoneDriverV2
, self
).is_auth_token_valid(ksconn
.auth_ref
['token']['expires'],
274 "%Y-%m-%dT%H:%M:%SZ")
278 class KeystoneDriverV3(KeystoneDriver
):
280 Driver class for keystoneclient V3 APIs
282 def __init__(self
, username
,
287 user_domain_name
= None,
288 project_domain_name
= None,
291 Constructor for KeystoneDriverV3 class
293 username (string) : Username
294 password (string) : Password
295 auth_url (string) : Authentication URL
296 tenant_name(string): Tenant Name
297 user_domain_name (string) : User domain name
298 project_domain_name (string): Project domain name
299 region (string) : Region name
302 self
._username
= username
303 self
._password
= password
304 self
._auth
_url
= auth_url
305 self
._tenant
_name
= tenant_name
306 self
._insecure
= insecure
307 self
._user
_domain
_name
= user_domain_name
308 self
._project
_domain
_name
= project_domain_name
309 self
._region
= region
310 super(KeystoneDriverV3
, self
).__init
__(ksclientv3
.Client
)
312 def _get_keystone_credentials(self
):
314 Returns the dictionary of kwargs required to instantiate python-keystoneclient class
317 creds
['username'] = self
._username
318 creds
['password'] = self
._password
319 creds
['auth_url'] = self
._auth
_url
320 creds
['project_name'] = self
._tenant
_name
321 creds
['insecure'] = self
._insecure
322 creds
['user_domain_name'] = self
._user
_domain
_name
323 creds
['project_domain_name'] = self
._project
_domain
_name
324 creds
['region_name'] = self
._region
327 def get_user_domain_name(self
):
329 Returns the domain_name of the associated OpenStack user account
331 return self
._user
_domain
_name
;
333 def get_project_domain_name(self
):
335 Returns the domain_name of the associated OpenStack project
337 return self
._project
_domain
_name
;
339 def get_auth_token(self
):
341 Returns a valid auth_token
343 Returns (string): auth_token string
345 ksconn
= self
._get
_keystone
_connection
()
346 return ksconn
.auth_ref
['auth_token']
348 def is_auth_token_valid(self
):
350 Performs validity on auth_token
354 True/False (Boolean): (auth_token is valid or auth_token is invalid)
356 ksconn
= self
._get
_keystone
_connection
()
357 result
= super(KeystoneDriverV3
, self
).is_auth_token_valid(ksconn
.auth_ref
['expires_at'],
358 "%Y-%m-%dT%H:%M:%S.%fZ")
361 class NovaDriver(object):
363 Driver for openstack nova_client
365 def __init__(self
, ks_drv
, service_name
, version
):
367 Constructor for NovaDriver
368 Arguments: KeystoneDriver class object
371 self
._service
_name
= service_name
372 self
._version
= version
374 def _get_nova_credentials(self
):
376 Returns a dictionary of kwargs required to instantiate python-novaclient class
379 creds
['version'] = self
._version
380 creds
['bypass_url'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, "publicURL")
381 creds
['username'] = self
.ks_drv
.get_username()
382 creds
['project_id'] = self
.ks_drv
.get_tenant_name()
383 creds
['auth_token'] = self
.ks_drv
.get_auth_token()
384 creds
['insecure'] = self
.ks_drv
.get_security_mode()
385 #creds['user_domain_name'] = self.ks_drv.get_user_domain_name()
386 #creds['project_domain_name'] = self.ks_drv.get_project_domain_name()
390 def _get_nova_connection(self
):
392 Returns an object of class python-novaclient
394 if not hasattr(self
, '_nova_connection'):
395 self
._nova
_connection
= nova_client
.Client(**self
._get
_nova
_credentials
())
397 # Reinitialize if auth_token is no longer valid
398 if not self
.ks_drv
.is_auth_token_valid():
399 self
._nova
_connection
= nova_client
.Client(**self
._get
_nova
_credentials
())
400 return self
._nova
_connection
402 def _flavor_get(self
, flavor_id
):
404 Get flavor by flavor_id
406 flavor_id(string): UUID of flavor_id
409 dictionary of flavor parameters
411 nvconn
= self
._get
_nova
_connection
()
413 flavor
= nvconn
.flavors
.get(flavor_id
)
414 except Exception as e
:
415 logger
.info("OpenstackDriver: Did not find flavor with flavor_id : %s. Exception: %s"%(flavor_id
, str(e
)))
419 extra_specs
= flavor
.get_keys()
420 except Exception as e
:
421 logger
.info("OpenstackDriver: Could not get the EPA attributes for flavor with flavor_id : %s. Exception: %s"%(flavor_id
, str(e
)))
424 response
= flavor
.to_dict()
425 assert 'extra_specs' not in response
, "Key extra_specs present as flavor attribute"
426 response
['extra_specs'] = extra_specs
429 def flavor_get(self
, flavor_id
):
431 Get flavor by flavor_id
433 flavor_id(string): UUID of flavor_id
436 dictionary of flavor parameters
438 return self
._flavor
_get
(flavor_id
)
440 def flavor_list(self
):
442 Returns list of all flavors (dictionary per flavor)
447 A list of dictionaries. Each dictionary contains attributes for a single flavor instance
451 nvconn
= self
._get
_nova
_connection
()
453 flavors
= nvconn
.flavors
.list()
454 except Exception as e
:
455 logger
.error("OpenstackDriver: List Flavor operation failed. Exception: %s"%(str(e
)))
458 flavor_info
= [ self
.flavor_get(flv
.id) for flv
in flavors
]
461 def flavor_create(self
, name
, ram
, vcpu
, disk
, extra_specs
):
466 name (string): Name of the new flavor
467 ram (int) : Memory in MB
468 vcpus (int) : Number of VCPUs
469 disk (int) : Secondary storage size in GB
470 extra_specs (dictionary): EPA attributes dictionary
473 flavor_id (string): UUID of flavor created
475 nvconn
= self
._get
_nova
_connection
()
477 flavor
= nvconn
.flavors
.create(name
= name
,
486 except Exception as e
:
487 logger
.error("OpenstackDriver: Create Flavor operation failed. Exception: %s"%(str(e
)))
492 flavor
.set_keys(extra_specs
)
493 except Exception as e
:
494 logger
.error("OpenstackDriver: Set Key operation failed for flavor: %s. Exception: %s" %(flavor
.id, str(e
)))
498 def flavor_delete(self
, flavor_id
):
500 Deletes a flavor identified by flavor_id
503 flavor_id (string): UUID of flavor to be deleted
507 assert flavor_id
== self
._flavor
_get
(flavor_id
)['id']
508 nvconn
= self
._get
_nova
_connection
()
510 nvconn
.flavors
.delete(flavor_id
)
511 except Exception as e
:
512 logger
.error("OpenstackDriver: Delete flavor operation failed for flavor: %s. Exception: %s" %(flavor_id
, str(e
)))
516 def server_list(self
):
518 Returns a list of available VMs for the project
523 A list of dictionaries. Each dictionary contains attributes associated
528 nvconn
= self
._get
_nova
_connection
()
530 servers
= nvconn
.servers
.list()
531 except Exception as e
:
532 logger
.error("OpenstackDriver: List Server operation failed. Exception: %s" %(str(e
)))
534 server_info
= [ server
.to_dict() for server
in servers
]
537 def _nova_server_get(self
, server_id
):
539 Returns a dictionary of attributes associated with VM identified by service_id
542 server_id (string): UUID of the VM/server for which information is requested
545 A dictionary object with attributes associated with VM identified by server_id
547 nvconn
= self
._get
_nova
_connection
()
549 server
= nvconn
.servers
.get(server
= server_id
)
550 except Exception as e
:
551 logger
.info("OpenstackDriver: Get Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
554 return server
.to_dict()
556 def server_get(self
, server_id
):
558 Returns a dictionary of attributes associated with VM identified by service_id
561 server_id (string): UUID of the VM/server for which information is requested
564 A dictionary object with attributes associated with VM identified by server_id
566 return self
._nova
_server
_get
(server_id
)
568 def server_create(self
, **kwargs
):
570 Creates a new VM/server instance
573 A dictionary of following key-value pairs
575 server_name(string) : Name of the VM/Server
576 flavor_id (string) : UUID of the flavor to be used for VM
577 image_id (string) : UUID of the image to be used VM/Server instance,
578 This could be None if volumes (with images) are being used
579 network_list(List) : A List of network_ids. A port will be created in these networks
580 port_list (List) : A List of port-ids. These ports will be added to VM.
581 metadata (dict) : A dictionary of arbitrary key-value pairs associated with VM/server
582 userdata (string) : A script which shall be executed during first boot of the VM
583 availability_zone (string) : A name of the availability zone where instance should be launched
584 scheduler_hints (string) : Openstack scheduler_hints to be passed to nova scheduler
587 server_id (string): UUID of the VM/server created
591 if 'network_list' in kwargs
:
592 for network_id
in kwargs
['network_list']:
593 nics
.append({'net-id': network_id
})
595 if 'port_list' in kwargs
:
596 for port_id
in kwargs
['port_list']:
597 nics
.append({'port-id': port_id
})
599 nvconn
= self
._get
_nova
_connection
()
603 server
= nvconn
.servers
.create(kwargs
['name'],
606 meta
= kwargs
['metadata'],
607 files
= kwargs
['files'],
608 reservation_id
= None,
611 userdata
= kwargs
['userdata'],
612 security_groups
= kwargs
['security_groups'],
613 availability_zone
= kwargs
['availability_zone'],
614 block_device_mapping_v2
= kwargs
['block_device_mapping_v2'],
616 scheduler_hints
= kwargs
['scheduler_hints'],
617 config_drive
= kwargs
['config_drive'])
618 except Exception as e
:
619 logger
.info("OpenstackDriver: Create Server operation failed. Exception: %s" %(str(e
)))
621 return server
.to_dict()['id']
623 def server_delete(self
, server_id
):
625 Deletes a server identified by server_id
628 server_id (string): UUID of the server to be deleted
632 nvconn
= self
._get
_nova
_connection
()
634 nvconn
.servers
.delete(server_id
)
635 except Exception as e
:
636 logger
.error("OpenstackDriver: Delete server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
639 def server_start(self
, server_id
):
641 Starts a server identified by server_id
644 server_id (string): UUID of the server to be started
648 nvconn
= self
._get
_nova
_connection
()
650 nvconn
.servers
.start(server_id
)
651 except Exception as e
:
652 logger
.error("OpenstackDriver: Start Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
655 def server_stop(self
, server_id
):
658 server_id (string): UUID of the server to be stopped
662 nvconn
= self
._get
_nova
_connection
()
664 nvconn
.servers
.stop(server_id
)
665 except Exception as e
:
666 logger
.error("OpenstackDriver: Stop Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
669 def server_pause(self
, server_id
):
672 server_id (string): UUID of the server to be paused
676 nvconn
= self
._get
_nova
_connection
()
678 nvconn
.servers
.pause(server_id
)
679 except Exception as e
:
680 logger
.error("OpenstackDriver: Pause Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
683 def server_unpause(self
, server_id
):
686 server_id (string): UUID of the server to be unpaused
690 nvconn
= self
._get
_nova
_connection
()
692 nvconn
.servers
.unpause(server_id
)
693 except Exception as e
:
694 logger
.error("OpenstackDriver: Resume Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
698 def server_suspend(self
, server_id
):
701 server_id (string): UUID of the server to be suspended
705 nvconn
= self
._get
_nova
_connection
()
707 nvconn
.servers
.suspend(server_id
)
708 except Exception as e
:
709 logger
.error("OpenstackDriver: Suspend Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
712 def server_resume(self
, server_id
):
715 server_id (string): UUID of the server to be resumed
719 nvconn
= self
._get
_nova
_connection
()
721 nvconn
.servers
.resume(server_id
)
722 except Exception as e
:
723 logger
.error("OpenstackDriver: Resume Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
726 def server_reboot(self
, server_id
, reboot_type
):
729 server_id (string) : UUID of the server to be rebooted
735 nvconn
= self
._get
_nova
_connection
()
737 nvconn
.servers
.reboot(server_id
, reboot_type
)
738 except Exception as e
:
739 logger
.error("OpenstackDriver: Reboot Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
742 def server_console(self
, server_id
, console_type
= 'novnc'):
745 server_id (string) : UUID of the server to be rebooted
746 console_type(string):
750 A dictionary object response for console information
752 nvconn
= self
._get
_nova
_connection
()
754 console_info
= nvconn
.servers
.get_vnc_console(server_id
, console_type
)
755 except Exception as e
:
756 logger
.error("OpenstackDriver: Server Get-Console operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
760 def server_rebuild(self
, server_id
, image_id
):
763 server_id (string) : UUID of the server to be rebooted
764 image_id (string) : UUID of the image to use
768 nvconn
= self
._get
_nova
_connection
()
770 nvconn
.servers
.rebuild(server_id
, image_id
)
771 except Exception as e
:
772 logger
.error("OpenstackDriver: Rebuild Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
776 def server_add_port(self
, server_id
, port_id
):
779 server_id (string): UUID of the server
780 port_id (string): UUID of the port to be attached
784 nvconn
= self
._get
_nova
_connection
()
786 nvconn
.servers
.interface_attach(server_id
,
790 except Exception as e
:
791 logger
.error("OpenstackDriver: Server Port Add operation failed for server_id : %s, port_id : %s. Exception: %s" %(server_id
, port_id
, str(e
)))
794 def server_delete_port(self
, server_id
, port_id
):
797 server_id (string): UUID of the server
798 port_id (string): UUID of the port to be deleted
802 nvconn
= self
._get
_nova
_connection
()
804 nvconn
.servers
.interface_detach(server_id
, port_id
)
805 except Exception as e
:
806 logger
.error("OpenstackDriver: Server Port Delete operation failed for server_id : %s, port_id : %s. Exception: %s" %(server_id
, port_id
, str(e
)))
809 def floating_ip_list(self
):
814 List of objects of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
816 nvconn
= self
._get
_nova
_connection
()
818 ip_list
= nvconn
.floating_ips
.list()
819 except Exception as e
:
820 logger
.error("OpenstackDriver: Floating IP List operation failed. Exception: %s" %str
(e
))
825 def floating_ip_create(self
, pool
):
828 pool (string): Name of the pool (optional)
830 An object of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
832 nvconn
= self
._get
_nova
_connection
()
834 floating_ip
= nvconn
.floating_ips
.create(pool
)
835 except Exception as e
:
836 logger
.error("OpenstackDriver: Floating IP Create operation failed. Exception: %s" %str
(e
))
841 def floating_ip_delete(self
, floating_ip
):
844 floating_ip: An object of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
848 nvconn
= self
._get
_nova
_connection
()
850 floating_ip
= nvconn
.floating_ips
.delete(floating_ip
)
851 except Exception as e
:
852 logger
.error("OpenstackDriver: Floating IP Delete operation failed. Exception: %s" %str
(e
))
855 def floating_ip_assign(self
, server_id
, floating_ip
, fixed_ip
):
858 server_id (string) : UUID of the server
859 floating_ip (string): IP address string for floating-ip
860 fixed_ip (string) : IP address string for the fixed-ip with which floating ip will be associated
864 nvconn
= self
._get
_nova
_connection
()
866 nvconn
.servers
.add_floating_ip(server_id
, floating_ip
, fixed_ip
)
867 except Exception as e
:
868 logger
.error("OpenstackDriver: Assign Floating IP operation failed. Exception: %s" %str
(e
))
871 def floating_ip_release(self
, server_id
, floating_ip
):
874 server_id (string) : UUID of the server
875 floating_ip (string): IP address string for floating-ip
879 nvconn
= self
._get
_nova
_connection
()
881 nvconn
.servers
.remove_floating_ip(server_id
, floating_ip
)
882 except Exception as e
:
883 logger
.error("OpenstackDriver: Release Floating IP operation failed. Exception: %s" %str
(e
))
886 def volume_list(self
, server_id
):
888 List of volumes attached to the server
893 List of dictionary objects where dictionary is representation of class (novaclient.v2.volumes.Volume)
895 nvconn
= self
._get
_nova
_connection
()
897 volumes
= nvconn
.volumes
.get_server_volumes(server_id
=server_id
)
898 except Exception as e
:
899 logger
.error("OpenstackDriver: Get volume information failed. Exception: %s" %str
(e
))
902 volume_info
= [v
.to_dict() for v
in volumes
]
906 def group_list(self
):
908 List of Server Affinity and Anti-Affinity Groups
913 List of dictionary objects where dictionary is representation of class (novaclient.v2.server_groups.ServerGroup)
915 nvconn
= self
._get
_nova
_connection
()
917 group_list
= nvconn
.server_groups
.list()
918 except Exception as e
:
919 logger
.error("OpenstackDriver: Server Group List operation failed. Exception: %s" %str
(e
))
922 group_info
= [ group
.to_dict() for group
in group_list
]
927 class NovaDriverV2(NovaDriver
):
929 Driver class for novaclient V2 APIs
931 def __init__(self
, ks_drv
):
933 Constructor for NovaDriver
934 Arguments: KeystoneDriver class object
936 super(NovaDriverV2
, self
).__init
__(ks_drv
, 'compute', '2.0')
938 class NovaDriverV21(NovaDriver
):
940 Driver class for novaclient V2 APIs
942 def __init__(self
, ks_drv
):
944 Constructor for NovaDriver
945 Arguments: KeystoneDriver class object
947 super(NovaDriverV21
, self
).__init
__(ks_drv
, 'compute', '2.1')
949 class GlanceDriver(object):
951 Driver for openstack glance-client
953 def __init__(self
, ks_drv
, service_name
, version
):
955 Constructor for GlanceDriver
956 Arguments: KeystoneDriver class object
959 self
._service
_name
= service_name
960 self
._version
= version
962 def _get_glance_credentials(self
):
964 Returns a dictionary of kwargs required to instantiate python-glanceclient class
969 A dictionary object of arguments
972 creds
['version'] = self
._version
973 creds
['endpoint'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, 'publicURL')
974 creds
['token'] = self
.ks_drv
.get_auth_token()
975 creds
['insecure'] = self
.ks_drv
.get_security_mode()
978 def _get_glance_connection(self
):
980 Returns a object of class python-glanceclient
982 if not hasattr(self
, '_glance_connection'):
983 self
._glance
_connection
= glclient
.Client(**self
._get
_glance
_credentials
())
985 # Reinitialize if auth_token is no longer valid
986 if not self
.ks_drv
.is_auth_token_valid():
987 self
._glance
_connection
= glclient
.Client(**self
._get
_glance
_credentials
())
988 return self
._glance
_connection
990 def image_list(self
):
992 Returns list of dictionaries. Each dictionary contains attributes associated with
997 Returns: List of dictionaries.
999 glconn
= self
._get
_glance
_connection
()
1002 image_info
= glconn
.images
.list()
1003 except Exception as e
:
1004 logger
.error("OpenstackDriver: List Image operation failed. Exception: %s" %(str(e
)))
1006 images
= [ img
for img
in image_info
]
1009 def image_create(self
, **kwargs
):
1013 A dictionary of kwargs with following keys
1015 'name'(string) : Name of the image
1016 'location'(string) : URL (http://....) where image is located
1017 'disk_format'(string) : Disk format
1018 Possible values are 'ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso'
1019 'container_format'(string): Container format
1020 Possible values are 'ami', 'ari', 'aki', 'bare', 'ovf'
1021 'tags' : A list of user tags
1022 'checksum' : The image md5 checksum
1025 image_id (string) : UUID of the image
1028 glconn
= self
._get
_glance
_connection
()
1030 image
= glconn
.images
.create(**kwargs
)
1031 except Exception as e
:
1032 logger
.error("OpenstackDriver: Create Image operation failed. Exception: %s" %(str(e
)))
1037 def image_upload(self
, image_id
, fd
):
1042 image_id: UUID of the image
1043 fd : File descriptor for the image file
1046 glconn
= self
._get
_glance
_connection
()
1048 glconn
.images
.upload(image_id
, fd
)
1049 except Exception as e
:
1050 logger
.error("OpenstackDriver: Image upload operation failed. Exception: %s" %(str(e
)))
1053 def image_add_location(self
, image_id
, location
, metadata
):
1055 Add image URL location
1058 image_id : UUID of the image
1059 location : http URL for the image
1063 glconn
= self
._get
_glance
_connection
()
1065 image
= glconn
.images
.add_location(image_id
, location
, metadata
)
1066 except Exception as e
:
1067 logger
.error("OpenstackDriver: Image location add operation failed. Exception: %s" %(str(e
)))
1070 def image_update(self
):
1073 def image_delete(self
, image_id
):
1078 image_id: UUID of the image
1083 assert image_id
== self
._image
_get
(image_id
)['id']
1084 glconn
= self
._get
_glance
_connection
()
1086 glconn
.images
.delete(image_id
)
1087 except Exception as e
:
1088 logger
.error("OpenstackDriver: Delete Image operation failed for image_id : %s. Exception: %s" %(image_id
, str(e
)))
1092 def _image_get(self
, image_id
):
1094 Returns a dictionary object of VM image attributes
1097 image_id (string): UUID of the image
1100 A dictionary of the image attributes
1102 glconn
= self
._get
_glance
_connection
()
1104 image
= glconn
.images
.get(image_id
)
1105 except GlanceException
.HTTPBadRequest
:
1106 # RIFT-14241: The get image request occasionally returns the below message. Retry in case of bad request exception.
1107 # Error code 400.: Message: Bad request syntax ('0').: Error code explanation: 400 = Bad request syntax or unsupported method. (HTTP 400)
1108 logger
.warning("OpenstackDriver: Got bad request response during get_image request. Retrying.")
1109 image
= glconn
.images
.get(image_id
)
1110 except Exception as e
:
1111 logger
.error("OpenstackDriver: Get Image operation failed for image_id : %s. Exception: %s" %(image_id
, str(e
)))
1116 def image_get(self
, image_id
):
1118 Returns a dictionary object of VM image attributes
1121 image_id (string): UUID of the image
1124 A dictionary of the image attributes
1126 return self
._image
_get
(image_id
)
1128 class GlanceDriverV2(GlanceDriver
):
1130 Driver for openstack glance-client V2
1132 def __init__(self
, ks_drv
):
1133 super(GlanceDriverV2
, self
).__init
__(ks_drv
, 'image', 2)
1135 class NeutronDriver(object):
1137 Driver for openstack neutron neutron-client
1139 def __init__(self
, ks_drv
, service_name
, version
):
1141 Constructor for NeutronDriver
1142 Arguments: KeystoneDriver class object
1144 self
.ks_drv
= ks_drv
1145 self
._service
_name
= service_name
1146 self
._version
= version
1148 def _get_neutron_credentials(self
):
1150 Returns a dictionary of kwargs required to instantiate python-neutronclient class
1153 Dictionary of kwargs
1156 creds
['api_version'] = self
._version
1157 creds
['endpoint_url'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, 'publicURL')
1158 creds
['token'] = self
.ks_drv
.get_auth_token()
1159 creds
['tenant_name'] = self
.ks_drv
.get_tenant_name()
1160 creds
['insecure'] = self
.ks_drv
.get_security_mode()
1163 def _get_neutron_connection(self
):
1165 Returns an object of class python-neutronclient
1167 if not hasattr(self
, '_neutron_connection'):
1168 self
._neutron
_connection
= ntclient
.Client(**self
._get
_neutron
_credentials
())
1170 # Reinitialize if auth_token is no longer valid
1171 if not self
.ks_drv
.is_auth_token_valid():
1172 self
._neutron
_connection
= ntclient
.Client(**self
._get
_neutron
_credentials
())
1173 return self
._neutron
_connection
1175 def network_list(self
):
1177 Returns list of dictionaries. Each dictionary contains the attributes for a network
1183 A list of dictionaries
1186 ntconn
= self
._get
_neutron
_connection
()
1188 networks
= ntconn
.list_networks()
1189 except Exception as e
:
1190 logger
.error("OpenstackDriver: List Network operation failed. Exception: %s" %(str(e
)))
1192 return networks
['networks']
1194 def network_create(self
, **kwargs
):
1196 Creates a new network for the project
1199 A dictionary with following key-values
1201 name (string) : Name of the network
1202 admin_state_up(Boolean) : True/False (Defaults: True)
1203 external_router(Boolean) : Connectivity with external router. True/False (Defaults: False)
1204 shared(Boolean) : Shared among tenants. True/False (Defaults: False)
1205 physical_network(string) : The physical network where this network object is implemented (optional).
1206 network_type : The type of physical network that maps to this network resource (optional).
1207 Possible values are: 'flat', 'vlan', 'vxlan', 'gre'
1208 segmentation_id : An isolated segment on the physical network. The network_type attribute
1209 defines the segmentation model. For example, if the network_type value
1210 is vlan, this ID is a vlan identifier. If the network_type value is gre,
1211 this ID is a gre key.
1214 params
= {'network':
1215 {'name' : kwargs
['name'],
1216 'admin_state_up' : kwargs
['admin_state_up'],
1217 'tenant_id' : self
.ks_drv
.get_tenant_id(),
1218 'shared' : kwargs
['shared'],
1219 #'port_security_enabled': port_security_enabled,
1220 'router:external' : kwargs
['external_router']}}
1222 if 'physical_network' in kwargs
:
1223 params
['network']['provider:physical_network'] = kwargs
['physical_network']
1224 if 'network_type' in kwargs
:
1225 params
['network']['provider:network_type'] = kwargs
['network_type']
1226 if 'segmentation_id' in kwargs
:
1227 params
['network']['provider:segmentation_id'] = kwargs
['segmentation_id']
1229 ntconn
= self
._get
_neutron
_connection
()
1231 logger
.debug("Calling neutron create_network() with params: %s", str(params
))
1232 net
= ntconn
.create_network(params
)
1233 except Exception as e
:
1234 logger
.error("OpenstackDriver: Create Network operation failed. Exception: %s" %(str(e
)))
1236 logger
.debug("Got create_network response from neutron connection: %s", str(net
))
1237 network_id
= net
['network']['id']
1239 raise Exception("Empty network id returned from create_network. (params: %s)" % str(params
))
1243 def network_delete(self
, network_id
):
1245 Deletes a network identified by network_id
1248 network_id (string): UUID of the network
1252 assert network_id
== self
._network
_get
(network_id
)['id']
1253 ntconn
= self
._get
_neutron
_connection
()
1255 ntconn
.delete_network(network_id
)
1256 except Exception as e
:
1257 logger
.error("OpenstackDriver: Delete Network operation failed. Exception: %s" %(str(e
)))
1260 def _network_get(self
, network_id
):
1262 Returns a dictionary object describing the attributes of the network
1265 network_id (string): UUID of the network
1268 A dictionary object of the network attributes
1270 ntconn
= self
._get
_neutron
_connection
()
1271 network
= ntconn
.list_networks(id = network_id
)['networks']
1273 raise NeutronException
.NotFound("Network with id %s not found"%(network_id))
1277 def network_get(self
, network_id
):
1279 Returns a dictionary object describing the attributes of the network
1282 network_id (string): UUID of the network
1285 A dictionary object of the network attributes
1287 return self
._network
_get
(network_id
)
1289 def subnet_create(self
, **kwargs
):
1291 Creates a subnet on the network
1294 A dictionary with following key value pairs
1296 network_id(string) : UUID of the network where subnet needs to be created
1297 subnet_cidr(string) : IPv4 address prefix (e.g. '1.1.1.0/24') for the subnet
1298 ip_version (integer): 4 for IPv4 and 6 for IPv6
1303 subnet_id (string): UUID of the created subnet
1306 params
['network_id'] = kwargs
['network_id']
1307 params
['ip_version'] = kwargs
['ip_version']
1309 # if params['ip_version'] == 6:
1310 # assert 0, "IPv6 is not supported"
1312 if 'subnetpool_id' in kwargs
:
1313 params
['subnetpool_id'] = kwargs
['subnetpool_id']
1315 params
['cidr'] = kwargs
['cidr']
1317 if 'gateway_ip' in kwargs
:
1318 params
['gateway_ip'] = kwargs
['gateway_ip']
1320 params
['gateway_ip'] = None
1322 if 'dhcp_params' in kwargs
:
1323 params
['enable_dhcp'] = kwargs
['dhcp_params']['enable_dhcp']
1324 if 'start_address' in kwargs
['dhcp_params'] and 'count' in kwargs
['dhcp_params']:
1325 end_address
= (ipaddress
.IPv4Address(kwargs
['dhcp_params']['start_address']) + kwargs
['dhcp_params']['count']).compressed
1326 params
['allocation_pools'] = [ {'start': kwargs
['dhcp_params']['start_address'] ,
1327 'end' : end_address
} ]
1329 if 'dns_server' in kwargs
:
1330 params
['dns_nameservers'] = []
1331 for server
in kwargs
['dns_server']:
1332 params
['dns_nameservers'].append(server
)
1334 ntconn
= self
._get
_neutron
_connection
()
1336 subnet
= ntconn
.create_subnet({'subnets': [params
]})
1337 except Exception as e
:
1338 logger
.error("OpenstackDriver: Create Subnet operation failed. Exception: %s" %(str(e
)))
1341 return subnet
['subnets'][0]['id']
1343 def subnet_list(self
):
1345 Returns a list of dictionaries. Each dictionary contains attributes describing the subnet
1350 A dictionary of the objects of subnet attributes
1352 ntconn
= self
._get
_neutron
_connection
()
1354 subnets
= ntconn
.list_subnets()['subnets']
1355 except Exception as e
:
1356 logger
.error("OpenstackDriver: List Subnet operation failed. Exception: %s" %(str(e
)))
1360 def _subnet_get(self
, subnet_id
):
1362 Returns a dictionary object describing the attributes of a subnet.
1365 subnet_id (string): UUID of the subnet
1368 A dictionary object of the subnet attributes
1370 ntconn
= self
._get
_neutron
_connection
()
1371 subnets
= ntconn
.list_subnets(id=subnet_id
)
1372 if not subnets
['subnets']:
1373 logger
.error("OpenstackDriver: Get subnet operation failed for subnet_id: %s" %(subnet_id))
1374 #raise NeutronException.NotFound("Could not find subnet_id %s" %(subnet_id))
1377 return subnets
['subnets'][0]
1379 def subnet_get(self
, subnet_id
):
1381 Returns a dictionary object describing the attributes of a subnet.
1384 subnet_id (string): UUID of the subnet
1387 A dictionary object of the subnet attributes
1389 return self
._subnet
_get
(subnet_id
)
1391 def subnet_delete(self
, subnet_id
):
1393 Deletes a subnet identified by subnet_id
1396 subnet_id (string): UUID of the subnet to be deleted
1400 ntconn
= self
._get
_neutron
_connection
()
1401 assert subnet_id
== self
._subnet
_get
(self
,subnet_id
)
1403 ntconn
.delete_subnet(subnet_id
)
1404 except Exception as e
:
1405 logger
.error("OpenstackDriver: Delete Subnet operation failed for subnet_id : %s. Exception: %s" %(subnet_id
, str(e
)))
1408 def port_list(self
, **kwargs
):
1410 Returns a list of dictionaries. Each dictionary contains attributes describing the port
1413 kwargs (dictionary): A dictionary for filters for port_list operation
1416 A dictionary of the objects of port attributes
1420 ntconn
= self
._get
_neutron
_connection
()
1422 kwargs
['tenant_id'] = self
.ks_drv
.get_tenant_id()
1425 ports
= ntconn
.list_ports(**kwargs
)
1426 except Exception as e
:
1427 logger
.info("OpenstackDriver: List Port operation failed. Exception: %s" %(str(e
)))
1429 return ports
['ports']
1431 def port_create(self
, **kwargs
):
1433 Create a port in network
1436 A dictionary of following
1438 name (string) : Name of the port
1439 network_id(string) : UUID of the network_id identifying the network to which port belongs
1440 subnet_id(string) : UUID of the subnet_id from which IP-address will be assigned to port
1441 vnic_type(string) : Possible values are "normal", "direct", "macvtap"
1444 port_id (string) : UUID of the port
1448 "admin_state_up" : kwargs
['admin_state_up'],
1449 "name" : kwargs
['name'],
1450 "network_id" : kwargs
['network_id'],
1451 "fixed_ips" : [ {"subnet_id": kwargs
['subnet_id']}],
1452 "binding:vnic_type" : kwargs
['port_type']}}
1453 if 'port_security_enabled' in kwargs
:
1454 params
["port"]["port_security_enabled"] = kwargs
['port_security_enabled']
1456 ntconn
= self
._get
_neutron
_connection
()
1458 port
= ntconn
.create_port(params
)
1459 except Exception as e
:
1460 logger
.error("OpenstackDriver: Port Create operation failed. Exception: %s" %(str(e
)))
1462 return port
['port']['id']
1464 def _port_get(self
, port_id
):
1466 Returns a dictionary object describing the attributes of the port
1469 port_id (string): UUID of the port
1472 A dictionary object of the port attributes
1474 ntconn
= self
._get
_neutron
_connection
()
1475 port
= ntconn
.list_ports(id=port_id
)['ports']
1477 raise NeutronException
.NotFound("Could not find port_id %s" %(port_id))
1480 def port_get(self
, port_id
):
1482 Returns a dictionary object describing the attributes of the port
1485 port_id (string): UUID of the port
1488 A dictionary object of the port attributes
1490 return self
._port
_get
(port_id
)
1492 def port_delete(self
, port_id
):
1494 Deletes a port identified by port_id
1497 port_id (string) : UUID of the port
1501 assert port_id
== self
._port
_get
(port_id
)['id']
1502 ntconn
= self
._get
_neutron
_connection
()
1504 ntconn
.delete_port(port_id
)
1505 except Exception as e
:
1506 logger
.error("Port Delete operation failed for port_id : %s. Exception: %s" %(port_id
, str(e
)))
1509 def security_group_list(self
):
1511 Returns a list of dictionaries. Each dictionary contains attributes describing the security group
1517 A dictionary of the objects of security group attributes
1519 ntconn
= self
._get
_neutron
_connection
()
1521 group_list
= ntconn
.list_security_groups(tenant_id
=self
.ks_drv
.get_tenant_id())
1522 except Exception as e
:
1523 logger
.error("List Security group operation, Exception: %s" %(str(e
)))
1526 if 'security_groups' in group_list
:
1527 return group_list
['security_groups']
1531 def subnetpool_list(self
, **kwargs
):
1533 Returns a list of dictionaries. Each dictionary contains attributes describing a subnet prefix pool
1539 A dictionary of the objects of subnet prefix pool
1541 ntconn
= self
._get
_neutron
_connection
()
1543 pool_list
= ntconn
.list_subnetpools(**kwargs
)
1544 except Exception as e
:
1545 logger
.error("List SubnetPool operation, Exception: %s" %(str(e
)))
1548 if 'subnetpools' in pool_list
:
1549 return pool_list
['subnetpools']
1553 class NeutronDriverV2(NeutronDriver
):
1555 Driver for openstack neutron neutron-client v2
1557 def __init__(self
, ks_drv
):
1559 Constructor for NeutronDriver
1560 Arguments: KeystoneDriver class object
1562 super(NeutronDriverV2
, self
).__init
__(ks_drv
, 'network', '2.0')
1566 class CeilometerDriver(object):
1568 Driver for openstack ceilometer client
1571 def __init__(self
, ks_drv
, service_name
, version
):
1573 Constructor for CeilometerDriver
1574 Arguments: KeystoneDriver class object
1576 self
.ks_drv
= ks_drv
1577 self
._service
_name
= service_name
1578 self
._version
= version
1583 """The version of the ceilometer client used by the driver"""
1584 return self
._version
1588 """The instance of ceilometer client used by the driver"""
1589 if self
._client
is None or not self
.ks_drv
.is_auth_token_valid():
1590 self
._client
= ceilo_client
.Client(**self
.credentials
)
1595 def auth_token(self
):
1596 """The authorization token for the ceilometer client"""
1598 return self
.ks_drv
.get_auth_token()
1599 except KeystoneExceptions
.EndpointNotFound
as e
:
1600 logger
.error("OpenstackDriver: unable to get authorization token for ceilometer. Exception: %s" %(str(e
)))
1604 def security_mode(self
):
1605 """The security mode for the ceilometer client"""
1607 return self
.ks_drv
.get_security_mode()
1608 except KeystoneExceptions
.EndpointNotFound
as e
:
1609 logger
.error("OpenstackDriver: unable to get security mode for ceilometer. Exception: %s" %(str(e
)))
1614 """The service endpoint for the ceilometer client"""
1616 return self
.ks_drv
.get_service_endpoint(self
._service
_name
, "publicURL")
1617 except KeystoneExceptions
.EndpointNotFound
as e
:
1618 logger
.error("OpenstackDriver: unable to get endpoint for ceilometer. Exception: %s" %(str(e
)))
1622 def credentials(self
):
1623 """A dictionary of credentials for the ceilometer client"""
1625 version
=self
.version
,
1626 endpoint
=self
.endpoint
,
1627 token
=self
.auth_token
,
1628 insecure
=self
.security_mode
,
1633 """A list of the available meters"""
1635 return self
.client
.meters
.list()
1636 except Exception as e
:
1637 logger
.error("OpenstackDriver: List meters operation failed. Exception: %s" %(str(e
)))
1642 """The ceilometer client alarms manager"""
1643 return self
.client
.alarms
1645 def query_samples(self
, vim_instance_id
, counter_name
, limit
=1):
1646 """Returns a list of samples
1649 vim_instance_id - the ID of the VIM that the samples are from
1650 counter_name - the counter that the samples will come from
1651 limit - a limit on the number of samples to return
1659 filter = json
.dumps({
1661 {"=": {"resource": vim_instance_id
}},
1662 {"=": {"counter_name": counter_name
}}
1665 result
= self
.client
.query_samples
.query(filter=filter, limit
=limit
)
1666 return result
[-limit
:]
1668 except Exception as e
:
1674 class CeilometerDriverV2(CeilometerDriver
):
1676 Driver for openstack ceilometer ceilometer-client
1678 def __init__(self
, ks_drv
):
1680 Constructor for CeilometerDriver
1681 Arguments: CeilometerDriver class object
1683 super(CeilometerDriverV2
, self
).__init
__(ks_drv
, 'metering', '2')
1685 class OpenstackDriver(object):
1687 Driver for openstack nova, neutron, glance, keystone, swift, cinder services
1689 def __init__(self
, username
,
1693 mgmt_network
= None,
1694 cert_validate
= False,
1695 user_domain_name
= None,
1696 project_domain_name
= None,
1699 OpenstackDriver Driver constructor
1701 username (string) : Username for project/tenant.
1702 password (string) : Password
1703 auth_url (string) : Keystone Authentication URL.
1704 tenant_name (string) : Openstack project name
1705 mgmt_network(string, optional) : Management network name. Each VM created with this cloud-account will
1706 have a default interface into management network.
1707 cert_validate (boolean, optional) : In case of SSL/TLS connection if certificate validation is required or not.
1708 user_domain_name : Domain name for user
1709 project_domain_name : Domain name for project
1710 region : Region name
1712 insecure
= not cert_validate
1713 if auth_url
.find('/v3') != -1:
1714 self
.ks_drv
= KeystoneDriverV3(username
,
1720 project_domain_name
,
1722 self
.glance_drv
= GlanceDriverV2(self
.ks_drv
)
1723 self
.nova_drv
= NovaDriverV21(self
.ks_drv
)
1724 self
.neutron_drv
= NeutronDriverV2(self
.ks_drv
)
1725 self
.ceilo_drv
= CeilometerDriverV2(self
.ks_drv
)
1726 self
.cinder_drv
= CinderDriverV2(self
.ks_drv
)
1727 elif auth_url
.find('/v2') != -1:
1729 self
.ks_drv
= KeystoneDriverV2(username
,
1735 self
.glance_drv
= GlanceDriverV2(self
.ks_drv
)
1736 self
.nova_drv
= NovaDriverV2(self
.ks_drv
)
1737 self
.neutron_drv
= NeutronDriverV2(self
.ks_drv
)
1738 self
.ceilo_drv
= CeilometerDriverV2(self
.ks_drv
)
1739 self
.cinder_drv
= CinderDriverV2(self
.ks_drv
)
1741 logger
.error("Could not identity the version information for openstack service endpoints. Auth_URL should contain \"/v2\" or \"/v3\" string in it")
1742 raise NotImplementedError("Auth URL is wrong or invalid. Only Keystone v2 & v3 supported")
1744 self
._mgmt
_network
_id
= None
1745 if mgmt_network
!= None:
1746 self
._mgmt
_network
= mgmt_network
1750 ntconn
= self
.neutron_drv
._get
_neutron
_connection
()
1751 networks
= ntconn
.list_networks()
1752 except (KeystoneExceptions
.Unauthorized
, KeystoneExceptions
.AuthorizationFailure
) as e
:
1754 except Exception as e
:
1755 logger
.error("OpenstackDriver: List Network operation failed. Exception: %s" %(str(e
)))
1758 network_list
= [ network
for network
in networks
['networks'] if network
['name'] == mgmt_network
]
1760 if not network_list
:
1761 raise NeutronException
.NotFound("Could not find network %s" %(mgmt_network))
1762 self
._mgmt
_network
_id
= network_list
[0]['id']
1764 def validate_account_creds(self
):
1766 ksconn
= self
.ks_drv
._get
_keystone
_connection
()
1767 except KeystoneExceptions
.AuthorizationFailure
as e
:
1768 logger
.error("OpenstackDriver: Unable to authenticate or validate the existing credentials. Exception: %s" %(str(e
)))
1769 raise ValidationError("Invalid Credentials: "+ str(e
))
1770 except Exception as e
:
1771 logger
.error("OpenstackDriver: Could not connect to Openstack. Exception: %s" %(str(e
)))
1772 raise ValidationError("Connection Error: "+ str(e
))
1774 def get_mgmt_network_id(self
):
1775 return self
._mgmt
_network
_id
1777 def glance_image_create(self
, **kwargs
):
1778 if not 'disk_format' in kwargs
:
1779 kwargs
['disk_format'] = 'qcow2'
1780 if not 'container_format' in kwargs
:
1781 kwargs
['container_format'] = 'bare'
1782 if not 'min_disk' in kwargs
:
1783 kwargs
['min_disk'] = 0
1784 if not 'min_ram' in kwargs
:
1785 kwargs
['min_ram'] = 0
1786 return self
.glance_drv
.image_create(**kwargs
)
1788 def glance_image_upload(self
, image_id
, fd
):
1789 self
.glance_drv
.image_upload(image_id
, fd
)
1791 def glance_image_add_location(self
, image_id
, location
):
1792 self
.glance_drv
.image_add_location(image_id
, location
)
1794 def glance_image_delete(self
, image_id
):
1795 self
.glance_drv
.image_delete(image_id
)
1797 def glance_image_list(self
):
1798 return self
.glance_drv
.image_list()
1800 def glance_image_get(self
, image_id
):
1801 return self
.glance_drv
.image_get(image_id
)
1804 def nova_flavor_list(self
):
1805 return self
.nova_drv
.flavor_list()
1807 def nova_flavor_create(self
, name
, ram
, vcpus
, disk
, epa_specs
):
1808 extra_specs
= epa_specs
if epa_specs
else {}
1809 return self
.nova_drv
.flavor_create(name
,
1813 extra_specs
= extra_specs
)
1815 def nova_flavor_delete(self
, flavor_id
):
1816 self
.nova_drv
.flavor_delete(flavor_id
)
1818 def nova_flavor_get(self
, flavor_id
):
1819 return self
.nova_drv
.flavor_get(flavor_id
)
1821 def nova_server_create(self
, **kwargs
):
1822 def _verify_image(image_id
):
1823 image
= self
.glance_drv
.image_get(image_id
)
1824 if image
['status'] != 'active':
1825 raise GlanceException
.NotFound("Image with image_id: %s not found in active state. Current State: %s" %(image
['id'], image
['status']))
1827 assert kwargs
['flavor_id'] == self
.nova_drv
.flavor_get(kwargs
['flavor_id'])['id']
1829 if kwargs
['block_device_mapping_v2'] is not None:
1830 for block_map
in kwargs
['block_device_mapping_v2']:
1831 if 'uuid' in block_map
:
1832 _verify_image(block_map
['uuid'])
1834 _verify_image(kwargs
['image_id'])
1836 # if 'network_list' in kwargs:
1837 # kwargs['network_list'].append(self._mgmt_network_id)
1839 # kwargs['network_list'] = [self._mgmt_network_id]
1841 if 'security_groups' not in kwargs
:
1842 nvconn
= self
.nova_drv
._get
_nova
_connection
()
1843 sec_groups
= nvconn
.security_groups
.list()
1845 ## Should we add VM in all availability security_groups ???
1846 kwargs
['security_groups'] = [x
.name
for x
in sec_groups
]
1848 kwargs
['security_groups'] = None
1850 return self
.nova_drv
.server_create(**kwargs
)
1852 def nova_server_add_port(self
, server_id
, port_id
):
1853 self
.nova_drv
.server_add_port(server_id
, port_id
)
1855 def nova_server_delete_port(self
, server_id
, port_id
):
1856 self
.nova_drv
.server_delete_port(server_id
, port_id
)
1858 def nova_server_start(self
, server_id
):
1859 self
.nova_drv
.server_start(server_id
)
1861 def nova_server_stop(self
, server_id
):
1862 self
.nova_drv
.server_stop(server_id
)
1864 def nova_server_delete(self
, server_id
):
1865 self
.nova_drv
.server_delete(server_id
)
1867 def nova_server_reboot(self
, server_id
):
1868 self
.nova_drv
.server_reboot(server_id
, reboot_type
='HARD')
1870 def nova_server_rebuild(self
, server_id
, image_id
):
1871 self
.nova_drv
.server_rebuild(server_id
, image_id
)
1873 def nova_floating_ip_list(self
):
1874 return self
.nova_drv
.floating_ip_list()
1876 def nova_floating_ip_create(self
, pool
= None):
1877 return self
.nova_drv
.floating_ip_create(pool
)
1879 def nova_floating_ip_delete(self
, floating_ip
):
1880 self
.nova_drv
.floating_ip_delete(floating_ip
)
1882 def nova_floating_ip_assign(self
, server_id
, floating_ip
, fixed_ip
):
1883 self
.nova_drv
.floating_ip_assign(server_id
, floating_ip
, fixed_ip
)
1885 def nova_floating_ip_release(self
, server_id
, floating_ip
):
1886 self
.nova_drv
.floating_ip_release(server_id
, floating_ip
)
1888 def nova_server_list(self
):
1889 return self
.nova_drv
.server_list()
1891 def nova_server_get(self
, server_id
):
1892 return self
.nova_drv
.server_get(server_id
)
1894 def nova_server_console(self
, server_id
):
1895 return self
.nova_drv
.server_console(server_id
)
1897 def nova_server_group_list(self
):
1898 return self
.nova_drv
.group_list()
1900 def nova_volume_list(self
, server_id
):
1901 return self
.nova_drv
.volume_list(server_id
)
1903 def neutron_network_list(self
):
1904 return self
.neutron_drv
.network_list()
1906 def neutron_network_get(self
, network_id
):
1907 return self
.neutron_drv
.network_get(network_id
)
1909 def neutron_network_create(self
, **kwargs
):
1910 return self
.neutron_drv
.network_create(**kwargs
)
1912 def neutron_network_delete(self
, network_id
):
1913 self
.neutron_drv
.network_delete(network_id
)
1915 def neutron_subnet_list(self
):
1916 return self
.neutron_drv
.subnet_list()
1918 def neutron_subnet_get(self
, subnet_id
):
1919 return self
.neutron_drv
.subnet_get(subnet_id
)
1921 def neutron_subnet_create(self
, **kwargs
):
1922 return self
.neutron_drv
.subnet_create(**kwargs
)
1924 def netruon_subnet_delete(self
, subnet_id
):
1925 self
.neutron_drv
.subnet_delete(subnet_id
)
1927 def neutron_subnetpool_list(self
):
1928 return self
.neutron_drv
.subnetpool_list()
1930 def netruon_subnetpool_by_name(self
, pool_name
):
1931 pool_list
= self
.neutron_drv
.subnetpool_list(**{'name': pool_name
})
1937 def neutron_port_list(self
, **kwargs
):
1938 return self
.neutron_drv
.port_list(**kwargs
)
1940 def neutron_port_get(self
, port_id
):
1941 return self
.neutron_drv
.port_get(port_id
)
1943 def neutron_port_create(self
, **kwargs
):
1944 subnets
= [subnet
for subnet
in self
.neutron_drv
.subnet_list() if subnet
['network_id'] == kwargs
['network_id']]
1945 assert len(subnets
) == 1
1946 kwargs
['subnet_id'] = subnets
[0]['id']
1947 if not 'admin_state_up' in kwargs
:
1948 kwargs
['admin_state_up'] = True
1949 port_id
= self
.neutron_drv
.port_create(**kwargs
)
1951 if 'vm_id' in kwargs
:
1952 self
.nova_server_add_port(kwargs
['vm_id'], port_id
)
1955 def neutron_security_group_list(self
):
1956 return self
.neutron_drv
.security_group_list()
1958 def neutron_security_group_by_name(self
, group_name
):
1959 group_list
= self
.neutron_drv
.security_group_list()
1960 groups
= [group
for group
in group_list
if group
['name'] == group_name
]
1966 def neutron_port_delete(self
, port_id
):
1967 self
.neutron_drv
.port_delete(port_id
)
1969 def ceilo_meter_endpoint(self
):
1970 return self
.ceilo_drv
.endpoint
1972 def ceilo_meter_list(self
):
1973 return self
.ceilo_drv
.meters
1975 def ceilo_nfvi_metrics(self
, vim_id
):
1976 """Returns a dict of NFVI metrics for a given VM
1979 vim_id - the VIM ID of the VM to retrieve the metrics for
1982 A dict of NFVI metrics
1985 def query_latest_sample(counter_name
):
1987 filter = json
.dumps({
1989 {"=": {"resource": vim_id
}},
1990 {"=": {"counter_name": counter_name
}}
1993 orderby
= json
.dumps([{"timestamp": "DESC"}])
1994 result
= self
.ceilo_drv
.client
.query_samples
.query(
2004 except Exception as e
:
2005 logger
.error("Got exception while querying ceilometer, exception details:%s " %str
(e
))
2009 memory_usage
= query_latest_sample("memory.usage")
2010 disk_usage
= query_latest_sample("disk.usage")
2011 cpu_util
= query_latest_sample("cpu_util")
2015 if memory_usage
is not None:
2016 memory_usage
.volume
= 1e6
* memory_usage
.volume
2017 metrics
["memory_usage"] = memory_usage
.to_dict()
2019 if disk_usage
is not None:
2020 metrics
["disk_usage"] = disk_usage
.to_dict()
2022 if cpu_util
is not None:
2023 metrics
["cpu_util"] = cpu_util
.to_dict()
2027 def ceilo_alarm_list(self
):
2028 """Returns a list of ceilometer alarms"""
2029 return self
.ceilo_drv
.client
.alarms
.list()
2031 def ceilo_alarm_create(self
,
2044 """Create a new Alarm
2047 name - the name of the alarm
2048 meter - the name of the meter to measure
2049 statistic - the type of statistic used to trigger the alarm
2050 ('avg', 'min', 'max', 'count', 'sum')
2051 operation - the relational operator that, combined with the
2052 threshold value, determines when the alarm is
2053 triggered ('lt', 'le', 'eq', 'ge', 'gt')
2054 threshold - the value of the statistic that will trigger the
2056 period - the duration (seconds) over which to evaluate the
2058 evaluations - the number of samples of the meter statistic to
2059 collect when evaluating the threshold
2060 severity - a measure of the urgency or importance of the alarm
2061 ('low', 'moderate', 'critical')
2062 repeat - a flag that indicates whether the alarm should be
2063 triggered once (False) or repeatedly while the alarm
2064 condition is true (True)
2065 enabled - a flag that indicates whether the alarm is enabled
2066 (True) or disabled (False)
2067 actions - a dict specifying the URLs for webhooks. The dict can
2068 have up to 3 keys: 'insufficient_data', 'alarm',
2069 'ok'. Each key is associated with a list of URLs to
2070 webhooks that will be invoked when one of the 3
2072 kwargs - an arbitrary dict of keyword arguments that are
2073 passed to the ceilometer client
2076 ok_actions
= actions
.get('ok') if actions
is not None else None
2077 alarm_actions
= actions
.get('alarm') if actions
is not None else None
2078 insufficient_data_actions
= actions
.get('insufficient_data') if actions
is not None else None
2080 return self
.ceilo_drv
.client
.alarms
.create(
2083 statistic
=statistic
,
2084 comparison_operator
=operation
,
2085 threshold
=threshold
,
2087 evaluation_periods
=evaluations
,
2089 repeat_actions
=repeat
,
2091 ok_actions
=ok_actions
,
2092 alarm_actions
=alarm_actions
,
2093 insufficient_data_actions
=insufficient_data_actions
,
2097 def ceilo_alarm_update(self
, alarm_id
, **kwargs
):
2098 """Updates an existing alarm
2101 alarm_id - the identifier of the alarm to update
2102 kwargs - a dict of the alarm attributes to update
2105 return self
.ceilo_drv
.client
.alarms
.update(alarm_id
, **kwargs
)
2107 def ceilo_alarm_delete(self
, alarm_id
):
2108 self
.ceilo_drv
.client
.alarms
.delete(alarm_id
)
2110 def cinder_volume_list(self
):
2111 return self
.cinder_drv
.volume_list()
2113 def cinder_volume_get(self
,vol_id
):
2114 return self
.cinder_drv
.volume_get(vol_id
)
2116 def cinder_volume_set_metadata(self
, volumeid
, metadata
):
2117 return self
.cinder_drv
.volume_set_metadata(volumeid
, metadata
)
2119 def cinder_volume_delete_metadata(self
, volumeid
, metadata
):
2120 return self
.cinder_drv
.volume_delete_metadata(volumeid
, metadata
)
2124 class CinderDriver(object):
2126 Driver for openstack cinder-client
2128 def __init__(self
, ks_drv
, service_name
, version
):
2130 Constructor for CinderDriver
2131 Arguments: KeystoneDriver class object
2133 self
.ks_drv
= ks_drv
2134 self
._service
_name
= service_name
2135 self
._version
= version
2137 def _get_cinder_credentials(self
):
2139 Returns a dictionary of kwargs required to instantiate python-cinderclient class
2144 A dictionary object of arguments
2147 creds
['version'] = self
._version
2148 creds
['username'] = self
.ks_drv
.get_username()
2149 creds
['api_key'] = self
.ks_drv
.get_password()
2150 creds
['auth_url'] = self
.ks_drv
.get_service_endpoint("identity", "publicURL")
2151 creds
['project_id'] = self
.ks_drv
.get_tenant_name()
2152 creds
['insecure'] = self
.ks_drv
.get_security_mode()
2156 def _get_cinder_connection(self
):
2158 Returns a object of class python-cinderclient
2160 if not hasattr(self
, '_cinder_connection'):
2161 self
._cinder
_connection
= cinder_client
.Client(**self
._get
_cinder
_credentials
())
2163 # Reinitialize if auth_token is no longer valid
2164 if not self
.ks_drv
.is_auth_token_valid():
2165 self
._cinder
_connection
= cinder_client
.Client(**self
._get
_cinder
_credentials
())
2166 return self
._cinder
_connection
2168 def volume_list(self
):
2170 Returns list of dictionaries. Each dictionary contains attributes associated with
2175 Returns: List of dictionaries.
2177 cinderconn
= self
._get
_cinder
_connection
()
2180 volume_info
= cinderconn
.volumes
.list()
2181 except Exception as e
:
2182 logger
.error("OpenstackDriver: List volumes operation failed. Exception: %s" %(str(e
)))
2184 volumes
= [ volume
for volume
in volume_info
]
2187 def volume_get(self
, volume_id
):
2193 Returns: List of dictionaries.
2195 cinderconn
= self
._get
_cinder
_connection
()
2197 vol
= cinderconn
.volumes
.get(volume_id
)
2198 except Exception as e
:
2199 logger
.error("OpenstackDriver: Get volume operation failed. Exception: %s" %(str(e
)))
2203 def volume_set_metadata(self
, volume_id
, metadata
):
2205 Set metadata for volume
2206 Metadata is a dictionary of key-value pairs
2210 Returns: List of dictionaries.
2212 cinderconn
= self
._get
_cinder
_connection
()
2214 cinderconn
.volumes
.set_metadata(volume_id
, metadata
)
2215 except Exception as e
:
2216 logger
.error("OpenstackDriver: Set metadata operation failed. Exception: %s" %(str(e
)))
2219 def volume_delete_metadata(self
, volume_id
, metadata
):
2221 Delete metadata for volume
2222 Metadata is a dictionary of key-value pairs
2226 Returns: List of dictionaries.
2228 cinderconn
= self
._get
_cinder
_connection
()
2230 cinderconn
.volumes
.delete_metadata(volume_id
, metadata
)
2231 except Exception as e
:
2232 logger
.error("OpenstackDriver: Delete metadata operation failed. Exception: %s" %(str(e
)))
2235 class CinderDriverV2(CinderDriver
):
2237 Driver for openstack cinder-client V2
2239 def __init__(self
, ks_drv
):
2240 super(CinderDriverV2
, self
).__init
__(ks_drv
, 'volumev2', 2)