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
):
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
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 super(KeystoneDriverV2
, self
).__init
__(ksclientv2
.Client
)
240 def _get_keystone_credentials(self
):
242 Returns the dictionary of kwargs required to instantiate python-keystoneclient class
245 #creds['user_domain'] = self._domain_name
246 creds
['username'] = self
._username
247 creds
['password'] = self
._password
248 creds
['auth_url'] = self
._auth
_url
249 creds
['tenant_name'] = self
._tenant
_name
250 creds
['insecure'] = self
.get_security_mode()
253 def get_auth_token(self
):
255 Returns a valid auth_token
257 Returns (string): auth_token string
259 ksconn
= self
._get
_keystone
_connection
()
260 return ksconn
.auth_token
262 def is_auth_token_valid(self
):
264 Performs validity on auth_token
268 True/False (Boolean): (auth_token is valid or auth_token is invalid)
270 ksconn
= self
._get
_keystone
_connection
()
271 result
= super(KeystoneDriverV2
, self
).is_auth_token_valid(ksconn
.auth_ref
['token']['expires'],
272 "%Y-%m-%dT%H:%M:%SZ")
276 class KeystoneDriverV3(KeystoneDriver
):
278 Driver class for keystoneclient V3 APIs
280 def __init__(self
, username
, password
, auth_url
,tenant_name
, insecure
, user_domain_name
= None, project_domain_name
= None):
282 Constructor for KeystoneDriverV3 class
284 username (string) : Username
285 password (string) : Password
286 auth_url (string) : Authentication URL
287 tenant_name(string): Tenant Name
291 self
._username
= username
292 self
._password
= password
293 self
._auth
_url
= auth_url
294 self
._tenant
_name
= tenant_name
295 self
._insecure
= insecure
296 self
._user
_domain
_name
= user_domain_name
297 self
._project
_domain
_name
= project_domain_name
298 super(KeystoneDriverV3
, self
).__init
__(ksclientv3
.Client
)
300 def _get_keystone_credentials(self
):
302 Returns the dictionary of kwargs required to instantiate python-keystoneclient class
305 creds
['username'] = self
._username
306 creds
['password'] = self
._password
307 creds
['auth_url'] = self
._auth
_url
308 creds
['project_name'] = self
._tenant
_name
309 creds
['insecure'] = self
._insecure
310 creds
['user_domain_name'] = self
._user
_domain
_name
311 creds
['project_domain_name'] = self
._project
_domain
_name
314 def get_user_domain_name(self
):
316 Returns the domain_name of the associated OpenStack user account
318 return self
._user
_domain
_name
;
320 def get_project_domain_name(self
):
322 Returns the domain_name of the associated OpenStack project
324 return self
._project
_domain
_name
;
326 def get_auth_token(self
):
328 Returns a valid auth_token
330 Returns (string): auth_token string
332 ksconn
= self
._get
_keystone
_connection
()
333 return ksconn
.auth_ref
['auth_token']
335 def is_auth_token_valid(self
):
337 Performs validity on auth_token
341 True/False (Boolean): (auth_token is valid or auth_token is invalid)
343 ksconn
= self
._get
_keystone
_connection
()
344 result
= super(KeystoneDriverV3
, self
).is_auth_token_valid(ksconn
.auth_ref
['expires_at'],
345 "%Y-%m-%dT%H:%M:%S.%fZ")
348 class NovaDriver(object):
350 Driver for openstack nova_client
352 def __init__(self
, ks_drv
, service_name
, version
):
354 Constructor for NovaDriver
355 Arguments: KeystoneDriver class object
358 self
._service
_name
= service_name
359 self
._version
= version
361 def _get_nova_credentials(self
):
363 Returns a dictionary of kwargs required to instantiate python-novaclient class
366 creds
['version'] = self
._version
367 creds
['bypass_url'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, "publicURL")
368 creds
['username'] = self
.ks_drv
.get_username()
369 creds
['project_id'] = self
.ks_drv
.get_tenant_name()
370 creds
['auth_token'] = self
.ks_drv
.get_auth_token()
371 creds
['insecure'] = self
.ks_drv
.get_security_mode()
372 creds
['user_domain_name'] = self
.ks_drv
.get_user_domain_name()
373 creds
['project_domain_name'] = self
.ks_drv
.get_project_domain_name()
377 def _get_nova_connection(self
):
379 Returns an object of class python-novaclient
381 if not hasattr(self
, '_nova_connection'):
382 self
._nova
_connection
= nova_client
.Client(**self
._get
_nova
_credentials
())
384 # Reinitialize if auth_token is no longer valid
385 if not self
.ks_drv
.is_auth_token_valid():
386 self
._nova
_connection
= nova_client
.Client(**self
._get
_nova
_credentials
())
387 return self
._nova
_connection
389 def _flavor_get(self
, flavor_id
):
391 Get flavor by flavor_id
393 flavor_id(string): UUID of flavor_id
396 dictionary of flavor parameters
398 nvconn
= self
._get
_nova
_connection
()
400 flavor
= nvconn
.flavors
.get(flavor_id
)
401 except Exception as e
:
402 logger
.info("OpenstackDriver: Did not find flavor with flavor_id : %s. Exception: %s"%(flavor_id
, str(e
)))
406 extra_specs
= flavor
.get_keys()
407 except Exception as e
:
408 logger
.info("OpenstackDriver: Could not get the EPA attributes for flavor with flavor_id : %s. Exception: %s"%(flavor_id
, str(e
)))
411 response
= flavor
.to_dict()
412 assert 'extra_specs' not in response
, "Key extra_specs present as flavor attribute"
413 response
['extra_specs'] = extra_specs
416 def flavor_get(self
, flavor_id
):
418 Get flavor by flavor_id
420 flavor_id(string): UUID of flavor_id
423 dictionary of flavor parameters
425 return self
._flavor
_get
(flavor_id
)
427 def flavor_list(self
):
429 Returns list of all flavors (dictionary per flavor)
434 A list of dictionaries. Each dictionary contains attributes for a single flavor instance
438 nvconn
= self
._get
_nova
_connection
()
440 flavors
= nvconn
.flavors
.list()
441 except Exception as e
:
442 logger
.error("OpenstackDriver: List Flavor operation failed. Exception: %s"%(str(e
)))
445 flavor_info
= [ self
.flavor_get(flv
.id) for flv
in flavors
]
448 def flavor_create(self
, name
, ram
, vcpu
, disk
, extra_specs
):
453 name (string): Name of the new flavor
454 ram (int) : Memory in MB
455 vcpus (int) : Number of VCPUs
456 disk (int) : Secondary storage size in GB
457 extra_specs (dictionary): EPA attributes dictionary
460 flavor_id (string): UUID of flavor created
462 nvconn
= self
._get
_nova
_connection
()
464 flavor
= nvconn
.flavors
.create(name
= name
,
473 except Exception as e
:
474 logger
.error("OpenstackDriver: Create Flavor operation failed. Exception: %s"%(str(e
)))
479 flavor
.set_keys(extra_specs
)
480 except Exception as e
:
481 logger
.error("OpenstackDriver: Set Key operation failed for flavor: %s. Exception: %s" %(flavor
.id, str(e
)))
485 def flavor_delete(self
, flavor_id
):
487 Deletes a flavor identified by flavor_id
490 flavor_id (string): UUID of flavor to be deleted
494 assert flavor_id
== self
._flavor
_get
(flavor_id
)['id']
495 nvconn
= self
._get
_nova
_connection
()
497 nvconn
.flavors
.delete(flavor_id
)
498 except Exception as e
:
499 logger
.error("OpenstackDriver: Delete flavor operation failed for flavor: %s. Exception: %s" %(flavor_id
, str(e
)))
503 def server_list(self
):
505 Returns a list of available VMs for the project
510 A list of dictionaries. Each dictionary contains attributes associated
515 nvconn
= self
._get
_nova
_connection
()
517 servers
= nvconn
.servers
.list()
518 except Exception as e
:
519 logger
.error("OpenstackDriver: List Server operation failed. Exception: %s" %(str(e
)))
521 server_info
= [ server
.to_dict() for server
in servers
]
524 def _nova_server_get(self
, server_id
):
526 Returns a dictionary of attributes associated with VM identified by service_id
529 server_id (string): UUID of the VM/server for which information is requested
532 A dictionary object with attributes associated with VM identified by server_id
534 nvconn
= self
._get
_nova
_connection
()
536 server
= nvconn
.servers
.get(server
= server_id
)
537 except Exception as e
:
538 logger
.info("OpenstackDriver: Get Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
541 return server
.to_dict()
543 def server_get(self
, server_id
):
545 Returns a dictionary of attributes associated with VM identified by service_id
548 server_id (string): UUID of the VM/server for which information is requested
551 A dictionary object with attributes associated with VM identified by server_id
553 return self
._nova
_server
_get
(server_id
)
555 def server_create(self
, **kwargs
):
557 Creates a new VM/server instance
560 A dictionary of following key-value pairs
562 server_name(string) : Name of the VM/Server
563 flavor_id (string) : UUID of the flavor to be used for VM
564 image_id (string) : UUID of the image to be used VM/Server instance,
565 This could be None if volumes (with images) are being used
566 network_list(List) : A List of network_ids. A port will be created in these networks
567 port_list (List) : A List of port-ids. These ports will be added to VM.
568 metadata (dict) : A dictionary of arbitrary key-value pairs associated with VM/server
569 userdata (string) : A script which shall be executed during first boot of the VM
570 availability_zone (string) : A name of the availability zone where instance should be launched
571 scheduler_hints (string) : Openstack scheduler_hints to be passed to nova scheduler
574 server_id (string): UUID of the VM/server created
578 if 'network_list' in kwargs
:
579 for network_id
in kwargs
['network_list']:
580 nics
.append({'net-id': network_id
})
582 if 'port_list' in kwargs
:
583 for port_id
in kwargs
['port_list']:
584 nics
.append({'port-id': port_id
})
586 nvconn
= self
._get
_nova
_connection
()
590 server
= nvconn
.servers
.create(kwargs
['name'],
593 meta
= kwargs
['metadata'],
594 files
= kwargs
['files'],
595 reservation_id
= None,
598 userdata
= kwargs
['userdata'],
599 security_groups
= kwargs
['security_groups'],
600 availability_zone
= kwargs
['availability_zone'],
601 block_device_mapping_v2
= kwargs
['block_device_mapping_v2'],
603 scheduler_hints
= kwargs
['scheduler_hints'],
604 config_drive
= kwargs
['config_drive'])
605 except Exception as e
:
606 logger
.info("OpenstackDriver: Create Server operation failed. Exception: %s" %(str(e
)))
608 return server
.to_dict()['id']
610 def server_delete(self
, server_id
):
612 Deletes a server identified by server_id
615 server_id (string): UUID of the server to be deleted
619 nvconn
= self
._get
_nova
_connection
()
621 nvconn
.servers
.delete(server_id
)
622 except Exception as e
:
623 logger
.error("OpenstackDriver: Delete server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
626 def server_start(self
, server_id
):
628 Starts a server identified by server_id
631 server_id (string): UUID of the server to be started
635 nvconn
= self
._get
_nova
_connection
()
637 nvconn
.servers
.start(server_id
)
638 except Exception as e
:
639 logger
.error("OpenstackDriver: Start Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
642 def server_stop(self
, server_id
):
645 server_id (string): UUID of the server to be stopped
649 nvconn
= self
._get
_nova
_connection
()
651 nvconn
.servers
.stop(server_id
)
652 except Exception as e
:
653 logger
.error("OpenstackDriver: Stop Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
656 def server_pause(self
, server_id
):
659 server_id (string): UUID of the server to be paused
663 nvconn
= self
._get
_nova
_connection
()
665 nvconn
.servers
.pause(server_id
)
666 except Exception as e
:
667 logger
.error("OpenstackDriver: Pause Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
670 def server_unpause(self
, server_id
):
673 server_id (string): UUID of the server to be unpaused
677 nvconn
= self
._get
_nova
_connection
()
679 nvconn
.servers
.unpause(server_id
)
680 except Exception as e
:
681 logger
.error("OpenstackDriver: Resume Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
685 def server_suspend(self
, server_id
):
688 server_id (string): UUID of the server to be suspended
692 nvconn
= self
._get
_nova
_connection
()
694 nvconn
.servers
.suspend(server_id
)
695 except Exception as e
:
696 logger
.error("OpenstackDriver: Suspend Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
699 def server_resume(self
, server_id
):
702 server_id (string): UUID of the server to be resumed
706 nvconn
= self
._get
_nova
_connection
()
708 nvconn
.servers
.resume(server_id
)
709 except Exception as e
:
710 logger
.error("OpenstackDriver: Resume Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
713 def server_reboot(self
, server_id
, reboot_type
):
716 server_id (string) : UUID of the server to be rebooted
722 nvconn
= self
._get
_nova
_connection
()
724 nvconn
.servers
.reboot(server_id
, reboot_type
)
725 except Exception as e
:
726 logger
.error("OpenstackDriver: Reboot Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
729 def server_console(self
, server_id
, console_type
= 'novnc'):
732 server_id (string) : UUID of the server to be rebooted
733 console_type(string):
737 A dictionary object response for console information
739 nvconn
= self
._get
_nova
_connection
()
741 console_info
= nvconn
.servers
.get_vnc_console(server_id
, console_type
)
742 except Exception as e
:
743 logger
.error("OpenstackDriver: Server Get-Console operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
747 def server_rebuild(self
, server_id
, image_id
):
750 server_id (string) : UUID of the server to be rebooted
751 image_id (string) : UUID of the image to use
755 nvconn
= self
._get
_nova
_connection
()
757 nvconn
.servers
.rebuild(server_id
, image_id
)
758 except Exception as e
:
759 logger
.error("OpenstackDriver: Rebuild Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
763 def server_add_port(self
, server_id
, port_id
):
766 server_id (string): UUID of the server
767 port_id (string): UUID of the port to be attached
771 nvconn
= self
._get
_nova
_connection
()
773 nvconn
.servers
.interface_attach(server_id
,
777 except Exception as e
:
778 logger
.error("OpenstackDriver: Server Port Add operation failed for server_id : %s, port_id : %s. Exception: %s" %(server_id
, port_id
, str(e
)))
781 def server_delete_port(self
, server_id
, port_id
):
784 server_id (string): UUID of the server
785 port_id (string): UUID of the port to be deleted
789 nvconn
= self
._get
_nova
_connection
()
791 nvconn
.servers
.interface_detach(server_id
, port_id
)
792 except Exception as e
:
793 logger
.error("OpenstackDriver: Server Port Delete operation failed for server_id : %s, port_id : %s. Exception: %s" %(server_id
, port_id
, str(e
)))
796 def floating_ip_list(self
):
801 List of objects of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
803 nvconn
= self
._get
_nova
_connection
()
805 ip_list
= nvconn
.floating_ips
.list()
806 except Exception as e
:
807 logger
.error("OpenstackDriver: Floating IP List operation failed. Exception: %s" %str
(e
))
812 def floating_ip_create(self
, pool
):
815 pool (string): Name of the pool (optional)
817 An object of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
819 nvconn
= self
._get
_nova
_connection
()
821 floating_ip
= nvconn
.floating_ips
.create(pool
)
822 except Exception as e
:
823 logger
.error("OpenstackDriver: Floating IP Create operation failed. Exception: %s" %str
(e
))
828 def floating_ip_delete(self
, floating_ip
):
831 floating_ip: An object of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
835 nvconn
= self
._get
_nova
_connection
()
837 floating_ip
= nvconn
.floating_ips
.delete(floating_ip
)
838 except Exception as e
:
839 logger
.error("OpenstackDriver: Floating IP Delete operation failed. Exception: %s" %str
(e
))
842 def floating_ip_assign(self
, server_id
, floating_ip
, fixed_ip
):
845 server_id (string) : UUID of the server
846 floating_ip (string): IP address string for floating-ip
847 fixed_ip (string) : IP address string for the fixed-ip with which floating ip will be associated
851 nvconn
= self
._get
_nova
_connection
()
853 nvconn
.servers
.add_floating_ip(server_id
, floating_ip
, fixed_ip
)
854 except Exception as e
:
855 logger
.error("OpenstackDriver: Assign Floating IP operation failed. Exception: %s" %str
(e
))
858 def floating_ip_release(self
, server_id
, floating_ip
):
861 server_id (string) : UUID of the server
862 floating_ip (string): IP address string for floating-ip
866 nvconn
= self
._get
_nova
_connection
()
868 nvconn
.servers
.remove_floating_ip(server_id
, floating_ip
)
869 except Exception as e
:
870 logger
.error("OpenstackDriver: Release Floating IP operation failed. Exception: %s" %str
(e
))
873 def volume_list(self
, server_id
):
875 List of volumes attached to the server
880 List of dictionary objects where dictionary is representation of class (novaclient.v2.volumes.Volume)
882 nvconn
= self
._get
_nova
_connection
()
884 volumes
= nvconn
.volumes
.get_server_volumes(server_id
=server_id
)
885 except Exception as e
:
886 logger
.error("OpenstackDriver: Get volume information failed. Exception: %s" %str
(e
))
889 volume_info
= [v
.to_dict() for v
in volumes
]
893 def group_list(self
):
895 List of Server Affinity and Anti-Affinity Groups
900 List of dictionary objects where dictionary is representation of class (novaclient.v2.server_groups.ServerGroup)
902 nvconn
= self
._get
_nova
_connection
()
904 group_list
= nvconn
.server_groups
.list()
905 except Exception as e
:
906 logger
.error("OpenstackDriver: Server Group List operation failed. Exception: %s" %str
(e
))
909 group_info
= [ group
.to_dict() for group
in group_list
]
914 class NovaDriverV2(NovaDriver
):
916 Driver class for novaclient V2 APIs
918 def __init__(self
, ks_drv
):
920 Constructor for NovaDriver
921 Arguments: KeystoneDriver class object
923 super(NovaDriverV2
, self
).__init
__(ks_drv
, 'compute', '2.0')
925 class NovaDriverV21(NovaDriver
):
927 Driver class for novaclient V2 APIs
929 def __init__(self
, ks_drv
):
931 Constructor for NovaDriver
932 Arguments: KeystoneDriver class object
934 super(NovaDriverV21
, self
).__init
__(ks_drv
, 'compute', '2.1')
936 class GlanceDriver(object):
938 Driver for openstack glance-client
940 def __init__(self
, ks_drv
, service_name
, version
):
942 Constructor for GlanceDriver
943 Arguments: KeystoneDriver class object
946 self
._service
_name
= service_name
947 self
._version
= version
949 def _get_glance_credentials(self
):
951 Returns a dictionary of kwargs required to instantiate python-glanceclient class
956 A dictionary object of arguments
959 creds
['version'] = self
._version
960 creds
['endpoint'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, 'publicURL')
961 creds
['token'] = self
.ks_drv
.get_auth_token()
962 creds
['insecure'] = self
.ks_drv
.get_security_mode()
965 def _get_glance_connection(self
):
967 Returns a object of class python-glanceclient
969 if not hasattr(self
, '_glance_connection'):
970 self
._glance
_connection
= glclient
.Client(**self
._get
_glance
_credentials
())
972 # Reinitialize if auth_token is no longer valid
973 if not self
.ks_drv
.is_auth_token_valid():
974 self
._glance
_connection
= glclient
.Client(**self
._get
_glance
_credentials
())
975 return self
._glance
_connection
977 def image_list(self
):
979 Returns list of dictionaries. Each dictionary contains attributes associated with
984 Returns: List of dictionaries.
986 glconn
= self
._get
_glance
_connection
()
989 image_info
= glconn
.images
.list()
990 except Exception as e
:
991 logger
.error("OpenstackDriver: List Image operation failed. Exception: %s" %(str(e
)))
993 images
= [ img
for img
in image_info
]
996 def image_create(self
, **kwargs
):
1000 A dictionary of kwargs with following keys
1002 'name'(string) : Name of the image
1003 'location'(string) : URL (http://....) where image is located
1004 'disk_format'(string) : Disk format
1005 Possible values are 'ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso'
1006 'container_format'(string): Container format
1007 Possible values are 'ami', 'ari', 'aki', 'bare', 'ovf'
1008 'tags' : A list of user tags
1009 'checksum' : The image md5 checksum
1012 image_id (string) : UUID of the image
1015 glconn
= self
._get
_glance
_connection
()
1017 image
= glconn
.images
.create(**kwargs
)
1018 except Exception as e
:
1019 logger
.error("OpenstackDriver: Create Image operation failed. Exception: %s" %(str(e
)))
1024 def image_upload(self
, image_id
, fd
):
1029 image_id: UUID of the image
1030 fd : File descriptor for the image file
1033 glconn
= self
._get
_glance
_connection
()
1035 glconn
.images
.upload(image_id
, fd
)
1036 except Exception as e
:
1037 logger
.error("OpenstackDriver: Image upload operation failed. Exception: %s" %(str(e
)))
1040 def image_add_location(self
, image_id
, location
, metadata
):
1042 Add image URL location
1045 image_id : UUID of the image
1046 location : http URL for the image
1050 glconn
= self
._get
_glance
_connection
()
1052 image
= glconn
.images
.add_location(image_id
, location
, metadata
)
1053 except Exception as e
:
1054 logger
.error("OpenstackDriver: Image location add operation failed. Exception: %s" %(str(e
)))
1057 def image_update(self
):
1060 def image_delete(self
, image_id
):
1065 image_id: UUID of the image
1070 assert image_id
== self
._image
_get
(image_id
)['id']
1071 glconn
= self
._get
_glance
_connection
()
1073 glconn
.images
.delete(image_id
)
1074 except Exception as e
:
1075 logger
.error("OpenstackDriver: Delete Image operation failed for image_id : %s. Exception: %s" %(image_id
, str(e
)))
1079 def _image_get(self
, image_id
):
1081 Returns a dictionary object of VM image attributes
1084 image_id (string): UUID of the image
1087 A dictionary of the image attributes
1089 glconn
= self
._get
_glance
_connection
()
1091 image
= glconn
.images
.get(image_id
)
1092 except GlanceException
.HTTPBadRequest
:
1093 # RIFT-14241: The get image request occasionally returns the below message. Retry in case of bad request exception.
1094 # Error code 400.: Message: Bad request syntax ('0').: Error code explanation: 400 = Bad request syntax or unsupported method. (HTTP 400)
1095 logger
.warning("OpenstackDriver: Got bad request response during get_image request. Retrying.")
1096 image
= glconn
.images
.get(image_id
)
1097 except Exception as e
:
1098 logger
.error("OpenstackDriver: Get Image operation failed for image_id : %s. Exception: %s" %(image_id
, str(e
)))
1103 def image_get(self
, image_id
):
1105 Returns a dictionary object of VM image attributes
1108 image_id (string): UUID of the image
1111 A dictionary of the image attributes
1113 return self
._image
_get
(image_id
)
1115 class GlanceDriverV2(GlanceDriver
):
1117 Driver for openstack glance-client V2
1119 def __init__(self
, ks_drv
):
1120 super(GlanceDriverV2
, self
).__init
__(ks_drv
, 'image', 2)
1122 class NeutronDriver(object):
1124 Driver for openstack neutron neutron-client
1126 def __init__(self
, ks_drv
, service_name
, version
):
1128 Constructor for NeutronDriver
1129 Arguments: KeystoneDriver class object
1131 self
.ks_drv
= ks_drv
1132 self
._service
_name
= service_name
1133 self
._version
= version
1135 def _get_neutron_credentials(self
):
1137 Returns a dictionary of kwargs required to instantiate python-neutronclient class
1140 Dictionary of kwargs
1143 creds
['api_version'] = self
._version
1144 creds
['endpoint_url'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, 'publicURL')
1145 creds
['token'] = self
.ks_drv
.get_auth_token()
1146 creds
['tenant_name'] = self
.ks_drv
.get_tenant_name()
1147 creds
['insecure'] = self
.ks_drv
.get_security_mode()
1150 def _get_neutron_connection(self
):
1152 Returns an object of class python-neutronclient
1154 if not hasattr(self
, '_neutron_connection'):
1155 self
._neutron
_connection
= ntclient
.Client(**self
._get
_neutron
_credentials
())
1157 # Reinitialize if auth_token is no longer valid
1158 if not self
.ks_drv
.is_auth_token_valid():
1159 self
._neutron
_connection
= ntclient
.Client(**self
._get
_neutron
_credentials
())
1160 return self
._neutron
_connection
1162 def network_list(self
):
1164 Returns list of dictionaries. Each dictionary contains the attributes for a network
1170 A list of dictionaries
1173 ntconn
= self
._get
_neutron
_connection
()
1175 networks
= ntconn
.list_networks()
1176 except Exception as e
:
1177 logger
.error("OpenstackDriver: List Network operation failed. Exception: %s" %(str(e
)))
1179 return networks
['networks']
1181 def network_create(self
, **kwargs
):
1183 Creates a new network for the project
1186 A dictionary with following key-values
1188 name (string) : Name of the network
1189 admin_state_up(Boolean) : True/False (Defaults: True)
1190 external_router(Boolean) : Connectivity with external router. True/False (Defaults: False)
1191 shared(Boolean) : Shared among tenants. True/False (Defaults: False)
1192 physical_network(string) : The physical network where this network object is implemented (optional).
1193 network_type : The type of physical network that maps to this network resource (optional).
1194 Possible values are: 'flat', 'vlan', 'vxlan', 'gre'
1195 segmentation_id : An isolated segment on the physical network. The network_type attribute
1196 defines the segmentation model. For example, if the network_type value
1197 is vlan, this ID is a vlan identifier. If the network_type value is gre,
1198 this ID is a gre key.
1201 params
= {'network':
1202 {'name' : kwargs
['name'],
1203 'admin_state_up' : kwargs
['admin_state_up'],
1204 'tenant_id' : self
.ks_drv
.get_tenant_id(),
1205 'shared' : kwargs
['shared'],
1206 #'port_security_enabled': port_security_enabled,
1207 'router:external' : kwargs
['external_router']}}
1209 if 'physical_network' in kwargs
:
1210 params
['network']['provider:physical_network'] = kwargs
['physical_network']
1211 if 'network_type' in kwargs
:
1212 params
['network']['provider:network_type'] = kwargs
['network_type']
1213 if 'segmentation_id' in kwargs
:
1214 params
['network']['provider:segmentation_id'] = kwargs
['segmentation_id']
1216 ntconn
= self
._get
_neutron
_connection
()
1218 logger
.debug("Calling neutron create_network() with params: %s", str(params
))
1219 net
= ntconn
.create_network(params
)
1220 except Exception as e
:
1221 logger
.error("OpenstackDriver: Create Network operation failed. Exception: %s" %(str(e
)))
1223 logger
.debug("Got create_network response from neutron connection: %s", str(net
))
1224 network_id
= net
['network']['id']
1226 raise Exception("Empty network id returned from create_network. (params: %s)" % str(params
))
1230 def network_delete(self
, network_id
):
1232 Deletes a network identified by network_id
1235 network_id (string): UUID of the network
1239 assert network_id
== self
._network
_get
(network_id
)['id']
1240 ntconn
= self
._get
_neutron
_connection
()
1242 ntconn
.delete_network(network_id
)
1243 except Exception as e
:
1244 logger
.error("OpenstackDriver: Delete Network operation failed. Exception: %s" %(str(e
)))
1247 def _network_get(self
, network_id
):
1249 Returns a dictionary object describing the attributes of the network
1252 network_id (string): UUID of the network
1255 A dictionary object of the network attributes
1257 ntconn
= self
._get
_neutron
_connection
()
1258 network
= ntconn
.list_networks(id = network_id
)['networks']
1260 raise NeutronException
.NotFound("Network with id %s not found"%(network_id))
1264 def network_get(self
, network_id
):
1266 Returns a dictionary object describing the attributes of the network
1269 network_id (string): UUID of the network
1272 A dictionary object of the network attributes
1274 return self
._network
_get
(network_id
)
1276 def subnet_create(self
, **kwargs
):
1278 Creates a subnet on the network
1281 A dictionary with following key value pairs
1283 network_id(string) : UUID of the network where subnet needs to be created
1284 subnet_cidr(string) : IPv4 address prefix (e.g. '1.1.1.0/24') for the subnet
1285 ip_version (integer): 4 for IPv4 and 6 for IPv6
1290 subnet_id (string): UUID of the created subnet
1293 params
['network_id'] = kwargs
['network_id']
1294 params
['ip_version'] = kwargs
['ip_version']
1296 # if params['ip_version'] == 6:
1297 # assert 0, "IPv6 is not supported"
1299 if 'subnetpool_id' in kwargs
:
1300 params
['subnetpool_id'] = kwargs
['subnetpool_id']
1302 params
['cidr'] = kwargs
['cidr']
1304 if 'gateway_ip' in kwargs
:
1305 params
['gateway_ip'] = kwargs
['gateway_ip']
1307 params
['gateway_ip'] = None
1309 if 'dhcp_params' in kwargs
:
1310 params
['enable_dhcp'] = kwargs
['dhcp_params']['enable_dhcp']
1311 if 'start_address' in kwargs
['dhcp_params'] and 'count' in kwargs
['dhcp_params']:
1312 end_address
= (ipaddress
.IPv4Address(kwargs
['dhcp_params']['start_address']) + kwargs
['dhcp_params']['count']).compressed
1313 params
['allocation_pools'] = [ {'start': kwargs
['dhcp_params']['start_address'] ,
1314 'end' : end_address
} ]
1316 if 'dns_server' in kwargs
:
1317 params
['dns_nameservers'] = []
1318 for server
in kwargs
['dns_server']:
1319 params
['dns_nameservers'].append(server
)
1321 ntconn
= self
._get
_neutron
_connection
()
1323 subnet
= ntconn
.create_subnet({'subnets': [params
]})
1324 except Exception as e
:
1325 logger
.error("OpenstackDriver: Create Subnet operation failed. Exception: %s" %(str(e
)))
1328 return subnet
['subnets'][0]['id']
1330 def subnet_list(self
):
1332 Returns a list of dictionaries. Each dictionary contains attributes describing the subnet
1337 A dictionary of the objects of subnet attributes
1339 ntconn
= self
._get
_neutron
_connection
()
1341 subnets
= ntconn
.list_subnets()['subnets']
1342 except Exception as e
:
1343 logger
.error("OpenstackDriver: List Subnet operation failed. Exception: %s" %(str(e
)))
1347 def _subnet_get(self
, subnet_id
):
1349 Returns a dictionary object describing the attributes of a subnet.
1352 subnet_id (string): UUID of the subnet
1355 A dictionary object of the subnet attributes
1357 ntconn
= self
._get
_neutron
_connection
()
1358 subnets
= ntconn
.list_subnets(id=subnet_id
)
1359 if not subnets
['subnets']:
1360 logger
.error("OpenstackDriver: Get subnet operation failed for subnet_id: %s" %(subnet_id))
1361 #raise NeutronException.NotFound("Could not find subnet_id %s" %(subnet_id))
1364 return subnets
['subnets'][0]
1366 def subnet_get(self
, subnet_id
):
1368 Returns a dictionary object describing the attributes of a subnet.
1371 subnet_id (string): UUID of the subnet
1374 A dictionary object of the subnet attributes
1376 return self
._subnet
_get
(subnet_id
)
1378 def subnet_delete(self
, subnet_id
):
1380 Deletes a subnet identified by subnet_id
1383 subnet_id (string): UUID of the subnet to be deleted
1387 ntconn
= self
._get
_neutron
_connection
()
1388 assert subnet_id
== self
._subnet
_get
(self
,subnet_id
)
1390 ntconn
.delete_subnet(subnet_id
)
1391 except Exception as e
:
1392 logger
.error("OpenstackDriver: Delete Subnet operation failed for subnet_id : %s. Exception: %s" %(subnet_id
, str(e
)))
1395 def port_list(self
, **kwargs
):
1397 Returns a list of dictionaries. Each dictionary contains attributes describing the port
1400 kwargs (dictionary): A dictionary for filters for port_list operation
1403 A dictionary of the objects of port attributes
1407 ntconn
= self
._get
_neutron
_connection
()
1409 kwargs
['tenant_id'] = self
.ks_drv
.get_tenant_id()
1412 ports
= ntconn
.list_ports(**kwargs
)
1413 except Exception as e
:
1414 logger
.info("OpenstackDriver: List Port operation failed. Exception: %s" %(str(e
)))
1416 return ports
['ports']
1418 def port_create(self
, **kwargs
):
1420 Create a port in network
1423 A dictionary of following
1425 name (string) : Name of the port
1426 network_id(string) : UUID of the network_id identifying the network to which port belongs
1427 subnet_id(string) : UUID of the subnet_id from which IP-address will be assigned to port
1428 vnic_type(string) : Possible values are "normal", "direct", "macvtap"
1431 port_id (string) : UUID of the port
1435 "admin_state_up" : kwargs
['admin_state_up'],
1436 "name" : kwargs
['name'],
1437 "network_id" : kwargs
['network_id'],
1438 "fixed_ips" : [ {"subnet_id": kwargs
['subnet_id']}],
1439 "binding:vnic_type" : kwargs
['port_type']}}
1441 ntconn
= self
._get
_neutron
_connection
()
1443 port
= ntconn
.create_port(params
)
1444 except Exception as e
:
1445 logger
.error("OpenstackDriver: Port Create operation failed. Exception: %s" %(str(e
)))
1447 return port
['port']['id']
1449 def _port_get(self
, port_id
):
1451 Returns a dictionary object describing the attributes of the port
1454 port_id (string): UUID of the port
1457 A dictionary object of the port attributes
1459 ntconn
= self
._get
_neutron
_connection
()
1460 port
= ntconn
.list_ports(id=port_id
)['ports']
1462 raise NeutronException
.NotFound("Could not find port_id %s" %(port_id))
1465 def port_get(self
, port_id
):
1467 Returns a dictionary object describing the attributes of the port
1470 port_id (string): UUID of the port
1473 A dictionary object of the port attributes
1475 return self
._port
_get
(port_id
)
1477 def port_delete(self
, port_id
):
1479 Deletes a port identified by port_id
1482 port_id (string) : UUID of the port
1486 assert port_id
== self
._port
_get
(port_id
)['id']
1487 ntconn
= self
._get
_neutron
_connection
()
1489 ntconn
.delete_port(port_id
)
1490 except Exception as e
:
1491 logger
.error("Port Delete operation failed for port_id : %s. Exception: %s" %(port_id
, str(e
)))
1494 def security_group_list(self
):
1496 Returns a list of dictionaries. Each dictionary contains attributes describing the security group
1502 A dictionary of the objects of security group attributes
1504 ntconn
= self
._get
_neutron
_connection
()
1506 group_list
= ntconn
.list_security_groups(tenant_id
=self
.ks_drv
.get_tenant_id())
1507 except Exception as e
:
1508 logger
.error("List Security group operation, Exception: %s" %(str(e
)))
1511 if 'security_groups' in group_list
:
1512 return group_list
['security_groups']
1516 def subnetpool_list(self
, **kwargs
):
1518 Returns a list of dictionaries. Each dictionary contains attributes describing a subnet prefix pool
1524 A dictionary of the objects of subnet prefix pool
1526 ntconn
= self
._get
_neutron
_connection
()
1528 pool_list
= ntconn
.list_subnetpools(**kwargs
)
1529 except Exception as e
:
1530 logger
.error("List SubnetPool operation, Exception: %s" %(str(e
)))
1533 if 'subnetpools' in pool_list
:
1534 return pool_list
['subnetpools']
1538 class NeutronDriverV2(NeutronDriver
):
1540 Driver for openstack neutron neutron-client v2
1542 def __init__(self
, ks_drv
):
1544 Constructor for NeutronDriver
1545 Arguments: KeystoneDriver class object
1547 super(NeutronDriverV2
, self
).__init
__(ks_drv
, 'network', '2.0')
1551 class CeilometerDriver(object):
1553 Driver for openstack ceilometer client
1556 def __init__(self
, ks_drv
, service_name
, version
):
1558 Constructor for CeilometerDriver
1559 Arguments: KeystoneDriver class object
1561 self
.ks_drv
= ks_drv
1562 self
._service
_name
= service_name
1563 self
._version
= version
1568 """The version of the ceilometer client used by the driver"""
1569 return self
._version
1573 """The instance of ceilometer client used by the driver"""
1574 if self
._client
is None or not self
.ks_drv
.is_auth_token_valid():
1575 self
._client
= ceilo_client
.Client(**self
.credentials
)
1580 def auth_token(self
):
1581 """The authorization token for the ceilometer client"""
1583 return self
.ks_drv
.get_auth_token()
1584 except KeystoneExceptions
.EndpointNotFound
as e
:
1585 logger
.error("OpenstackDriver: unable to get authorization token for ceilometer. Exception: %s" %(str(e
)))
1589 def security_mode(self
):
1590 """The security mode for the ceilometer client"""
1592 return self
.ks_drv
.get_security_mode()
1593 except KeystoneExceptions
.EndpointNotFound
as e
:
1594 logger
.error("OpenstackDriver: unable to get security mode for ceilometer. Exception: %s" %(str(e
)))
1599 """The service endpoint for the ceilometer client"""
1601 return self
.ks_drv
.get_service_endpoint(self
._service
_name
, "publicURL")
1602 except KeystoneExceptions
.EndpointNotFound
as e
:
1603 logger
.error("OpenstackDriver: unable to get endpoint for ceilometer. Exception: %s" %(str(e
)))
1607 def credentials(self
):
1608 """A dictionary of credentials for the ceilometer client"""
1610 version
=self
.version
,
1611 endpoint
=self
.endpoint
,
1612 token
=self
.auth_token
,
1613 insecure
=self
.security_mode
,
1618 """A list of the available meters"""
1620 return self
.client
.meters
.list()
1621 except Exception as e
:
1622 logger
.error("OpenstackDriver: List meters operation failed. Exception: %s" %(str(e
)))
1627 """The ceilometer client alarms manager"""
1628 return self
.client
.alarms
1630 def query_samples(self
, vim_instance_id
, counter_name
, limit
=1):
1631 """Returns a list of samples
1634 vim_instance_id - the ID of the VIM that the samples are from
1635 counter_name - the counter that the samples will come from
1636 limit - a limit on the number of samples to return
1644 filter = json
.dumps({
1646 {"=": {"resource": vim_instance_id
}},
1647 {"=": {"counter_name": counter_name
}}
1650 result
= self
.client
.query_samples
.query(filter=filter, limit
=limit
)
1651 return result
[-limit
:]
1653 except Exception as e
:
1659 class CeilometerDriverV2(CeilometerDriver
):
1661 Driver for openstack ceilometer ceilometer-client
1663 def __init__(self
, ks_drv
):
1665 Constructor for CeilometerDriver
1666 Arguments: CeilometerDriver class object
1668 super(CeilometerDriverV2
, self
).__init
__(ks_drv
, 'metering', '2')
1670 class OpenstackDriver(object):
1672 Driver for openstack nova, neutron, glance, keystone, swift, cinder services
1674 def __init__(self
, username
, password
, auth_url
, tenant_name
, mgmt_network
= None, cert_validate
= False, user_domain_name
= None, project_domain_name
= None):
1676 OpenstackDriver Driver constructor
1678 username (string) : Username for project/tenant.
1679 password (string) : Password
1680 auth_url (string) : Keystone Authentication URL.
1681 tenant_name (string) : Openstack project name
1682 mgmt_network(string, optional) : Management network name. Each VM created with this cloud-account will
1683 have a default interface into management network.
1684 cert_validate (boolean, optional) : In case of SSL/TLS connection if certificate validation is required or not.
1687 insecure
= not cert_validate
1688 if auth_url
.find('/v3') != -1:
1689 self
.ks_drv
= KeystoneDriverV3(username
, password
, auth_url
, tenant_name
, insecure
, user_domain_name
, project_domain_name
)
1690 self
.glance_drv
= GlanceDriverV2(self
.ks_drv
)
1691 self
.nova_drv
= NovaDriverV21(self
.ks_drv
)
1692 self
.neutron_drv
= NeutronDriverV2(self
.ks_drv
)
1693 self
.ceilo_drv
= CeilometerDriverV2(self
.ks_drv
)
1694 self
.cinder_drv
= CinderDriverV2(self
.ks_drv
)
1695 elif auth_url
.find('/v2') != -1:
1696 self
.ks_drv
= KeystoneDriverV2(username
, password
, auth_url
, tenant_name
, insecure
)
1697 self
.glance_drv
= GlanceDriverV2(self
.ks_drv
)
1698 self
.nova_drv
= NovaDriverV2(self
.ks_drv
)
1699 self
.neutron_drv
= NeutronDriverV2(self
.ks_drv
)
1700 self
.ceilo_drv
= CeilometerDriverV2(self
.ks_drv
)
1701 self
.cinder_drv
= CinderDriverV2(self
.ks_drv
)
1703 logger
.error("Could not identity the version information for openstack service endpoints. Auth_URL should contain \"/v2\" or \"/v3\" string in it")
1704 raise NotImplementedError("Auth URL is wrong or invalid. Only Keystone v2 & v3 supported")
1706 self
._mgmt
_network
_id
= None
1707 if mgmt_network
!= None:
1708 self
._mgmt
_network
= mgmt_network
1712 ntconn
= self
.neutron_drv
._get
_neutron
_connection
()
1713 networks
= ntconn
.list_networks()
1714 except (KeystoneExceptions
.Unauthorized
, KeystoneExceptions
.AuthorizationFailure
) as e
:
1716 except Exception as e
:
1717 logger
.error("OpenstackDriver: List Network operation failed. Exception: %s" %(str(e
)))
1720 network_list
= [ network
for network
in networks
['networks'] if network
['name'] == mgmt_network
]
1722 if not network_list
:
1723 raise NeutronException
.NotFound("Could not find network %s" %(mgmt_network))
1724 self
._mgmt
_network
_id
= network_list
[0]['id']
1726 def validate_account_creds(self
):
1728 ksconn
= self
.ks_drv
._get
_keystone
_connection
()
1729 except KeystoneExceptions
.AuthorizationFailure
as e
:
1730 logger
.error("OpenstackDriver: Unable to authenticate or validate the existing credentials. Exception: %s" %(str(e
)))
1731 raise ValidationError("Invalid Credentials: "+ str(e
))
1732 except Exception as e
:
1733 logger
.error("OpenstackDriver: Could not connect to Openstack. Exception: %s" %(str(e
)))
1734 raise ValidationError("Connection Error: "+ str(e
))
1736 def get_mgmt_network_id(self
):
1737 return self
._mgmt
_network
_id
1739 def glance_image_create(self
, **kwargs
):
1740 if not 'disk_format' in kwargs
:
1741 kwargs
['disk_format'] = 'qcow2'
1742 if not 'container_format' in kwargs
:
1743 kwargs
['container_format'] = 'bare'
1744 if not 'min_disk' in kwargs
:
1745 kwargs
['min_disk'] = 0
1746 if not 'min_ram' in kwargs
:
1747 kwargs
['min_ram'] = 0
1748 return self
.glance_drv
.image_create(**kwargs
)
1750 def glance_image_upload(self
, image_id
, fd
):
1751 self
.glance_drv
.image_upload(image_id
, fd
)
1753 def glance_image_add_location(self
, image_id
, location
):
1754 self
.glance_drv
.image_add_location(image_id
, location
)
1756 def glance_image_delete(self
, image_id
):
1757 self
.glance_drv
.image_delete(image_id
)
1759 def glance_image_list(self
):
1760 return self
.glance_drv
.image_list()
1762 def glance_image_get(self
, image_id
):
1763 return self
.glance_drv
.image_get(image_id
)
1766 def nova_flavor_list(self
):
1767 return self
.nova_drv
.flavor_list()
1769 def nova_flavor_create(self
, name
, ram
, vcpus
, disk
, epa_specs
):
1770 extra_specs
= epa_specs
if epa_specs
else {}
1771 return self
.nova_drv
.flavor_create(name
,
1775 extra_specs
= extra_specs
)
1777 def nova_flavor_delete(self
, flavor_id
):
1778 self
.nova_drv
.flavor_delete(flavor_id
)
1780 def nova_flavor_get(self
, flavor_id
):
1781 return self
.nova_drv
.flavor_get(flavor_id
)
1783 def nova_server_create(self
, **kwargs
):
1784 def _verify_image(image_id
):
1785 image
= self
.glance_drv
.image_get(image_id
)
1786 if image
['status'] != 'active':
1787 raise GlanceException
.NotFound("Image with image_id: %s not found in active state. Current State: %s" %(image
['id'], image
['status']))
1789 assert kwargs
['flavor_id'] == self
.nova_drv
.flavor_get(kwargs
['flavor_id'])['id']
1791 if kwargs
['block_device_mapping_v2'] is not None:
1792 for block_map
in kwargs
['block_device_mapping_v2']:
1793 if 'uuid' in block_map
:
1794 _verify_image(block_map
['uuid'])
1796 _verify_image(kwargs
['image_id'])
1798 # if 'network_list' in kwargs:
1799 # kwargs['network_list'].append(self._mgmt_network_id)
1801 # kwargs['network_list'] = [self._mgmt_network_id]
1803 if 'security_groups' not in kwargs
:
1804 nvconn
= self
.nova_drv
._get
_nova
_connection
()
1805 sec_groups
= nvconn
.security_groups
.list()
1807 ## Should we add VM in all availability security_groups ???
1808 kwargs
['security_groups'] = [x
.name
for x
in sec_groups
]
1810 kwargs
['security_groups'] = None
1812 return self
.nova_drv
.server_create(**kwargs
)
1814 def nova_server_add_port(self
, server_id
, port_id
):
1815 self
.nova_drv
.server_add_port(server_id
, port_id
)
1817 def nova_server_delete_port(self
, server_id
, port_id
):
1818 self
.nova_drv
.server_delete_port(server_id
, port_id
)
1820 def nova_server_start(self
, server_id
):
1821 self
.nova_drv
.server_start(server_id
)
1823 def nova_server_stop(self
, server_id
):
1824 self
.nova_drv
.server_stop(server_id
)
1826 def nova_server_delete(self
, server_id
):
1827 self
.nova_drv
.server_delete(server_id
)
1829 def nova_server_reboot(self
, server_id
):
1830 self
.nova_drv
.server_reboot(server_id
, reboot_type
='HARD')
1832 def nova_server_rebuild(self
, server_id
, image_id
):
1833 self
.nova_drv
.server_rebuild(server_id
, image_id
)
1835 def nova_floating_ip_list(self
):
1836 return self
.nova_drv
.floating_ip_list()
1838 def nova_floating_ip_create(self
, pool
= None):
1839 return self
.nova_drv
.floating_ip_create(pool
)
1841 def nova_floating_ip_delete(self
, floating_ip
):
1842 self
.nova_drv
.floating_ip_delete(floating_ip
)
1844 def nova_floating_ip_assign(self
, server_id
, floating_ip
, fixed_ip
):
1845 self
.nova_drv
.floating_ip_assign(server_id
, floating_ip
, fixed_ip
)
1847 def nova_floating_ip_release(self
, server_id
, floating_ip
):
1848 self
.nova_drv
.floating_ip_release(server_id
, floating_ip
)
1850 def nova_server_list(self
):
1851 return self
.nova_drv
.server_list()
1853 def nova_server_get(self
, server_id
):
1854 return self
.nova_drv
.server_get(server_id
)
1856 def nova_server_console(self
, server_id
):
1857 return self
.nova_drv
.server_console(server_id
)
1859 def nova_server_group_list(self
):
1860 return self
.nova_drv
.group_list()
1862 def nova_volume_list(self
, server_id
):
1863 return self
.nova_drv
.volume_list(server_id
)
1865 def neutron_network_list(self
):
1866 return self
.neutron_drv
.network_list()
1868 def neutron_network_get(self
, network_id
):
1869 return self
.neutron_drv
.network_get(network_id
)
1871 def neutron_network_create(self
, **kwargs
):
1872 return self
.neutron_drv
.network_create(**kwargs
)
1874 def neutron_network_delete(self
, network_id
):
1875 self
.neutron_drv
.network_delete(network_id
)
1877 def neutron_subnet_list(self
):
1878 return self
.neutron_drv
.subnet_list()
1880 def neutron_subnet_get(self
, subnet_id
):
1881 return self
.neutron_drv
.subnet_get(subnet_id
)
1883 def neutron_subnet_create(self
, **kwargs
):
1884 return self
.neutron_drv
.subnet_create(**kwargs
)
1886 def netruon_subnet_delete(self
, subnet_id
):
1887 self
.neutron_drv
.subnet_delete(subnet_id
)
1889 def neutron_subnetpool_list(self
):
1890 return self
.neutron_drv
.subnetpool_list()
1892 def netruon_subnetpool_by_name(self
, pool_name
):
1893 pool_list
= self
.neutron_drv
.subnetpool_list(**{'name': pool_name
})
1899 def neutron_port_list(self
, **kwargs
):
1900 return self
.neutron_drv
.port_list(**kwargs
)
1902 def neutron_port_get(self
, port_id
):
1903 return self
.neutron_drv
.port_get(port_id
)
1905 def neutron_port_create(self
, **kwargs
):
1906 subnets
= [subnet
for subnet
in self
.neutron_drv
.subnet_list() if subnet
['network_id'] == kwargs
['network_id']]
1907 assert len(subnets
) == 1
1908 kwargs
['subnet_id'] = subnets
[0]['id']
1909 if not 'admin_state_up' in kwargs
:
1910 kwargs
['admin_state_up'] = True
1911 port_id
= self
.neutron_drv
.port_create(**kwargs
)
1913 if 'vm_id' in kwargs
:
1914 self
.nova_server_add_port(kwargs
['vm_id'], port_id
)
1917 def neutron_security_group_list(self
):
1918 return self
.neutron_drv
.security_group_list()
1920 def neutron_security_group_by_name(self
, group_name
):
1921 group_list
= self
.neutron_drv
.security_group_list()
1922 groups
= [group
for group
in group_list
if group
['name'] == group_name
]
1928 def neutron_port_delete(self
, port_id
):
1929 self
.neutron_drv
.port_delete(port_id
)
1931 def ceilo_meter_endpoint(self
):
1932 return self
.ceilo_drv
.endpoint
1934 def ceilo_meter_list(self
):
1935 return self
.ceilo_drv
.meters
1937 def ceilo_nfvi_metrics(self
, vim_id
):
1938 """Returns a dict of NFVI metrics for a given VM
1941 vim_id - the VIM ID of the VM to retrieve the metrics for
1944 A dict of NFVI metrics
1947 def query_latest_sample(counter_name
):
1949 filter = json
.dumps({
1951 {"=": {"resource": vim_id
}},
1952 {"=": {"counter_name": counter_name
}}
1955 orderby
= json
.dumps([{"timestamp": "DESC"}])
1956 result
= self
.ceilo_drv
.client
.query_samples
.query(
1966 except Exception as e
:
1967 logger
.error("Got exception while querying ceilometer, exception details:%s " %str
(e
))
1971 memory_usage
= query_latest_sample("memory.usage")
1972 disk_usage
= query_latest_sample("disk.usage")
1973 cpu_util
= query_latest_sample("cpu_util")
1977 if memory_usage
is not None:
1978 memory_usage
.volume
= 1e6
* memory_usage
.volume
1979 metrics
["memory_usage"] = memory_usage
.to_dict()
1981 if disk_usage
is not None:
1982 metrics
["disk_usage"] = disk_usage
.to_dict()
1984 if cpu_util
is not None:
1985 metrics
["cpu_util"] = cpu_util
.to_dict()
1989 def ceilo_alarm_list(self
):
1990 """Returns a list of ceilometer alarms"""
1991 return self
.ceilo_drv
.client
.alarms
.list()
1993 def ceilo_alarm_create(self
,
2006 """Create a new Alarm
2009 name - the name of the alarm
2010 meter - the name of the meter to measure
2011 statistic - the type of statistic used to trigger the alarm
2012 ('avg', 'min', 'max', 'count', 'sum')
2013 operation - the relational operator that, combined with the
2014 threshold value, determines when the alarm is
2015 triggered ('lt', 'le', 'eq', 'ge', 'gt')
2016 threshold - the value of the statistic that will trigger the
2018 period - the duration (seconds) over which to evaluate the
2020 evaluations - the number of samples of the meter statistic to
2021 collect when evaluating the threshold
2022 severity - a measure of the urgency or importance of the alarm
2023 ('low', 'moderate', 'critical')
2024 repeat - a flag that indicates whether the alarm should be
2025 triggered once (False) or repeatedly while the alarm
2026 condition is true (True)
2027 enabled - a flag that indicates whether the alarm is enabled
2028 (True) or disabled (False)
2029 actions - a dict specifying the URLs for webhooks. The dict can
2030 have up to 3 keys: 'insufficient_data', 'alarm',
2031 'ok'. Each key is associated with a list of URLs to
2032 webhooks that will be invoked when one of the 3
2034 kwargs - an arbitrary dict of keyword arguments that are
2035 passed to the ceilometer client
2038 ok_actions
= actions
.get('ok') if actions
is not None else None
2039 alarm_actions
= actions
.get('alarm') if actions
is not None else None
2040 insufficient_data_actions
= actions
.get('insufficient_data') if actions
is not None else None
2042 return self
.ceilo_drv
.client
.alarms
.create(
2045 statistic
=statistic
,
2046 comparison_operator
=operation
,
2047 threshold
=threshold
,
2049 evaluation_periods
=evaluations
,
2051 repeat_actions
=repeat
,
2053 ok_actions
=ok_actions
,
2054 alarm_actions
=alarm_actions
,
2055 insufficient_data_actions
=insufficient_data_actions
,
2059 def ceilo_alarm_update(self
, alarm_id
, **kwargs
):
2060 """Updates an existing alarm
2063 alarm_id - the identifier of the alarm to update
2064 kwargs - a dict of the alarm attributes to update
2067 return self
.ceilo_drv
.client
.alarms
.update(alarm_id
, **kwargs
)
2069 def ceilo_alarm_delete(self
, alarm_id
):
2070 self
.ceilo_drv
.client
.alarms
.delete(alarm_id
)
2072 def cinder_volume_list(self
):
2073 return self
.cinder_drv
.volume_list()
2075 def cinder_volume_get(self
,vol_id
):
2076 return self
.cinder_drv
.volume_get(vol_id
)
2078 def cinder_volume_set_metadata(self
, volumeid
, metadata
):
2079 return self
.cinder_drv
.volume_set_metadata(volumeid
, metadata
)
2081 def cinder_volume_delete_metadata(self
, volumeid
, metadata
):
2082 return self
.cinder_drv
.volume_delete_metadata(volumeid
, metadata
)
2086 class CinderDriver(object):
2088 Driver for openstack cinder-client
2090 def __init__(self
, ks_drv
, service_name
, version
):
2092 Constructor for CinderDriver
2093 Arguments: KeystoneDriver class object
2095 self
.ks_drv
= ks_drv
2096 self
._service
_name
= service_name
2097 self
._version
= version
2099 def _get_cinder_credentials(self
):
2101 Returns a dictionary of kwargs required to instantiate python-cinderclient class
2106 A dictionary object of arguments
2109 creds
['version'] = self
._version
2110 creds
['username'] = self
.ks_drv
.get_username()
2111 creds
['api_key'] = self
.ks_drv
.get_password()
2112 creds
['auth_url'] = self
.ks_drv
.get_service_endpoint("identity", "publicURL")
2113 creds
['project_id'] = self
.ks_drv
.get_tenant_name()
2114 creds
['insecure'] = self
.ks_drv
.get_security_mode()
2118 def _get_cinder_connection(self
):
2120 Returns a object of class python-cinderclient
2122 if not hasattr(self
, '_cinder_connection'):
2123 self
._cinder
_connection
= cinder_client
.Client(**self
._get
_cinder
_credentials
())
2125 # Reinitialize if auth_token is no longer valid
2126 if not self
.ks_drv
.is_auth_token_valid():
2127 self
._cinder
_connection
= cinder_client
.Client(**self
._get
_cinder
_credentials
())
2128 return self
._cinder
_connection
2130 def volume_list(self
):
2132 Returns list of dictionaries. Each dictionary contains attributes associated with
2137 Returns: List of dictionaries.
2139 cinderconn
= self
._get
_cinder
_connection
()
2142 volume_info
= cinderconn
.volumes
.list()
2143 except Exception as e
:
2144 logger
.error("OpenstackDriver: List volumes operation failed. Exception: %s" %(str(e
)))
2146 volumes
= [ volume
for volume
in volume_info
]
2149 def volume_get(self
, volume_id
):
2155 Returns: List of dictionaries.
2157 cinderconn
= self
._get
_cinder
_connection
()
2159 vol
= cinderconn
.volumes
.get(volume_id
)
2160 except Exception as e
:
2161 logger
.error("OpenstackDriver: Get volume operation failed. Exception: %s" %(str(e
)))
2165 def volume_set_metadata(self
, volume_id
, metadata
):
2167 Set metadata for volume
2168 Metadata is a dictionary of key-value pairs
2172 Returns: List of dictionaries.
2174 cinderconn
= self
._get
_cinder
_connection
()
2176 cinderconn
.volumes
.set_metadata(volume_id
, metadata
)
2177 except Exception as e
:
2178 logger
.error("OpenstackDriver: Set metadata operation failed. Exception: %s" %(str(e
)))
2181 def volume_delete_metadata(self
, volume_id
, metadata
):
2183 Delete metadata for volume
2184 Metadata is a dictionary of key-value pairs
2188 Returns: List of dictionaries.
2190 cinderconn
= self
._get
_cinder
_connection
()
2192 cinderconn
.volumes
.delete_metadata(volume_id
, metadata
)
2193 except Exception as e
:
2194 logger
.error("OpenstackDriver: Delete metadata operation failed. Exception: %s" %(str(e
)))
2197 class CinderDriverV2(CinderDriver
):
2199 Driver for openstack cinder-client V2
2201 def __init__(self
, ks_drv
):
2202 super(CinderDriverV2
, self
).__init
__(ks_drv
, 'volumev2', 2)