Align API types with database types

In more recent versions of SQLAlchemy library the datatypes
filters are stricter and now rejects strings with boolean values
such as "True"/"False" to a field mapped as boolean in the
underlying database.

This commit:

1. Aligns fields with API types mapped as string but with its
database counterparts mapped as boolean, also changing places
where the value was being compared as a string

2. Fixes the bool_or_none function used to parse boolean types,
as it was returning True when strings like 'false', 'n' and 'no'
were passed as parameter

3. Removes code from sensor and sensorgroup API that was checking
the now boolean field against string values (confirmed that there
are no references to force-action in hwmon code on metal repo)

Test Plan:
PASS: install/bootstrap/unlock host
PASS: test cgtsclient system commands for changed attributes:
      - host: ttys_dcd
        (verified manifest apply msg on logs)
      - memory: hugepages_configured, vm_pending_as_percentage,
                vm_hugepages_use_1G
        (executed "grep Huge /proc/meminfo" after host-unlock)
      - sensor: suppress
        (verified suppress/unsuppress msgs on logs)
      - sensorgroup: suppress
        (verified suppress/unsuppress msgs on logs)
        (verified propagated suppress/suppress msgs on logs)
PASS: run AIO-SX upgrade successfully
PASS: all of the above on Debian (except upgrade)

Closes-bug: 1977517
Change-Id: Ie78f98b1b6141dc7ea5e4a125c64d50e1993f582
Signed-off-by: Heitor Matsui <HeitorVieira.Matsui@windriver.com>
This commit is contained in:
Heitor Matsui 2022-06-28 17:35:17 -03:00
parent 2914421a12
commit ebd16cc31b
16 changed files with 73 additions and 94 deletions

View File

