Persist iSCSI Initiator Name, NVMe hostid and hostnqn [1/2]
This is a part of solution to persist some iSCSI and NVMe parameters across host reinstallations, host upgrades and backup/restore. We will persist this information in the i_host table of the sysinv database in the following columns: - iscsi_initiator_name - nvme_host_id - nvme_host_nqn Test Plan: PASS: After host-unlock, check if the puppet hieradata was updated with the new values. PASS: After manually change three configurations files, restart sysinv-conductor and sysinv-agent and check if changes are reflected in the inventory. PASS: After manually change three configurations files, wait for the sysinv-agent audit to fire and sysinv-agent and check if changes are reflected in the inventory. Story: 2010693 Task: 48967 Change-Id: Iede05815d37d65547fc04de89bc6409853cbf54e Signed-off-by: Hediberto Cavalcante da Silva <hediberto.cavalcantedasilva@windriver.com> Signed-off-by: Gustavo Ornaghi Antunes <gustavo.ornaghiantunes@windriver.com> Signed-off-by: Tiago Leal <Tiago.Leal@windriver.com>
This commit is contained in:
parent
a95d95b770
commit
9ac2181705
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -38,7 +38,8 @@ def _print_ihost_show(ihost, columns=None, output_format=None):
|
||||
'clock_synchronization', 'device_image_update',
|
||||
'reboot_needed', 'max_cpu_mhz_configured',
|
||||
'min_cpu_mhz_allowed', 'max_cpu_mhz_allowed',
|
||||
'cstates_available', 'apparmor']
|
||||
'cstates_available', 'apparmor', 'iscsi_initiator_name',
|
||||
'nvme_host_id', 'nvme_host_nqn']
|
||||
optional_fields = ['vsc_controllers', 'ttys_dcd']
|
||||
if ihost.subfunctions != ihost.personality:
|
||||
fields.append('subfunctions')
|
||||
|
@ -17,7 +17,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Copyright (c) 2013-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2024 Wind River Systems, Inc.
|
||||
#
|
||||
|
||||
|
||||
@ -1089,10 +1089,6 @@ class AgentManager(service.PeriodicService):
|
||||
config_uuid = self.iconfig_read_config_applied()
|
||||
imsg_dict.update({'config_applied': config_uuid})
|
||||
|
||||
iscsi_initiator_name = self.get_host_iscsi_initiator_name()
|
||||
if iscsi_initiator_name is not None:
|
||||
imsg_dict.update({'iscsi_initiator_name': iscsi_initiator_name})
|
||||
|
||||
self.platform_update_by_host(rpcapi,
|
||||
icontext,
|
||||
self._ihost_uuid,
|
||||
@ -1542,6 +1538,7 @@ class AgentManager(service.PeriodicService):
|
||||
|
||||
if self._ihost_uuid and \
|
||||
os.path.isfile(tsc.INITIAL_CONFIG_COMPLETE_FLAG):
|
||||
imsg_dict = {}
|
||||
if not self._report_to_conductor_iplatform_avail_flag and \
|
||||
not self._wait_for_nova_lvg(icontext, rpcapi, self._ihost_uuid, nova_lvgs):
|
||||
imsg_dict = {'availability': constants.AVAILABILITY_AVAILABLE}
|
||||
@ -1549,10 +1546,6 @@ class AgentManager(service.PeriodicService):
|
||||
config_uuid = self.iconfig_read_config_applied()
|
||||
imsg_dict.update({'config_applied': config_uuid})
|
||||
|
||||
iscsi_initiator_name = self.get_host_iscsi_initiator_name()
|
||||
if iscsi_initiator_name is not None:
|
||||
imsg_dict.update({'iscsi_initiator_name': iscsi_initiator_name})
|
||||
|
||||
if self._ihost_personality == constants.CONTROLLER:
|
||||
idisk = self._idisk_operator.idisk_get()
|
||||
try:
|
||||
@ -1565,14 +1558,25 @@ class AgentManager(service.PeriodicService):
|
||||
"conductor.")
|
||||
pass
|
||||
|
||||
self.platform_update_by_host(rpcapi,
|
||||
icontext,
|
||||
self._ihost_uuid,
|
||||
imsg_dict)
|
||||
|
||||
self._report_to_conductor_iplatform_avail()
|
||||
self._iconfig_read_config_reported = config_uuid
|
||||
|
||||
iscsi_initiator_name = self.get_host_iscsi_initiator_name()
|
||||
nvme_host_id = self.get_host_nvme_host_id()
|
||||
nvme_host_nqn = self.get_host_nvme_host_nqn()
|
||||
|
||||
if iscsi_initiator_name is not None:
|
||||
imsg_dict.update({'iscsi_initiator_name': iscsi_initiator_name})
|
||||
if nvme_host_id is not None:
|
||||
imsg_dict.update({'nvme_host_id': nvme_host_id})
|
||||
if nvme_host_nqn is not None:
|
||||
imsg_dict.update({'nvme_host_nqn': nvme_host_nqn})
|
||||
|
||||
self.platform_update_by_host(rpcapi,
|
||||
icontext,
|
||||
self._ihost_uuid,
|
||||
imsg_dict)
|
||||
|
||||
if self._ihost_uuid:
|
||||
LOG.debug("SysInv Agent Inventory Audit running.")
|
||||
|
||||
@ -2199,6 +2203,32 @@ class AgentManager(service.PeriodicService):
|
||||
|
||||
return iscsi_initiator_name
|
||||
|
||||
def get_host_nvme_host_id(self):
|
||||
nvme_host_id = None
|
||||
try:
|
||||
stdout, __ = utils.execute('cat', '/etc/nvme/hostid',
|
||||
run_as_root=True)
|
||||
if stdout:
|
||||
nvme_host_id = stdout.strip()
|
||||
LOG.info("nvme host id = %s" % nvme_host_id)
|
||||
except Exception:
|
||||
LOG.error("Failed retrieving nvme host id")
|
||||
|
||||
return nvme_host_id
|
||||
|
||||
def get_host_nvme_host_nqn(self):
|
||||
nvme_host_nqn = None
|
||||
try:
|
||||
stdout, __ = utils.execute('cat', '/etc/nvme/hostnqn',
|
||||
run_as_root=True)
|
||||
if stdout:
|
||||
nvme_host_nqn = stdout.strip()
|
||||
LOG.info("nvme host nqn = %s" % nvme_host_nqn)
|
||||
except Exception:
|
||||
LOG.error("Failed retrieving nvme host nqn")
|
||||
|
||||
return nvme_host_nqn
|
||||
|
||||
def disk_prepare(self, context, host_uuid, idisk_dict,
|
||||
skip_format, is_cinder_device):
|
||||
"""prepare disk for system use.
|
||||
|
@ -572,6 +572,12 @@ class Host(base.APIBase):
|
||||
iscsi_initiator_name = wtypes.text
|
||||
"The iscsi initiator name (only used for worker hosts)"
|
||||
|
||||
nvme_host_id = wtypes.text
|
||||
"The NVMe Host ID"
|
||||
|
||||
nvme_host_nqn = wtypes.text
|
||||
"The NVMe Host NQN"
|
||||
|
||||
device_image_update = wtypes.text
|
||||
"Represent the status of device image update of this ihost."
|
||||
|
||||
@ -606,7 +612,7 @@ class Host(base.APIBase):
|
||||
'reboot_needed', 'inv_state', 'clock_synchronization',
|
||||
'max_cpu_mhz_configured', 'min_cpu_mhz_allowed',
|
||||
'max_cpu_mhz_allowed', 'cstates_available',
|
||||
'apparmor']
|
||||
'apparmor', 'nvme_host_id', 'nvme_host_nqn']
|
||||
|
||||
fields = minimum_fields if not expand else None
|
||||
uhost = Host.from_rpc_object(rpc_ihost, fields)
|
||||
|
@ -16,7 +16,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Copyright (c) 2013-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2024 Wind River Systems, Inc.
|
||||
#
|
||||
|
||||
"""Conduct all activity related system inventory.
|
||||
@ -6275,12 +6275,27 @@ class ConductorManager(service.PeriodicService):
|
||||
val[constants.HOST_ACTION_STATE] = action_state
|
||||
|
||||
iscsi_initiator_name = imsg_dict.get('iscsi_initiator_name')
|
||||
nvme_host_id = imsg_dict.get('nvme_host_id')
|
||||
nvme_host_nqn = imsg_dict.get('nvme_host_nqn')
|
||||
|
||||
if (iscsi_initiator_name and
|
||||
ihost.iscsi_initiator_name is None):
|
||||
iscsi_initiator_name != ihost.iscsi_initiator_name):
|
||||
LOG.info("%s updating iscsi initiator=%s" %
|
||||
(ihost.hostname, iscsi_initiator_name))
|
||||
val['iscsi_initiator_name'] = iscsi_initiator_name
|
||||
|
||||
if (nvme_host_id and
|
||||
nvme_host_id != ihost.nvme_host_id):
|
||||
LOG.info("%s updating NVMe host_id=%s" %
|
||||
(ihost.hostname, nvme_host_id))
|
||||
val['nvme_host_id'] = nvme_host_id
|
||||
|
||||
if (nvme_host_nqn and
|
||||
nvme_host_nqn != ihost.nvme_host_nqn):
|
||||
LOG.info("%s updating NVMe host_nqn=%s" %
|
||||
(ihost.hostname, nvme_host_nqn))
|
||||
val['nvme_host_nqn'] = nvme_host_nqn
|
||||
|
||||
if max_cpu_dict:
|
||||
ihost.capabilities.update({
|
||||
constants.IHOST_IS_MAX_CPU_MHZ_CONFIGURABLE:
|
||||
|
@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (c) 2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from sqlalchemy import Column, MetaData, Table
|
||||
from sqlalchemy import String
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
host_table = Table('i_host', meta, autoload=True)
|
||||
host_table.create_column(Column('nvme_host_id', String(36)))
|
||||
host_table.create_column(Column('nvme_host_nqn', String(224)))
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
raise NotImplementedError('SysInv database downgrade is unsupported.')
|
@ -15,7 +15,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Copyright (c) 2013-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -242,6 +242,8 @@ class ihost(Base):
|
||||
vsc_controllers = Column(String(255))
|
||||
ttys_dcd = Column(Boolean)
|
||||
iscsi_initiator_name = Column(String(64))
|
||||
nvme_host_id = Column(String(36))
|
||||
nvme_host_nqn = Column(String(224))
|
||||
|
||||
device_image_update = Column(String(64))
|
||||
reboot_needed = Column(Boolean, nullable=False, default=False)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -110,7 +110,9 @@ class Host(base.SysinvObject):
|
||||
'max_cpu_mhz_configured': utils.str_or_none,
|
||||
'min_cpu_mhz_allowed': utils.str_or_none,
|
||||
'max_cpu_mhz_allowed': utils.str_or_none,
|
||||
'cstates_available': utils.str_or_none
|
||||
'cstates_available': utils.str_or_none,
|
||||
'nvme_host_id': utils.str_or_none,
|
||||
'nvme_host_nqn': utils.str_or_none
|
||||
}
|
||||
|
||||
_foreign_fields = {
|
||||
|
@ -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
|
||||
#
|
||||
@ -180,9 +180,64 @@ class PlatformPuppet(base.BasePuppet):
|
||||
except exception.AddressNotFoundByName:
|
||||
pass
|
||||
return {
|
||||
'platform::config::params::hosts': hosts
|
||||
'platform::config::params::hosts': hosts,
|
||||
'platform::config::iscsi::params::initiator_name': self._get_iscsi_initiator_name(host),
|
||||
'platform::config::nvme::params::host_id': self._get_nvme_host_id(host),
|
||||
'platform::config::nvme::params::host_nqn': self._get_nvme_host_nqn(host.hostname)
|
||||
}
|
||||
|
||||
def _get_iscsi_initiator_name(self, host):
|
||||
iscsi_initiator_name = None
|
||||
if not host.iscsi_initiator_name:
|
||||
try:
|
||||
stdout, __ = utils.execute('/usr/sbin/iscsi-iname', '-p', 'iqn.2018-05.io.starlingx',
|
||||
run_as_root=True)
|
||||
if stdout:
|
||||
iscsi_initiator_name = stdout.strip()
|
||||
LOG.info("iscsi initiator name = %s" % iscsi_initiator_name)
|
||||
except Exception:
|
||||
LOG.error("Failed generate a new iscsi initiator name")
|
||||
else:
|
||||
iscsi_initiator_name = host.iscsi_initiator_name
|
||||
LOG.info("Getting iscsi initiator name from database")
|
||||
|
||||
return iscsi_initiator_name
|
||||
|
||||
def _get_nvme_host_id(self, host):
|
||||
nvme_host_id = None
|
||||
if not host.nvme_host_id:
|
||||
try:
|
||||
stdout, __ = utils.execute('/usr/bin/uuidgen',
|
||||
run_as_root=True)
|
||||
if stdout:
|
||||
nvme_host_id = stdout.strip()
|
||||
LOG.info("nvme host id = %s" % nvme_host_id)
|
||||
except Exception:
|
||||
LOG.error("Failed generate a new nvme host id")
|
||||
else:
|
||||
nvme_host_id = host.nvme_host_id
|
||||
LOG.info("Getting nvme host id from database")
|
||||
|
||||
return nvme_host_id
|
||||
|
||||
def _get_nvme_host_nqn(self, hostname):
|
||||
host = self.dbapi.ihost_get_by_hostname(hostname)
|
||||
nvme_host_nqn = None
|
||||
if not host.nvme_host_nqn:
|
||||
try:
|
||||
stdout, __ = utils.execute('/usr/sbin/nvme', 'gen-hostnqn',
|
||||
run_as_root=True)
|
||||
if stdout:
|
||||
nvme_host_nqn = stdout.strip()
|
||||
LOG.info("nvme host nqn = %s" % nvme_host_nqn)
|
||||
except Exception:
|
||||
LOG.error("Failed generate a new nvme host nqn")
|
||||
else:
|
||||
nvme_host_nqn = host.nvme_host_nqn
|
||||
LOG.info("Getting nvme host nqn from database")
|
||||
|
||||
return nvme_host_nqn
|
||||
|
||||
def _get_amqp_config(self):
|
||||
if utils.is_fqdn_ready_to_use():
|
||||
amqp_config_dict = {
|
||||
|
@ -15,7 +15,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Copyright (c) 2013-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2013-2024 Wind River Systems, Inc.
|
||||
#
|
||||
|
||||
"""Sysinv test utilities."""
|
||||
@ -174,7 +174,9 @@ def get_test_ihost(**kw):
|
||||
'max_cpu_mhz_configured': kw.get('max_cpu_mhz_configured', ''),
|
||||
'min_cpu_mhz_allowed': kw.get('min_cpu_mhz_allowed', ''),
|
||||
'max_cpu_mhz_allowed': kw.get('max_cpu_mhz_allowed', ''),
|
||||
'cstates_available': kw.get('cstates_available', '')
|
||||
'cstates_available': kw.get('cstates_available', ''),
|
||||
'nvme_host_id': kw.get('nvme_host_id', None),
|
||||
'nvme_host_nqn': kw.get('nvme_host_nqn', None)
|
||||
}
|
||||
return inv
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user