New system service-parameter sysinv_api_workers
The new system service-parameter will allow a user to specify the number of sysinv api workers for horizontal scaling The maximum value is capped at the number of physical cores. The values - service -> platform - section -> config - name -> sysinv_api_workers - value -> [1 .. n ] - personality -> None - resource -> ::platform::sysinv::params::sysinv_api_workers CGTS-CLIENT - add --format arg to cli - update service-parameter Unit Tests SYSINV REST API - add validation for sysinv_api_workers parameter ( min 1, max core count) SYSINV Conductor - update config to include sysinv_api_workers in puppet config hierdata Test plan: PASS - Unit testing PASS - AIO-SX: verify default sysinv_api_workers_value verify system service-parameter-add verify system service-parameter-modify verify system service-parameter-delete PASS - AIO-DX: verify default sysinv_api_workers_value verify system service-parameter-add verify system service-parameter-modify verify system service-parameter-delete PASS - AIO-SX system controller: verify default sysinv_api_workers value PASS - AIO-SX/DX: verify max sysinv_api_workers <= physical cores compare to system host-cpu-list <controller> ---------------- Example error: ---------------- Parameter 'sysinv_api_workers' must be between 1 and 6. Story: 2011106 Task: 50065 Change-Id: I7fa0407a747def9bf66060a1b6622029a00ba5a8 Signed-off-by: Kyale, Eliud <Eliud.Kyale@windriver.com>
This commit is contained in:
parent
180ac1df30
commit
ed952d898a
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013-2019 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2019,2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -17,7 +17,6 @@ import keystoneauth1
|
||||
from cgtsclient import exc
|
||||
from cgtsclient import shell as cgts_shell
|
||||
from cgtsclient.tests import utils
|
||||
from cgtsclient.v1.ihost import ihost
|
||||
|
||||
FAKE_ENV = {'OS_USERNAME': 'username',
|
||||
'OS_PASSWORD': 'password',
|
||||
@ -62,9 +61,22 @@ class ShellTest(utils.BaseTestCase):
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class ShellBaseTest(ShellTest):
|
||||
|
||||
def test_help_unknown_command(self):
|
||||
self.assertRaises(exc.CommandError, self.shell, 'help foofoo')
|
||||
|
||||
def test_help_on_network_addrpool_subcommand(self):
|
||||
self.shell("help network-addrpool-list")
|
||||
self.shell("help network-addrpool-show")
|
||||
self.shell("help network-addrpool-assign")
|
||||
self.shell("help network-addrpool-remove")
|
||||
|
||||
def test_auth_param(self):
|
||||
self.make_env(exclude='OS_USERNAME')
|
||||
self.test_help()
|
||||
|
||||
def test_debug(self):
|
||||
httplib2.debuglevel = 0
|
||||
self.shell('--debug help')
|
||||
@ -101,28 +113,3 @@ class ShellTest(utils.BaseTestCase):
|
||||
for r in required:
|
||||
self.assertThat(help_text,
|
||||
matchers.MatchesRegex(r, self.re_options))
|
||||
|
||||
def test_auth_param(self):
|
||||
self.make_env(exclude='OS_USERNAME')
|
||||
self.test_help()
|
||||
|
||||
@mock.patch('cgtsclient.v1.ihost.ihostManager.list')
|
||||
def test_host_list(self, mock_list):
|
||||
# This unit test mocks returning a single controller-0 host through host-list
|
||||
fake_controller = {'id': '0',
|
||||
'hostname': 'controller-0',
|
||||
'personality': 'controller',
|
||||
'administrative': 'unlocked',
|
||||
'operational': 'enabled',
|
||||
'availability': 'available'}
|
||||
mock_list.return_value = [ihost(None, fake_controller, True)]
|
||||
self.make_env()
|
||||
host_results = self.shell("host-list")
|
||||
self.assertIn('controller-0', host_results)
|
||||
self.assertNotIn('controller-1', host_results)
|
||||
|
||||
def test_help_on_network_addrpool_subcommand(self):
|
||||
self.shell("help network-addrpool-list")
|
||||
self.shell("help network-addrpool-show")
|
||||
self.shell("help network-addrpool-assign")
|
||||
self.shell("help network-addrpool-remove")
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2019-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2019-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -193,6 +193,21 @@ class HostTest(test_shell.ShellTest):
|
||||
self.assertIn(str(FAKE_KUBE_HOST_UPGRADE_2['status']),
|
||||
results)
|
||||
|
||||
@mock.patch('cgtsclient.v1.ihost.ihostManager.list')
|
||||
def test_host_list(self, mock_list):
|
||||
# This unit test mocks returning a single controller-0 host through host-list
|
||||
fake_controller = {'id': '0',
|
||||
'hostname': 'controller-0',
|
||||
'personality': 'controller',
|
||||
'administrative': 'unlocked',
|
||||
'operational': 'enabled',
|
||||
'availability': 'available'}
|
||||
mock_list.return_value = [ihost(None, fake_controller, True)]
|
||||
self.make_env()
|
||||
host_results = self.shell("host-list")
|
||||
self.assertIn('controller-0', host_results)
|
||||
self.assertNotIn('controller-1', host_results)
|
||||
|
||||
def test_kube_host_upgrade_kubelet(self):
|
||||
self.make_env()
|
||||
self.ihost_manager_list_result = [ihost(None, FAKE_IHOST_2, True)]
|
||||
|
@ -0,0 +1,302 @@
|
||||
#
|
||||
# Copyright (c) 2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import copy
|
||||
import testtools
|
||||
import uuid
|
||||
|
||||
from cgtsclient.tests import utils
|
||||
import cgtsclient.v1.service_parameter
|
||||
|
||||
CREATE_PARAMETER_1 = {
|
||||
'service': 'platform',
|
||||
'section': 'config',
|
||||
'parameters': {
|
||||
'sysinv_api_workers': 10
|
||||
},
|
||||
'personality': None,
|
||||
'resource': None,
|
||||
}
|
||||
|
||||
PARAMETER_1 = {
|
||||
'uuid': str(uuid.uuid4()),
|
||||
'service': 'platform',
|
||||
'section': 'config',
|
||||
'name': 'sysinv_api_workers',
|
||||
'value': 10,
|
||||
'personality': None,
|
||||
'resource': None,
|
||||
}
|
||||
|
||||
CREATE_PARAMETER_2 = {
|
||||
'service': 'docker',
|
||||
'section': 'docker-registry',
|
||||
'parameters': {
|
||||
'url': 'oldregistry:5000/starlingx/docker.io'
|
||||
},
|
||||
'personality': None,
|
||||
'resource': None,
|
||||
}
|
||||
|
||||
PARAMETER_2 = {
|
||||
'uuid': str(uuid.uuid4()),
|
||||
'service': 'docker',
|
||||
'section': 'docker-registry',
|
||||
'name': 'url',
|
||||
'value': 'oldregistry:5000/starlingx/docker.io',
|
||||
'personality': None,
|
||||
'resource': None,
|
||||
}
|
||||
|
||||
UPDATED_PARAMETER_1 = copy.deepcopy(PARAMETER_1)
|
||||
NEW_VALUE_PARAMETER_1 = 15
|
||||
UPDATED_PARAMETER_1['value'] = NEW_VALUE_PARAMETER_1
|
||||
|
||||
UPDATED_PARAMETER_2 = copy.deepcopy(PARAMETER_2)
|
||||
NEW_VALUE_PARAMETER_2 = 'newregistry:5000/starlingx/docker.io'
|
||||
UPDATED_PARAMETER_2['value'] = NEW_VALUE_PARAMETER_2
|
||||
|
||||
PARAMETERS = {
|
||||
"parameters": [PARAMETER_1, PARAMETER_2]
|
||||
}
|
||||
|
||||
fixtures_default = {
|
||||
'/v1/service_parameter':
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
PARAMETERS,
|
||||
),
|
||||
'POST': (
|
||||
{},
|
||||
PARAMETER_1,
|
||||
),
|
||||
},
|
||||
'/v1/service_parameter/%s' % PARAMETER_1['uuid']:
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
PARAMETER_1,
|
||||
),
|
||||
'DELETE': (
|
||||
{},
|
||||
None,
|
||||
),
|
||||
'PATCH': (
|
||||
{},
|
||||
UPDATED_PARAMETER_1,
|
||||
),
|
||||
},
|
||||
'/v1/service_parameter/%s' % PARAMETER_2['uuid']:
|
||||
{
|
||||
'GET': (
|
||||
{},
|
||||
PARAMETER_2,
|
||||
),
|
||||
'DELETE': (
|
||||
{},
|
||||
None,
|
||||
),
|
||||
'PATCH': (
|
||||
{},
|
||||
UPDATED_PARAMETER_2,
|
||||
),
|
||||
},
|
||||
'/v1/service_parameter/apply':
|
||||
{
|
||||
'POST': (
|
||||
{},
|
||||
None,
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class ServiceParameterManagerTest(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ServiceParameterManagerTest, self).setUp()
|
||||
self.api = utils.FakeAPI(fixtures_default)
|
||||
self.mgr = \
|
||||
cgtsclient.v1.service_parameter.ServiceParameterManager(self.api)
|
||||
|
||||
def test_service_parameter_list(self):
|
||||
parameters = self.mgr.list()
|
||||
expect = [
|
||||
# (method , url , headers , body )
|
||||
('GET', '/v1/service_parameter', {}, None)
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertEqual(len(parameters), 2)
|
||||
|
||||
def test_service_parameter_get(self):
|
||||
parameter_1 = self.mgr.get(PARAMETER_1['uuid'])
|
||||
expect = [
|
||||
('GET',
|
||||
'/v1/service_parameter/%s' % PARAMETER_1['uuid'],
|
||||
{},
|
||||
None),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(
|
||||
isinstance(parameter_1,
|
||||
cgtsclient.v1.service_parameter.ServiceParameter))
|
||||
|
||||
self.assertEqual(parameter_1.uuid, PARAMETER_1['uuid'])
|
||||
self.assertEqual(parameter_1.service, PARAMETER_1['service'])
|
||||
self.assertEqual(parameter_1.section, PARAMETER_1['section'])
|
||||
self.assertEqual(parameter_1.name, PARAMETER_1['name'])
|
||||
self.assertEqual(parameter_1.value, PARAMETER_1['value'])
|
||||
|
||||
parameter_2 = self.mgr.get(UPDATED_PARAMETER_2['uuid'])
|
||||
expect = [
|
||||
('GET',
|
||||
'/v1/service_parameter/%s' % PARAMETER_1['uuid'],
|
||||
{},
|
||||
None),
|
||||
('GET',
|
||||
'/v1/service_parameter/%s' % PARAMETER_2['uuid'],
|
||||
{},
|
||||
None)
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(
|
||||
isinstance(parameter_2,
|
||||
cgtsclient.v1.service_parameter.ServiceParameter))
|
||||
|
||||
self.assertEqual(parameter_2.uuid, PARAMETER_2['uuid'])
|
||||
self.assertEqual(parameter_2.service, PARAMETER_2['service'])
|
||||
self.assertEqual(parameter_2.section, PARAMETER_2['section'])
|
||||
self.assertEqual(parameter_2.name, PARAMETER_2['name'])
|
||||
self.assertEqual(parameter_2.value, PARAMETER_2['value'])
|
||||
|
||||
def test_service_parameter_create(self):
|
||||
parameter_1 = self.mgr.create(
|
||||
PARAMETER_1['service'],
|
||||
PARAMETER_1['section'],
|
||||
PARAMETER_1['personality'],
|
||||
PARAMETER_1['resource'],
|
||||
{
|
||||
PARAMETER_1['name']: PARAMETER_1['value'],
|
||||
}
|
||||
)
|
||||
|
||||
self.api.fixtures['/v1/service_parameter']['POST'] = (
|
||||
{},
|
||||
PARAMETER_2,
|
||||
)
|
||||
parameter_2 = self.mgr.create(
|
||||
PARAMETER_2['service'],
|
||||
PARAMETER_2['section'],
|
||||
PARAMETER_2['personality'],
|
||||
PARAMETER_2['resource'],
|
||||
{
|
||||
PARAMETER_2['name']: PARAMETER_2['value'],
|
||||
}
|
||||
)
|
||||
|
||||
expect = [
|
||||
('POST',
|
||||
'/v1/service_parameter',
|
||||
{},
|
||||
CREATE_PARAMETER_1),
|
||||
('POST',
|
||||
'/v1/service_parameter',
|
||||
{},
|
||||
CREATE_PARAMETER_2),
|
||||
]
|
||||
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
|
||||
isinstance(
|
||||
parameter_1,
|
||||
cgtsclient.v1.service_parameter.ServiceParameter)
|
||||
isinstance(
|
||||
parameter_2,
|
||||
cgtsclient.v1.service_parameter.ServiceParameter)
|
||||
|
||||
self.assertEqual(parameter_1.uuid, PARAMETER_1['uuid'])
|
||||
self.assertEqual(parameter_1.service, PARAMETER_1['service'])
|
||||
self.assertEqual(parameter_1.section, PARAMETER_1['section'])
|
||||
self.assertEqual(parameter_1.name, PARAMETER_1['name'])
|
||||
self.assertEqual(parameter_1.value, PARAMETER_1['value'])
|
||||
|
||||
self.assertEqual(parameter_2.uuid, PARAMETER_2['uuid'])
|
||||
self.assertEqual(parameter_2.service, PARAMETER_2['service'])
|
||||
self.assertEqual(parameter_2.section, PARAMETER_2['section'])
|
||||
self.assertEqual(parameter_2.name, PARAMETER_2['name'])
|
||||
self.assertEqual(parameter_2.value, PARAMETER_2['value'])
|
||||
|
||||
def test_service_parameter_delete(self):
|
||||
parameter = self.mgr.delete(PARAMETER_1['uuid'])
|
||||
expect = [
|
||||
('DELETE',
|
||||
'/v1/service_parameter/%s' % PARAMETER_1['uuid'],
|
||||
{},
|
||||
None),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(parameter is None)
|
||||
|
||||
def test_service_parameter_apply(self):
|
||||
_, body = self.mgr.apply(
|
||||
PARAMETER_1['service'],
|
||||
PARAMETER_1['section'],
|
||||
)
|
||||
expect = [
|
||||
(
|
||||
'POST',
|
||||
'/v1/service_parameter/apply',
|
||||
{},
|
||||
{
|
||||
"service": PARAMETER_1['service'],
|
||||
"section": PARAMETER_1['section'],
|
||||
}
|
||||
),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(body is None)
|
||||
|
||||
def test_service_parameter_update(self):
|
||||
patch_1 = [
|
||||
{
|
||||
'op': 'replace',
|
||||
'path': '/name',
|
||||
'value': PARAMETER_1['name'],
|
||||
},
|
||||
{
|
||||
'op': 'replace',
|
||||
'path': '/value',
|
||||
'value': PARAMETER_1['value']
|
||||
},
|
||||
]
|
||||
patch_2 = [
|
||||
{
|
||||
'op': 'replace',
|
||||
'path': '/name',
|
||||
'value': PARAMETER_2['name'],
|
||||
},
|
||||
{
|
||||
'op': 'replace',
|
||||
'path': '/value',
|
||||
'value': PARAMETER_2['value']
|
||||
},
|
||||
]
|
||||
parameter_1 = self.mgr.update(PARAMETER_1['uuid'], patch_1)
|
||||
parameter_2 = self.mgr.update(PARAMETER_2['uuid'], patch_2)
|
||||
expect = [
|
||||
('PATCH',
|
||||
'/v1/service_parameter/%s' % PARAMETER_1['uuid'],
|
||||
{},
|
||||
patch_1),
|
||||
('PATCH',
|
||||
'/v1/service_parameter/%s' % PARAMETER_2['uuid'],
|
||||
{},
|
||||
patch_2),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertEqual(parameter_1.value, NEW_VALUE_PARAMETER_1)
|
||||
self.assertEqual(parameter_2.value, NEW_VALUE_PARAMETER_2)
|
@ -0,0 +1,215 @@
|
||||
#
|
||||
# Copyright (c) 2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import mock
|
||||
import uuid
|
||||
import yaml
|
||||
|
||||
from cgtsclient import exc
|
||||
from cgtsclient.tests import test_shell
|
||||
from cgtsclient.v1.service_parameter import ServiceParameter
|
||||
|
||||
from http import HTTPStatus
|
||||
from testtools import ExpectedException
|
||||
|
||||
FAKE_SERVICE_PARAMETER_1 = {
|
||||
'uuid': str(uuid.uuid4()),
|
||||
'service': 'platform',
|
||||
'section': 'config',
|
||||
'name': 'sysinv_api_workers',
|
||||
'value': 10,
|
||||
'personality': None,
|
||||
'resource': None,
|
||||
}
|
||||
|
||||
FAKE_SERVICE_PARAMETER_2 = {
|
||||
'uuid': str(uuid.uuid4()),
|
||||
'service': 'docker',
|
||||
'section': 'docker-registry',
|
||||
'name': 'url',
|
||||
'value': 'myregistry:5000/starlingx/docker.io',
|
||||
'personality': None,
|
||||
'resource': None,
|
||||
}
|
||||
|
||||
|
||||
class MockResponse:
|
||||
|
||||
def __init__(self, status_code, json_data) -> None:
|
||||
self.json_data = json_data
|
||||
self.status_code = status_code
|
||||
|
||||
def json(self):
|
||||
return self.json_data
|
||||
|
||||
|
||||
class ServiceParameterTest(test_shell.ShellTest):
|
||||
|
||||
def setUp(self):
|
||||
super(ServiceParameterTest, self).setUp()
|
||||
self.make_env()
|
||||
|
||||
@mock.patch('cgtsclient.v1.service_parameter.ServiceParameterManager.list')
|
||||
def test_service_parameter_list(self, mock_list):
|
||||
mock_list.return_value = [
|
||||
ServiceParameter(None, FAKE_SERVICE_PARAMETER_1, True),
|
||||
ServiceParameter(None, FAKE_SERVICE_PARAMETER_2, True),
|
||||
]
|
||||
|
||||
results_str = self.shell("service-parameter-list --format yaml")
|
||||
results_list = yaml.safe_load(results_str)
|
||||
|
||||
self.assertTrue(isinstance(results_list, list),
|
||||
"service-parameter-list should return a list")
|
||||
|
||||
expected_list = [FAKE_SERVICE_PARAMETER_2, FAKE_SERVICE_PARAMETER_1]
|
||||
self.assertCountEqual(expected_list, results_list)
|
||||
|
||||
@mock.patch('cgtsclient.v1.service_parameter.ServiceParameterManager.get')
|
||||
def test_service_parameter_show(self, mock_get):
|
||||
mock_get.return_value = ServiceParameter(None,
|
||||
FAKE_SERVICE_PARAMETER_1,
|
||||
True)
|
||||
results = self.shell("service-parameter-show --format yaml "
|
||||
f"{FAKE_SERVICE_PARAMETER_1['uuid']}")
|
||||
service_parameter = yaml.safe_load(results)
|
||||
|
||||
self.assertEqual(service_parameter['service'],
|
||||
FAKE_SERVICE_PARAMETER_1['service'])
|
||||
self.assertEqual(service_parameter['section'],
|
||||
FAKE_SERVICE_PARAMETER_1['section'])
|
||||
self.assertEqual(service_parameter['name'],
|
||||
FAKE_SERVICE_PARAMETER_1['name'])
|
||||
self.assertEqual(service_parameter['value'],
|
||||
FAKE_SERVICE_PARAMETER_1['value'])
|
||||
|
||||
@mock.patch(
|
||||
'cgtsclient.v1.service_parameter.ServiceParameterManager.apply'
|
||||
)
|
||||
def test_service_parameter_apply(self, mock_apply):
|
||||
resp = MockResponse(HTTPStatus.OK, {})
|
||||
mock_apply.return_value = (resp, resp.json())
|
||||
self.shell("service-parameter-apply"
|
||||
f" --section {FAKE_SERVICE_PARAMETER_1['section']}"
|
||||
f" {FAKE_SERVICE_PARAMETER_1['service']}")
|
||||
mock_apply.assert_called_once()
|
||||
|
||||
@mock.patch(
|
||||
'cgtsclient.v1.service_parameter.ServiceParameterManager.apply'
|
||||
)
|
||||
def test_service_parameter_apply_invalid(self, mock_apply):
|
||||
mock_apply.side_effect = exc.HTTPNotFound()
|
||||
exception_str = 'Failed to apply service parameters'
|
||||
with ExpectedException(exc.CommandError, exception_str):
|
||||
self.shell("service-parameter-apply --section invalid_section"
|
||||
" invalid_service")
|
||||
|
||||
@mock.patch(
|
||||
'cgtsclient.v1.service_parameter.ServiceParameterManager.delete'
|
||||
)
|
||||
def test_service_parameter_delete(self, mock_delete):
|
||||
self.shell(f"service-parameter-delete"
|
||||
f" {FAKE_SERVICE_PARAMETER_1['uuid']}")
|
||||
mock_delete.assert_called_once()
|
||||
|
||||
@mock.patch(
|
||||
'cgtsclient.v1.service_parameter.ServiceParameterManager.get'
|
||||
)
|
||||
@mock.patch(
|
||||
'cgtsclient.v1.service_parameter.ServiceParameterManager.create'
|
||||
)
|
||||
def test_service_parameter_add(self, mock_create, mock_get):
|
||||
body = {
|
||||
'parameters': [
|
||||
FAKE_SERVICE_PARAMETER_1
|
||||
]
|
||||
}
|
||||
mock_create.return_value = ServiceParameter(None,
|
||||
body,
|
||||
True)
|
||||
mock_get.return_value = ServiceParameter(None,
|
||||
FAKE_SERVICE_PARAMETER_1,
|
||||
True)
|
||||
self.shell("service-parameter-add"
|
||||
f" {FAKE_SERVICE_PARAMETER_1['service']}"
|
||||
f" {FAKE_SERVICE_PARAMETER_1['section']}"
|
||||
f" {FAKE_SERVICE_PARAMETER_1['name']}="
|
||||
f" {FAKE_SERVICE_PARAMETER_1['value']}")
|
||||
mock_create.assert_called_once()
|
||||
mock_get.assert_called_once()
|
||||
|
||||
def test_service_parameter_add_invalid_parameters(self):
|
||||
custom_resource = "::platform::config::params::custom"
|
||||
keyvaluepairs = "param1=true param2=disabled param3=10"
|
||||
exception_str =\
|
||||
"Cannot specify multiple parameters with custom resource."
|
||||
with ExpectedException(exc.CommandError, exception_str):
|
||||
self.shell("service-parameter-add platform config "
|
||||
f" {keyvaluepairs} "
|
||||
f"--resource {custom_resource}")
|
||||
|
||||
@mock.patch(
|
||||
'cgtsclient.v1.service_parameter.ServiceParameterManager.create'
|
||||
)
|
||||
def test_service_parameter_add_failed(self, mock_create):
|
||||
mock_create.side_effect = exc.HTTPNotFound()
|
||||
attributes =\
|
||||
{
|
||||
FAKE_SERVICE_PARAMETER_1['name']:
|
||||
str(FAKE_SERVICE_PARAMETER_1['value'])
|
||||
}
|
||||
exception_str = \
|
||||
f'Failed to create Service parameters: {attributes} '
|
||||
with ExpectedException(exc.CommandError, exception_str):
|
||||
self.shell("service-parameter-add"
|
||||
f" {FAKE_SERVICE_PARAMETER_1['service']}"
|
||||
f" {FAKE_SERVICE_PARAMETER_1['section']}"
|
||||
f" {FAKE_SERVICE_PARAMETER_1['name']}="
|
||||
f"{FAKE_SERVICE_PARAMETER_1['value']}")
|
||||
|
||||
@mock.patch(
|
||||
'cgtsclient.v1.service_parameter.ServiceParameterManager.list'
|
||||
)
|
||||
@mock.patch(
|
||||
'cgtsclient.v1.service_parameter.ServiceParameterManager.update')
|
||||
def test_service_parameter_modify(self, mock_update, mock_list):
|
||||
FAKE_SERVICE_PARAMETER_1_MODIFIED = FAKE_SERVICE_PARAMETER_1
|
||||
FAKE_SERVICE_PARAMETER_1_MODIFIED['value'] = 15
|
||||
mock_list.return_value = [
|
||||
ServiceParameter(None, FAKE_SERVICE_PARAMETER_1, True),
|
||||
ServiceParameter(None, FAKE_SERVICE_PARAMETER_2, True),
|
||||
]
|
||||
mock_update.return_value = \
|
||||
ServiceParameter(None, FAKE_SERVICE_PARAMETER_1_MODIFIED, True)
|
||||
r = self.shell("service-parameter-modify"
|
||||
f" {FAKE_SERVICE_PARAMETER_1['service']}"
|
||||
f" {FAKE_SERVICE_PARAMETER_1['section']}"
|
||||
f" {FAKE_SERVICE_PARAMETER_1['name']}="
|
||||
f"{FAKE_SERVICE_PARAMETER_1_MODIFIED['value']}"
|
||||
" --format yaml")
|
||||
|
||||
mock_list.assert_called_once()
|
||||
mock_update.assert_called_once()
|
||||
|
||||
service_parameter = yaml.safe_load(r)
|
||||
self.assertEqual(service_parameter['service'],
|
||||
FAKE_SERVICE_PARAMETER_1['service'])
|
||||
self.assertEqual(service_parameter['section'],
|
||||
FAKE_SERVICE_PARAMETER_1['section'])
|
||||
self.assertEqual(service_parameter['name'],
|
||||
FAKE_SERVICE_PARAMETER_1['name'])
|
||||
self.assertEqual(service_parameter['value'],
|
||||
FAKE_SERVICE_PARAMETER_1_MODIFIED['value'])
|
||||
|
||||
def test_service_parameter_modify_invalid_parameters(self):
|
||||
custom_resource = "::platform::config::params::custom"
|
||||
keyvaluepairs = "param1=true param2=disabled param3=10"
|
||||
exception_str = \
|
||||
"Cannot specify multiple parameters with custom resource."
|
||||
with ExpectedException(exc.CommandError, exception_str):
|
||||
self.shell("service-parameter-modify platform config "
|
||||
f" {keyvaluepairs} "
|
||||
f"--resource {custom_resource}")
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013-2019 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2019,2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -13,20 +13,24 @@ from cgtsclient import exc
|
||||
from cgtsclient.v1 import options
|
||||
|
||||
|
||||
def _print_service_parameter_show(obj):
|
||||
def _print_service_parameter_show(service_parameter, output_format=None):
|
||||
fields = ['uuid', 'service', 'section', 'name', 'value',
|
||||
'personality', 'resource']
|
||||
data = [(f, getattr(obj, f, '')) for f in fields]
|
||||
utils.print_tuple_list(data)
|
||||
data_list = [(f, getattr(service_parameter, f, '')) for f in fields]
|
||||
data = dict(data_list)
|
||||
utils.print_dict_with_format(data, wrap=72, output_format=output_format)
|
||||
|
||||
|
||||
@utils.arg('uuid',
|
||||
metavar='<uuid>',
|
||||
help="UUID of service parameter")
|
||||
@utils.arg('--format',
|
||||
choices=['table', 'yaml', 'value'],
|
||||
help="Specify the output format, defaults to table")
|
||||
def do_service_parameter_show(cc, args):
|
||||
"""Show Service parameter."""
|
||||
service_parameter = cc.service_parameter.get(args.uuid)
|
||||
_print_service_parameter_show(service_parameter)
|
||||
_print_service_parameter_show(service_parameter, args.format)
|
||||
|
||||
|
||||
@utils.arg('--service',
|
||||
@ -107,12 +111,14 @@ def _find_service_parameter(cc, service, section, name):
|
||||
metavar='<resource>',
|
||||
default=None,
|
||||
help="Custom resource to be updated")
|
||||
@utils.arg('--format',
|
||||
choices=['table', 'yaml', 'value'],
|
||||
help="specify the output format, defaults to table")
|
||||
def do_service_parameter_modify(cc, args):
|
||||
"""Modify Service Parameter attributes."""
|
||||
|
||||
patch = []
|
||||
attributes = utils.extract_keypairs(args)
|
||||
|
||||
if len(attributes) > 1 \
|
||||
and (args.resource is not None or args.personality is not None):
|
||||
raise exc.CommandError("Cannot specify multiple parameters with custom resource.")
|
||||
@ -129,7 +135,7 @@ def do_service_parameter_modify(cc, args):
|
||||
if args.resource:
|
||||
patch.append({'op': 'replace', 'path': '/resource', 'value': args.resource})
|
||||
parameter = cc.service_parameter.update(service_parameter.uuid, patch)
|
||||
_print_service_parameter_show(parameter)
|
||||
_print_service_parameter_show(parameter, output_format=args.format)
|
||||
|
||||
|
||||
@utils.arg('service',
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2015-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2015-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -658,7 +658,7 @@ class ServiceParameterController(rest.RestController):
|
||||
|
||||
try:
|
||||
# Pass name to update_service_config only in case the parameters are the Intel
|
||||
# NIC driver version and intel_pstate.
|
||||
# NIC driver version, intel_pstate or sysinv_api_workers.
|
||||
new_name = None
|
||||
if section == constants.SERVICE_PARAM_SECTION_PLATFORM_CONFIG and \
|
||||
name == constants.SERVICE_PARAM_NAME_PLAT_CONFIG_INTEL_NIC_DRIVER_VERSION:
|
||||
@ -668,6 +668,10 @@ class ServiceParameterController(rest.RestController):
|
||||
name == constants.SERVICE_PARAM_NAME_PLAT_CONFIG_INTEL_PSTATE:
|
||||
new_name = name
|
||||
|
||||
elif section == constants.SERVICE_PARAM_SECTION_PLATFORM_CONFIG and \
|
||||
name == constants.SERVICE_PARAM_NAME_PLATFORM_SYSINV_API_WORKERS:
|
||||
new_name = name
|
||||
|
||||
pecan.request.rpcapi.update_service_config(
|
||||
pecan.request.context, service, section=section, name=new_name)
|
||||
except rpc_common.RemoteError as e:
|
||||
@ -815,8 +819,8 @@ class ServiceParameterController(rest.RestController):
|
||||
delete_k8s_configmap(parameter.as_dict(), self.kube_operator)
|
||||
|
||||
try:
|
||||
# Pass name to update_service_config only in case the parameter is the Intel
|
||||
# NIC driver version
|
||||
# Pass name to update_service_config only in case the parameter is
|
||||
# the Intel NIC driver version, intel_pstate or sysinv_api_workers
|
||||
name = None
|
||||
if parameter.section == constants.SERVICE_PARAM_SECTION_PLATFORM_CONFIG and \
|
||||
parameter.name == constants.SERVICE_PARAM_NAME_PLAT_CONFIG_INTEL_NIC_DRIVER_VERSION:
|
||||
@ -826,6 +830,10 @@ class ServiceParameterController(rest.RestController):
|
||||
parameter.name == constants.SERVICE_PARAM_NAME_PLAT_CONFIG_INTEL_PSTATE:
|
||||
name = parameter.name
|
||||
|
||||
elif parameter.section == constants.SERVICE_PARAM_SECTION_PLATFORM_CONFIG and \
|
||||
parameter.name == constants.SERVICE_PARAM_NAME_PLATFORM_SYSINV_API_WORKERS:
|
||||
name = parameter.name
|
||||
|
||||
pecan.request.rpcapi.update_service_config(
|
||||
pecan.request.context,
|
||||
parameter.service,
|
||||
|
@ -1383,6 +1383,9 @@ SERVICE_PARAM_NAME_CEPH_MONITOR_AUTH_ID_RECLAIM = 'auth_id_reclaim'
|
||||
SERVICE_PARAM_NAME_PLATFORM_MAX_CPU_PERCENTAGE = 'cpu_max_freq_min_percentage'
|
||||
SERVICE_PARAM_PLATFORM_MAX_CPU_PERCENTAGE_DEFAULT = 80
|
||||
|
||||
# The number of sysinv-api workers
|
||||
SERVICE_PARAM_NAME_PLATFORM_SYSINV_API_WORKERS = 'sysinv_api_workers'
|
||||
|
||||
# DNS host record Service Parameters
|
||||
SERVICE_PARAM_SECTION_DNS_HOST_RECORD = 'host-record'
|
||||
SERVICE_PARAM_NAME_DNS_HOST_RECORD_HOSTS = 'hosts'
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2017-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -608,6 +608,13 @@ def _validate_max_cpu_min_percentage(name, value):
|
||||
return _validate_range(name, value, 60, 100)
|
||||
|
||||
|
||||
def _validate_sysinv_api_workers(name, value):
|
||||
"""Check if sysinv_api_workers value is valid"""
|
||||
MAX_WORKERS = cutils.get_platform_core_count(pecan.request.dbapi)
|
||||
MIN_WORKERS = 1
|
||||
return _validate_range(name, value, MIN_WORKERS, MAX_WORKERS)
|
||||
|
||||
|
||||
def parse_volume_string_to_dict(parameter):
|
||||
"""
|
||||
Parse volume string value from parameter to dictionary.
|
||||
@ -801,6 +808,7 @@ PLATFORM_CONFIG_PARAMETER_OPTIONAL = [
|
||||
constants.SERVICE_PARAM_NAME_PLATFORM_MAX_CPU_PERCENTAGE,
|
||||
constants.SERVICE_PARAM_NAME_PLAT_CONFIG_INTEL_NIC_DRIVER_VERSION,
|
||||
constants.SERVICE_PARAM_NAME_PLAT_CONFIG_INTEL_PSTATE,
|
||||
constants.SERVICE_PARAM_NAME_PLATFORM_SYSINV_API_WORKERS,
|
||||
]
|
||||
|
||||
PLATFORM_CONFIG_PARAMETER_READONLY = [
|
||||
@ -816,14 +824,19 @@ PLATFORM_CONFIG_PARAMETER_VALIDATOR = {
|
||||
_validate_intel_nic_driver_version,
|
||||
constants.SERVICE_PARAM_NAME_PLAT_CONFIG_INTEL_PSTATE:
|
||||
_validate_intel_pstate,
|
||||
constants.SERVICE_PARAM_NAME_PLATFORM_SYSINV_API_WORKERS:
|
||||
_validate_sysinv_api_workers,
|
||||
}
|
||||
|
||||
PLATFORM_CONFIG_PARAMETER_RESOURCE = {
|
||||
constants.SERVICE_PARAM_NAME_PLAT_CONFIG_VIRTUAL: 'platform::params::virtual_system',
|
||||
constants.SERVICE_PARAM_NAME_PLAT_CONFIG_VIRTUAL:
|
||||
'platform::params::virtual_system',
|
||||
constants.SERVICE_PARAM_NAME_PLAT_CONFIG_INTEL_NIC_DRIVER_VERSION:
|
||||
'platform::compute::grub::params::g_intel_nic_driver_version',
|
||||
constants.SERVICE_PARAM_NAME_PLAT_CONFIG_INTEL_PSTATE:
|
||||
'platform::compute::grub::params::g_intel_pstate',
|
||||
constants.SERVICE_PARAM_NAME_PLATFORM_SYSINV_API_WORKERS:
|
||||
'platform::sysinv::params::sysinv_api_workers',
|
||||
}
|
||||
|
||||
IDENTITY_LDAP_PARAMETER_OPTIONAL = [
|
||||
|
@ -1018,6 +1018,30 @@ def is_virtual_worker(ihost):
|
||||
return False
|
||||
|
||||
|
||||
def get_platform_core_count(dbapi):
|
||||
"""
|
||||
Determine the number of platform cores available
|
||||
Returns the minimum of the 2 controllers or 1
|
||||
"""
|
||||
core_list = []
|
||||
controllers = dbapi.ihost_get_by_personality(constants.CONTROLLER)
|
||||
platform_functions = [
|
||||
constants.PLATFORM_FUNCTION,
|
||||
constants.SHARED_FUNCTION
|
||||
]
|
||||
for controller in controllers:
|
||||
number_platform_cores = 0
|
||||
cpu_list = dbapi.icpu_get_by_ihost(controller.uuid)
|
||||
for cpu in cpu_list:
|
||||
if int(cpu['thread']) == 0:
|
||||
if cpu['allocated_function'] in platform_functions:
|
||||
number_platform_cores += 1
|
||||
if number_platform_cores > 0:
|
||||
core_list.append(number_platform_cores)
|
||||
|
||||
return min(core_list, default=1)
|
||||
|
||||
|
||||
def is_low_core_system(ihost, dba):
|
||||
"""
|
||||
Determine if the hosts core count is less than or equal to a xeon-d cpu
|
||||
|
@ -12047,6 +12047,11 @@ class ConductorManager(service.PeriodicService):
|
||||
# _config_update_hosts() above. Node needs a reboot to clear it.
|
||||
config_uuid = self._config_clear_reboot_required(config_uuid)
|
||||
self._config_apply_runtime_manifest(context, config_uuid, config_dict, force=True)
|
||||
elif section == constants.SERVICE_PARAM_SECTION_PLATFORM_CONFIG and \
|
||||
name == constants.SERVICE_PARAM_NAME_PLATFORM_SYSINV_API_WORKERS:
|
||||
reboot = True
|
||||
personalities = [constants.CONTROLLER]
|
||||
config_uuid = self._config_update_hosts(context, personalities, reboot=True)
|
||||
elif section == constants.SERVICE_PARAM_SECTION_PLATFORM_COREDUMP:
|
||||
personalities = [constants.CONTROLLER,
|
||||
constants.WORKER,
|
||||
|
Loading…
Reference in New Issue
Block a user