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
31 import novaclient
.exceptions
as NovaException
32 import keystoneclient
.exceptions
as KeystoneExceptions
33 import neutronclient
.common
.exceptions
as NeutronException
34 import glanceclient
.exc
as GlanceException
36 logger
= logging
.getLogger('rwcal.openstack.drv')
37 logger
.setLevel(logging
.DEBUG
)
39 class ValidationError(Exception):
43 class KeystoneDriver(object):
45 Driver base-class for keystoneclient APIs
47 def __init__(self
, ksclient
):
49 Constructor for KeystoneDriver base class
53 self
.ksclient
= ksclient
55 def get_username(self
):
57 Returns the username associated with keystoneclient connection
61 def get_password(self
):
63 Returns the password associated with keystoneclient connection
67 def get_tenant_name(self
):
69 Returns the tenant name associated with keystoneclient connection
71 return self
._tenant
_name
73 def get_user_domain_name(self
):
75 Returns None as this field does not exist for v2.
79 def get_project_domain_name(self
):
81 Returns None as this field does not exist for v2.
85 def _get_keystone_connection(self
):
87 Returns object of class python-keystoneclient class
89 if not hasattr(self
, '_keystone_connection'):
90 self
._keystone
_connection
= self
.ksclient(**self
._get
_keystone
_credentials
())
91 return self
._keystone
_connection
93 def is_auth_token_valid(self
, token_expiry
, time_fmt
):
95 Performs validity on auth_token
97 token_expiry (string): Expiry time for token
98 time_fmt (string) : Format for expiry string in auth_ref
101 True/False (Boolean): (auth_token is valid or auth_token is invalid)
105 import dateutil
.parser
107 now
= datetime
.datetime
.timetuple(datetime
.datetime
.utcnow())
108 expires_at
= dateutil
.parser
.parse(token_expiry
)
109 t_now
= time
.mktime(now
)
110 t_expiry
= time
.mktime(expires_at
.timetuple())
112 if (t_expiry
<= t_now
) or ((t_expiry
- t_now
) < 300 ):
113 ### Token has expired or about to expire (5 minute)
114 delattr(self
, '_keystone_connection')
118 except Exception as e
:
119 logger
.error("Received except %s during auth_token validity check" %str
(e
))
120 logger
.info("Can not validate the auth_token. Assuming invalid")
124 def get_service_endpoint(self
, service_type
, endpoint_type
):
126 Returns requested type of endpoint for requested service type
128 service_type (string): Service Type (e.g. computev3, image, network)
129 endpoint_type(string): Endpoint Type (e.g. publicURL,adminURL,internalURL)
131 service_endpoint(string): Service endpoint string
133 endpoint_kwargs
= {'service_type' : service_type
,
134 'endpoint_type' : endpoint_type
}
136 ksconn
= self
._get
_keystone
_connection
()
137 service_endpoint
= ksconn
.service_catalog
.url_for(**endpoint_kwargs
)
138 except (KeystoneExceptions
.Unauthorized
, KeystoneExceptions
.AuthorizationFailure
) as e
:
140 except Exception as e
:
141 logger
.error("OpenstackDriver: Service Catalog discovery operation failed for service_type: %s, endpoint_type: %s. Exception: %s" %(service_type
, endpoint_type
, str(e
)))
143 return service_endpoint
146 def get_raw_token(self
):
148 Returns a valid raw_auth_token string
150 Returns (string): raw_auth_token string
152 ksconn
= self
._get
_keystone
_connection
()
154 raw_token
= ksconn
.get_raw_token_from_identity_service(auth_url
= self
._auth
_url
,
155 token
= self
.get_auth_token())
156 except KeystoneExceptions
.AuthorizationFailure
as e
:
157 logger
.error("OpenstackDriver: get_raw_token_from_identity_service Failure. Exception: %s" %(str(e
)))
160 except Exception as e
:
161 logger
.error("OpenstackDriver: Could not retrieve raw_token. Exception: %s" %(str(e
)))
165 def get_tenant_id(self
):
167 Returns tenant_id for the project/tenant. Tenant name is provided during
170 Returns (string): Tenant ID
172 ksconn
= self
._get
_keystone
_connection
()
173 return ksconn
.tenant_id
175 def get_security_mode(self
):
177 Returns certificate_validation policy in case of SSL/TLS connection.
178 This policy is provided during class instantiation
181 The boolean returned are designed to match the python-client class instantiation ("insecure") value.
182 for nova/neutron/glance/keystone clients
184 True: No certificate validation required -- Insecure mode
185 False: Certificate validation required -- Secure mode
187 return self
._insecure
189 def tenant_list(self
):
191 Returns list of tenants
195 def tenant_create(self
, name
):
201 def tenant_delete(self
, tenant_id
):
203 Deletes a tenant identified by tenant_id
207 def roles_list(self
):
210 def roles_create(self
):
213 def roles_delete(self
):
216 class KeystoneDriverV2(KeystoneDriver
):
218 Driver class for keystoneclient V2 APIs
220 def __init__(self
, username
, password
, auth_url
,tenant_name
, insecure
):
222 Constructor for KeystoneDriverV3 class
224 username (string) : Username
225 password (string) : Password
226 auth_url (string) : Authentication URL
227 tenant_name(string): Tenant Name
231 self
._username
= username
232 self
._password
= password
233 self
._auth
_url
= auth_url
234 self
._tenant
_name
= tenant_name
235 self
._insecure
= insecure
236 super(KeystoneDriverV2
, self
).__init
__(ksclientv2
.Client
)
238 def _get_keystone_credentials(self
):
240 Returns the dictionary of kwargs required to instantiate python-keystoneclient class
243 #creds['user_domain'] = self._domain_name
244 creds
['username'] = self
._username
245 creds
['password'] = self
._password
246 creds
['auth_url'] = self
._auth
_url
247 creds
['tenant_name'] = self
._tenant
_name
248 creds
['insecure'] = self
.get_security_mode()
251 def get_auth_token(self
):
253 Returns a valid auth_token
255 Returns (string): auth_token string
257 ksconn
= self
._get
_keystone
_connection
()
258 return ksconn
.auth_token
260 def is_auth_token_valid(self
):
262 Performs validity on auth_token
266 True/False (Boolean): (auth_token is valid or auth_token is invalid)
268 ksconn
= self
._get
_keystone
_connection
()
269 result
= super(KeystoneDriverV2
, self
).is_auth_token_valid(ksconn
.auth_ref
['token']['expires'],
270 "%Y-%m-%dT%H:%M:%SZ")
274 class KeystoneDriverV3(KeystoneDriver
):
276 Driver class for keystoneclient V3 APIs
278 def __init__(self
, username
, password
, auth_url
,tenant_name
, insecure
, user_domain_name
= None, project_domain_name
= None):
280 Constructor for KeystoneDriverV3 class
282 username (string) : Username
283 password (string) : Password
284 auth_url (string) : Authentication URL
285 tenant_name(string): Tenant Name
289 self
._username
= username
290 self
._password
= password
291 self
._auth
_url
= auth_url
292 self
._tenant
_name
= tenant_name
293 self
._insecure
= insecure
294 self
._user
_domain
_name
= user_domain_name
295 self
._project
_domain
_name
= project_domain_name
296 super(KeystoneDriverV3
, self
).__init
__(ksclientv3
.Client
)
298 def _get_keystone_credentials(self
):
300 Returns the dictionary of kwargs required to instantiate python-keystoneclient class
303 creds
['username'] = self
._username
304 creds
['password'] = self
._password
305 creds
['auth_url'] = self
._auth
_url
306 creds
['project_name'] = self
._tenant
_name
307 creds
['insecure'] = self
._insecure
308 creds
['user_domain_name'] = self
._user
_domain
_name
309 creds
['project_domain_name'] = self
._project
_domain
_name
312 def get_user_domain_name(self
):
314 Returns the domain_name of the associated OpenStack user account
316 return self
._user
_domain
_name
;
318 def get_project_domain_name(self
):
320 Returns the domain_name of the associated OpenStack project
322 return self
._project
_domain
_name
;
324 def get_auth_token(self
):
326 Returns a valid auth_token
328 Returns (string): auth_token string
330 ksconn
= self
._get
_keystone
_connection
()
331 return ksconn
.auth_ref
['auth_token']
333 def is_auth_token_valid(self
):
335 Performs validity on auth_token
339 True/False (Boolean): (auth_token is valid or auth_token is invalid)
341 ksconn
= self
._get
_keystone
_connection
()
342 result
= super(KeystoneDriverV3
, self
).is_auth_token_valid(ksconn
.auth_ref
['expires_at'],
343 "%Y-%m-%dT%H:%M:%S.%fZ")
346 class NovaDriver(object):
348 Driver for openstack nova_client
350 def __init__(self
, ks_drv
, service_name
, version
):
352 Constructor for NovaDriver
353 Arguments: KeystoneDriver class object
356 self
._service
_name
= service_name
357 self
._version
= version
359 def _get_nova_credentials(self
):
361 Returns a dictionary of kwargs required to instantiate python-novaclient class
364 creds
['version'] = self
._version
365 creds
['bypass_url'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, "publicURL")
366 creds
['username'] = self
.ks_drv
.get_username()
367 creds
['project_id'] = self
.ks_drv
.get_tenant_name()
368 creds
['auth_token'] = self
.ks_drv
.get_auth_token()
369 creds
['insecure'] = self
.ks_drv
.get_security_mode()
370 creds
['user_domain_name'] = self
.ks_drv
.get_user_domain_name()
371 creds
['project_domain_name'] = self
.ks_drv
.get_project_domain_name()
375 def _get_nova_connection(self
):
377 Returns an object of class python-novaclient
379 if not hasattr(self
, '_nova_connection'):
380 self
._nova
_connection
= nova_client
.Client(**self
._get
_nova
_credentials
())
382 # Reinitialize if auth_token is no longer valid
383 if not self
.ks_drv
.is_auth_token_valid():
384 self
._nova
_connection
= nova_client
.Client(**self
._get
_nova
_credentials
())
385 return self
._nova
_connection
387 def _flavor_get(self
, flavor_id
):
389 Get flavor by flavor_id
391 flavor_id(string): UUID of flavor_id
394 dictionary of flavor parameters
396 nvconn
= self
._get
_nova
_connection
()
398 flavor
= nvconn
.flavors
.get(flavor_id
)
399 except Exception as e
:
400 logger
.info("OpenstackDriver: Did not find flavor with flavor_id : %s. Exception: %s"%(flavor_id
, str(e
)))
404 extra_specs
= flavor
.get_keys()
405 except Exception as e
:
406 logger
.info("OpenstackDriver: Could not get the EPA attributes for flavor with flavor_id : %s. Exception: %s"%(flavor_id
, str(e
)))
409 response
= flavor
.to_dict()
410 assert 'extra_specs' not in response
, "Key extra_specs present as flavor attribute"
411 response
['extra_specs'] = extra_specs
414 def flavor_get(self
, flavor_id
):
416 Get flavor by flavor_id
418 flavor_id(string): UUID of flavor_id
421 dictionary of flavor parameters
423 return self
._flavor
_get
(flavor_id
)
425 def flavor_list(self
):
427 Returns list of all flavors (dictionary per flavor)
432 A list of dictionaries. Each dictionary contains attributes for a single flavor instance
436 nvconn
= self
._get
_nova
_connection
()
438 flavors
= nvconn
.flavors
.list()
439 except Exception as e
:
440 logger
.error("OpenstackDriver: List Flavor operation failed. Exception: %s"%(str(e
)))
443 flavor_info
= [ self
.flavor_get(flv
.id) for flv
in flavors
]
446 def flavor_create(self
, name
, ram
, vcpu
, disk
, extra_specs
):
451 name (string): Name of the new flavor
452 ram (int) : Memory in MB
453 vcpus (int) : Number of VCPUs
454 disk (int) : Secondary storage size in GB
455 extra_specs (dictionary): EPA attributes dictionary
458 flavor_id (string): UUID of flavor created
460 nvconn
= self
._get
_nova
_connection
()
462 flavor
= nvconn
.flavors
.create(name
= name
,
471 except Exception as e
:
472 logger
.error("OpenstackDriver: Create Flavor operation failed. Exception: %s"%(str(e
)))
477 flavor
.set_keys(extra_specs
)
478 except Exception as e
:
479 logger
.error("OpenstackDriver: Set Key operation failed for flavor: %s. Exception: %s" %(flavor
.id, str(e
)))
483 def flavor_delete(self
, flavor_id
):
485 Deletes a flavor identified by flavor_id
488 flavor_id (string): UUID of flavor to be deleted
492 assert flavor_id
== self
._flavor
_get
(flavor_id
)['id']
493 nvconn
= self
._get
_nova
_connection
()
495 nvconn
.flavors
.delete(flavor_id
)
496 except Exception as e
:
497 logger
.error("OpenstackDriver: Delete flavor operation failed for flavor: %s. Exception: %s" %(flavor_id
, str(e
)))
501 def server_list(self
):
503 Returns a list of available VMs for the project
508 A list of dictionaries. Each dictionary contains attributes associated
513 nvconn
= self
._get
_nova
_connection
()
515 servers
= nvconn
.servers
.list()
516 except Exception as e
:
517 logger
.error("OpenstackDriver: List Server operation failed. Exception: %s" %(str(e
)))
519 server_info
= [ server
.to_dict() for server
in servers
]
522 def _nova_server_get(self
, server_id
):
524 Returns a dictionary of attributes associated with VM identified by service_id
527 server_id (string): UUID of the VM/server for which information is requested
530 A dictionary object with attributes associated with VM identified by server_id
532 nvconn
= self
._get
_nova
_connection
()
534 server
= nvconn
.servers
.get(server
= server_id
)
535 except Exception as e
:
536 logger
.info("OpenstackDriver: Get Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
539 return server
.to_dict()
541 def server_get(self
, server_id
):
543 Returns a dictionary of attributes associated with VM identified by service_id
546 server_id (string): UUID of the VM/server for which information is requested
549 A dictionary object with attributes associated with VM identified by server_id
551 return self
._nova
_server
_get
(server_id
)
553 def server_create(self
, **kwargs
):
555 Creates a new VM/server instance
558 A dictionary of following key-value pairs
560 server_name(string) : Name of the VM/Server
561 flavor_id (string) : UUID of the flavor to be used for VM
562 image_id (string) : UUID of the image to be used VM/Server instance,
563 This could be None if volumes (with images) are being used
564 network_list(List) : A List of network_ids. A port will be created in these networks
565 port_list (List) : A List of port-ids. These ports will be added to VM.
566 metadata (dict) : A dictionary of arbitrary key-value pairs associated with VM/server
567 userdata (string) : A script which shall be executed during first boot of the VM
568 availability_zone (string) : A name of the availability zone where instance should be launched
569 scheduler_hints (string) : Openstack scheduler_hints to be passed to nova scheduler
572 server_id (string): UUID of the VM/server created
576 if 'network_list' in kwargs
:
577 for network_id
in kwargs
['network_list']:
578 nics
.append({'net-id': network_id
})
580 if 'port_list' in kwargs
:
581 for port_id
in kwargs
['port_list']:
582 nics
.append({'port-id': port_id
})
584 nvconn
= self
._get
_nova
_connection
()
588 server
= nvconn
.servers
.create(kwargs
['name'],
591 meta
= kwargs
['metadata'],
593 reservation_id
= None,
596 userdata
= kwargs
['userdata'],
597 security_groups
= kwargs
['security_groups'],
598 availability_zone
= kwargs
['availability_zone'],
599 block_device_mapping_v2
= kwargs
['block_device_mapping_v2'],
601 scheduler_hints
= kwargs
['scheduler_hints'],
603 except Exception as e
:
604 logger
.info("OpenstackDriver: Create Server operation failed. Exception: %s" %(str(e
)))
606 return server
.to_dict()['id']
608 def server_delete(self
, server_id
):
610 Deletes a server identified by server_id
613 server_id (string): UUID of the server to be deleted
617 nvconn
= self
._get
_nova
_connection
()
619 nvconn
.servers
.delete(server_id
)
620 except Exception as e
:
621 logger
.error("OpenstackDriver: Delete server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
624 def server_start(self
, server_id
):
626 Starts a server identified by server_id
629 server_id (string): UUID of the server to be started
633 nvconn
= self
._get
_nova
_connection
()
635 nvconn
.servers
.start(server_id
)
636 except Exception as e
:
637 logger
.error("OpenstackDriver: Start Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
640 def server_stop(self
, server_id
):
643 server_id (string): UUID of the server to be stopped
647 nvconn
= self
._get
_nova
_connection
()
649 nvconn
.servers
.stop(server_id
)
650 except Exception as e
:
651 logger
.error("OpenstackDriver: Stop Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
654 def server_pause(self
, server_id
):
657 server_id (string): UUID of the server to be paused
661 nvconn
= self
._get
_nova
_connection
()
663 nvconn
.servers
.pause(server_id
)
664 except Exception as e
:
665 logger
.error("OpenstackDriver: Pause Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
668 def server_unpause(self
, server_id
):
671 server_id (string): UUID of the server to be unpaused
675 nvconn
= self
._get
_nova
_connection
()
677 nvconn
.servers
.unpause(server_id
)
678 except Exception as e
:
679 logger
.error("OpenstackDriver: Resume Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
683 def server_suspend(self
, server_id
):
686 server_id (string): UUID of the server to be suspended
690 nvconn
= self
._get
_nova
_connection
()
692 nvconn
.servers
.suspend(server_id
)
693 except Exception as e
:
694 logger
.error("OpenstackDriver: Suspend Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
697 def server_resume(self
, server_id
):
700 server_id (string): UUID of the server to be resumed
704 nvconn
= self
._get
_nova
_connection
()
706 nvconn
.servers
.resume(server_id
)
707 except Exception as e
:
708 logger
.error("OpenstackDriver: Resume Server operation failed for server_id : %s. Exception: %s" %(server_id
, str(e
)))
711 def server_reboot(self
, server_id
, reboot_type
):
714 server_id (string) : UUID of the server to be rebooted
720 nvconn
= self
._get
_nova
_connection
()
722 nvconn
.servers
.reboot(server_id
, reboot_type
)
723 except Exception as e
:
724 logger
.error("OpenstackDriver: Reboot Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
727 def server_console(self
, server_id
, console_type
= 'novnc'):
730 server_id (string) : UUID of the server to be rebooted
731 console_type(string):
735 A dictionary object response for console information
737 nvconn
= self
._get
_nova
_connection
()
739 console_info
= nvconn
.servers
.get_vnc_console(server_id
, console_type
)
740 except Exception as e
:
741 logger
.error("OpenstackDriver: Server Get-Console operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
745 def server_rebuild(self
, server_id
, image_id
):
748 server_id (string) : UUID of the server to be rebooted
749 image_id (string) : UUID of the image to use
753 nvconn
= self
._get
_nova
_connection
()
755 nvconn
.servers
.rebuild(server_id
, image_id
)
756 except Exception as e
:
757 logger
.error("OpenstackDriver: Rebuild Server operation failed for server_id: %s. Exception: %s" %(server_id
, str(e
)))
761 def server_add_port(self
, server_id
, port_id
):
764 server_id (string): UUID of the server
765 port_id (string): UUID of the port to be attached
769 nvconn
= self
._get
_nova
_connection
()
771 nvconn
.servers
.interface_attach(server_id
,
775 except Exception as e
:
776 logger
.error("OpenstackDriver: Server Port Add operation failed for server_id : %s, port_id : %s. Exception: %s" %(server_id
, port_id
, str(e
)))
779 def server_delete_port(self
, server_id
, port_id
):
782 server_id (string): UUID of the server
783 port_id (string): UUID of the port to be deleted
787 nvconn
= self
._get
_nova
_connection
()
789 nvconn
.servers
.interface_detach(server_id
, port_id
)
790 except Exception as e
:
791 logger
.error("OpenstackDriver: Server Port Delete operation failed for server_id : %s, port_id : %s. Exception: %s" %(server_id
, port_id
, str(e
)))
794 def floating_ip_list(self
):
799 List of objects of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
801 nvconn
= self
._get
_nova
_connection
()
803 ip_list
= nvconn
.floating_ips
.list()
804 except Exception as e
:
805 logger
.error("OpenstackDriver: Floating IP List operation failed. Exception: %s" %str
(e
))
810 def floating_ip_create(self
, pool
):
813 pool (string): Name of the pool (optional)
815 An object of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
817 nvconn
= self
._get
_nova
_connection
()
819 floating_ip
= nvconn
.floating_ips
.create(pool
)
820 except Exception as e
:
821 logger
.error("OpenstackDriver: Floating IP Create operation failed. Exception: %s" %str
(e
))
826 def floating_ip_delete(self
, floating_ip
):
829 floating_ip: An object of floating IP nova class (novaclient.v2.floating_ips.FloatingIP)
833 nvconn
= self
._get
_nova
_connection
()
835 floating_ip
= nvconn
.floating_ips
.delete(floating_ip
)
836 except Exception as e
:
837 logger
.error("OpenstackDriver: Floating IP Delete operation failed. Exception: %s" %str
(e
))
840 def floating_ip_assign(self
, server_id
, floating_ip
, fixed_ip
):
843 server_id (string) : UUID of the server
844 floating_ip (string): IP address string for floating-ip
845 fixed_ip (string) : IP address string for the fixed-ip with which floating ip will be associated
849 nvconn
= self
._get
_nova
_connection
()
851 nvconn
.servers
.add_floating_ip(server_id
, floating_ip
, fixed_ip
)
852 except Exception as e
:
853 logger
.error("OpenstackDriver: Assign Floating IP operation failed. Exception: %s" %str
(e
))
856 def floating_ip_release(self
, server_id
, floating_ip
):
859 server_id (string) : UUID of the server
860 floating_ip (string): IP address string for floating-ip
864 nvconn
= self
._get
_nova
_connection
()
866 nvconn
.servers
.remove_floating_ip(server_id
, floating_ip
)
867 except Exception as e
:
868 logger
.error("OpenstackDriver: Release Floating IP operation failed. Exception: %s" %str
(e
))
871 def volume_list(self
, server_id
):
873 List of volumes attached to the server
878 List of dictionary objects where dictionary is representation of class (novaclient.v2.volumes.Volume)
880 nvconn
= self
._get
_nova
_connection
()
882 volumes
= nvconn
.volumes
.get_server_volumes(server_id
=server_id
)
883 except Exception as e
:
884 logger
.error("OpenstackDriver: Get volume information failed. Exception: %s" %str
(e
))
887 volume_info
= [v
.to_dict() for v
in volumes
]
891 def group_list(self
):
893 List of Server Affinity and Anti-Affinity Groups
898 List of dictionary objects where dictionary is representation of class (novaclient.v2.server_groups.ServerGroup)
900 nvconn
= self
._get
_nova
_connection
()
902 group_list
= nvconn
.server_groups
.list()
903 except Exception as e
:
904 logger
.error("OpenstackDriver: Server Group List operation failed. Exception: %s" %str
(e
))
907 group_info
= [ group
.to_dict() for group
in group_list
]
912 class NovaDriverV2(NovaDriver
):
914 Driver class for novaclient V2 APIs
916 def __init__(self
, ks_drv
):
918 Constructor for NovaDriver
919 Arguments: KeystoneDriver class object
921 super(NovaDriverV2
, self
).__init
__(ks_drv
, 'compute', '2.0')
923 class NovaDriverV21(NovaDriver
):
925 Driver class for novaclient V2 APIs
927 def __init__(self
, ks_drv
):
929 Constructor for NovaDriver
930 Arguments: KeystoneDriver class object
932 super(NovaDriverV21
, self
).__init
__(ks_drv
, 'compute', '2.1')
934 class GlanceDriver(object):
936 Driver for openstack glance-client
938 def __init__(self
, ks_drv
, service_name
, version
):
940 Constructor for GlanceDriver
941 Arguments: KeystoneDriver class object
944 self
._service
_name
= service_name
945 self
._version
= version
947 def _get_glance_credentials(self
):
949 Returns a dictionary of kwargs required to instantiate python-glanceclient class
954 A dictionary object of arguments
957 creds
['version'] = self
._version
958 creds
['endpoint'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, 'publicURL')
959 creds
['token'] = self
.ks_drv
.get_auth_token()
960 creds
['insecure'] = self
.ks_drv
.get_security_mode()
963 def _get_glance_connection(self
):
965 Returns a object of class python-glanceclient
967 if not hasattr(self
, '_glance_connection'):
968 self
._glance
_connection
= glclient
.Client(**self
._get
_glance
_credentials
())
970 # Reinitialize if auth_token is no longer valid
971 if not self
.ks_drv
.is_auth_token_valid():
972 self
._glance
_connection
= glclient
.Client(**self
._get
_glance
_credentials
())
973 return self
._glance
_connection
975 def image_list(self
):
977 Returns list of dictionaries. Each dictionary contains attributes associated with
982 Returns: List of dictionaries.
984 glconn
= self
._get
_glance
_connection
()
987 image_info
= glconn
.images
.list()
988 except Exception as e
:
989 logger
.error("OpenstackDriver: List Image operation failed. Exception: %s" %(str(e
)))
991 images
= [ img
for img
in image_info
]
994 def image_create(self
, **kwargs
):
998 A dictionary of kwargs with following keys
1000 'name'(string) : Name of the image
1001 'location'(string) : URL (http://....) where image is located
1002 'disk_format'(string) : Disk format
1003 Possible values are 'ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso'
1004 'container_format'(string): Container format
1005 Possible values are 'ami', 'ari', 'aki', 'bare', 'ovf'
1006 'tags' : A list of user tags
1007 'checksum' : The image md5 checksum
1010 image_id (string) : UUID of the image
1013 glconn
= self
._get
_glance
_connection
()
1015 image
= glconn
.images
.create(**kwargs
)
1016 except Exception as e
:
1017 logger
.error("OpenstackDriver: Create Image operation failed. Exception: %s" %(str(e
)))
1022 def image_upload(self
, image_id
, fd
):
1027 image_id: UUID of the image
1028 fd : File descriptor for the image file
1031 glconn
= self
._get
_glance
_connection
()
1033 glconn
.images
.upload(image_id
, fd
)
1034 except Exception as e
:
1035 logger
.error("OpenstackDriver: Image upload operation failed. Exception: %s" %(str(e
)))
1038 def image_add_location(self
, image_id
, location
, metadata
):
1040 Add image URL location
1043 image_id : UUID of the image
1044 location : http URL for the image
1048 glconn
= self
._get
_glance
_connection
()
1050 image
= glconn
.images
.add_location(image_id
, location
, metadata
)
1051 except Exception as e
:
1052 logger
.error("OpenstackDriver: Image location add operation failed. Exception: %s" %(str(e
)))
1055 def image_update(self
):
1058 def image_delete(self
, image_id
):
1063 image_id: UUID of the image
1068 assert image_id
== self
._image
_get
(image_id
)['id']
1069 glconn
= self
._get
_glance
_connection
()
1071 glconn
.images
.delete(image_id
)
1072 except Exception as e
:
1073 logger
.error("OpenstackDriver: Delete Image operation failed for image_id : %s. Exception: %s" %(image_id
, str(e
)))
1077 def _image_get(self
, image_id
):
1079 Returns a dictionary object of VM image attributes
1082 image_id (string): UUID of the image
1085 A dictionary of the image attributes
1087 glconn
= self
._get
_glance
_connection
()
1089 image
= glconn
.images
.get(image_id
)
1090 except GlanceException
.HTTPBadRequest
:
1091 # RIFT-14241: The get image request occasionally returns the below message. Retry in case of bad request exception.
1092 # Error code 400.: Message: Bad request syntax ('0').: Error code explanation: 400 = Bad request syntax or unsupported method. (HTTP 400)
1093 logger
.warning("OpenstackDriver: Got bad request response during get_image request. Retrying.")
1094 image
= glconn
.images
.get(image_id
)
1095 except Exception as e
:
1096 logger
.error("OpenstackDriver: Get Image operation failed for image_id : %s. Exception: %s" %(image_id
, str(e
)))
1101 def image_get(self
, image_id
):
1103 Returns a dictionary object of VM image attributes
1106 image_id (string): UUID of the image
1109 A dictionary of the image attributes
1111 return self
._image
_get
(image_id
)
1113 class GlanceDriverV2(GlanceDriver
):
1115 Driver for openstack glance-client V2
1117 def __init__(self
, ks_drv
):
1118 super(GlanceDriverV2
, self
).__init
__(ks_drv
, 'image', 2)
1120 class NeutronDriver(object):
1122 Driver for openstack neutron neutron-client
1124 def __init__(self
, ks_drv
, service_name
, version
):
1126 Constructor for NeutronDriver
1127 Arguments: KeystoneDriver class object
1129 self
.ks_drv
= ks_drv
1130 self
._service
_name
= service_name
1131 self
._version
= version
1133 def _get_neutron_credentials(self
):
1135 Returns a dictionary of kwargs required to instantiate python-neutronclient class
1138 Dictionary of kwargs
1141 creds
['api_version'] = self
._version
1142 creds
['endpoint_url'] = self
.ks_drv
.get_service_endpoint(self
._service
_name
, 'publicURL')
1143 creds
['token'] = self
.ks_drv
.get_auth_token()
1144 creds
['tenant_name'] = self
.ks_drv
.get_tenant_name()
1145 creds
['insecure'] = self
.ks_drv
.get_security_mode()
1148 def _get_neutron_connection(self
):
1150 Returns an object of class python-neutronclient
1152 if not hasattr(self
, '_neutron_connection'):
1153 self
._neutron
_connection
= ntclient
.Client(**self
._get
_neutron
_credentials
())
1155 # Reinitialize if auth_token is no longer valid
1156 if not self
.ks_drv
.is_auth_token_valid():
1157 self
._neutron
_connection
= ntclient
.Client(**self
._get
_neutron
_credentials
())
1158 return self
._neutron
_connection
1160 def network_list(self
):
1162 Returns list of dictionaries. Each dictionary contains the attributes for a network
1168 A list of dictionaries
1171 ntconn
= self
._get
_neutron
_connection
()
1173 networks
= ntconn
.list_networks()
1174 except Exception as e
:
1175 logger
.error("OpenstackDriver: List Network operation failed. Exception: %s" %(str(e
)))
1177 return networks
['networks']
1179 def network_create(self
, **kwargs
):
1181 Creates a new network for the project
1184 A dictionary with following key-values
1186 name (string) : Name of the network
1187 admin_state_up(Boolean) : True/False (Defaults: True)
1188 external_router(Boolean) : Connectivity with external router. True/False (Defaults: False)
1189 shared(Boolean) : Shared among tenants. True/False (Defaults: False)
1190 physical_network(string) : The physical network where this network object is implemented (optional).
1191 network_type : The type of physical network that maps to this network resource (optional).
1192 Possible values are: 'flat', 'vlan', 'vxlan', 'gre'
1193 segmentation_id : An isolated segment on the physical network. The network_type attribute
1194 defines the segmentation model. For example, if the network_type value
1195 is vlan, this ID is a vlan identifier. If the network_type value is gre,
1196 this ID is a gre key.
1199 params
= {'network':
1200 {'name' : kwargs
['name'],
1201 'admin_state_up' : kwargs
['admin_state_up'],
1202 'tenant_id' : self
.ks_drv
.get_tenant_id(),
1203 'shared' : kwargs
['shared'],
1204 #'port_security_enabled': port_security_enabled,
1205 'router:external' : kwargs
['external_router']}}
1207 if 'physical_network' in kwargs
:
1208 params
['network']['provider:physical_network'] = kwargs
['physical_network']
1209 if 'network_type' in kwargs
:
1210 params
['network']['provider:network_type'] = kwargs
['network_type']
1211 if 'segmentation_id' in kwargs
:
1212 params
['network']['provider:segmentation_id'] = kwargs
['segmentation_id']
1214 ntconn
= self
._get
_neutron
_connection
()
1216 logger
.debug("Calling neutron create_network() with params: %s", str(params
))
1217 net
= ntconn
.create_network(params
)
1218 except Exception as e
:
1219 logger
.error("OpenstackDriver: Create Network operation failed. Exception: %s" %(str(e
)))
1221 logger
.debug("Got create_network response from neutron connection: %s", str(net
))
1222 network_id
= net
['network']['id']
1224 raise Exception("Empty network id returned from create_network. (params: %s)" % str(params
))
1228 def network_delete(self
, network_id
):
1230 Deletes a network identified by network_id
1233 network_id (string): UUID of the network
1237 assert network_id
== self
._network
_get
(network_id
)['id']
1238 ntconn
= self
._get
_neutron
_connection
()
1240 ntconn
.delete_network(network_id
)
1241 except Exception as e
:
1242 logger
.error("OpenstackDriver: Delete Network operation failed. Exception: %s" %(str(e
)))
1245 def _network_get(self
, network_id
):
1247 Returns a dictionary object describing the attributes of the network
1250 network_id (string): UUID of the network
1253 A dictionary object of the network attributes
1255 ntconn
= self
._get
_neutron
_connection
()
1256 network
= ntconn
.list_networks(id = network_id
)['networks']
1258 raise NeutronException
.NotFound("Network with id %s not found"%(network_id))
1262 def network_get(self
, network_id
):
1264 Returns a dictionary object describing the attributes of the network
1267 network_id (string): UUID of the network
1270 A dictionary object of the network attributes
1272 return self
._network
_get
(network_id
)
1274 def subnet_create(self
, **kwargs
):
1276 Creates a subnet on the network
1279 A dictionary with following key value pairs
1281 network_id(string) : UUID of the network where subnet needs to be created
1282 subnet_cidr(string) : IPv4 address prefix (e.g. '1.1.1.0/24') for the subnet
1283 ip_version (integer): 4 for IPv4 and 6 for IPv6
1288 subnet_id (string): UUID of the created subnet
1291 params
['network_id'] = kwargs
['network_id']
1292 params
['ip_version'] = kwargs
['ip_version']
1294 # if params['ip_version'] == 6:
1295 # assert 0, "IPv6 is not supported"
1297 if 'subnetpool_id' in kwargs
:
1298 params
['subnetpool_id'] = kwargs
['subnetpool_id']
1300 params
['cidr'] = kwargs
['cidr']
1302 if 'gateway_ip' in kwargs
:
1303 params
['gateway_ip'] = kwargs
['gateway_ip']
1305 params
['gateway_ip'] = None
1307 if 'dhcp_params' in kwargs
:
1308 params
['enable_dhcp'] = kwargs
['dhcp_params']['enable_dhcp']
1309 if 'start_address' in kwargs
['dhcp_params'] and 'count' in kwargs
['dhcp_params']:
1310 end_address
= (ipaddress
.IPv4Address(kwargs
['dhcp_params']['start_address']) + kwargs
['dhcp_params']['count']).compressed
1311 params
['allocation_pools'] = [ {'start': kwargs
['dhcp_params']['start_address'] ,
1312 'end' : end_address
} ]
1314 if 'dns_server' in kwargs
:
1315 params
['dns_nameservers'] = []
1316 for server
in kwargs
['dns_server']:
1317 params
['dns_nameservers'].append(server
)
1319 ntconn
= self
._get
_neutron
_connection
()
1321 subnet
= ntconn
.create_subnet({'subnets': [params
]})
1322 except Exception as e
:
1323 logger
.error("OpenstackDriver: Create Subnet operation failed. Exception: %s" %(str(e
)))
1326 return subnet
['subnets'][0]['id']
1328 def subnet_list(self
):
1330 Returns a list of dictionaries. Each dictionary contains attributes describing the subnet
1335 A dictionary of the objects of subnet attributes
1337 ntconn
= self
._get
_neutron
_connection
()
1339 subnets
= ntconn
.list_subnets()['subnets']
1340 except Exception as e
:
1341 logger
.error("OpenstackDriver: List Subnet operation failed. Exception: %s" %(str(e
)))
1345 def _subnet_get(self
, subnet_id
):
1347 Returns a dictionary object describing the attributes of a subnet.
1350 subnet_id (string): UUID of the subnet
1353 A dictionary object of the subnet attributes
1355 ntconn
= self
._get
_neutron
_connection
()
1356 subnets
= ntconn
.list_subnets(id=subnet_id
)
1357 if not subnets
['subnets']:
1358 logger
.error("OpenstackDriver: Get subnet operation failed for subnet_id: %s" %(subnet_id))
1359 #raise NeutronException.NotFound("Could not find subnet_id %s" %(subnet_id))
1362 return subnets
['subnets'][0]
1364 def subnet_get(self
, subnet_id
):
1366 Returns a dictionary object describing the attributes of a subnet.
1369 subnet_id (string): UUID of the subnet
1372 A dictionary object of the subnet attributes
1374 return self
._subnet
_get
(subnet_id
)
1376 def subnet_delete(self
, subnet_id
):
1378 Deletes a subnet identified by subnet_id
1381 subnet_id (string): UUID of the subnet to be deleted
1385 ntconn
= self
._get
_neutron
_connection
()
1386 assert subnet_id
== self
._subnet
_get
(self
,subnet_id
)
1388 ntconn
.delete_subnet(subnet_id
)
1389 except Exception as e
:
1390 logger
.error("OpenstackDriver: Delete Subnet operation failed for subnet_id : %s. Exception: %s" %(subnet_id
, str(e
)))
1393 def port_list(self
, **kwargs
):
1395 Returns a list of dictionaries. Each dictionary contains attributes describing the port
1398 kwargs (dictionary): A dictionary for filters for port_list operation
1401 A dictionary of the objects of port attributes
1405 ntconn
= self
._get
_neutron
_connection
()
1407 kwargs
['tenant_id'] = self
.ks_drv
.get_tenant_id()
1410 ports
= ntconn
.list_ports(**kwargs
)
1411 except Exception as e
:
1412 logger
.info("OpenstackDriver: List Port operation failed. Exception: %s" %(str(e
)))
1414 return ports
['ports']
1416 def port_create(self
, **kwargs
):
1418 Create a port in network
1421 A dictionary of following
1423 name (string) : Name of the port
1424 network_id(string) : UUID of the network_id identifying the network to which port belongs
1425 subnet_id(string) : UUID of the subnet_id from which IP-address will be assigned to port
1426 vnic_type(string) : Possible values are "normal", "direct", "macvtap"
1429 port_id (string) : UUID of the port
1433 "admin_state_up" : kwargs
['admin_state_up'],
1434 "name" : kwargs
['name'],
1435 "network_id" : kwargs
['network_id'],
1436 "fixed_ips" : [ {"subnet_id": kwargs
['subnet_id']}],
1437 "binding:vnic_type" : kwargs
['port_type']}}
1439 ntconn
= self
._get
_neutron
_connection
()
1441 port
= ntconn
.create_port(params
)
1442 except Exception as e
:
1443 logger
.error("OpenstackDriver: Port Create operation failed. Exception: %s" %(str(e
)))
1445 return port
['port']['id']
1447 def _port_get(self
, port_id
):
1449 Returns a dictionary object describing the attributes of the port
1452 port_id (string): UUID of the port
1455 A dictionary object of the port attributes
1457 ntconn
= self
._get
_neutron
_connection
()
1458 port
= ntconn
.list_ports(id=port_id
)['ports']
1460 raise NeutronException
.NotFound("Could not find port_id %s" %(port_id))
1463 def port_get(self
, port_id
):
1465 Returns a dictionary object describing the attributes of the port
1468 port_id (string): UUID of the port
1471 A dictionary object of the port attributes
1473 return self
._port
_get
(port_id
)
1475 def port_delete(self
, port_id
):
1477 Deletes a port identified by port_id
1480 port_id (string) : UUID of the port
1484 assert port_id
== self
._port
_get
(port_id
)['id']
1485 ntconn
= self
._get
_neutron
_connection
()
1487 ntconn
.delete_port(port_id
)
1488 except Exception as e
:
1489 logger
.error("Port Delete operation failed for port_id : %s. Exception: %s" %(port_id
, str(e
)))
1492 def security_group_list(self
):
1494 Returns a list of dictionaries. Each dictionary contains attributes describing the security group
1500 A dictionary of the objects of security group attributes
1502 ntconn
= self
._get
_neutron
_connection
()
1504 group_list
= ntconn
.list_security_groups(tenant_id
=self
.ks_drv
.get_tenant_id())
1505 except Exception as e
:
1506 logger
.error("List Security group operation, Exception: %s" %(str(e
)))
1509 if 'security_groups' in group_list
:
1510 return group_list
['security_groups']
1514 def subnetpool_list(self
, **kwargs
):
1516 Returns a list of dictionaries. Each dictionary contains attributes describing a subnet prefix pool
1522 A dictionary of the objects of subnet prefix pool
1524 ntconn
= self
._get
_neutron
_connection
()
1526 pool_list
= ntconn
.list_subnetpools(**kwargs
)
1527 except Exception as e
:
1528 logger
.error("List SubnetPool operation, Exception: %s" %(str(e
)))
1531 if 'subnetpools' in pool_list
:
1532 return pool_list
['subnetpools']
1536 class NeutronDriverV2(NeutronDriver
):
1538 Driver for openstack neutron neutron-client v2
1540 def __init__(self
, ks_drv
):
1542 Constructor for NeutronDriver
1543 Arguments: KeystoneDriver class object
1545 super(NeutronDriverV2
, self
).__init
__(ks_drv
, 'network', '2.0')
1549 class CeilometerDriver(object):
1551 Driver for openstack ceilometer client
1554 def __init__(self
, ks_drv
, service_name
, version
):
1556 Constructor for CeilometerDriver
1557 Arguments: KeystoneDriver class object
1559 self
.ks_drv
= ks_drv
1560 self
._service
_name
= service_name
1561 self
._version
= version
1566 """The version of the ceilometer client used by the driver"""
1567 return self
._version
1571 """The instance of ceilometer client used by the driver"""
1572 if self
._client
is None or not self
.ks_drv
.is_auth_token_valid():
1573 self
._client
= ceilo_client
.Client(**self
.credentials
)
1578 def auth_token(self
):
1579 """The authorization token for the ceilometer client"""
1581 return self
.ks_drv
.get_auth_token()
1582 except KeystoneExceptions
.EndpointNotFound
as e
:
1583 logger
.error("OpenstackDriver: unable to get authorization token for ceilometer. Exception: %s" %(str(e
)))
1587 def security_mode(self
):
1588 """The security mode for the ceilometer client"""
1590 return self
.ks_drv
.get_security_mode()
1591 except KeystoneExceptions
.EndpointNotFound
as e
:
1592 logger
.error("OpenstackDriver: unable to get security mode for ceilometer. Exception: %s" %(str(e
)))
1597 """The service endpoint for the ceilometer client"""
1599 return self
.ks_drv
.get_service_endpoint(self
._service
_name
, "publicURL")
1600 except KeystoneExceptions
.EndpointNotFound
as e
:
1601 logger
.error("OpenstackDriver: unable to get endpoint for ceilometer. Exception: %s" %(str(e
)))
1605 def credentials(self
):
1606 """A dictionary of credentials for the ceilometer client"""
1608 version
=self
.version
,
1609 endpoint
=self
.endpoint
,
1610 token
=self
.auth_token
,
1611 insecure
=self
.security_mode
,
1616 """A list of the available meters"""
1618 return self
.client
.meters
.list()
1619 except Exception as e
:
1620 logger
.error("OpenstackDriver: List meters operation failed. Exception: %s" %(str(e
)))
1625 """The ceilometer client alarms manager"""
1626 return self
.client
.alarms
1628 def query_samples(self
, vim_instance_id
, counter_name
, limit
=1):
1629 """Returns a list of samples
1632 vim_instance_id - the ID of the VIM that the samples are from
1633 counter_name - the counter that the samples will come from
1634 limit - a limit on the number of samples to return
1642 filter = json
.dumps({
1644 {"=": {"resource": vim_instance_id
}},
1645 {"=": {"counter_name": counter_name
}}
1648 result
= self
.client
.query_samples
.query(filter=filter, limit
=limit
)
1649 return result
[-limit
:]
1651 except Exception as e
:
1657 class CeilometerDriverV2(CeilometerDriver
):
1659 Driver for openstack ceilometer ceilometer-client
1661 def __init__(self
, ks_drv
):
1663 Constructor for CeilometerDriver
1664 Arguments: CeilometerDriver class object
1666 super(CeilometerDriverV2
, self
).__init
__(ks_drv
, 'metering', '2')
1668 class OpenstackDriver(object):
1670 Driver for openstack nova, neutron, glance, keystone, swift, cinder services
1672 def __init__(self
, username
, password
, auth_url
, tenant_name
, mgmt_network
= None, cert_validate
= False, user_domain_name
= None, project_domain_name
= None):
1674 OpenstackDriver Driver constructor
1676 username (string) : Username for project/tenant.
1677 password (string) : Password
1678 auth_url (string) : Keystone Authentication URL.
1679 tenant_name (string) : Openstack project name
1680 mgmt_network(string, optional) : Management network name. Each VM created with this cloud-account will
1681 have a default interface into management network.
1682 cert_validate (boolean, optional) : In case of SSL/TLS connection if certificate validation is required or not.
1685 insecure
= not cert_validate
1686 if auth_url
.find('/v3') != -1:
1687 self
.ks_drv
= KeystoneDriverV3(username
, password
, auth_url
, tenant_name
, insecure
, user_domain_name
, project_domain_name
)
1688 self
.glance_drv
= GlanceDriverV2(self
.ks_drv
)
1689 self
.nova_drv
= NovaDriverV21(self
.ks_drv
)
1690 self
.neutron_drv
= NeutronDriverV2(self
.ks_drv
)
1691 self
.ceilo_drv
= CeilometerDriverV2(self
.ks_drv
)
1692 elif auth_url
.find('/v2') != -1:
1693 self
.ks_drv
= KeystoneDriverV2(username
, password
, auth_url
, tenant_name
, insecure
)
1694 self
.glance_drv
= GlanceDriverV2(self
.ks_drv
)
1695 self
.nova_drv
= NovaDriverV2(self
.ks_drv
)
1696 self
.neutron_drv
= NeutronDriverV2(self
.ks_drv
)
1697 self
.ceilo_drv
= CeilometerDriverV2(self
.ks_drv
)
1699 logger
.error("Could not identity the version information for openstack service endpoints. Auth_URL should contain \"/v2\" or \"/v3\" string in it")
1700 raise NotImplementedError("Auth URL is wrong or invalid. Only Keystone v2 & v3 supported")
1702 self
._mgmt
_network
_id
= None
1703 if mgmt_network
!= None:
1704 self
._mgmt
_network
= mgmt_network
1708 ntconn
= self
.neutron_drv
._get
_neutron
_connection
()
1709 networks
= ntconn
.list_networks()
1710 except (KeystoneExceptions
.Unauthorized
, KeystoneExceptions
.AuthorizationFailure
) as e
:
1712 except Exception as e
:
1713 logger
.error("OpenstackDriver: List Network operation failed. Exception: %s" %(str(e
)))
1716 network_list
= [ network
for network
in networks
['networks'] if network
['name'] == mgmt_network
]
1718 if not network_list
:
1719 raise NeutronException
.NotFound("Could not find network %s" %(mgmt_network))
1720 self
._mgmt
_network
_id
= network_list
[0]['id']
1722 def validate_account_creds(self
):
1724 ksconn
= self
.ks_drv
._get
_keystone
_connection
()
1725 except KeystoneExceptions
.AuthorizationFailure
as e
:
1726 logger
.error("OpenstackDriver: Unable to authenticate or validate the existing credentials. Exception: %s" %(str(e
)))
1727 raise ValidationError("Invalid Credentials: "+ str(e
))
1728 except Exception as e
:
1729 logger
.error("OpenstackDriver: Could not connect to Openstack. Exception: %s" %(str(e
)))
1730 raise ValidationError("Connection Error: "+ str(e
))
1732 def get_mgmt_network_id(self
):
1733 return self
._mgmt
_network
_id
1735 def glance_image_create(self
, **kwargs
):
1736 if not 'disk_format' in kwargs
:
1737 kwargs
['disk_format'] = 'qcow2'
1738 if not 'container_format' in kwargs
:
1739 kwargs
['container_format'] = 'bare'
1740 if not 'min_disk' in kwargs
:
1741 kwargs
['min_disk'] = 0
1742 if not 'min_ram' in kwargs
:
1743 kwargs
['min_ram'] = 0
1744 return self
.glance_drv
.image_create(**kwargs
)
1746 def glance_image_upload(self
, image_id
, fd
):
1747 self
.glance_drv
.image_upload(image_id
, fd
)
1749 def glance_image_add_location(self
, image_id
, location
):
1750 self
.glance_drv
.image_add_location(image_id
, location
)
1752 def glance_image_delete(self
, image_id
):
1753 self
.glance_drv
.image_delete(image_id
)
1755 def glance_image_list(self
):
1756 return self
.glance_drv
.image_list()
1758 def glance_image_get(self
, image_id
):
1759 return self
.glance_drv
.image_get(image_id
)
1762 def nova_flavor_list(self
):
1763 return self
.nova_drv
.flavor_list()
1765 def nova_flavor_create(self
, name
, ram
, vcpus
, disk
, epa_specs
):
1766 extra_specs
= epa_specs
if epa_specs
else {}
1767 return self
.nova_drv
.flavor_create(name
,
1771 extra_specs
= extra_specs
)
1773 def nova_flavor_delete(self
, flavor_id
):
1774 self
.nova_drv
.flavor_delete(flavor_id
)
1776 def nova_flavor_get(self
, flavor_id
):
1777 return self
.nova_drv
.flavor_get(flavor_id
)
1779 def nova_server_create(self
, **kwargs
):
1780 def _verify_image(image_id
):
1781 image
= self
.glance_drv
.image_get(image_id
)
1782 if image
['status'] != 'active':
1783 raise GlanceException
.NotFound("Image with image_id: %s not found in active state. Current State: %s" %(image
['id'], image
['status']))
1785 assert kwargs
['flavor_id'] == self
.nova_drv
.flavor_get(kwargs
['flavor_id'])['id']
1787 if kwargs
['block_device_mapping_v2'] is not None:
1788 for block_map
in kwargs
['block_device_mapping_v2']:
1789 if 'uuid' in block_map
:
1790 _verify_image(block_map
['uuid'])
1792 _verify_image(kwargs
['image_id'])
1794 # if 'network_list' in kwargs:
1795 # kwargs['network_list'].append(self._mgmt_network_id)
1797 # kwargs['network_list'] = [self._mgmt_network_id]
1799 if 'security_groups' not in kwargs
:
1800 nvconn
= self
.nova_drv
._get
_nova
_connection
()
1801 sec_groups
= nvconn
.security_groups
.list()
1803 ## Should we add VM in all availability security_groups ???
1804 kwargs
['security_groups'] = [x
.name
for x
in sec_groups
]
1806 kwargs
['security_groups'] = None
1808 return self
.nova_drv
.server_create(**kwargs
)
1810 def nova_server_add_port(self
, server_id
, port_id
):
1811 self
.nova_drv
.server_add_port(server_id
, port_id
)
1813 def nova_server_delete_port(self
, server_id
, port_id
):
1814 self
.nova_drv
.server_delete_port(server_id
, port_id
)
1816 def nova_server_start(self
, server_id
):
1817 self
.nova_drv
.server_start(server_id
)
1819 def nova_server_stop(self
, server_id
):
1820 self
.nova_drv
.server_stop(server_id
)
1822 def nova_server_delete(self
, server_id
):
1823 self
.nova_drv
.server_delete(server_id
)
1825 def nova_server_reboot(self
, server_id
):
1826 self
.nova_drv
.server_reboot(server_id
, reboot_type
='HARD')
1828 def nova_server_rebuild(self
, server_id
, image_id
):
1829 self
.nova_drv
.server_rebuild(server_id
, image_id
)
1831 def nova_floating_ip_list(self
):
1832 return self
.nova_drv
.floating_ip_list()
1834 def nova_floating_ip_create(self
, pool
= None):
1835 return self
.nova_drv
.floating_ip_create(pool
)
1837 def nova_floating_ip_delete(self
, floating_ip
):
1838 self
.nova_drv
.floating_ip_delete(floating_ip
)
1840 def nova_floating_ip_assign(self
, server_id
, floating_ip
, fixed_ip
):
1841 self
.nova_drv
.floating_ip_assign(server_id
, floating_ip
, fixed_ip
)
1843 def nova_floating_ip_release(self
, server_id
, floating_ip
):
1844 self
.nova_drv
.floating_ip_release(server_id
, floating_ip
)
1846 def nova_server_list(self
):
1847 return self
.nova_drv
.server_list()
1849 def nova_server_get(self
, server_id
):
1850 return self
.nova_drv
.server_get(server_id
)
1852 def nova_server_console(self
, server_id
):
1853 return self
.nova_drv
.server_console(server_id
)
1855 def nova_server_group_list(self
):
1856 return self
.nova_drv
.group_list()
1858 def nova_volume_list(self
, server_id
):
1859 return self
.nova_drv
.volume_list(server_id
)
1861 def neutron_network_list(self
):
1862 return self
.neutron_drv
.network_list()
1864 def neutron_network_get(self
, network_id
):
1865 return self
.neutron_drv
.network_get(network_id
)
1867 def neutron_network_create(self
, **kwargs
):
1868 return self
.neutron_drv
.network_create(**kwargs
)
1870 def neutron_network_delete(self
, network_id
):
1871 self
.neutron_drv
.network_delete(network_id
)
1873 def neutron_subnet_list(self
):
1874 return self
.neutron_drv
.subnet_list()
1876 def neutron_subnet_get(self
, subnet_id
):
1877 return self
.neutron_drv
.subnet_get(subnet_id
)
1879 def neutron_subnet_create(self
, **kwargs
):
1880 return self
.neutron_drv
.subnet_create(**kwargs
)
1882 def netruon_subnet_delete(self
, subnet_id
):
1883 self
.neutron_drv
.subnet_delete(subnet_id
)
1885 def neutron_subnetpool_list(self
):
1886 return self
.neutron_drv
.subnetpool_list()
1888 def netruon_subnetpool_by_name(self
, pool_name
):
1889 pool_list
= self
.neutron_drv
.subnetpool_list(**{'name': pool_name
})
1895 def neutron_port_list(self
, **kwargs
):
1896 return self
.neutron_drv
.port_list(**kwargs
)
1898 def neutron_port_get(self
, port_id
):
1899 return self
.neutron_drv
.port_get(port_id
)
1901 def neutron_port_create(self
, **kwargs
):
1902 subnets
= [subnet
for subnet
in self
.neutron_drv
.subnet_list() if subnet
['network_id'] == kwargs
['network_id']]
1903 assert len(subnets
) == 1
1904 kwargs
['subnet_id'] = subnets
[0]['id']
1905 if not 'admin_state_up' in kwargs
:
1906 kwargs
['admin_state_up'] = True
1907 port_id
= self
.neutron_drv
.port_create(**kwargs
)
1909 if 'vm_id' in kwargs
:
1910 self
.nova_server_add_port(kwargs
['vm_id'], port_id
)
1913 def neutron_security_group_list(self
):
1914 return self
.neutron_drv
.security_group_list()
1916 def neutron_security_group_by_name(self
, group_name
):
1917 group_list
= self
.neutron_drv
.security_group_list()
1918 groups
= [group
for group
in group_list
if group
['name'] == group_name
]
1924 def neutron_port_delete(self
, port_id
):
1925 self
.neutron_drv
.port_delete(port_id
)
1927 def ceilo_meter_endpoint(self
):
1928 return self
.ceilo_drv
.endpoint
1930 def ceilo_meter_list(self
):
1931 return self
.ceilo_drv
.meters
1933 def ceilo_nfvi_metrics(self
, vim_id
):
1934 """Returns a dict of NFVI metrics for a given VM
1937 vim_id - the VIM ID of the VM to retrieve the metrics for
1940 A dict of NFVI metrics
1943 def query_latest_sample(counter_name
):
1945 filter = json
.dumps({
1947 {"=": {"resource": vim_id
}},
1948 {"=": {"counter_name": counter_name
}}
1951 orderby
= json
.dumps([{"timestamp": "DESC"}])
1952 result
= self
.ceilo_drv
.client
.query_samples
.query(
1962 except Exception as e
:
1963 logger
.error("Got exception while querying ceilometer, exception details:%s " %str
(e
))
1967 memory_usage
= query_latest_sample("memory.usage")
1968 disk_usage
= query_latest_sample("disk.usage")
1969 cpu_util
= query_latest_sample("cpu_util")
1973 if memory_usage
is not None:
1974 memory_usage
.volume
= 1e6
* memory_usage
.volume
1975 metrics
["memory_usage"] = memory_usage
.to_dict()
1977 if disk_usage
is not None:
1978 metrics
["disk_usage"] = disk_usage
.to_dict()
1980 if cpu_util
is not None:
1981 metrics
["cpu_util"] = cpu_util
.to_dict()
1985 def ceilo_alarm_list(self
):
1986 """Returns a list of ceilometer alarms"""
1987 return self
.ceilo_drv
.client
.alarms
.list()
1989 def ceilo_alarm_create(self
,
2002 """Create a new Alarm
2005 name - the name of the alarm
2006 meter - the name of the meter to measure
2007 statistic - the type of statistic used to trigger the alarm
2008 ('avg', 'min', 'max', 'count', 'sum')
2009 operation - the relational operator that, combined with the
2010 threshold value, determines when the alarm is
2011 triggered ('lt', 'le', 'eq', 'ge', 'gt')
2012 threshold - the value of the statistic that will trigger the
2014 period - the duration (seconds) over which to evaluate the
2016 evaluations - the number of samples of the meter statistic to
2017 collect when evaluating the threshold
2018 severity - a measure of the urgency or importance of the alarm
2019 ('low', 'moderate', 'critical')
2020 repeat - a flag that indicates whether the alarm should be
2021 triggered once (False) or repeatedly while the alarm
2022 condition is true (True)
2023 enabled - a flag that indicates whether the alarm is enabled
2024 (True) or disabled (False)
2025 actions - a dict specifying the URLs for webhooks. The dict can
2026 have up to 3 keys: 'insufficient_data', 'alarm',
2027 'ok'. Each key is associated with a list of URLs to
2028 webhooks that will be invoked when one of the 3
2030 kwargs - an arbitrary dict of keyword arguments that are
2031 passed to the ceilometer client
2034 ok_actions
= actions
.get('ok') if actions
is not None else None
2035 alarm_actions
= actions
.get('alarm') if actions
is not None else None
2036 insufficient_data_actions
= actions
.get('insufficient_data') if actions
is not None else None
2038 return self
.ceilo_drv
.client
.alarms
.create(
2041 statistic
=statistic
,
2042 comparison_operator
=operation
,
2043 threshold
=threshold
,
2045 evaluation_periods
=evaluations
,
2047 repeat_actions
=repeat
,
2049 ok_actions
=ok_actions
,
2050 alarm_actions
=alarm_actions
,
2051 insufficient_data_actions
=insufficient_data_actions
,
2055 def ceilo_alarm_update(self
, alarm_id
, **kwargs
):
2056 """Updates an existing alarm
2059 alarm_id - the identifier of the alarm to update
2060 kwargs - a dict of the alarm attributes to update
2063 return self
.ceilo_drv
.client
.alarms
.update(alarm_id
, **kwargs
)
2065 def ceilo_alarm_delete(self
, alarm_id
):
2066 self
.ceilo_drv
.client
.alarms
.delete(alarm_id
)