Validate commit_id sent by controller on deploy host
This commit adds a validation on software agent, to check if the commit_id sent by software controller on deploy host matches with the remote commit_id. Test Plan: PASS: run "deploy host" successfully PASS: simulate commit_id divergence, observe deploy host is blocked, remote is removed and error message is logged Story: 2010676 Task: 49904 Signed-off-by: Heitor Matsui <heitorvieira.matsui@windriver.com> Change-Id: I75176ada3a9534ac2812ecdff366d925e438a836
This commit is contained in:
parent
5585c1fc3b
commit
ee78efb5f7
|
@ -549,3 +549,37 @@ def add_ostree_remote(major_release, nodetype):
|
|||
LOG.exception("Error adding %s ostree remote: %s" % (major_release, str(e)))
|
||||
raise
|
||||
return rel_name
|
||||
|
||||
|
||||
def delete_ostree_remote(remote):
|
||||
"""
|
||||
Delete an ostree remote
|
||||
:param remote: remote name to be deleted
|
||||
"""
|
||||
cmd = ["ostree", "remote", "delete", "--if-exists", remote]
|
||||
try:
|
||||
subprocess.check_call(cmd)
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.exception("Error deleting %s ostree remote: %s" % (remote, str(e)))
|
||||
|
||||
|
||||
def check_commit_id(remote, commit_id):
|
||||
"""
|
||||
Check if commit_id matches with the commit_id from the remote ostree_repo
|
||||
:param remote: ostree remote name to be checked against
|
||||
:param commit_id: commit_id sent by the controller to the agent
|
||||
:return: boolean indicating if commit_id matches with remote commit_id
|
||||
"""
|
||||
commit_id_match = False
|
||||
cmd = "ostree remote summary %s | grep 'Latest Commit' -A1" % remote
|
||||
try:
|
||||
# output should be similar to:
|
||||
# Latest Commit (<n> bytes):
|
||||
# <ostree_commit_id>
|
||||
output = subprocess.check_output(cmd, shell=True, text=True,
|
||||
stderr=subprocess.STDOUT).strip()
|
||||
remote_commit_id = output.split("\n")[1].strip()
|
||||
commit_id_match = commit_id == remote_commit_id
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.exception("Error getting remote commit_id: %s: %s" % (str(e), e.stdout))
|
||||
return commit_id_match
|
||||
|
|
|
@ -340,6 +340,7 @@ class PatchMessageAgentInstallReq(messages.PatchMessage):
|
|||
messages.PatchMessage.__init__(self, messages.PATCHMSG_AGENT_INSTALL_REQ)
|
||||
self.force = False
|
||||
self.major_release = None
|
||||
self.commit_id = None
|
||||
|
||||
def decode(self, data):
|
||||
messages.PatchMessage.decode(self, data)
|
||||
|
@ -347,13 +348,16 @@ class PatchMessageAgentInstallReq(messages.PatchMessage):
|
|||
self.force = data['force']
|
||||
if 'major_release' in data:
|
||||
self.major_release = data['major_release']
|
||||
if 'commit_id' in data:
|
||||
self.commit_id = data['commit_id']
|
||||
|
||||
def encode(self):
|
||||
# Nothing to add to the HELLO_AGENT, so just call the super class
|
||||
messages.PatchMessage.encode(self)
|
||||
|
||||
def handle(self, sock, addr):
|
||||
LOG.info("Handling host install request, force=%s, major_release=%s", self.force, self.major_release)
|
||||
LOG.info("Handling host install request, force=%s, major_release=%s, commit_id=%s",
|
||||
self.force, self.major_release, self.commit_id)
|
||||
global pa
|
||||
resp = PatchMessageAgentInstallResp()
|
||||
|
||||
|
@ -372,7 +376,7 @@ class PatchMessageAgentInstallReq(messages.PatchMessage):
|
|||
resp.reject_reason = 'Node must be locked.'
|
||||
resp.send(sock, addr)
|
||||
return
|
||||
resp.status = pa.handle_install(major_release=self.major_release)
|
||||
resp.status = pa.handle_install(major_release=self.major_release, commit_id=self.commit_id)
|
||||
resp.send(sock, addr)
|
||||
|
||||
def send(self, sock): # pylint: disable=unused-argument
|
||||
|
@ -477,10 +481,8 @@ class PatchAgent(PatchService):
|
|||
self.latest_sysroot_commit = active_sysroot_commit
|
||||
self.last_repo_revision = active_sysroot_commit
|
||||
|
||||
# checks if this is a major release deployment operation
|
||||
if major_release:
|
||||
upgrade_feed_commit = ostree_utils.get_feed_latest_commit(major_release)
|
||||
LOG.info("Major release deployment for %s with commit %s" % (major_release,
|
||||
upgrade_feed_commit))
|
||||
self.changes = True
|
||||
return True
|
||||
|
||||
|
@ -507,7 +509,8 @@ class PatchAgent(PatchService):
|
|||
verbose_to_stdout=False,
|
||||
disallow_insvc_patch=False,
|
||||
delete_older_deployments=False,
|
||||
major_release=None):
|
||||
major_release=None,
|
||||
commit_id=None):
|
||||
#
|
||||
# The disallow_insvc_patch parameter is set when we're installing
|
||||
# the patch during init. At that time, we don't want to deal with
|
||||
|
@ -561,10 +564,23 @@ class PatchAgent(PatchService):
|
|||
remote = None
|
||||
ref = None
|
||||
if major_release:
|
||||
LOG.info("Major release deployment for %s with commit %s" % (major_release, commit_id))
|
||||
|
||||
# add remote
|
||||
nodetype = utils.get_platform_conf("nodetype")
|
||||
remote = ostree_utils.add_ostree_remote(major_release, nodetype)
|
||||
ref = "%s:%s" % (remote, constants.OSTREE_REF)
|
||||
LOG.info("OSTree remote added: %s" % remote)
|
||||
|
||||
# check if remote commit_id matches with the one sent by the controller
|
||||
commit_id_match = ostree_utils.check_commit_id(remote, commit_id)
|
||||
if not commit_id_match:
|
||||
LOG.exception("The OSTree commit_id %s sent by the controller "
|
||||
"doesn't match with the remote commit_id." % commit_id)
|
||||
ostree_utils.delete_ostree_remote(remote)
|
||||
LOG.info("OSTree remote deleted: %s" % remote)
|
||||
return False
|
||||
|
||||
ref = "%s:%s" % (remote, constants.OSTREE_REF)
|
||||
copy_target_release_pxeboot_files(major_release)
|
||||
|
||||
# Build up the install set
|
||||
|
|
|
@ -523,12 +523,14 @@ class PatchMessageAgentInstallReq(messages.PatchMessage):
|
|||
self.ip = None
|
||||
self.force = False
|
||||
self.major_release = None
|
||||
self.commit_id = None
|
||||
|
||||
def encode(self):
|
||||
global sc
|
||||
messages.PatchMessage.encode(self)
|
||||
self.message['force'] = self.force
|
||||
self.message['major_release'] = self.major_release
|
||||
self.message['commit_id'] = self.commit_id
|
||||
|
||||
def handle(self, sock, addr):
|
||||
LOG.error("Should not get here")
|
||||
|
@ -2747,13 +2749,15 @@ class PatchController(PatchService):
|
|||
# Check if there is a major release deployment in progress
|
||||
# and set agent request parameters accordingly
|
||||
major_release = None
|
||||
commit_id = None
|
||||
if self.check_upgrade_in_progress():
|
||||
upgrade_release = self.get_software_upgrade()
|
||||
major_release = upgrade_release["to_release"]
|
||||
commit_id = ostree_utils.get_feed_latest_commit(major_release)
|
||||
force = False
|
||||
async_req = False
|
||||
msg = "Running major release deployment, major_release=%s, force=%s, async_req=%s" % (
|
||||
major_release, force, async_req)
|
||||
msg = "Running major release deployment, major_release=%s, force=%s, async_req=%s, commit_id=%s" % (
|
||||
major_release, force, async_req, commit_id)
|
||||
msg_info += msg + "\n"
|
||||
LOG.info(msg)
|
||||
set_host_target_load(hostname, major_release)
|
||||
|
@ -2768,6 +2772,7 @@ class PatchController(PatchService):
|
|||
installreq.ip = ip
|
||||
installreq.force = force
|
||||
installreq.major_release = major_release
|
||||
installreq.commit_id = commit_id
|
||||
installreq.encode()
|
||||
self.socket_lock.acquire()
|
||||
installreq.send(self.sock_out)
|
||||
|
|
Loading…
Reference in New Issue