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_keystone_connection(self
):
77 Returns object of class python-keystoneclient class
79 if not hasattr(self
, '_keystone_connection'):
80 self
._keystone
_connection
= self
.ksclient(**self
._get
_keystone
_credentials
())
81 return self
._keystone
_connection
83 def is_auth_token_valid(self
, token_expiry
, time_fmt
):
85 Performs validity on auth_token
87 token_expiry (string): Expiry time for token
88 time_fmt (string) : Format for expiry string in auth_ref
91 True/False (Boolean): (auth_token is valid or auth_token is invalid)
95 import dateutil
.parser
97 now
= datetime
.datetime
.timetuple(datetime
.datetime
.utcnow())
98 expires_at
= dateutil
.parser
.parse(token_expiry
)
99 t_now
= time
.mktime(now
)
100 t_expiry
= time
.mktime(expires_at
.timetuple())
102 if (t_expiry
<= t_now
) or ((t_expiry
- t_now
) < 300 ):
103 ### Token has expired or about to expire (5 minute)
104 delattr(self
, '_keystone_connection')
108 except Exception as e
:
109 logger
.error("Received except %s during auth_token validity check" %str
(e
))
110 logger
.info("Can not validate the auth_token. Assuming invalid")
114 def get_service_endpoint(self
, service_type
, endpoint_type
):
116 Returns requested type of endpoint for requested service type
118 service_type (string): Service Type (e.g. computev3, image, network)
119 endpoint_type(string): Endpoint Type (e.g. publicURL,adminURL,internalURL)
121 service_endpoint(string): Service endpoint string
123 endpoint_kwargs
= {'service_type' : service_type
,
124 'endpoint_type' : endpoint_type
}
126 ksconn
= self
._get
_keystone
_connection
()
127 service_endpoint
= ksconn
.service_catalog
.url_for(**endpoint_kwargs
)
128 except (KeystoneExceptions
.Unauthorized
, KeystoneExceptions
.AuthorizationFailure
) as e
:
130 except Exception as e
:
131 logger
.error("OpenstackDriver: Service Catalog discovery operation failed for service_type: %s, endpoint_type: %s. Exception: %s" %(service_type
, endpoint_type
, str(e
)))
133 return service_endpoint
136 def get_raw_token(self
):
138 Returns a valid raw_auth_token string
140 Returns (string): raw_auth_token string
142 ksconn
= self
._get
_keystone
_connection
()
144 raw_token
= ksconn
.get_raw_token_from_identity_service(auth_url
= self
._auth
_url
,
145 token
= self
.get_auth_token())
146 except KeystoneExceptions
.AuthorizationFailure
as e
:
147 logger
.error("OpenstackDriver: get_raw_token_from_identity_service Failure. Exception: %s" %(str(e
)))
150 except Exception as e
:
151 logger
.error("OpenstackDriver: Could not retrieve raw_token. Exception: %s" %(str(e
)))
155 def get_tenant_id(self
):
157 Returns tenant_id for the project/tenant. Tenant name is provided during
160 Returns (string): Tenant ID
162 ksconn
= self
._get
_keystone
_connection
()
163 return ksconn
.tenant_id
165 def get_security_mode(self
):
167 Returns certificate_validation policy in case of SSL/TLS connection.
168 This policy is provided during class instantiation
171 The boolean returned are designed to match the python-client class instantiation ("insecure") value.
172 for nova/neutron/glance/keystone clients
174 True: No certificate validation required -- Insecure mode
175 False: Certificate validation required -- Secure mode
177 return self
._insecure
179 def tenant_list(self
):
181 Returns list of tenants
185 def tenant_create(self
, name
):
191 def tenant_delete(self
, tenant_id
):
193 Deletes a tenant identified by tenant_id
197 def roles_list(self
):
200 def roles_create(self
):
203 def roles_delete(self
):
206 class KeystoneDriverV2(KeystoneDriver
):
208 Driver class for keystoneclient V2 APIs
210 def __init__(self
, username
, password
, auth_url
,tenant_name
, insecure
):
212 Constructor for KeystoneDriverV3 class
214 username (string) : Username
215 password (string) : Password
216 auth_url (string) : Authentication URL
217 tenant_name(string): Tenant Name
221 self
._username
= username
222 self
._password
= password
223 self
._auth
_url
= auth_url
224 self
._tenant
_name
= tenant_name
225 self
._insecure
= insecure
226 super(KeystoneDriverV2
, self
).__init
__(ksclientv2
.Client
)
228 def _get_keystone_credentials(self
):
230 Returns the dictionary of kwargs required to instantiate python-keystoneclient class
233 #creds['user_domain'] = self._domain_name
234 creds
['username'] = self
._username
235 creds
['password'] = self
._password
236 creds
['auth_url'] = self
._auth
_url
237 creds
['tenant_name'] = self
._tenant
_name
238 creds
['insecure'] = self
.get_security_mode()
241 def get_auth_token(self
):
243 Returns a valid auth_token
245 Returns (string): auth_token string
247 ksconn
= self
._get
_keystone
_connection
()
248 return ksconn
.auth_token
250 def is_auth_token_valid(self
):
252 Performs validity on auth_token
256 True/False (Boolean): (auth_token is valid or auth_token is invalid)
258 ksconn
= self
._get
_keystone
_connection
()
259 result
= super(KeystoneDriverV2
, self
).is_auth_token_valid(ksconn
.auth_ref
['token']['expires'],
260 "%Y-%m-%dT%H:%M:%SZ")
264 class KeystoneDriverV3(KeystoneDriver
):
266 Driver class for keystoneclient V3 APIs
268 def __init__(self
, username
, password
, auth_url
,tenant_name
, insecure
):
270 Constructor for KeystoneDriverV3 class
272 username (string) : Username
273 password (string) : Password
274 auth_url (string) : Authentication URL
275 tenant_name(string): Tenant Name
279 self
._username
= username
280 self
._password
= password
281 self
._auth
_url
= auth_url
282 self
._tenant
_name
= tenant_name
283 self
._insecure
= insecure
284 super(KeystoneDriverV3
, self
).__init
__(ksclientv3
.Client
)
286 def _get_keystone_credentials(self
):
288 Returns the dictionary of kwargs required to instantiate python-keystoneclient class
291 #creds['user_domain'] = self._domain_name
292 creds
['username'] = self
._username
293 creds
['password'] = self
._password
294 creds
['auth_url'] = self
._auth
_url
295 creds
['project_name'] = self
._tenant
_name
296 creds
['insecure'] = self
._insecure
299 def get_auth_token(self
):
301 Returns a valid auth_token
303 Returns (string): auth_token string
305 ksconn
= self
._get
_keystone
_connection
()
306 return ksconn
.auth_ref
['auth_token']
308 def is_auth_token_valid(self
):
310 Performs validity on auth_token
314 True/False (Boolean): (auth_token is valid or auth_token is invalid)
316 ksconn
= self
._get
_keystone
_connection
()
317 result
= super(KeystoneDriverV3
, self
).is_auth_token_valid(ksconn
.auth_ref
['expires_at'],
318 "%Y-%m-%dT%H:%M:%S.%fZ")
321 class NovaDriver(object):
323 Driver for openstack nova_client
325 def __init__(self
, ks_drv
, service_name
, version
):
327 Constructor for NovaDriver
328 Arguments: KeystoneDriver class object
331 self
._service
_name
= service_name
332 self
._version
= version
334 def _get_nova_credentials(self
):
336 Returns a dictionary of kwargs required to instantiate python-novaclient class
339 creds
['version'] = self
._version
340 creds
['bypass_url'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, "publicURL")
341 creds
['username'] = self
.ks_drv
.get_username()
342 creds
['project_id'] = self
.ks_drv
.get_tenant_name()
343 creds
['auth_token'] = self
.ks_drv
.get_auth_token()
344 creds
['insecure'] = self
.ks_drv
.get_security_mode()
347 def _get_nova_connection(self
):
349 Returns an object of class python-novaclient
351 if not hasattr(self
, '_nova_connection'):
352 self
._nova
_connection
= nova_client
.Client(**self
._get
_nova
_credentials
())
354 # Reinitialize if auth_token is no longer valid
355 if not self
.ks_drv
.is_auth_token_valid():
356 self
._nova
_connection
= nova_client
.Client(**self
._get
_nova
_credentials
())
357 return self
._nova
_connection
359 def _flavor_get(self
, flavor_id
):
361 Get flavor by flavor_id
363 flavor_id(string): UUID of flavor_id
366 dictionary of flavor parameters
368 nvconn
= self
._get
_nova
_connection
()
370 flavor
= nvconn
.flavors
.get(flavor_id
)
371 except Exception as e
:
372 logger
.info("OpenstackDriver: Did not find flavor with flavor_id : %s. Exception: %s"%(flavor_id
, str(e
)))
376 extra_specs
= flavor
.get_keys()
377 except Exception as e
:
378 logger
.info("OpenstackDriver: Could not get the EPA attributes for flavor with flavor_id : %s. Exception: %s"%(flavor_id
, str(e
)))
381 response
= flavor
.to_dict()
382 assert 'extra_specs' not in response
, "Key extra_specs present as flavor attribute"
383 response
['extra_specs'] = extra_specs
386 def flavor_get(self
, flavor_id
):
388 Get flavor by flavor_id
390 flavor_id(string): UUID of flavor_id
393 dictionary of flavor parameters
395 return self
._flavor
_get
(flavor_id
)
397 def flavor_list(self
):
399 Returns list of all flavors (dictionary per flavor)
404 A list of dictionaries. Each dictionary contains attributes for a single flavor instance
408 nvconn
= self
._get
_nova
_connection
()
410 flavors
= nvconn
.flavors
.list()
411 except Exception as e
:
412 logger
.error("OpenstackDriver: List Flavor operation failed. Exception: %s"%(str(e
)))
415 flavor_info
= [ self
.flavor_get(flv
.id) for flv
in flavors
]
418 def flavor_create(self
, name
, ram
, vcpu
, disk
, extra_specs
):
423 name (string): Name of the new flavor
424 ram (int) : Memory in MB
425 vcpus (int) : Number of VCPUs
426 disk (int) : Secondary storage size in GB
427 extra_specs (dictionary): EPA attributes dictionary
430 flavor_id (string): UUID of flavor created
432 nvconn
= self
._get
_nova
_connection
()
434 flavor
= nvconn
.flavors
.create(name
= name
,
443 except Exception as e
:
444 logger
.error("OpenstackDriver: Create Flavor operation failed. Exception: %s"%(str(e
)))
449 flavor
.set_keys(extra_specs
)
450 except Exception as e
:
451 logger
.error("OpenstackDriver: Set Key operation failed for flavor: %s. Exception: %s" %(flavor
.id, str(e
)))
455 def flavor_delete(self
, flavor_id
):
457 Deletes a flavor identified by flavor_id
460 flavor_id (string): UUID of flavor to be deleted
464 assert flavor_id
== self
._flavor
_get
(flavor_id
)['id']
465 nvconn
= self
._get
_nova
_connection
()
467 nvconn
.flavors
.delete(flavor_id
)
468 except Exception as e
:
469 logger
.error("OpenstackDriver: Delete flavor operation failed for flavor: %s. Exception: %s" %(flavor_id
, str(e
)))
473 def server_list(self
):
475 Returns a list of available VMs for the project
480 A list of dictionaries. Each dictionary contains attributes associated
485 nvconn
= self
._get
_nova
_connection
()
487 servers
= nvconn
.servers
.list()
488 except Exception as e
:
489 logger
.error("OpenstackDriver: List Server operation failed. Exception: %s" %(str(e
)))
491 server_info
= [ server
.to_dict() for server
in servers
]
494 def _nova_server_get(self
, server_id
):
496 Returns a dictionary of attributes associated with VM identified by service_id
499 server_id (string): UUID of the VM/server for which information is requested
502 A dictionary object with attributes associated with VM identified by server_id
504 nvconn
= self
._get
_nova
_connection
()
506 server
= nvconn
.servers
.get(server
= server_id
)
507 except Exception as e
:
508 logger
.info("OpenstackDriver: Get Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
511 return server
.to_dict()
513 def server_get(self
, server_id
):
515 Returns a dictionary of attributes associated with VM identified by service_id
518 server_id (string): UUID of the VM/server for which information is requested
521 A dictionary object with attributes associated with VM identified by server_id
523 return self
._nova
_server
_get
(server_id
)
525 def server_create(self
, **kwargs
):
527 Creates a new VM/server instance
530 A dictionary of following key-value pairs
532 server_name(string) : Name of the VM/Server
533 flavor_id (string) : UUID of the flavor to be used for VM
534 image_id (string) : UUID of the image to be used VM/Server instance,
535 This could be None if volumes (with images) are being used
536 network_list(List) : A List of network_ids. A port will be created in these networks
537 port_list (List) : A List of port-ids. These ports will be added to VM.
538 metadata (dict) : A dictionary of arbitrary key-value pairs associated with VM/server
539 userdata (string) : A script which shall be executed during first boot of the VM
540 availability_zone (string) : A name of the availability zone where instance should be launched
541 scheduler_hints (string) : Openstack scheduler_hints to be passed to nova scheduler
544 server_id (string): UUID of the VM/server created
548 if 'network_list' in kwargs
:
549 for network_id
in kwargs
['network_list']:
550 nics
.append({'net-id': network_id
})
552 if 'port_list' in kwargs
:
553 for port_id
in kwargs
['port_list']:
554 nics
.append({'port-id': port_id
})
556 nvconn
= self
._get
_nova
_connection
()
560 server
= nvconn
.servers
.create(kwargs
['name'],
563 meta
= kwargs
['metadata'],
564 files
= kwargs
['files'],
565 reservation_id
= None,
568 userdata
= kwargs
['userdata'],
569 security_groups
= kwargs
['security_groups'],
570 availability_zone
= kwargs
['availability_zone'],
571 block_device_mapping_v2
= kwargs
['block_device_mapping_v2'],
573 scheduler_hints
= kwargs
['scheduler_hints'],
574 config_drive
= kwargs
['config_drive'])
575 except Exception as e
:
576 logger
.info("OpenstackDriver: Create Server operation failed. Exception: %s" %(str(e
)))
578 return server
.to_dict()['id']
580 def server_delete(self
, server_id
):
582 Deletes a server identified by server_id
585 server_id (string): UUID of the server to be deleted
589 nvconn
= self
._get
_nova
_connection
()
591 nvconn
.servers
.delete(server_id
)
592 except Exception as e
:
593 logger
.error("OpenstackDriver: Delete server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
596 def server_start(self
, server_id
):
598 Starts a server identified by server_id
601 server_id (string): UUID of the server to be started
605 nvconn
= self
._get
_nova
_connection
()
607 nvconn
.servers
.start(server_id
)
608 except Exception as e
:
609 logger
.error("OpenstackDriver: Start Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
612 def server_stop(self
, server_id
):
615 server_id (string): UUID of the server to be stopped
619 nvconn
= self
._get
_nova
_connection
()
621 nvconn
.servers
.stop(server_id
)
622 except Exception as e
:
623 logger
.error("OpenstackDriver: Stop Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
626 def server_pause(self
, server_id
):
629 server_id (string): UUID of the server to be paused
633 nvconn
= self
._get
_nova
_connection
()
635 nvconn
.servers
.pause(server_id
)
636 except Exception as e
:
637 logger
.error("OpenstackDriver: Pause Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
640 def server_unpause(self
, server_id
):
643 server_id (string): UUID of the server to be unpaused
647 nvconn
= self
._get
_nova
_connection
()
649 nvconn
.servers
.unpause(server_id
)
650 except Exception as e
:
651 logger
.error("OpenstackDriver: Resume Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
655 def server_suspend(self
, server_id
):
658 server_id (string): UUID of the server to be suspended
662 nvconn
= self
._get
_nova
_connection
()
664 nvconn
.servers
.suspend(server_id
)
665 except Exception as e
:
666 logger
.error("OpenstackDriver: Suspend Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
669 def server_resume(self
, server_id
):
672 server_id (string): UUID of the server to be resumed
676 nvconn
= self
._get
_nova
_connection
()
678 nvconn
.servers
.resume(server_id
)
679 except Exception as e
:
680 logger
.error("OpenstackDriver: Resume Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
683 def server_reboot(self
, server_id
, reboot_type
):
686 server_id (string) : UUID of the server to be rebooted
692 nvconn
= self
._get
_nova
_connection
()
694 nvconn
.servers
.reboot(server_id
, reboot_type
)
695 except Exception as e
:
696 logger
.error("OpenstackDriver: Reboot Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
699 def server_console(self
, server_id
, console_type
= 'novnc'):
702 server_id (string) : UUID of the server to be rebooted
703 console_type(string):
707 A dictionary object response for console information
709 nvconn
= self
._get
_nova
_connection
()
711 console_info
= nvconn
.servers
.get_vnc_console(server_id
, console_type
)
712 except Exception as e
:
713 logger
.error("OpenstackDriver: Server Get-Console operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
717 def server_rebuild(self
, server_id
, image_id
):
720 server_id (string) : UUID of the server to be rebooted
721 image_id (string) : UUID of the image to use
725 nvconn
= self
._get
_nova
_connection
()
727 nvconn
.servers
.rebuild(server_id
, image_id
)
728 except Exception as e
:
729 logger
.error("OpenstackDriver: Rebuild Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
733 def server_add_port(self
, server_id
, port_id
):
736 server_id (string): UUID of the server
737 port_id (string): UUID of the port to be attached
741 nvconn
= self
._get
_nova
_connection
()
743 nvconn
.servers
.interface_attach(server_id
,
747 except Exception as e
:
748 logger
.error("OpenstackDriver: Server Port Add operation failed for server_id : %s, port_id : %s. Exception: %s" %(server_id
, port_id
, str(e
)))
751 def server_delete_port(self
, server_id
, port_id
):
754 server_id (string): UUID of the server
755 port_id (string): UUID of the port to be deleted
759 nvconn
= self
._get
_nova
_connection
()
761 nvconn
.servers
.interface_detach(server_id
, port_id
)
762 except Exception as e
:
763 logger
.error("OpenstackDriver: Server Port Delete operation failed for server_id : %s, port_id : %s. Exception: %s" %(server_id
, port_id
, str(e
)))
766 def floating_ip_list(self
):
771 List of objects of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
773 nvconn
= self
._get
_nova
_connection
()
775 ip_list
= nvconn
.floating_ips
.list()
776 except Exception as e
:
777 logger
.error("OpenstackDriver: Floating IP List operation failed. Exception: %s" %str
(e
))
782 def floating_ip_create(self
, pool
):
785 pool (string): Name of the pool (optional)
787 An object of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
789 nvconn
= self
._get
_nova
_connection
()
791 floating_ip
= nvconn
.floating_ips
.create(pool
)
792 except Exception as e
:
793 logger
.error("OpenstackDriver: Floating IP Create operation failed. Exception: %s" %str
(e
))
798 def floating_ip_delete(self
, floating_ip
):
801 floating_ip: An object of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
805 nvconn
= self
._get
_nova
_connection
()
807 floating_ip
= nvconn
.floating_ips
.delete(floating_ip
)
808 except Exception as e
:
809 logger
.error("OpenstackDriver: Floating IP Delete operation failed. Exception: %s" %str
(e
))
812 def floating_ip_assign(self
, server_id
, floating_ip
, fixed_ip
):
815 server_id (string) : UUID of the server
816 floating_ip (string): IP address string for floating-ip
817 fixed_ip (string) : IP address string for the fixed-ip with which floating ip will be associated
821 nvconn
= self
._get
_nova
_connection
()
823 nvconn
.servers
.add_floating_ip(server_id
, floating_ip
, fixed_ip
)
824 except Exception as e
:
825 logger
.error("OpenstackDriver: Assign Floating IP operation failed. Exception: %s" %str
(e
))
828 def floating_ip_release(self
, server_id
, floating_ip
):
831 server_id (string) : UUID of the server
832 floating_ip (string): IP address string for floating-ip
836 nvconn
= self
._get
_nova
_connection
()
838 nvconn
.servers
.remove_floating_ip(server_id
, floating_ip
)
839 except Exception as e
:
840 logger
.error("OpenstackDriver: Release Floating IP operation failed. Exception: %s" %str
(e
))
843 def volume_list(self
, server_id
):
845 List of volumes attached to the server
850 List of dictionary objects where dictionary is representation of class (novaclient.v2.volumes.Volume)
852 nvconn
= self
._get
_nova
_connection
()
854 volumes
= nvconn
.volumes
.get_server_volumes(server_id
=server_id
)
855 except Exception as e
:
856 logger
.error("OpenstackDriver: Get volume information failed. Exception: %s" %str
(e
))
859 volume_info
= [v
.to_dict() for v
in volumes
]
863 def group_list(self
):
865 List of Server Affinity and Anti-Affinity Groups
870 List of dictionary objects where dictionary is representation of class (novaclient.v2.server_groups.ServerGroup)
872 nvconn
= self
._get
_nova
_connection
()
874 group_list
= nvconn
.server_groups
.list()
875 except Exception as e
:
876 logger
.error("OpenstackDriver: Server Group List operation failed. Exception: %s" %str
(e
))
879 group_info
= [ group
.to_dict() for group
in group_list
]
884 class NovaDriverV2(NovaDriver
):
886 Driver class for novaclient V2 APIs
888 def __init__(self
, ks_drv
):
890 Constructor for NovaDriver
891 Arguments: KeystoneDriver class object
893 super(NovaDriverV2
, self
).__init
__(ks_drv
, 'compute', '2.0')
895 class NovaDriverV21(NovaDriver
):
897 Driver class for novaclient V2 APIs
899 def __init__(self
, ks_drv
):
901 Constructor for NovaDriver
902 Arguments: KeystoneDriver class object
904 super(NovaDriverV21
, self
).__init
__(ks_drv
, 'computev21', '2.1')
906 class GlanceDriver(object):
908 Driver for openstack glance-client
910 def __init__(self
, ks_drv
, service_name
, version
):
912 Constructor for GlanceDriver
913 Arguments: KeystoneDriver class object
916 self
._service
_name
= service_name
917 self
._version
= version
919 def _get_glance_credentials(self
):
921 Returns a dictionary of kwargs required to instantiate python-glanceclient class
926 A dictionary object of arguments
929 creds
['version'] = self
._version
930 creds
['endpoint'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, 'publicURL')
931 creds
['token'] = self
.ks_drv
.get_auth_token()
932 creds
['insecure'] = self
.ks_drv
.get_security_mode()
935 def _get_glance_connection(self
):
937 Returns a object of class python-glanceclient
939 if not hasattr(self
, '_glance_connection'):
940 self
._glance
_connection
= glclient
.Client(**self
._get
_glance
_credentials
())
942 # Reinitialize if auth_token is no longer valid
943 if not self
.ks_drv
.is_auth_token_valid():
944 self
._glance
_connection
= glclient
.Client(**self
._get
_glance
_credentials
())
945 return self
._glance
_connection
947 def image_list(self
):
949 Returns list of dictionaries. Each dictionary contains attributes associated with
954 Returns: List of dictionaries.
956 glconn
= self
._get
_glance
_connection
()
959 image_info
= glconn
.images
.list()
960 except Exception as e
:
961 logger
.error("OpenstackDriver: List Image operation failed. Exception: %s" %(str(e
)))
963 images
= [ img
for img
in image_info
]
966 def image_create(self
, **kwargs
):
970 A dictionary of kwargs with following keys
972 'name'(string) : Name of the image
973 'location'(string) : URL (http://....) where image is located
974 'disk_format'(string) : Disk format
975 Possible values are 'ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso'
976 'container_format'(string): Container format
977 Possible values are 'ami', 'ari', 'aki', 'bare', 'ovf'
978 'tags' : A list of user tags
979 'checksum' : The image md5 checksum
982 image_id (string) : UUID of the image
985 glconn
= self
._get
_glance
_connection
()
987 image
= glconn
.images
.create(**kwargs
)
988 except Exception as e
:
989 logger
.error("OpenstackDriver: Create Image operation failed. Exception: %s" %(str(e
)))
994 def image_upload(self
, image_id
, fd
):
999 image_id: UUID of the image
1000 fd : File descriptor for the image file
1003 glconn
= self
._get
_glance
_connection
()
1005 glconn
.images
.upload(image_id
, fd
)
1006 except Exception as e
:
1007 logger
.error("OpenstackDriver: Image upload operation failed. Exception: %s" %(str(e
)))
1010 def image_add_location(self
, image_id
, location
, metadata
):
1012 Add image URL location
1015 image_id : UUID of the image
1016 location : http URL for the image
1020 glconn
= self
._get
_glance
_connection
()
1022 image
= glconn
.images
.add_location(image_id
, location
, metadata
)
1023 except Exception as e
:
1024 logger
.error("OpenstackDriver: Image location add operation failed. Exception: %s" %(str(e
)))
1027 def image_update(self
):
1030 def image_delete(self
, image_id
):
1035 image_id: UUID of the image
1040 assert image_id
== self
._image
_get
(image_id
)['id']
1041 glconn
= self
._get
_glance
_connection
()
1043 glconn
.images
.delete(image_id
)
1044 except Exception as e
:
1045 logger
.error("OpenstackDriver: Delete Image operation failed for image_id : %s. Exception: %s" %(image_id
, str(e
)))
1049 def _image_get(self
, image_id
):
1051 Returns a dictionary object of VM image attributes
1054 image_id (string): UUID of the image
1057 A dictionary of the image attributes
1059 glconn
= self
._get
_glance
_connection
()
1061 image
= glconn
.images
.get(image_id
)
1062 except GlanceException
.HTTPBadRequest
:
1063 # RIFT-14241: The get image request occasionally returns the below message. Retry in case of bad request exception.
1064 # Error code 400.: Message: Bad request syntax ('0').: Error code explanation: 400 = Bad request syntax or unsupported method. (HTTP 400)
1065 logger
.warning("OpenstackDriver: Got bad request response during get_image request. Retrying.")
1066 image
= glconn
.images
.get(image_id
)
1067 except Exception as e
:
1068 logger
.error("OpenstackDriver: Get Image operation failed for image_id : %s. Exception: %s" %(image_id
, str(e
)))
1073 def image_get(self
, image_id
):
1075 Returns a dictionary object of VM image attributes
1078 image_id (string): UUID of the image
1081 A dictionary of the image attributes
1083 return self
._image
_get
(image_id
)
1085 class GlanceDriverV2(GlanceDriver
):
1087 Driver for openstack glance-client V2
1089 def __init__(self
, ks_drv
):
1090 super(GlanceDriverV2
, self
).__init
__(ks_drv
, 'image', 2)
1092 class NeutronDriver(object):
1094 Driver for openstack neutron neutron-client
1096 def __init__(self
, ks_drv
, service_name
, version
):
1098 Constructor for NeutronDriver
1099 Arguments: KeystoneDriver class object
1101 self
.ks_drv
= ks_drv
1102 self
._service
_name
= service_name
1103 self
._version
= version
1105 def _get_neutron_credentials(self
):
1107 Returns a dictionary of kwargs required to instantiate python-neutronclient class
1110 Dictionary of kwargs
1113 creds
['api_version'] = self
._version
1114 creds
['endpoint_url'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, 'publicURL')
1115 creds
['token'] = self
.ks_drv
.get_auth_token()
1116 creds
['tenant_name'] = self
.ks_drv
.get_tenant_name()
1117 creds
['insecure'] = self
.ks_drv
.get_security_mode()
1120 def _get_neutron_connection(self
):
1122 Returns an object of class python-neutronclient
1124 if not hasattr(self
, '_neutron_connection'):
1125 self
._neutron
_connection
= ntclient
.Client(**self
._get
_neutron
_credentials
())
1127 # Reinitialize if auth_token is no longer valid
1128 if not self
.ks_drv
.is_auth_token_valid():
1129 self
._neutron
_connection
= ntclient
.Client(**self
._get
_neutron
_credentials
())
1130 return self
._neutron
_connection
1132 def network_list(self
):
1134 Returns list of dictionaries. Each dictionary contains the attributes for a network
1140 A list of dictionaries
1143 ntconn
= self
._get
_neutron
_connection
()
1145 networks
= ntconn
.list_networks()
1146 except Exception as e
:
1147 logger
.error("OpenstackDriver: List Network operation failed. Exception: %s" %(str(e
)))
1149 return networks
['networks']
1151 def network_create(self
, **kwargs
):
1153 Creates a new network for the project
1156 A dictionary with following key-values
1158 name (string) : Name of the network
1159 admin_state_up(Boolean) : True/False (Defaults: True)
1160 external_router(Boolean) : Connectivity with external router. True/False (Defaults: False)
1161 shared(Boolean) : Shared among tenants. True/False (Defaults: False)
1162 physical_network(string) : The physical network where this network object is implemented (optional).
1163 network_type : The type of physical network that maps to this network resource (optional).
1164 Possible values are: 'flat', 'vlan', 'vxlan', 'gre'
1165 segmentation_id : An isolated segment on the physical network. The network_type attribute
1166 defines the segmentation model. For example, if the network_type value
1167 is vlan, this ID is a vlan identifier. If the network_type value is gre,
1168 this ID is a gre key.
1171 params
= {'network':
1172 {'name' : kwargs
['name'],
1173 'admin_state_up' : kwargs
['admin_state_up'],
1174 'tenant_id' : self
.ks_drv
.get_tenant_id(),
1175 'shared' : kwargs
['shared'],
1176 #'port_security_enabled': port_security_enabled,
1177 'router:external' : kwargs
['external_router']}}
1179 if 'physical_network' in kwargs
:
1180 params
['network']['provider:physical_network'] = kwargs
['physical_network']
1181 if 'network_type' in kwargs
:
1182 params
['network']['provider:network_type'] = kwargs
['network_type']
1183 if 'segmentation_id' in kwargs
:
1184 params
['network']['provider:segmentation_id'] = kwargs
['segmentation_id']
1186 ntconn
= self
._get
_neutron
_connection
()
1188 logger
.debug("Calling neutron create_network() with params: %s", str(params
))
1189 net
= ntconn
.create_network(params
)
1190 except Exception as e
:
1191 logger
.error("OpenstackDriver: Create Network operation failed. Exception: %s" %(str(e
)))
1193 logger
.debug("Got create_network response from neutron connection: %s", str(net
))
1194 network_id
= net
['network']['id']
1196 raise Exception("Empty network id returned from create_network. (params: %s)" % str(params
))
1200 def network_delete(self
, network_id
):
1202 Deletes a network identified by network_id
1205 network_id (string): UUID of the network
1209 assert network_id
== self
._network
_get
(network_id
)['id']
1210 ntconn
= self
._get
_neutron
_connection
()
1212 ntconn
.delete_network(network_id
)
1213 except Exception as e
:
1214 logger
.error("OpenstackDriver: Delete Network operation failed. Exception: %s" %(str(e
)))
1217 def _network_get(self
, network_id
):
1219 Returns a dictionary object describing the attributes of the network
1222 network_id (string): UUID of the network
1225 A dictionary object of the network attributes
1227 ntconn
= self
._get
_neutron
_connection
()
1228 network
= ntconn
.list_networks(id = network_id
)['networks']
1230 raise NeutronException
.NotFound("Network with id %s not found"%(network_id))
1234 def network_get(self
, network_id
):
1236 Returns a dictionary object describing the attributes of the network
1239 network_id (string): UUID of the network
1242 A dictionary object of the network attributes
1244 return self
._network
_get
(network_id
)
1246 def subnet_create(self
, **kwargs
):
1248 Creates a subnet on the network
1251 A dictionary with following key value pairs
1253 network_id(string) : UUID of the network where subnet needs to be created
1254 subnet_cidr(string) : IPv4 address prefix (e.g. '1.1.1.0/24') for the subnet
1255 ip_version (integer): 4 for IPv4 and 6 for IPv6
1260 subnet_id (string): UUID of the created subnet
1263 params
['network_id'] = kwargs
['network_id']
1264 params
['ip_version'] = kwargs
['ip_version']
1266 # if params['ip_version'] == 6:
1267 # assert 0, "IPv6 is not supported"
1269 if 'subnetpool_id' in kwargs
:
1270 params
['subnetpool_id'] = kwargs
['subnetpool_id']
1272 params
['cidr'] = kwargs
['cidr']
1274 if 'gateway_ip' in kwargs
:
1275 params
['gateway_ip'] = kwargs
['gateway_ip']
1277 params
['gateway_ip'] = None
1279 if 'dhcp_params' in kwargs
:
1280 params
['enable_dhcp'] = kwargs
['dhcp_params']['enable_dhcp']
1281 if 'start_address' in kwargs
['dhcp_params'] and 'count' in kwargs
['dhcp_params']:
1282 end_address
= (ipaddress
.IPv4Address(kwargs
['dhcp_params']['start_address']) + kwargs
['dhcp_params']['count']).compressed
1283 params
['allocation_pools'] = [ {'start': kwargs
['dhcp_params']['start_address'] ,
1284 'end' : end_address
} ]
1286 if 'dns_server' in kwargs
:
1287 params
['dns_nameservers'] = []
1288 for server
in kwargs
['dns_server']:
1289 params
['dns_nameservers'].append(server
)
1291 ntconn
= self
._get
_neutron
_connection
()
1293 subnet
= ntconn
.create_subnet({'subnets': [params
]})
1294 except Exception as e
:
1295 logger
.error("OpenstackDriver: Create Subnet operation failed. Exception: %s" %(str(e
)))
1298 return subnet
['subnets'][0]['id']
1300 def subnet_list(self
):
1302 Returns a list of dictionaries. Each dictionary contains attributes describing the subnet
1307 A dictionary of the objects of subnet attributes
1309 ntconn
= self
._get
_neutron
_connection
()
1311 subnets
= ntconn
.list_subnets()['subnets']
1312 except Exception as e
:
1313 logger
.error("OpenstackDriver: List Subnet operation failed. Exception: %s" %(str(e
)))
1317 def _subnet_get(self
, subnet_id
):
1319 Returns a dictionary object describing the attributes of a subnet.
1322 subnet_id (string): UUID of the subnet
1325 A dictionary object of the subnet attributes
1327 ntconn
= self
._get
_neutron
_connection
()
1328 subnets
= ntconn
.list_subnets(id=subnet_id
)
1329 if not subnets
['subnets']:
1330 logger
.error("OpenstackDriver: Get subnet operation failed for subnet_id: %s" %(subnet_id))
1331 #raise NeutronException.NotFound("Could not find subnet_id %s" %(subnet_id))
1334 return subnets
['subnets'][0]
1336 def subnet_get(self
, subnet_id
):
1338 Returns a dictionary object describing the attributes of a subnet.
1341 subnet_id (string): UUID of the subnet
1344 A dictionary object of the subnet attributes
1346 return self
._subnet
_get
(subnet_id
)
1348 def subnet_delete(self
, subnet_id
):
1350 Deletes a subnet identified by subnet_id
1353 subnet_id (string): UUID of the subnet to be deleted
1357 ntconn
= self
._get
_neutron
_connection
()
1358 assert subnet_id
== self
._subnet
_get
(self
,subnet_id
)
1360 ntconn
.delete_subnet(subnet_id
)
1361 except Exception as e
:
1362 logger
.error("OpenstackDriver: Delete Subnet operation failed for subnet_id : %s. Exception: %s" %(subnet_id
, str(e
)))
1365 def port_list(self
, **kwargs
):
1367 Returns a list of dictionaries. Each dictionary contains attributes describing the port
1370 kwargs (dictionary): A dictionary for filters for port_list operation
1373 A dictionary of the objects of port attributes
1377 ntconn
= self
._get
_neutron
_connection
()
1379 kwargs
['tenant_id'] = self
.ks_drv
.get_tenant_id()
1382 ports
= ntconn
.list_ports(**kwargs
)
1383 except Exception as e
:
1384 logger
.info("OpenstackDriver: List Port operation failed. Exception: %s" %(str(e
)))
1386 return ports
['ports']
1388 def port_create(self
, **kwargs
):
1390 Create a port in network
1393 A dictionary of following
1395 name (string) : Name of the port
1396 network_id(string) : UUID of the network_id identifying the network to which port belongs
1397 subnet_id(string) : UUID of the subnet_id from which IP-address will be assigned to port
1398 vnic_type(string) : Possible values are "normal", "direct", "macvtap"
1401 port_id (string) : UUID of the port
1405 "admin_state_up" : kwargs
['admin_state_up'],
1406 "name" : kwargs
['name'],
1407 "network_id" : kwargs
['network_id'],
1408 "fixed_ips" : [ {"subnet_id": kwargs
['subnet_id']}],
1409 "binding:vnic_type" : kwargs
['port_type']}}
1411 ntconn
= self
._get
_neutron
_connection
()
1413 port
= ntconn
.create_port(params
)
1414 except Exception as e
:
1415 logger
.error("OpenstackDriver: Port Create operation failed. Exception: %s" %(str(e
)))
1417 return port
['port']['id']
1419 def _port_get(self
, port_id
):
1421 Returns a dictionary object describing the attributes of the port
1424 port_id (string): UUID of the port
1427 A dictionary object of the port attributes
1429 ntconn
= self
._get
_neutron
_connection
()
1430 port
= ntconn
.list_ports(id=port_id
)['ports']
1432 raise NeutronException
.NotFound("Could not find port_id %s" %(port_id))
1435 def port_get(self
, port_id
):
1437 Returns a dictionary object describing the attributes of the port
1440 port_id (string): UUID of the port
1443 A dictionary object of the port attributes
1445 return self
._port
_get
(port_id
)
1447 def port_delete(self
, port_id
):
1449 Deletes a port identified by port_id
1452 port_id (string) : UUID of the port
1456 assert port_id
== self
._port
_get
(port_id
)['id']
1457 ntconn
= self
._get
_neutron
_connection
()
1459 ntconn
.delete_port(port_id
)
1460 except Exception as e
:
1461 logger
.error("Port Delete operation failed for port_id : %s. Exception: %s" %(port_id
, str(e
)))
1464 def security_group_list(self
):
1466 Returns a list of dictionaries. Each dictionary contains attributes describing the security group
1472 A dictionary of the objects of security group attributes
1474 ntconn
= self
._get
_neutron
_connection
()
1476 group_list
= ntconn
.list_security_groups(tenant_id
=self
.ks_drv
.get_tenant_id())
1477 except Exception as e
:
1478 logger
.error("List Security group operation, Exception: %s" %(str(e
)))
1481 if 'security_groups' in group_list
:
1482 return group_list
['security_groups']
1486 def subnetpool_list(self
, **kwargs
):
1488 Returns a list of dictionaries. Each dictionary contains attributes describing a subnet prefix pool
1494 A dictionary of the objects of subnet prefix pool
1496 ntconn
= self
._get
_neutron
_connection
()
1498 pool_list
= ntconn
.list_subnetpools(**kwargs
)
1499 except Exception as e
:
1500 logger
.error("List SubnetPool operation, Exception: %s" %(str(e
)))
1503 if 'subnetpools' in pool_list
:
1504 return pool_list
['subnetpools']
1508 class NeutronDriverV2(NeutronDriver
):
1510 Driver for openstack neutron neutron-client v2
1512 def __init__(self
, ks_drv
):
1514 Constructor for NeutronDriver
1515 Arguments: KeystoneDriver class object
1517 super(NeutronDriverV2
, self
).__init
__(ks_drv
, 'network', '2.0')
1521 class CeilometerDriver(object):
1523 Driver for openstack ceilometer client
1526 def __init__(self
, ks_drv
, service_name
, version
):
1528 Constructor for CeilometerDriver
1529 Arguments: KeystoneDriver class object
1531 self
.ks_drv
= ks_drv
1532 self
._service
_name
= service_name
1533 self
._version
= version
1538 """The version of the ceilometer client used by the driver"""
1539 return self
._version
1543 """The instance of ceilometer client used by the driver"""
1544 if self
._client
is None or not self
.ks_drv
.is_auth_token_valid():
1545 self
._client
= ceilo_client
.Client(**self
.credentials
)
1550 def auth_token(self
):
1551 """The authorization token for the ceilometer client"""
1553 return self
.ks_drv
.get_auth_token()
1554 except KeystoneExceptions
.EndpointNotFound
as e
:
1555 logger
.error("OpenstackDriver: unable to get authorization token for ceilometer. Exception: %s" %(str(e
)))
1559 def security_mode(self
):
1560 """The security mode for the ceilometer client"""
1562 return self
.ks_drv
.get_security_mode()
1563 except KeystoneExceptions
.EndpointNotFound
as e
:
1564 logger
.error("OpenstackDriver: unable to get security mode for ceilometer. Exception: %s" %(str(e
)))
1569 """The service endpoint for the ceilometer client"""
1571 return self
.ks_drv
.get_service_endpoint(self
._service
_name
, "publicURL")
1572 except KeystoneExceptions
.EndpointNotFound
as e
:
1573 logger
.error("OpenstackDriver: unable to get endpoint for ceilometer. Exception: %s" %(str(e
)))
1577 def credentials(self
):
1578 """A dictionary of credentials for the ceilometer client"""
1580 version
=self
.version
,
1581 endpoint
=self
.endpoint
,
1582 token
=self
.auth_token
,
1583 insecure
=self
.security_mode
,
1588 """A list of the available meters"""
1590 return self
.client
.meters
.list()
1591 except Exception as e
:
1592 logger
.error("OpenstackDriver: List meters operation failed. Exception: %s" %(str(e
)))
1597 """The ceilometer client alarms manager"""
1598 return self
.client
.alarms
1600 def query_samples(self
, vim_instance_id
, counter_name
, limit
=1):
1601 """Returns a list of samples
1604 vim_instance_id - the ID of the VIM that the samples are from
1605 counter_name - the counter that the samples will come from
1606 limit - a limit on the number of samples to return
1614 filter = json
.dumps({
1616 {"=": {"resource": vim_instance_id
}},
1617 {"=": {"counter_name": counter_name
}}
1620 result
= self
.client
.query_samples
.query(filter=filter, limit
=limit
)
1621 return result
[-limit
:]
1623 except Exception as e
:
1629 class CeilometerDriverV2(CeilometerDriver
):
1631 Driver for openstack ceilometer ceilometer-client
1633 def __init__(self
, ks_drv
):
1635 Constructor for CeilometerDriver
1636 Arguments: CeilometerDriver class object
1638 super(CeilometerDriverV2
, self
).__init
__(ks_drv
, 'metering', '2')
1640 class OpenstackDriver(object):
1642 Driver for openstack nova, neutron, glance, keystone, swift, cinder services
1644 def __init__(self
, username
, password
, auth_url
, tenant_name
, mgmt_network
= None, cert_validate
= False):
1646 OpenstackDriver Driver constructor
1648 username (string) : Username for project/tenant.
1649 password (string) : Password
1650 auth_url (string) : Keystone Authentication URL.
1651 tenant_name (string) : Openstack project name
1652 mgmt_network(string, optional) : Management network name. Each VM created with this cloud-account will
1653 have a default interface into management network.
1654 cert_validate (boolean, optional) : In case of SSL/TLS connection if certificate validation is required or not.
1657 insecure
= not cert_validate
1658 if auth_url
.find('/v3') != -1:
1659 self
.ks_drv
= KeystoneDriverV3(username
, password
, auth_url
, tenant_name
, insecure
)
1660 self
.glance_drv
= GlanceDriverV2(self
.ks_drv
)
1661 self
.nova_drv
= NovaDriverV21(self
.ks_drv
)
1662 self
.neutron_drv
= NeutronDriverV2(self
.ks_drv
)
1663 self
.ceilo_drv
= CeilometerDriverV2(self
.ks_drv
)
1664 self
.cinder_drv
= CinderDriverV2(self
.ks_drv
)
1665 elif auth_url
.find('/v2') != -1:
1666 self
.ks_drv
= KeystoneDriverV2(username
, password
, auth_url
, tenant_name
, insecure
)
1667 self
.glance_drv
= GlanceDriverV2(self
.ks_drv
)
1668 self
.nova_drv
= NovaDriverV2(self
.ks_drv
)
1669 self
.neutron_drv
= NeutronDriverV2(self
.ks_drv
)
1670 self
.ceilo_drv
= CeilometerDriverV2(self
.ks_drv
)
1671 self
.cinder_drv
= CinderDriverV2(self
.ks_drv
)
1673 logger
.error("Could not identity the version information for openstack service endpoints. Auth_URL should contain \"/v2\" or \"/v3\" string in it")
1674 raise NotImplementedError("Auth URL is wrong or invalid. Only Keystone v2 & v3 supported")
1676 self
._mgmt
_network
_id
= None
1677 if mgmt_network
!= None:
1678 self
._mgmt
_network
= mgmt_network
1682 ntconn
= self
.neutron_drv
._get
_neutron
_connection
()
1683 networks
= ntconn
.list_networks()
1684 except (KeystoneExceptions
.Unauthorized
, KeystoneExceptions
.AuthorizationFailure
) as e
:
1686 except Exception as e
:
1687 logger
.error("OpenstackDriver: List Network operation failed. Exception: %s" %(str(e
)))
1690 network_list
= [ network
for network
in networks
['networks'] if network
['name'] == mgmt_network
]
1692 if not network_list
:
1693 raise NeutronException
.NotFound("Could not find network %s" %(mgmt_network))
1694 self
._mgmt
_network
_id
= network_list
[0]['id']
1696 def validate_account_creds(self
):
1698 ksconn
= self
.ks_drv
._get
_keystone
_connection
()
1699 except KeystoneExceptions
.AuthorizationFailure
as e
:
1700 logger
.error("OpenstackDriver: Unable to authenticate or validate the existing credentials. Exception: %s" %(str(e
)))
1701 raise ValidationError("Invalid Credentials: "+ str(e
))
1702 except Exception as e
:
1703 logger
.error("OpenstackDriver: Could not connect to Openstack. Exception: %s" %(str(e
)))
1704 raise ValidationError("Connection Error: "+ str(e
))
1706 def get_mgmt_network_id(self
):
1707 return self
._mgmt
_network
_id
1709 def glance_image_create(self
, **kwargs
):
1710 if not 'disk_format' in kwargs
:
1711 kwargs
['disk_format'] = 'qcow2'
1712 if not 'container_format' in kwargs
:
1713 kwargs
['container_format'] = 'bare'
1714 if not 'min_disk' in kwargs
:
1715 kwargs
['min_disk'] = 0
1716 if not 'min_ram' in kwargs
:
1717 kwargs
['min_ram'] = 0
1718 return self
.glance_drv
.image_create(**kwargs
)
1720 def glance_image_upload(self
, image_id
, fd
):
1721 self
.glance_drv
.image_upload(image_id
, fd
)
1723 def glance_image_add_location(self
, image_id
, location
):
1724 self
.glance_drv
.image_add_location(image_id
, location
)
1726 def glance_image_delete(self
, image_id
):
1727 self
.glance_drv
.image_delete(image_id
)
1729 def glance_image_list(self
):
1730 return self
.glance_drv
.image_list()
1732 def glance_image_get(self
, image_id
):
1733 return self
.glance_drv
.image_get(image_id
)
1736 def nova_flavor_list(self
):
1737 return self
.nova_drv
.flavor_list()
1739 def nova_flavor_create(self
, name
, ram
, vcpus
, disk
, epa_specs
):
1740 extra_specs
= epa_specs
if epa_specs
else {}
1741 return self
.nova_drv
.flavor_create(name
,
1745 extra_specs
= extra_specs
)
1747 def nova_flavor_delete(self
, flavor_id
):
1748 self
.nova_drv
.flavor_delete(flavor_id
)
1750 def nova_flavor_get(self
, flavor_id
):
1751 return self
.nova_drv
.flavor_get(flavor_id
)
1753 def nova_server_create(self
, **kwargs
):
1754 def _verify_image(image_id
):
1755 image
= self
.glance_drv
.image_get(image_id
)
1756 if image
['status'] != 'active':
1757 raise GlanceException
.NotFound("Image with image_id: %s not found in active state. Current State: %s" %(image
['id'], image
['status']))
1759 assert kwargs
['flavor_id'] == self
.nova_drv
.flavor_get(kwargs
['flavor_id'])['id']
1761 if kwargs
['block_device_mapping_v2'] is not None:
1762 for block_map
in kwargs
['block_device_mapping_v2']:
1763 if 'uuid' in block_map
:
1764 _verify_image(block_map
['uuid'])
1766 _verify_image(kwargs
['image_id'])
1768 # if 'network_list' in kwargs:
1769 # kwargs['network_list'].append(self._mgmt_network_id)
1771 # kwargs['network_list'] = [self._mgmt_network_id]
1773 if 'security_groups' not in kwargs
:
1774 nvconn
= self
.nova_drv
._get
_nova
_connection
()
1775 sec_groups
= nvconn
.security_groups
.list()
1777 ## Should we add VM in all availability security_groups ???
1778 kwargs
['security_groups'] = [x
.name
for x
in sec_groups
]
1780 kwargs
['security_groups'] = None
1782 return self
.nova_drv
.server_create(**kwargs
)
1784 def nova_server_add_port(self
, server_id
, port_id
):
1785 self
.nova_drv
.server_add_port(server_id
, port_id
)
1787 def nova_server_delete_port(self
, server_id
, port_id
):
1788 self
.nova_drv
.server_delete_port(server_id
, port_id
)
1790 def nova_server_start(self
, server_id
):
1791 self
.nova_drv
.server_start(server_id
)
1793 def nova_server_stop(self
, server_id
):
1794 self
.nova_drv
.server_stop(server_id
)
1796 def nova_server_delete(self
, server_id
):
1797 self
.nova_drv
.server_delete(server_id
)
1799 def nova_server_reboot(self
, server_id
):
1800 self
.nova_drv
.server_reboot(server_id
, reboot_type
='HARD')
1802 def nova_server_rebuild(self
, server_id
, image_id
):
1803 self
.nova_drv
.server_rebuild(server_id
, image_id
)
1805 def nova_floating_ip_list(self
):
1806 return self
.nova_drv
.floating_ip_list()
1808 def nova_floating_ip_create(self
, pool
= None):
1809 return self
.nova_drv
.floating_ip_create(pool
)
1811 def nova_floating_ip_delete(self
, floating_ip
):
1812 self
.nova_drv
.floating_ip_delete(floating_ip
)
1814 def nova_floating_ip_assign(self
, server_id
, floating_ip
, fixed_ip
):
1815 self
.nova_drv
.floating_ip_assign(server_id
, floating_ip
, fixed_ip
)
1817 def nova_floating_ip_release(self
, server_id
, floating_ip
):
1818 self
.nova_drv
.floating_ip_release(server_id
, floating_ip
)
1820 def nova_server_list(self
):
1821 return self
.nova_drv
.server_list()
1823 def nova_server_get(self
, server_id
):
1824 return self
.nova_drv
.server_get(server_id
)
1826 def nova_server_console(self
, server_id
):
1827 return self
.nova_drv
.server_console(server_id
)
1829 def nova_server_group_list(self
):
1830 return self
.nova_drv
.group_list()
1832 def nova_volume_list(self
, server_id
):
1833 return self
.nova_drv
.volume_list(server_id
)
1835 def neutron_network_list(self
):
1836 return self
.neutron_drv
.network_list()
1838 def neutron_network_get(self
, network_id
):
1839 return self
.neutron_drv
.network_get(network_id
)
1841 def neutron_network_create(self
, **kwargs
):
1842 return self
.neutron_drv
.network_create(**kwargs
)
1844 def neutron_network_delete(self
, network_id
):
1845 self
.neutron_drv
.network_delete(network_id
)
1847 def neutron_subnet_list(self
):
1848 return self
.neutron_drv
.subnet_list()
1850 def neutron_subnet_get(self
, subnet_id
):
1851 return self
.neutron_drv
.subnet_get(subnet_id
)
1853 def neutron_subnet_create(self
, **kwargs
):
1854 return self
.neutron_drv
.subnet_create(**kwargs
)
1856 def netruon_subnet_delete(self
, subnet_id
):
1857 self
.neutron_drv
.subnet_delete(subnet_id
)
1859 def neutron_subnetpool_list(self
):
1860 return self
.neutron_drv
.subnetpool_list()
1862 def netruon_subnetpool_by_name(self
, pool_name
):
1863 pool_list
= self
.neutron_drv
.subnetpool_list(**{'name': pool_name
})
1869 def neutron_port_list(self
, **kwargs
):
1870 return self
.neutron_drv
.port_list(**kwargs
)
1872 def neutron_port_get(self
, port_id
):
1873 return self
.neutron_drv
.port_get(port_id
)
1875 def neutron_port_create(self
, **kwargs
):
1876 subnets
= [subnet
for subnet
in self
.neutron_drv
.subnet_list() if subnet
['network_id'] == kwargs
['network_id']]
1877 assert len(subnets
) == 1
1878 kwargs
['subnet_id'] = subnets
[0]['id']
1879 if not 'admin_state_up' in kwargs
:
1880 kwargs
['admin_state_up'] = True
1881 port_id
= self
.neutron_drv
.port_create(**kwargs
)
1883 if 'vm_id' in kwargs
:
1884 self
.nova_server_add_port(kwargs
['vm_id'], port_id
)
1887 def neutron_security_group_list(self
):
1888 return self
.neutron_drv
.security_group_list()
1890 def neutron_security_group_by_name(self
, group_name
):
1891 group_list
= self
.neutron_drv
.security_group_list()
1892 groups
= [group
for group
in group_list
if group
['name'] == group_name
]
1898 def neutron_port_delete(self
, port_id
):
1899 self
.neutron_drv
.port_delete(port_id
)
1901 def ceilo_meter_endpoint(self
):
1902 return self
.ceilo_drv
.endpoint
1904 def ceilo_meter_list(self
):
1905 return self
.ceilo_drv
.meters
1907 def ceilo_nfvi_metrics(self
, vim_id
):
1908 """Returns a dict of NFVI metrics for a given VM
1911 vim_id - the VIM ID of the VM to retrieve the metrics for
1914 A dict of NFVI metrics
1917 def query_latest_sample(counter_name
):
1919 filter = json
.dumps({
1921 {"=": {"resource": vim_id
}},
1922 {"=": {"counter_name": counter_name
}}
1925 orderby
= json
.dumps([{"timestamp": "DESC"}])
1926 result
= self
.ceilo_drv
.client
.query_samples
.query(
1936 except Exception as e
:
1937 logger
.error("Got exception while querying ceilometer, exception details:%s " %str
(e
))
1941 memory_usage
= query_latest_sample("memory.usage")
1942 disk_usage
= query_latest_sample("disk.usage")
1943 cpu_util
= query_latest_sample("cpu_util")
1947 if memory_usage
is not None:
1948 memory_usage
.volume
= 1e6
* memory_usage
.volume
1949 metrics
["memory_usage"] = memory_usage
.to_dict()
1951 if disk_usage
is not None:
1952 metrics
["disk_usage"] = disk_usage
.to_dict()
1954 if cpu_util
is not None:
1955 metrics
["cpu_util"] = cpu_util
.to_dict()
1959 def ceilo_alarm_list(self
):
1960 """Returns a list of ceilometer alarms"""
1961 return self
.ceilo_drv
.client
.alarms
.list()
1963 def ceilo_alarm_create(self
,
1976 """Create a new Alarm
1979 name - the name of the alarm
1980 meter - the name of the meter to measure
1981 statistic - the type of statistic used to trigger the alarm
1982 ('avg', 'min', 'max', 'count', 'sum')
1983 operation - the relational operator that, combined with the
1984 threshold value, determines when the alarm is
1985 triggered ('lt', 'le', 'eq', 'ge', 'gt')
1986 threshold - the value of the statistic that will trigger the
1988 period - the duration (seconds) over which to evaluate the
1990 evaluations - the number of samples of the meter statistic to
1991 collect when evaluating the threshold
1992 severity - a measure of the urgency or importance of the alarm
1993 ('low', 'moderate', 'critical')
1994 repeat - a flag that indicates whether the alarm should be
1995 triggered once (False) or repeatedly while the alarm
1996 condition is true (True)
1997 enabled - a flag that indicates whether the alarm is enabled
1998 (True) or disabled (False)
1999 actions - a dict specifying the URLs for webhooks. The dict can
2000 have up to 3 keys: 'insufficient_data', 'alarm',
2001 'ok'. Each key is associated with a list of URLs to
2002 webhooks that will be invoked when one of the 3
2004 kwargs - an arbitrary dict of keyword arguments that are
2005 passed to the ceilometer client
2008 ok_actions
= actions
.get('ok') if actions
is not None else None
2009 alarm_actions
= actions
.get('alarm') if actions
is not None else None
2010 insufficient_data_actions
= actions
.get('insufficient_data') if actions
is not None else None
2012 return self
.ceilo_drv
.client
.alarms
.create(
2015 statistic
=statistic
,
2016 comparison_operator
=operation
,
2017 threshold
=threshold
,
2019 evaluation_periods
=evaluations
,
2021 repeat_actions
=repeat
,
2023 ok_actions
=ok_actions
,
2024 alarm_actions
=alarm_actions
,
2025 insufficient_data_actions
=insufficient_data_actions
,
2029 def ceilo_alarm_update(self
, alarm_id
, **kwargs
):
2030 """Updates an existing alarm
2033 alarm_id - the identifier of the alarm to update
2034 kwargs - a dict of the alarm attributes to update
2037 return self
.ceilo_drv
.client
.alarms
.update(alarm_id
, **kwargs
)
2039 def ceilo_alarm_delete(self
, alarm_id
):
2040 self
.ceilo_drv
.client
.alarms
.delete(alarm_id
)
2042 def cinder_volume_list(self
):
2043 return self
.cinder_drv
.volume_list()
2045 def cinder_volume_get(self
,vol_id
):
2046 return self
.cinder_drv
.volume_get(vol_id
)
2048 def cinder_volume_set_metadata(self
, volumeid
, metadata
):
2049 return self
.cinder_drv
.volume_set_metadata(volumeid
, metadata
)
2051 def cinder_volume_delete_metadata(self
, volumeid
, metadata
):
2052 return self
.cinder_drv
.volume_delete_metadata(volumeid
, metadata
)
2056 class CinderDriver(object):
2058 Driver for openstack cinder-client
2060 def __init__(self
, ks_drv
, service_name
, version
):
2062 Constructor for CinderDriver
2063 Arguments: KeystoneDriver class object
2065 self
.ks_drv
= ks_drv
2066 self
._service
_name
= service_name
2067 self
._version
= version
2069 def _get_cinder_credentials(self
):
2071 Returns a dictionary of kwargs required to instantiate python-cinderclient class
2076 A dictionary object of arguments
2079 creds
['version'] = self
._version
2080 creds
['username'] = self
.ks_drv
.get_username()
2081 creds
['api_key'] = self
.ks_drv
.get_password()
2082 creds
['auth_url'] = self
.ks_drv
.get_service_endpoint("identity", "publicURL")
2083 creds
['project_id'] = self
.ks_drv
.get_tenant_name()
2084 creds
['insecure'] = self
.ks_drv
.get_security_mode()
2088 def _get_cinder_connection(self
):
2090 Returns a object of class python-cinderclient
2092 if not hasattr(self
, '_cinder_connection'):
2093 self
._cinder
_connection
= cinder_client
.Client(**self
._get
_cinder
_credentials
())
2095 # Reinitialize if auth_token is no longer valid
2096 if not self
.ks_drv
.is_auth_token_valid():
2097 self
._cinder
_connection
= cinder_client
.Client(**self
._get
_cinder
_credentials
())
2098 return self
._cinder
_connection
2100 def volume_list(self
):
2102 Returns list of dictionaries. Each dictionary contains attributes associated with
2107 Returns: List of dictionaries.
2109 cinderconn
= self
._get
_cinder
_connection
()
2112 volume_info
= cinderconn
.volumes
.list()
2113 except Exception as e
:
2114 logger
.error("OpenstackDriver: List volumes operation failed. Exception: %s" %(str(e
)))
2116 volumes
= [ volume
for volume
in volume_info
]
2119 def volume_get(self
, volume_id
):
2125 Returns: List of dictionaries.
2127 cinderconn
= self
._get
_cinder
_connection
()
2129 vol
= cinderconn
.volumes
.get(volume_id
)
2130 except Exception as e
:
2131 logger
.error("OpenstackDriver: Get volume operation failed. Exception: %s" %(str(e
)))
2135 def volume_set_metadata(self
, volume_id
, metadata
):
2137 Set metadata for volume
2138 Metadata is a dictionary of key-value pairs
2142 Returns: List of dictionaries.
2144 cinderconn
= self
._get
_cinder
_connection
()
2146 cinderconn
.volumes
.set_metadata(volume_id
, metadata
)
2147 except Exception as e
:
2148 logger
.error("OpenstackDriver: Set metadata operation failed. Exception: %s" %(str(e
)))
2151 def volume_delete_metadata(self
, volume_id
, metadata
):
2153 Delete metadata for volume
2154 Metadata is a dictionary of key-value pairs
2158 Returns: List of dictionaries.
2160 cinderconn
= self
._get
_cinder
_connection
()
2162 cinderconn
.volumes
.delete_metadata(volume_id
, metadata
)
2163 except Exception as e
:
2164 logger
.error("OpenstackDriver: Delete metadata operation failed. Exception: %s" %(str(e
)))
2167 class CinderDriverV2(CinderDriver
):
2169 Driver for openstack cinder-client V2
2171 def __init__(self
, ks_drv
):
2172 super(CinderDriverV2
, self
).__init
__(ks_drv
, 'volumev2', 2)