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:
@@ -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'),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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':
|
||||
|
||||
@@ -25,6 +25,7 @@ module=policy
|
||||
module=processutils
|
||||
module=rootwrap
|
||||
module=rpc
|
||||
module=strutils
|
||||
module=timeutils
|
||||
module=uuidutils
|
||||
module=version
|
||||
|
||||
Reference in New Issue
Block a user