summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kurilin <akurilin@mirantis.com>2015-09-09 14:02:42 +0300
committerAndrey Kurilin <akurilin@mirantis.com>2015-09-10 15:54:38 +0300
commita96e9d57c56e53f4e02701d2ae9f9194bb6e3d5b (patch)
treef85533602fa4df6a5f696b752851d8bcd1092157
parente612205ab850b291a78e539d15923c8716d90158 (diff)
Restrict direct usage of novaclient.v2.client
A lot of project uses incorrect import of versioned novaclient client obj (i.e. novaclient.v2.client.Client). It leads to unability to change interface of such inner classes. This patch updates docs to include warning note and add warning message to `novaclient.v2.client.Client` object. Change-Id: Ifeba391716d3d51d6a75a53cad405e1ec595e27b Related-Bug: #1493576
Notes
Notes (review): Verified+2: Jenkins Code-Review+2: Kevin L. Mitchell <kevin.mitchell@rackspace.com> Workflow+1: Kevin L. Mitchell <kevin.mitchell@rackspace.com> Code-Review+2: John Garbutt <john@johngarbutt.com> Code-Review+1: Alex Xu <hejie.xu@intel.com> Submitted-by: Jenkins Submitted-at: Thu, 10 Sep 2015 18:11:07 +0000 Reviewed-on: https://review.openstack.org/221706 Project: openstack/python-novaclient Branch: refs/heads/master
-rw-r--r--README.rst2
-rw-r--r--doc/source/api.rst37
-rw-r--r--novaclient/client.py25
-rw-r--r--novaclient/v2/client.py52
4 files changed, 69 insertions, 47 deletions
diff --git a/README.rst b/README.rst
index 00a361d..9725cd5 100644
--- a/README.rst
+++ b/README.rst
@@ -1,5 +1,5 @@
1Python bindings to the OpenStack Nova API 1Python bindings to the OpenStack Nova API
2================================================== 2=========================================
3 3
4This is a client for the OpenStack Nova API. There's a Python API (the 4This is a client for the OpenStack Nova API. There's a Python API (the
5``novaclient`` module), and a command-line script (``nova``). Each 5``novaclient`` module), and a command-line script (``nova``). Each
diff --git a/doc/source/api.rst b/doc/source/api.rst
index 8bcb219..ded67ed 100644
--- a/doc/source/api.rst
+++ b/doc/source/api.rst
@@ -1,5 +1,5 @@
1The :mod:`novaclient` Python API 1The :mod:`novaclient` Python API
2================================== 2================================
3 3
4.. module:: novaclient 4.. module:: novaclient
5 :synopsis: A client for the OpenStack Nova API. 5 :synopsis: A client for the OpenStack Nova API.
@@ -14,7 +14,10 @@ First create a client instance with your credentials::
14 >>> from novaclient import client 14 >>> from novaclient import client
15 >>> nova = client.Client(VERSION, USERNAME, PASSWORD, PROJECT_ID, AUTH_URL) 15 >>> nova = client.Client(VERSION, USERNAME, PASSWORD, PROJECT_ID, AUTH_URL)
16 16
17Here ``VERSION`` can be: ``1.1``, ``2``. 17Here ``VERSION`` can be a string or ``novaclient.api_versions.APIVersion`` obj.
18If you prefer string value, you can use ``1.1`` (deprecated now), ``2`` or
19``2.X`` (where X is a microversion).
20
18 21
19Alternatively, you can create a client instance using the keystoneclient 22Alternatively, you can create a client instance using the keystoneclient
20session API:: 23session API::
@@ -23,9 +26,9 @@ session API::
23 >>> from keystoneclient import session 26 >>> from keystoneclient import session
24 >>> from novaclient import client 27 >>> from novaclient import client
25 >>> auth = v2.Password(auth_url=AUTH_URL, 28 >>> auth = v2.Password(auth_url=AUTH_URL,
26 username=USERNAME, 29 ... username=USERNAME,
27 password=PASSWORD, 30 ... password=PASSWORD,
28 tenant_name=PROJECT_ID) 31 ... tenant_name=PROJECT_ID)
29 >>> sess = session.Session(auth=auth) 32 >>> sess = session.Session(auth=auth)
30 >>> nova = client.Client(VERSION, session=sess) 33 >>> nova = client.Client(VERSION, session=sess)
31 34
@@ -33,6 +36,23 @@ For more information on this keystoneclient API, see `Using Sessions`_.
33 36
34.. _Using Sessions: http://docs.openstack.org/developer/python-keystoneclient/using-sessions.html 37.. _Using Sessions: http://docs.openstack.org/developer/python-keystoneclient/using-sessions.html
35 38
39It is also possible to use an instance as a context manager in which case
40there will be a session kept alive for the duration of the with statement::
41
42 >>> from novaclient import client
43 >>> with client.Client(VERSION, USERNAME, PASSWORD,
44 ... PROJECT_ID, AUTH_URL) as nova:
45 ... nova.servers.list()
46 ... nova.flavors.list()
47 ...
48
49It is also possible to have a permanent (process-long) connection pool,
50by passing a connection_pool=True::
51
52 >>> from novaclient import client
53 >>> nova = client.Client(VERSION, USERNAME, PASSWORD, PROJECT_ID,
54 ... AUTH_URL, connection_pool=True)
55
36Then call methods on its managers:: 56Then call methods on its managers::
37 57
38 >>> nova.servers.list() 58 >>> nova.servers.list()
@@ -51,6 +71,13 @@ Then call methods on its managers::
51 >>> nova.servers.create("my-server", flavor=fl) 71 >>> nova.servers.create("my-server", flavor=fl)
52 <Server: my-server> 72 <Server: my-server>
53 73
74.. warning:: Direct initialization of ``novaclient.v2.client.Client`` object
75 can cause you to "shoot yourself in the foot". See launchpad bug-report
76 `1493576`_ for more details.
77
78.. _1493576: https://launchpad.net/bugs/1493576
79
80
54Reference 81Reference
55--------- 82---------
56 83
diff --git a/novaclient/client.py b/novaclient/client.py
index 1592555..f7ac870 100644
--- a/novaclient/client.py
+++ b/novaclient/client.py
@@ -785,6 +785,27 @@ def get_client_class(version):
785 785
786 786
787def Client(version, *args, **kwargs): 787def Client(version, *args, **kwargs):
788 """Initialize client object based on given version.""" 788 """Initialize client object based on given version.
789
790 HOW-TO:
791 The simplest way to create a client instance is initialization with your
792 credentials::
793
794 >>> from novaclient import client
795 >>> nova = client.Client(VERSION, USERNAME, PASSWORD,
796 ... PROJECT_ID, AUTH_URL)
797
798 Here ``VERSION`` can be a string or
799 ``novaclient.api_versions.APIVersion`` obj. If you prefer string value,
800 you can use ``1.1`` (deprecated now), ``2`` or ``2.X``
801 (where X is a microversion).
802
803
804 Alternatively, you can create a client instance using the keystoneclient
805 session API. See "The novaclient Python API" page at
806 python-novaclient's doc.
807 """
789 api_version, client_class = _get_client_class_and_version(version) 808 api_version, client_class = _get_client_class_and_version(version)
790 return client_class(api_version=api_version, *args, **kwargs) 809 kwargs.pop("direct_use", None)
810 return client_class(api_version=api_version, direct_use=False,
811 *args, **kwargs)
diff --git a/novaclient/v2/client.py b/novaclient/v2/client.py
index 1c195d5..d48c062 100644
--- a/novaclient/v2/client.py
+++ b/novaclient/v2/client.py
@@ -14,6 +14,7 @@
14# under the License. 14# under the License.
15 15
16from novaclient import client 16from novaclient import client
17from novaclient.i18n import _LW
17from novaclient.v2 import agents 18from novaclient.v2 import agents
18from novaclient.v2 import aggregates 19from novaclient.v2 import aggregates
19from novaclient.v2 import availability_zones 20from novaclient.v2 import availability_zones
@@ -53,44 +54,8 @@ class Client(object):
53 """ 54 """
54 Top-level object to access the OpenStack Compute API. 55 Top-level object to access the OpenStack Compute API.
55 56
56 Create an instance with your creds:: 57 .. warning:: All scripts and projects should not initialize this class
57 58 directly. It should be done via `novaclient.client.Client` interface.
58 >>> client = Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL)
59
60 Or, alternatively, you can create a client instance using the
61 keystoneclient.session API::
62
63 >>> from keystoneclient.auth.identity import v2
64 >>> from keystoneclient import session
65 >>> from novaclient import client
66 >>> auth = v2.Password(auth_url=AUTH_URL,
67 username=USERNAME,
68 password=PASSWORD,
69 tenant_name=PROJECT_ID)
70 >>> sess = session.Session(auth=auth)
71 >>> nova = client.Client(VERSION, session=sess)
72
73 Then call methods on its managers::
74
75 >>> nova.servers.list()
76 ...
77 >>> nova.flavors.list()
78 ...
79
80 It is also possible to use an instance as a context manager in which
81 case there will be a session kept alive for the duration of the with
82 statement::
83
84 >>> with Client(USERNAME, PASSWORD, PROJECT_ID, AUTH_URL) as client:
85 ... client.servers.list()
86 ... client.flavors.list()
87 ...
88
89 It is also possible to have a permanent (process-long) connection pool,
90 by passing a connection_pool=True::
91
92 >>> client = Client(USERNAME, PASSWORD, PROJECT_ID,
93 ... AUTH_URL, connection_pool=True)
94 """ 59 """
95 60
96 def __init__(self, username=None, api_key=None, project_id=None, 61 def __init__(self, username=None, api_key=None, project_id=None,
@@ -103,7 +68,7 @@ class Client(object):
103 auth_system='keystone', auth_plugin=None, auth_token=None, 68 auth_system='keystone', auth_plugin=None, auth_token=None,
104 cacert=None, tenant_id=None, user_id=None, 69 cacert=None, tenant_id=None, user_id=None,
105 connection_pool=False, session=None, auth=None, 70 connection_pool=False, session=None, auth=None,
106 api_version=None, **kwargs): 71 api_version=None, direct_use=True, **kwargs):
107 """ 72 """
108 :param str username: Username 73 :param str username: Username
109 :param str api_key: API Key 74 :param str api_key: API Key
@@ -136,6 +101,15 @@ class Client(object):
136 :param api_version: Compute API version 101 :param api_version: Compute API version
137 :type api_version: novaclient.api_versions.APIVersion 102 :type api_version: novaclient.api_versions.APIVersion
138 """ 103 """
104 if direct_use:
105 import warnings
106
107 warnings.warn(
108 _LW("'novaclient.v2.client.Client' is not designed to be "
109 "initialized directly. It is inner class of novaclient. "
110 "Please, use 'novaclient.client.Client' instead. "
111 "Related lp bug-report: 1493576"))
112
139 # FIXME(comstud): Rename the api_key argument above when we 113 # FIXME(comstud): Rename the api_key argument above when we
140 # know it's not being used as keyword argument 114 # know it's not being used as keyword argument
141 115