Handle unicode multi-byte characters

If you pass unicode multi-byte character to 'hypervisor-list'
and 'instance-usage-audit-log' commands using --matching
and --before options respectively, it returns keyerror.

This patch fixes these issues by encoding the host name and
date passed to the --matching and --before options
respectively.

Closes-Bug: #1804156

Change-Id: I9587af7e0fdd921fcaebe3e5c6c5bb40a9393e01
This commit is contained in:
asmita singh 2019-01-02 06:59:56 +00:00
parent 81ea9887f0
commit 4450e7ba31
6 changed files with 62 additions and 0 deletions

View File

@ -10,6 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_utils import encodeutils
from six.moves.urllib import parse
from novaclient import api_versions
from novaclient.tests.unit.fixture_data import base
@ -130,6 +133,31 @@ class V1(base.Fixture):
json=get_os_hypervisors_search,
headers=self.headers)
if uuid_as_id:
get_os_hypervisors_search_u_v2_53 = {
'error_name': 'BadRequest',
'message': 'Invalid input for query parameters '
'hypervisor_hostname_pattern.',
'code': 400}
# hypervisor_hostname_pattern is encoded in the url method
url = self.url(hypervisor_hostname_pattern='\\u5de5\\u4f5c')
self.requests_mock.get(url,
json=get_os_hypervisors_search_u_v2_53,
headers=self.headers, status_code=400)
else:
get_os_hypervisors_search_unicode = {
'error_name': 'NotFound',
'message': "No hypervisor matching "
"'\\u5de5\\u4f5c' could be found.",
'code': 404
}
hypervisor_hostname_pattern = parse.quote(encodeutils.safe_encode(
'\\u5de5\\u4f5c'))
url = self.url(hypervisor_hostname_pattern, 'search')
self.requests_mock.get(url,
json=get_os_hypervisors_search_unicode,
headers=self.headers, status_code=404)
get_hyper_server = {
'hypervisors': [
{

View File

@ -126,6 +126,7 @@ class FakeSessionClient(base_client.SessionClient):
munged_url = munged_url.replace('@', '_')
munged_url = munged_url.replace('%20', '_')
munged_url = munged_url.replace('%3A', '_')
munged_url = munged_url.replace('%', '_')
callback = "%s_%s" % (method.lower(), munged_url)
if url is None or callback == "get_http:__nova_api:8774":
@ -176,6 +177,10 @@ class FakeSessionClient(base_client.SessionClient):
"text": body,
"headers": headers,
})
if status >= 400:
raise exceptions.from_response(r, body, url, method)
return r, body
def get_versions(self):
@ -2095,6 +2100,9 @@ class FakeSessionClient(base_client.SessionClient):
"total_errors": 3,
"total_instances": 6}})
def get_os_instance_usage_audit_log__5Cu5de5_5Cu4f5c(self, **kw):
return (400, {}, {"Invalid timestamp for date \u6f22\u5b57"})
def post_servers_uuid1_action(self, **kw):
return 202, {}, {}

View File

@ -14,6 +14,7 @@
# under the License.
from novaclient import api_versions
from novaclient import exceptions
from novaclient.tests.unit.fixture_data import client
from novaclient.tests.unit.fixture_data import hypervisors as data
from novaclient.tests.unit import utils
@ -107,6 +108,17 @@ class HypervisorsTest(utils.FixturedTestCase):
for idx, hyper in enumerate(result):
self.compare_to_expected(expected[idx], hyper)
def test_hypervisor_search_unicode(self):
hypervisor_match = u'\\u5de5\\u4f5c'
if self.cs.api_version >= api_versions.APIVersion('2.53'):
self.assertRaises(exceptions.BadRequest,
self.cs.hypervisors.search,
hypervisor_match)
else:
self.assertRaises(exceptions.NotFound,
self.cs.hypervisors.search,
hypervisor_match)
def test_hypervisor_servers(self):
expected = [
dict(id=self.data_fixture.hyper_id_1,

View File

@ -14,6 +14,7 @@
# under the License.
from novaclient import api_versions
from novaclient import exceptions
from novaclient.tests.unit import utils
from novaclient.tests.unit.v2 import fakes
@ -35,3 +36,8 @@ class InstanceUsageAuditLogTests(utils.TestCase):
self.cs.assert_called(
'GET',
'/os-instance_usage_audit_log/2016-12-10%2013%3A59%3A59.999999')
def test_instance_usage_audit_log_with_before_unicode(self):
before = u'\\u5de5\\u4f5c'
self.assertRaises(exceptions.BadRequest,
self.cs.instance_usage_audit_log.get, before)

View File

@ -17,6 +17,8 @@
Hypervisors interface
"""
from oslo_utils import encodeutils
import six
from six.moves.urllib import parse
from novaclient import api_versions
@ -83,6 +85,8 @@ class HypervisorManager(base.ManagerWithFind):
# Starting with microversion 2.53, the /servers and /search routes are
# deprecated and we get the same results using GET /os-hypervisors
# using query parameters for the hostname pattern and servers.
if six.PY2:
hypervisor_match = encodeutils.safe_encode(hypervisor_match)
if self.api_version >= api_versions.APIVersion('2.53'):
url = ('/os-hypervisors?hypervisor_hostname_pattern=%s' %
parse.quote(hypervisor_match, safe=''))

View File

@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_utils import encodeutils
import six
from six.moves.urllib import parse
from novaclient import base
@ -32,6 +34,8 @@ class InstanceUsageAuditLogManager(base.Manager):
before which to list usage audits.
"""
if before:
if six.PY2:
before = encodeutils.safe_encode(before)
return self._get('/os-instance_usage_audit_log/%s' %
parse.quote(before, safe=''),
'instance_usage_audit_log')