diff options
| -rw-r--r-- | doc/source/conf.py | 4 | ||||
| -rw-r--r-- | neutronclient/client.py | 1 | ||||
| -rw-r--r-- | neutronclient/common/clientmanager.py | 5 | ||||
| -rw-r--r-- | neutronclient/common/exceptions.py | 4 | ||||
| -rw-r--r-- | neutronclient/neutron/v2_0/__init__.py | 17 | ||||
| -rw-r--r-- | neutronclient/neutron/v2_0/agentscheduler.py | 4 | ||||
| -rw-r--r-- | neutronclient/neutron/v2_0/router.py | 12 | ||||
| -rw-r--r-- | neutronclient/neutron/v2_0/subnet.py | 19 | ||||
| -rw-r--r-- | neutronclient/neutron/v2_0/vpn/ikepolicy.py | 5 | ||||
| -rw-r--r-- | neutronclient/neutron/v2_0/vpn/ipsec_site_connection.py | 10 | ||||
| -rw-r--r-- | neutronclient/neutron/v2_0/vpn/ipsecpolicy.py | 5 | ||||
| -rw-r--r-- | neutronclient/shell.py | 8 | ||||
| -rw-r--r-- | neutronclient/tests/unit/test_cli20.py | 1 | ||||
| -rw-r--r-- | neutronclient/tests/unit/test_cli20_subnet.py | 93 | ||||
| -rw-r--r-- | neutronclient/tests/unit/test_name_or_id.py | 47 | ||||
| -rw-r--r-- | neutronclient/tests/unit/test_shell.py | 25 | ||||
| -rw-r--r-- | neutronclient/tests/unit/test_ssl.py | 2 | ||||
| -rw-r--r-- | neutronclient/v2_0/client.py | 4 | ||||
| -rw-r--r-- | test-requirements.txt | 1 | ||||
| -rw-r--r-- | tox.ini | 4 |
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 @@ -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 |
