From 3d5fffd7a391d159f49acc54f2b5307a9d44e5f0 Mon Sep 17 00:00:00 2001 From: tengqm Date: Fri, 16 Jan 2015 15:15:20 +0800 Subject: [PATCH] Revised sdk interface This module is used to interface with openstacksdk. The main problem we encountered is that the default list() operation carries DB session. There are cases where our list generation is from in-memory data. To overcome that we provide a list_short() method to Resource class. The SenlinConnection class is not useful at the moment. The UserPreferences is a standard way to specify desired API version, region name, an API visibility (public, private, admin). We provide a subclass here to deal with the respective requirements. --- senlinclient/common/sdk.py | 114 +++++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 31 deletions(-) diff --git a/senlinclient/common/sdk.py b/senlinclient/common/sdk.py index 385bab2e..9265b42f 100644 --- a/senlinclient/common/sdk.py +++ b/senlinclient/common/sdk.py @@ -10,45 +10,97 @@ # License for the specific language governing permissions and limitations # under the License. +import argparse +import os from openstack import connection +from openstack import user_preference from openstack.identity import identity_service +from openstack import resource as base +# Alias here for consistency +prop = base.prop -class SenlinConnection(connection.Connection): - '''Connection object - It has 'session' property +class UserPreferenceAction(argparse.Action): ''' - def __init__(**kwargs): - ''' openstacksdk expects the followin arguments - auth_plugin - auth_url - project_name - domain_name - project_domain_name - user_domain_name - user_name - password - verify - token + A custom action to parse user preferences as key=value pairs + + Stores results in users preferences object. + ''' + pref = user_preference.UserPreference() + + @classmethod + def env(cls, *vars): + for v in vars: + values = os.environ.get(v, None) + if values is None: + continue + cls.set_option(v, values) + return cls.pref + return cls.pref + + @classmethod + def set_option(cls, var, values): + if var == 'OS_REGION_NAME': + var = 'region' + var = var.replace('--os-api-', '') + var = var.replace('OS_API_', '') + var = var.lower() + for kvp in values.split(','): + if var == 'region': + if '=' in kvp: + service, value = kvp.split('=') + else: + service = cls.pref.ALL + value = kvp + else: + if '=' in kvp: + service, value = kvp.split('=') + else: + service = cls.pref.ALL + value = kvp + if var == 'name': + cls.pref.set_name(service, value) + elif var == 'region': + cls.pref.set_region(service, value) + elif var == 'version': + cls.pref.set_version(service, value) + elif var == 'visibility': + cls.pref.set_visibility(service, value) + + def __call__(self, parser, namespace, values, option_string=None): + if getattr(namespace, self.dest, None) is None: + setattr(namespace, self.dest, UserPreferenceAction.pref) + self.set_option(option_string, values) + + +class Resource(base.Resource): + ''' + Senlin version of resource. + + These classes are here because the OpenStack SDK base version is making + some assumptions about operations that cannot be satisfied in Senlin. + ''' + @classmethod + def list_short(cls, session, path_args=None, **params): ''' - preference = kwargs.pop('user_preferences', {}) - super(SenlinConnection, self).__init__(preference=preference, **kwargs) + Return a generator that will page through results of GET requests. + This method bypasses the DB session support and retrieves list that + is directly exposed by server. + ''' + if not cls.allow_list: + raise exceptions.MethodNotSupported('list') + if path_args: + url = cls.base_path % path_args + else: + url = cls.base_path -def run_create(connection, **kwargs): - cls = senlinclient.v1.client. - obj = cls.new(**kwargs) - obj.create(sess) + resp = session.get(url, service=cls.service, params=params).body + if cls.resources_key: + resp = resp[cls.resources_key] - -def run_get(connection, **kwargs): - sess = conneciton.session - obj = cls.new(**kwargs) - obj.get(sess) - - -def run_list(connection): - sess = connection.session - return cls.list(sess, path_args=**kwargs) + for data in resp: + value = cls.existing(**data) + yield value