summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/common/command.py42
-rw-r--r--openstackclient/common/utils.py22
-rw-r--r--openstackclient/compute/v2/flavor.py28
-rw-r--r--openstackclient/compute/v2/server.py121
-rw-r--r--openstackclient/image/v1/image.py65
-rw-r--r--openstackclient/image/v2/image.py84
-rw-r--r--openstackclient/network/v2/port.py42
-rw-r--r--openstackclient/tests/common/test_command.py32
-rw-r--r--openstackclient/tests/compute/v2/test_security_group.py45
-rw-r--r--openstackclient/tests/compute/v2/test_security_group_rule.py59
-rw-r--r--openstackclient/tests/compute/v2/test_server.py146
-rw-r--r--openstackclient/tests/image/v1/test_image.py9
-rw-r--r--openstackclient/tests/image/v2/test_image.py63
-rw-r--r--openstackclient/tests/network/v2/fakes.py77
-rw-r--r--openstackclient/tests/network/v2/test_port.py53
15 files changed, 560 insertions, 328 deletions
diff --git a/openstackclient/common/command.py b/openstackclient/common/command.py
new file mode 100644
index 00000000..b8d9fc6f
--- /dev/null
+++ b/openstackclient/common/command.py
@@ -0,0 +1,42 @@
+# Copyright 2016 NEC Corporation
+#
+# 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.
+
+import abc
+import logging
+
+from cliff import command
+from cliff import lister
+from cliff import show
+import six
+
+
+class CommandMeta(abc.ABCMeta):
+ def __new__(mcs, name, bases, cls_dict):
+ if 'log' not in cls_dict:
+ cls_dict['log'] = logging.getLogger(
+ cls_dict['__module__'] + '.' + name)
+ return super(CommandMeta, mcs).__new__(mcs, name, bases, cls_dict)
+
+
+@six.add_metaclass(CommandMeta)
+class Command(command.Command):
+ pass
+
+
+class Lister(Command, lister.Lister):
+ pass
+
+
+class ShowOne(Command, show.ShowOne):
+ pass
diff --git a/openstackclient/common/utils.py b/openstackclient/common/utils.py
index 096c995b..3ae30c8f 100644
--- a/openstackclient/common/utils.py
+++ b/openstackclient/common/utils.py
@@ -26,28 +26,32 @@ from oslo_utils import importutils
from openstackclient.common import exceptions
-def log_method(log, level=logging.DEBUG):
- """Logs a method and its arguments when entered."""
+class log_method(object):
- def decorator(func):
+ def __init__(self, log=None, level=logging.DEBUG):
+ self._log = log
+ self._level = level
+
+ def __call__(self, func):
func_name = func.__name__
+ if not self._log:
+ self._log = logging.getLogger(func.__class__.__name__)
@six.wraps(func)
- def wrapper(self, *args, **kwargs):
- if log.isEnabledFor(level):
+ def wrapper(*args, **kwargs):
+ if self._log.isEnabledFor(self._level):
pretty_args = []
if args:
pretty_args.extend(str(a) for a in args)
if kwargs:
pretty_args.extend(
"%s=%s" % (k, v) for k, v in six.iteritems(kwargs))
- log.log(level, "%s(%s)", func_name, ", ".join(pretty_args))
- return func(self, *args, **kwargs)
+ self._log.log(self._level, "%s(%s)",
+ func_name, ", ".join(pretty_args))
+ return func(*args, **kwargs)
return wrapper
- return decorator
-
def find_resource(manager, name_or_id, **kwargs):
"""Helper for the _find_* methods.
diff --git a/openstackclient/compute/v2/flavor.py b/openstackclient/compute/v2/flavor.py
index b34197e0..1af5fe70 100644
--- a/openstackclient/compute/v2/flavor.py
+++ b/openstackclient/compute/v2/flavor.py
@@ -15,22 +15,16 @@
"""Flavor action implementations"""
-import logging
import six
-from cliff import command
-from cliff import lister
-from cliff import show
-
+from openstackclient.common import command
from openstackclient.common import parseractions
from openstackclient.common import utils
-class CreateFlavor(show.ShowOne):
+class CreateFlavor(command.ShowOne):
"""Create new flavor"""
- log = logging.getLogger(__name__ + ".CreateFlavor")
-
def get_parser(self, prog_name):
parser = super(CreateFlavor, self).get_parser(prog_name)
parser.add_argument(
@@ -128,8 +122,6 @@ class CreateFlavor(show.ShowOne):
class DeleteFlavor(command.Command):
"""Delete flavor"""
- log = logging.getLogger(__name__ + ".DeleteFlavor")
-
def get_parser(self, prog_name):
parser = super(DeleteFlavor, self).get_parser(prog_name)
parser.add_argument(
@@ -147,11 +139,9 @@ class DeleteFlavor(command.Command):
compute_client.flavors.delete(flavor.id)
-class ListFlavor(lister.Lister):
+class ListFlavor(command.Lister):
"""List flavors"""
- log = logging.getLogger(__name__ + ".ListFlavor")
-
def get_parser(self, prog_name):
parser = super(ListFlavor, self).get_parser(prog_name)
public_group = parser.add_mutually_exclusive_group()
@@ -231,11 +221,9 @@ class ListFlavor(lister.Lister):
) for s in data))
-class ShowFlavor(show.ShowOne):
+class ShowFlavor(command.ShowOne):
"""Display flavor details"""
- log = logging.getLogger(__name__ + ".ShowFlavor")
-
def get_parser(self, prog_name):
parser = super(ShowFlavor, self).get_parser(prog_name)
parser.add_argument(
@@ -258,11 +246,9 @@ class ShowFlavor(show.ShowOne):
return zip(*sorted(six.iteritems(flavor)))
-class SetFlavor(show.ShowOne):
+class SetFlavor(command.ShowOne):
"""Set flavor properties"""
- log = logging.getLogger(__name__ + ".SetFlavor")
-
def get_parser(self, prog_name):
parser = super(SetFlavor, self).get_parser(prog_name)
parser.add_argument(
@@ -292,11 +278,9 @@ class SetFlavor(show.ShowOne):
return zip(*sorted(six.iteritems(flavor)))
-class UnsetFlavor(show.ShowOne):
+class UnsetFlavor(command.ShowOne):
"""Unset flavor properties"""
- log = logging.getLogger(__name__ + ".UnsetFlavor")
-
def get_parser(self, prog_name):
parser = super(UnsetFlavor, self).get_parser(prog_name)
parser.add_argument(
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index f5876d4f..b4db6216 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -18,14 +18,11 @@
import argparse
import getpass
import io
-import logging
import os
import six
import sys
-from cliff import command
-from cliff import lister
-from cliff import show
+from openstackclient.common import command
try:
from novaclient.v2 import servers
@@ -173,8 +170,6 @@ def _show_progress(progress):
class AddServerSecurityGroup(command.Command):
"""Add security group to server"""
- log = logging.getLogger(__name__ + '.AddServerSecurityGroup')
-
def get_parser(self, prog_name):
parser = super(AddServerSecurityGroup, self).get_parser(prog_name)
parser.add_argument(
@@ -209,8 +204,6 @@ class AddServerSecurityGroup(command.Command):
class AddServerVolume(command.Command):
"""Add volume to server"""
- log = logging.getLogger(__name__ + '.AddServerVolume')
-
def get_parser(self, prog_name):
parser = super(AddServerVolume, self).get_parser(prog_name)
parser.add_argument(
@@ -252,11 +245,9 @@ class AddServerVolume(command.Command):
)
-class CreateServer(show.ShowOne):
+class CreateServer(command.ShowOne):
"""Create a new server"""
- log = logging.getLogger(__name__ + '.CreateServer')
-
def get_parser(self, prog_name):
parser = super(CreateServer, self).get_parser(prog_name)
parser.add_argument(
@@ -379,7 +370,7 @@ class CreateServer(show.ShowOne):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
volume_client = self.app.client_manager.volume
@@ -556,11 +547,9 @@ class CreateServer(show.ShowOne):
return zip(*sorted(six.iteritems(details)))
-class CreateServerImage(show.ShowOne):
+class CreateServerImage(command.ShowOne):
"""Create a new disk image from a running server"""
- log = logging.getLogger(__name__ + '.CreateServerImage')
-
def get_parser(self, prog_name):
parser = super(CreateServerImage, self).get_parser(prog_name)
parser.add_argument(
@@ -580,7 +569,7 @@ class CreateServerImage(show.ShowOne):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
image_client = self.app.client_manager.image
@@ -622,8 +611,6 @@ class CreateServerImage(show.ShowOne):
class DeleteServer(command.Command):
"""Delete server(s)"""
- log = logging.getLogger(__name__ + '.DeleteServer')
-
def get_parser(self, prog_name):
parser = super(DeleteServer, self).get_parser(prog_name)
parser.add_argument(
@@ -639,7 +626,7 @@ class DeleteServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
for server in parsed_args.server:
@@ -660,11 +647,9 @@ class DeleteServer(command.Command):
raise SystemExit
-class ListServer(lister.Lister):
+class ListServer(command.Lister):
"""List servers"""
- log = logging.getLogger(__name__ + '.ListServer')
-
def get_parser(self, prog_name):
parser = super(ListServer, self).get_parser(prog_name)
parser.add_argument(
@@ -756,7 +741,7 @@ class ListServer(lister.Lister):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
identity_client = self.app.client_manager.identity
@@ -877,8 +862,6 @@ class LockServer(command.Command):
"""Lock server(s). A non-admin user will not be able to execute actions"""
- log = logging.getLogger(__name__ + '.LockServer')
-
def get_parser(self, prog_name):
parser = super(LockServer, self).get_parser(prog_name)
parser.add_argument(
@@ -889,7 +872,7 @@ class LockServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -913,8 +896,6 @@ class LockServer(command.Command):
class MigrateServer(command.Command):
"""Migrate server to different host"""
- log = logging.getLogger(__name__ + '.MigrateServer')
-
def get_parser(self, prog_name):
parser = super(MigrateServer, self).get_parser(prog_name)
parser.add_argument(
@@ -963,7 +944,7 @@ class MigrateServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -996,8 +977,6 @@ class MigrateServer(command.Command):
class PauseServer(command.Command):
"""Pause server(s)"""
- log = logging.getLogger(__name__ + '.PauseServer')
-
def get_parser(self, prog_name):
parser = super(PauseServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1008,7 +987,7 @@ class PauseServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
for server in parsed_args.server:
@@ -1021,8 +1000,6 @@ class PauseServer(command.Command):
class RebootServer(command.Command):
"""Perform a hard or soft server reboot"""
- log = logging.getLogger(__name__ + '.RebootServer')
-
def get_parser(self, prog_name):
parser = super(RebootServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1054,7 +1031,7 @@ class RebootServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
server = utils.find_resource(
@@ -1073,11 +1050,9 @@ class RebootServer(command.Command):
raise SystemExit
-class RebuildServer(show.ShowOne):
+class RebuildServer(command.ShowOne):
"""Rebuild server"""
- log = logging.getLogger(__name__ + '.RebuildServer')
-
def get_parser(self, prog_name):
parser = super(RebuildServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1103,7 +1078,7 @@ class RebuildServer(show.ShowOne):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -1133,8 +1108,6 @@ class RebuildServer(show.ShowOne):
class RemoveServerSecurityGroup(command.Command):
"""Remove security group from server"""
- log = logging.getLogger(__name__ + '.RemoveServerSecurityGroup')
-
def get_parser(self, prog_name):
parser = super(RemoveServerSecurityGroup, self).get_parser(prog_name)
parser.add_argument(
@@ -1169,8 +1142,6 @@ class RemoveServerSecurityGroup(command.Command):
class RemoveServerVolume(command.Command):
"""Remove volume from server"""
- log = logging.getLogger(__name__ + '.RemoveServerVolume')
-
def get_parser(self, prog_name):
parser = super(RemoveServerVolume, self).get_parser(prog_name)
parser.add_argument(
@@ -1206,11 +1177,9 @@ class RemoveServerVolume(command.Command):
)
-class RescueServer(show.ShowOne):
+class RescueServer(command.ShowOne):
"""Put server in rescue mode"""
- log = logging.getLogger(__name__ + '.RescueServer')
-
def get_parser(self, prog_name):
parser = super(RescueServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1220,7 +1189,7 @@ class RescueServer(show.ShowOne):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -1234,8 +1203,6 @@ class RescueServer(show.ShowOne):
class ResizeServer(command.Command):
"""Scale server to a new flavor"""
- log = logging.getLogger(__name__ + '.ResizeServer')
-
def get_parser(self, prog_name):
parser = super(ResizeServer, self).get_parser(prog_name)
phase_group = parser.add_mutually_exclusive_group()
@@ -1266,7 +1233,7 @@ class ResizeServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -1300,8 +1267,6 @@ class ResizeServer(command.Command):
class ResumeServer(command.Command):
"""Resume server(s)"""
- log = logging.getLogger(__name__ + '.ResumeServer')
-
def get_parser(self, prog_name):
parser = super(ResumeServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1312,7 +1277,7 @@ class ResumeServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -1326,8 +1291,6 @@ class ResumeServer(command.Command):
class SetServer(command.Command):
"""Set server properties"""
- log = logging.getLogger(__name__ + '.SetServer')
-
def get_parser(self, prog_name):
parser = super(SetServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1354,7 +1317,7 @@ class SetServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -1385,8 +1348,6 @@ class SetServer(command.Command):
class ShelveServer(command.Command):
"""Shelve server(s)"""
- log = logging.getLogger(__name__ + '.ShelveServer')
-
def get_parser(self, prog_name):
parser = super(ShelveServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1397,7 +1358,7 @@ class ShelveServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
for server in parsed_args.server:
@@ -1407,11 +1368,9 @@ class ShelveServer(command.Command):
).shelve()
-class ShowServer(show.ShowOne):
+class ShowServer(command.ShowOne):
"""Show server details"""
- log = logging.getLogger(__name__ + '.ShowServer')
-
def get_parser(self, prog_name):
parser = super(ShowServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1427,7 +1386,7 @@ class ShowServer(show.ShowOne):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
server = utils.find_resource(compute_client.servers,
@@ -1447,8 +1406,6 @@ class ShowServer(show.ShowOne):
class SshServer(command.Command):
"""Ssh to server"""
- log = logging.getLogger(__name__ + '.SshServer')
-
def get_parser(self, prog_name):
parser = super(SshServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1550,7 +1507,7 @@ class SshServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -1594,8 +1551,6 @@ class SshServer(command.Command):
class StartServer(command.Command):
"""Start server(s)."""
- log = logging.getLogger(__name__ + '.StartServer')
-
def get_parser(self, prog_name):
parser = super(StartServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1606,7 +1561,7 @@ class StartServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
for server in parsed_args.server:
@@ -1619,8 +1574,6 @@ class StartServer(command.Command):
class StopServer(command.Command):
"""Stop server(s)."""
- log = logging.getLogger(__name__ + '.StopServer')
-
def get_parser(self, prog_name):
parser = super(StopServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1631,7 +1584,7 @@ class StopServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
for server in parsed_args.server:
@@ -1644,8 +1597,6 @@ class StopServer(command.Command):
class SuspendServer(command.Command):
"""Suspend server(s)"""
- log = logging.getLogger(__name__ + '.SuspendServer')
-
def get_parser(self, prog_name):
parser = super(SuspendServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1656,7 +1607,7 @@ class SuspendServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -1670,8 +1621,6 @@ class SuspendServer(command.Command):
class UnlockServer(command.Command):
"""Unlock server(s)"""
- log = logging.getLogger(__name__ + '.UnlockServer')
-
def get_parser(self, prog_name):
parser = super(UnlockServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1682,7 +1631,7 @@ class UnlockServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -1696,8 +1645,6 @@ class UnlockServer(command.Command):
class UnpauseServer(command.Command):
"""Unpause server(s)"""
- log = logging.getLogger(__name__ + '.UnpauseServer')
-
def get_parser(self, prog_name):
parser = super(UnpauseServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1708,7 +1655,7 @@ class UnpauseServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -1722,8 +1669,6 @@ class UnpauseServer(command.Command):
class UnrescueServer(command.Command):
"""Restore server from rescue mode"""
- log = logging.getLogger(__name__ + '.UnrescueServer')
-
def get_parser(self, prog_name):
parser = super(UnrescueServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1733,7 +1678,7 @@ class UnrescueServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
@@ -1746,8 +1691,6 @@ class UnrescueServer(command.Command):
class UnsetServer(command.Command):
"""Unset server properties"""
- log = logging.getLogger(__name__ + '.UnsetServer')
-
def get_parser(self, prog_name):
parser = super(UnsetServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1765,7 +1708,7 @@ class UnsetServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
server = utils.find_resource(
@@ -1783,8 +1726,6 @@ class UnsetServer(command.Command):
class UnshelveServer(command.Command):
"""Unshelve server(s)"""
- log = logging.getLogger(__name__ + '.UnshelveServer')
-
def get_parser(self, prog_name):
parser = super(UnshelveServer, self).get_parser(prog_name)
parser.add_argument(
@@ -1795,7 +1736,7 @@ class UnshelveServer(command.Command):
)
return parser
- @utils.log_method(log)
+ @utils.log_method()
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
for server in parsed_args.server:
diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py
index 0382501e..c18f3fc7 100644
--- a/openstackclient/image/v1/image.py
+++ b/openstackclient/image/v1/image.py
@@ -35,6 +35,7 @@ from glanceclient.common import utils as gc_utils
from openstackclient.api import utils as api_utils
from openstackclient.common import parseractions
from openstackclient.common import utils
+from openstackclient.i18n import _ # noqa
DEFAULT_CONTAINER_FORMAT = 'bare'
@@ -93,11 +94,6 @@ class CreateImage(show.ShowOne):
"(default: %s)" % DEFAULT_DISK_FORMAT,
)
parser.add_argument(
- "--owner",
- metavar="<project>",
- help="Image owner project name or ID",
- )
- parser.add_argument(
"--size",
metavar="<size>",
help="Image size, in bytes (only used with --location and"
@@ -178,12 +174,32 @@ class CreateImage(show.ShowOne):
help="Set a property on this image "
"(repeat option to set multiple properties)",
)
+ # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early
+ # 2.x release. Do not remove before Jan 2017
+ # and a 3.x release.
+ project_group = parser.add_mutually_exclusive_group()
+ project_group.add_argument(
+ "--project",
+ metavar="<project>",
+ help="Set an alternate project on this image (name or ID)",
+ )
+ project_group.add_argument(
+ "--owner",
+ metavar="<project>",
+ help=argparse.SUPPRESS,
+ )
return parser
def take_action(self, parsed_args):
self.log.debug("take_action(%s)", parsed_args)
image_client = self.app.client_manager.image
+ if getattr(parsed_args, 'owner', None) is not None:
+ self.log.warning(_(
+ 'The --owner option is deprecated, '
+ 'please use --project instead.'
+ ))
+
# Build an attribute dict from the parsed args, only include
# attributes that were actually set on the command line
kwargs = {}
@@ -198,6 +214,12 @@ class CreateImage(show.ShowOne):
# Only include a value in kwargs for attributes that are
# actually present on the command line
kwargs[attr] = val
+
+ # Special case project option back to API attribute name 'owner'
+ val = getattr(parsed_args, 'project', None)
+ if val:
+ kwargs['owner'] = val
+
# Handle exclusive booleans with care
# Avoid including attributes in kwargs if an option is not
# present on the command line. These exclusive booleans are not
@@ -383,7 +405,7 @@ class ListImage(lister.Lister):
'Status',
'Visibility',
'Protected',
- 'Owner',
+ 'Project',
'Properties',
)
else:
@@ -477,11 +499,6 @@ class SetImage(command.Command):
help="New image name",
)
parser.add_argument(
- "--owner",
- metavar="<project>",
- help="New image owner project (name or ID)",
- )
- parser.add_argument(
"--min-disk",
metavar="<disk-gb>",
type=int,
@@ -590,12 +607,32 @@ class SetImage(command.Command):
metavar="<checksum>",
help="Image hash used for verification",
)
+ # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early
+ # 2.x release. Do not remove before Jan 2017
+ # and a 3.x release.
+ project_group = parser.add_mutually_exclusive_group()
+ project_group.add_argument(
+ "--project",
+ metavar="<project>",
+ help="Set an alternate project on this image (name or ID)",
+ )
+ project_group.add_argument(
+ "--owner",
+ metavar="<project>",
+ help=argparse.SUPPRESS,
+ )
return parser
def take_action(self, parsed_args):
self.log.debug("take_action(%s)", parsed_args)
image_client = self.app.client_manager.image
+ if getattr(parsed_args, 'owner', None) is not None:
+ self.log.warning(_(
+ 'The --owner option is deprecated, '
+ 'please use --project instead.'
+ ))
+
kwargs = {}
copy_attrs = ('name', 'owner', 'min_disk', 'min_ram', 'properties',
'container_format', 'disk_format', 'size', 'store',
@@ -607,6 +644,12 @@ class SetImage(command.Command):
# Only include a value in kwargs for attributes that are
# actually present on the command line
kwargs[attr] = val
+
+ # Special case project option back to API attribute name 'owner'
+ val = getattr(parsed_args, 'project', None)
+ if val:
+ kwargs['owner'] = val
+
# Handle exclusive booleans with care
# Avoid including attributes in kwargs if an option is not
# present on the command line. These exclusive booleans are not
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py
index 106da9ef..123599ed 100644
--- a/openstackclient/image/v2/image.py
+++ b/openstackclient/image/v2/image.py
@@ -28,6 +28,7 @@ from openstackclient.api import utils as api_utils
from openstackclient.common import exceptions
from openstackclient.common import parseractions
from openstackclient.common import utils
+from openstackclient.i18n import _ # noqa
from openstackclient.identity import common
@@ -148,11 +149,6 @@ class CreateImage(show.ShowOne):
"(default: %s)" % DEFAULT_DISK_FORMAT,
)
parser.add_argument(
- "--owner",
- metavar="<owner>",
- help="Image owner project name or ID",
- )
- parser.add_argument(
"--min-disk",
metavar="<disk-gb>",
type=int,
@@ -220,6 +216,20 @@ class CreateImage(show.ShowOne):
help="Set a tag on this image "
"(repeat option to set multiple tags)",
)
+ # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early
+ # 2.x release. Do not remove before Jan 2017
+ # and a 3.x release.
+ project_group = parser.add_mutually_exclusive_group()
+ project_group.add_argument(
+ "--project",
+ metavar="<project>",
+ help="Set an alternate project on this image (name or ID)",
+ )
+ project_group.add_argument(
+ "--owner",
+ metavar="<project>",
+ help=argparse.SUPPRESS,
+ )
common.add_project_domain_option_to_parser(parser)
for deadopt in self.deadopts:
parser.add_argument(
@@ -246,8 +256,7 @@ class CreateImage(show.ShowOne):
kwargs = {}
copy_attrs = ('name', 'id',
'container_format', 'disk_format',
- 'min_disk', 'min_ram',
- 'tags', 'owner')
+ 'min_disk', 'min_ram', 'tags')
for attr in copy_attrs:
if attr in parsed_args:
val = getattr(parsed_args, attr, None)
@@ -255,6 +264,7 @@ class CreateImage(show.ShowOne):
# Only include a value in kwargs for attributes that
# are actually present on the command line
kwargs[attr] = val
+
# properties should get flattened into the general kwargs
if getattr(parsed_args, 'properties', None):
for k, v in six.iteritems(parsed_args.properties):
@@ -275,6 +285,21 @@ class CreateImage(show.ShowOne):
if parsed_args.private:
kwargs['visibility'] = 'private'
+ # Handle deprecated --owner option
+ project_arg = parsed_args.project
+ if parsed_args.owner:
+ project_arg = parsed_args.owner
+ self.log.warning(_(
+ 'The --owner option is deprecated, '
+ 'please use --project instead.'
+ ))
+ if project_arg:
+ kwargs['owner'] = common.find_project(
+ identity_client,
+ project_arg,
+ parsed_args.project_domain,
+ ).id
+
# open the file first to ensure any failures are handled before the
# image is created
fp = gc_utils.get_data_file(parsed_args)
@@ -458,7 +483,7 @@ class ListImage(lister.Lister):
'Status',
'Visibility',
'Protected',
- 'Owner',
+ 'Project',
'Tags',
)
else:
@@ -599,11 +624,6 @@ class SetImage(command.Command):
help="New image name"
)
parser.add_argument(
- "--owner",
- metavar="<project>",
- help="New image owner project (name or ID)",
- )
- parser.add_argument(
"--min-disk",
type=int,
metavar="<disk-gb>",
@@ -713,6 +733,20 @@ class SetImage(command.Command):
action="store_true",
help="Activate the image",
)
+ # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early
+ # 2.x release. Do not remove before Jan 2017
+ # and a 3.x release.
+ project_group = parser.add_mutually_exclusive_group()
+ project_group.add_argument(
+ "--project",
+ metavar="<project>",
+ help="Set an alternate project on this image (name or ID)",
+ )
+ project_group.add_argument(
+ "--owner",
+ metavar="<project>",
+ help=argparse.SUPPRESS,
+ )
common.add_project_domain_option_to_parser(parser)
for deadopt in self.deadopts:
parser.add_argument(
@@ -738,7 +772,7 @@ class SetImage(command.Command):
copy_attrs = ('architecture', 'container_format', 'disk_format',
'file', 'instance_id', 'kernel_id', 'locations',
'min_disk', 'min_ram', 'name', 'os_distro', 'os_version',
- 'owner', 'prefix', 'progress', 'ramdisk_id', 'tags')
+ 'prefix', 'progress', 'ramdisk_id', 'tags')
for attr in copy_attrs:
if attr in parsed_args:
val = getattr(parsed_args, attr, None)
@@ -767,6 +801,21 @@ class SetImage(command.Command):
if parsed_args.private:
kwargs['visibility'] = 'private'
+ # Handle deprecated --owner option
+ project_arg = parsed_args.project
+ if parsed_args.owner:
+ project_arg = parsed_args.owner
+ self.log.warning(_(
+ 'The --owner option is deprecated, '
+ 'please use --project instead.'
+ ))
+ if project_arg:
+ kwargs['owner'] = common.find_project(
+ identity_client,
+ project_arg,
+ parsed_args.project_domain,
+ ).id
+
# Checks if anything that requires getting the image
if not (kwargs or parsed_args.deactivate or parsed_args.activate):
self.log.warning("No arguments specified")
@@ -791,13 +840,6 @@ class SetImage(command.Command):
# Tags should be extended, but duplicates removed
kwargs['tags'] = list(set(image.tags).union(set(parsed_args.tags)))
- if parsed_args.owner:
- kwargs['owner'] = common.find_project(
- identity_client,
- parsed_args.owner,
- parsed_args.project_domain,
- ).id
-
try:
image = image_client.images.update(image.id, **kwargs)
except Exception as e:
diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py
new file mode 100644
index 00000000..ad906a28
--- /dev/null
+++ b/openstackclient/network/v2/port.py
@@ -0,0 +1,42 @@
+# 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.
+#
+
+"""Port action implementations"""
+
+import logging
+
+from cliff import command
+
+
+class DeletePort(command.Command):
+ """Delete port(s)"""
+
+ log = logging.getLogger(__name__ + '.DeletePort')
+
+ def get_parser(self, prog_name):
+ parser = super(DeletePort, self).get_parser(prog_name)
+ parser.add_argument(
+ 'port',
+ metavar="<port>",
+ nargs="+",
+ help=("Port(s) to delete (name or ID)")
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ self.log.debug('take_action(%s)' % parsed_args)
+ client = self.app.client_manager.network
+
+ for port in parsed_args.port:
+ res = client.find_port(port)
+ client.delete_port(res)
diff --git a/openstackclient/tests/common/test_command.py b/openstackclient/tests/common/test_command.py
new file mode 100644
index 00000000..1b2584bd
--- /dev/null
+++ b/openstackclient/tests/common/test_command.py
@@ -0,0 +1,32 @@
+# Copyright 2016 NEC Corporation
+#
+# 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.
+
+import mock
+
+from openstackclient.common import command
+from openstackclient.tests import utils as test_utils
+
+
+class FakeCommand(command.Command):
+ def take_action(self, parsed_args):
+ pass
+
+
+class TestCommand(test_utils.TestCase):
+
+ def test_command_has_logger(self):
+ cmd = FakeCommand(mock.Mock(), mock.Mock())
+ self.assertTrue(hasattr(cmd, 'log'))
+ self.assertEqual('openstackclient.tests.common.test_command.'
+ 'FakeCommand', cmd.log.name)
diff --git a/openstackclient/tests/compute/v2/test_security_group.py b/openstackclient/tests/compute/v2/test_security_group.py
index fdb659a8..87cc4870 100644
--- a/openstackclient/tests/compute/v2/test_security_group.py
+++ b/openstackclient/tests/compute/v2/test_security_group.py
@@ -56,6 +56,19 @@ class TestSecurityGroup(compute_fakes.TestComputev2):
class TestSecurityGroupCreate(TestSecurityGroup):
+ columns = (
+ 'description',
+ 'id',
+ 'name',
+ 'tenant_id',
+ )
+ data = (
+ security_group_description,
+ security_group_id,
+ security_group_name,
+ identity_fakes.project_id,
+ )
+
def setUp(self):
super(TestSecurityGroupCreate, self).setUp()
@@ -86,20 +99,8 @@ class TestSecurityGroupCreate(TestSecurityGroup):
security_group_name,
)
- collist = (
- 'description',
- 'id',
- 'name',
- 'tenant_id',
- )
- self.assertEqual(collist, columns)
- datalist = (
- security_group_description,
- security_group_id,
- security_group_name,
- identity_fakes.project_id,
- )
- self.assertEqual(datalist, data)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
def test_security_group_create_description(self):
arglist = [
@@ -121,20 +122,8 @@ class TestSecurityGroupCreate(TestSecurityGroup):
security_group_description,
)
- collist = (
- 'description',
- 'id',
- 'name',
- 'tenant_id',
- )
- self.assertEqual(collist, columns)
- datalist = (
- security_group_description,
- security_group_id,
- security_group_name,
- identity_fakes.project_id,
- )
- self.assertEqual(datalist, data)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
class TestSecurityGroupList(TestSecurityGroup):
diff --git a/openstackclient/tests/compute/v2/test_security_group_rule.py b/openstackclient/tests/compute/v2/test_security_group_rule.py
index 0e7ee05d..a2f9b108 100644
--- a/openstackclient/tests/compute/v2/test_security_group_rule.py
+++ b/openstackclient/tests/compute/v2/test_security_group_rule.py
@@ -116,6 +116,15 @@ class TestSecurityGroupRule(compute_fakes.TestComputev2):
class TestSecurityGroupRuleCreate(TestSecurityGroupRule):
+ columns = (
+ 'id',
+ 'ip_protocol',
+ 'ip_range',
+ 'parent_group_id',
+ 'port_range',
+ 'remote_security_group',
+ )
+
def setUp(self):
super(TestSecurityGroupRuleCreate, self).setUp()
@@ -156,15 +165,7 @@ class TestSecurityGroupRuleCreate(TestSecurityGroupRule):
None,
)
- collist = (
- 'id',
- 'ip_protocol',
- 'ip_range',
- 'parent_group_id',
- 'port_range',
- 'remote_security_group',
- )
- self.assertEqual(collist, columns)
+ self.assertEqual(self.columns, columns)
datalist = (
security_group_rule_id,
'tcp',
@@ -208,15 +209,7 @@ class TestSecurityGroupRuleCreate(TestSecurityGroupRule):
None,
)
- collist = (
- 'id',
- 'ip_protocol',
- 'ip_range',
- 'parent_group_id',
- 'port_range',
- 'remote_security_group',
- )
- self.assertEqual(collist, columns)
+ self.assertEqual(self.columns, columns)
datalist = (
security_group_rule_id,
'tcp',
@@ -264,15 +257,7 @@ class TestSecurityGroupRuleCreate(TestSecurityGroupRule):
security_group_id,
)
- collist = (
- 'id',
- 'ip_protocol',
- 'ip_range',
- 'parent_group_id',
- 'port_range',
- 'remote_security_group',
- )
- self.assertEqual(collist, columns)
+ self.assertEqual(self.columns, columns)
datalist = (
security_group_rule_id,
'tcp',
@@ -315,15 +300,7 @@ class TestSecurityGroupRuleCreate(TestSecurityGroupRule):
None,
)
- collist = (
- 'id',
- 'ip_protocol',
- 'ip_range',
- 'parent_group_id',
- 'port_range',
- 'remote_security_group',
- )
- self.assertEqual(collist, columns)
+ self.assertEqual(self.columns, columns)
datalist = (
security_group_rule_id,
'udp',
@@ -369,15 +346,7 @@ class TestSecurityGroupRuleCreate(TestSecurityGroupRule):
None,
)
- collist = (
- 'id',
- 'ip_protocol',
- 'ip_range',
- 'parent_group_id',
- 'port_range',
- 'remote_security_group',
- )
- self.assertEqual(collist, columns)
+ self.assertEqual(self.columns, columns)
datalist = (
security_group_rule_id,
'icmp',
diff --git a/openstackclient/tests/compute/v2/test_server.py b/openstackclient/tests/compute/v2/test_server.py
index 72fdbafc..f6b62291 100644
--- a/openstackclient/tests/compute/v2/test_server.py
+++ b/openstackclient/tests/compute/v2/test_server.py
@@ -89,6 +89,26 @@ class TestServer(compute_fakes.TestComputev2):
class TestServerCreate(TestServer):
+ columns = (
+ 'addresses',
+ 'flavor',
+ 'id',
+ 'name',
+ 'networks',
+ 'properties',
+ )
+
+ def datalist(self):
+ datalist = (
+ '',
+ self.flavor.name + ' ()',
+ self.new_server.id,
+ self.new_server.name,
+ self.new_server.networks,
+ '',
+ )
+ return datalist
+
def setUp(self):
super(TestServerCreate, self).setUp()
@@ -171,24 +191,8 @@ class TestServerCreate(TestServer):
**kwargs
)
- collist = (
- 'addresses',
- 'flavor',
- 'id',
- 'name',
- 'networks',
- 'properties',
- )
- self.assertEqual(collist, columns)
- datalist = (
- '',
- self.flavor.name + ' ()',
- self.new_server.id,
- self.new_server.name,
- self.new_server.networks,
- '',
- )
- self.assertEqual(datalist, data)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist(), data)
def test_server_create_with_network(self):
arglist = [
@@ -272,24 +276,8 @@ class TestServerCreate(TestServer):
**kwargs
)
- collist = (
- 'addresses',
- 'flavor',
- 'id',
- 'name',
- 'networks',
- 'properties',
- )
- self.assertEqual(collist, columns)
- datalist = (
- '',
- self.flavor.name + ' ()',
- self.new_server.id,
- self.new_server.name,
- self.new_server.networks,
- '',
- )
- self.assertEqual(datalist, data)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist(), data)
@mock.patch('openstackclient.compute.v2.server.io.open')
def test_server_create_userdata(self, mock_open):
@@ -345,24 +333,8 @@ class TestServerCreate(TestServer):
**kwargs
)
- collist = (
- 'addresses',
- 'flavor',
- 'id',
- 'name',
- 'networks',
- 'properties',
- )
- self.assertEqual(collist, columns)
- datalist = (
- '',
- self.flavor.name + ' ()',
- self.new_server.id,
- self.new_server.name,
- self.new_server.networks,
- '',
- )
- self.assertEqual(datalist, data)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist(), data)
def test_server_create_with_block_device_mapping(self):
arglist = [
@@ -414,24 +386,8 @@ class TestServerCreate(TestServer):
**kwargs
)
- collist = (
- 'addresses',
- 'flavor',
- 'id',
- 'name',
- 'networks',
- 'properties',
- )
- self.assertEqual(collist, columns)
- datalist = (
- '',
- self.flavor.name + ' ()',
- self.new_server.id,
- self.new_server.name,
- self.new_server.networks,
- '',
- )
- self.assertEqual(datalist, data)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist(), data)
class TestServerDelete(TestServer):
@@ -536,6 +492,26 @@ class TestServerDelete(TestServer):
class TestServerImageCreate(TestServer):
+ columns = (
+ 'id',
+ 'name',
+ 'owner',
+ 'protected',
+ 'tags',
+ 'visibility',
+ )
+
+ def datalist(self):
+ datalist = (
+ self.image.id,
+ self.image.name,
+ self.image.owner,
+ self.image.protected,
+ self.image.tags,
+ self.image.visibility,
+ )
+ return datalist
+
def setUp(self):
super(TestServerImageCreate, self).setUp()
@@ -569,17 +545,8 @@ class TestServerImageCreate(TestServer):
self.server.name,
)
- collist = ('id', 'name', 'owner', 'protected', 'tags', 'visibility')
- self.assertEqual(collist, columns)
- datalist = (
- self.image.id,
- self.image.name,
- self.image.owner,
- self.image.protected,
- self.image.tags,
- self.image.visibility,
- )
- self.assertEqual(datalist, data)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist(), data)
def test_server_image_create_name(self):
arglist = [
@@ -601,17 +568,8 @@ class TestServerImageCreate(TestServer):
'img-nam',
)
- collist = ('id', 'name', 'owner', 'protected', 'tags', 'visibility')
- self.assertEqual(collist, columns)
- datalist = (
- self.image.id,
- self.image.name,
- self.image.owner,
- self.image.protected,
- self.image.tags,
- self.image.visibility,
- )
- self.assertEqual(datalist, data)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist(), data)
class TestServerList(TestServer):
diff --git a/openstackclient/tests/image/v1/test_image.py b/openstackclient/tests/image/v1/test_image.py
index 4d964bdb..60b7f309 100644
--- a/openstackclient/tests/image/v1/test_image.py
+++ b/openstackclient/tests/image/v1/test_image.py
@@ -103,6 +103,7 @@ class TestImageCreate(TestImage):
'--min-ram', '4',
'--protected',
'--private',
+ '--project', 'q',
image_fakes.image_name,
]
verifylist = [
@@ -114,6 +115,7 @@ class TestImageCreate(TestImage):
('unprotected', False),
('public', False),
('private', True),
+ ('project', 'q'),
('name', image_fakes.image_name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -130,6 +132,7 @@ class TestImageCreate(TestImage):
min_ram=4,
protected=True,
is_public=False,
+ owner='q',
data=mock.ANY,
)
@@ -358,7 +361,7 @@ class TestImageList(TestImage):
'Status',
'Visibility',
'Protected',
- 'Owner',
+ 'Project',
'Properties',
)
@@ -484,22 +487,22 @@ class TestImageSet(TestImage):
def test_image_set_options(self):
arglist = [
'--name', 'new-name',
- '--owner', 'new-owner',
'--min-disk', '2',
'--min-ram', '4',
'--container-format', 'ovf',
'--disk-format', 'vmdk',
'--size', '35165824',
+ '--project', 'new-owner',
image_fakes.image_name,
]
verifylist = [
('name', 'new-name'),
- ('owner', 'new-owner'),
('min_disk', 2),
('min_ram', 4),
('container_format', 'ovf'),
('disk_format', 'vmdk'),
('size', 35165824),
+ ('project', 'new-owner'),
('image', image_fakes.image_name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
diff --git a/openstackclient/tests/image/v2/test_image.py b/openstackclient/tests/image/v2/test_image.py
index 02182413..3534a3a4 100644
--- a/openstackclient/tests/image/v2/test_image.py
+++ b/openstackclient/tests/image/v2/test_image.py
@@ -131,11 +131,11 @@ class TestImageCreate(TestImage):
'--disk-format', 'fs',
'--min-disk', '10',
'--min-ram', '4',
- '--owner', self.new_image.owner,
('--protected'
if self.new_image.protected else '--unprotected'),
('--private'
if self.new_image.visibility == 'private' else '--public'),
+ '--project', self.new_image.owner,
'--project-domain', identity_fakes.domain_id,
self.new_image.name,
]
@@ -144,11 +144,11 @@ class TestImageCreate(TestImage):
('disk_format', 'fs'),
('min_disk', 10),
('min_ram', 4),
- ('owner', self.new_image.owner),
('protected', self.new_image.protected),
('unprotected', not self.new_image.protected),
('public', self.new_image.visibility == 'public'),
('private', self.new_image.visibility == 'private'),
+ ('project', self.new_image.owner),
('project_domain', identity_fakes.domain_id),
('name', self.new_image.name),
]
@@ -217,6 +217,40 @@ class TestImageCreate(TestImage):
parsed_args,
)
+ def test_image_create_with_unexist_project(self):
+ self.project_mock.get.side_effect = exceptions.NotFound(None)
+ self.project_mock.find.side_effect = exceptions.NotFound(None)
+
+ arglist = [
+ '--container-format', 'ovf',
+ '--disk-format', 'fs',
+ '--min-disk', '10',
+ '--min-ram', '4',
+ '--protected',
+ '--private',
+ '--project', 'unexist_owner',
+ image_fakes.image_name,
+ ]
+ verifylist = [
+ ('container_format', 'ovf'),
+ ('disk_format', 'fs'),
+ ('min_disk', 10),
+ ('min_ram', 4),
+ ('protected', True),
+ ('unprotected', False),
+ ('public', False),
+ ('private', True),
+ ('project', 'unexist_owner'),
+ ('name', image_fakes.image_name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args,
+ )
+
@mock.patch('glanceclient.common.utils.get_data_file', name='Open')
def test_image_create_file(self, mock_open):
mock_file = mock.MagicMock(name='File')
@@ -575,7 +609,7 @@ class TestImageList(TestImage):
'Status',
'Visibility',
'Protected',
- 'Owner',
+ 'Project',
'Tags',
)
@@ -755,21 +789,21 @@ class TestImageSet(TestImage):
def test_image_set_options(self):
arglist = [
'--name', 'new-name',
- '--owner', identity_fakes.project_name,
'--min-disk', '2',
'--min-ram', '4',
'--container-format', 'ovf',
'--disk-format', 'vmdk',
+ '--project', identity_fakes.project_name,
'--project-domain', identity_fakes.domain_id,
image_fakes.image_id,
]
verifylist = [
('name', 'new-name'),
- ('owner', identity_fakes.project_name),
('min_disk', 2),
('min_ram', 4),
('container_format', 'ovf'),
('disk_format', 'vmdk'),
+ ('project', identity_fakes.project_name),
('project_domain', identity_fakes.domain_id),
('image', image_fakes.image_id),
]
@@ -809,6 +843,25 @@ class TestImageSet(TestImage):
exceptions.CommandError,
self.cmd.take_action, parsed_args)
+ def test_image_set_with_unexist_project(self):
+ self.project_mock.get.side_effect = exceptions.NotFound(None)
+ self.project_mock.find.side_effect = exceptions.NotFound(None)
+
+ arglist = [
+ '--project', 'unexist_owner',
+ image_fakes.image_id,
+ ]
+ verifylist = [
+ ('project', 'unexist_owner'),
+ ('image', image_fakes.image_id),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action, parsed_args)
+
def test_image_set_bools1(self):
arglist = [
'--protected',
diff --git a/openstackclient/tests/network/v2/fakes.py b/openstackclient/tests/network/v2/fakes.py
index 80760a77..de885c62 100644
--- a/openstackclient/tests/network/v2/fakes.py
+++ b/openstackclient/tests/network/v2/fakes.py
@@ -145,6 +145,83 @@ class FakeNetwork(object):
return mock.MagicMock(side_effect=networks)
+class FakePort(object):
+ """Fake one or more ports."""
+
+ @staticmethod
+ def create_one_port(attrs={}, methods={}):
+ """Create a fake port.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :param Dictionary methods:
+ A dictionary with all methods
+ :return:
+ A FakeResource object, with id, name, admin_state_up,
+ status, tenant_id
+ """
+ # Set default attributes.
+ port_attrs = {
+ 'id': 'port-id-' + uuid.uuid4().hex,
+ 'name': 'port-name-' + uuid.uuid4().hex,
+ 'status': 'ACTIVE',
+ 'admin_state_up': True,
+ 'tenant_id': 'project-id-' + uuid.uuid4().hex,
+ }
+
+ # Overwrite default attributes.
+ port_attrs.update(attrs)
+
+ # Set default methods.
+ port_methods = {}
+
+ # Overwrite default methods.
+ port_methods.update(methods)
+
+ port = fakes.FakeResource(info=copy.deepcopy(port_attrs),
+ methods=copy.deepcopy(port_methods),
+ loaded=True)
+ return port
+
+ @staticmethod
+ def create_ports(attrs={}, methods={}, count=2):
+ """Create multiple fake ports.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :param Dictionary methods:
+ A dictionary with all methods
+ :param int count:
+ The number of ports to fake
+ :return:
+ A list of FakeResource objects faking the ports
+ """
+ ports = []
+ for i in range(0, count):
+ ports.append(FakePort.create_one_port(attrs, methods))
+
+ return ports
+
+ @staticmethod
+ def get_ports(ports=None, count=2):
+ """Get an iterable MagicMock object with a list of faked ports.
+
+ If ports list is provided, then initialize the Mock object with the
+ list. Otherwise create one.
+
+ :param List ports:
+ A list of FakeResource objects faking ports
+ :param int count:
+ The number of ports to fake
+ :return:
+ An iterable Mock object with side_effect set to a list of faked
+ ports
+ """
+ if ports is None:
+ ports = FakePort.create_ports(count)
+ return mock.MagicMock(side_effect=ports)
+
+
class FakeRouter(object):
"""Fake one or more routers."""
diff --git a/openstackclient/tests/network/v2/test_port.py b/openstackclient/tests/network/v2/test_port.py
new file mode 100644
index 00000000..a1ddefa1
--- /dev/null
+++ b/openstackclient/tests/network/v2/test_port.py
@@ -0,0 +1,53 @@
+# 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.
+#
+
+import mock
+
+from openstackclient.network.v2 import port
+from openstackclient.tests.network.v2 import fakes as network_fakes
+
+
+class TestPort(network_fakes.TestNetworkV2):
+
+ def setUp(self):
+ super(TestPort, self).setUp()
+
+ # Get a shortcut to the network client
+ self.network = self.app.client_manager.network
+
+
+class TestDeletePort(TestPort):
+
+ # The port to delete.
+ _port = network_fakes.FakePort.create_one_port()
+
+ def setUp(self):
+ super(TestDeletePort, self).setUp()
+
+ self.network.delete_port = mock.Mock(return_value=None)
+ self.network.find_port = mock.Mock(return_value=self._port)
+ # Get the command object to test
+ self.cmd = port.DeletePort(self.app, self.namespace)
+
+ def test_delete(self):
+ arglist = [
+ self._port.name,
+ ]
+ verifylist = [
+ ('port', [self._port.name]),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.network.delete_port.assert_called_with(self._port)
+ self.assertIsNone(result)