@ -16,7 +16,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2021 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
@ -428,7 +428,7 @@ class Host(base.APIBase):
mtce_info = wtypes.text
"Represent the mtce info"
reserved = wtypes.text
reserved = types.boolean
config_status = wtypes.text
"Represent the configuration status of this ihost."
@ -535,7 +535,7 @@ class Host(base.APIBase):
vsc_controllers = wtypes.text
"Represent the VSC controllers used by this ihost."
ttys_dcd = wtypes.text
ttys_dcd = types.boolean
"Enable or disable serial console carrier detect"
software_load = wtypes.text
@ -1972,9 +1972,12 @@ class HostController(rest.RestController):
if key in ihost_dict and key not in patched_ihost:
patched_ihost[key] = defaults[key]
# Update only the fields that have changed
if ihost_obj[key] != patched_ihost[key]:
ihost_obj[key] = patched_ihost[key]
# To compare, first cast the patch value into same datatype
# using the corresponding parsing function for the field in
# ihost_obj and then update only the fields that have changed
parsed_patch_value = ihost_obj.fields[key](patched_ihost[key])
if ihost_obj[key] != parsed_patch_value:
ihost_obj[key] = parsed_patch_value
delta = ihost_obj.obj_what_changed()
delta_handle = list(delta)
@ -3895,12 +3898,12 @@ class HostController(rest.RestController):
for m in mems:
memtotal = m.node_memtotal_mib
allocated = m.platform_reserved_mib
if m.hugepages_configured == "True":
if m.hugepages_configured is True:
if m.vswitch_hugepages_reqd is not None:
allocated += m.vswitch_hugepages_reqd * m.vswitch_hugepages_size_mib
else:
allocated += m.vswitch_hugepages_nr * m.vswitch_hugepages_size_mib
if(m.vm_pending_as_percentage == "True"):
if m.vm_pending_as_percentage is True:
if m.vm_hugepages_nr_2M_pending is not None:
allocated += (memtotal - allocated) \
* m.vm_hugepages_nr_2M_pending // 100
@ -4029,20 +4032,20 @@ class HostController(rest.RestController):
for node in ihost_inodes:
mems = pecan.request.dbapi.imemory_get_by_inode(node['id'])
for m in mems:
if m.hugepages_configured == "True":
if m.hugepages_configured is True:
value = {}
vs_hugepages_nr = m.vswitch_hugepages_nr
if m.vm_hugepages_nr_2M_pending is not None:
vm_hugepages_nr_2M = m.vm_hugepages_nr_2M_pending
elif m.vm_hugepages_2M_percentage is not None and m.vm_pending_as_percentage == "True":
elif m.vm_hugepages_2M_percentage is not None and m.vm_pending_as_percentage is True:
vm_hugepages_nr_2M = m.vm_hugepages_2M_percentage
else:
vm_hugepages_nr_2M = m.vm_hugepages_nr_2M
if m.vm_hugepages_nr_1G_pending is not None:
vm_hugepages_nr_1G = m.vm_hugepages_nr_1G_pending
elif m.vm_hugepages_1G_percentage is not None and m.vm_pending_as_percentage == "True":
elif m.vm_hugepages_1G_percentage is not None and m.vm_pending_as_percentage is True:
vm_hugepages_nr_1G = m.vm_hugepages_1G_percentage
else:
vm_hugepages_nr_1G = m.vm_hugepages_nr_1G
@ -4062,7 +4065,7 @@ class HostController(rest.RestController):
# Current value might not be suitable after upgrading or
# patching
if m.vm_pending_as_percentage == "False" and vm_hugepages_nr_2M > int((vm_mem_mib * 0.9) //
if m.vm_pending_as_percentage is False and vm_hugepages_nr_2M > int((vm_mem_mib * 0.9) //
constants.MIB_2M):
vm_hugepages_nr_2M = int((vm_mem_mib * 0.9) //
constants.MIB_2M)

View File

@ -15,10 +15,9 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2021 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
import jsonpatch
import pecan
@ -92,7 +91,7 @@ class Memory(base.APIBase):
platform_reserved_mib = int
"Represent the imemory platform reserved in MiB"
hugepages_configured = wtypes.text
hugepages_configured = types.boolean
"Represent whether huge pages are configured"
vswitch_hugepages_size_mib = int
@ -107,7 +106,7 @@ class Memory(base.APIBase):
vswitch_hugepages_avail = int
"Represent the imemory vswitch number of hugepages available"
vm_pending_as_percentage = wtypes.text
vm_pending_as_percentage = types.boolean
"Represents if the hugepages are represented by percentage (True) or by integer (False)."
vm_hugepages_nr_2M_pending = int
@ -134,7 +133,7 @@ class Memory(base.APIBase):
vm_hugepages_nr_4K = int
"Represent the imemory vm number of hugepages (4K pages)"
vm_hugepages_use_1G = wtypes.text
vm_hugepages_use_1G = types.boolean
"1G hugepage is supported 'True' or not 'False' "
vm_hugepages_avail_1G = int
@ -427,11 +426,11 @@ class MemoryController(rest.RestController):
vswitch_hugepages_size_mib = p['value']
if p['path'] == '/vm_pending_as_percentage':
vm_pending_as_percentage = p['value']
vm_pending_as_percentage = rpc_port.fields['vm_pending_as_percentage'](p['value'])
if vm_pending_as_percentage is None:
vm_pending_as_percentage = rpc_port["vm_pending_as_percentage"]
elif vm_pending_as_percentage == "True":
elif vm_pending_as_percentage is True:
if vm_hugepages_nr_2M_pending is not None:
patch.append({'op': 'replace', 'path': '/vm_hugepages_2M_percentage',
'value': vm_hugepages_nr_2M_pending})
@ -687,7 +686,7 @@ def _check_memory(dbapi, rpc_port, ihost, platform_reserved_mib=None,
# Check if it is within the total amount of memory
mem_alloc = 0
if vm_pending_as_percentage == "True":
if vm_pending_as_percentage is True:
if vm_hugepages_nr_2M_pending is not None:
mem_alloc += int(hp_mem_avail * int(vm_hugepages_nr_2M_pending) // 100)
elif rpc_port['vm_hugepages_2M_percentage'] is not None:
@ -737,7 +736,7 @@ def _check_huge_values(rpc_port, patch, vm_hugepages_nr_2M=None,
platform_reserved_mib=None, vm_pending_as_percentage=None,
has_vswitch_enabled=False):
if rpc_port['vm_hugepages_use_1G'] == 'False':
if rpc_port['vm_hugepages_use_1G'] is False:
vs_hp_size = vswitch_hugepages_size_mib
if vm_hugepages_nr_1G or vs_hp_size == constants.MIB_1G:
# cannot provision 1G huge pages if the processor does not support
@ -838,14 +837,14 @@ def _check_huge_values(rpc_port, patch, vm_hugepages_nr_2M=None,
new_1G_pages = int(vm_hugepages_nr_1G)
elif rpc_port['vm_hugepages_nr_1G_pending']:
new_1G_pages = int(rpc_port['vm_hugepages_nr_1G_pending'])
elif vm_pending_as_percentage == "True" and rpc_port['vm_hugepages_1G_percentage']:
elif vm_pending_as_percentage is True and rpc_port['vm_hugepages_1G_percentage']:
new_1G_pages = int(rpc_port['vm_hugepages_1G_percentage'])
elif rpc_port['vm_hugepages_nr_1G']:
new_1G_pages = int(rpc_port['vm_hugepages_nr_1G'])
else:
new_1G_pages = 0
if(vm_pending_as_percentage == "True"):
if vm_pending_as_percentage is True:
vm_hp_1G_reqd_mib = int((node_memtotal_mib - base_mem_mib
- int(new_vs_pages * vs_hp_size_mib))
* new_1G_pages // 100)
@ -857,7 +856,7 @@ def _check_huge_values(rpc_port, patch, vm_hugepages_nr_2M=None,
new_2M_pages = int(vm_hugepages_nr_2M)
elif rpc_port['vm_hugepages_nr_2M_pending']:
new_2M_pages = int(rpc_port['vm_hugepages_nr_2M_pending'])
elif vm_pending_as_percentage == "True" and rpc_port['vm_hugepages_2M_percentage']:
elif vm_pending_as_percentage is True and rpc_port['vm_hugepages_2M_percentage']:
new_2M_pages = int(rpc_port['vm_hugepages_2M_percentage'])
elif rpc_port['vm_hugepages_nr_2M']:
new_2M_pages = int(rpc_port['vm_hugepages_nr_2M'])
@ -867,7 +866,7 @@ def _check_huge_values(rpc_port, patch, vm_hugepages_nr_2M=None,
hp_mem_avail = node_memtotal_mib - base_mem_mib \
- int(new_vs_pages * vs_hp_size_mib)
if(vm_pending_as_percentage == "True"):
if vm_pending_as_percentage is True:
vm_hp_2M_reqd_mib = int(hp_mem_avail * new_2M_pages // 100)
else:
vm_hp_2M_reqd_mib = new_2M_pages * constants.MIB_2M
@ -900,7 +899,7 @@ def _check_huge_values(rpc_port, patch, vm_hugepages_nr_2M=None,
"Host only supports single huge page size."))
# Check if percentage of pages is within valid range
if(vm_pending_as_percentage == "True"):
if vm_pending_as_percentage is True:
if(not 0 <= new_2M_pages <= 100):
raise wsme.exc.ClientSideError(_(
"2M hugepage percent allocation must be within 0% - 100%."))

View File

@ -15,10 +15,9 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
import copy
import jsonpatch
import pecan
from pecan import rest
@ -96,7 +95,7 @@ class Sensor(base.APIBase):
actions_critical = wtypes.text
"Represent the critical configured actions of the isensor. CSV."
suppress = wtypes.text
suppress = types.boolean
"Represent supress isensor if True, otherwise not suppress isensor"
value = wtypes.text
@ -434,8 +433,6 @@ class SensorController(rest.RestController):
raise wsme.exc.ClientSideError(_("Invalid datatype=%s" %
rpc_sensor.datatype))
rpc_sensor_orig = copy.deepcopy(rpc_sensor)
# replace ihost_uuid and isensorgroup_uuid with corresponding
utils.validate_patch(patch)
patch_obj = jsonpatch.JsonPatch(patch)
@ -478,18 +475,13 @@ class SensorController(rest.RestController):
delta = rpc_sensor.obj_what_changed()
sensor_suppress_attrs = ['suppress']
force_action = False
if any(x in delta for x in sensor_suppress_attrs):
valid_suppress = ['True', 'False', 'true', 'false', 'force_action']
if rpc_sensor.suppress.lower() not in valid_suppress:
valid_suppress = [True, False]
if rpc_sensor.suppress not in valid_suppress:
raise wsme.exc.ClientSideError(_("Invalid suppress value, "
"select 'True' or 'False'"))
elif rpc_sensor.suppress.lower() == 'force_action':
LOG.info("suppress=%s" % rpc_sensor.suppress.lower())
rpc_sensor.suppress = rpc_sensor_orig.suppress
force_action = True
self._semantic_modifiable_fields(patch_obj, force_action)
self._semantic_modifiable_fields(patch_obj)
if not pecan.request.user_agent.startswith('hwmon'):
hwmon_sensor = cutils.removekeys_nonhwmon(
@ -521,10 +513,7 @@ class SensorController(rest.RestController):
hwmon_response.get('reason'),
hwmon_response.get('action'))
if force_action:
LOG.error(msg)
else:
raise wsme.exc.ClientSideError(msg)
raise wsme.exc.ClientSideError(msg)
rpc_sensor.save()

View File

@ -15,10 +15,9 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2016 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
import copy
import jsonpatch
import pecan
from pecan import rest
@ -136,7 +135,7 @@ class SensorGroup(base.APIBase):
six.integer_types)}
"Represent meta data of the isensorgroup"
suppress = wtypes.text
suppress = types.boolean
"Represent supress isensor if True, otherwise not suppress isensor"
sensors = wtypes.text
@ -462,8 +461,6 @@ class SensorGroupController(rest.RestController):
raise wsme.exc.ClientSideError(_("Invalid datatype=%s" %
rsensorgroup.datatype))
rsensorgroup_orig = copy.deepcopy(rsensorgroup)
host = pecan.request.dbapi.ihost_get(
rsensorgroup['host_id']).as_dict()
@ -509,20 +506,14 @@ class SensorGroupController(rest.RestController):
rsensorgroup[field] = getattr(sensorgroup, field)
delta = rsensorgroup.obj_what_changed()
sensorgroup_suppress_attrs = ['suppress']
force_action = False
if any(x in delta for x in sensorgroup_suppress_attrs):
valid_suppress = ['True', 'False', 'true', 'false', 'force_action']
if rsensorgroup.suppress.lower() not in valid_suppress:
valid_suppress = [True, False]
if rsensorgroup.suppress not in valid_suppress:
raise wsme.exc.ClientSideError(_("Invalid suppress value, "
"select 'True' or 'False'"))
elif rsensorgroup.suppress.lower() == 'force_action':
LOG.info("suppress=%s" % rsensorgroup.suppress.lower())
rsensorgroup.suppress = rsensorgroup_orig.suppress
force_action = True
self._semantic_modifiable_fields(patch_obj, force_action)
self._semantic_modifiable_fields(patch_obj)
if not pecan.request.user_agent.startswith('hwmon'):
hwmon_sensorgroup = cutils.removekeys_nonhwmon(
@ -553,10 +544,7 @@ class SensorGroupController(rest.RestController):
hwmon_response.get('reason'),
hwmon_response.get('action'))
if force_action:
LOG.error(msg)
else:
raise wsme.exc.ClientSideError(msg)
raise wsme.exc.ClientSideError(msg)
sensorgroup_prop_attrs = ['audit_interval_group',
'actions_minor_group',

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2019 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -51,7 +51,7 @@ class Host(base.SysinvObject):
'subfunction_oper': utils.str_or_none,
'subfunction_avail': utils.str_or_none,
# Host is working on a blocking process
'reserved': utils.str_or_none,
'reserved': utils.bool_or_none,
# NOTE: instance_uuid must be read-only when server is provisioned
'uuid': utils.str_or_none,
@ -92,7 +92,7 @@ class Host(base.SysinvObject):
'console': utils.str_or_none,
'tboot': utils.str_or_none,
'vsc_controllers': utils.str_or_none,
'ttys_dcd': utils.str_or_none,
'ttys_dcd': utils.bool_or_none,
'software_load': utils.str_or_none,
'target_load': utils.str_or_none,
'install_state': utils.str_or_none,

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2016 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -32,14 +32,14 @@ class Memory(base.SysinvObject):
'platform_reserved_mib': utils.int_or_none,
'node_memtotal_mib': utils.int_or_none,
'hugepages_configured': utils.str_or_none,
'hugepages_configured': utils.bool_or_none,
'vswitch_hugepages_size_mib': utils.int_or_none,
'vswitch_hugepages_reqd': utils.int_or_none,
'vswitch_hugepages_nr': utils.int_or_none,
'vswitch_hugepages_avail': utils.int_or_none,
'vm_pending_as_percentage': utils.str_or_none,
'vm_pending_as_percentage': utils.bool_or_none,
'vm_hugepages_nr_2M_pending': utils.int_or_none,
'vm_hugepages_nr_1G_pending': utils.int_or_none,
'vm_hugepages_nr_2M': utils.int_or_none,
@ -51,7 +51,7 @@ class Memory(base.SysinvObject):
'vm_hugepages_nr_4K': utils.int_or_none,
'vm_hugepages_use_1G': utils.str_or_none,
'vm_hugepages_use_1G': utils.bool_or_none,
'vm_hugepages_possible_2M': utils.int_or_none,
'vm_hugepages_possible_1G': utils.int_or_none,
'capabilities': utils.dict_or_none,

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -50,7 +50,7 @@ class Sensor(base.SysinvObject):
't_critical_lower': utils.str_or_none,
't_critical_upper': utils.str_or_none,
'suppress': utils.str_or_none,
'suppress': utils.bool_or_none,
'capabilities': utils.dict_or_none
}

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -50,7 +50,7 @@ class SensorAnalog(base.SysinvObject):
't_critical_lower': utils.str_or_none,
't_critical_upper': utils.str_or_none,
'suppress': utils.str_or_none,
'suppress': utils.bool_or_none,
'capabilities': utils.dict_or_none
}

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -39,7 +39,7 @@ class SensorDiscrete(base.SysinvObject):
'actions_major': utils.str_or_none,
'actions_critical': utils.str_or_none,
'suppress': utils.str_or_none,
'suppress': utils.bool_or_none,
'capabilities': utils.dict_or_none
}

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -50,7 +50,7 @@ class SensorGroup(base.SysinvObject):
't_critical_lower_group': utils.str_or_none,
't_critical_upper_group': utils.str_or_none,
'suppress': utils.str_or_none,
'suppress': utils.bool_or_none,
'capabilities': utils.dict_or_none,
'actions_critical_choices': utils.str_or_none,

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -52,7 +52,7 @@ class SensorGroupAnalog(base.SysinvObject):
't_critical_lower_group': utils.str_or_none,
't_critical_upper_group': utils.str_or_none,
'suppress': utils.str_or_none,
'suppress': utils.bool_or_none,
'capabilities': utils.dict_or_none
}

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2015 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -41,7 +41,7 @@ class SensorGroupDiscrete(base.SysinvObject):
'actions_major_group': utils.str_or_none,
'actions_critical_group': utils.str_or_none,
'suppress': utils.str_or_none,
'suppress': utils.bool_or_none,
'capabilities': utils.dict_or_none
}

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2016 Wind River Systems, Inc.
# Copyright (c) 2013-2022 Wind River Systems, Inc.
#
@ -52,11 +52,11 @@ def datetime_or_str_or_none(val):
def bool_or_none(val):
"""Attempt to parse an boolean value, or None."""
"""Attempt to parse a boolean value, or None."""
if val is None:
return False
elif isinstance(val, six.string_types):
return bool(val.lower() in ['y', 'n', 'yes', 'no', 'true', 'false'])
return bool(val.lower() in ['y', 'yes', 'true'])
else:
return bool(int(val) != 0)

View File

@ -1,4 +1,4 @@
# Copyright (c) 2017-2020 Wind River Systems, Inc.
# Copyright (c) 2017-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -646,7 +646,7 @@ class PlatformPuppet(base.BasePuppet):
total_hugepages_2M = vm_hugepages_nr_2M
total_hugepages_1G = vm_hugepages_nr_1G
if(vm_pending_as_percentage == "True"):
if vm_pending_as_percentage is True:
vm_hugepages_nr_2M = memory.vm_hugepages_nr_2M_pending if \
memory.vm_hugepages_nr_2M_pending is not None else \
memory.vm_hugepages_2M_percentage if memory.vm_hugepages_2M_percentage \
@ -908,7 +908,7 @@ class PlatformPuppet(base.BasePuppet):
def _get_ttys_dcd_config(self, host):
return {
"platform::tty::params::enabled":
str(host.ttys_dcd) in ['True', 'true'],
host.ttys_dcd is True,
"platform::tty::params::active_device":
host.console.split(',')[0]
}

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2017-2019 Wind River Systems, Inc.
# Copyright (c) 2017-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -70,7 +70,7 @@ class sensorgroupTestCase(base.FunctionalTest):
actions_minor_group='action minor',
actions_major_group='action major',
actions_critical_group='action critical',
suppress='False',)
suppress=False,)
# Assert values got set properly in sensorgroup
self.assertEqual(42, # Expected
@ -85,7 +85,7 @@ class sensorgroupTestCase(base.FunctionalTest):
self.assertEqual('action critical', # Expected
self.get_json('/isensorgroups/%s/' %
sensorgroup.json['uuid'])['actions_critical_group']) # Result
self.assertEqual('False', # Expected
self.assertEqual(False, # Expected
self.get_json('/isensorgroups/%s/' %
sensorgroup.json['uuid'])['suppress']) # Result
@ -102,7 +102,7 @@ class sensorgroupTestCase(base.FunctionalTest):
self.assertEqual('action critical', # Expected
self.get_json('/isensors/%s/' %
sensor.json['uuid'])['actions_critical']) # Result
self.assertEqual('False', # Expected
self.assertEqual(False, # Expected
self.get_json('/isensors/%s/' %
sensor.json['uuid'])['suppress']) # Result
@ -160,7 +160,7 @@ class sensorgroupTestCase(base.FunctionalTest):
actions_minor_group='action minor',
actions_major_group='action major',
actions_critical_group='action critical',
suppress='False', )
suppress=False, )
# Assert values got set properly in sensorgroup
self.assertEqual(42, # Expected
@ -175,7 +175,7 @@ class sensorgroupTestCase(base.FunctionalTest):
self.assertEqual('action critical', # Expected
self.get_json('/isensorgroups/%s/' %
sensorgroup.json['uuid'])['actions_critical_group']) # Result
self.assertEqual('False', # Expected
self.assertEqual(False, # Expected
self.get_json('/isensorgroups/%s/' %
sensorgroup.json['uuid'])['suppress']) # Result
@ -193,7 +193,7 @@ class sensorgroupTestCase(base.FunctionalTest):
self.assertEqual('action critical', # Expected
self.get_json('/isensors/%s/' %
sensor[i].json['uuid'])['actions_critical']) # Result
self.assertEqual('False', # Expected
self.assertEqual(False, # Expected
self.get_json('/isensors/%s/' %
sensor[i].json['uuid'])['suppress']) # Result

View File

@ -157,7 +157,7 @@ def get_test_ihost(**kw):
'install_output': kw.get('install_output', 'text'),
'console': kw.get('console', 'ttyS0,115200'),
'tboot': kw.get('tboot', ''),
'ttys_dcd': kw.get('ttys_dcd', None),
'ttys_dcd': kw.get('ttys_dcd', False),
'updated_at': None,
'created_at': None,
'install_state': kw.get('install_state', None),