summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/common/clientmanager.py23
-rw-r--r--openstackclient/common/quota.py8
-rw-r--r--openstackclient/image/v2/image.py11
-rw-r--r--openstackclient/tests/functional/common/test_quota.py44
-rw-r--r--openstackclient/tests/unit/common/test_quota.py50
-rw-r--r--openstackclient/tests/unit/image/v2/test_image.py22
6 files changed, 151 insertions, 7 deletions
diff --git a/openstackclient/common/clientmanager.py b/openstackclient/common/clientmanager.py
index c1118ad3..66dc880e 100644
--- a/openstackclient/common/clientmanager.py
+++ b/openstackclient/common/clientmanager.py
@@ -15,12 +15,13 @@
"""Manage access to the clients, including authenticating when needed."""
+import importlib
import logging
import sys
from osc_lib import clientmanager
from osc_lib import shell
-import pkg_resources
+import stevedore
LOG = logging.getLogger(__name__)
@@ -143,17 +144,25 @@ class ClientManager(clientmanager.ClientManager):
def get_plugin_modules(group):
"""Find plugin entry points"""
mod_list = []
- for ep in pkg_resources.iter_entry_points(group):
+ mgr = stevedore.ExtensionManager(group)
+ for ep in mgr:
LOG.debug('Found plugin %s', ep.name)
+ # Different versions of stevedore use different
+ # implementations of EntryPoint from other libraries, which
+ # are not API-compatible.
try:
- __import__(ep.module_name)
- except Exception:
+ module_name = ep.entry_point.module_name
+ except AttributeError:
+ module_name = ep.entry_point.module
+
+ try:
+ module = importlib.import_module(module_name)
+ except Exception as err:
sys.stderr.write(
- "WARNING: Failed to import plugin %s.\n" % ep.name)
+ "WARNING: Failed to import plugin %s: %s.\n" % (ep.name, err))
continue
- module = sys.modules[ep.module_name]
mod_list.append(module)
init_func = getattr(module, 'Initialize', None)
if init_func:
@@ -164,7 +173,7 @@ def get_plugin_modules(group):
clientmanager.ClientManager,
module.API_NAME,
clientmanager.ClientCache(
- getattr(sys.modules[ep.module_name], 'make_client', None)
+ getattr(sys.modules[module_name], 'make_client', None)
),
)
return mod_list
diff --git a/openstackclient/common/quota.py b/openstackclient/common/quota.py
index 71b8ea61..11de986b 100644
--- a/openstackclient/common/quota.py
+++ b/openstackclient/common/quota.py
@@ -525,6 +525,11 @@ class SetQuota(common.NetDetectionMixin, command.Command):
metavar='<volume-type>',
help=_('Set quotas for a specific <volume-type>'),
)
+ parser.add_argument(
+ '--force',
+ action='store_true',
+ help=_('Force quota update (only supported by compute)')
+ )
return parser
def take_action(self, parsed_args):
@@ -538,6 +543,9 @@ class SetQuota(common.NetDetectionMixin, command.Command):
if value is not None:
compute_kwargs[k] = value
+ if parsed_args.force:
+ compute_kwargs['force'] = True
+
volume_kwargs = {}
for k, v in VOLUME_QUOTAS.items():
value = getattr(parsed_args, k, None)
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py
index 50a64d4c..029f57a3 100644
--- a/openstackclient/image/v2/image.py
+++ b/openstackclient/image/v2/image.py
@@ -324,6 +324,14 @@ class CreateImage(command.ShowOne):
metavar="<project>",
help=_("Set an alternate project on this image (name or ID)"),
)
+ parser.add_argument(
+ "--import",
+ dest="use_import",
+ action="store_true",
+ help=_(
+ "Force the use of glance image import instead of"
+ " direct upload")
+ )
common.add_project_domain_option_to_parser(parser)
for deadopt in self.deadopts:
parser.add_argument(
@@ -388,6 +396,9 @@ class CreateImage(command.ShowOne):
parsed_args.project_domain,
).id
+ if parsed_args.use_import:
+ kwargs['use_import'] = True
+
# open the file first to ensure any failures are handled before the
# image is created. Get the file name (if it is file, and not stdin)
# for easier further handling.
diff --git a/openstackclient/tests/functional/common/test_quota.py b/openstackclient/tests/functional/common/test_quota.py
index 9c057460..4c2fc0e3 100644
--- a/openstackclient/tests/functional/common/test_quota.py
+++ b/openstackclient/tests/functional/common/test_quota.py
@@ -165,3 +165,47 @@ class QuotaTests(base.TestCase):
# returned attributes
self.assertTrue(cmd_output["key-pairs"] >= 0)
self.assertTrue(cmd_output["snapshots"] >= 0)
+
+ def test_quota_set_force(self):
+ """Test to set instance value by force """
+ json_output = json.loads(self.openstack(
+ 'quota list -f json --detail --compute'
+ ))
+ in_use = limit = None
+ for j in json_output:
+ if j["Resource"] == "instances":
+ in_use = j["In Use"]
+ limit = j["Limit"]
+
+ # Reduce count of in_use
+ in_use = in_use - 1
+ # cannot have negative instances limit
+ if in_use < 0:
+ in_use = 0
+
+ # set the limit by force now
+ self.openstack(
+ 'quota set ' + self.PROJECT_NAME +
+ '--instances ' + str(in_use) + ' --force'
+ )
+ cmd_output = json.loads(self.openstack(
+ 'quota show -f json ' + self.PROJECT_NAME
+ ))
+ self.assertIsNotNone(cmd_output)
+ self.assertEqual(
+ in_use,
+ cmd_output["instances"]
+ )
+
+ # Set instances limit to original limit now
+ self.openstack(
+ 'quota set ' + self.PROJECT_NAME + '--instances ' + str(limit)
+ )
+ cmd_output = json.loads(self.openstack(
+ 'quota show -f json ' + self.PROJECT_NAME
+ ))
+ self.assertIsNotNone(cmd_output)
+ self.assertEqual(
+ limit,
+ cmd_output["instances"]
+ )
diff --git a/openstackclient/tests/unit/common/test_quota.py b/openstackclient/tests/unit/common/test_quota.py
index 3fff062b..6504c5b0 100644
--- a/openstackclient/tests/unit/common/test_quota.py
+++ b/openstackclient/tests/unit/common/test_quota.py
@@ -900,6 +900,56 @@ class TestQuotaSet(TestQuota):
self.assertNotCalled(self.network_mock.update_quota)
self.assertIsNone(result)
+ def test_quota_set_with_force(self):
+ arglist = [
+ '--cores', str(compute_fakes.core_num),
+ '--ram', str(compute_fakes.ram_num),
+ '--instances', str(compute_fakes.instance_num),
+ '--volumes', str(volume_fakes.QUOTA['volumes']),
+ '--subnets', str(network_fakes.QUOTA['subnet']),
+ '--force',
+ self.projects[0].name,
+ ]
+ verifylist = [
+ ('cores', compute_fakes.core_num),
+ ('ram', compute_fakes.ram_num),
+ ('instances', compute_fakes.instance_num),
+ ('volumes', volume_fakes.QUOTA['volumes']),
+ ('subnet', network_fakes.QUOTA['subnet']),
+ ('force', True),
+ ('project', self.projects[0].name),
+ ]
+ self.app.client_manager.network_endpoint_enabled = True
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ kwargs_compute = {
+ 'cores': compute_fakes.core_num,
+ 'ram': compute_fakes.ram_num,
+ 'instances': compute_fakes.instance_num,
+ 'force': True,
+ }
+ kwargs_volume = {
+ 'volumes': volume_fakes.QUOTA['volumes'],
+ }
+ kwargs_network = {
+ 'subnet': network_fakes.QUOTA['subnet'],
+ }
+ self.compute_quotas_mock.update.assert_called_once_with(
+ self.projects[0].id,
+ **kwargs_compute
+ )
+ self.volume_quotas_mock.update.assert_called_once_with(
+ self.projects[0].id,
+ **kwargs_volume
+ )
+ self.network_mock.update_quota.assert_called_once_with(
+ self.projects[0].id,
+ **kwargs_network
+ )
+ self.assertIsNone(result)
+
class TestQuotaShow(TestQuota):
diff --git a/openstackclient/tests/unit/image/v2/test_image.py b/openstackclient/tests/unit/image/v2/test_image.py
index a021cfc7..310f6b76 100644
--- a/openstackclient/tests/unit/image/v2/test_image.py
+++ b/openstackclient/tests/unit/image/v2/test_image.py
@@ -271,6 +271,28 @@ class TestImageCreate(TestImage):
exceptions.CommandError,
self.cmd.take_action, parsed_args)
+ @mock.patch('sys.stdin', side_effect=[None])
+ def test_image_create_import(self, raw_input):
+
+ arglist = [
+ '--import',
+ self.new_image.name,
+ ]
+ verifylist = [
+ ('name', self.new_image.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # ImageManager.create(name=, **)
+ self.client.create_image.assert_called_with(
+ name=self.new_image.name,
+ container_format=image.DEFAULT_CONTAINER_FORMAT,
+ disk_format=image.DEFAULT_DISK_FORMAT,
+ use_import=True
+ )
+
class TestAddProjectToImage(TestImage):