Provide API to enable/disable NTP service in SysInv

NTP API is modified to prevent both PTP and NTP from running at the same time.
Additional parameter "--enabled=<true/false>" is intoduced for the "ntp-modify".
User is able to disable NTP service before turning PTP service on.

Depends-On: I0831487fb14de80edec0ee8df5cc6f23dfb6bae8
Change-Id: Icdf6b0a4bf5f5ffee6742a6cba03ed22c7d6d038
Story: 2002935
Task: 24646
Signed-off-by: Alex Kozyrev <alex.kozyrev@windriver.com>
This commit is contained in:
Alex Kozyrev 2018-08-16 09:29:15 -04:00
parent a8f68a41b1
commit 5b0695fd9d
18 changed files with 94 additions and 30 deletions

View File

@ -1,2 +1,2 @@
SRC_DIR="cgts-client"
TIS_PATCH_VER=58
TIS_PATCH_VER=59

View File

@ -60,7 +60,7 @@ def donot_dns_add(cc, args):
suuid = getattr(idns, 'uuid', '')
except exc.HTTPNotFound:
raise exc.CommandError('DNS create failed: %s ' %
raise exc.CommandError('DNS create failed: name %s, fields %s ' %
(args.cname, fields))
try:

View File

@ -14,8 +14,8 @@ from cgtsclient import exc
def _print_intp_show(intp):
fields = ['uuid', 'ntpservers', 'isystem_uuid',
'created_at', 'updated_at']
fields = ['uuid', 'enabled', 'ntpservers',
'isystem_uuid', 'created_at', 'updated_at']
data = [(f, getattr(intp, f, '')) for f in fields]
utils.print_tuple_list(data)
@ -34,8 +34,8 @@ def donot_config_ntp_list(cc, args):
intps = cc.intp.list()
field_labels = ['uuid', 'ntpservers']
fields = ['uuid', 'ntpservers']
field_labels = ['uuid', 'enabled', 'ntpservers']
fields = ['uuid', 'enabled', 'ntpservers']
utils.print_list(intps, fields, field_labels, sortby=1)
@ -59,7 +59,7 @@ def donot_ntp_add(cc, args):
suuid = getattr(intp, 'uuid', '')
except exc.HTTPNotFound:
raise exc.CommandError('NTP create failed: %s ' %
raise exc.CommandError('NTP create failed: name: %s, fields %s ' %
(args.cname, fields))
try:
@ -69,10 +69,12 @@ def donot_ntp_add(cc, args):
_print_intp_show(intp)
@utils.arg('--enabled',
metavar='<true/false>',
help="NTP service enabled.")
@utils.arg('attributes',
metavar='<path=value>',
nargs='+',
nargs='*',
action='append',
default=[],
help="NTP attributes to modify ")
@ -83,6 +85,9 @@ def do_ntp_modify(cc, args):
intp = intps[0]
op = "replace"
if args.enabled is not None:
args.attributes[0].append('enabled=%s' % args.enabled)
for attribute in args.attributes:
if 'ntpservers=' in attribute:
ntpservers = attribute[0].split('=')[1]

View File

@ -30,8 +30,8 @@ def do_sdn_controller_show(cc, args):
try:
controller = cc.sdn_controller.get(args.uuid)
except exc.HTTPNotFound:
raise exc.CommandError('Create SDN Controller UUID not found: %s',
args.uuid)
raise exc.CommandError('Create SDN Controller UUID not found: %s'
% args.uuid)
_print_sdn_controller_show(controller)

View File

@ -1,2 +1,2 @@
SRC_DIR="sysinv"
TIS_PATCH_VER=277
TIS_PATCH_VER=278

View File

@ -154,9 +154,9 @@ def _check_dns_data(dns):
MAX_S = 3
if 'forisystemid' in dns.keys():
ntp_list = pecan.request.dbapi.intp_get_list(dns['forisystemid'])
ntp_list = pecan.request.dbapi.intp_get_by_isystem(dns['forisystemid'])
else:
ntp_list = []
ntp_list = pecan.request.dbapi.intp_get_by_isystem(dns['isystem_uuid'])
if nameservers:
for nameservers in [n.strip() for n in nameservers.split(',')]:

View File

@ -1744,7 +1744,7 @@ class HostController(rest.RestController):
delta_handle = list(delta)
uptime_update = False
if 'uptime' in delta:
if 'uptime' in delta_handle:
# There is a log of uptime updates, so just do a debug log
uptime_update = True
LOG.debug("%s %s patch" % (ihost_obj.hostname,

View File

@ -65,6 +65,9 @@ class NTP(base.APIBase):
uuid = types.uuid
"Unique UUID for this ntp"
enabled = types.boolean
"Represent the status of the intp."
ntpservers = wtypes.text
"Represent the ntpservers of the intp. csv list."
@ -101,6 +104,7 @@ class NTP(base.APIBase):
ntp = NTP(**rpc_ntp.as_dict())
if not expand:
ntp.unset_fields_except(['uuid',
'enabled',
'ntpservers',
'isystem_uuid',
'created_at',
@ -147,6 +151,7 @@ class intpCollection(collection.Collection):
##############
def _check_ntp_data(op, ntp):
# Get data
enabled = ntp['enabled']
ntpservers = ntp['ntpservers']
intp_ntpservers_list = []
ntp_ntpservers = ""
@ -154,7 +159,7 @@ def _check_ntp_data(op, ntp):
MAX_S = 3
dns_list = pecan.request.dbapi.idns_get_list(ntp['forisystemid'])
dns_list = pecan.request.dbapi.idns_get_by_isystem(ntp['forisystemid'])
if dns_list:
if hasattr(dns_list[0], 'nameservers'):
@ -187,8 +192,8 @@ def _check_ntp_data(op, ntp):
"Please configure a valid NTP "
"IP address or hostname.") % (ntpserver))
if len(intp_ntpservers_list) == 0:
raise wsme.exc.ClientSideError(_("No NTP servers provided."))
if len(intp_ntpservers_list) == 0 and enabled is None:
raise wsme.exc.ClientSideError(_("No NTP parameters provided."))
if len(intp_ntpservers_list) > MAX_S:
raise wsme.exc.ClientSideError(_(
@ -344,12 +349,18 @@ class NTPController(rest.RestController):
rpc_ntp[field] = ntp[field]
delta = rpc_ntp.obj_what_changed()
delta_handle = list(delta)
if delta:
rpc_ntp.save()
if 'enabled' in delta_handle:
service_change = True
else:
service_change = False
if action == constants.APPLY_ACTION:
# perform rpc to conductor to perform config apply
pecan.request.rpcapi.update_ntp_config(pecan.request.context)
pecan.request.rpcapi.update_ntp_config(pecan.request.context,
service_change)
else:
LOG.info("No NTP config changes")

View File

@ -610,6 +610,10 @@ class MultipleResults(SysinvException):
message = _("More than one result found.")
class NTPNotFound(NotFound):
message = _("No NTP with id %(uuid)s found.")
class DiskNotFound(NotFound):
message = _("No disk with id %(disk_id)s")

View File

@ -5146,9 +5146,14 @@ class ConductorManager(service.PeriodicService):
config_uuid = self._config_update_hosts(context, personalities)
self._update_resolv_file(context, config_uuid, personalities)
def update_ntp_config(self, context):
def update_ntp_config(self, context, service_change=False):
"""Update the NTP configuration"""
personalities = [constants.CONTROLLER]
if service_change:
personalities = [constants.CONTROLLER,
constants.COMPUTE,
constants.STORAGE]
else:
personalities = [constants.CONTROLLER]
self._config_update_hosts(context, personalities, reboot=True)
def update_system_mode_config(self, context):

View File

@ -694,12 +694,13 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
"""
return self.call(context, self.make_msg('update_dns_config'))
def update_ntp_config(self, context):
def update_ntp_config(self, context, service_change=False):
"""Synchronously, have the conductor update the NTP configuration.
:param context: request context.
"""
return self.call(context, self.make_msg('update_ntp_config'))
return self.call(context, self.make_msg('update_ntp_config',
service_change=service_change))
def update_system_mode_config(self, context):
"""Synchronously, have the conductor update the system mode

View File

@ -1945,14 +1945,15 @@ class Connection(object):
:param forisystemid: intp belongs to this isystem
:param values: A dict containing several items used to identify
and track the cpu.
and track the ntp settings.
{
'enabled': 'True'
'ntpservers': '0.pool.ntp.org,
1.pool.ntp.org,
2.pool.ntp.org',
'forisystemid': '1'
}
:returns: An ntp.
:returns: An intp.
"""
@abc.abstractmethod

View File

@ -3577,7 +3577,7 @@ class Connection(api.Connection):
try:
return query.one()
except NoResultFound:
raise exception.ServerNotFound(server=server)
raise exception.NTPNotFound(server=server)
@objects.objectify(objects.ntp)
def intp_create(self, values):
@ -3633,7 +3633,7 @@ class Connection(api.Connection):
count = query.update(values, synchronize_session='fetch')
if count != 1:
raise exception.ServerNotFound(server=server)
raise exception.NTPNotFound(server=server)
return query.one()
def intp_destroy(self, server):
@ -3644,7 +3644,7 @@ class Connection(api.Connection):
try:
query.one()
except NoResultFound:
raise exception.ServerNotFound(server=server)
raise exception.NTPNotFound(server=server)
# if node_ref['reservation'] is not None:
# raise exception.NodeLocked(node=node)
@ -4418,7 +4418,7 @@ class Connection(api.Connection):
# isystem_get() to raise an exception if the isystem is not found
isystem_obj = self.isystem_get(isystem_id)
query = model_query(models.remotelogging)
query = query.filter_by(forisystemid=isystem_obj.id)
query = query.filter_by(system_id=isystem_obj.id)
return _paginate_query(models.remotelogging, limit, marker,
sort_key, sort_dir, query)

View File

@ -0,0 +1,25 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
from sqlalchemy import Column, MetaData, Table, Boolean
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
intp_table = Table('i_ntp', meta, autoload=True)
intp_table.create_column(Column('enabled', Boolean, default=True))
def downgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
intp_table = Table('i_ntp', meta, autoload=True)
intp_table.drop_column('enabled')

View File

@ -823,6 +823,7 @@ class intp(Base):
id = Column(Integer, primary_key=True)
uuid = Column(String(36))
enabled = Column(Boolean, default=True)
ntpservers = Column(String(255)) # csv list of ntp servers
forisystemid = Column(Integer,

View File

@ -21,6 +21,7 @@ class NTP(base.SysinvObject):
'id': int,
'uuid': utils.str_or_none,
'enabled': utils.bool_or_none,
'ntpservers': utils.str_or_none,
'forisystemid': utils.int_or_none,

View File

@ -378,8 +378,8 @@ class PlatformPuppet(base.BasePuppet):
return config
def _get_host_ntp_config(self, host):
ntp = self.dbapi.intp_get_one()
if host.personality == constants.CONTROLLER:
ntp = self.dbapi.intp_get_one()
servers = ntp.ntpservers.split(',') if ntp.ntpservers else []
else:
controller0_address = self._get_address_by_name(
@ -425,6 +425,7 @@ class PlatformPuppet(base.BasePuppet):
ntpdate_timeout = "30"
return {
'platform::ntp::enabled': ntp.enabled,
'platform::ntp::servers': servers,
'platform::ntp::ntpdate_timeout': ntpdate_timeout,
}

View File

@ -1886,3 +1886,12 @@ class TestMigrations(BaseMigrationTestCase, WalkVersionsMixin):
getattr(sqlalchemy.types, coltype)))
# Assert deletion of the i_storconfig table
self.assertTableNotExists(engine, 'storage_file')
def _check_074(self, engine, data):
ntps = db_utils.get_table(engine, 'i_ntp')
ntps_col = {
'enabled': 'Boolean',
}
for col, coltype in ntps_col.items():
self.assertTrue(isinstance(ntps.c[col].type,
getattr(sqlalchemy.types, coltype)))