Adjust IPsec related codes to support upgrade

This commit updates various codes related to the "protecting mgmt
network with IPsec" feature, to support stx 9 to stx 10 upgrade. With
this changeset, the IPsec feature will not break current upgrade. There
will be follow-up changes to fully support stx 9 to stx 10 upgrade with
the IPsec feature.

Test Plan: (AIO DX system)
PASS: Packages build, image build.
PASS: Without IPsec feature enabled, upgrade from stx 9 to stx 10,
      verify all steps are successful.
PASS: With Ipsec feature enabled, upgrade from stx 9 to stx 10, verify
      all steps are successful.
      (IPsec is not configured and enabled during upgrade)

Story: 2010940
Task: 50095

Change-Id: Id708f540f39ed98a9e05cc12a71a5a4fa3d5bfa5
Signed-off-by: Andy Ning <andy.ning@windriver.com>
This commit is contained in:
Andy Ning 2024-05-14 17:22:13 -04:00
parent 69e075e250
commit 50fbde3211
4 changed files with 104 additions and 12 deletions

View File

@ -0,0 +1,82 @@
#!/usr/bin/python
# Copyright (c) 2024 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# This script is to update the "mgmt_ipsec" flag in capabilities of
# sysinv i_host table to "upgrading". This flag will be checked by
# ipsec-server when it receives IPsec config request from ipsec-client.
# It will refuse the request if this flag is "upgrading", meaning
# during upgrade, IPsec won't be configured/enabled.
import json
import sys
from psycopg2.extras import RealDictCursor
import psycopg2
from controllerconfig.common import log
from sysinv.common import constants
LOG = log.get_logger(__name__)
def main():
action = None
from_release = None
to_release = None # noqa
arg = 1
while arg < len(sys.argv):
if arg == 1:
from_release = sys.argv[arg]
elif arg == 2:
to_release = sys.argv[arg] # noqa
elif arg == 3:
action = sys.argv[arg]
else:
print(f"Invalid option {sys.argv[arg]}.")
return 1
arg += 1
log.configure()
if from_release == "22.12" and action == "migrate":
try:
LOG.info("Update mgmt_ipsec in capabilities of sysinv i_host table,"
f"from the release {from_release} to {to_release} with "
f"action: {action}")
update_mgmt_ipsec(constants.MGMT_IPSEC_UPGRADING)
except Exception as ex:
LOG.exception(ex)
print(ex)
return 1
def update_mgmt_ipsec(value):
"""This function update mgmt_ipsec in in capabilities of sysinv
i_host table to the value.
"""
conn = psycopg2.connect("dbname='sysinv' user='postgres'")
with conn:
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute("select uuid, capabilities from i_host;")
rows = cur.fetchall()
if rows is None:
LOG.exception("Failed to fetch i_host data")
raise
for record in rows:
capabilities = json.loads(record['capabilities'])
capabilities.update({constants.MGMT_IPSEC_FLAG: value})
sqlcom = ("update i_host set "
f"capabilities='{json.dumps(capabilities)}' "
f"where uuid='{record['uuid']}'")
cur.execute(sqlcom)
conn.commit()
if __name__ == "__main__":
sys.exit(main())

View File

@ -1207,7 +1207,7 @@ class HostController(rest.RestController):
# Ensure data has valid value
if data not in [constants.MGMT_IPSEC_ENABLING,
constants.MGMT_IPSEC_ENABLED, constants.MGMT_IPSEC_DISABLED]:
LOG.error(_("Invalid value for mgmt_ipsec: %s" % data))
LOG.error(_("Invalid value for %s: %s" % (constants.MGMT_IPSEC_FLAG, data)))
return False
try:
@ -1217,10 +1217,10 @@ class HostController(rest.RestController):
capabilities = host.get('capabilities')
if (data == constants.MGMT_IPSEC_DISABLED and
capabilities.get('mgmt_ipsec') is not None):
capabilities.pop('mgmt_ipsec')
capabilities.get(constants.MGMT_IPSEC_FLAG) is not None):
capabilities.pop(constants.MGMT_IPSEC_FLAG)
else:
capabilities.update({'mgmt_ipsec': data})
capabilities.update({constants.MGMT_IPSEC_FLAG: data})
pecan.request.dbapi.ihost_update(uuid, {'capabilities': capabilities})
except exception.ServerNotFound:
@ -7020,8 +7020,8 @@ class HostController(rest.RestController):
# Remove IPSec flag to allow a new configuration after reinstall
capabilities = hostupdate.ihost_orig['capabilities']
if capabilities.get('mgmt_ipsec') is not None:
capabilities.pop('mgmt_ipsec')
if capabilities.get(constants.MGMT_IPSEC_FLAG) is not None:
capabilities.pop(constants.MGMT_IPSEC_FLAG)
hostupdate.ihost_val_update({'capabilities': capabilities})
hostupdate.notify_mtce = True

View File

@ -2508,10 +2508,14 @@ RUNTIME_CONFIG_STATE_RETRIED = "retried"
# LUKS vault type
LUKS_VAULT_TYPE_NAME = "luks_encrypted_vault"
# mgmt. network IPsec flag
MGMT_IPSEC_FLAG = 'mgmt_ipsec'
# mgmt. network IPSec state
MGMT_IPSEC_ENABLING = 'enabling'
MGMT_IPSEC_ENABLED = 'enabled'
MGMT_IPSEC_DISABLED = 'disabled'
MGMT_IPSEC_UPGRADING = 'upgrading'
# If True, makes outputs compatible with single stack versions of ansible-playbooks and stx-puppet.
# Shall be removed when the other projects are updated.

View File

@ -299,9 +299,9 @@ class IPsecConnection(object):
self.ots_token.purge()
if (self.op_code == constants.OP_CODE_INITIAL_AUTH and
self.mgmt_ipsec != constants.MGMT_IPSEC_ENABLED and not
self._update_mgmt_ipsec_state(constants.MGMT_IPSEC_DISABLED)):
return False
not self.mgmt_ipsec and
self.mgmt_ipsec != constants.MGMT_IPSEC_ENABLED):
return self._update_mgmt_ipsec_state(constants.MGMT_IPSEC_DISABLED)
return True
@ -340,10 +340,16 @@ class IPsecConnection(object):
LOG.error("TLS secret is unreachable.")
return
data = bytes(secret.data.get(attr, None), "utf-8")
if not data:
data = secret.data.get(attr, None)
if data is None:
if attr == self.ROOT_CA_CRT:
data = secret.data.get(self.CA_CRT, None)
if data is None:
LOG.error("Failed to retrieve %s info." % attr)
return
return data
data = bytes(data, "utf-8")
if attr == self.CA_KEY:
data = base64.b64decode(data)