diff options
-rwxr-xr-x | .testr.conf | 2 | ||||
-rw-r--r-- | doc/source/conf.py | 22 | ||||
-rw-r--r-- | openstack-common.conf | 2 | ||||
-rwxr-xr-x | run_tests.sh | 4 | ||||
-rw-r--r-- | saharaclient/api/__init__.py (renamed from savannaclient/nova/__init__.py) | 0 | ||||
-rw-r--r-- | saharaclient/api/base.py (renamed from savannaclient/api/base.py) | 0 | ||||
-rw-r--r-- | saharaclient/api/client.py (renamed from savannaclient/api/client.py) | 24 | ||||
-rw-r--r-- | saharaclient/api/cluster_templates.py (renamed from savannaclient/api/cluster_templates.py) | 2 | ||||
-rw-r--r-- | saharaclient/api/clusters.py (renamed from savannaclient/api/clusters.py) | 2 | ||||
-rw-r--r-- | saharaclient/api/data_sources.py (renamed from savannaclient/api/data_sources.py) | 2 | ||||
-rw-r--r-- | saharaclient/api/helpers.py (renamed from savannaclient/api/helpers.py) | 2 | ||||
-rw-r--r-- | saharaclient/api/httpclient.py (renamed from savannaclient/api/httpclient.py) | 0 | ||||
-rw-r--r-- | saharaclient/api/images.py (renamed from savannaclient/api/images.py) | 2 | ||||
-rw-r--r-- | saharaclient/api/job_binaries.py (renamed from savannaclient/api/job_binaries.py) | 2 | ||||
-rw-r--r-- | saharaclient/api/job_binary_internals.py (renamed from savannaclient/api/job_binary_internals.py) | 2 | ||||
-rw-r--r-- | saharaclient/api/job_executions.py (renamed from savannaclient/api/job_executions.py) | 2 | ||||
-rw-r--r-- | saharaclient/api/jobs.py (renamed from savannaclient/api/jobs.py) | 2 | ||||
-rw-r--r-- | saharaclient/api/node_group_templates.py (renamed from savannaclient/api/node_group_templates.py) | 2 | ||||
-rw-r--r-- | saharaclient/api/parameters.py (renamed from savannaclient/api/parameters.py) | 0 | ||||
-rw-r--r-- | saharaclient/api/plugins.py (renamed from savannaclient/api/plugins.py) | 2 | ||||
-rw-r--r-- | saharaclient/api/shell.py (renamed from savannaclient/api/shell.py) | 6 | ||||
-rw-r--r-- | saharaclient/client.py | 30 | ||||
-rw-r--r-- | saharaclient/nova/__init__.py (renamed from savannaclient/openstack/__init__.py) | 0 | ||||
-rw-r--r-- | saharaclient/nova/auth_plugin.py (renamed from savannaclient/nova/auth_plugin.py) | 4 | ||||
-rw-r--r-- | saharaclient/nova/base.py (renamed from savannaclient/nova/base.py) | 6 | ||||
-rw-r--r-- | saharaclient/nova/extension.py (renamed from savannaclient/nova/extension.py) | 4 | ||||
-rw-r--r-- | saharaclient/nova/utils.py (renamed from savannaclient/nova/utils.py) | 4 | ||||
-rw-r--r-- | saharaclient/openstack/__init__.py (renamed from savannaclient/openstack/common/apiclient/__init__.py) | 0 | ||||
-rw-r--r-- | saharaclient/openstack/common/__init__.py (renamed from savannaclient/tests/__init__.py) | 0 | ||||
-rw-r--r-- | saharaclient/openstack/common/apiclient/__init__.py (renamed from savannaclient/tests/nova/__init__.py) | 0 | ||||
-rw-r--r-- | saharaclient/openstack/common/apiclient/auth.py (renamed from savannaclient/openstack/common/apiclient/auth.py) | 4 | ||||
-rw-r--r-- | saharaclient/openstack/common/apiclient/base.py (renamed from savannaclient/openstack/common/apiclient/base.py) | 4 | ||||
-rw-r--r-- | saharaclient/openstack/common/apiclient/client.py (renamed from savannaclient/openstack/common/apiclient/client.py) | 6 | ||||
-rw-r--r-- | saharaclient/openstack/common/apiclient/exceptions.py (renamed from savannaclient/openstack/common/apiclient/exceptions.py) | 0 | ||||
-rw-r--r-- | saharaclient/openstack/common/apiclient/fake_client.py (renamed from savannaclient/openstack/common/apiclient/fake_client.py) | 2 | ||||
-rw-r--r-- | saharaclient/openstack/common/cliutils.py (renamed from savannaclient/openstack/common/cliutils.py) | 8 | ||||
-rw-r--r-- | saharaclient/openstack/common/gettextutils.py (renamed from savannaclient/openstack/common/gettextutils.py) | 14 | ||||
-rw-r--r-- | saharaclient/openstack/common/importutils.py (renamed from savannaclient/openstack/common/importutils.py) | 2 | ||||
-rw-r--r-- | saharaclient/openstack/common/strutils.py (renamed from savannaclient/openstack/common/strutils.py) | 2 | ||||
-rw-r--r-- | saharaclient/openstack/common/uuidutils.py (renamed from savannaclient/openstack/common/uuidutils.py) | 0 | ||||
-rw-r--r-- | saharaclient/shell.py | 765 | ||||
-rw-r--r-- | saharaclient/tests/__init__.py | 0 | ||||
-rw-r--r-- | saharaclient/tests/nova/__init__.py | 0 | ||||
-rw-r--r-- | saharaclient/tests/nova/test_shell.py (renamed from savannaclient/tests/nova/test_shell.py) | 14 | ||||
-rw-r--r-- | saharaclient/tests/nova/utils.py (renamed from savannaclient/tests/nova/utils.py) | 0 | ||||
-rw-r--r-- | saharaclient/tests/test_resource.py (renamed from savannaclient/tests/test_resource.py) | 2 | ||||
-rw-r--r-- | saharaclient/version.py (renamed from savannaclient/version.py) | 0 | ||||
-rw-r--r-- | savannaclient/api/__init__.py | 1 | ||||
-rw-r--r-- | savannaclient/client.py | 30 | ||||
-rw-r--r-- | savannaclient/openstack/common/__init__.py | 2 | ||||
-rw-r--r-- | savannaclient/shell.py | 766 | ||||
-rw-r--r-- | setup.cfg | 7 |
52 files changed, 880 insertions, 879 deletions
diff --git a/.testr.conf b/.testr.conf index 9c4a212..b72b987 100755 --- a/.testr.conf +++ b/.testr.conf @@ -2,6 +2,6 @@ test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ - ${PYTHON:-python} -m subunit.run discover savannaclient $LISTOPT $IDOPTION + ${PYTHON:-python} -m subunit.run discover saharaclient $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--list diff --git a/doc/source/conf.py b/doc/source/conf.py index 9b55f48..d65da06 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -25,7 +25,7 @@ on_rtd = os.environ.get('READTHEDOCS', None) == 'True' # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) -sys.path.insert(0, os.path.abspath('../../savannaclient')) +sys.path.insert(0, os.path.abspath('../../saharaclient')) sys.path.append(os.path.abspath('..')) sys.path.append(os.path.abspath('../bin')) @@ -55,7 +55,7 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'Savanna Client' +project = u'Sahara Client' copyright = u'2013, OpenStack Foundation' # The version info for the project you're documenting, acts as replacement for @@ -63,10 +63,10 @@ copyright = u'2013, OpenStack Foundation' # built documents. # # Version info -from savannaclient.version import version_info as savannaclient_version -release = savannaclient_version.release_string() +from saharaclient.version import version_info as saharaclient_version +release = saharaclient_version.release_string() # The short X.Y version. -version = savannaclient_version.version_string() +version = saharaclient_version.version_string() # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -122,7 +122,7 @@ if on_rtd: # The name for this set of Sphinx documents. If None, it defaults to # "<project> v<release> documentation". -html_title = 'Savanna Client' +html_title = 'Sahara Client' # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None @@ -189,7 +189,7 @@ html_sidebars = { #html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'SavannaClientDoc' +htmlhelp_basename = 'SaharaClientDoc' # -- Options for LaTeX output -------------------------------------------------- @@ -208,7 +208,7 @@ latex_elements = { # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'savannaclientdoc.tex', u'Savanna Client', + ('index', 'saharaclientdoc.tex', u'Sahara Client', u'OpenStack Foundation', 'manual'), ] @@ -238,7 +238,7 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'savannaclient', u'Savanna Client', + ('index', 'saharaclient', u'Sahara Client', [u'OpenStack Foundation'], 1) ] @@ -252,8 +252,8 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'Savanna Client', u'Savanna Client', - u'OpenStack Foundation', 'Savanna Client', 'Savanna Client', + ('index', 'Sahara Client', u'Sahara Client', + u'OpenStack Foundation', 'Sahara Client', 'Sahara Client', 'Miscellaneous'), ] diff --git a/openstack-common.conf b/openstack-common.conf index 305a32c..974fdb5 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -1,5 +1,5 @@ [DEFAULT] -base=savannaclient +base=saharaclient module=apiclient.exceptions module=importutils diff --git a/run_tests.sh b/run_tests.sh index e0f37e9..31a67b7 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -79,7 +79,7 @@ function run_tests { if [ "x$testrargs" = "x" ]; then testrargs="^(?!.*test_coverage_ext).*$" fi - export PYTHON="${wrapper} coverage run --source savannaclient --parallel-mode" + export PYTHON="${wrapper} coverage run --source saharaclient --parallel-mode" fi # Just run the test suites in current environment set +e @@ -160,5 +160,5 @@ fi if [ $coverage -eq 1 ]; then echo "Generating coverage report in covhtml/" ${wrapper} coverage combine - ${wrapper} coverage html --include='savannaclient/*' --omit='savannaclient/openstack/common/*' -d covhtml -i + ${wrapper} coverage html --include='saharaclient/*' --omit='saharaclient/openstack/common/*' -d covhtml -i fi diff --git a/savannaclient/nova/__init__.py b/saharaclient/api/__init__.py index e69de29..e69de29 100644 --- a/savannaclient/nova/__init__.py +++ b/saharaclient/api/__init__.py diff --git a/savannaclient/api/base.py b/saharaclient/api/base.py index cf4c493..cf4c493 100644 --- a/savannaclient/api/base.py +++ b/saharaclient/api/base.py diff --git a/savannaclient/api/client.py b/saharaclient/api/client.py index 9e5f863..bbb701b 100644 --- a/savannaclient/api/client.py +++ b/saharaclient/api/client.py @@ -16,17 +16,17 @@ from keystoneclient.v2_0 import client as keystone_client_v2 from keystoneclient.v3 import client as keystone_client_v3 -from savannaclient.api import cluster_templates -from savannaclient.api import clusters -from savannaclient.api import data_sources -from savannaclient.api import httpclient -from savannaclient.api import images -from savannaclient.api import job_binaries -from savannaclient.api import job_binary_internals -from savannaclient.api import job_executions -from savannaclient.api import jobs -from savannaclient.api import node_group_templates -from savannaclient.api import plugins +from saharaclient.api import cluster_templates +from saharaclient.api import clusters +from saharaclient.api import data_sources +from saharaclient.api import httpclient +from saharaclient.api import images +from saharaclient.api import job_binaries +from saharaclient.api import job_binary_internals +from saharaclient.api import job_executions +from saharaclient.api import jobs +from saharaclient.api import node_group_templates +from saharaclient.api import plugins class Client(object): @@ -60,7 +60,7 @@ class Client(object): savanna_catalog_url = endpoint break if not savanna_catalog_url: - raise RuntimeError("Could not find Savanna endpoint in catalog") + raise RuntimeError("Could not find Sahara endpoint in catalog") self.client = httpclient.HTTPClient(savanna_catalog_url, input_auth_token) diff --git a/savannaclient/api/cluster_templates.py b/saharaclient/api/cluster_templates.py index e51cf99..f9ca583 100644 --- a/savannaclient/api/cluster_templates.py +++ b/saharaclient/api/cluster_templates.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from savannaclient.api import base +from saharaclient.api import base class ClusterTemplate(base.Resource): diff --git a/savannaclient/api/clusters.py b/saharaclient/api/clusters.py index a3fe556..ec9a822 100644 --- a/savannaclient/api/clusters.py +++ b/saharaclient/api/clusters.py @@ -15,7 +15,7 @@ import six -from savannaclient.api import base +from saharaclient.api import base class Cluster(base.Resource): diff --git a/savannaclient/api/data_sources.py b/saharaclient/api/data_sources.py index 3fc9808..7ba0059 100644 --- a/savannaclient/api/data_sources.py +++ b/saharaclient/api/data_sources.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from savannaclient.api import base +from saharaclient.api import base class DataSources(base.Resource): diff --git a/savannaclient/api/helpers.py b/saharaclient/api/helpers.py index 104d65a..79495c9 100644 --- a/savannaclient/api/helpers.py +++ b/saharaclient/api/helpers.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from savannaclient.api import parameters as params +from saharaclient.api import parameters as params class Helpers(object): diff --git a/savannaclient/api/httpclient.py b/saharaclient/api/httpclient.py index 946e9c3..946e9c3 100644 --- a/savannaclient/api/httpclient.py +++ b/saharaclient/api/httpclient.py diff --git a/savannaclient/api/images.py b/saharaclient/api/images.py index 6ebfae6..a705e15 100644 --- a/savannaclient/api/images.py +++ b/saharaclient/api/images.py @@ -15,7 +15,7 @@ import json -from savannaclient.api import base +from saharaclient.api import base class Image(base.Resource): diff --git a/savannaclient/api/job_binaries.py b/saharaclient/api/job_binaries.py index a1dc67e..a1e4b9e 100644 --- a/savannaclient/api/job_binaries.py +++ b/saharaclient/api/job_binaries.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from savannaclient.api import base +from saharaclient.api import base class JobBinaries(base.Resource): diff --git a/savannaclient/api/job_binary_internals.py b/saharaclient/api/job_binary_internals.py index 9515f7b..b90d478 100644 --- a/savannaclient/api/job_binary_internals.py +++ b/saharaclient/api/job_binary_internals.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from savannaclient.api import base +from saharaclient.api import base class JobBinaryInternal(base.Resource): diff --git a/savannaclient/api/job_executions.py b/saharaclient/api/job_executions.py index 70f43db..68ef4e6 100644 --- a/savannaclient/api/job_executions.py +++ b/saharaclient/api/job_executions.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from savannaclient.api import base +from saharaclient.api import base class JobExecution(base.Resource): diff --git a/savannaclient/api/jobs.py b/saharaclient/api/jobs.py index d230315..d3231eb 100644 --- a/savannaclient/api/jobs.py +++ b/saharaclient/api/jobs.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from savannaclient.api import base +from saharaclient.api import base class Job(base.Resource): diff --git a/savannaclient/api/node_group_templates.py b/saharaclient/api/node_group_templates.py index 2c38897..f9ae36a 100644 --- a/savannaclient/api/node_group_templates.py +++ b/saharaclient/api/node_group_templates.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from savannaclient.api import base +from saharaclient.api import base class NodeGroupTemplate(base.Resource): diff --git a/savannaclient/api/parameters.py b/saharaclient/api/parameters.py index 4575b56..4575b56 100644 --- a/savannaclient/api/parameters.py +++ b/saharaclient/api/parameters.py diff --git a/savannaclient/api/plugins.py b/saharaclient/api/plugins.py index 1efffc2..967da39 100644 --- a/savannaclient/api/plugins.py +++ b/saharaclient/api/plugins.py @@ -15,7 +15,7 @@ from six.moves.urllib import parse as urlparse -from savannaclient.api import base +from saharaclient.api import base class Plugin(base.Resource): diff --git a/savannaclient/api/shell.py b/saharaclient/api/shell.py index 162ad08..20f2269 100644 --- a/savannaclient/api/shell.py +++ b/saharaclient/api/shell.py @@ -17,8 +17,8 @@ import argparse import datetime import inspect import json -from savannaclient.nova import utils -from savannaclient.openstack.common.apiclient import exceptions +from saharaclient.nova import utils +from saharaclient.openstack.common.apiclient import exceptions import sys @@ -121,7 +121,7 @@ def do_plugin_list(cs, args): metavar='<plugin>', required=True, help='Name of the plugin.') -# TODO(mattf) - savannaclient does not support query w/ version +# TODO(mattf) - saharaclient does not support query w/ version #@utils.arg('--version', # metavar='<version>', # help='Optional version') diff --git a/saharaclient/client.py b/saharaclient/client.py index 80af29d..2af15ca 100644 --- a/saharaclient/client.py +++ b/saharaclient/client.py @@ -13,7 +13,33 @@ # See the License for the specific language governing permissions and # limitations under the License. -from savannaclient import client as savannaclient +from saharaclient.openstack.common import importutils -Client = savannaclient.Client +class UnsupportedVersion(Exception): + """Indicates that the user is trying to use an unsupported + version of the API. + """ + pass + + +def get_client_class(version): + version_map = { + '1.0': 'saharaclient.api.client.Client', + '1.1': 'saharaclient.api.client.Client', + } + try: + client_path = version_map[str(version)] + except (KeyError, ValueError): + supported_versions = ''.join(version_map.keys()) + msg = ("Invalid client version '%(version)s'; must be one of: " + "%(versions)s") % {'version': version, + 'versions': supported_versions} + raise UnsupportedVersion(msg) + + return importutils.import_class(client_path) + + +def Client(version, *args, **kwargs): + client_class = get_client_class(version) + return client_class(*args, **kwargs) diff --git a/savannaclient/openstack/__init__.py b/saharaclient/nova/__init__.py index e69de29..e69de29 100644 --- a/savannaclient/openstack/__init__.py +++ b/saharaclient/nova/__init__.py diff --git a/savannaclient/nova/auth_plugin.py b/saharaclient/nova/auth_plugin.py index 518676f..aa0dca3 100644 --- a/savannaclient/nova/auth_plugin.py +++ b/saharaclient/nova/auth_plugin.py @@ -19,8 +19,8 @@ import pkg_resources import six -from savannaclient.nova import utils -from savannaclient.openstack.common.apiclient import exceptions +from saharaclient.nova import utils +from saharaclient.openstack.common.apiclient import exceptions logger = logging.getLogger(__name__) diff --git a/savannaclient/nova/base.py b/saharaclient/nova/base.py index 12b3467..9667b8d 100644 --- a/savannaclient/nova/base.py +++ b/saharaclient/nova/base.py @@ -29,9 +29,9 @@ import threading import six -from savannaclient.nova import utils -from savannaclient.openstack.common.apiclient import exceptions -from savannaclient.openstack.common import strutils +from saharaclient.nova import utils +from saharaclient.openstack.common.apiclient import exceptions +from saharaclient.openstack.common import strutils def getid(obj): diff --git a/savannaclient/nova/extension.py b/saharaclient/nova/extension.py index 4cb178b..9a292dc 100644 --- a/savannaclient/nova/extension.py +++ b/saharaclient/nova/extension.py @@ -13,8 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. -from savannaclient.nova import base -from savannaclient.nova import utils +from saharaclient.nova import base +from saharaclient.nova import utils class Extension(utils.HookableMixin): diff --git a/savannaclient/nova/utils.py b/saharaclient/nova/utils.py index d9eb0c7..8630704 100644 --- a/savannaclient/nova/utils.py +++ b/saharaclient/nova/utils.py @@ -22,8 +22,8 @@ import uuid import prettytable import six -from savannaclient.openstack.common.apiclient import exceptions -from savannaclient.openstack.common import strutils +from saharaclient.openstack.common.apiclient import exceptions +from saharaclient.openstack.common import strutils def arg(*args, **kwargs): diff --git a/savannaclient/openstack/common/apiclient/__init__.py b/saharaclient/openstack/__init__.py index e69de29..e69de29 100644 --- a/savannaclient/openstack/common/apiclient/__init__.py +++ b/saharaclient/openstack/__init__.py diff --git a/savannaclient/tests/__init__.py b/saharaclient/openstack/common/__init__.py index e69de29..e69de29 100644 --- a/savannaclient/tests/__init__.py +++ b/saharaclient/openstack/common/__init__.py diff --git a/savannaclient/tests/nova/__init__.py b/saharaclient/openstack/common/apiclient/__init__.py index e69de29..e69de29 100644 --- a/savannaclient/tests/nova/__init__.py +++ b/saharaclient/openstack/common/apiclient/__init__.py diff --git a/savannaclient/openstack/common/apiclient/auth.py b/saharaclient/openstack/common/apiclient/auth.py index 2f91d66..a4184b7 100644 --- a/savannaclient/openstack/common/apiclient/auth.py +++ b/saharaclient/openstack/common/apiclient/auth.py @@ -24,7 +24,7 @@ import os import six from stevedore import extension -from savannaclient.openstack.common.apiclient import exceptions +from saharaclient.openstack.common.apiclient import exceptions _discovered_plugins = {} @@ -41,7 +41,7 @@ def discover_auth_systems(): def add_plugin(ext): _discovered_plugins[ext.name] = ext.plugin - ep_namespace = "savannaclient.openstack.common.apiclient.auth" + ep_namespace = "saharaclient.openstack.common.apiclient.auth" mgr = extension.ExtensionManager(ep_namespace) mgr.map(add_plugin) diff --git a/savannaclient/openstack/common/apiclient/base.py b/saharaclient/openstack/common/apiclient/base.py index cf12373..2301cf3 100644 --- a/savannaclient/openstack/common/apiclient/base.py +++ b/saharaclient/openstack/common/apiclient/base.py @@ -29,8 +29,8 @@ import copy import six from six.moves.urllib import parse -from savannaclient.openstack.common.apiclient import exceptions -from savannaclient.openstack.common import strutils +from saharaclient.openstack.common.apiclient import exceptions +from saharaclient.openstack.common import strutils def getid(obj): diff --git a/savannaclient/openstack/common/apiclient/client.py b/saharaclient/openstack/common/apiclient/client.py index a1d81b5..787fde4 100644 --- a/savannaclient/openstack/common/apiclient/client.py +++ b/saharaclient/openstack/common/apiclient/client.py @@ -35,8 +35,8 @@ except ImportError: import requests -from savannaclient.openstack.common.apiclient import exceptions -from savannaclient.openstack.common import importutils +from saharaclient.openstack.common.apiclient import exceptions +from saharaclient.openstack.common import importutils _logger = logging.getLogger(__name__) @@ -60,7 +60,7 @@ class HTTPClient(object): into terminal and send the same request with curl. """ - user_agent = "savannaclient.openstack.common.apiclient" + user_agent = "saharaclient.openstack.common.apiclient" def __init__(self, auth_plugin, diff --git a/savannaclient/openstack/common/apiclient/exceptions.py b/saharaclient/openstack/common/apiclient/exceptions.py index ada1344..ada1344 100644 --- a/savannaclient/openstack/common/apiclient/exceptions.py +++ b/saharaclient/openstack/common/apiclient/exceptions.py diff --git a/savannaclient/openstack/common/apiclient/fake_client.py b/saharaclient/openstack/common/apiclient/fake_client.py index 959d508..09c1971 100644 --- a/savannaclient/openstack/common/apiclient/fake_client.py +++ b/saharaclient/openstack/common/apiclient/fake_client.py @@ -30,7 +30,7 @@ import requests import six from six.moves.urllib import parse -from savannaclient.openstack.common.apiclient import client +from saharaclient.openstack.common.apiclient import client def assert_has_keys(dct, required=[], optional=[]): diff --git a/savannaclient/openstack/common/cliutils.py b/saharaclient/openstack/common/cliutils.py index 33191e1..736a9e6 100644 --- a/savannaclient/openstack/common/cliutils.py +++ b/saharaclient/openstack/common/cliutils.py @@ -28,10 +28,10 @@ import prettytable import six from six import moves -from savannaclient.openstack.common.apiclient import exceptions -from savannaclient.openstack.common.gettextutils import _ -from savannaclient.openstack.common import strutils -from savannaclient.openstack.common import uuidutils +from saharaclient.openstack.common.apiclient import exceptions +from saharaclient.openstack.common.gettextutils import _ +from saharaclient.openstack.common import strutils +from saharaclient.openstack.common import uuidutils def validate_args(fn, *args, **kwargs): diff --git a/savannaclient/openstack/common/gettextutils.py b/saharaclient/openstack/common/gettextutils.py index 04c373e..7173789 100644 --- a/savannaclient/openstack/common/gettextutils.py +++ b/saharaclient/openstack/common/gettextutils.py @@ -19,7 +19,7 @@ gettext for openstack-common modules. Usual usage in an openstack.common module: - from savannaclient.openstack.common.gettextutils import _ + from saharaclient.openstack.common.gettextutils import _ """ import copy @@ -33,15 +33,15 @@ import re from babel import localedata import six -_localedir = os.environ.get('savannaclient'.upper() + '_LOCALEDIR') -_t = gettext.translation('savannaclient', localedir=_localedir, fallback=True) +_localedir = os.environ.get('saharaclient'.upper() + '_LOCALEDIR') +_t = gettext.translation('saharaclient', localedir=_localedir, fallback=True) # We use separate translation catalogs for each log level, so set up a # mapping between the log level name and the translator. The domain # for the log level is project_name + "-log-" + log_level so messages # for each level end up in their own catalog. _t_log_levels = dict( - (level, gettext.translation('savannaclient' + '-log-' + level, + (level, gettext.translation('saharaclient' + '-log-' + level, localedir=_localedir, fallback=True)) for level in ['info', 'warning', 'error', 'critical'] @@ -65,7 +65,7 @@ def enable_lazy(): def _(msg): if USE_LAZY: - return Message(msg, domain='savannaclient') + return Message(msg, domain='saharaclient') else: if six.PY3: return _t.gettext(msg) @@ -76,7 +76,7 @@ def _log_translation(msg, level): """Build a single translation of a log message """ if USE_LAZY: - return Message(msg, domain='savannaclient' + '-log-' + level) + return Message(msg, domain='saharaclient' + '-log-' + level) else: translator = _t_log_levels[level] if six.PY3: @@ -153,7 +153,7 @@ class Message(six.text_type): """ def __new__(cls, msgid, msgtext=None, params=None, - domain='savannaclient', *args): + domain='saharaclient', *args): """Create a new Message object. In order for translation to work gettext requires a message ID, this diff --git a/savannaclient/openstack/common/importutils.py b/saharaclient/openstack/common/importutils.py index 9390854..a0e6677 100644 --- a/savannaclient/openstack/common/importutils.py +++ b/saharaclient/openstack/common/importutils.py @@ -59,7 +59,7 @@ def import_module(import_str): def import_versioned_module(version, submodule=None): - module = 'savannaclient.v%s' % version + module = 'saharaclient.v%s' % version if submodule: module = '.'.join((module, submodule)) return import_module(module) diff --git a/savannaclient/openstack/common/strutils.py b/saharaclient/openstack/common/strutils.py index 5a7ba14..6e90ab8 100644 --- a/savannaclient/openstack/common/strutils.py +++ b/saharaclient/openstack/common/strutils.py @@ -24,7 +24,7 @@ import unicodedata import six -from savannaclient.openstack.common.gettextutils import _ +from saharaclient.openstack.common.gettextutils import _ UNIT_PREFIX_EXPONENT = { diff --git a/savannaclient/openstack/common/uuidutils.py b/saharaclient/openstack/common/uuidutils.py index 234b880..234b880 100644 --- a/savannaclient/openstack/common/uuidutils.py +++ b/saharaclient/openstack/common/uuidutils.py diff --git a/saharaclient/shell.py b/saharaclient/shell.py new file mode 100644 index 0000000..6f0664b --- /dev/null +++ b/saharaclient/shell.py @@ -0,0 +1,765 @@ +# Copyright 2010 Jacob Kaplan-Moss +# Copyright 2011 OpenStack Foundation +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +### +### This code is taken from python-novaclient. Goal is minimal modification. +### + +""" +Command-line interface to the OpenStack Sahara API. +""" + +from __future__ import print_function +import argparse +import getpass +import glob +import imp +import itertools +import logging +import os +import pkgutil +import sys + +import pkg_resources +import six + +HAS_KEYRING = False +all_errors = ValueError +try: + import keyring + HAS_KEYRING = True + try: + if isinstance(keyring.get_keyring(), keyring.backend.GnomeKeyring): + import gnomekeyring + all_errors = (ValueError, + gnomekeyring.IOError, + gnomekeyring.NoKeyringDaemonError) + except Exception: + pass +except ImportError: + pass + +from saharaclient.api import client +from saharaclient.api import shell as shell_api +from saharaclient.nova import auth_plugin as nova_auth_plugin +from saharaclient.nova import extension as nova_extension +from saharaclient.openstack.common.apiclient import exceptions as exc +from saharaclient.openstack.common import cliutils +from saharaclient.openstack.common import strutils + +DEFAULT_API_VERSION = 'api' +DEFAULT_ENDPOINT_TYPE = 'publicURL' +DEFAULT_SERVICE_TYPE = 'data_processing' + +logger = logging.getLogger(__name__) + + +def positive_non_zero_float(text): + if text is None: + return None + try: + value = float(text) + except ValueError: + msg = "%s must be a float" % text + raise argparse.ArgumentTypeError(msg) + if value <= 0: + msg = "%s must be greater than 0" % text + raise argparse.ArgumentTypeError(msg) + return value + + +class SecretsHelper(object): + def __init__(self, args, client): + self.args = args + self.client = client + self.key = None + + def _validate_string(self, text): + if text is None or len(text) == 0: + return False + return True + + def _make_key(self): + if self.key is not None: + return self.key + keys = [ + self.client.auth_url, + self.client.projectid, + self.client.user, + self.client.region_name, + self.client.endpoint_type, + self.client.service_type, + self.client.service_name, + self.client.volume_service_name, + ] + for (index, key) in enumerate(keys): + if key is None: + keys[index] = '?' + else: + keys[index] = str(keys[index]) + self.key = "/".join(keys) + return self.key + + def _prompt_password(self, verify=True): + pw = None + if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty(): + # Check for Ctl-D + try: + while True: + pw1 = getpass.getpass('OS Password: ') + if verify: + pw2 = getpass.getpass('Please verify: ') + else: + pw2 = pw1 + if pw1 == pw2 and self._validate_string(pw1): + pw = pw1 + break + except EOFError: + pass + return pw + + def save(self, auth_token, management_url, tenant_id): + if not HAS_KEYRING or not self.args.os_cache: + return + if auth_token == self.auth_token and \ + management_url == self.management_url: + # Nothing changed.... + return + if not all([management_url, auth_token, tenant_id]): + raise ValueError("Unable to save empty management url/auth token") + value = "|".join([str(auth_token), + str(management_url), + str(tenant_id)]) + keyring.set_password("saharaclient_auth", self._make_key(), value) + + @property + def password(self): + if self._validate_string(self.args.os_password): + return self.args.os_password + verify_pass = \ + strutils.bool_from_string(cliutils.env("OS_VERIFY_PASSWORD")) + return self._prompt_password(verify_pass) + + @property + def management_url(self): + if not HAS_KEYRING or not self.args.os_cache: + return None + management_url = None + try: + block = keyring.get_password('saharaclient_auth', + self._make_key()) + if block: + _token, management_url, _tenant_id = block.split('|', 2) + except all_errors: + pass + return management_url + + @property + def auth_token(self): + # Now is where it gets complicated since we + # want to look into the keyring module, if it + # exists and see if anything was provided in that + # file that we can use. + if not HAS_KEYRING or not self.args.os_cache: + return None + token = None + try: + block = keyring.get_password('saharaclient_auth', + self._make_key()) + if block: + token, _management_url, _tenant_id = block.split('|', 2) + except all_errors: + pass + return token + + @property + def tenant_id(self): + if not HAS_KEYRING or not self.args.os_cache: + return None + tenant_id = None + try: + block = keyring.get_password('saharaclient_auth', + self._make_key()) + if block: + _token, _management_url, tenant_id = block.split('|', 2) + except all_errors: + pass + return tenant_id + + +class SavannaClientArgumentParser(argparse.ArgumentParser): + + def __init__(self, *args, **kwargs): + super(SavannaClientArgumentParser, self).__init__(*args, **kwargs) + + def error(self, message): + """error(message: string) + + Prints a usage message incorporating the message to stderr and + exits. + """ + self.print_usage(sys.stderr) + #FIXME(lzyeval): if changes occur in argparse.ArgParser._check_value + choose_from = ' (choose from' + progparts = self.prog.partition(' ') + self.exit(2, "error: %(errmsg)s\nTry '%(mainp)s help %(subp)s'" + " for more information.\n" % + {'errmsg': message.split(choose_from)[0], + 'mainp': progparts[0], + 'subp': progparts[2]}) + + +class OpenStackSavannaShell(object): + + def get_base_parser(self): + parser = SavannaClientArgumentParser( + prog='sahara', + description=__doc__.strip(), + epilog='See "sahara help COMMAND" ' + 'for help on a specific command.', + add_help=False, + formatter_class=OpenStackHelpFormatter, + ) + + # Global arguments + parser.add_argument('-h', '--help', + action='store_true', + help=argparse.SUPPRESS) + +# NA for Savanna +# parser.add_argument('--version', +# action='version', +# version=saharaclient.__version__) + + parser.add_argument('--debug', + default=False, + action='store_true', + help="Print debugging output.") + + parser.add_argument('--os-cache', + default=strutils.bool_from_string( + cliutils.env('OS_CACHE', default=False)), + action='store_true', + help="Use the auth token cache. Defaults to False " + "if env[OS_CACHE] is not set.") + +# TODO(mattf) - add get_timings support to Client +# parser.add_argument('--timings', +# default=False, +# action='store_true', +# help="Print call timing info") + +# TODO(mattf) - use timeout +# parser.add_argument('--timeout', +# default=600, +# metavar='<seconds>', +# type=positive_non_zero_float, +# help="Set HTTP call timeout (in seconds)") + + parser.add_argument('--os-username', + metavar='<auth-user-name>', + default=cliutils.env('OS_USERNAME', + 'SAHARA_USERNAME'), + help='Defaults to env[OS_USERNAME].') + parser.add_argument('--os_username', + help=argparse.SUPPRESS) + + parser.add_argument('--os-password', + metavar='<auth-password>', + default=cliutils.env('OS_PASSWORD', + 'SAHARA_PASSWORD'), + help='Defaults to env[OS_PASSWORD].') + parser.add_argument('--os_password', + help=argparse.SUPPRESS) + + parser.add_argument('--os-tenant-name', + metavar='<auth-tenant-name>', + default=cliutils.env('OS_TENANT_NAME', + 'SAHARA_PROJECT_ID'), + help='Defaults to env[OS_TENANT_NAME].') + parser.add_argument('--os_tenant_name', + help=argparse.SUPPRESS) + + parser.add_argument('--os-tenant-id', + metavar='<auth-tenant-id>', + default=cliutils.env('OS_TENANT_ID'), + help='Defaults to env[OS_TENANT_ID].') + + parser.add_argument('--os-auth-url', + metavar='<auth-url>', + default=cliutils.env('OS_AUTH_URL', 'SAHARA_URL'), + help='Defaults to env[OS_AUTH_URL].') + parser.add_argument('--os_auth_url', + help=argparse.SUPPRESS) + +# NA for Savanna +# parser.add_argument('--os-region-name', +# metavar='<region-name>', +# default=utils.env('OS_REGION_NAME', 'SAHARA_REGION_NAME'), +# help='Defaults to env[OS_REGION_NAME].') +# parser.add_argument('--os_region_name', +# help=argparse.SUPPRESS) + + parser.add_argument('--os-auth-system', + metavar='<auth-system>', + default=cliutils.env('OS_AUTH_SYSTEM'), + help='Defaults to env[OS_AUTH_SYSTEM].') + parser.add_argument('--os_auth_system', + help=argparse.SUPPRESS) + + parser.add_argument('--service-type', + metavar='<service-type>', + help='Defaults to data_processing for all ' + 'actions.') + parser.add_argument('--service_type', + help=argparse.SUPPRESS) + +# NA for Savanna +# parser.add_argument('--service-name', +# metavar='<service-name>', +# default=utils.env('SAHARA_SERVICE_NAME'), +# help='Defaults to env[SAHARA_SERVICE_NAME]') +# parser.add_argument('--service_name', +# help=argparse.SUPPRESS) + +# NA for Savanna +# parser.add_argument('--volume-service-name', +# metavar='<volume-service-name>', +# default=utils.env('NOVA_VOLUME_SERVICE_NAME'), +# help='Defaults to env[NOVA_VOLUME_SERVICE_NAME]') +# parser.add_argument('--volume_service_name', +# help=argparse.SUPPRESS) + + parser.add_argument('--endpoint-type', + metavar='<endpoint-type>', + default=cliutils.env( + 'SAHARA_ENDPOINT_TYPE', + default=DEFAULT_ENDPOINT_TYPE), + help='Defaults to env[SAHARA_ENDPOINT_TYPE] or ' + + DEFAULT_ENDPOINT_TYPE + '.') + # NOTE(dtroyer): We can't add --endpoint_type here due to argparse + # thinking usage-list --end is ambiguous; but it + # works fine with only --endpoint-type present + # Go figure. I'm leaving this here for doc purposes. + #parser.add_argument('--endpoint_type', + # help=argparse.SUPPRESS) + + parser.add_argument('--sahara-api-version', + metavar='<sahara-api-ver>', + default=cliutils.env( + 'SAHARA_API_VERSION', + default=DEFAULT_API_VERSION), + help='Accepts "api", ' + 'defaults to env[SAHARA_API_VERSION].') + parser.add_argument('--sahara_api_version', + help=argparse.SUPPRESS) + + parser.add_argument('--os-cacert', + metavar='<ca-certificate>', + default=cliutils.env('OS_CACERT', default=None), + help='Specify a CA bundle file to use in ' + 'verifying a TLS (https) server certificate. ' + 'Defaults to env[OS_CACERT].') + +# NA for Savanna +# parser.add_argument('--insecure', +# default=utils.env('NOVACLIENT_INSECURE', default=False), +# action='store_true', +# help="Explicitly allow novaclient to perform \"insecure\" " +# "SSL (https) requests. The server's certificate will " +# "not be verified against any certificate authorities. " +# "This option should be used with caution.") + + parser.add_argument('--bypass-url', + metavar='<bypass-url>', + default=cliutils.env('BYPASS_URL', default=None), + dest='bypass_url', + help="Use this API endpoint instead of the " + "Service Catalog.") + parser.add_argument('--bypass_url', + help=argparse.SUPPRESS) + + # The auth-system-plugins might require some extra options + nova_auth_plugin.load_auth_system_opts(parser) + + return parser + + def get_subcommand_parser(self, version): + parser = self.get_base_parser() + + self.subcommands = {} + subparsers = parser.add_subparsers(metavar='<subcommand>') + + try: + actions_module = { + 'api': shell_api, + }[version] + except KeyError: + actions_module = shell_api + actions_module = shell_api + + self._find_actions(subparsers, actions_module) + self._find_actions(subparsers, self) + + for extension in self.extensions: + self._find_actions(subparsers, extension.module) + + self._add_bash_completion_subparser(subparsers) + + return parser + + def _discover_extensions(self, version): + extensions = [] + for name, module in itertools.chain( + self._discover_via_python_path(), + self._discover_via_contrib_path(version), + self._discover_via_entry_points()): + + extension = nova_extension.Extension(name, module) + extensions.append(extension) + + return extensions + + def _discover_via_python_path(self): + for (module_loader, name, _ispkg) in pkgutil.iter_modules(): + if name.endswith('_python_savannaclient_ext'): + if not hasattr(module_loader, 'load_module'): + # Python 2.6 compat: actually get an ImpImporter obj + module_loader = module_loader.find_module(name) + + module = module_loader.load_module(name) + if hasattr(module, 'extension_name'): + name = module.extension_name + + yield name, module + + def _discover_via_contrib_path(self, version): + module_path = os.path.dirname(os.path.abspath(__file__)) + version_str = "v%s" % version.replace('.', '_') + ext_path = os.path.join(module_path, version_str, 'contrib') + ext_glob = os.path.join(ext_path, "*.py") + + for ext_path in glob.iglob(ext_glob): + name = os.path.basename(ext_path)[:-3] + + if name == "__init__": + continue + + module = imp.load_source(name, ext_path) + yield name, module + + def _discover_via_entry_points(self): + for ep in pkg_resources.iter_entry_points('saharaclient.extension'): + name = ep.name + module = ep.load() + + yield name, module + + def _add_bash_completion_subparser(self, subparsers): + subparser = \ + subparsers.add_parser('bash_completion', + add_help=False, + formatter_class=OpenStackHelpFormatter) + self.subcommands['bash_completion'] = subparser + subparser.set_defaults(func=self.do_bash_completion) + + def _find_actions(self, subparsers, actions_module): + for attr in (a for a in dir(actions_module) if a.startswith('do_')): + # I prefer to be hyphen-separated instead of underscores. + command = attr[3:].replace('_', '-') + callback = getattr(actions_module, attr) + desc = callback.__doc__ or '' + action_help = desc.strip() + arguments = getattr(callback, 'arguments', []) + + subparser = \ + subparsers.add_parser(command, + help=action_help, + description=desc, + add_help=False, + formatter_class=OpenStackHelpFormatter) + subparser.add_argument('-h', '--help', + action='help', + help=argparse.SUPPRESS,) + self.subcommands[command] = subparser + for (args, kwargs) in arguments: + subparser.add_argument(*args, **kwargs) + subparser.set_defaults(func=callback) + + def setup_debugging(self, debug): + if not debug: + return + + streamformat = "%(levelname)s (%(module)s:%(lineno)d) %(message)s" + # Set up the root logger to debug so that the submodules can + # print debug messages + logging.basicConfig(level=logging.DEBUG, + format=streamformat) + + def main(self, argv): + + # Parse args once to find version and debug settings + parser = self.get_base_parser() + (options, args) = parser.parse_known_args(argv) + self.setup_debugging(options.debug) + + # Discover available auth plugins + nova_auth_plugin.discover_auth_systems() + + # build available subcommands based on version + self.extensions = \ + self._discover_extensions(options.sahara_api_version) + self._run_extension_hooks('__pre_parse_args__') + + # NOTE(dtroyer): Hackery to handle --endpoint_type due to argparse + # thinking usage-list --end is ambiguous; but it + # works fine with only --endpoint-type present + # Go figure. + if '--endpoint_type' in argv: + spot = argv.index('--endpoint_type') + argv[spot] = '--endpoint-type' + + subcommand_parser = \ + self.get_subcommand_parser(options.sahara_api_version) + self.parser = subcommand_parser + + if options.help or not argv: + subcommand_parser.print_help() + return 0 + + args = subcommand_parser.parse_args(argv) + self._run_extension_hooks('__post_parse_args__', args) + + # Short-circuit and deal with help right away. + if args.func == self.do_help: + self.do_help(args) + return 0 + elif args.func == self.do_bash_completion: + self.do_bash_completion(args) + return 0 + +# (os_username, os_tenant_name, os_tenant_id, os_auth_url, +# os_region_name, os_auth_system, endpoint_type, insecure, +# service_type, service_name, volume_service_name, +# bypass_url, os_cache, cacert) = ( #, timeout) = ( +# args.os_username, +# args.os_tenant_name, args.os_tenant_id, +# args.os_auth_url, +# args.os_region_name, +# args.os_auth_system, +# args.endpoint_type, args.insecure, +# args.service_type, +# args.service_name, args.volume_service_name, +# args.bypass_url, args.os_cache, +# args.os_cacert, args.timeout) + (os_username, os_tenant_name, os_tenant_id, + os_auth_url, os_auth_system, endpoint_type, + service_type, bypass_url, os_cache, + cacert) = \ + (args.os_username, args.os_tenant_name, args.os_tenant_id, + args.os_auth_url, args.os_auth_system, args.endpoint_type, + args.service_type, args.bypass_url, args.os_cache, + args.os_cacert) + + if os_auth_system and os_auth_system != "keystone": + auth_plugin = nova_auth_plugin.load_plugin(os_auth_system) + else: + auth_plugin = None + + # Fetched and set later as needed + os_password = None + + if not endpoint_type: + endpoint_type = DEFAULT_ENDPOINT_TYPE + + if not service_type: + service_type = DEFAULT_SERVICE_TYPE +# NA for Savanna - there is only one service this CLI accesses +# service_type = utils.get_service_type(args.func) or service_type + + #FIXME(usrleon): Here should be restrict for project id same as + # for os_username or os_password but for compatibility it is not. + if not cliutils.isunauthenticated(args.func): + if auth_plugin: + auth_plugin.parse_opts(args) + + if not auth_plugin or not auth_plugin.opts: + if not os_username: + raise exc.CommandError("You must provide a username " + "via either --os-username or " + "env[OS_USERNAME]") + + if not os_tenant_name and not os_tenant_id: + raise exc.CommandError("You must provide a tenant name " + "or tenant id via --os-tenant-name, " + "--os-tenant-id, env[OS_TENANT_NAME] " + "or env[OS_TENANT_ID]") + + if not os_auth_url: + if os_auth_system and os_auth_system != 'keystone': + os_auth_url = auth_plugin.get_auth_url() + + if not os_auth_url: + raise exc.CommandError("You must provide an auth url " + "via either --os-auth-url or " + "env[OS_AUTH_URL] or specify an " + "auth_system which defines a " + "default url with --os-auth-system " + "or env[OS_AUTH_SYSTEM]") + +# NA for Savanna +# if (options.os_compute_api_version and +# options.os_compute_api_version != '1.0'): +# if not os_tenant_name and not os_tenant_id: +# raise exc.CommandError("You must provide a tenant name " +# "or tenant id via --os-tenant-name, " +# "--os-tenant-id, env[OS_TENANT_NAME] " +# "or env[OS_TENANT_ID]") +# +# if not os_auth_url: +# raise exc.CommandError("You must provide an auth url " +# "via either --os-auth-url or env[OS_AUTH_URL]") + +# NOTE: The Sahara client authenticates when you create it. So instead of +# creating here and authenticating later, which is what the novaclient +# does, we just create the client later. + + # Now check for the password/token of which pieces of the + # identifying keyring key can come from the underlying client + if not cliutils.isunauthenticated(args.func): +# NA for Savanna - Client can't be used with SecretsHelper +# helper = SecretsHelper(args, self.cs.client) + if (auth_plugin and auth_plugin.opts and + "os_password" not in auth_plugin.opts): + use_pw = False + else: + use_pw = True + +# tenant_id, auth_token, management_url = (helper.tenant_id, +# helper.auth_token, +# helper.management_url) +# +# if tenant_id and auth_token and management_url: +# self.cs.client.tenant_id = tenant_id +# self.cs.client.auth_token = auth_token +# self.cs.client.management_url = management_url +# # authenticate just sets up some values in this case, no REST +# # calls +# self.cs.authenticate() + if use_pw: + # Auth using token must have failed or not happened + # at all, so now switch to password mode and save + # the token when its gotten... using our keyring + # saver +# os_password = helper.password + os_password = args.os_password + if not os_password: + raise exc.CommandError( + 'Expecting a password provided via either ' + '--os-password, env[OS_PASSWORD], or ' + 'prompted response') +# self.cs.client.password = os_password +# self.cs.client.keyring_saver = helper + +# NA for Savanna +# try: +# if not utils.isunauthenticated(args.func): +# self.cs.authenticate() +# except exc.Unauthorized: +# raise exc.CommandError("Invalid OpenStack Sahara credentials.") +# except exc.AuthorizationFailure: +# raise exc.CommandError("Unable to authorize user") + + self.cs = client.Client(username=os_username, + api_key=os_password, + project_id=os_tenant_id, + project_name=os_tenant_name, + auth_url=os_auth_url, + savanna_url=bypass_url) + + args.func(self.cs, args) + +# TODO(mattf) - add get_timings support to Client +# if args.timings: +# self._dump_timings(self.cs.get_timings()) + + def _dump_timings(self, timings): + class Tyme(object): + def __init__(self, url, seconds): + self.url = url + self.seconds = seconds + results = [Tyme(url, end - start) for url, start, end in timings] + total = 0.0 + for tyme in results: + total += tyme.seconds + results.append(Tyme("Total", total)) + cliutils.print_list(results, ["url", "seconds"], sortby_index=None) + + def _run_extension_hooks(self, hook_type, *args, **kwargs): + """Run hooks for all registered extensions.""" + for extension in self.extensions: + extension.run_hooks(hook_type, *args, **kwargs) + + def do_bash_completion(self, _args): + """Prints all of the commands and options to stdout so that the + sahara.bash_completion script doesn't have to hard code them. + """ + commands = set() + options = set() + for sc_str, sc in self.subcommands.items(): + commands.add(sc_str) + for option in sc._optionals._option_string_actions.keys(): + options.add(option) + + commands.remove('bash-completion') + commands.remove('bash_completion') + print(' '.join(commands | options)) + + @cliutils.arg('command', metavar='<subcommand>', nargs='?', + help='Display help for <subcommand>.') + def do_help(self, args): + """Display help about this program or one of its subcommands.""" + if args.command: + if args.command in self.subcommands: + self.subcommands[args.command].print_help() + else: + raise exc.CommandError("'%s' is not a valid subcommand" % + args.command) + else: + self.parser.print_help() + + +# I'm picky about my shell help. +class OpenStackHelpFormatter(argparse.HelpFormatter): + def start_section(self, heading): + # Title-case the headings + heading = '%s%s' % (heading[0].upper(), heading[1:]) + super(OpenStackHelpFormatter, self).start_section(heading) + + +def main(): + try: + OpenStackSavannaShell().main(map(strutils.safe_decode, sys.argv[1:])) + + except Exception as e: + logger.debug(e, exc_info=1) + print("ERROR: %s" % strutils.safe_encode(six.text_type(e)), + file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/saharaclient/tests/__init__.py b/saharaclient/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/saharaclient/tests/__init__.py diff --git a/saharaclient/tests/nova/__init__.py b/saharaclient/tests/nova/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/saharaclient/tests/nova/__init__.py diff --git a/savannaclient/tests/nova/test_shell.py b/saharaclient/tests/nova/test_shell.py index cf64f24..66581e5 100644 --- a/savannaclient/tests/nova/test_shell.py +++ b/saharaclient/tests/nova/test_shell.py @@ -22,10 +22,10 @@ import fixtures import mock from testtools import matchers -import savannaclient.api.client -from savannaclient.openstack.common.apiclient import exceptions -import savannaclient.shell -from savannaclient.tests.nova import utils +import saharaclient.api.client +from saharaclient.openstack.common.apiclient import exceptions +import saharaclient.shell +from saharaclient.tests.nova import utils FAKE_ENV = {'OS_USERNAME': 'username', 'OS_PASSWORD': 'password', @@ -89,7 +89,7 @@ class ShellTest(utils.TestCase): try: sys.stdout = six.StringIO() sys.stderr = six.StringIO() - _shell = savannaclient.shell.OpenStackSavannaShell() + _shell = saharaclient.shell.OpenStackSavannaShell() _shell.main(argstr.split()) except SystemExit: exc_type, exc_value, exc_traceback = sys.exc_info() @@ -212,7 +212,7 @@ class ShellTest(utils.TestCase): # @mock.patch('sys.stdin', side_effect=mock.MagicMock) # @mock.patch('getpass.getpass', return_value='password') # def test_password(self, mock_getpass, mock_stdin): - @mock.patch('savannaclient.api.client.Client', FakePluginClient) + @mock.patch('saharaclient.api.client.Client', FakePluginClient) def test_password(self): ex = ( '+------+----------+---------------+\n' @@ -272,7 +272,7 @@ class ShellTest(utils.TestCase): # def test_v_unknown_service_type(self, mock_client): # self._test_service_type('unknown', 'compute', mock_client) - @mock.patch('savannaclient.api.client.Client', FakePluginClient) + @mock.patch('saharaclient.api.client.Client', FakePluginClient) def test_image_list(self): ex = ( '+------+------------+----------+------+-------------+\n' diff --git a/savannaclient/tests/nova/utils.py b/saharaclient/tests/nova/utils.py index 7c204d0..7c204d0 100644 --- a/savannaclient/tests/nova/utils.py +++ b/saharaclient/tests/nova/utils.py diff --git a/savannaclient/tests/test_resource.py b/saharaclient/tests/test_resource.py index 4548a60..e0526d8 100644 --- a/savannaclient/tests/test_resource.py +++ b/saharaclient/tests/test_resource.py @@ -15,7 +15,7 @@ import testtools -from savannaclient.api import base +from saharaclient.api import base class ResourceTest(testtools.TestCase): diff --git a/savannaclient/version.py b/saharaclient/version.py index 0291078..0291078 100644 --- a/savannaclient/version.py +++ b/saharaclient/version.py diff --git a/savannaclient/api/__init__.py b/savannaclient/api/__init__.py index e69de29..812595c 100644 --- a/savannaclient/api/__init__.py +++ b/savannaclient/api/__init__.py @@ -0,0 +1 @@ +from saharaclient.api import base as base # noqa diff --git a/savannaclient/client.py b/savannaclient/client.py index 3317f1d..ac52ed8 100644 --- a/savannaclient/client.py +++ b/savannaclient/client.py @@ -13,33 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from savannaclient.openstack.common import importutils +from saharaclient import client as saharaclient -class UnsupportedVersion(Exception): - """Indicates that the user is trying to use an unsupported - version of the API. - """ - pass - - -def get_client_class(version): - version_map = { - '1.0': 'savannaclient.api.client.Client', - '1.1': 'savannaclient.api.client.Client', - } - try: - client_path = version_map[str(version)] - except (KeyError, ValueError): - supported_versions = ''.join(version_map.keys()) - msg = ("Invalid client version '%(version)s'; must be one of: " - "%(versions)s") % {'version': version, - 'versions': supported_versions} - raise UnsupportedVersion(msg) - - return importutils.import_class(client_path) - - -def Client(version, *args, **kwargs): - client_class = get_client_class(version) - return client_class(*args, **kwargs) +Client = saharaclient.Client diff --git a/savannaclient/openstack/common/__init__.py b/savannaclient/openstack/common/__init__.py deleted file mode 100644 index 2a00f3b..0000000 --- a/savannaclient/openstack/common/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -import six -six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox')) diff --git a/savannaclient/shell.py b/savannaclient/shell.py index ededfad..a8bc0f2 100644 --- a/savannaclient/shell.py +++ b/savannaclient/shell.py @@ -1,765 +1 @@ -# Copyright 2010 Jacob Kaplan-Moss -# Copyright 2011 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -### -### This code is taken from python-novaclient. Goal is minimal modification. -### - -""" -Command-line interface to the OpenStack Sahara API. -""" - -from __future__ import print_function -import argparse -import getpass -import glob -import imp -import itertools -import logging -import os -import pkgutil -import sys - -import pkg_resources -import six - -HAS_KEYRING = False -all_errors = ValueError -try: - import keyring - HAS_KEYRING = True - try: - if isinstance(keyring.get_keyring(), keyring.backend.GnomeKeyring): - import gnomekeyring - all_errors = (ValueError, - gnomekeyring.IOError, - gnomekeyring.NoKeyringDaemonError) - except Exception: - pass -except ImportError: - pass - -from savannaclient.api import client -from savannaclient.api import shell as shell_api -from savannaclient.nova import auth_plugin as nova_auth_plugin -from savannaclient.nova import extension as nova_extension -from savannaclient.openstack.common.apiclient import exceptions as exc -from savannaclient.openstack.common import cliutils -from savannaclient.openstack.common import strutils - -DEFAULT_SAHARA_API_VERSION = 'api' -DEFAULT_ENDPOINT_TYPE = 'publicURL' -DEFAULT_SAHARA_SERVICE_TYPE = 'data_processing' - -logger = logging.getLogger(__name__) - - -def positive_non_zero_float(text): - if text is None: - return None - try: - value = float(text) - except ValueError: - msg = "%s must be a float" % text - raise argparse.ArgumentTypeError(msg) - if value <= 0: - msg = "%s must be greater than 0" % text - raise argparse.ArgumentTypeError(msg) - return value - - -class SecretsHelper(object): - def __init__(self, args, client): - self.args = args - self.client = client - self.key = None - - def _validate_string(self, text): - if text is None or len(text) == 0: - return False - return True - - def _make_key(self): - if self.key is not None: - return self.key - keys = [ - self.client.auth_url, - self.client.projectid, - self.client.user, - self.client.region_name, - self.client.endpoint_type, - self.client.service_type, - self.client.service_name, - self.client.volume_service_name, - ] - for (index, key) in enumerate(keys): - if key is None: - keys[index] = '?' - else: - keys[index] = str(keys[index]) - self.key = "/".join(keys) - return self.key - - def _prompt_password(self, verify=True): - pw = None - if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty(): - # Check for Ctl-D - try: - while True: - pw1 = getpass.getpass('OS Password: ') - if verify: - pw2 = getpass.getpass('Please verify: ') - else: - pw2 = pw1 - if pw1 == pw2 and self._validate_string(pw1): - pw = pw1 - break - except EOFError: - pass - return pw - - def save(self, auth_token, management_url, tenant_id): - if not HAS_KEYRING or not self.args.os_cache: - return - if auth_token == self.auth_token and \ - management_url == self.management_url: - # Nothing changed.... - return - if not all([management_url, auth_token, tenant_id]): - raise ValueError("Unable to save empty management url/auth token") - value = "|".join([str(auth_token), - str(management_url), - str(tenant_id)]) - keyring.set_password("savannaclient_auth", self._make_key(), value) - - @property - def password(self): - if self._validate_string(self.args.os_password): - return self.args.os_password - verify_pass = \ - strutils.bool_from_string(cliutils.env("OS_VERIFY_PASSWORD")) - return self._prompt_password(verify_pass) - - @property - def management_url(self): - if not HAS_KEYRING or not self.args.os_cache: - return None - management_url = None - try: - block = keyring.get_password('savannaclient_auth', - self._make_key()) - if block: - _token, management_url, _tenant_id = block.split('|', 2) - except all_errors: - pass - return management_url - - @property - def auth_token(self): - # Now is where it gets complicated since we - # want to look into the keyring module, if it - # exists and see if anything was provided in that - # file that we can use. - if not HAS_KEYRING or not self.args.os_cache: - return None - token = None - try: - block = keyring.get_password('savannaclient_auth', - self._make_key()) - if block: - token, _management_url, _tenant_id = block.split('|', 2) - except all_errors: - pass - return token - - @property - def tenant_id(self): - if not HAS_KEYRING or not self.args.os_cache: - return None - tenant_id = None - try: - block = keyring.get_password('savannaclient_auth', - self._make_key()) - if block: - _token, _management_url, tenant_id = block.split('|', 2) - except all_errors: - pass - return tenant_id - - -class SavannaClientArgumentParser(argparse.ArgumentParser): - - def __init__(self, *args, **kwargs): - super(SavannaClientArgumentParser, self).__init__(*args, **kwargs) - - def error(self, message): - """error(message: string) - - Prints a usage message incorporating the message to stderr and - exits. - """ - self.print_usage(sys.stderr) - #FIXME(lzyeval): if changes occur in argparse.ArgParser._check_value - choose_from = ' (choose from' - progparts = self.prog.partition(' ') - self.exit(2, "error: %(errmsg)s\nTry '%(mainp)s help %(subp)s'" - " for more information.\n" % - {'errmsg': message.split(choose_from)[0], - 'mainp': progparts[0], - 'subp': progparts[2]}) - - -class OpenStackSavannaShell(object): - - def get_base_parser(self): - parser = SavannaClientArgumentParser( - prog='sahara', - description=__doc__.strip(), - epilog='See "sahara help COMMAND" ' - 'for help on a specific command.', - add_help=False, - formatter_class=OpenStackHelpFormatter, - ) - - # Global arguments - parser.add_argument('-h', '--help', - action='store_true', - help=argparse.SUPPRESS) - -# NA for Savanna -# parser.add_argument('--version', -# action='version', -# version=savannaclient.__version__) - - parser.add_argument('--debug', - default=False, - action='store_true', - help="Print debugging output.") - - parser.add_argument('--os-cache', - default=strutils.bool_from_string( - cliutils.env('OS_CACHE', default=False)), - action='store_true', - help="Use the auth token cache. Defaults to False " - "if env[OS_CACHE] is not set.") - -# TODO(mattf) - add get_timings support to Client -# parser.add_argument('--timings', -# default=False, -# action='store_true', -# help="Print call timing info") - -# TODO(mattf) - use timeout -# parser.add_argument('--timeout', -# default=600, -# metavar='<seconds>', -# type=positive_non_zero_float, -# help="Set HTTP call timeout (in seconds)") - - parser.add_argument('--os-username', - metavar='<auth-user-name>', - default=cliutils.env('OS_USERNAME', - 'SAHARA_USERNAME'), - help='Defaults to env[OS_USERNAME].') - parser.add_argument('--os_username', - help=argparse.SUPPRESS) - - parser.add_argument('--os-password', - metavar='<auth-password>', - default=cliutils.env('OS_PASSWORD', - 'SAHARA_PASSWORD'), - help='Defaults to env[OS_PASSWORD].') - parser.add_argument('--os_password', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-name', - metavar='<auth-tenant-name>', - default=cliutils.env('OS_TENANT_NAME', - 'SAHARA_PROJECT_ID'), - help='Defaults to env[OS_TENANT_NAME].') - parser.add_argument('--os_tenant_name', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-id', - metavar='<auth-tenant-id>', - default=cliutils.env('OS_TENANT_ID'), - help='Defaults to env[OS_TENANT_ID].') - - parser.add_argument('--os-auth-url', - metavar='<auth-url>', - default=cliutils.env('OS_AUTH_URL', 'SAHARA_URL'), - help='Defaults to env[OS_AUTH_URL].') - parser.add_argument('--os_auth_url', - help=argparse.SUPPRESS) - -# NA for Savanna -# parser.add_argument('--os-region-name', -# metavar='<region-name>', -# default=utils.env('OS_REGION_NAME', 'SAVANNA_REGION_NAME'), -# help='Defaults to env[OS_REGION_NAME].') -# parser.add_argument('--os_region_name', -# help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-system', - metavar='<auth-system>', - default=cliutils.env('OS_AUTH_SYSTEM'), - help='Defaults to env[OS_AUTH_SYSTEM].') - parser.add_argument('--os_auth_system', - help=argparse.SUPPRESS) - - parser.add_argument('--service-type', - metavar='<service-type>', - help='Defaults to data_processing for all ' - 'actions.') - parser.add_argument('--service_type', - help=argparse.SUPPRESS) - -# NA for Savanna -# parser.add_argument('--service-name', -# metavar='<service-name>', -# default=utils.env('SAVANNA_SERVICE_NAME'), -# help='Defaults to env[SAVANNA_SERVICE_NAME]') -# parser.add_argument('--service_name', -# help=argparse.SUPPRESS) - -# NA for Savanna -# parser.add_argument('--volume-service-name', -# metavar='<volume-service-name>', -# default=utils.env('NOVA_VOLUME_SERVICE_NAME'), -# help='Defaults to env[NOVA_VOLUME_SERVICE_NAME]') -# parser.add_argument('--volume_service_name', -# help=argparse.SUPPRESS) - - parser.add_argument('--endpoint-type', - metavar='<endpoint-type>', - default=cliutils.env( - 'SAHARA_ENDPOINT_TYPE', - default=DEFAULT_ENDPOINT_TYPE), - help='Defaults to env[SAHARA_ENDPOINT_TYPE] or ' - + DEFAULT_ENDPOINT_TYPE + '.') - # NOTE(dtroyer): We can't add --endpoint_type here due to argparse - # thinking usage-list --end is ambiguous; but it - # works fine with only --endpoint-type present - # Go figure. I'm leaving this here for doc purposes. - #parser.add_argument('--endpoint_type', - # help=argparse.SUPPRESS) - - parser.add_argument('--sahara-api-version', - metavar='<sahara-api-ver>', - default=cliutils.env( - 'SAHARA_API_VERSION', - default=DEFAULT_SAHARA_API_VERSION), - help='Accepts "api", ' - 'defaults to env[SAHARA_API_VERSION].') - parser.add_argument('--sahara_api_version', - help=argparse.SUPPRESS) - - parser.add_argument('--os-cacert', - metavar='<ca-certificate>', - default=cliutils.env('OS_CACERT', default=None), - help='Specify a CA bundle file to use in ' - 'verifying a TLS (https) server certificate. ' - 'Defaults to env[OS_CACERT].') - -# NA for Savanna -# parser.add_argument('--insecure', -# default=utils.env('NOVACLIENT_INSECURE', default=False), -# action='store_true', -# help="Explicitly allow novaclient to perform \"insecure\" " -# "SSL (https) requests. The server's certificate will " -# "not be verified against any certificate authorities. " -# "This option should be used with caution.") - - parser.add_argument('--bypass-url', - metavar='<bypass-url>', - default=cliutils.env('BYPASS_URL', default=None), - dest='bypass_url', - help="Use this API endpoint instead of the " - "Service Catalog.") - parser.add_argument('--bypass_url', - help=argparse.SUPPRESS) - - # The auth-system-plugins might require some extra options - nova_auth_plugin.load_auth_system_opts(parser) - - return parser - - def get_subcommand_parser(self, version): - parser = self.get_base_parser() - - self.subcommands = {} - subparsers = parser.add_subparsers(metavar='<subcommand>') - - try: - actions_module = { - 'api': shell_api, - }[version] - except KeyError: - actions_module = shell_api - actions_module = shell_api - - self._find_actions(subparsers, actions_module) - self._find_actions(subparsers, self) - - for extension in self.extensions: - self._find_actions(subparsers, extension.module) - - self._add_bash_completion_subparser(subparsers) - - return parser - - def _discover_extensions(self, version): - extensions = [] - for name, module in itertools.chain( - self._discover_via_python_path(), - self._discover_via_contrib_path(version), - self._discover_via_entry_points()): - - extension = nova_extension.Extension(name, module) - extensions.append(extension) - - return extensions - - def _discover_via_python_path(self): - for (module_loader, name, _ispkg) in pkgutil.iter_modules(): - if name.endswith('_python_savannaclient_ext'): - if not hasattr(module_loader, 'load_module'): - # Python 2.6 compat: actually get an ImpImporter obj - module_loader = module_loader.find_module(name) - - module = module_loader.load_module(name) - if hasattr(module, 'extension_name'): - name = module.extension_name - - yield name, module - - def _discover_via_contrib_path(self, version): - module_path = os.path.dirname(os.path.abspath(__file__)) - version_str = "v%s" % version.replace('.', '_') - ext_path = os.path.join(module_path, version_str, 'contrib') - ext_glob = os.path.join(ext_path, "*.py") - - for ext_path in glob.iglob(ext_glob): - name = os.path.basename(ext_path)[:-3] - - if name == "__init__": - continue - - module = imp.load_source(name, ext_path) - yield name, module - - def _discover_via_entry_points(self): - for ep in pkg_resources.iter_entry_points('savannaclient.extension'): - name = ep.name - module = ep.load() - - yield name, module - - def _add_bash_completion_subparser(self, subparsers): - subparser = \ - subparsers.add_parser('bash_completion', - add_help=False, - formatter_class=OpenStackHelpFormatter) - self.subcommands['bash_completion'] = subparser - subparser.set_defaults(func=self.do_bash_completion) - - def _find_actions(self, subparsers, actions_module): - for attr in (a for a in dir(actions_module) if a.startswith('do_')): - # I prefer to be hyphen-separated instead of underscores. - command = attr[3:].replace('_', '-') - callback = getattr(actions_module, attr) - desc = callback.__doc__ or '' - action_help = desc.strip() - arguments = getattr(callback, 'arguments', []) - - subparser = \ - subparsers.add_parser(command, - help=action_help, - description=desc, - add_help=False, - formatter_class=OpenStackHelpFormatter) - subparser.add_argument('-h', '--help', - action='help', - help=argparse.SUPPRESS,) - self.subcommands[command] = subparser - for (args, kwargs) in arguments: - subparser.add_argument(*args, **kwargs) - subparser.set_defaults(func=callback) - - def setup_debugging(self, debug): - if not debug: - return - - streamformat = "%(levelname)s (%(module)s:%(lineno)d) %(message)s" - # Set up the root logger to debug so that the submodules can - # print debug messages - logging.basicConfig(level=logging.DEBUG, - format=streamformat) - - def main(self, argv): - - # Parse args once to find version and debug settings - parser = self.get_base_parser() - (options, args) = parser.parse_known_args(argv) - self.setup_debugging(options.debug) - - # Discover available auth plugins - nova_auth_plugin.discover_auth_systems() - - # build available subcommands based on version - self.extensions = \ - self._discover_extensions(options.sahara_api_version) - self._run_extension_hooks('__pre_parse_args__') - - # NOTE(dtroyer): Hackery to handle --endpoint_type due to argparse - # thinking usage-list --end is ambiguous; but it - # works fine with only --endpoint-type present - # Go figure. - if '--endpoint_type' in argv: - spot = argv.index('--endpoint_type') - argv[spot] = '--endpoint-type' - - subcommand_parser = \ - self.get_subcommand_parser(options.sahara_api_version) - self.parser = subcommand_parser - - if options.help or not argv: - subcommand_parser.print_help() - return 0 - - args = subcommand_parser.parse_args(argv) - self._run_extension_hooks('__post_parse_args__', args) - - # Short-circuit and deal with help right away. - if args.func == self.do_help: - self.do_help(args) - return 0 - elif args.func == self.do_bash_completion: - self.do_bash_completion(args) - return 0 - -# (os_username, os_tenant_name, os_tenant_id, os_auth_url, -# os_region_name, os_auth_system, endpoint_type, insecure, -# service_type, service_name, volume_service_name, -# bypass_url, os_cache, cacert) = ( #, timeout) = ( -# args.os_username, -# args.os_tenant_name, args.os_tenant_id, -# args.os_auth_url, -# args.os_region_name, -# args.os_auth_system, -# args.endpoint_type, args.insecure, -# args.service_type, -# args.service_name, args.volume_service_name, -# args.bypass_url, args.os_cache, -# args.os_cacert, args.timeout) - (os_username, os_tenant_name, os_tenant_id, - os_auth_url, os_auth_system, endpoint_type, - service_type, bypass_url, os_cache, - cacert) = \ - (args.os_username, args.os_tenant_name, args.os_tenant_id, - args.os_auth_url, args.os_auth_system, args.endpoint_type, - args.service_type, args.bypass_url, args.os_cache, - args.os_cacert) - - if os_auth_system and os_auth_system != "keystone": - auth_plugin = nova_auth_plugin.load_plugin(os_auth_system) - else: - auth_plugin = None - - # Fetched and set later as needed - os_password = None - - if not endpoint_type: - endpoint_type = DEFAULT_ENDPOINT_TYPE - - if not service_type: - service_type = DEFAULT_SAHARA_SERVICE_TYPE -# NA for Savanna - there is only one service this CLI accesses -# service_type = utils.get_service_type(args.func) or service_type - - #FIXME(usrleon): Here should be restrict for project id same as - # for os_username or os_password but for compatibility it is not. - if not cliutils.isunauthenticated(args.func): - if auth_plugin: - auth_plugin.parse_opts(args) - - if not auth_plugin or not auth_plugin.opts: - if not os_username: - raise exc.CommandError("You must provide a username " - "via either --os-username or " - "env[OS_USERNAME]") - - if not os_tenant_name and not os_tenant_id: - raise exc.CommandError("You must provide a tenant name " - "or tenant id via --os-tenant-name, " - "--os-tenant-id, env[OS_TENANT_NAME] " - "or env[OS_TENANT_ID]") - - if not os_auth_url: - if os_auth_system and os_auth_system != 'keystone': - os_auth_url = auth_plugin.get_auth_url() - - if not os_auth_url: - raise exc.CommandError("You must provide an auth url " - "via either --os-auth-url or " - "env[OS_AUTH_URL] or specify an " - "auth_system which defines a " - "default url with --os-auth-system " - "or env[OS_AUTH_SYSTEM]") - -# NA for Savanna -# if (options.os_compute_api_version and -# options.os_compute_api_version != '1.0'): -# if not os_tenant_name and not os_tenant_id: -# raise exc.CommandError("You must provide a tenant name " -# "or tenant id via --os-tenant-name, " -# "--os-tenant-id, env[OS_TENANT_NAME] " -# "or env[OS_TENANT_ID]") -# -# if not os_auth_url: -# raise exc.CommandError("You must provide an auth url " -# "via either --os-auth-url or env[OS_AUTH_URL]") - -# NOTE: The Savanna client authenticates when you create it. So instead of -# creating here and authenticating later, which is what the novaclient -# does, we just create the client later. - - # Now check for the password/token of which pieces of the - # identifying keyring key can come from the underlying client - if not cliutils.isunauthenticated(args.func): -# NA for Savanna - Client can't be used with SecretsHelper -# helper = SecretsHelper(args, self.cs.client) - if (auth_plugin and auth_plugin.opts and - "os_password" not in auth_plugin.opts): - use_pw = False - else: - use_pw = True - -# tenant_id, auth_token, management_url = (helper.tenant_id, -# helper.auth_token, -# helper.management_url) -# -# if tenant_id and auth_token and management_url: -# self.cs.client.tenant_id = tenant_id -# self.cs.client.auth_token = auth_token -# self.cs.client.management_url = management_url -# # authenticate just sets up some values in this case, no REST -# # calls -# self.cs.authenticate() - if use_pw: - # Auth using token must have failed or not happened - # at all, so now switch to password mode and save - # the token when its gotten... using our keyring - # saver -# os_password = helper.password - os_password = args.os_password - if not os_password: - raise exc.CommandError( - 'Expecting a password provided via either ' - '--os-password, env[OS_PASSWORD], or ' - 'prompted response') -# self.cs.client.password = os_password -# self.cs.client.keyring_saver = helper - -# NA for Savanna -# try: -# if not utils.isunauthenticated(args.func): -# self.cs.authenticate() -# except exc.Unauthorized: -# raise exc.CommandError("Invalid OpenStack Savanna credentials.") -# except exc.AuthorizationFailure: -# raise exc.CommandError("Unable to authorize user") - - self.cs = client.Client(username=os_username, - api_key=os_password, - project_id=os_tenant_id, - project_name=os_tenant_name, - auth_url=os_auth_url, - savanna_url=bypass_url) - - args.func(self.cs, args) - -# TODO(mattf) - add get_timings support to Client -# if args.timings: -# self._dump_timings(self.cs.get_timings()) - - def _dump_timings(self, timings): - class Tyme(object): - def __init__(self, url, seconds): - self.url = url - self.seconds = seconds - results = [Tyme(url, end - start) for url, start, end in timings] - total = 0.0 - for tyme in results: - total += tyme.seconds - results.append(Tyme("Total", total)) - cliutils.print_list(results, ["url", "seconds"], sortby_index=None) - - def _run_extension_hooks(self, hook_type, *args, **kwargs): - """Run hooks for all registered extensions.""" - for extension in self.extensions: - extension.run_hooks(hook_type, *args, **kwargs) - - def do_bash_completion(self, _args): - """Prints all of the commands and options to stdout so that the - sahara.bash_completion script doesn't have to hard code them. - """ - commands = set() - options = set() - for sc_str, sc in self.subcommands.items(): - commands.add(sc_str) - for option in sc._optionals._option_string_actions.keys(): - options.add(option) - - commands.remove('bash-completion') - commands.remove('bash_completion') - print(' '.join(commands | options)) - - @cliutils.arg('command', metavar='<subcommand>', nargs='?', - help='Display help for <subcommand>.') - def do_help(self, args): - """Display help about this program or one of its subcommands.""" - if args.command: - if args.command in self.subcommands: - self.subcommands[args.command].print_help() - else: - raise exc.CommandError("'%s' is not a valid subcommand" % - args.command) - else: - self.parser.print_help() - - -# I'm picky about my shell help. -class OpenStackHelpFormatter(argparse.HelpFormatter): - def start_section(self, heading): - # Title-case the headings - heading = '%s%s' % (heading[0].upper(), heading[1:]) - super(OpenStackHelpFormatter, self).start_section(heading) - - -def main(): - try: - OpenStackSavannaShell().main(map(strutils.safe_decode, sys.argv[1:])) - - except Exception as e: - logger.debug(e, exc_info=1) - print("ERROR: %s" % strutils.safe_encode(six.text_type(e)), - file=sys.stderr) - sys.exit(1) - - -if __name__ == "__main__": - main() +from saharaclient.shell import main as main # noqa @@ -1,6 +1,6 @@ [metadata] name = python-savannaclient -summary = Client library for Savanna API +summary = Client library for Sahara API description-file = README.rst license = Apache License, Version 2.0 @@ -28,10 +28,11 @@ packages = [entry_points] console_scripts = - savanna = savannaclient.shell:main + + sahara = saharaclient.shell:main # TODO(slukjanov): remove this code (temp to migrate to the new name) - sahara = savannaclient.shell:main + savanna = saharaclient.shell:main [build_sphinx] all_files = 1 |