summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/conf.py4
-rw-r--r--neutronclient/client.py1
-rw-r--r--neutronclient/common/clientmanager.py5
-rw-r--r--neutronclient/common/exceptions.py4
-rw-r--r--neutronclient/neutron/v2_0/__init__.py17
-rw-r--r--neutronclient/neutron/v2_0/agentscheduler.py4
-rw-r--r--neutronclient/neutron/v2_0/router.py12
-rw-r--r--neutronclient/neutron/v2_0/subnet.py19
-rw-r--r--neutronclient/neutron/v2_0/vpn/ikepolicy.py5
-rw-r--r--neutronclient/neutron/v2_0/vpn/ipsec_site_connection.py10
-rw-r--r--neutronclient/neutron/v2_0/vpn/ipsecpolicy.py5
-rw-r--r--neutronclient/shell.py8
-rw-r--r--neutronclient/tests/unit/test_cli20.py1
-rw-r--r--neutronclient/tests/unit/test_cli20_subnet.py93
-rw-r--r--neutronclient/tests/unit/test_name_or_id.py47
-rw-r--r--neutronclient/tests/unit/test_shell.py25
-rw-r--r--neutronclient/tests/unit/test_ssl.py2
-rw-r--r--neutronclient/v2_0/client.py4
-rw-r--r--test-requirements.txt1
-rw-r--r--tox.ini4
20 files changed, 238 insertions, 33 deletions
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 91d2186..0001ce6 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -7,7 +7,7 @@ project = 'python-neutronclient'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx']
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'oslosphinx']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -35,7 +35,7 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
-html_theme = 'nature'
+# html_theme = 'nature'
# Output file base name for HTML help builder.
htmlhelp_basename = '%sdoc' % project
diff --git a/neutronclient/client.py b/neutronclient/client.py
index 7379edb..e41511f 100644
--- a/neutronclient/client.py
+++ b/neutronclient/client.py
@@ -144,6 +144,7 @@ class HTTPClient(object):
method,
url,
verify=self.verify_cert,
+ timeout=self.timeout,
**kwargs)
return resp, resp.text
diff --git a/neutronclient/common/clientmanager.py b/neutronclient/common/clientmanager.py
index db6883b..69d1b0c 100644
--- a/neutronclient/common/clientmanager.py
+++ b/neutronclient/common/clientmanager.py
@@ -64,6 +64,7 @@ class ClientManager(object):
ca_cert=None,
log_credentials=False,
service_type=None,
+ timeout=None
):
self._token = token
self._url = url
@@ -82,6 +83,7 @@ class ClientManager(object):
self._insecure = insecure
self._ca_cert = ca_cert
self._log_credentials = log_credentials
+ self._timeout = timeout
return
def initialize(self):
@@ -98,7 +100,8 @@ class ClientManager(object):
endpoint_type=self._endpoint_type,
insecure=self._insecure,
ca_cert=self._ca_cert,
- log_credentials=self._log_credentials)
+ log_credentials=self._log_credentials,
+ timeout=self._timeout)
httpclient.authenticate()
# Populate other password flow attributes
self._token = httpclient.auth_token
diff --git a/neutronclient/common/exceptions.py b/neutronclient/common/exceptions.py
index 3572660..4c21e62 100644
--- a/neutronclient/common/exceptions.py
+++ b/neutronclient/common/exceptions.py
@@ -155,6 +155,10 @@ class IpAddressGenerationFailureClient(Conflict):
pass
+class MacAddressInUseClient(Conflict):
+ pass
+
+
class ExternalIpAddressExhaustedClient(BadRequest):
pass
diff --git a/neutronclient/neutron/v2_0/__init__.py b/neutronclient/neutron/v2_0/__init__.py
index 565edc6..6c978f4 100644
--- a/neutronclient/neutron/v2_0/__init__.py
+++ b/neutronclient/neutron/v2_0/__init__.py
@@ -62,10 +62,13 @@ def find_resourceid_by_id(client, resource, resource_id):
message=not_found_message, status_code=404)
-def _find_resourceid_by_name(client, resource, name):
+def _find_resourceid_by_name(client, resource, name, project_id=None):
resource_plural = _get_resource_plural(resource, client)
obj_lister = getattr(client, "list_%s" % resource_plural)
- data = obj_lister(name=name, fields='id')
+ params = {'name': name, 'fields': 'id'}
+ if project_id:
+ params['tenant_id'] = project_id
+ data = obj_lister(**params)
collection = resource_plural
info = data[collection]
if len(info) > 1:
@@ -82,17 +85,19 @@ def _find_resourceid_by_name(client, resource, name):
return info[0]['id']
-def find_resourceid_by_name_or_id(client, resource, name_or_id):
+def find_resourceid_by_name_or_id(client, resource, name_or_id,
+ project_id=None):
try:
return find_resourceid_by_id(client, resource, name_or_id)
except exceptions.NeutronClientException:
- return _find_resourceid_by_name(client, resource, name_or_id)
+ return _find_resourceid_by_name(client, resource, name_or_id,
+ project_id)
def add_show_list_common_argument(parser):
parser.add_argument(
'-D', '--show-details',
- help=_('Show detailed info.'),
+ help=_('Show detailed information.'),
action='store_true',
default=False, )
parser.add_argument(
@@ -357,7 +362,7 @@ class NeutronCommand(command.OpenStackCommand):
parser = super(NeutronCommand, self).get_parser(prog_name)
parser.add_argument(
'--request-format',
- help=_('The xml or json request format.'),
+ help=_('The XML or JSON request format.'),
default='json',
choices=['json', 'xml', ], )
parser.add_argument(
diff --git a/neutronclient/neutron/v2_0/agentscheduler.py b/neutronclient/neutron/v2_0/agentscheduler.py
index 03d2454..cd38c50 100644
--- a/neutronclient/neutron/v2_0/agentscheduler.py
+++ b/neutronclient/neutron/v2_0/agentscheduler.py
@@ -76,7 +76,7 @@ class RemoveNetworkFromDhcpAgent(neutronV20.NeutronCommand):
neutron_client, 'network', parsed_args.network)
neutron_client.remove_network_from_dhcp_agent(
parsed_args.dhcp_agent, _net_id)
- print(_('Removed network %s to DHCP agent') % parsed_args.network,
+ print(_('Removed network %s from DHCP agent') % parsed_args.network,
file=self.app.stdout)
@@ -180,7 +180,7 @@ class RemoveRouterFromL3Agent(neutronV20.NeutronCommand):
neutron_client, 'router', parsed_args.router)
neutron_client.remove_router_from_l3_agent(
parsed_args.l3_agent, _id)
- print(_('Removed Router %s to L3 agent') % parsed_args.router,
+ print(_('Removed router %s from L3 agent') % parsed_args.router,
file=self.app.stdout)
diff --git a/neutronclient/neutron/v2_0/router.py b/neutronclient/neutron/v2_0/router.py
index b2d935b..76f18b1 100644
--- a/neutronclient/neutron/v2_0/router.py
+++ b/neutronclient/neutron/v2_0/router.py
@@ -70,15 +70,15 @@ class CreateRouter(neutronV20.CreateCommand):
'name', metavar='NAME',
help=_('Name of router to create.'))
parser.add_argument(
- '--distributed',
- dest='distributed', action='store_true',
- default=argparse.SUPPRESS,
+ 'distributed', action='store_true',
help=_('Create a distributed router.'))
def args2body(self, parsed_args):
- body = {self.resource: {'admin_state_up': parsed_args.admin_state}}
- neutronV20.update_dict(parsed_args, body[self.resource],
- ['name', 'distributed', 'tenant_id'])
+ body = {'router': {
+ 'name': parsed_args.name,
+ 'admin_state_up': parsed_args.admin_state, }, }
+ if parsed_args.tenant_id:
+ body['router'].update({'tenant_id': parsed_args.tenant_id})
return body
diff --git a/neutronclient/neutron/v2_0/subnet.py b/neutronclient/neutron/v2_0/subnet.py
index 15eec6d..4de0058 100644
--- a/neutronclient/neutron/v2_0/subnet.py
+++ b/neutronclient/neutron/v2_0/subnet.py
@@ -84,6 +84,14 @@ def add_updatable_arguments(parser):
'--enable-dhcp',
action='store_true',
help=_('Enable DHCP for this subnet.'))
+ parser.add_argument(
+ '--ipv6-ra-mode',
+ choices=['dhcpv6-stateful', 'dhcpv6-stateless', 'slaac'],
+ help=_('IPv6 RA (Router Advertisement) mode.'))
+ parser.add_argument(
+ '--ipv6-address-mode',
+ choices=['dhcpv6-stateful', 'dhcpv6-stateless', 'slaac'],
+ help=_('IPv6 address mode.'))
def updatable_args2body(parsed_args, body):
@@ -111,6 +119,17 @@ def updatable_args2body(parsed_args, body):
body['subnet']['host_routes'] = parsed_args.host_routes
if parsed_args.dns_nameservers:
body['subnet']['dns_nameservers'] = parsed_args.dns_nameservers
+ if parsed_args.ipv6_ra_mode:
+ if parsed_args.ip_version == 4:
+ raise exceptions.CommandError(_("--ipv6-ra-mode is invalid "
+ "when --ip-version is 4"))
+ body['subnet']['ipv6_ra_mode'] = parsed_args.ipv6_ra_mode
+ if parsed_args.ipv6_address_mode:
+ if parsed_args.ip_version == 4:
+ raise exceptions.CommandError(_("--ipv6-address-mode is "
+ "invalid when --ip-version "
+ "is 4"))
+ body['subnet']['ipv6_address_mode'] = parsed_args.ipv6_address_mode
class ListSubnet(neutronV20.ListCommand):
diff --git a/neutronclient/neutron/v2_0/vpn/ikepolicy.py b/neutronclient/neutron/v2_0/vpn/ikepolicy.py
index 1191c52..90d432d 100644
--- a/neutronclient/neutron/v2_0/vpn/ikepolicy.py
+++ b/neutronclient/neutron/v2_0/vpn/ikepolicy.py
@@ -60,10 +60,7 @@ class CreateIKEPolicy(neutronv20.CreateCommand):
'Default:sha1'))
parser.add_argument(
'--encryption-algorithm',
- default='aes-128', choices=['3des',
- 'aes-128',
- 'aes-192',
- 'aes-256'],
+ default='aes-128',
help=_('Encryption algorithm in lowercase, default:aes-128'))
parser.add_argument(
'--phase1-negotiation-mode',
diff --git a/neutronclient/neutron/v2_0/vpn/ipsec_site_connection.py b/neutronclient/neutron/v2_0/vpn/ipsec_site_connection.py
index ad8c851..aefdf6a 100644
--- a/neutronclient/neutron/v2_0/vpn/ipsec_site_connection.py
+++ b/neutronclient/neutron/v2_0/vpn/ipsec_site_connection.py
@@ -34,7 +34,7 @@ def _format_peer_cidrs(ipsec_site_connection):
class ListIPsecSiteConnection(neutronv20.ListCommand):
- """List IPsecSiteConnections that belong to a given tenant."""
+ """List IPsec site connections that belong to a given tenant."""
resource = 'ipsec_site_connection'
log = logging.getLogger(__name__ + '.ListIPsecSiteConnection')
@@ -47,7 +47,7 @@ class ListIPsecSiteConnection(neutronv20.ListCommand):
class ShowIPsecSiteConnection(neutronv20.ShowCommand):
- """Show information of a given IPsecSiteConnection."""
+ """Show information of a given IPsec site connection."""
resource = 'ipsec_site_connection'
log = logging.getLogger(__name__ + '.ShowIPsecSiteConnection')
@@ -162,7 +162,7 @@ class CreateIPsecSiteConnection(neutronv20.CreateCommand):
class UpdateIPsecSiteConnection(neutronv20.UpdateCommand):
- """Update a given IPsecSiteConnection."""
+ """Update a given IPsec site connection."""
resource = 'ipsec_site_connection'
log = logging.getLogger(__name__ + '.UpdateIPsecSiteConnection')
@@ -173,7 +173,7 @@ class UpdateIPsecSiteConnection(neutronv20.UpdateCommand):
'--dpd',
metavar="action=ACTION,interval=INTERVAL,timeout=TIMEOUT",
type=utils.str2dict,
- help=vpn_utils.dpd_help("IPsec connection"))
+ help=vpn_utils.dpd_help("IPsec connection."))
def args2body(self, parsed_args):
body = {'ipsec_site_connection': {
@@ -186,7 +186,7 @@ class UpdateIPsecSiteConnection(neutronv20.UpdateCommand):
class DeleteIPsecSiteConnection(neutronv20.DeleteCommand):
- """Delete a given IPsecSiteConnection."""
+ """Delete a given IPsec site connection."""
resource = 'ipsec_site_connection'
log = logging.getLogger(__name__ + '.DeleteIPsecSiteConnection')
diff --git a/neutronclient/neutron/v2_0/vpn/ipsecpolicy.py b/neutronclient/neutron/v2_0/vpn/ipsecpolicy.py
index 65d2541..6ac182a 100644
--- a/neutronclient/neutron/v2_0/vpn/ipsecpolicy.py
+++ b/neutronclient/neutron/v2_0/vpn/ipsecpolicy.py
@@ -62,10 +62,7 @@ class CreateIPsecPolicy(neutronv20.CreateCommand):
help=_('Authentication algorithm in lowercase, default:sha1'))
parser.add_argument(
'--encryption-algorithm',
- default='aes-128', choices=['3des',
- 'aes-128',
- 'aes-192',
- 'aes-256'],
+ default='aes-128',
help=_('Encryption algorithm in lowercase, default:aes-128'))
parser.add_argument(
'--encapsulation-mode',
diff --git a/neutronclient/shell.py b/neutronclient/shell.py
index 2369c4b..f1f2e2e 100644
--- a/neutronclient/shell.py
+++ b/neutronclient/shell.py
@@ -446,6 +446,12 @@ class NeutronShell(app.App):
help=_('Defaults to env[OS_NETWORK_SERVICE_TYPE] or network.'))
parser.add_argument(
+ '--timeout', metavar='<seconds>',
+ default=env('OS_NETWORK_TIMEOUT', default=None), type=float,
+ help=_('Timeout in seconds to wait for an HTTP response. Defaults '
+ 'to env[OS_NETWORK_TIMEOUT] or None if not specified.'))
+
+ parser.add_argument(
'--endpoint-type', metavar='<endpoint-type>',
default=env('OS_ENDPOINT_TYPE', default='publicURL'),
help=_('Defaults to env[OS_ENDPOINT_TYPE] or publicURL.'))
@@ -643,6 +649,7 @@ class NeutronShell(app.App):
endpoint_type=self.options.endpoint_type,
insecure=self.options.insecure,
ca_cert=self.options.os_cacert,
+ timeout=self.options.timeout,
log_credentials=True)
return
@@ -689,6 +696,7 @@ class NeutronShell(app.App):
formatter = logging.Formatter(self.DEBUG_MESSAGE_FORMAT)
else:
formatter = logging.Formatter(self.CONSOLE_MESSAGE_FORMAT)
+ logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING)
console.setFormatter(formatter)
root_logger.addHandler(console)
return
diff --git a/neutronclient/tests/unit/test_cli20.py b/neutronclient/tests/unit/test_cli20.py
index 8224752..9fd2d38 100644
--- a/neutronclient/tests/unit/test_cli20.py
+++ b/neutronclient/tests/unit/test_cli20.py
@@ -605,6 +605,7 @@ class CLITestV20ExceptionHandler(CLITestV20Base):
('IpAddressInUse', exceptions.IpAddressInUseClient, 409),
('IpAddressGenerationFailure',
exceptions.IpAddressGenerationFailureClient, 409),
+ ('MacAddressInUse', exceptions.MacAddressInUseClient, 409),
('ExternalIpAddressExhausted',
exceptions.ExternalIpAddressExhaustedClient, 400),
('OverQuota', exceptions.OverQuotaClient, 409),
diff --git a/neutronclient/tests/unit/test_cli20_subnet.py b/neutronclient/tests/unit/test_cli20_subnet.py
index d28d6f3..fb34003 100644
--- a/neutronclient/tests/unit/test_cli20_subnet.py
+++ b/neutronclient/tests/unit/test_cli20_subnet.py
@@ -336,6 +336,99 @@ class CLITestV20SubnetJSON(test_cli20.CLITestV20Base):
self.mox.VerifyAll()
self.mox.UnsetStubs()
+ def test_create_subnet_with_ipv6_ra_mode(self):
+ resource = 'subnet'
+ cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None)
+ name = 'myname'
+ myid = 'myid'
+ netid = 'netid'
+ cidr = 'prefixvalue'
+ args = ['--tenant_id', 'tenantid',
+ '--ip-version', '6',
+ '--ipv6-ra-mode', 'dhcpv6-stateful',
+ netid, cidr]
+ position_names = ['ip_version', 'ipv6_ra_mode',
+ 'network_id', 'cidr']
+ position_values = [6, 'dhcpv6-stateful', netid, cidr]
+ self._test_create_resource(resource, cmd, name, myid, args,
+ position_names, position_values,
+ tenant_id='tenantid')
+
+ def test_create_subnet_with_ipv6_address_mode(self):
+ resource = 'subnet'
+ cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None)
+ name = 'myname'
+ myid = 'myid'
+ netid = 'netid'
+ cidr = 'prefixvalue'
+ args = ['--tenant_id', 'tenantid',
+ '--ip-version', '6',
+ '--ipv6-address-mode', 'dhcpv6-stateful',
+ netid, cidr]
+ position_names = ['ip_version', 'ipv6_address_mode',
+ 'network_id', 'cidr']
+ position_values = [6, 'dhcpv6-stateful', netid, cidr]
+
+ self._test_create_resource(resource, cmd, name, myid, args,
+ position_names, position_values,
+ tenant_id='tenantid')
+
+ def test_create_subnet_with_ipv6_modes(self):
+ resource = 'subnet'
+ cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None)
+ name = 'myname'
+ myid = 'myid'
+ netid = 'netid'
+ cidr = 'prefixvalue'
+ args = ['--tenant_id', 'tenantid',
+ '--ip-version', '6',
+ '--ipv6-address-mode', 'slaac',
+ '--ipv6-ra-mode', 'slaac',
+ netid, cidr]
+ position_names = ['ip_version', 'ipv6_address_mode',
+ 'ipv6_ra_mode', 'network_id', 'cidr']
+ position_values = [6, 'slaac', 'slaac', netid, cidr]
+
+ self._test_create_resource(resource, cmd, name, myid, args,
+ position_names, position_values,
+ tenant_id='tenantid')
+
+ def test_create_subnet_with_ipv6_ra_mode_ipv4(self):
+ resource = 'subnet'
+ cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None)
+ name = 'myname'
+ myid = 'myid'
+ netid = 'netid'
+ cidr = 'prefixvalue'
+ args = ['--tenant_id', 'tenantid',
+ '--ip-version', '4',
+ '--ipv6-ra-mode', 'slaac',
+ netid, cidr]
+ position_names = ['ip_version', 'ipv6_ra_mode',
+ 'network_id', 'cidr']
+ position_values = [4, None, netid, cidr]
+ self.assertRaises(exceptions.CommandError, self._test_create_resource,
+ resource, cmd, name, myid, args, position_names,
+ position_values, tenant_id='tenantid')
+
+ def test_create_subnet_with_ipv6_address_mode_ipv4(self):
+ resource = 'subnet'
+ cmd = subnet.CreateSubnet(test_cli20.MyApp(sys.stdout), None)
+ name = 'myname'
+ myid = 'myid'
+ netid = 'netid'
+ cidr = 'prefixvalue'
+ args = ['--tenant_id', 'tenantid',
+ '--ip-version', '4',
+ '--ipv6-address-mode', 'slaac',
+ netid, cidr]
+ position_names = ['ip_version', 'ipv6_address_mode',
+ 'network_id', 'cidr']
+ position_values = [4, None, netid, cidr]
+ self.assertRaises(exceptions.CommandError, self._test_create_resource,
+ resource, cmd, name, myid, args, position_names,
+ position_values, tenant_id='tenantid')
+
def test_list_subnets_detail(self):
"""List subnets: -D."""
resources = "subnets"
diff --git a/neutronclient/tests/unit/test_name_or_id.py b/neutronclient/tests/unit/test_name_or_id.py
index 7ddf804..9d876b9 100644
--- a/neutronclient/tests/unit/test_name_or_id.py
+++ b/neutronclient/tests/unit/test_name_or_id.py
@@ -129,3 +129,50 @@ class CLITestNameorID(testtools.TestCase):
except exceptions.NeutronClientException as ex:
self.assertIn('Unable to find', ex.message)
self.assertEqual(404, ex.status_code)
+
+ def test_get_id_from_name_multiple_with_project(self):
+ name = 'web_server'
+ project = str(uuid.uuid4())
+ expect_id = str(uuid.uuid4())
+ reses = {'security_groups':
+ [{'id': expect_id, 'tenant_id': project}]}
+ resstr = self.client.serialize(reses)
+ self.mox.StubOutWithMock(self.client.httpclient, "request")
+ path = getattr(self.client, "security_groups_path")
+ self.client.httpclient.request(
+ test_cli20.end_url(path, "fields=id&name=%s&tenant_id=%s" %
+ (name, project)),
+ 'GET',
+ body=None,
+ headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN)
+ ).AndReturn((test_cli20.MyResp(200), resstr))
+ self.mox.ReplayAll()
+
+ observed_id = neutronV20.find_resourceid_by_name_or_id(
+ self.client, 'security_group', name, project)
+
+ self.assertEqual(expect_id, observed_id)
+
+ def test_get_id_from_name_multiple_with_project_not_found(self):
+ name = 'web_server'
+ project = str(uuid.uuid4())
+ reses = {'security_groups':
+ [{'id': str(uuid.uuid4()), 'tenant_id': str(uuid.uuid4())}]}
+ resstr = self.client.serialize(reses)
+ self.mox.StubOutWithMock(self.client.httpclient, "request")
+ path = getattr(self.client, "security_groups_path")
+ self.client.httpclient.request(
+ test_cli20.end_url(path, "fields=id&name=%s&tenant_id=%s" %
+ (name, project)),
+ 'GET',
+ body=None,
+ headers=mox.ContainsKeyValue('X-Auth-Token', test_cli20.TOKEN)
+ ).AndReturn((test_cli20.MyResp(200), resstr))
+ self.mox.ReplayAll()
+
+ try:
+ neutronV20.find_resourceid_by_name_or_id(
+ self.client, 'security_group', name, project)
+ except exceptions.NeutronClientException as ex:
+ self.assertIn('Unable to find', ex.message)
+ self.assertEqual(404, ex.status_code)
diff --git a/neutronclient/tests/unit/test_shell.py b/neutronclient/tests/unit/test_shell.py
index b0bb82a..ecda0bf 100644
--- a/neutronclient/tests/unit/test_shell.py
+++ b/neutronclient/tests/unit/test_shell.py
@@ -129,7 +129,7 @@ class ShellTest(testtools.TestCase):
password='test', region_name='', api_version={'network': '2.0'},
auth_strategy='keystone', service_type='network',
endpoint_type='publicURL', insecure=False, ca_cert=None,
- log_credentials=True)
+ log_credentials=True, timeout=None)
neutron_shell.run_subcommand(['quota-list'])
self.mox.ReplayAll()
cmdline = ('--os-username test '
@@ -185,3 +185,26 @@ class ShellTest(testtools.TestCase):
# --endpoint-type and $OS_ENDPOINT_TYPE
namespace = parser.parse_args(['--endpoint-type=admin'])
self.assertEqual('admin', namespace.endpoint_type)
+
+ def test_timeout_option(self):
+ shell = openstack_shell.NeutronShell('2.0')
+ parser = shell.build_option_parser('descr', '2.0')
+
+ # Neither $OS_ENDPOINT_TYPE nor --endpoint-type
+ namespace = parser.parse_args([])
+ self.assertIsNone(namespace.timeout)
+
+ # --endpoint-type but not $OS_ENDPOINT_TYPE
+ namespace = parser.parse_args(['--timeout=50'])
+ self.assertEqual(50, namespace.timeout)
+
+ def test_timeout_environment_variable(self):
+ fixture = fixtures.EnvironmentVariable("OS_NETWORK_TIMEOUT",
+ "50")
+ self.useFixture(fixture)
+
+ shell = openstack_shell.NeutronShell('2.0')
+ parser = shell.build_option_parser('descr', '2.0')
+
+ namespace = parser.parse_args([])
+ self.assertEqual(50, namespace.timeout)
diff --git a/neutronclient/tests/unit/test_ssl.py b/neutronclient/tests/unit/test_ssl.py
index be6e3a2..f22f0d3 100644
--- a/neutronclient/tests/unit/test_ssl.py
+++ b/neutronclient/tests/unit/test_ssl.py
@@ -63,6 +63,7 @@ class TestSSL(testtools.TestCase):
username=mox.IgnoreArg(),
user_id=mox.IgnoreArg(),
log_credentials=mox.IgnoreArg(),
+ timeout=mox.IgnoreArg(),
)
openstack_shell.NeutronShell.interact().AndReturn(0)
self.mox.ReplayAll()
@@ -94,6 +95,7 @@ class TestSSL(testtools.TestCase):
username=mox.IgnoreArg(),
user_id=mox.IgnoreArg(),
log_credentials=mox.IgnoreArg(),
+ timeout=mox.IgnoreArg(),
)
openstack_shell.NeutronShell.interact().AndReturn(0)
self.mox.ReplayAll()
diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py
index 60070de..a102781 100644
--- a/neutronclient/v2_0/client.py
+++ b/neutronclient/v2_0/client.py
@@ -1257,7 +1257,7 @@ class Client(object):
return response.status_code
def serialize(self, data):
- """Serializes a dictionary into either XML or json.
+ """Serializes a dictionary into either XML or JSON.
A dictionary with a single key can be passed and
it can contain any structure.
@@ -1272,7 +1272,7 @@ class Client(object):
type(data))
def deserialize(self, data, status_code):
- """Deserializes an XML or json string into a dictionary."""
+ """Deserializes an XML or JSON string into a dictionary."""
if status_code == 204:
return data
return serializer.Serializer(self.get_attr_metadata()).deserialize(
diff --git a/test-requirements.txt b/test-requirements.txt
index b7b5695..ad976c6 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -5,6 +5,7 @@ coverage>=3.6
discover
fixtures>=0.3.14
mox3>=0.7.0
+oslosphinx
oslotest
python-subunit>=0.0.18
sphinx>=1.1.2,!=1.2.0,<1.3
diff --git a/tox.ini b/tox.ini
index a498e52..bac7c76 100644
--- a/tox.ini
+++ b/tox.ini
@@ -24,6 +24,10 @@ commands = {posargs}
[testenv:cover]
commands = python setup.py testr --coverage --testr-args='{posargs}'
+[testenv:docs]
+commands=
+ python setup.py build_sphinx
+
[tox:jenkins]
downloadcache = ~/cache/pip