d for d in daemons if d.hostname is not None and d.hostname not in hosts]
daemons = _get_earlier_daemons([_latest_type(dtypes)], other_hosts_daemons)
err_msg_base += 'Daemons with types earlier in upgrade order than daemons on given host need upgrading.\n'
- need_upgrade_self, n1, n2, _ = self._detect_need_upgrade(daemons, target_digests)
+ need_upgrade_self, n1, n2, _ = self._detect_need_upgrade(daemons, target_digests, target_name)
if need_upgrade_self and ('mgr' not in dtypes or (daemon_types is None and services is None)):
# also report active mgr as needing to be upgraded. It is not included in the resulting list
# by default as it is treated special and handled via the need_upgrade_self bool
return True # if mds has no fs it should pass ok-to-stop
- def _detect_need_upgrade(self, daemons: List[DaemonDescription], target_digests: Optional[List[str]] = None) -> Tuple[bool, List[Tuple[DaemonDescription, bool]], List[Tuple[DaemonDescription, bool]], int]:
+ def _detect_need_upgrade(self, daemons: List[DaemonDescription], target_digests: Optional[List[str]] = None, target_name: Optional[str] = None) -> Tuple[bool, List[Tuple[DaemonDescription, bool]], List[Tuple[DaemonDescription, bool]], int]:
# this function takes a list of daemons and container digests. The purpose
# is to go through each daemon and check if the current container digests
# for that daemon match the target digests. The purpose being that we determine
done = 0
if target_digests is None:
target_digests = []
+ if target_name is None:
+ target_name = ''
for d in daemons:
assert d.daemon_type is not None
assert d.daemon_id is not None
assert d.hostname is not None
if self.mgr.use_agent and not self.mgr.cache.host_metadata_up_to_date(d.hostname):
continue
- correct_digest = False
- if (any(d in target_digests for d in (d.container_image_digests or []))
- or d.daemon_type in MONITORING_STACK_TYPES):
- logger.debug('daemon %s.%s container digest correct' % (
+ correct_image = False
+ # check if the container digest for the digest we're upgrading to matches
+ # the container digest for the daemon if "use_repo_digest" setting is true
+ # or that the image name matches the daemon's image name if "use_repo_digest"
+ # is false. The idea is to generally check if the daemon is already using
+ # the image we're upgrading to or not. Additionally, since monitoring stack
+ # daemons are included in the upgrade process but don't use the ceph images
+ # we are assuming any monitoring stack daemon is on the "correct" image already
+ if (
+ (self.mgr.use_repo_digest and d.matches_digests(target_digests))
+ or (not self.mgr.use_repo_digest and d.matches_image_name(target_name))
+ or (d.daemon_type in MONITORING_STACK_TYPES)
+ ):
+ logger.debug('daemon %s.%s on correct image' % (
d.daemon_type, d.daemon_id))
- correct_digest = True
+ correct_image = True
+ # do deployed_by check using digest no matter what. We don't care
+ # what repo the image used to deploy the daemon was as long
+ # as the image content is correct
if any(d in target_digests for d in (d.deployed_by or [])):
logger.debug('daemon %s.%s deployed by correct version' % (
d.daemon_type, d.daemon_id))
need_upgrade_self = True
continue
- if correct_digest:
+ if correct_image:
logger.debug('daemon %s.%s not deployed by correct version' % (
d.daemon_type, d.daemon_id))
need_upgrade_deployer.append((d, True))
daemons_of_type = [d for d in daemons if d.daemon_type == daemon_type]
need_upgrade_self, need_upgrade, need_upgrade_deployer, done = self._detect_need_upgrade(
- daemons_of_type, target_digests)
+ daemons_of_type, target_digests, target_image)
upgraded_daemon_count += done
self._update_upgrade_progress(upgraded_daemon_count / len(daemons))
[d[0].name() for d in need_upgrade_deployer]
dds = [d for d in self.mgr.cache.get_daemons_by_type(
daemon_type) if d.name() not in need_upgrade_names]
- need_upgrade_active, n1, n2, __ = self._detect_need_upgrade(dds, target_digests)
+ need_upgrade_active, n1, n2, __ = self._detect_need_upgrade(dds, target_digests, target_image)
if not n1:
if not need_upgrade_self and need_upgrade_active:
need_upgrade_self = True
# types. If we haven't actually finished upgrading all the daemons
# of this type, we should exit the loop here
_, n1, n2, _ = self._detect_need_upgrade(
- self.mgr.cache.get_daemons_by_type(daemon_type), target_digests)
+ self.mgr.cache.get_daemons_by_type(daemon_type), target_digests, target_image)
if n1 or n2:
continue
return (daemon_type_to_service(self.daemon_type) + '.' + self.daemon_id).startswith(service_name + '.')
return False
+ def matches_digests(self, digests: Optional[List[str]]) -> bool:
+ # the DaemonDescription class maintains a list of container digests
+ # for the container image last reported as being used for the daemons.
+ # This function checks if any of those digests match any of the digests
+ # in the list of digests provided as an arg to this function
+ if not digests or not self.container_image_digests:
+ return False
+ return any(d in digests for d in self.container_image_digests)
+
+ def matches_image_name(self, image_name: Optional[str]) -> bool:
+ # the DaemonDescription class has an attribute that tracks the image
+ # name of the container image last reported as being used by the daemon.
+ # This function compares if the image name provided as an arg matches
+ # the image name in said attribute
+ if not image_name or not self.container_image_name:
+ return False
+ return image_name == self.container_image_name
+
def service_id(self) -> str:
assert self.daemon_id is not None
assert self.daemon_type is not None