summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/compute/v2/server.py8
-rw-r--r--openstackclient/identity/v3/identity_provider.py4
-rw-r--r--openstackclient/identity/v3/token.py2
-rw-r--r--openstackclient/identity/v3/trust.py2
-rw-r--r--openstackclient/network/client.py3
-rw-r--r--openstackclient/network/v2/network.py2
-rw-r--r--openstackclient/network/v2/port.py8
-rw-r--r--openstackclient/network/v2/router.py10
-rw-r--r--openstackclient/network/v2/subnet.py14
-rw-r--r--openstackclient/network/v2/subnet_pool.py36
-rw-r--r--openstackclient/tests/compute/v2/fakes.py92
-rw-r--r--openstackclient/tests/fakes.py3
-rw-r--r--openstackclient/tests/network/v2/fakes.py228
-rw-r--r--openstackclient/tests/network/v2/test_network.py12
-rw-r--r--openstackclient/tests/network/v2/test_router.py23
-rw-r--r--openstackclient/tests/network/v2/test_subnet.py20
-rw-r--r--openstackclient/tests/network/v2/test_subnet_pool.py105
-rw-r--r--openstackclient/tests/volume/v2/fakes.py2
-rw-r--r--openstackclient/tests/volume/v2/test_type.py66
-rw-r--r--openstackclient/volume/v1/snapshot.py2
-rw-r--r--openstackclient/volume/v2/snapshot.py2
-rw-r--r--openstackclient/volume/v2/volume.py2
-rw-r--r--openstackclient/volume/v2/volume_type.py56
23 files changed, 413 insertions, 289 deletions
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index d3b601b0..bf9f0985 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -293,7 +293,7 @@ class CreateServer(command.ShowOne):
action='append',
default=[],
help=_('Security group to assign to this server (name or ID) '
- '(repeat for multiple groups)'),
+ '(repeat option to set multiple groups)'),
)
parser.add_argument(
'--key-name',
@@ -305,7 +305,7 @@ class CreateServer(command.ShowOne):
metavar='<key=value>',
action=parseractions.KeyValueAction,
help=_('Set a property on this server '
- '(repeat for multiple values)'),
+ '(repeat option to set multiple values)'),
)
parser.add_argument(
'--file',
@@ -313,7 +313,7 @@ class CreateServer(command.ShowOne):
action='append',
default=[],
help=_('File to inject into image before boot '
- '(repeat for multiple files)'),
+ '(repeat option to set multiple files)'),
)
parser.add_argument(
'--user-data',
@@ -1738,7 +1738,7 @@ class UnsetServer(command.Command):
action='append',
default=[],
help=_('Property key to remove from server '
- '(repeat to remove multiple values)'),
+ '(repeat option to remove multiple values)'),
)
return parser
diff --git a/openstackclient/identity/v3/identity_provider.py b/openstackclient/identity/v3/identity_provider.py
index 37f79ed6..276a7f57 100644
--- a/openstackclient/identity/v3/identity_provider.py
+++ b/openstackclient/identity/v3/identity_provider.py
@@ -35,7 +35,7 @@ class CreateIdentityProvider(command.ShowOne):
metavar='<remote-id>',
action='append',
help='Remote IDs to associate with the Identity Provider '
- '(repeat to provide multiple values)'
+ '(repeat option to provide multiple values)'
)
identity_remote_id_provider.add_argument(
'--remote-id-file',
@@ -139,7 +139,7 @@ class SetIdentityProvider(command.Command):
metavar='<remote-id>',
action='append',
help='Remote IDs to associate with the Identity Provider '
- '(repeat to provide multiple values)'
+ '(repeat option to provide multiple values)'
)
identity_remote_id_provider.add_argument(
'--remote-id-file',
diff --git a/openstackclient/identity/v3/token.py b/openstackclient/identity/v3/token.py
index 62a4c4a3..bdc5e95f 100644
--- a/openstackclient/identity/v3/token.py
+++ b/openstackclient/identity/v3/token.py
@@ -40,7 +40,7 @@ class AuthorizeRequestToken(command.ShowOne):
action='append',
default=[],
help='Roles to authorize (name or ID) '
- '(repeat to set multiple values) (required)',
+ '(repeat option to set multiple values, required)',
required=True
)
return parser
diff --git a/openstackclient/identity/v3/trust.py b/openstackclient/identity/v3/trust.py
index 26fb8338..b6f5c6b4 100644
--- a/openstackclient/identity/v3/trust.py
+++ b/openstackclient/identity/v3/trust.py
@@ -48,7 +48,7 @@ class CreateTrust(command.ShowOne):
action='append',
default=[],
help='Roles to authorize (name or ID) '
- '(repeat to set multiple values) (required)',
+ '(repeat option to set multiple values, required)',
required=True
)
parser.add_argument(
diff --git a/openstackclient/network/client.py b/openstackclient/network/client.py
index 7714c525..dca9efc4 100644
--- a/openstackclient/network/client.py
+++ b/openstackclient/network/client.py
@@ -31,7 +31,8 @@ API_VERSIONS = {
def make_client(instance):
"""Returns a network proxy"""
- conn = connection.Connection(authenticator=instance.session.auth)
+ conn = connection.Connection(authenticator=instance.session.auth,
+ verify=instance.session.verify)
LOG.debug('Connection: %s', conn)
LOG.debug('Network client initialized using OpenStack SDK: %s',
conn.network)
diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py
index ebd5cb63..20d943ed 100644
--- a/openstackclient/network/v2/network.py
+++ b/openstackclient/network/v2/network.py
@@ -142,7 +142,7 @@ class CreateNetwork(common.NetworkAndComputeShowOne):
metavar='<availability-zone>',
help='Availability Zone in which to create this network '
'(requires the Network Availability Zone extension, '
- 'this option can be repeated).',
+ 'repeat option to set multiple availability zones)',
)
external_router_grp = parser.add_mutually_exclusive_group()
external_router_grp.add_argument(
diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py
index a9e80428..820f2ac2 100644
--- a/openstackclient/network/v2/port.py
+++ b/openstackclient/network/v2/port.py
@@ -210,13 +210,13 @@ class CreatePort(command.ShowOne):
optional_keys=['subnet', 'ip-address'],
help='Desired IP and/or subnet (name or ID) for this port: '
'subnet=<subnet>,ip-address=<ip-address> '
- '(this option can be repeated)')
+ '(repeat option to set multiple fixed IP addresses)')
parser.add_argument(
'--binding-profile',
metavar='<binding-profile>',
action=parseractions.KeyValueAction,
help='Custom data to be passed as binding:profile: <key>=<value> '
- '(this option can be repeated)')
+ '(repeat option to set multiple binding:profile data)')
admin_group = parser.add_mutually_exclusive_group()
admin_group.add_argument(
'--enable',
@@ -360,7 +360,7 @@ class SetPort(command.Command):
optional_keys=['subnet', 'ip-address'],
help='Desired IP and/or subnet (name or ID) for this port: '
'subnet=<subnet>,ip-address=<ip-address> '
- '(this option can be repeated)')
+ '(repeat option to set multiple fixed IP addresses)')
fixed_ip.add_argument(
'--no-fixed-ip',
action='store_true',
@@ -371,7 +371,7 @@ class SetPort(command.Command):
metavar='<binding-profile>',
action=parseractions.KeyValueAction,
help='Custom data to be passed as binding:profile: <key>=<value> '
- '(this option can be repeated)')
+ '(repeat option to set multiple binding:profile data)')
binding_profile.add_argument(
'--no-binding-profile',
action='store_true',
diff --git a/openstackclient/network/v2/router.py b/openstackclient/network/v2/router.py
index 6a78be6c..2ededae8 100644
--- a/openstackclient/network/v2/router.py
+++ b/openstackclient/network/v2/router.py
@@ -179,7 +179,7 @@ class CreateRouter(command.ShowOne):
dest='availability_zone_hints',
help='Availability Zone in which to create this router '
'(requires the Router Availability Zone extension, '
- 'this option can be repeated).',
+ 'repeat option to set multiple availability zones)',
)
identity_common.add_project_domain_option_to_parser(parser)
@@ -368,10 +368,10 @@ class SetRouter(command.Command):
dest='routes',
default=None,
required_keys=['destination', 'gateway'],
- help="Routes associated with the router. "
- "Repeat this option to set multiple routes. "
- "destination: destination subnet (in CIDR notation). "
- "gateway: nexthop IP address.",
+ help="Routes associated with the router "
+ "destination: destination subnet (in CIDR notation) "
+ "gateway: nexthop IP address "
+ "(repeat option to set multiple routes)",
)
routes_group.add_argument(
'--clear-routes',
diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py
index eb96bb1f..3d539fea 100644
--- a/openstackclient/network/v2/subnet.py
+++ b/openstackclient/network/v2/subnet.py
@@ -52,15 +52,15 @@ def _get_common_parse_arguments(parser):
required_keys=['start', 'end'],
help='Allocation pool IP addresses for this subnet '
'e.g.: start=192.168.199.2,end=192.168.199.254 '
- '(This option can be repeated)',
+ '(repeat option to add multiple IP addresses)',
)
parser.add_argument(
'--dns-nameserver',
metavar='<dns-nameserver>',
action='append',
dest='dns_nameservers',
- help='DNS name server for this subnet '
- '(This option can be repeated)',
+ help='DNS server for this subnet '
+ '(repeat option to set multiple DNS servers)',
)
parser.add_argument(
'--host-route',
@@ -72,7 +72,7 @@ def _get_common_parse_arguments(parser):
'e.g.: destination=10.10.0.0/16,gateway=192.168.71.254 '
'destination: destination subnet (in CIDR notation) '
'gateway: nexthop IP address '
- '(This option can be repeated)',
+ '(repeat option to add multiple routes)',
)
@@ -365,6 +365,12 @@ class SetSubnet(command.Command):
if not attrs:
msg = "Nothing specified to be set"
raise exceptions.CommandError(msg)
+ if 'dns_nameservers' in attrs:
+ attrs['dns_nameservers'] += obj.dns_nameservers
+ if 'host_routes' in attrs:
+ attrs['host_routes'] += obj.host_routes
+ if 'allocation_pools' in attrs:
+ attrs['allocation_pools'] += obj.allocation_pools
client.update_subnet(obj, **attrs)
return
diff --git a/openstackclient/network/v2/subnet_pool.py b/openstackclient/network/v2/subnet_pool.py
index 6b6fc090..0837f81b 100644
--- a/openstackclient/network/v2/subnet_pool.py
+++ b/openstackclient/network/v2/subnet_pool.py
@@ -35,6 +35,8 @@ _formatters = {
def _get_attrs(client_manager, parsed_args):
attrs = {}
+ network_client = client_manager.network
+
if parsed_args.name is not None:
attrs['name'] = str(parsed_args.name)
if parsed_args.prefixes is not None:
@@ -46,6 +48,12 @@ def _get_attrs(client_manager, parsed_args):
if parsed_args.max_prefix_length is not None:
attrs['max_prefixlen'] = parsed_args.max_prefix_length
+ if parsed_args.address_scope is not None:
+ attrs['address_scope_id'] = network_client.find_address_scope(
+ parsed_args.address_scope, ignore_missing=False).id
+ if 'no_address_scope' in parsed_args and parsed_args.no_address_scope:
+ attrs['address_scope_id'] = None
+
# "subnet pool set" command doesn't support setting project.
if 'project' in parsed_args and parsed_args.project is not None:
identity_client = client_manager.identity
@@ -65,8 +73,8 @@ def _add_prefix_options(parser):
metavar='<pool-prefix>',
dest='prefixes',
action='append',
- help='Set subnet pool prefixes (in CIDR notation). '
- 'Repeat this option to set multiple prefixes.',
+ help='Set subnet pool prefixes (in CIDR notation) '
+ '(repeat option to set multiple prefixes)',
)
parser.add_argument(
'--default-prefix-length',
@@ -105,7 +113,13 @@ class CreateSubnetPool(command.ShowOne):
help="Owner's project (name or ID)",
)
identity_common.add_project_domain_option_to_parser(parser)
-
+ parser.add_argument(
+ '--address-scope',
+ metavar='<address-scope>',
+ help="Set address scope associated with the subnet pool "
+ "(name or ID). Prefixes must be unique across address "
+ "scopes.",
+ )
return parser
def take_action(self, parsed_args):
@@ -184,7 +198,7 @@ class ListSubnetPool(command.Lister):
return (headers,
(utils.get_item_properties(
s, columns,
- formatters={},
+ formatters=_formatters,
) for s in data))
@@ -204,7 +218,19 @@ class SetSubnetPool(command.Command):
help='Set subnet pool name',
)
_add_prefix_options(parser)
-
+ address_scope_group = parser.add_mutually_exclusive_group()
+ address_scope_group.add_argument(
+ '--address-scope',
+ metavar='<address-scope>',
+ help="Set address scope associated with the subnet pool "
+ "(name or ID). Prefixes must be unique across address "
+ "scopes.",
+ )
+ address_scope_group.add_argument(
+ '--no-address-scope',
+ action='store_true',
+ help="Remove address scope associated with the subnet pool",
+ )
return parser
def take_action(self, parsed_args):
diff --git a/openstackclient/tests/compute/v2/fakes.py b/openstackclient/tests/compute/v2/fakes.py
index 6c67c470..1cca2787 100644
--- a/openstackclient/tests/compute/v2/fakes.py
+++ b/openstackclient/tests/compute/v2/fakes.py
@@ -342,20 +342,16 @@ class FakeSecurityGroup(object):
"""Fake one or more security groups."""
@staticmethod
- def create_one_security_group(attrs=None, methods=None):
+ def create_one_security_group(attrs=None):
"""Create a fake security group.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:return:
A FakeResource object, with id, name, etc.
"""
if attrs is None:
attrs = {}
- if methods is None:
- methods = {}
# Set default attributes.
security_group_attrs = {
@@ -369,28 +365,17 @@ class FakeSecurityGroup(object):
# Overwrite default attributes.
security_group_attrs.update(attrs)
- # Set default methods.
- security_group_methods = {
- 'keys': ['id', 'name', 'description', 'tenant_id', 'rules'],
- }
-
- # Overwrite default methods.
- security_group_methods.update(methods)
-
security_group = fakes.FakeResource(
info=copy.deepcopy(security_group_attrs),
- methods=copy.deepcopy(security_group_methods),
loaded=True)
return security_group
@staticmethod
- def create_security_groups(attrs=None, methods=None, count=2):
+ def create_security_groups(attrs=None, count=2):
"""Create multiple fake security groups.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of security groups to fake
:return:
@@ -399,7 +384,7 @@ class FakeSecurityGroup(object):
security_groups = []
for i in range(0, count):
security_groups.append(
- FakeSecurityGroup.create_one_security_group(attrs, methods))
+ FakeSecurityGroup.create_one_security_group(attrs))
return security_groups
@@ -408,20 +393,16 @@ class FakeSecurityGroupRule(object):
"""Fake one or more security group rules."""
@staticmethod
- def create_one_security_group_rule(attrs=None, methods=None):
+ def create_one_security_group_rule(attrs=None):
"""Create a fake security group rule.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:return:
A FakeResource object, with id, etc.
"""
if attrs is None:
attrs = {}
- if methods is None:
- methods = {}
# Set default attributes.
security_group_rule_attrs = {
@@ -437,26 +418,17 @@ class FakeSecurityGroupRule(object):
# Overwrite default attributes.
security_group_rule_attrs.update(attrs)
- # Set default methods.
- security_group_rule_methods = {}
-
- # Overwrite default methods.
- security_group_rule_methods.update(methods)
-
security_group_rule = fakes.FakeResource(
info=copy.deepcopy(security_group_rule_attrs),
- methods=copy.deepcopy(security_group_rule_methods),
loaded=True)
return security_group_rule
@staticmethod
- def create_security_group_rules(attrs=None, methods=None, count=2):
+ def create_security_group_rules(attrs=None, count=2):
"""Create multiple fake security group rules.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of security group rules to fake
:return:
@@ -465,8 +437,7 @@ class FakeSecurityGroupRule(object):
security_group_rules = []
for i in range(0, count):
security_group_rules.append(
- FakeSecurityGroupRule.create_one_security_group_rule(
- attrs, methods))
+ FakeSecurityGroupRule.create_one_security_group_rule(attrs))
return security_group_rules
@@ -688,13 +659,11 @@ class FakeAvailabilityZone(object):
"""Fake one or more compute availability zones (AZs)."""
@staticmethod
- def create_one_availability_zone(attrs={}, methods={}):
+ def create_one_availability_zone(attrs={}):
"""Create a fake AZ.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:return:
A FakeResource object with zoneName, zoneState, etc.
"""
@@ -717,18 +686,15 @@ class FakeAvailabilityZone(object):
availability_zone = fakes.FakeResource(
info=copy.deepcopy(availability_zone),
- methods=methods,
loaded=True)
return availability_zone
@staticmethod
- def create_availability_zones(attrs={}, methods={}, count=2):
+ def create_availability_zones(attrs={}, count=2):
"""Create multiple fake AZs.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of AZs to fake
:return:
@@ -737,8 +703,7 @@ class FakeAvailabilityZone(object):
availability_zones = []
for i in range(0, count):
availability_zone = \
- FakeAvailabilityZone.create_one_availability_zone(
- attrs, methods)
+ FakeAvailabilityZone.create_one_availability_zone(attrs)
availability_zones.append(availability_zone)
return availability_zones
@@ -748,13 +713,11 @@ class FakeFloatingIP(object):
"""Fake one or more floating ip."""
@staticmethod
- def create_one_floating_ip(attrs={}, methods={}):
+ def create_one_floating_ip(attrs={}):
"""Create a fake floating ip.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:return:
A FakeResource object, with id, ip, and so on
"""
@@ -770,27 +733,18 @@ class FakeFloatingIP(object):
# Overwrite default attributes.
floating_ip_attrs.update(attrs)
- # Set default methods.
- floating_ip_methods = {}
-
- # Overwrite default methods.
- floating_ip_methods.update(methods)
-
floating_ip = fakes.FakeResource(
info=copy.deepcopy(floating_ip_attrs),
- methods=copy.deepcopy(floating_ip_methods),
loaded=True)
return floating_ip
@staticmethod
- def create_floating_ips(attrs={}, methods={}, count=2):
+ def create_floating_ips(attrs={}, count=2):
"""Create multiple fake floating ips.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of floating ips to fake
:return:
@@ -798,10 +752,7 @@ class FakeFloatingIP(object):
"""
floating_ips = []
for i in range(0, count):
- floating_ips.append(FakeFloatingIP.create_one_floating_ip(
- attrs,
- methods
- ))
+ floating_ips.append(FakeFloatingIP.create_one_floating_ip(attrs))
return floating_ips
@staticmethod
@@ -828,13 +779,11 @@ class FakeNetwork(object):
"""Fake one or more networks."""
@staticmethod
- def create_one_network(attrs={}, methods={}):
+ def create_one_network(attrs={}):
"""Create a fake network.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:return:
A FakeResource object, with id, label, cidr and so on
"""
@@ -877,28 +826,17 @@ class FakeNetwork(object):
# Overwrite default attributes.
network_attrs.update(attrs)
- # Set default methods.
- network_methods = {
- 'keys': ['id', 'label', 'cidr'],
- }
-
- # Overwrite default methods.
- network_methods.update(methods)
-
network = fakes.FakeResource(info=copy.deepcopy(network_attrs),
- methods=copy.deepcopy(network_methods),
loaded=True)
return network
@staticmethod
- def create_networks(attrs={}, methods={}, count=2):
+ def create_networks(attrs={}, count=2):
"""Create multiple fake networks.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of networks to fake
:return:
@@ -906,7 +844,7 @@ class FakeNetwork(object):
"""
networks = []
for i in range(0, count):
- networks.append(FakeNetwork.create_one_network(attrs, methods))
+ networks.append(FakeNetwork.create_one_network(attrs))
return networks
diff --git a/openstackclient/tests/fakes.py b/openstackclient/tests/fakes.py
index 9fdcc7e9..f0cebb06 100644
--- a/openstackclient/tests/fakes.py
+++ b/openstackclient/tests/fakes.py
@@ -183,6 +183,9 @@ class FakeResource(object):
info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys)
return "<%s %s>" % (self.__class__.__name__, info)
+ def keys(self):
+ return self._info.keys()
+
class FakeResponse(requests.Response):
diff --git a/openstackclient/tests/network/v2/fakes.py b/openstackclient/tests/network/v2/fakes.py
index 7f89ef7a..5fd7ea3b 100644
--- a/openstackclient/tests/network/v2/fakes.py
+++ b/openstackclient/tests/network/v2/fakes.py
@@ -71,17 +71,52 @@ class TestNetworkV2(utils.TestCommand):
)
+class FakeAddressScope(object):
+ """Fake one or more address scopes."""
+
+ @staticmethod
+ def create_one_address_scope(attrs=None):
+ """Create a fake address scope.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :return:
+ A FakeResource object with name, id, etc.
+ """
+ if attrs is None:
+ attrs = {}
+
+ # Set default attributes.
+ address_scope_attrs = {
+ 'name': 'address-scope-name-' + uuid.uuid4().hex,
+ 'id': 'address-scope-id-' + uuid.uuid4().hex,
+ 'tenant_id': 'project-id-' + uuid.uuid4().hex,
+ 'shared': False,
+ 'ip_version': 4,
+ }
+
+ # Overwrite default attributes.
+ address_scope_attrs.update(attrs)
+
+ address_scope = fakes.FakeResource(
+ info=copy.deepcopy(address_scope_attrs),
+ loaded=True)
+
+ # Set attributes with special mapping in OpenStack SDK.
+ address_scope.project_id = address_scope_attrs['tenant_id']
+
+ return address_scope
+
+
class FakeAvailabilityZone(object):
"""Fake one or more network availability zones (AZs)."""
@staticmethod
- def create_one_availability_zone(attrs={}, methods={}):
+ def create_one_availability_zone(attrs={}):
"""Create a fake AZ.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:return:
A FakeResource object with name, state, etc.
"""
@@ -97,18 +132,15 @@ class FakeAvailabilityZone(object):
availability_zone = fakes.FakeResource(
info=copy.deepcopy(availability_zone),
- methods=methods,
loaded=True)
return availability_zone
@staticmethod
- def create_availability_zones(attrs={}, methods={}, count=2):
+ def create_availability_zones(attrs={}, count=2):
"""Create multiple fake AZs.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of AZs to fake
:return:
@@ -117,8 +149,7 @@ class FakeAvailabilityZone(object):
availability_zones = []
for i in range(0, count):
availability_zone = \
- FakeAvailabilityZone.create_one_availability_zone(
- attrs, methods)
+ FakeAvailabilityZone.create_one_availability_zone(attrs)
availability_zones.append(availability_zone)
return availability_zones
@@ -128,13 +159,11 @@ class FakeNetwork(object):
"""Fake one or more networks."""
@staticmethod
- def create_one_network(attrs={}, methods={}):
+ def create_one_network(attrs={}):
"""Create a fake network.
: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,
router_external, status, subnets, tenant_id
@@ -158,18 +187,7 @@ class FakeNetwork(object):
# Overwrite default attributes.
network_attrs.update(attrs)
- # Set default methods.
- network_methods = {
- 'keys': ['id', 'name', 'admin_state_up', 'router_external',
- 'status', 'subnets', 'tenant_id', 'availability_zones',
- 'availability_zone_hints', 'is_default'],
- }
-
- # Overwrite default methods.
- network_methods.update(methods)
-
network = fakes.FakeResource(info=copy.deepcopy(network_attrs),
- methods=copy.deepcopy(network_methods),
loaded=True)
# Set attributes with special mapping in OpenStack SDK.
@@ -178,13 +196,11 @@ class FakeNetwork(object):
return network
@staticmethod
- def create_networks(attrs={}, methods={}, count=2):
+ def create_networks(attrs={}, count=2):
"""Create multiple fake networks.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of networks to fake
:return:
@@ -192,7 +208,7 @@ class FakeNetwork(object):
"""
networks = []
for i in range(0, count):
- networks.append(FakeNetwork.create_one_network(attrs, methods))
+ networks.append(FakeNetwork.create_one_network(attrs))
return networks
@@ -220,7 +236,7 @@ class FakePort(object):
"""Fake one or more ports."""
@staticmethod
- def create_one_port(attrs={}, methods={}):
+ def create_one_port(attrs={}):
"""Create a fake port.
:param Dictionary attrs:
@@ -258,23 +274,7 @@ class FakePort(object):
# Overwrite default attributes.
port_attrs.update(attrs)
- # Set default methods.
- port_methods = {
- 'keys': ['admin_state_up', 'allowed_address_pairs',
- 'binding:host_id', 'binding:profile',
- 'binding:vif_details', 'binding:vif_type',
- 'binding:vnic_type', 'device_id', 'device_owner',
- 'dns_assignment', 'dns_name', 'extra_dhcp_opts',
- 'fixed_ips', 'id', 'mac_address', 'name',
- 'network_id', 'port_security_enabled',
- 'security_groups', 'status', 'tenant_id'],
- }
-
- # Overwrite default methods.
- port_methods.update(methods)
-
port = fakes.FakeResource(info=copy.deepcopy(port_attrs),
- methods=copy.deepcopy(port_methods),
loaded=True)
# Set attributes with special mappings in OpenStack SDK.
@@ -288,13 +288,11 @@ class FakePort(object):
return port
@staticmethod
- def create_ports(attrs={}, methods={}, count=2):
+ def create_ports(attrs={}, 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:
@@ -302,7 +300,7 @@ class FakePort(object):
"""
ports = []
for i in range(0, count):
- ports.append(FakePort.create_one_port(attrs, methods))
+ ports.append(FakePort.create_one_port(attrs))
return ports
@@ -330,13 +328,11 @@ class FakeRouter(object):
"""Fake one or more routers."""
@staticmethod
- def create_one_router(attrs={}, methods={}):
+ def create_one_router(attrs={}):
"""Create a fake router.
: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
@@ -359,17 +355,7 @@ class FakeRouter(object):
# Overwrite default attributes.
router_attrs.update(attrs)
- # Set default methods.
- router_methods = {
- 'keys': ['id', 'name', 'admin_state_up', 'distributed', 'ha',
- 'tenant_id'],
- }
-
- # Overwrite default methods.
- router_methods.update(methods)
-
router = fakes.FakeResource(info=copy.deepcopy(router_attrs),
- methods=copy.deepcopy(router_methods),
loaded=True)
# Set attributes with special mapping in OpenStack SDK.
@@ -378,13 +364,11 @@ class FakeRouter(object):
return router
@staticmethod
- def create_routers(attrs={}, methods={}, count=2):
+ def create_routers(attrs={}, count=2):
"""Create multiple fake routers.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of routers to fake
:return:
@@ -392,7 +376,7 @@ class FakeRouter(object):
"""
routers = []
for i in range(0, count):
- routers.append(FakeRouter.create_one_router(attrs, methods))
+ routers.append(FakeRouter.create_one_router(attrs))
return routers
@@ -420,20 +404,16 @@ class FakeSecurityGroup(object):
"""Fake one or more security groups."""
@staticmethod
- def create_one_security_group(attrs=None, methods=None):
+ def create_one_security_group(attrs=None):
"""Create a fake security group.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:return:
A FakeResource object, with id, name, etc.
"""
if attrs is None:
attrs = {}
- if methods is None:
- methods = {}
# Set default attributes.
security_group_attrs = {
@@ -447,18 +427,8 @@ class FakeSecurityGroup(object):
# Overwrite default attributes.
security_group_attrs.update(attrs)
- # Set default methods.
- security_group_methods = {
- 'keys': ['id', 'name', 'description', 'tenant_id',
- 'security_group_rules'],
- }
-
- # Overwrite default methods.
- security_group_methods.update(methods)
-
security_group = fakes.FakeResource(
info=copy.deepcopy(security_group_attrs),
- methods=copy.deepcopy(security_group_methods),
loaded=True)
# Set attributes with special mapping in OpenStack SDK.
@@ -467,13 +437,11 @@ class FakeSecurityGroup(object):
return security_group
@staticmethod
- def create_security_groups(attrs=None, methods=None, count=2):
+ def create_security_groups(attrs=None, count=2):
"""Create multiple fake security groups.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of security groups to fake
:return:
@@ -482,7 +450,7 @@ class FakeSecurityGroup(object):
security_groups = []
for i in range(0, count):
security_groups.append(
- FakeSecurityGroup.create_one_security_group(attrs, methods))
+ FakeSecurityGroup.create_one_security_group(attrs))
return security_groups
@@ -491,20 +459,16 @@ class FakeSecurityGroupRule(object):
"""Fake one or more security group rules."""
@staticmethod
- def create_one_security_group_rule(attrs=None, methods=None):
+ def create_one_security_group_rule(attrs=None):
"""Create a fake security group rule.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:return:
A FakeResource object, with id, etc.
"""
if attrs is None:
attrs = {}
- if methods is None:
- methods = {}
# Set default attributes.
security_group_rule_attrs = {
@@ -523,19 +487,8 @@ class FakeSecurityGroupRule(object):
# Overwrite default attributes.
security_group_rule_attrs.update(attrs)
- # Set default methods.
- security_group_rule_methods = {
- 'keys': ['direction', 'ethertype', 'id', 'port_range_max',
- 'port_range_min', 'protocol', 'remote_group_id',
- 'remote_ip_prefix', 'security_group_id', 'tenant_id'],
- }
-
- # Overwrite default methods.
- security_group_rule_methods.update(methods)
-
security_group_rule = fakes.FakeResource(
info=copy.deepcopy(security_group_rule_attrs),
- methods=copy.deepcopy(security_group_rule_methods),
loaded=True)
# Set attributes with special mapping in OpenStack SDK.
@@ -544,13 +497,11 @@ class FakeSecurityGroupRule(object):
return security_group_rule
@staticmethod
- def create_security_group_rules(attrs=None, methods=None, count=2):
+ def create_security_group_rules(attrs=None, count=2):
"""Create multiple fake security group rules.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of security group rules to fake
:return:
@@ -559,8 +510,7 @@ class FakeSecurityGroupRule(object):
security_group_rules = []
for i in range(0, count):
security_group_rules.append(
- FakeSecurityGroupRule.create_one_security_group_rule(
- attrs, methods))
+ FakeSecurityGroupRule.create_one_security_group_rule(attrs))
return security_group_rules
@@ -569,13 +519,11 @@ class FakeSubnet(object):
"""Fake one or more subnets."""
@staticmethod
- def create_one_subnet(attrs={}, methods={}):
+ def create_one_subnet(attrs={}):
"""Create a fake subnet.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:return:
A FakeResource object faking the subnet
"""
@@ -601,19 +549,7 @@ class FakeSubnet(object):
# Overwrite default attributes.
subnet_attrs.update(attrs)
- # Set default methods.
- subnet_methods = {
- 'keys': ['id', 'name', 'network_id', 'cidr', 'enable_dhcp',
- 'allocation_pools', 'dns_nameservers', 'gateway_ip',
- 'host_routes', 'ip_version', 'tenant_id',
- 'ipv6_address_mode', 'ipv6_ra_mode', 'subnetpool_id']
- }
-
- # Overwrite default methods.
- subnet_methods.update(methods)
-
subnet = fakes.FakeResource(info=copy.deepcopy(subnet_attrs),
- methods=copy.deepcopy(subnet_methods),
loaded=True)
# Set attributes with special mappings in OpenStack SDK.
subnet.project_id = subnet_attrs['tenant_id']
@@ -621,13 +557,11 @@ class FakeSubnet(object):
return subnet
@staticmethod
- def create_subnets(attrs={}, methods={}, count=2):
+ def create_subnets(attrs={}, count=2):
"""Create multiple fake subnets.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of subnets to fake
:return:
@@ -635,7 +569,7 @@ class FakeSubnet(object):
"""
subnets = []
for i in range(0, count):
- subnets.append(FakeSubnet.create_one_subnet(attrs, methods))
+ subnets.append(FakeSubnet.create_one_subnet(attrs))
return subnets
@@ -644,13 +578,11 @@ class FakeFloatingIP(object):
"""Fake one or more floating ip."""
@staticmethod
- def create_one_floating_ip(attrs={}, methods={}):
+ def create_one_floating_ip(attrs={}):
"""Create a fake floating ip.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:return:
A FakeResource object, with id, ip, and so on
"""
@@ -671,19 +603,8 @@ class FakeFloatingIP(object):
# Overwrite default attributes.
floating_ip_attrs.update(attrs)
- # Set default methods.
- floating_ip_methods = {
- 'keys': ['id', 'floating_ip_address', 'fixed_ip_address',
- 'dns_domain', 'dns_name', 'status', 'router_id',
- 'floating_network_id', 'port_id', 'tenant_id']
- }
-
- # Overwrite default methods.
- floating_ip_methods.update(methods)
-
floating_ip = fakes.FakeResource(
info=copy.deepcopy(floating_ip_attrs),
- methods=copy.deepcopy(floating_ip_methods),
loaded=True
)
@@ -693,13 +614,11 @@ class FakeFloatingIP(object):
return floating_ip
@staticmethod
- def create_floating_ips(attrs={}, methods={}, count=2):
+ def create_floating_ips(attrs={}, count=2):
"""Create multiple fake floating ips.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of floating ips to fake
:return:
@@ -707,10 +626,7 @@ class FakeFloatingIP(object):
"""
floating_ips = []
for i in range(0, count):
- floating_ips.append(FakeFloatingIP.create_one_floating_ip(
- attrs,
- methods
- ))
+ floating_ips.append(FakeFloatingIP.create_one_floating_ip(attrs))
return floating_ips
@staticmethod
@@ -737,13 +653,11 @@ class FakeSubnetPool(object):
"""Fake one or more subnet pools."""
@staticmethod
- def create_one_subnet_pool(attrs={}, methods={}):
+ def create_one_subnet_pool(attrs={}):
"""Create a fake subnet pool.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:return:
A FakeResource object faking the subnet pool
"""
@@ -766,20 +680,8 @@ class FakeSubnetPool(object):
# Overwrite default attributes.
subnet_pool_attrs.update(attrs)
- # Set default methods.
- subnet_pool_methods = {
- 'keys': ['id', 'name', 'prefixes', 'default_prefixlen',
- 'address_scope_id', 'tenant_id', 'is_default',
- 'shared', 'max_prefixlen', 'min_prefixlen',
- 'default_quota', 'ip_version']
- }
-
- # Overwrite default methods.
- subnet_pool_methods.update(methods)
-
subnet_pool = fakes.FakeResource(
info=copy.deepcopy(subnet_pool_attrs),
- methods=copy.deepcopy(subnet_pool_methods),
loaded=True
)
@@ -789,13 +691,11 @@ class FakeSubnetPool(object):
return subnet_pool
@staticmethod
- def create_subnet_pools(attrs={}, methods={}, count=2):
+ def create_subnet_pools(attrs={}, count=2):
"""Create multiple fake subnet pools.
:param Dictionary attrs:
A dictionary with all attributes
- :param Dictionary methods:
- A dictionary with all methods
:param int count:
The number of subnet pools to fake
:return:
@@ -804,7 +704,7 @@ class FakeSubnetPool(object):
subnet_pools = []
for i in range(0, count):
subnet_pools.append(
- FakeSubnetPool.create_one_subnet_pool(attrs, methods)
+ FakeSubnetPool.create_one_subnet_pool(attrs)
)
return subnet_pools
diff --git a/openstackclient/tests/network/v2/test_network.py b/openstackclient/tests/network/v2/test_network.py
index 0dec0e2f..8a75101b 100644
--- a/openstackclient/tests/network/v2/test_network.py
+++ b/openstackclient/tests/network/v2/test_network.py
@@ -54,7 +54,9 @@ class TestCreateNetworkIdentityV3(TestNetwork):
'is_default',
'name',
'project_id',
+ 'provider_network_type',
'router_external',
+ 'shared',
'status',
'subnets',
)
@@ -67,7 +69,9 @@ class TestCreateNetworkIdentityV3(TestNetwork):
_network.is_default,
_network.name,
_network.project_id,
+ _network.provider_network_type,
network._format_router_external(_network.router_external),
+ _network.shared,
_network.status,
utils.format_list(_network.subnets),
)
@@ -219,7 +223,9 @@ class TestCreateNetworkIdentityV2(TestNetwork):
'is_default',
'name',
'project_id',
+ 'provider_network_type',
'router_external',
+ 'shared',
'status',
'subnets',
)
@@ -232,7 +238,9 @@ class TestCreateNetworkIdentityV2(TestNetwork):
_network.is_default,
_network.name,
_network.project_id,
+ _network.provider_network_type,
network._format_router_external(_network.router_external),
+ _network.shared,
_network.status,
utils.format_list(_network.subnets),
)
@@ -539,7 +547,9 @@ class TestShowNetwork(TestNetwork):
'is_default',
'name',
'project_id',
+ 'provider_network_type',
'router_external',
+ 'shared',
'status',
'subnets',
)
@@ -552,7 +562,9 @@ class TestShowNetwork(TestNetwork):
_network.is_default,
_network.name,
_network.project_id,
+ _network.provider_network_type,
network._format_router_external(_network.router_external),
+ _network.shared,
_network.status,
utils.format_list(_network.subnets),
)
diff --git a/openstackclient/tests/network/v2/test_router.py b/openstackclient/tests/network/v2/test_router.py
index cf94bfd0..e8041498 100644
--- a/openstackclient/tests/network/v2/test_router.py
+++ b/openstackclient/tests/network/v2/test_router.py
@@ -117,19 +117,29 @@ class TestCreateRouter(TestRouter):
columns = (
'admin_state_up',
+ 'availability_zone_hints',
+ 'availability_zones',
'distributed',
+ 'external_gateway_info',
'ha',
'id',
'name',
'project_id',
+ 'routes',
+ 'status',
)
data = (
router._format_admin_state(new_router.admin_state_up),
+ osc_utils.format_list(new_router.availability_zone_hints),
+ osc_utils.format_list(new_router.availability_zones),
new_router.distributed,
+ router._format_external_gateway_info(new_router.external_gateway_info),
new_router.ha,
new_router.id,
new_router.name,
new_router.tenant_id,
+ new_router.routes,
+ new_router.status,
)
def setUp(self):
@@ -541,20 +551,29 @@ class TestShowRouter(TestRouter):
columns = (
'admin_state_up',
+ 'availability_zone_hints',
+ 'availability_zones',
'distributed',
+ 'external_gateway_info',
'ha',
'id',
'name',
'project_id',
+ 'routes',
+ 'status',
)
-
data = (
router._format_admin_state(_router.admin_state_up),
+ osc_utils.format_list(_router.availability_zone_hints),
+ osc_utils.format_list(_router.availability_zones),
_router.distributed,
+ router._format_external_gateway_info(_router.external_gateway_info),
_router.ha,
_router.id,
_router.name,
- _router.project_id,
+ _router.tenant_id,
+ _router.routes,
+ _router.status,
)
def setUp(self):
diff --git a/openstackclient/tests/network/v2/test_subnet.py b/openstackclient/tests/network/v2/test_subnet.py
index 2535bbe6..ede37416 100644
--- a/openstackclient/tests/network/v2/test_subnet.py
+++ b/openstackclient/tests/network/v2/test_subnet.py
@@ -536,6 +536,26 @@ class TestSetSubnet(TestSubnet):
self.assertRaises(exceptions.CommandError, self.cmd.take_action,
parsed_args)
+ def test_append_options(self):
+ _testsubnet = network_fakes.FakeSubnet.create_one_subnet(
+ {'dns_nameservers': ["10.0.0.1"]})
+ self.network.find_subnet = mock.Mock(return_value=_testsubnet)
+ arglist = [
+ '--dns-nameserver', '10.0.0.2',
+ _testsubnet.name,
+ ]
+ verifylist = [
+ ('dns_nameservers', ['10.0.0.2']),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+ attrs = {
+ 'dns_nameservers': ['10.0.0.2', '10.0.0.1'],
+ }
+ self.network.update_subnet.assert_called_once_with(
+ _testsubnet, **attrs)
+ self.assertIsNone(result)
+
class TestShowSubnet(TestSubnet):
# The subnets to be shown
diff --git a/openstackclient/tests/network/v2/test_subnet_pool.py b/openstackclient/tests/network/v2/test_subnet_pool.py
index 093e26c6..cbb32fc3 100644
--- a/openstackclient/tests/network/v2/test_subnet_pool.py
+++ b/openstackclient/tests/network/v2/test_subnet_pool.py
@@ -38,6 +38,8 @@ class TestCreateSubnetPool(TestSubnetPool):
# The new subnet pool to create.
_subnet_pool = network_fakes.FakeSubnetPool.create_one_subnet_pool()
+ _address_scope = network_fakes.FakeAddressScope.create_one_address_scope()
+
columns = (
'address_scope_id',
'default_prefixlen',
@@ -76,6 +78,9 @@ class TestCreateSubnetPool(TestSubnetPool):
# Get the command object to test
self.cmd = subnet_pool.CreateSubnetPool(self.app, self.namespace)
+ self.network.find_address_scope = mock.Mock(
+ return_value=self._address_scope)
+
# Set identity client. And get a shortcut to Identity client.
identity_client = identity_fakes_v3.FakeIdentityv3Client(
endpoint=fakes.AUTH_URL,
@@ -193,6 +198,29 @@ class TestCreateSubnetPool(TestSubnetPool):
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
+ def test_create_address_scope_option(self):
+ arglist = [
+ '--pool-prefix', '10.0.10.0/24',
+ '--address-scope', self._address_scope.id,
+ self._subnet_pool.name,
+ ]
+ verifylist = [
+ ('prefixes', ['10.0.10.0/24']),
+ ('address_scope', self._address_scope.id),
+ ('name', self._subnet_pool.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = (self.cmd.take_action(parsed_args))
+
+ self.network.create_subnet_pool.assert_called_once_with(**{
+ 'prefixes': ['10.0.10.0/24'],
+ 'address_scope_id': self._address_scope.id,
+ 'name': self._subnet_pool.name,
+ })
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.data, data)
+
class TestDeleteSubnetPool(TestSubnetPool):
@@ -246,7 +274,7 @@ class TestListSubnetPool(TestSubnetPool):
data.append((
pool.id,
pool.name,
- pool.prefixes,
+ utils.format_list(pool.prefixes),
))
data_long = []
@@ -254,7 +282,7 @@ class TestListSubnetPool(TestSubnetPool):
data_long.append((
pool.id,
pool.name,
- pool.prefixes,
+ utils.format_list(pool.prefixes),
pool.default_prefixlen,
pool.address_scope_id,
))
@@ -301,6 +329,8 @@ class TestSetSubnetPool(TestSubnetPool):
# The subnet_pool to set.
_subnet_pool = network_fakes.FakeSubnetPool.create_one_subnet_pool()
+ _address_scope = network_fakes.FakeAddressScope.create_one_address_scope()
+
def setUp(self):
super(TestSetSubnetPool, self).setUp()
@@ -309,21 +339,24 @@ class TestSetSubnetPool(TestSubnetPool):
self.network.find_subnet_pool = mock.Mock(
return_value=self._subnet_pool)
+ self.network.find_address_scope = mock.Mock(
+ return_value=self._address_scope)
+
# Get the command object to test
self.cmd = subnet_pool.SetSubnetPool(self.app, self.namespace)
def test_set_this(self):
arglist = [
- self._subnet_pool.name,
'--name', 'noob',
'--default-prefix-length', '8',
'--min-prefix-length', '8',
+ self._subnet_pool.name,
]
verifylist = [
- ('subnet_pool', self._subnet_pool.name),
('name', 'noob'),
('default_prefix_length', '8'),
('min_prefix_length', '8'),
+ ('subnet_pool', self._subnet_pool.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -340,15 +373,15 @@ class TestSetSubnetPool(TestSubnetPool):
def test_set_that(self):
arglist = [
- self._subnet_pool.name,
'--pool-prefix', '10.0.1.0/24',
'--pool-prefix', '10.0.2.0/24',
'--max-prefix-length', '16',
+ self._subnet_pool.name,
]
verifylist = [
- ('subnet_pool', self._subnet_pool.name),
('prefixes', ['10.0.1.0/24', '10.0.2.0/24']),
('max_prefix_length', '16'),
+ ('subnet_pool', self._subnet_pool.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -374,17 +407,73 @@ class TestSetSubnetPool(TestSubnetPool):
def test_set_len_negative(self):
arglist = [
- self._subnet_pool.name,
'--max-prefix-length', '-16',
+ self._subnet_pool.name,
]
verifylist = [
- ('subnet_pool', self._subnet_pool.name),
('max_prefix_length', '-16'),
+ ('subnet_pool', self._subnet_pool.name),
]
self.assertRaises(argparse.ArgumentTypeError, self.check_parser,
self.cmd, arglist, verifylist)
+ def test_set_address_scope(self):
+ arglist = [
+ '--address-scope', self._address_scope.id,
+ self._subnet_pool.name,
+ ]
+ verifylist = [
+ ('address_scope', self._address_scope.id),
+ ('subnet_pool', self._subnet_pool.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ attrs = {
+ 'address_scope_id': self._address_scope.id,
+ }
+ self.network.update_subnet_pool.assert_called_once_with(
+ self._subnet_pool, **attrs)
+ self.assertIsNone(result)
+
+ def test_set_no_address_scope(self):
+ arglist = [
+ '--no-address-scope',
+ self._subnet_pool.name,
+ ]
+ verifylist = [
+ ('no_address_scope', True),
+ ('subnet_pool', self._subnet_pool.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ attrs = {
+ 'address_scope_id': None,
+ }
+ self.network.update_subnet_pool.assert_called_once_with(
+ self._subnet_pool, **attrs)
+ self.assertIsNone(result)
+
+ def test_set_no_address_scope_conflict(self):
+ arglist = [
+ '--address-scope', self._address_scope.id,
+ '--no-address-scope',
+ self._subnet_pool.name,
+ ]
+ verifylist = [
+ ('address_scope', self._address_scope.id),
+ ('no_address_scope', True),
+ ('subnet_pool', self._subnet_pool.name),
+ ]
+
+ # Exclusive arguments will conflict here.
+ self.assertRaises(tests_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
+
class TestShowSubnetPool(TestSubnetPool):
diff --git a/openstackclient/tests/volume/v2/fakes.py b/openstackclient/tests/volume/v2/fakes.py
index 97bbc59b..3c238d10 100644
--- a/openstackclient/tests/volume/v2/fakes.py
+++ b/openstackclient/tests/volume/v2/fakes.py
@@ -243,6 +243,8 @@ class FakeVolumeClient(object):
self.backups.resource_class = fakes.FakeResource(None, {})
self.volume_types = mock.Mock()
self.volume_types.resource_class = fakes.FakeResource(None, {})
+ self.volume_type_access = mock.Mock()
+ self.volume_type_access.resource_class = fakes.FakeResource(None, {})
self.restores = mock.Mock()
self.restores.resource_class = fakes.FakeResource(None, {})
self.qos_specs = mock.Mock()
diff --git a/openstackclient/tests/volume/v2/test_type.py b/openstackclient/tests/volume/v2/test_type.py
index b014706b..448da432 100644
--- a/openstackclient/tests/volume/v2/test_type.py
+++ b/openstackclient/tests/volume/v2/test_type.py
@@ -15,6 +15,8 @@
import copy
from openstackclient.tests import fakes
+from openstackclient.tests.identity.v3 import fakes as identity_fakes
+from openstackclient.tests import utils as tests_utils
from openstackclient.tests.volume.v2 import fakes as volume_fakes
from openstackclient.volume.v2 import volume_type
@@ -41,6 +43,13 @@ class TestType(volume_fakes.TestVolume):
self.types_mock = self.app.client_manager.volume.volume_types
self.types_mock.reset_mock()
+ self.types_access_mock = (
+ self.app.client_manager.volume.volume_type_access)
+ self.types_access_mock.reset_mock()
+
+ self.projects_mock = self.app.client_manager.identity.projects
+ self.projects_mock.reset_mock()
+
class TestTypeCreate(TestType):
@@ -211,6 +220,13 @@ class TestTypeSet(TestType):
loaded=True,
)
+ # Return a project
+ self.projects_mock.get.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(identity_fakes.PROJECT),
+ loaded=True,
+ )
+
# Get the command object to test
self.cmd = volume_type.SetVolumeType(self.app, None)
@@ -286,6 +302,56 @@ class TestTypeSet(TestType):
self.assertIn('myprop', result)
self.assertEqual('myvalue', result['myprop'])
+ def test_type_set_not_called_without_project_argument(self):
+ arglist = [
+ '--project', '',
+ volume_fakes.type_id,
+ ]
+ verifylist = [
+ ('project', ''),
+ ('volume_type', volume_fakes.type_id),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.assertIsNone(result)
+
+ self.assertFalse(self.types_access_mock.add_project_access.called)
+
+ def test_type_set_failed_with_missing_volume_type_argument(self):
+ arglist = [
+ '--project', 'identity_fakes.project_id',
+ ]
+ verifylist = [
+ ('project', 'identity_fakes.project_id'),
+ ]
+
+ self.assertRaises(tests_utils.ParserException,
+ self.check_parser,
+ self.cmd,
+ arglist,
+ verifylist)
+
+ def test_type_set_project_access(self):
+ arglist = [
+ '--project', identity_fakes.project_id,
+ volume_fakes.type_id,
+ ]
+ verifylist = [
+ ('project', identity_fakes.project_id),
+ ('volume_type', volume_fakes.type_id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.assertIsNone(result)
+
+ self.types_access_mock.add_project_access.assert_called_with(
+ volume_fakes.type_id,
+ identity_fakes.project_id,
+ )
+
class TestTypeShow(TestType):
diff --git a/openstackclient/volume/v1/snapshot.py b/openstackclient/volume/v1/snapshot.py
index c54bac8a..6c6131ea 100644
--- a/openstackclient/volume/v1/snapshot.py
+++ b/openstackclient/volume/v1/snapshot.py
@@ -249,7 +249,7 @@ class UnsetSnapshot(command.Command):
action='append',
default=[],
help='Property to remove from snapshot '
- '(repeat to remove multiple values)',
+ '(repeat option to remove multiple properties)',
required=True,
)
return parser
diff --git a/openstackclient/volume/v2/snapshot.py b/openstackclient/volume/v2/snapshot.py
index c9e50297..f124a5e2 100644
--- a/openstackclient/volume/v2/snapshot.py
+++ b/openstackclient/volume/v2/snapshot.py
@@ -240,7 +240,7 @@ class UnsetSnapshot(command.Command):
action='append',
default=[],
help='Property to remove from snapshot '
- '(repeat to remove multiple values)',
+ '(repeat option to remove multiple properties)',
)
return parser
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index 5b7511e8..5a739f61 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -110,7 +110,7 @@ class CreateVolume(command.ShowOne):
snapshot = None
if parsed_args.snapshot:
snapshot = utils.find_resource(
- volume_client.snapshots,
+ volume_client.volume_snapshots,
parsed_args.snapshot).id
project = None
diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py
index 5509ac52..203974da 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -17,8 +17,10 @@
import six
from openstackclient.common import command
+from openstackclient.common import exceptions
from openstackclient.common import parseractions
from openstackclient.common import utils
+from openstackclient.identity import common as identity_common
class CreateVolumeType(command.ShowOne):
@@ -55,7 +57,7 @@ class CreateVolumeType(command.ShowOne):
'--property',
metavar='<key=value>',
action=parseractions.KeyValueAction,
- help='Set a property on this volume type'
+ help='Set a property on this volume type '
'(repeat option to set multiple properties)',
)
return parser
@@ -156,19 +158,30 @@ class SetVolumeType(command.Command):
help='Set a property on this volume type '
'(repeat option to set multiple properties)',
)
+ parser.add_argument(
+ '--project',
+ metavar='<project>',
+ help='Set volume type access to project (name or ID) (admin only)',
+ )
+ identity_common.add_project_domain_option_to_parser(parser)
+
return parser
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
+ identity_client = self.app.client_manager.identity
+
volume_type = utils.find_resource(
volume_client.volume_types, parsed_args.volume_type)
if (not parsed_args.name
and not parsed_args.description
- and not parsed_args.property):
+ and not parsed_args.property
+ and not parsed_args.project):
self.app.log.error("No changes requested\n")
return
+ result = 0
kwargs = {}
if parsed_args.name:
kwargs['name'] = parsed_args.name
@@ -176,13 +189,42 @@ class SetVolumeType(command.Command):
kwargs['description'] = parsed_args.description
if kwargs:
- volume_client.volume_types.update(
- volume_type.id,
- **kwargs
- )
+ try:
+ volume_client.volume_types.update(
+ volume_type.id,
+ **kwargs
+ )
+ except Exception as e:
+ self.app.log.error("Failed to update volume type name or"
+ " description: " + str(e))
+ result += 1
if parsed_args.property:
- volume_type.set_keys(parsed_args.property)
+ try:
+ volume_type.set_keys(parsed_args.property)
+ except Exception as e:
+ self.app.log.error("Failed to set volume type property: " +
+ str(e))
+ result += 1
+
+ if parsed_args.project:
+ project_info = None
+ try:
+ project_info = identity_common.find_project(
+ identity_client,
+ parsed_args.project,
+ parsed_args.project_domain)
+
+ volume_client.volume_type_access.add_project_access(
+ volume_type.id, project_info.id)
+ except Exception as e:
+ self.app.log.error("Failed to set volume type access to"
+ " project: " + str(e))
+ result += 1
+
+ if result > 0:
+ raise exceptions.CommandError("Command Failed: One or more of the"
+ " operations failed")
class ShowVolumeType(command.ShowOne):