Skip to content


Add support for default project_id and user_id
Browse files Browse the repository at this point in the history
The user_id and project_id fields for our volumes and snapshots had a
very poor default value, they were defaulting to None.  And the only way
we had to change them was to provide an override for these fields when
creating the resource.

This patch adds a better default for these values ("cinderlib") and also
supports setting a different default on the setup process passing
project_id and user_id parameters to the "setup" method.
  • Loading branch information
Akrog committed Mar 14, 2018
1 parent 76cca47 commit fe871a5
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 13 deletions.
1 change: 1 addition & 0 deletions HISTORY.rst
Expand Up @@ -9,6 +9,7 @@ History

- Modify fields on connect method.
- Support setting custom root_helper.
- Setting default project_id and user_id.

- Bug fixes:

Expand Down
43 changes: 31 additions & 12 deletions cinderlib/
Expand Up @@ -41,12 +41,31 @@

__all__ = ['setup', 'load', 'json', 'jsons', 'Backend', 'Volume', 'Snapshot',

DEFAULT_PROJECT_ID = 'cinderlib'
DEFAULT_USER_ID = 'cinderlib'
CONTEXT = context.RequestContext(user_id=DEFAULT_USER_ID,


def set_context(project_id=None, user_id=None):
global CONTEXT
project_id = project_id or DEFAULT_PROJECT_ID
user_id = user_id or DEFAULT_USER_ID
if project_id != CONTEXT.project_id or user_id != CONTEXT.user_id:
CONTEXT.user_id = user_id
CONTEXT.project_id = project_id
Volume.DEFAULT_FIELDS_VALUES['user_id'] = user_id
Volume.DEFAULT_FIELDS_VALUES['project_id'] = project_id

class Backend(object):
"""Representation of a Cinder Driver.
Expand All @@ -63,7 +82,6 @@ class Backend(object):
backends = {}
global_initialization = False
context = context.get_admin_context()

def __init__(self, volume_backend_name, **driver_cfg):
if not self.global_initialization:
Expand All @@ -79,7 +97,7 @@ def __init__(self, volume_backend_name, **driver_cfg):,
cluster_name=None, # No clusters for now: volume_cmd.CONF.cluster,
active_backend_id=None) # No failover for now
Expand Down Expand Up @@ -156,11 +174,13 @@ def validate_connector(self, connector_dict):
def global_setup(cls, file_locks_path=None, root_helper='sudo',
suppress_requests_ssl_warnings=True, disable_logs=True,
non_uuid_ids=False, output_all_backend_info=False,
project_id=None, user_id=None, **log_params):
# Global setup can only be set once
if cls.global_initialization:
raise Exception('Already setup')

set_context(project_id, user_id)

# Prevent driver dynamic loading clearing configuration options
volume_cmd.CONF._ConfigOpts__cache = MyDict()

Expand Down Expand Up @@ -271,7 +291,6 @@ class Object(object):
"""Base class for our resource representation objects."""
objects = collections.defaultdict(dict)
context = context.get_admin_context()

def __init__(self, backend, **fields_data):
self.backend = backend
Expand Down Expand Up @@ -310,7 +329,7 @@ def _create_ovo(self, **fields_data):
elif field.nullable:
fields_values.setdefault(field_name, None)

return self.OVO_CLASS(context=self.context, **fields_values)
return self.OVO_CLASS(context=CONTEXT, **fields_values)

def json(self):
Expand Down Expand Up @@ -342,7 +361,7 @@ def load(cls, json_src):
backend = Backend(**json_src['backend'])

ovo = cinder_base_ovo.CinderObject.obj_from_primitive(json_src['ovo'],
return cls._load(backend, ovo)

def _replace_ovo(self, ovo):
Expand All @@ -362,8 +381,8 @@ class Volume(Object):
OVO_CLASS = volume_cmd.objects.Volume
'size': 1,
'user_id': Object.context.user_id,
'project_id': Object.context.project_id,
'user_id': CONTEXT.user_id,
'project_id': CONTEXT.project_id,
'status': 'creating',
'attach_status': 'detached',
Expand All @@ -390,10 +409,10 @@ def __init__(self, backend_or_vol, **kwargs):
kwargs['display_name'] = kwargs.pop('name')

super(Volume, self).__init__(backend_or_vol, **kwargs)
self.snapshots = set()
Expand Down Expand Up @@ -556,7 +575,7 @@ def detach(self, force=False, ignore_errors=False):

def connect(self, connector_dict, **ovo_fields):
if not self.exported:
model_update = self.backend.driver.create_export(self.context,
model_update = self.backend.driver.create_export(CONTEXT,
if model_update:
Expand Down
22 changes: 21 additions & 1 deletion docs/topics/initialization.rst
Expand Up @@ -23,7 +23,7 @@ The method definition is as follows:
def global_setup(cls, file_locks_path=None, root_helpers='sudo',
suppress_requests_ssl_warnings=True, disable_logs=True,
non_uuid_ids=False, output_all_backend_info=False,
project_id=None, user_id=None, **log_params):
The meaning of the library's configuration options are:
Expand Down Expand Up @@ -102,6 +102,26 @@ default.

Defaults to `True`.


*Cinder* is a multi-tenant service, and when resources are created they belong
to a specific tenant/project. With this parameter we can define, using a
string, an identifier for our project that will be assigned to the resources we

Defaults to `cinderlib`.


Within each project/tenant the *Cinder* project supports multiple users, so
when it creates a resource a reference to the user that created it is stored
in the resource. Using this this parameter we can define, using a string, an
identifier for the user of cinderlib to be recorded in the resources.

Defaults to `cinderlib`.

other keyword arguments

Expand Down

1 comment on commit fe871a5

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, this enables the use of SolidFire with cinderlib now; and likely some other backends as well!

Please sign in to comment.