Make use of openstack.common.jsonutils.
This patch imports jsonutils from openstack-common. It removes the equivalent code from nova.utils and then converts the code base to use jsonutils. The primary motivator for this change was to remove the rest of the dependencies from nova.rpc on nova.utils. Change-Id: If43658b9b098ed56cba018c81be268b8c3e2916a
This commit is contained in:
parent
c8cafc6e9d
commit
ba76b954e6
@ -38,6 +38,7 @@ from nova import flags
|
||||
from nova import log as logging
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import importutils
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova import utils
|
||||
from nova import wsgi
|
||||
|
||||
@ -226,7 +227,7 @@ class EC2Token(wsgi.Middleware):
|
||||
'path': req.path,
|
||||
'params': auth_params,
|
||||
}}}
|
||||
creds_json = utils.dumps(creds)
|
||||
creds_json = jsonutils.dumps(creds)
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
|
||||
# Disable "has no x member" pylint error
|
||||
@ -245,7 +246,7 @@ class EC2Token(wsgi.Middleware):
|
||||
# having keystone return token, tenant,
|
||||
# user, and roles from this call.
|
||||
|
||||
result = utils.loads(response)
|
||||
result = jsonutils.loads(response)
|
||||
try:
|
||||
token_id = result['access']['token']['id']
|
||||
except (AttributeError, KeyError), e:
|
||||
@ -289,7 +290,7 @@ class EC2KeystoneAuth(wsgi.Middleware):
|
||||
creds = {'ec2Credentials': cred_dict}
|
||||
else:
|
||||
creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}}
|
||||
creds_json = utils.dumps(creds)
|
||||
creds_json = jsonutils.dumps(creds)
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
|
||||
o = urlparse.urlparse(FLAGS.keystone_ec2_url)
|
||||
@ -306,7 +307,7 @@ class EC2KeystoneAuth(wsgi.Middleware):
|
||||
else:
|
||||
msg = _("Failure communicating with keystone")
|
||||
return ec2_error(req, request_id, "Unauthorized", msg)
|
||||
result = utils.loads(data)
|
||||
result = jsonutils.loads(data)
|
||||
conn.close()
|
||||
|
||||
try:
|
||||
@ -645,7 +646,7 @@ class Executor(wsgi.Application):
|
||||
env.pop(k)
|
||||
|
||||
LOG.exception(_('Unexpected error raised: %s'), unicode(ex))
|
||||
LOG.error(_('Environment: %s') % utils.dumps(env))
|
||||
LOG.error(_('Environment: %s') % jsonutils.dumps(env))
|
||||
return ec2_error(req, request_id, 'UnknownError',
|
||||
_('An unknown error has occurred. '
|
||||
'Please try your request again.'))
|
||||
|
@ -26,7 +26,7 @@ import webob
|
||||
|
||||
from nova import exception
|
||||
from nova import log as logging
|
||||
from nova import utils
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova import wsgi
|
||||
|
||||
|
||||
@ -130,7 +130,7 @@ class JSONDeserializer(TextDeserializer):
|
||||
|
||||
def _from_json(self, datastring):
|
||||
try:
|
||||
return utils.loads(datastring)
|
||||
return jsonutils.loads(datastring)
|
||||
except ValueError:
|
||||
msg = _("cannot understand JSON")
|
||||
raise exception.MalformedRequestBody(reason=msg)
|
||||
@ -242,7 +242,7 @@ class JSONDictSerializer(DictSerializer):
|
||||
"""Default JSON request body serialization"""
|
||||
|
||||
def default(self, data):
|
||||
return utils.dumps(data)
|
||||
return jsonutils.dumps(data)
|
||||
|
||||
|
||||
class XMLDictSerializer(DictSerializer):
|
||||
@ -533,7 +533,7 @@ def action_peek_json(body):
|
||||
"""Determine action to invoke."""
|
||||
|
||||
try:
|
||||
decoded = utils.loads(body)
|
||||
decoded = jsonutils.loads(body)
|
||||
except ValueError:
|
||||
msg = _("cannot understand JSON")
|
||||
raise exception.MalformedRequestBody(reason=msg)
|
||||
|
@ -40,6 +40,7 @@ import nova.image
|
||||
from nova import log as logging
|
||||
from nova import network
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import jsonutils
|
||||
import nova.policy
|
||||
from nova import quota
|
||||
from nova import rpc
|
||||
@ -652,7 +653,7 @@ class API(BaseAPI):
|
||||
locals())
|
||||
|
||||
request_spec = {
|
||||
'image': utils.to_primitive(image),
|
||||
'image': jsonutils.to_primitive(image),
|
||||
'instance_properties': base_options,
|
||||
'instance_type': instance_type,
|
||||
'num_instances': num_instances,
|
||||
@ -1482,7 +1483,7 @@ class API(BaseAPI):
|
||||
"instance_type_id": new_instance_type['id'],
|
||||
"image": image,
|
||||
"update_db": False,
|
||||
"request_spec": utils.to_primitive(request_spec),
|
||||
"request_spec": jsonutils.to_primitive(request_spec),
|
||||
"filter_properties": filter_properties,
|
||||
}
|
||||
self._cast_scheduler_message(context,
|
||||
|
@ -64,6 +64,7 @@ from nova.notifier import api as notifier
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import excutils
|
||||
from nova.openstack.common import importutils
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova import rpc
|
||||
from nova import utils
|
||||
from nova.virt import driver
|
||||
@ -397,7 +398,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
bdm['device_name'])
|
||||
self.db.block_device_mapping_update(
|
||||
context, bdm['id'],
|
||||
{'connection_info': utils.dumps(cinfo)})
|
||||
{'connection_info': jsonutils.dumps(cinfo)})
|
||||
block_device_mapping.append({'connection_info': cinfo,
|
||||
'mount_device':
|
||||
bdm['device_name']})
|
||||
@ -635,7 +636,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
bdms = self._get_instance_volume_bdms(context, instance_uuid)
|
||||
block_device_mapping = []
|
||||
for bdm in bdms:
|
||||
cinfo = utils.loads(bdm['connection_info'])
|
||||
cinfo = jsonutils.loads(bdm['connection_info'])
|
||||
block_device_mapping.append({'connection_info': cinfo,
|
||||
'mount_device':
|
||||
bdm['device_name']})
|
||||
@ -1775,7 +1776,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
mountpoint)
|
||||
values = {
|
||||
'instance_uuid': instance_ref['uuid'],
|
||||
'connection_info': utils.dumps(connection_info),
|
||||
'connection_info': jsonutils.dumps(connection_info),
|
||||
'device_name': mountpoint,
|
||||
'delete_on_termination': False,
|
||||
'virtual_name': None,
|
||||
@ -1799,7 +1800,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
if instance_name not in self.driver.list_instances():
|
||||
LOG.warn(_('Detaching volume from unknown instance'),
|
||||
context=context, instance=instance)
|
||||
self.driver.detach_volume(utils.loads(bdm['connection_info']),
|
||||
self.driver.detach_volume(jsonutils.loads(bdm['connection_info']),
|
||||
instance_name,
|
||||
mp)
|
||||
|
||||
|
@ -65,6 +65,7 @@ from nova.network import model as network_model
|
||||
from nova.notifier import api as notifier
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import importutils
|
||||
from nova.openstack.common import jsonutils
|
||||
import nova.policy
|
||||
from nova import quota
|
||||
from nova import rpc
|
||||
@ -194,7 +195,7 @@ class RPCAllocateFixedIP(object):
|
||||
host = rpc.call(context, FLAGS.network_topic,
|
||||
{'method': 'set_network_host',
|
||||
'args': {'network_ref':
|
||||
utils.to_primitive(network)}})
|
||||
jsonutils.to_primitive(network)}})
|
||||
if host != self.host:
|
||||
# need to call allocate_fixed_ip to correct network host
|
||||
topic = self.db.queue_get_for(context,
|
||||
|
@ -21,7 +21,7 @@ import json
|
||||
import socket
|
||||
import urllib
|
||||
|
||||
from nova import utils
|
||||
from nova.openstack.common import jsonutils
|
||||
|
||||
|
||||
# FIXME(danwent): All content in this file should be removed once the
|
||||
@ -35,14 +35,11 @@ class JSONSerializer(object):
|
||||
the standard serializer from the quantum library.
|
||||
"""
|
||||
def serialize(self, data, content_type):
|
||||
try:
|
||||
return json.dumps(data)
|
||||
except TypeError:
|
||||
pass
|
||||
return json.dumps(utils.to_primitive(data))
|
||||
jsonutils.dumps(data)
|
||||
|
||||
def deserialize(self, data, content_type):
|
||||
return json.loads(data)
|
||||
return jsonutils.loads(data)
|
||||
|
||||
|
||||
# Quantum API v1.0 uses 420 + 430 for network + port not found
|
||||
# Quantum API v1.1 uses 404 for network + port not found
|
||||
|
@ -21,6 +21,7 @@ from nova import flags
|
||||
from nova import log as logging
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import importutils
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova import utils
|
||||
|
||||
|
||||
@ -121,7 +122,7 @@ def notify(context, publisher_id, event_type, priority, payload):
|
||||
_('%s not in valid priorities') % priority)
|
||||
|
||||
# Ensure everything is JSON serializable.
|
||||
payload = utils.to_primitive(payload, convert_instances=True)
|
||||
payload = jsonutils.to_primitive(payload, convert_instances=True)
|
||||
|
||||
driver = importutils.import_module(FLAGS.notification_driver)
|
||||
msg = dict(message_id=str(uuid.uuid4()),
|
||||
|
133
nova/openstack/common/jsonutils.py
Normal file
133
nova/openstack/common/jsonutils.py
Normal file
@ -0,0 +1,133 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2010 United States Government as represented by the
|
||||
# Administrator of the National Aeronautics and Space Administration.
|
||||
# Copyright 2011 Justin Santa Barbara
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
'''
|
||||
JSON related utilities.
|
||||
|
||||
This module provides a few things:
|
||||
|
||||
1) A handy function for getting an object down to something that can be
|
||||
JSON serialized. See to_primitive().
|
||||
|
||||
2) Wrappers around loads() and dumps(). The dumps() wrapper will
|
||||
automatically use to_primitive() for you if needed.
|
||||
|
||||
3) This sets up anyjson to use the loads() and dumps() wrappers if anyjson
|
||||
is available.
|
||||
'''
|
||||
|
||||
|
||||
import datetime
|
||||
import inspect
|
||||
import itertools
|
||||
import json
|
||||
|
||||
|
||||
def to_primitive(value, convert_instances=False, level=0):
|
||||
"""Convert a complex object into primitives.
|
||||
|
||||
Handy for JSON serialization. We can optionally handle instances,
|
||||
but since this is a recursive function, we could have cyclical
|
||||
data structures.
|
||||
|
||||
To handle cyclical data structures we could track the actual objects
|
||||
visited in a set, but not all objects are hashable. Instead we just
|
||||
track the depth of the object inspections and don't go too deep.
|
||||
|
||||
Therefore, convert_instances=True is lossy ... be aware.
|
||||
|
||||
"""
|
||||
nasty = [inspect.ismodule, inspect.isclass, inspect.ismethod,
|
||||
inspect.isfunction, inspect.isgeneratorfunction,
|
||||
inspect.isgenerator, inspect.istraceback, inspect.isframe,
|
||||
inspect.iscode, inspect.isbuiltin, inspect.isroutine,
|
||||
inspect.isabstract]
|
||||
for test in nasty:
|
||||
if test(value):
|
||||
return unicode(value)
|
||||
|
||||
# value of itertools.count doesn't get caught by inspects
|
||||
# above and results in infinite loop when list(value) is called.
|
||||
if type(value) == itertools.count:
|
||||
return unicode(value)
|
||||
|
||||
# FIXME(vish): Workaround for LP bug 852095. Without this workaround,
|
||||
# tests that raise an exception in a mocked method that
|
||||
# has a @wrap_exception with a notifier will fail. If
|
||||
# we up the dependency to 0.5.4 (when it is released) we
|
||||
# can remove this workaround.
|
||||
if getattr(value, '__module__', None) == 'mox':
|
||||
return 'mock'
|
||||
|
||||
if level > 3:
|
||||
return '?'
|
||||
|
||||
# The try block may not be necessary after the class check above,
|
||||
# but just in case ...
|
||||
try:
|
||||
if isinstance(value, (list, tuple)):
|
||||
o = []
|
||||
for v in value:
|
||||
o.append(to_primitive(v, convert_instances=convert_instances,
|
||||
level=level))
|
||||
return o
|
||||
elif isinstance(value, dict):
|
||||
o = {}
|
||||
for k, v in value.iteritems():
|
||||
o[k] = to_primitive(v, convert_instances=convert_instances,
|
||||
level=level)
|
||||
return o
|
||||
elif isinstance(value, datetime.datetime):
|
||||
return str(value)
|
||||
elif hasattr(value, 'iteritems'):
|
||||
return to_primitive(dict(value.iteritems()),
|
||||
convert_instances=convert_instances,
|
||||
level=level)
|
||||
elif hasattr(value, '__iter__'):
|
||||
return to_primitive(list(value), level)
|
||||
elif convert_instances and hasattr(value, '__dict__'):
|
||||
# Likely an instance of something. Watch for cycles.
|
||||
# Ignore class member vars.
|
||||
return to_primitive(value.__dict__,
|
||||
convert_instances=convert_instances,
|
||||
level=level + 1)
|
||||
else:
|
||||
return value
|
||||
except TypeError, e:
|
||||
# Class objects are tricky since they may define something like
|
||||
# __iter__ defined but it isn't callable as list().
|
||||
return unicode(value)
|
||||
|
||||
|
||||
def dumps(value):
|
||||
return json.dumps(value, default=to_primitive)
|
||||
|
||||
|
||||
def loads(s):
|
||||
return json.loads(s)
|
||||
|
||||
|
||||
try:
|
||||
import anyjson
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
anyjson._modules.append((__name__, 'dumps', TypeError,
|
||||
'loads', ValueError))
|
||||
anyjson.force_implementation(__name__)
|
@ -25,7 +25,7 @@ from nova import exception
|
||||
from nova import log as logging
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import importutils
|
||||
from nova import utils
|
||||
from nova.openstack.common import jsonutils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -174,13 +174,13 @@ def serialize_remote_exception(failure_info):
|
||||
'kwargs': kwargs
|
||||
}
|
||||
|
||||
json_data = utils.dumps(data)
|
||||
json_data = jsonutils.dumps(data)
|
||||
|
||||
return json_data
|
||||
|
||||
|
||||
def deserialize_remote_exception(conf, data):
|
||||
failure = utils.loads(str(data))
|
||||
failure = jsonutils.loads(str(data))
|
||||
|
||||
trace = failure.get('tb', [])
|
||||
message = failure.get('message', "") + "\n" + "\n".join(trace)
|
||||
|
@ -30,6 +30,7 @@ from nova import flags
|
||||
from nova import log as logging
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import importutils
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova import rpc
|
||||
from nova.rpc import common as rpc_common
|
||||
from nova import utils
|
||||
@ -442,7 +443,7 @@ class Scheduler(object):
|
||||
ret = rpc.call(context, topic,
|
||||
{"method": 'get_instance_disk_info',
|
||||
"args": {'instance_name': instance_ref['name']}})
|
||||
disk_infos = utils.loads(ret)
|
||||
disk_infos = jsonutils.loads(ret)
|
||||
|
||||
necessary = 0
|
||||
if disk_over_commit:
|
||||
|
@ -22,10 +22,10 @@ from nova.api.openstack.compute import extensions
|
||||
from nova.api.openstack import wsgi
|
||||
import nova.db.api
|
||||
from nova import flags
|
||||
from nova.openstack.common import jsonutils
|
||||
import nova.rpc
|
||||
from nova import test
|
||||
from nova.tests.api.openstack import fakes
|
||||
from nova import utils
|
||||
|
||||
|
||||
MANUAL_INSTANCE_UUID = fakes.FAKE_UUID
|
||||
@ -130,19 +130,19 @@ class DiskConfigTestCase(test.TestCase):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/fake/servers/%s' % MANUAL_INSTANCE_UUID)
|
||||
res = req.get_response(self.app)
|
||||
server_dict = utils.loads(res.body)['server']
|
||||
server_dict = jsonutils.loads(res.body)['server']
|
||||
self.assertDiskConfig(server_dict, 'MANUAL')
|
||||
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/fake/servers/%s' % AUTO_INSTANCE_UUID)
|
||||
res = req.get_response(self.app)
|
||||
server_dict = utils.loads(res.body)['server']
|
||||
server_dict = jsonutils.loads(res.body)['server']
|
||||
self.assertDiskConfig(server_dict, 'AUTO')
|
||||
|
||||
def test_detail_servers(self):
|
||||
req = fakes.HTTPRequest.blank('/fake/servers/detail')
|
||||
res = req.get_response(self.app)
|
||||
server_dicts = utils.loads(res.body)['servers']
|
||||
server_dicts = jsonutils.loads(res.body)['servers']
|
||||
|
||||
expectations = ['MANUAL', 'AUTO']
|
||||
for server_dict, expected in zip(server_dicts, expectations):
|
||||
@ -152,19 +152,19 @@ class DiskConfigTestCase(test.TestCase):
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/fake/images/a440c04b-79fa-479c-bed1-0b816eaec379')
|
||||
res = req.get_response(self.app)
|
||||
image_dict = utils.loads(res.body)['image']
|
||||
image_dict = jsonutils.loads(res.body)['image']
|
||||
self.assertDiskConfig(image_dict, 'MANUAL')
|
||||
|
||||
req = fakes.HTTPRequest.blank(
|
||||
'/fake/images/70a599e0-31e7-49b7-b260-868f441e862b')
|
||||
res = req.get_response(self.app)
|
||||
image_dict = utils.loads(res.body)['image']
|
||||
image_dict = jsonutils.loads(res.body)['image']
|
||||
self.assertDiskConfig(image_dict, 'AUTO')
|
||||
|
||||
def test_detail_image(self):
|
||||
req = fakes.HTTPRequest.blank('/fake/images/detail')
|
||||
res = req.get_response(self.app)
|
||||
image_dicts = utils.loads(res.body)['images']
|
||||
image_dicts = jsonutils.loads(res.body)['images']
|
||||
|
||||
expectations = ['MANUAL', 'AUTO']
|
||||
for image_dict, expected in zip(image_dicts, expectations):
|
||||
@ -184,9 +184,9 @@ class DiskConfigTestCase(test.TestCase):
|
||||
API_DISK_CONFIG: 'AUTO'
|
||||
}}
|
||||
|
||||
req.body = utils.dumps(body)
|
||||
req.body = jsonutils.dumps(body)
|
||||
res = req.get_response(self.app)
|
||||
server_dict = utils.loads(res.body)['server']
|
||||
server_dict = jsonutils.loads(res.body)['server']
|
||||
self.assertDiskConfig(server_dict, 'AUTO')
|
||||
|
||||
def test_create_server_override_manual(self):
|
||||
@ -200,9 +200,9 @@ class DiskConfigTestCase(test.TestCase):
|
||||
API_DISK_CONFIG: 'MANUAL'
|
||||
}}
|
||||
|
||||
req.body = utils.dumps(body)
|
||||
req.body = jsonutils.dumps(body)
|
||||
res = req.get_response(self.app)
|
||||
server_dict = utils.loads(res.body)['server']
|
||||
server_dict = jsonutils.loads(res.body)['server']
|
||||
self.assertDiskConfig(server_dict, 'MANUAL')
|
||||
|
||||
def test_create_server_detect_from_image(self):
|
||||
@ -218,9 +218,9 @@ class DiskConfigTestCase(test.TestCase):
|
||||
'flavorRef': '1',
|
||||
}}
|
||||
|
||||
req.body = utils.dumps(body)
|
||||
req.body = jsonutils.dumps(body)
|
||||
res = req.get_response(self.app)
|
||||
server_dict = utils.loads(res.body)['server']
|
||||
server_dict = jsonutils.loads(res.body)['server']
|
||||
self.assertDiskConfig(server_dict, 'MANUAL')
|
||||
|
||||
req = fakes.HTTPRequest.blank('/fake/servers')
|
||||
@ -232,9 +232,9 @@ class DiskConfigTestCase(test.TestCase):
|
||||
'flavorRef': '1',
|
||||
}}
|
||||
|
||||
req.body = utils.dumps(body)
|
||||
req.body = jsonutils.dumps(body)
|
||||
res = req.get_response(self.app)
|
||||
server_dict = utils.loads(res.body)['server']
|
||||
server_dict = jsonutils.loads(res.body)['server']
|
||||
self.assertDiskConfig(server_dict, 'AUTO')
|
||||
|
||||
def test_update_server_invalid_disk_config(self):
|
||||
@ -244,7 +244,7 @@ class DiskConfigTestCase(test.TestCase):
|
||||
req.method = 'PUT'
|
||||
req.content_type = 'application/json'
|
||||
body = {'server': {API_DISK_CONFIG: 'server_test'}}
|
||||
req.body = utils.dumps(body)
|
||||
req.body = jsonutils.dumps(body)
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(res.status_int, 400)
|
||||
expected_msg = ('{"badRequest": {"message": "%s must be either'
|
||||
|
@ -19,10 +19,10 @@ from nova.api.openstack import compute
|
||||
from nova.api.openstack.compute import extensions
|
||||
from nova.api.openstack import wsgi
|
||||
import nova.db.api
|
||||
from nova.openstack.common import jsonutils
|
||||
import nova.rpc
|
||||
from nova import test
|
||||
from nova.tests.api.openstack import fakes
|
||||
from nova import utils
|
||||
|
||||
|
||||
UUID = fakes.FAKE_UUID
|
||||
@ -52,7 +52,7 @@ class SchedulerHintsTestCase(test.TestCase):
|
||||
'flavorRef': '1',
|
||||
}}
|
||||
|
||||
req.body = utils.dumps(body)
|
||||
req.body = jsonutils.dumps(body)
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(202, res.status_int)
|
||||
|
||||
@ -76,7 +76,7 @@ class SchedulerHintsTestCase(test.TestCase):
|
||||
'os:scheduler_hints': {'a': 'b'},
|
||||
}
|
||||
|
||||
req.body = utils.dumps(body)
|
||||
req.body = jsonutils.dumps(body)
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(202, res.status_int)
|
||||
|
||||
@ -93,6 +93,6 @@ class SchedulerHintsTestCase(test.TestCase):
|
||||
'os:scheduler_hints': 'here',
|
||||
}
|
||||
|
||||
req.body = utils.dumps(body)
|
||||
req.body = jsonutils.dumps(body)
|
||||
res = req.get_response(self.app)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
@ -39,6 +39,7 @@ from nova import context
|
||||
from nova.db.sqlalchemy import models
|
||||
from nova import exception as exc
|
||||
import nova.image.fake
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova.tests import fake_network
|
||||
from nova.tests.glance import stubs as glance_stubs
|
||||
from nova import utils
|
||||
@ -464,7 +465,7 @@ def create_info_cache(nw_cache):
|
||||
return {"info_cache": {"network_info": nw_cache}}
|
||||
|
||||
if not isinstance(nw_cache, basestring):
|
||||
nw_cache = utils.dumps(nw_cache)
|
||||
nw_cache = jsonutils.dumps(nw_cache)
|
||||
|
||||
return {"info_cache": {"network_info": nw_cache}}
|
||||
|
||||
|
@ -20,9 +20,9 @@ import mox
|
||||
import StringIO
|
||||
|
||||
from nova import flags
|
||||
from nova import utils
|
||||
from nova import test
|
||||
from nova.compute import power_state
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova.tests import fake_utils
|
||||
from nova import exception
|
||||
|
||||
@ -95,8 +95,8 @@ class DomainReadWriteTestCase(test.TestCase):
|
||||
|
||||
def assertJSONEquals(self, x, y):
|
||||
"""Check if two json strings represent the equivalent Python object"""
|
||||
self.assertEquals(utils.loads(x), utils.loads(y))
|
||||
return utils.loads(x) == utils.loads(y)
|
||||
self.assertEquals(jsonutils.loads(x), jsonutils.loads(y))
|
||||
return jsonutils.loads(x) == jsonutils.loads(y)
|
||||
|
||||
def test_write_domain(self):
|
||||
"""Write the domain to file"""
|
||||
|
@ -15,8 +15,8 @@
|
||||
|
||||
import nova.db.api
|
||||
from nova.notifier import capacity_notifier as cn
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova import test
|
||||
from nova import utils
|
||||
|
||||
|
||||
class CapacityNotifierTestCase(test.TestCase):
|
||||
@ -24,7 +24,7 @@ class CapacityNotifierTestCase(test.TestCase):
|
||||
|
||||
def _make_msg(self, host, event):
|
||||
usage_info = dict(memory_mb=123, disk_gb=456)
|
||||
payload = utils.to_primitive(usage_info, convert_instances=True)
|
||||
payload = jsonutils.to_primitive(usage_info, convert_instances=True)
|
||||
return dict(
|
||||
publisher_id="compute.%s" % host,
|
||||
event_type="compute.instance.%s" % event,
|
||||
|
@ -38,6 +38,7 @@ from nova import exception
|
||||
from nova import flags
|
||||
from nova import log as logging
|
||||
from nova.openstack.common import importutils
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova import test
|
||||
from nova.tests import fake_network
|
||||
from nova.tests import fake_libvirt_utils
|
||||
@ -1405,7 +1406,7 @@ class LibvirtConnTestCase(test.TestCase):
|
||||
self.mox.ReplayAll()
|
||||
conn = connection.LibvirtConnection(False)
|
||||
info = conn.get_instance_disk_info(instance_ref.name)
|
||||
info = utils.loads(info)
|
||||
info = jsonutils.loads(info)
|
||||
self.assertEquals(info[0]['type'], 'raw')
|
||||
self.assertEquals(info[0]['path'], '/test/disk')
|
||||
self.assertEquals(info[0]['disk_size'], 10737418240)
|
||||
@ -2507,7 +2508,7 @@ class LibvirtConnectionTestCase(test.TestCase):
|
||||
'virt_disk_size': '10737418240',
|
||||
'backing_file': '/base/disk.local',
|
||||
'disk_size':'83886080'}]
|
||||
disk_info_text = utils.dumps(disk_info)
|
||||
disk_info_text = jsonutils.dumps(disk_info)
|
||||
|
||||
def fake_get_instance_disk_info(instance):
|
||||
return disk_info_text
|
||||
@ -2578,7 +2579,7 @@ class LibvirtConnectionTestCase(test.TestCase):
|
||||
'local_gb': 10, 'backing_file': '/base/disk'},
|
||||
{'type': 'raw', 'path': '/test/disk.local',
|
||||
'local_gb': 10, 'backing_file': '/base/disk.local'}]
|
||||
disk_info_text = utils.dumps(disk_info)
|
||||
disk_info_text = jsonutils.dumps(disk_info)
|
||||
|
||||
def fake_extend(path, size):
|
||||
pass
|
||||
@ -2668,4 +2669,4 @@ class LibvirtNonblockingTestCase(test.TestCase):
|
||||
"""Test bug 962840"""
|
||||
import nova.virt.libvirt.connection
|
||||
connection = nova.virt.libvirt.connection.get_connection('')
|
||||
utils.to_primitive(connection._conn, convert_instances=True)
|
||||
jsonutils.to_primitive(connection._conn, convert_instances=True)
|
||||
|
@ -443,93 +443,6 @@ class IsUUIDLikeTestCase(test.TestCase):
|
||||
self.assertUUIDLike(str(utils.gen_uuid()), True)
|
||||
|
||||
|
||||
class ToPrimitiveTestCase(test.TestCase):
|
||||
def test_list(self):
|
||||
self.assertEquals(utils.to_primitive([1, 2, 3]), [1, 2, 3])
|
||||
|
||||
def test_empty_list(self):
|
||||
self.assertEquals(utils.to_primitive([]), [])
|
||||
|
||||
def test_tuple(self):
|
||||
self.assertEquals(utils.to_primitive((1, 2, 3)), [1, 2, 3])
|
||||
|
||||
def test_dict(self):
|
||||
self.assertEquals(utils.to_primitive(dict(a=1, b=2, c=3)),
|
||||
dict(a=1, b=2, c=3))
|
||||
|
||||
def test_empty_dict(self):
|
||||
self.assertEquals(utils.to_primitive({}), {})
|
||||
|
||||
def test_datetime(self):
|
||||
x = datetime.datetime(1, 2, 3, 4, 5, 6, 7)
|
||||
self.assertEquals(utils.to_primitive(x), "0001-02-03 04:05:06.000007")
|
||||
|
||||
def test_iter(self):
|
||||
class IterClass(object):
|
||||
def __init__(self):
|
||||
self.data = [1, 2, 3, 4, 5]
|
||||
self.index = 0
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
if self.index == len(self.data):
|
||||
raise StopIteration
|
||||
self.index = self.index + 1
|
||||
return self.data[self.index - 1]
|
||||
|
||||
x = IterClass()
|
||||
self.assertEquals(utils.to_primitive(x), [1, 2, 3, 4, 5])
|
||||
|
||||
def test_iteritems(self):
|
||||
class IterItemsClass(object):
|
||||
def __init__(self):
|
||||
self.data = dict(a=1, b=2, c=3).items()
|
||||
self.index = 0
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def next(self):
|
||||
if self.index == len(self.data):
|
||||
raise StopIteration
|
||||
self.index = self.index + 1
|
||||
return self.data[self.index - 1]
|
||||
|
||||
x = IterItemsClass()
|
||||
ordered = utils.to_primitive(x)
|
||||
ordered.sort()
|
||||
self.assertEquals(ordered, [['a', 1], ['b', 2], ['c', 3]])
|
||||
|
||||
def test_instance(self):
|
||||
class MysteryClass(object):
|
||||
a = 10
|
||||
|
||||
def __init__(self):
|
||||
self.b = 1
|
||||
|
||||
x = MysteryClass()
|
||||
self.assertEquals(utils.to_primitive(x, convert_instances=True),
|
||||
dict(b=1))
|
||||
|
||||
self.assertEquals(utils.to_primitive(x), x)
|
||||
|
||||
def test_typeerror(self):
|
||||
x = bytearray # Class, not instance
|
||||
self.assertEquals(utils.to_primitive(x), u"<type 'bytearray'>")
|
||||
|
||||
def test_nasties(self):
|
||||
def foo():
|
||||
pass
|
||||
x = [datetime, foo, dir]
|
||||
ret = utils.to_primitive(x)
|
||||
self.assertEquals(len(ret), 3)
|
||||
self.assertTrue(ret[0].startswith(u"<module 'datetime' from "))
|
||||
self.assertTrue(ret[1].startswith('<function foo at 0x'))
|
||||
self.assertEquals(ret[2], '<built-in function dir>')
|
||||
|
||||
|
||||
class MonkeyPatchTestCase(test.TestCase):
|
||||
"""Unit test for utils.monkey_patch()."""
|
||||
def setUp(self):
|
||||
|
100
nova/utils.py
100
nova/utils.py
@ -25,8 +25,6 @@ import errno
|
||||
import functools
|
||||
import hashlib
|
||||
import inspect
|
||||
import itertools
|
||||
import json
|
||||
import os
|
||||
import pyclbr
|
||||
import random
|
||||
@ -677,104 +675,6 @@ def utf8(value):
|
||||
return value
|
||||
|
||||
|
||||
def to_primitive(value, convert_instances=False, level=0):
|
||||
"""Convert a complex object into primitives.
|
||||
|
||||
Handy for JSON serialization. We can optionally handle instances,
|
||||
but since this is a recursive function, we could have cyclical
|
||||
data structures.
|
||||
|
||||
To handle cyclical data structures we could track the actual objects
|
||||
visited in a set, but not all objects are hashable. Instead we just
|
||||
track the depth of the object inspections and don't go too deep.
|
||||
|
||||
Therefore, convert_instances=True is lossy ... be aware.
|
||||
|
||||
"""
|
||||
nasty = [inspect.ismodule, inspect.isclass, inspect.ismethod,
|
||||
inspect.isfunction, inspect.isgeneratorfunction,
|
||||
inspect.isgenerator, inspect.istraceback, inspect.isframe,
|
||||
inspect.iscode, inspect.isbuiltin, inspect.isroutine,
|
||||
inspect.isabstract]
|
||||
for test in nasty:
|
||||
if test(value):
|
||||
return unicode(value)
|
||||
|
||||
# value of itertools.count doesn't get caught by inspects
|
||||
# above and results in infinite loop when list(value) is called.
|
||||
if type(value) == itertools.count:
|
||||
return unicode(value)
|
||||
|
||||
# FIXME(vish): Workaround for LP bug 852095. Without this workaround,
|
||||
# tests that raise an exception in a mocked method that
|
||||
# has a @wrap_exception with a notifier will fail. If
|
||||
# we up the dependency to 0.5.4 (when it is released) we
|
||||
# can remove this workaround.
|
||||
if getattr(value, '__module__', None) == 'mox':
|
||||
return 'mock'
|
||||
|
||||
if level > 3:
|
||||
return '?'
|
||||
|
||||
# The try block may not be necessary after the class check above,
|
||||
# but just in case ...
|
||||
try:
|
||||
if isinstance(value, (list, tuple)):
|
||||
o = []
|
||||
for v in value:
|
||||
o.append(to_primitive(v, convert_instances=convert_instances,
|
||||
level=level))
|
||||
return o
|
||||
elif isinstance(value, dict):
|
||||
o = {}
|
||||
for k, v in value.iteritems():
|
||||
o[k] = to_primitive(v, convert_instances=convert_instances,
|
||||
level=level)
|
||||
return o
|
||||
elif isinstance(value, datetime.datetime):
|
||||
return str(value)
|
||||
elif hasattr(value, 'iteritems'):
|
||||
return to_primitive(dict(value.iteritems()),
|
||||
convert_instances=convert_instances,
|
||||
level=level)
|
||||
elif hasattr(value, '__iter__'):
|
||||
return to_primitive(list(value), level)
|
||||
elif convert_instances and hasattr(value, '__dict__'):
|
||||
# Likely an instance of something. Watch for cycles.
|
||||
# Ignore class member vars.
|
||||
return to_primitive(value.__dict__,
|
||||
convert_instances=convert_instances,
|
||||
level=level + 1)
|
||||
else:
|
||||
return value
|
||||
except TypeError, e:
|
||||
# Class objects are tricky since they may define something like
|
||||
# __iter__ defined but it isn't callable as list().
|
||||
return unicode(value)
|
||||
|
||||
|
||||
def dumps(value):
|
||||
try:
|
||||
return json.dumps(value)
|
||||
except TypeError:
|
||||
pass
|
||||
return json.dumps(to_primitive(value))
|
||||
|
||||
|
||||
def loads(s):
|
||||
return json.loads(s)
|
||||
|
||||
|
||||
try:
|
||||
import anyjson
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
anyjson._modules.append(("nova.utils", "dumps", TypeError,
|
||||
"loads", ValueError))
|
||||
anyjson.force_implementation("nova.utils")
|
||||
|
||||
|
||||
class GreenLockFile(lockfile.FileLock):
|
||||
"""Implementation of lockfile that allows for a lock per greenthread.
|
||||
|
||||
|
@ -18,7 +18,7 @@ from nova.compute import power_state
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova import log as logging
|
||||
from nova import utils
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova.virt.baremetal import nodes
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
@ -31,14 +31,14 @@ def read_domains(fname):
|
||||
f = open(fname, 'r')
|
||||
json = f.read()
|
||||
f.close()
|
||||
domains = utils.loads(json)
|
||||
domains = jsonutils.loads(json)
|
||||
return domains
|
||||
except IOError:
|
||||
raise exception.NotFound()
|
||||
|
||||
|
||||
def write_domains(fname, domains):
|
||||
json = utils.dumps(domains)
|
||||
json = jsonutils.dumps(domains)
|
||||
f = open(fname, 'w')
|
||||
f.write(json)
|
||||
f.close()
|
||||
|
@ -66,6 +66,7 @@ from nova import log as logging
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import excutils
|
||||
from nova.openstack.common import importutils
|
||||
from nova.openstack.common import jsonutils
|
||||
from nova import utils
|
||||
from nova.virt import driver
|
||||
from nova.virt.disk import api as disk
|
||||
@ -2017,7 +2018,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
|
||||
cpu_info['topology'] = topology
|
||||
cpu_info['features'] = features
|
||||
return utils.dumps(cpu_info)
|
||||
return jsonutils.dumps(cpu_info)
|
||||
|
||||
def block_stats(self, instance_name, disk):
|
||||
"""
|
||||
@ -2102,7 +2103,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
|
||||
"""
|
||||
|
||||
info = utils.loads(cpu_info)
|
||||
info = jsonutils.loads(cpu_info)
|
||||
LOG.info(_('Instance launched has CPU info:\n%s') % cpu_info)
|
||||
cpu = config.LibvirtConfigCPU()
|
||||
cpu.arch = info['arch']
|
||||
@ -2277,7 +2278,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
json strings specified in get_instance_disk_info
|
||||
|
||||
"""
|
||||
disk_info = utils.loads(disk_info_json)
|
||||
disk_info = jsonutils.loads(disk_info_json)
|
||||
|
||||
# make instance directory
|
||||
instance_dir = os.path.join(FLAGS.instances_path, instance_ref['name'])
|
||||
@ -2414,7 +2415,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
'virt_disk_size': virt_size,
|
||||
'backing_file': backing_file,
|
||||
'disk_size': dk_size})
|
||||
return utils.dumps(disk_info)
|
||||
return jsonutils.dumps(disk_info)
|
||||
|
||||
def get_disk_available_least(self):
|
||||
"""Return disk available least size.
|
||||
@ -2434,7 +2435,8 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
instances_sz = 0
|
||||
for i_name in instances_name:
|
||||
try:
|
||||
disk_infos = utils.loads(self.get_instance_disk_info(i_name))
|
||||
disk_infos = jsonutils.loads(
|
||||
self.get_instance_disk_info(i_name))
|
||||
for info in disk_infos:
|
||||
i_vt_sz = int(info['virt_disk_size'])
|
||||
i_dk_sz = int(info['disk_size'])
|
||||
@ -2495,7 +2497,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
LOG.debug(_("Starting migrate_disk_and_power_off"),
|
||||
instance=instance)
|
||||
disk_info_text = self.get_instance_disk_info(instance['name'])
|
||||
disk_info = utils.loads(disk_info_text)
|
||||
disk_info = jsonutils.loads(disk_info_text)
|
||||
|
||||
self._destroy(instance, network_info, cleanup=False)
|
||||
|
||||
@ -2561,7 +2563,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
LOG.debug(_("Starting finish_migration"), instance=instance)
|
||||
|
||||
# resize disks. only "disk" and "disk.local" are necessary.
|
||||
disk_info = utils.loads(disk_info)
|
||||
disk_info = jsonutils.loads(disk_info)
|
||||
for info in disk_info:
|
||||
fname = os.path.basename(info['path'])
|
||||
if fname == 'disk':
|
||||
@ -2647,7 +2649,7 @@ class HostState(object):
|
||||
data = {}
|
||||
data["vcpus"] = self.connection.get_vcpu_total()
|
||||
data["vcpus_used"] = self.connection.get_vcpu_used()
|
||||
data["cpu_info"] = utils.loads(self.connection.get_cpu_info())
|
||||
data["cpu_info"] = jsonutils.loads(self.connection.get_cpu_info())
|
||||
data["disk_total"] = self.connection.get_local_gb_total()
|
||||
data["disk_used"] = self.connection.get_local_gb_used()
|
||||
data["disk_available"] = data["disk_total"] - data["disk_used"]
|
||||
|
@ -1,7 +1,7 @@
|
||||
[DEFAULT]
|
||||
|
||||
# The list of modules to copy from openstack-common
|
||||
modules=cfg,excutils,local,importutils,iniparser,setup
|
||||
modules=cfg,excutils,local,importutils,iniparser,jsonutils,setup
|
||||
|
||||
# The base module to hold the copy of openstack.common
|
||||
base=nova
|
||||
|
Loading…
x
Reference in New Issue
Block a user