def openstack_cloud( config=None, strict=False, app_name=None, app_version=None, **kwargs): if not config: config = _get_openstack_config(app_name, app_version) try: cloud_region = config.get_one(**kwargs) except keystoneauth1.exceptions.auth_plugins.NoMatchingPlugin as e: raise OpenStackCloudException( "Invalid cloud configuration: {exc}".format(exc=str(e))) return OpenStackCloud(cloud_config=cloud_region, strict=strict)
def __init__(self, config_files=None, refresh=False, private=False, config_key=None, config_defaults=None, cloud=None, use_direct_get=False): if config_files is None: config_files = [] config = openstack.config.loader.OpenStackConfig( config_files=openstack.config.loader.CONFIG_FILES + config_files) self.extra_config = config.get_extra_config(config_key, config_defaults) if cloud is None: self.clouds = [ openstack.cloud.OpenStackCloud(cloud_config=cloud_region) for cloud_region in config.get_all() ] else: try: self.clouds = [ openstack.cloud.OpenStackCloud( cloud_config=config.get_one(cloud)) ] except openstack.config.exceptions.OpenStackConfigException as e: raise openstack.cloud.OpenStackCloudException(e) if private: for cloud in self.clouds: cloud.private = True # Handle manual invalidation of entire persistent cache if refresh: for cloud in self.clouds: cloud._cache.invalidate()
def connect_as(self, **kwargs): """Make a new OpenStackCloud object with new auth context. Take the existing settings from the current cloud and construct a new OpenStackCloud object with some of the auth settings overridden. This is useful for getting an object to perform tasks with as another user, or in the context of a different project. .. code-block:: python conn = openstack.connect(cloud='example') # Work normally servers = conn.list_servers() conn2 = conn.connect_as(username='******', password='') # Work as different-user servers = conn2.list_servers() :param kwargs: keyword arguments can contain anything that would normally go in an auth dict. They will override the same settings from the parent cloud as appropriate. Entries that do not want to be overridden can be ommitted. """ if self.config._openstack_config: config = self.config._openstack_config else: # TODO(mordred) Replace this with from_session config = openstack.config.OpenStackConfig( app_name=self.config._app_name, app_version=self.config._app_version, load_yaml_config=False) params = copy.deepcopy(self.config.config) # Remove profile from current cloud so that overridding works params.pop('profile', None) # Utility function to help with the stripping below. def pop_keys(params, auth, name_key, id_key): if name_key in auth or id_key in auth: params['auth'].pop(name_key, None) params['auth'].pop(id_key, None) # If there are user, project or domain settings in the incoming auth # dict, strip out both id and name so that a user can say: # cloud.connect_as(project_name='foo') # and have that work with clouds that have a project_id set in their # config. for prefix in ('user', 'project'): if prefix == 'user': name_key = 'username' else: name_key = 'project_name' id_key = '{prefix}_id'.format(prefix=prefix) pop_keys(params, kwargs, name_key, id_key) id_key = '{prefix}_domain_id'.format(prefix=prefix) name_key = '{prefix}_domain_name'.format(prefix=prefix) pop_keys(params, kwargs, name_key, id_key) for key, value in kwargs.items(): params['auth'][key] = value # TODO(mordred) Replace this chunk with the next patch that allows # passing a Session to CloudRegion. # Closure to pass to OpenStackConfig to ensure the new cloud shares # the Session with the current cloud. This will ensure that version # discovery cache will be re-used. def session_constructor(*args, **kwargs): # We need to pass our current keystone session to the Session # Constructor, otherwise the new auth plugin doesn't get used. return keystoneauth1.session.Session( session=self.session, discovery_cache=self.config._discovery_cache) cloud_config = config.get_one( session_constructor=session_constructor, **params) # Override the cloud name so that logging/location work right cloud_config._name = self.name cloud_config.config['profile'] = self.name # Use self.__class__ so that we return whatever this if, like if it's # a subclass in the case of shade wrapping sdk. return self.__class__(config=cloud_config)
def connect_as(self, **kwargs): """Make a new OpenStackCloud object with new auth context. Take the existing settings from the current cloud and construct a new OpenStackCloud object with some of the auth settings overridden. This is useful for getting an object to perform tasks with as another user, or in the context of a different project. .. code-block:: python conn = openstack.connect(cloud='example') # Work normally servers = conn.list_servers() conn2 = conn.connect_as(username='******', password='') # Work as different-user servers = conn2.list_servers() :param kwargs: keyword arguments can contain anything that would normally go in an auth dict. They will override the same settings from the parent cloud as appropriate. Entries that do not want to be overridden can be ommitted. """ if self.config._openstack_config: config = self.config._openstack_config else: # TODO(mordred) Replace this with from_session config = openstack.config.OpenStackConfig( app_name=self.config._app_name, app_version=self.config._app_version, load_yaml_config=False) params = copy.deepcopy(self.config.config) # Remove profile from current cloud so that overridding works params.pop('profile', None) # Utility function to help with the stripping below. def pop_keys(params, auth, name_key, id_key): if name_key in auth or id_key in auth: params['auth'].pop(name_key, None) params['auth'].pop(id_key, None) # If there are user, project or domain settings in the incoming auth # dict, strip out both id and name so that a user can say: # cloud.connect_as(project_name='foo') # and have that work with clouds that have a project_id set in their # config. for prefix in ('user', 'project'): if prefix == 'user': name_key = 'username' else: name_key = 'project_name' id_key = '{prefix}_id'.format(prefix=prefix) pop_keys(params, kwargs, name_key, id_key) id_key = '{prefix}_domain_id'.format(prefix=prefix) name_key = '{prefix}_domain_name'.format(prefix=prefix) pop_keys(params, kwargs, name_key, id_key) for key, value in kwargs.items(): params['auth'][key] = value # TODO(mordred) Replace this chunk with the next patch that allows # passing a Session to CloudRegion. # Closure to pass to OpenStackConfig to ensure the new cloud shares # the Session with the current cloud. This will ensure that version # discovery cache will be re-used. def session_constructor(*args, **kwargs): # We need to pass our current keystone session to the Session # Constructor, otherwise the new auth plugin doesn't get used. return keystoneauth1.session.Session( session=self.session, discovery_cache=self.config._discovery_cache) cloud_config = config.get_one(session_constructor=session_constructor, **params) # Override the cloud name so that logging/location work right cloud_config._name = self.name cloud_config.config['profile'] = self.name # Use self.__class__ so that we return whatever this if, like if it's # a subclass in the case of shade wrapping sdk. return self.__class__(config=cloud_config)