Use Oslo's bool_from_string

Oslo provides an equivalent implmentation of `bool_from_str` so we
should switch the code to use that instead.

Change-Id: I382f23af2468e276ae4342dff18cf06e1c24b755
This commit is contained in:
Rick Harris
2013-05-09 22:39:20 +00:00
parent da1d7390fe
commit 1b9489fb0d
15 changed files with 223 additions and 66 deletions
@@ -21,7 +21,7 @@ from webob import exc
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
from nova import utils
from nova.openstack.common import strutils
ALIAS = 'OS-DCF'
XMLNS_DCF = "http://docs.openstack.org/compute/ext/disk_config/api/v1.1"
@@ -65,7 +65,7 @@ class ImageDiskConfigController(wsgi.Controller):
metadata = image['metadata']
if INTERNAL_DISK_CONFIG in metadata:
raw_value = metadata[INTERNAL_DISK_CONFIG]
value = utils.bool_from_str(raw_value)
value = strutils.bool_from_string(raw_value)
image[API_DISK_CONFIG] = disk_config_to_api(value)
@wsgi.extends
@@ -21,6 +21,7 @@ from nova.api.openstack import wsgi
from nova import compute
from nova import exception
from nova.openstack.common import log as logging
from nova.openstack.common import strutils
from nova import utils
LOG = logging.getLogger(__name__)
@@ -47,7 +48,7 @@ class Controller(wsgi.Controller):
evacuate_body = body["evacuate"]
host = evacuate_body["host"]
on_shared_storage = utils.bool_from_str(
on_shared_storage = strutils.bool_from_string(
evacuate_body["onSharedStorage"])
password = None
@@ -25,6 +25,7 @@ from nova.api.openstack import xmlutil
from nova import compute
from nova import exception
from nova.openstack.common import log as logging
from nova.openstack.common import strutils
from nova.openstack.common import uuidutils
from nova import utils
from nova import volume
@@ -620,7 +621,7 @@ class SnapshotController(wsgi.Controller):
msg = _("Invalid value '%s' for force.") % force
raise exception.InvalidParameterValue(err=msg)
if utils.bool_from_str(force):
if strutils.bool_from_string(force):
new_snapshot = self.volume_api.create_snapshot_force(context,
vol,
snapshot.get('display_name'),
+10 -13
View File
@@ -23,6 +23,7 @@ from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
from nova.compute import flavors
from nova import exception
from nova.openstack.common import strutils
def make_flavor(elem, detailed=False):
@@ -91,25 +92,20 @@ class Controller(wsgi.Controller):
return self._view_builder.show(req, flavor)
def _get_is_public(self, req):
def _parse_is_public(self, is_public):
"""Parse is_public into something usable."""
is_public = req.params.get('is_public', None)
if is_public is None:
# preserve default value of showing only public flavors
return True
elif is_public is True or \
is_public.lower() in ['t', 'true', 'yes', '1']:
return True
elif is_public is False or \
is_public.lower() in ['f', 'false', 'no', '0']:
return False
elif is_public.lower() == 'none':
# value to match all flavors, ignore is_public
elif is_public == 'none':
return None
else:
msg = _('Invalid is_public filter [%s]') % req.params['is_public']
raise webob.exc.HTTPBadRequest(explanation=msg)
try:
return strutils.bool_from_string(is_public, strict=True)
except ValueError:
msg = _('Invalid is_public filter [%s]') % is_public
raise webob.exc.HTTPBadRequest(explanation=msg)
def _get_flavors(self, req):
"""Helper function that returns a list of flavor dicts."""
@@ -118,7 +114,8 @@ class Controller(wsgi.Controller):
context = req.environ['nova.context']
if context.is_admin:
# Only admin has query access to all flavor types
filters['is_public'] = self._get_is_public(req)
filters['is_public'] = self._parse_is_public(
req.params.get('is_public', None))
else:
filters['is_public'] = True
filters['disabled'] = False
+6 -4
View File
@@ -33,6 +33,7 @@ from nova import exception
from nova.openstack.common import importutils
from nova.openstack.common import log as logging
from nova.openstack.common.rpc import common as rpc_common
from nova.openstack.common import strutils
from nova.openstack.common import timeutils
from nova.openstack.common import uuidutils
from nova import utils
@@ -185,7 +186,8 @@ class CommonDeserializer(wsgi.MetadataXMLDeserializer):
res_id = server_node.getAttribute('return_reservation_id')
if res_id:
server['return_reservation_id'] = utils.bool_from_str(res_id)
server['return_reservation_id'] = \
strutils.bool_from_string(res_id)
scheduler_hints = self._extract_scheduler_hints(server_node)
if scheduler_hints:
@@ -253,7 +255,7 @@ class CommonDeserializer(wsgi.MetadataXMLDeserializer):
for attr in attributes:
value = child.getAttribute(attr)
if value:
mapping[attr] = utils.bool_from_str(value)
mapping[attr] = strutils.bool_from_string(value)
block_device_mapping.append(mapping)
return block_device_mapping
else:
@@ -826,7 +828,7 @@ class Controller(wsgi.Controller):
for bdm in block_device_mapping:
self._validate_device_name(bdm["device_name"])
if 'delete_on_termination' in bdm:
bdm['delete_on_termination'] = utils.bool_from_str(
bdm['delete_on_termination'] = strutils.bool_from_string(
bdm['delete_on_termination'])
ret_resv_id = False
@@ -991,7 +993,7 @@ class Controller(wsgi.Controller):
update_dict['access_ip_v6'] = access_ipv6.strip()
if 'auto_disk_config' in body['server']:
auto_disk_config = utils.bool_from_str(
auto_disk_config = strutils.bool_from_string(
body['server']['auto_disk_config'])
update_dict['auto_disk_config'] = auto_disk_config
+2 -1
View File
@@ -53,6 +53,7 @@ from nova import notifications
from nova.openstack.common import excutils
from nova.openstack.common import jsonutils
from nova.openstack.common import log as logging
from nova.openstack.common import strutils
from nova.openstack.common import timeutils
from nova.openstack.common import uuidutils
import nova.policy
@@ -439,7 +440,7 @@ class API(base.Base):
if value is not None:
if prop_type == 'bool':
value = utils.bool_from_str(value)
value = strutils.bool_from_string(value)
return value
+2 -1
View File
@@ -30,6 +30,7 @@ from nova import db
from nova import exception
from nova.openstack.common.db import exception as db_exc
from nova.openstack.common import log as logging
from nova.openstack.common import strutils
from nova import utils
instance_type_opts = [
@@ -130,7 +131,7 @@ def create(name, memory, vcpus, root_gb, ephemeral_gb=None, flavorid=None,
if not utils.is_valid_boolstr(is_public):
msg = _("is_public must be a boolean")
raise exception.InvalidInput(reason=msg)
kwargs['is_public'] = utils.bool_from_str(is_public)
kwargs['is_public'] = strutils.bool_from_string(is_public)
try:
return db.instance_type_create(context.get_admin_context(), kwargs)
+6 -4
View File
@@ -70,6 +70,7 @@ from nova.openstack.common import lockutils
from nova.openstack.common import log as logging
from nova.openstack.common import periodic_task
from nova.openstack.common.rpc import common as rpc_common
from nova.openstack.common import strutils
from nova.openstack.common import timeutils
from nova.openstack.common import uuidutils
from nova import quota
@@ -1030,10 +1031,11 @@ class NetworkManager(manager.Manager):
else:
kwargs["network_size"] = CONF.network_size
kwargs["multi_host"] = (CONF.multi_host
if kwargs["multi_host"] is None
else
utils.bool_from_str(kwargs["multi_host"]))
kwargs["multi_host"] = (
CONF.multi_host
if kwargs["multi_host"] is None
else strutils.bool_from_string(kwargs["multi_host"]))
kwargs["vlan_start"] = kwargs.get("vlan_start") or CONF.vlan_start
kwargs["vpn_start"] = kwargs.get("vpn_start") or CONF.vpn_start
kwargs["dns1"] = kwargs["dns1"] or CONF.flat_network_dns
+150
View File
@@ -0,0 +1,150 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack Foundation.
# 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.
"""
System-level utilities and helper functions.
"""
import sys
from nova.openstack.common.gettextutils import _
TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes')
FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no')
def int_from_bool_as_string(subject):
"""
Interpret a string as a boolean and return either 1 or 0.
Any string value in:
('True', 'true', 'On', 'on', '1')
is interpreted as a boolean True.
Useful for JSON-decoded stuff and config file parsing
"""
return bool_from_string(subject) and 1 or 0
def bool_from_string(subject, strict=False):
"""
Interpret a string as a boolean.
A case-insensitive match is performed such that strings matching 't',
'true', 'on', 'y', 'yes', or '1' are considered True and, when
`strict=False`, anything else is considered False.
Useful for JSON-decoded stuff and config file parsing.
If `strict=True`, unrecognized values, including None, will raise a
ValueError which is useful when parsing values passed in from an API call.
Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'.
"""
if not isinstance(subject, basestring):
subject = str(subject)
lowered = subject.strip().lower()
if lowered in TRUE_STRINGS:
return True
elif lowered in FALSE_STRINGS:
return False
elif strict:
acceptable = ', '.join(
"'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS))
msg = _("Unrecognized value '%(val)s', acceptable values are:"
" %(acceptable)s") % {'val': subject,
'acceptable': acceptable}
raise ValueError(msg)
else:
return False
def safe_decode(text, incoming=None, errors='strict'):
"""
Decodes incoming str using `incoming` if they're
not already unicode.
:param incoming: Text's current encoding
:param errors: Errors handling policy. See here for valid
values http://docs.python.org/2/library/codecs.html
:returns: text or a unicode `incoming` encoded
representation of it.
:raises TypeError: If text is not an isntance of basestring
"""
if not isinstance(text, basestring):
raise TypeError("%s can't be decoded" % type(text))
if isinstance(text, unicode):
return text
if not incoming:
incoming = (sys.stdin.encoding or
sys.getdefaultencoding())
try:
return text.decode(incoming, errors)
except UnicodeDecodeError:
# Note(flaper87) If we get here, it means that
# sys.stdin.encoding / sys.getdefaultencoding
# didn't return a suitable encoding to decode
# text. This happens mostly when global LANG
# var is not set correctly and there's no
# default encoding. In this case, most likely
# python will use ASCII or ANSI encoders as
# default encodings but they won't be capable
# of decoding non-ASCII characters.
#
# Also, UTF-8 is being used since it's an ASCII
# extension.
return text.decode('utf-8', errors)
def safe_encode(text, incoming=None,
encoding='utf-8', errors='strict'):
"""
Encodes incoming str/unicode using `encoding`. If
incoming is not specified, text is expected to
be encoded with current python's default encoding.
(`sys.getdefaultencoding`)
:param incoming: Text's current encoding
:param encoding: Expected encoding for text (Default UTF-8)
:param errors: Errors handling policy. See here for valid
values http://docs.python.org/2/library/codecs.html
:returns: text or a bytestring `encoding` encoded
representation of it.
:raises TypeError: If text is not an isntance of basestring
"""
if not isinstance(text, basestring):
raise TypeError("%s can't be encoded" % type(text))
if not incoming:
incoming = (sys.stdin.encoding or
sys.getdefaultencoding())
if isinstance(text, unicode):
return text.encode(encoding, errors)
elif text and encoding != incoming:
# Decode text before encoding it with `encoding`
text = safe_decode(text, incoming, errors)
return text.encode(encoding, errors)
return text
@@ -762,3 +762,37 @@ class DisabledFlavorsWithRealDBTest(test.TestCase):
self.req, self.disabled_type['flavorid'])['flavor']
self.assertEqual(flavor['name'], self.disabled_type['name'])
class ParseIsPublicTest(test.TestCase):
def setUp(self):
super(ParseIsPublicTest, self).setUp()
self.controller = flavors.Controller()
def assertPublic(self, expected, is_public):
self.assertIs(expected, self.controller._parse_is_public(is_public),
'%s did not return %s' % (is_public, expected))
def test_None(self):
self.assertPublic(True, None)
def test_truthy(self):
self.assertPublic(True, True)
self.assertPublic(True, 't')
self.assertPublic(True, 'true')
self.assertPublic(True, 'yes')
self.assertPublic(True, '1')
def test_falsey(self):
self.assertPublic(False, False)
self.assertPublic(False, 'f')
self.assertPublic(False, 'false')
self.assertPublic(False, 'no')
self.assertPublic(False, '0')
def test_string_none(self):
self.assertPublic(None, 'none')
def test_other(self):
self.assertRaises(
webob.exc.HTTPBadRequest, self.assertPublic, None, 'other')
@@ -2436,7 +2436,7 @@ class ServersControllerCreateTest(test.TestCase):
{'device_name': 'foo3', 'delete_on_termination': 'invalid'},
{'device_name': 'foo4', 'delete_on_termination': 0},
{'device_name': 'foo5', 'delete_on_termination': False}]
expected_dbm = [
expected_bdm = [
{'device_name': 'foo1', 'delete_on_termination': True},
{'device_name': 'foo2', 'delete_on_termination': True},
{'device_name': 'foo3', 'delete_on_termination': False},
@@ -2446,7 +2446,7 @@ class ServersControllerCreateTest(test.TestCase):
old_create = compute_api.API.create
def create(*args, **kwargs):
self.assertEqual(kwargs['block_device_mapping'], expected_dbm)
self.assertEqual(expected_bdm, kwargs['block_device_mapping'])
return old_create(*args, **kwargs)
self.stubs.Set(compute_api.API, 'create', create)
-22
View File
@@ -276,28 +276,6 @@ class GenericUtilsTestCase(test.TestCase):
hostname = "<}\x1fh\x10e\x08l\x02l\x05o\x12!{>"
self.assertEqual("hello", utils.sanitize_hostname(hostname))
def test_bool_from_str(self):
self.assertTrue(utils.bool_from_str('1'))
self.assertTrue(utils.bool_from_str('2'))
self.assertTrue(utils.bool_from_str('-1'))
self.assertTrue(utils.bool_from_str('true'))
self.assertTrue(utils.bool_from_str('True'))
self.assertTrue(utils.bool_from_str('tRuE'))
self.assertTrue(utils.bool_from_str('yes'))
self.assertTrue(utils.bool_from_str('Yes'))
self.assertTrue(utils.bool_from_str('YeS'))
self.assertTrue(utils.bool_from_str('y'))
self.assertTrue(utils.bool_from_str('Y'))
self.assertFalse(utils.bool_from_str('False'))
self.assertFalse(utils.bool_from_str('false'))
self.assertFalse(utils.bool_from_str('no'))
self.assertFalse(utils.bool_from_str('No'))
self.assertFalse(utils.bool_from_str('n'))
self.assertFalse(utils.bool_from_str('N'))
self.assertFalse(utils.bool_from_str('0'))
self.assertFalse(utils.bool_from_str(None))
self.assertFalse(utils.bool_from_str('junk'))
def test_read_cached_file(self):
self.mox.StubOutWithMock(os.path, "getmtime")
os.path.getmtime(mox.IgnoreArg()).AndReturn(1)
-13
View File
@@ -655,19 +655,6 @@ def parse_server_string(server_str):
return ('', '')
def bool_from_str(val):
"""Convert a string representation of a bool into a bool value."""
if not val:
return False
try:
return True if int(val) else False
except ValueError:
return val.lower() == 'true' or \
val.lower() == 'yes' or \
val.lower() == 'y'
def is_int_like(val):
"""Check if a value looks like an int."""
try:
+4 -2
View File
@@ -45,6 +45,7 @@ from nova.image import glance
from nova.openstack.common import excutils
from nova.openstack.common import log as logging
from nova.openstack.common import processutils
from nova.openstack.common import strutils
from nova import utils
from nova.virt import configdrive
from nova.virt.disk import api as disk
@@ -998,7 +999,7 @@ def _create_image(context, session, instance, name_label, image_id,
elif cache_images == 'some':
sys_meta = utils.metadata_to_dict(instance['system_metadata'])
try:
cache = utils.bool_from_str(sys_meta['image_cache_in_nova'])
cache = strutils.bool_from_string(sys_meta['image_cache_in_nova'])
except KeyError:
cache = False
elif cache_images == 'none':
@@ -1091,7 +1092,8 @@ def _image_uses_bittorrent(context, instance):
elif xenapi_torrent_images == 'some':
sys_meta = utils.metadata_to_dict(instance['system_metadata'])
try:
bittorrent = utils.bool_from_str(sys_meta['image_bittorrent'])
bittorrent = strutils.bool_from_string(
sys_meta['image_bittorrent'])
except KeyError:
pass
elif xenapi_torrent_images == 'none':
+1
View File
@@ -25,6 +25,7 @@ module=policy
module=processutils
module=rootwrap
module=rpc
module=strutils
module=timeutils
module=uuidutils
module=version