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'],
1440 "port_security_enabled" : kwargs
['port_security_enabled']}}
1442 ntconn
= self
._get
_neutron
_connection
()
1444 port
= ntconn
.create_port(params
)
1445 except Exception as e
:
1446 logger
.error("OpenstackDriver: Port Create operation failed. Exception: %s" %(str(e
)))
1448 return port
['port']['id']
1450 def _port_get(self
, port_id
):
1452 Returns a dictionary object describing the attributes of the port
1455 port_id (string): UUID of the port
1458 A dictionary object of the port attributes
1460 ntconn
= self
._get
_neutron
_connection
()
1461 port
= ntconn
.list_ports(id=port_id
)['ports']
1463 raise NeutronException
.NotFound("Could not find port_id %s" %(port_id))
1466 def port_get(self
, port_id
):
1468 Returns a dictionary object describing the attributes of the port
1471 port_id (string): UUID of the port
1474 A dictionary object of the port attributes
1476 return self
._port
_get
(port_id
)
1478 def port_delete(self
, port_id
):
1480 Deletes a port identified by port_id
1483 port_id (string) : UUID of the port
1487 assert port_id
== self
._port
_get
(port_id
)['id']
1488 ntconn
= self
._get
_neutron
_connection
()
1490 ntconn
.delete_port(port_id
)
1491 except Exception as e
:
1492 logger
.error("Port Delete operation failed for port_id : %s. Exception: %s" %(port_id
, str(e
)))
1495 def security_group_list(self
):
1497 Returns a list of dictionaries. Each dictionary contains attributes describing the security group
1503 A dictionary of the objects of security group attributes
1505 ntconn
= self
._get
_neutron
_connection
()
1507 group_list
= ntconn
.list_security_groups(tenant_id
=self
.ks_drv
.get_tenant_id())
1508 except Exception as e
:
1509 logger
.error("List Security group operation, Exception: %s" %(str(e
)))
1512 if 'security_groups' in group_list
:
1513 return group_list
['security_groups']
1517 def subnetpool_list(self
, **kwargs
):
1519 Returns a list of dictionaries. Each dictionary contains attributes describing a subnet prefix pool
1525 A dictionary of the objects of subnet prefix pool
1527 ntconn
= self
._get
_neutron
_connection
()
1529 pool_list
= ntconn
.list_subnetpools(**kwargs
)
1530 except Exception as e
:
1531 logger
.error("List SubnetPool operation, Exception: %s" %(str(e
)))
1534 if 'subnetpools' in pool_list
:
1535 return pool_list
['subnetpools']
1539 class NeutronDriverV2(NeutronDriver
):
1541 Driver for openstack neutron neutron-client v2
1543 def __init__(self
, ks_drv
):
1545 Constructor for NeutronDriver
1546 Arguments: KeystoneDriver class object
1548 super(NeutronDriverV2
, self
).__init
__(ks_drv
, 'network', '2.0')
1552 class CeilometerDriver(object):
1554 Driver for openstack ceilometer client
1557 def __init__(self
, ks_drv
, service_name
, version
):
1559 Constructor for CeilometerDriver
1560 Arguments: KeystoneDriver class object
1562 self
.ks_drv
= ks_drv
1563 self
._service
_name
= service_name
1564 self
._version
= version
1569 """The version of the ceilometer client used by the driver"""
1570 return self
._version
1574 """The instance of ceilometer client used by the driver"""
1575 if self
._client
is None or not self
.ks_drv
.is_auth_token_valid():
1576 self
._client
= ceilo_client
.Client(**self
.credentials
)
1581 def auth_token(self
):
1582 """The authorization token for the ceilometer client"""
1584 return self
.ks_drv
.get_auth_token()
1585 except KeystoneExceptions
.EndpointNotFound
as e
:
1586 logger
.error("OpenstackDriver: unable to get authorization token for ceilometer. Exception: %s" %(str(e
)))
1590 def security_mode(self
):
1591 """The security mode for the ceilometer client"""
1593 return self
.ks_drv
.get_security_mode()
1594 except KeystoneExceptions
.EndpointNotFound
as e
:
1595 logger
.error("OpenstackDriver: unable to get security mode for ceilometer. Exception: %s" %(str(e
)))
1600 """The service endpoint for the ceilometer client"""
1602 return self
.ks_drv
.get_service_endpoint(self
._service
_name
, "publicURL")
1603 except KeystoneExceptions
.EndpointNotFound
as e
:
1604 logger
.error("OpenstackDriver: unable to get endpoint for ceilometer. Exception: %s" %(str(e
)))
1608 def credentials(self
):
1609 """A dictionary of credentials for the ceilometer client"""
1611 version
=self
.version
,
1612 endpoint
=self
.endpoint
,
1613 token
=self
.auth_token
,
1614 insecure
=self
.security_mode
,
1619 """A list of the available meters"""
1621 return self
.client
.meters
.list()
1622 except Exception as e
:
1623 logger
.error("OpenstackDriver: List meters operation failed. Exception: %s" %(str(e
)))
1628 """The ceilometer client alarms manager"""
1629 return self
.client
.alarms
1631 def query_samples(self
, vim_instance_id
, counter_name
, limit
=1):
1632 """Returns a list of samples
1635 vim_instance_id - the ID of the VIM that the samples are from
1636 counter_name - the counter that the samples will come from
1637 limit - a limit on the number of samples to return
1645 filter = json
.dumps({
1647 {"=": {"resource": vim_instance_id
}},
1648 {"=": {"counter_name": counter_name
}}
1651 result
= self
.client
.query_samples
.query(filter=filter, limit
=limit
)
1652 return result
[-limit
:]
1654 except Exception as e
:
1660 class CeilometerDriverV2(CeilometerDriver
):
1662 Driver for openstack ceilometer ceilometer-client
1664 def __init__(self
, ks_drv
):
1666 Constructor for CeilometerDriver
1667 Arguments: CeilometerDriver class object
1669 super(CeilometerDriverV2
, self
).__init
__(ks_drv
, 'metering', '2')
1671 class OpenstackDriver(object):
1673 Driver for openstack nova, neutron, glance, keystone, swift, cinder services
1675 def __init__(self
, username
, password
, auth_url
, tenant_name
, mgmt_network
= None, cert_validate
= False, user_domain_name
= None, project_domain_name
= None):
1677 OpenstackDriver Driver constructor
1679 username (string) : Username for project/tenant.
1680 password (string) : Password
1681 auth_url (string) : Keystone Authentication URL.
1682 tenant_name (string) : Openstack project name
1683 mgmt_network(string, optional) : Management network name. Each VM created with this cloud-account will
1684 have a default interface into management network.
1685 cert_validate (boolean, optional) : In case of SSL/TLS connection if certificate validation is required or not.
1688 insecure
= not cert_validate
1689 if auth_url
.find('/v3') != -1:
1690 self
.ks_drv
= KeystoneDriverV3(username
, password
, auth_url
, tenant_name
, insecure
, user_domain_name
, project_domain_name
)
1691 self
.glance_drv
= GlanceDriverV2(self
.ks_drv
)
1692 self
.nova_drv
= NovaDriverV21(self
.ks_drv
)
1693 self
.neutron_drv
= NeutronDriverV2(self
.ks_drv
)
1694 self
.ceilo_drv
= CeilometerDriverV2(self
.ks_drv
)
1695 self
.cinder_drv
= CinderDriverV2(self
.ks_drv
)
1696 elif auth_url
.find('/v2') != -1:
1697 self
.ks_drv
= KeystoneDriverV2(username
, password
, auth_url
, tenant_name
, insecure
)
1698 self
.glance_drv
= GlanceDriverV2(self
.ks_drv
)
1699 self
.nova_drv
= NovaDriverV2(self
.ks_drv
)
1700 self
.neutron_drv
= NeutronDriverV2(self
.ks_drv
)
1701 self
.ceilo_drv
= CeilometerDriverV2(self
.ks_drv
)
1702 self
.cinder_drv
= CinderDriverV2(self
.ks_drv
)
1704 logger
.error("Could not identity the version information for openstack service endpoints. Auth_URL should contain \"/v2\" or \"/v3\" string in it")
1705 raise NotImplementedError("Auth URL is wrong or invalid. Only Keystone v2 & v3 supported")
1707 self
._mgmt
_network
_id
= None
1708 if mgmt_network
!= None:
1709 self
._mgmt
_network
= mgmt_network
1713 ntconn
= self
.neutron_drv
._get
_neutron
_connection
()
1714 networks
= ntconn
.list_networks()
1715 except (KeystoneExceptions
.Unauthorized
, KeystoneExceptions
.AuthorizationFailure
) as e
:
1717 except Exception as e
:
1718 logger
.error("OpenstackDriver: List Network operation failed. Exception: %s" %(str(e
)))
1721 network_list
= [ network
for network
in networks
['networks'] if network
['name'] == mgmt_network
]
1723 if not network_list
:
1724 raise NeutronException
.NotFound("Could not find network %s" %(mgmt_network))
1725 self
._mgmt
_network
_id
= network_list
[0]['id']
1727 def validate_account_creds(self
):
1729 ksconn
= self
.ks_drv
._get
_keystone
_connection
()
1730 except KeystoneExceptions
.AuthorizationFailure
as e
:
1731 logger
.error("OpenstackDriver: Unable to authenticate or validate the existing credentials. Exception: %s" %(str(e
)))
1732 raise ValidationError("Invalid Credentials: "+ str(e
))
1733 except Exception as e
:
1734 logger
.error("OpenstackDriver: Could not connect to Openstack. Exception: %s" %(str(e
)))
1735 raise ValidationError("Connection Error: "+ str(e
))
1737 def get_mgmt_network_id(self
):
1738 return self
._mgmt
_network
_id
1740 def glance_image_create(self
, **kwargs
):
1741 if not 'disk_format' in kwargs
:
1742 kwargs
['disk_format'] = 'qcow2'
1743 if not 'container_format' in kwargs
:
1744 kwargs
['container_format'] = 'bare'
1745 if not 'min_disk' in kwargs
:
1746 kwargs
['min_disk'] = 0
1747 if not 'min_ram' in kwargs
:
1748 kwargs
['min_ram'] = 0
1749 return self
.glance_drv
.image_create(**kwargs
)
1751 def glance_image_upload(self
, image_id
, fd
):
1752 self
.glance_drv
.image_upload(image_id
, fd
)
1754 def glance_image_add_location(self
, image_id
, location
):
1755 self
.glance_drv
.image_add_location(image_id
, location
)
1757 def glance_image_delete(self
, image_id
):
1758 self
.glance_drv
.image_delete(image_id
)
1760 def glance_image_list(self
):
1761 return self
.glance_drv
.image_list()
1763 def glance_image_get(self
, image_id
):
1764 return self
.glance_drv
.image_get(image_id
)
1767 def nova_flavor_list(self
):
1768 return self
.nova_drv
.flavor_list()
1770 def nova_flavor_create(self
, name
, ram
, vcpus
, disk
, epa_specs
):
1771 extra_specs
= epa_specs
if epa_specs
else {}
1772 return self
.nova_drv
.flavor_create(name
,
1776 extra_specs
= extra_specs
)
1778 def nova_flavor_delete(self
, flavor_id
):
1779 self
.nova_drv
.flavor_delete(flavor_id
)
1781 def nova_flavor_get(self
, flavor_id
):
1782 return self
.nova_drv
.flavor_get(flavor_id
)
1784 def nova_server_create(self
, **kwargs
):
1785 def _verify_image(image_id
):
1786 image
= self
.glance_drv
.image_get(image_id
)
1787 if image
['status'] != 'active':
1788 raise GlanceException
.NotFound("Image with image_id: %s not found in active state. Current State: %s" %(image
['id'], image
['status']))
1790 assert kwargs
['flavor_id'] == self
.nova_drv
.flavor_get(kwargs
['flavor_id'])['id']
1792 if kwargs
['block_device_mapping_v2'] is not None:
1793 for block_map
in kwargs
['block_device_mapping_v2']:
1794 if 'uuid' in block_map
:
1795 _verify_image(block_map
['uuid'])
1797 _verify_image(kwargs
['image_id'])
1799 # if 'network_list' in kwargs:
1800 # kwargs['network_list'].append(self._mgmt_network_id)
1802 # kwargs['network_list'] = [self._mgmt_network_id]
1804 if 'security_groups' not in kwargs
:
1805 nvconn
= self
.nova_drv
._get
_nova
_connection
()
1806 sec_groups
= nvconn
.security_groups
.list()
1808 ## Should we add VM in all availability security_groups ???
1809 kwargs
['security_groups'] = [x
.name
for x
in sec_groups
]
1811 kwargs
['security_groups'] = None
1813 return self
.nova_drv
.server_create(**kwargs
)
1815 def nova_server_add_port(self
, server_id
, port_id
):
1816 self
.nova_drv
.server_add_port(server_id
, port_id
)
1818 def nova_server_delete_port(self
, server_id
, port_id
):
1819 self
.nova_drv
.server_delete_port(server_id
, port_id
)
1821 def nova_server_start(self
, server_id
):
1822 self
.nova_drv
.server_start(server_id
)
1824 def nova_server_stop(self
, server_id
):
1825 self
.nova_drv
.server_stop(server_id
)
1827 def nova_server_delete(self
, server_id
):
1828 self
.nova_drv
.server_delete(server_id
)
1830 def nova_server_reboot(self
, server_id
):
1831 self
.nova_drv
.server_reboot(server_id
, reboot_type
='HARD')
1833 def nova_server_rebuild(self
, server_id
, image_id
):
1834 self
.nova_drv
.server_rebuild(server_id
, image_id
)
1836 def nova_floating_ip_list(self
):
1837 return self
.nova_drv
.floating_ip_list()
1839 def nova_floating_ip_create(self
, pool
= None):
1840 return self
.nova_drv
.floating_ip_create(pool
)
1842 def nova_floating_ip_delete(self
, floating_ip
):
1843 self
.nova_drv
.floating_ip_delete(floating_ip
)
1845 def nova_floating_ip_assign(self
, server_id
, floating_ip
, fixed_ip
):
1846 self
.nova_drv
.floating_ip_assign(server_id
, floating_ip
, fixed_ip
)
1848 def nova_floating_ip_release(self
, server_id
, floating_ip
):
1849 self
.nova_drv
.floating_ip_release(server_id
, floating_ip
)
1851 def nova_server_list(self
):
1852 return self
.nova_drv
.server_list()
1854 def nova_server_get(self
, server_id
):
1855 return self
.nova_drv
.server_get(server_id
)
1857 def nova_server_console(self
, server_id
):
1858 return self
.nova_drv
.server_console(server_id
)
1860 def nova_server_group_list(self
):
1861 return self
.nova_drv
.group_list()
1863 def nova_volume_list(self
, server_id
):
1864 return self
.nova_drv
.volume_list(server_id
)
1866 def neutron_network_list(self
):
1867 return self
.neutron_drv
.network_list()
1869 def neutron_network_get(self
, network_id
):
1870 return self
.neutron_drv
.network_get(network_id
)
1872 def neutron_network_create(self
, **kwargs
):
1873 return self
.neutron_drv
.network_create(**kwargs
)
1875 def neutron_network_delete(self
, network_id
):
1876 self
.neutron_drv
.network_delete(network_id
)
1878 def neutron_subnet_list(self
):
1879 return self
.neutron_drv
.subnet_list()
1881 def neutron_subnet_get(self
, subnet_id
):
1882 return self
.neutron_drv
.subnet_get(subnet_id
)
1884 def neutron_subnet_create(self
, **kwargs
):
1885 return self
.neutron_drv
.subnet_create(**kwargs
)
1887 def netruon_subnet_delete(self
, subnet_id
):
1888 self
.neutron_drv
.subnet_delete(subnet_id
)
1890 def neutron_subnetpool_list(self
):
1891 return self
.neutron_drv
.subnetpool_list()
1893 def netruon_subnetpool_by_name(self
, pool_name
):
1894 pool_list
= self
.neutron_drv
.subnetpool_list(**{'name': pool_name
})
1900 def neutron_port_list(self
, **kwargs
):
1901 return self
.neutron_drv
.port_list(**kwargs
)
1903 def neutron_port_get(self
, port_id
):
1904 return self
.neutron_drv
.port_get(port_id
)
1906 def neutron_port_create(self
, **kwargs
):
1907 subnets
= [subnet
for subnet
in self
.neutron_drv
.subnet_list() if subnet
['network_id'] == kwargs
['network_id']]
1908 assert len(subnets
) == 1
1909 kwargs
['subnet_id'] = subnets
[0]['id']
1910 if not 'admin_state_up' in kwargs
:
1911 kwargs
['admin_state_up'] = True
1912 port_id
= self
.neutron_drv
.port_create(**kwargs
)
1914 if 'vm_id' in kwargs
:
1915 self
.nova_server_add_port(kwargs
['vm_id'], port_id
)
1918 def neutron_security_group_list(self
):
1919 return self
.neutron_drv
.security_group_list()
1921 def neutron_security_group_by_name(self
, group_name
):
1922 group_list
= self
.neutron_drv
.security_group_list()
1923 groups
= [group
for group
in group_list
if group
['name'] == group_name
]
1929 def neutron_port_delete(self
, port_id
):
1930 self
.neutron_drv
.port_delete(port_id
)
1932 def ceilo_meter_endpoint(self
):
1933 return self
.ceilo_drv
.endpoint
1935 def ceilo_meter_list(self
):
1936 return self
.ceilo_drv
.meters
1938 def ceilo_nfvi_metrics(self
, vim_id
):
1939 """Returns a dict of NFVI metrics for a given VM
1942 vim_id - the VIM ID of the VM to retrieve the metrics for
1945 A dict of NFVI metrics
1948 def query_latest_sample(counter_name
):
1950 filter = json
.dumps({
1952 {"=": {"resource": vim_id
}},
1953 {"=": {"counter_name": counter_name
}}
1956 orderby
= json
.dumps([{"timestamp": "DESC"}])
1957 result
= self
.ceilo_drv
.client
.query_samples
.query(
1967 except Exception as e
:
1968 logger
.error("Got exception while querying ceilometer, exception details:%s " %str
(e
))
1972 memory_usage
= query_latest_sample("memory.usage")
1973 disk_usage
= query_latest_sample("disk.usage")
1974 cpu_util
= query_latest_sample("cpu_util")
1978 if memory_usage
is not None:
1979 memory_usage
.volume
= 1e6
* memory_usage
.volume
1980 metrics
["memory_usage"] = memory_usage
.to_dict()
1982 if disk_usage
is not None:
1983 metrics
["disk_usage"] = disk_usage
.to_dict()
1985 if cpu_util
is not None:
1986 metrics
["cpu_util"] = cpu_util
.to_dict()
1990 def ceilo_alarm_list(self
):
1991 """Returns a list of ceilometer alarms"""
1992 return self
.ceilo_drv
.client
.alarms
.list()
1994 def ceilo_alarm_create(self
,
2007 """Create a new Alarm
2010 name - the name of the alarm
2011 meter - the name of the meter to measure
2012 statistic - the type of statistic used to trigger the alarm
2013 ('avg', 'min', 'max', 'count', 'sum')
2014 operation - the relational operator that, combined with the
2015 threshold value, determines when the alarm is
2016 triggered ('lt', 'le', 'eq', 'ge', 'gt')
2017 threshold - the value of the statistic that will trigger the
2019 period - the duration (seconds) over which to evaluate the
2021 evaluations - the number of samples of the meter statistic to
2022 collect when evaluating the threshold
2023 severity - a measure of the urgency or importance of the alarm
2024 ('low', 'moderate', 'critical')
2025 repeat - a flag that indicates whether the alarm should be
2026 triggered once (False) or repeatedly while the alarm
2027 condition is true (True)
2028 enabled - a flag that indicates whether the alarm is enabled
2029 (True) or disabled (False)
2030 actions - a dict specifying the URLs for webhooks. The dict can
2031 have up to 3 keys: 'insufficient_data', 'alarm',
2032 'ok'. Each key is associated with a list of URLs to
2033 webhooks that will be invoked when one of the 3
2035 kwargs - an arbitrary dict of keyword arguments that are
2036 passed to the ceilometer client
2039 ok_actions
= actions
.get('ok') if actions
is not None else None
2040 alarm_actions
= actions
.get('alarm') if actions
is not None else None
2041 insufficient_data_actions
= actions
.get('insufficient_data') if actions
is not None else None
2043 return self
.ceilo_drv
.client
.alarms
.create(
2046 statistic
=statistic
,
2047 comparison_operator
=operation
,
2048 threshold
=threshold
,
2050 evaluation_periods
=evaluations
,
2052 repeat_actions
=repeat
,
2054 ok_actions
=ok_actions
,
2055 alarm_actions
=alarm_actions
,
2056 insufficient_data_actions
=insufficient_data_actions
,
2060 def ceilo_alarm_update(self
, alarm_id
, **kwargs
):
2061 """Updates an existing alarm
2064 alarm_id - the identifier of the alarm to update
2065 kwargs - a dict of the alarm attributes to update
2068 return self
.ceilo_drv
.client
.alarms
.update(alarm_id
, **kwargs
)
2070 def ceilo_alarm_delete(self
, alarm_id
):
2071 self
.ceilo_drv
.client
.alarms
.delete(alarm_id
)
2073 def cinder_volume_list(self
):
2074 return self
.cinder_drv
.volume_list()
2076 def cinder_volume_get(self
,vol_id
):
2077 return self
.cinder_drv
.volume_get(vol_id
)
2079 def cinder_volume_set_metadata(self
, volumeid
, metadata
):
2080 return self
.cinder_drv
.volume_set_metadata(volumeid
, metadata
)
2082 def cinder_volume_delete_metadata(self
, volumeid
, metadata
):
2083 return self
.cinder_drv
.volume_delete_metadata(volumeid
, metadata
)
2087 class CinderDriver(object):
2089 Driver for openstack cinder-client
2091 def __init__(self
, ks_drv
, service_name
, version
):
2093 Constructor for CinderDriver
2094 Arguments: KeystoneDriver class object
2096 self
.ks_drv
= ks_drv
2097 self
._service
_name
= service_name
2098 self
._version
= version
2100 def _get_cinder_credentials(self
):
2102 Returns a dictionary of kwargs required to instantiate python-cinderclient class
2107 A dictionary object of arguments
2110 creds
['version'] = self
._version
2111 creds
['username'] = self
.ks_drv
.get_username()
2112 creds
['api_key'] = self
.ks_drv
.get_password()
2113 creds
['auth_url'] = self
.ks_drv
.get_service_endpoint("identity", "publicURL")
2114 creds
['project_id'] = self
.ks_drv
.get_tenant_name()
2115 creds
['insecure'] = self
.ks_drv
.get_security_mode()
2119 def _get_cinder_connection(self
):
2121 Returns a object of class python-cinderclient
2123 if not hasattr(self
, '_cinder_connection'):
2124 self
._cinder
_connection
= cinder_client
.Client(**self
._get
_cinder
_credentials
())
2126 # Reinitialize if auth_token is no longer valid
2127 if not self
.ks_drv
.is_auth_token_valid():
2128 self
._cinder
_connection
= cinder_client
.Client(**self
._get
_cinder
_credentials
())
2129 return self
._cinder
_connection
2131 def volume_list(self
):
2133 Returns list of dictionaries. Each dictionary contains attributes associated with
2138 Returns: List of dictionaries.
2140 cinderconn
= self
._get
_cinder
_connection
()
2143 volume_info
= cinderconn
.volumes
.list()
2144 except Exception as e
:
2145 logger
.error("OpenstackDriver: List volumes operation failed. Exception: %s" %(str(e
)))
2147 volumes
= [ volume
for volume
in volume_info
]
2150 def volume_get(self
, volume_id
):
2156 Returns: List of dictionaries.
2158 cinderconn
= self
._get
_cinder
_connection
()
2160 vol
= cinderconn
.volumes
.get(volume_id
)
2161 except Exception as e
:
2162 logger
.error("OpenstackDriver: Get volume operation failed. Exception: %s" %(str(e
)))
2166 def volume_set_metadata(self
, volume_id
, metadata
):
2168 Set metadata for volume
2169 Metadata is a dictionary of key-value pairs
2173 Returns: List of dictionaries.
2175 cinderconn
= self
._get
_cinder
_connection
()
2177 cinderconn
.volumes
.set_metadata(volume_id
, metadata
)
2178 except Exception as e
:
2179 logger
.error("OpenstackDriver: Set metadata operation failed. Exception: %s" %(str(e
)))
2182 def volume_delete_metadata(self
, volume_id
, metadata
):
2184 Delete metadata for volume
2185 Metadata is a dictionary of key-value pairs
2189 Returns: List of dictionaries.
2191 cinderconn
= self
._get
_cinder
_connection
()
2193 cinderconn
.volumes
.delete_metadata(volume_id
, metadata
)
2194 except Exception as e
:
2195 logger
.error("OpenstackDriver: Delete metadata operation failed. Exception: %s" %(str(e
)))
2198 class CinderDriverV2(CinderDriver
):
2200 Driver for openstack cinder-client V2
2202 def __init__(self
, ks_drv
):
2203 super(CinderDriverV2
, self
).__init
__(ks_drv
, 'volumev2', 2)