Open ubuntu-server-builder opened 1 year ago
Launchpad user Ryan Harper(raharper) wrote on 2019-07-19T17:46:56.002900+00:00
Hi,
Thanks for filing the bug.
It appears that the distro.update_package_sources() runs with hardcoded frequency=PER_INSTANCE.
def update_package_sources(self):
self._runner.run("update-sources", self.package_command,
["update"], freq=PER_INSTANCE)
Cloud-init could supply the package-update-upgrade frequency when calling this distro method if configured.
Hi,
I was trying to add a PPA and install packages from it but it seems such scenarios are made impossible by this issue because it's not possible to "apt update" afterwards.
My config is at https://gitlab.com/crypto-config/crypto-configuration/-/blob/main/lxd-profile if you wish to look at it.
I'm not familiar with the cloud-init code and I don't know if freq can handle that but I would expect there should be a variable that is set after apt update, and unset whenever there is an operation that touches sources.
Thanks @adrien-n for the update and reproducer steps here. I think something like the following is what we want in this case. we want to force apt update to run if previously something like custom apt sources were provided (which triggered that first apt update call and sets theupdate-sources
semaphore). Here's a very basic diff that only fnuctionally handles debian.ubuntu, but we'd need to reflect update_package_sources call signatures to all distributions which subclass this method to ensure we don't traceback when freq param is provided.
diff --git a/cloudinit/config/cc_package_update_upgrade_install.py b/cloudinit/config/cc_package_update_upgrade_install.py
index a26e001d3..f62819e9d 100644
--- a/cloudinit/config/cc_package_update_upgrade_install.py
+++ b/cloudinit/config/cc_package_update_upgrade_install.py
@@ -17,7 +17,7 @@ from cloudinit.config import Config
from cloudinit.config.schema import MetaSchema, get_meta_doc
from cloudinit.distros import ALL_DISTROS
from cloudinit.log import flush_loggers
-from cloudinit.settings import PER_INSTANCE
+from cloudinit.settings import PER_ALWAYS, PER_INSTANCE
REBOOT_FILE = "/var/run/reboot-required"
REBOOT_CMD = ["/sbin/reboot"]
@@ -104,7 +104,13 @@ def handle(name: str, cfg: Config, cloud: Cloud, args: list) -> None:
errors = []
if update or upgrade:
try:
- cloud.distro.update_package_sources()
+ # We may want to only provide PER_ALWAYS if we also know
+ # update_packages was already performed due to user-data or system
+ # configuration in /etc/cloud/cloud.cfg.*/
+ kwargs = {}
+ if cloud.distro.runner.has_run("update-pacakges", PER_INSTANCE):
+ kwargs["freq"] = PER_ALWAYS
+ cloud.distro.update_package_sources(**kwargs)
except Exception as e:
util.logexc(LOG, "Package update failed")
errors.append(e)
diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
index 87390f634..85988db75 100644
--- a/cloudinit/distros/__init__.py
+++ b/cloudinit/distros/__init__.py
@@ -37,6 +37,7 @@ from cloudinit import (
importer,
net,
persistence,
+ settings,
ssh_util,
subp,
temp_utils,
@@ -322,10 +323,12 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta):
# managers.
raise NotImplementedError()
- def update_package_sources(self):
+ def update_package_sources(
+ self, freq: str = settings.PER_INSTANCE
+ ):
for manager in self.package_managers:
try:
- manager.update_package_sources()
+ manager.update_package_sources(freq=freq)
except Exception as e:
LOG.error(
"Failed to update package using %s: %s", manager.name, e
diff --git a/cloudinit/distros/package_management/apt.py b/cloudinit/distros/package_management/apt.py
index 3c4164cd2..378fb0888 100644
--- a/cloudinit/distros/package_management/apt.py
+++ b/cloudinit/distros/package_management/apt.py
@@ -105,12 +105,12 @@ class Apt(PackageManager):
apt_get_upgrade_subcommand=cfg.get("apt_get_upgrade_subcommand"),
)
- def update_package_sources(self):
+ def update_package_sources(self, freq: str = PER_INSTANCE):
self.runner.run(
"update-sources",
self.run_package_command,
["update"],
- freq=PER_INSTANCE,
+ freq=freq,
)
@functools.lru_cache(maxsize=1)
diff --git a/cloudinit/distros/package_management/package_manager.py b/cloudinit/distros/package_management/package_manager.py
index 864555f6a..381e9673b 100644
--- a/cloudinit/distros/package_management/package_manager.py
+++ b/cloudinit/distros/package_management/package_manager.py
@@ -18,7 +18,7 @@ class PackageManager(ABC):
return cls(runner)
@abstractmethod
- def update_package_sources(self):
+ def update_package_sources(self, freq: str):
...
@abstractmethod
diff --git a/cloudinit/distros/package_management/snap.py b/cloudinit/distros/package_management/snap.py
index 92eb1af8f..582cf29ab 100644
--- a/cloudinit/distros/package_management/snap.py
+++ b/cloudinit/distros/package_management/snap.py
@@ -1,6 +1,6 @@
# This file is part of cloud-init. See LICENSE file for license information.
import logging
-from typing import Iterable, List
+from typing import Iterable, List, Optional
from cloudinit import subp, util
from cloudinit.distros.package_management.package_manager import (
@@ -14,7 +14,7 @@ LOG = logging.getLogger(__name__)
class Snap(PackageManager):
name = "snap"
- def update_package_sources(self):
+ def update_package_sources(self, freq: Optional[str]):
pass
def install_packages(self, pkglist: Iterable) -> UninstalledPackages:
Add hacktoberfest label on this issue as I think it is reasonable for anyone to work this issue.
The 23.04
cloud images have now been pulled and we can't deploy our stuff with 23.10
until this has been fixed.
The Azure Ubuntu images suffer from having a predefined list of mirrors in /etc/cloud/cloud.cfg.d/90-azure.cfg
which means that you can't provision these images with your own images and install packages properly. As this is only present in 23.10
currently I suspect this issue is going to be important with the release of the next Ubuntu LTS 24.04
as people will need to actively work around this for all their Azure Ubuntu installs.
To work around this issue you need to replace the package
directive with a runcdm
that contains apt-get -y update
and then use apt-get install -y
for all the packages you need.
Alternatively you need to run apt-get -y update
in a runcmd
before the packages
directive.
This bug was originally filed in Launchpad as LP: #1785225
Launchpad details
Launchpad user Sirio Balmelli(siriobalmelli) wrote on 2018-08-03T11:12:56.923746+00:00
... also fails to call
apt-get update
Google gives no results.
Attempted guess at "update-sources" fails:
apt-get update
is executed beforeapt-get install
every time the machine is booted. On my system the install looks like:But did not obtain an update. There seem to be no other applicable modules listed in https://cloudinit.readthedocs.io/en/latest/topics/modules.html#
Environment:
/etc/cloud/cloud.cfg
cloud_init_modules: - seed_random - bootcmd - set_hostname - update_hostname - update_etc_hosts - ca-certs - rsyslog - users-groups - ssh
cloud_config_modules: - emit_upstart - ssh-import-id - locale - set-passwords - grub-dpkg - timezone - [apt-configure, always] - [runcmd, always] # doesn't actually EXECUTE the modules - that's left for scripts-user :P
cloud_final_modules: - landscape - lxd - ssh-authkey-fingerprints - final-message - power-state-change - [package-update-upgrade-install, always] - [scripts-user, always]
system_info: distro: ubuntu paths: cloud_dir: /var/lib/cloud/ templates_dir: /etc/cloud/templates/ upstart_dir: /etc/init/ ssh_svcname: ssh
disable_root: true
datasource_list: [NoCloud, None]
preserve_hostname: false hostname: {hostname} manage_etc_hosts: true
apt: preserve_sources_list: false primary: - arches: - amd64 - i386 - default uri: "http://archive.ubuntu.com/ubuntu/" search: - "http://ch.archive.ubuntu.com/ubuntu" - "http://us.archive.ubuntu.com/ubuntu" search_dns: true security: - arches: - amd64 - i386 - default uri: "http://security.ubuntu.com/ubuntu/" search_dns: true # (custom PPAs elided) sources_list: | deb http://archive.ubuntu.com/ubuntu/ xenial main restricted deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted deb http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted deb-src http://archive.ubuntu.com/ubuntu/ xenial-updates main restricted deb http://archive.ubuntu.com/ubuntu/ xenial universe deb-src http://archive.ubuntu.com/ubuntu/ xenial universe deb http://archive.ubuntu.com/ubuntu/ xenial-updates universe deb-src http://archive.ubuntu.com/ubuntu/ xenial-updates universe deb http://archive.ubuntu.com/ubuntu/ xenial multiverse deb-src http://archive.ubuntu.com/ubuntu/ xenial multiverse deb http://archive.ubuntu.com/ubuntu/ xenial-updates multiverse deb-src http://archive.ubuntu.com/ubuntu/ xenial-updates multiverse deb http://archive.ubuntu.com/ubuntu/ xenial-backports main restricted universe multiverse deb-src http://archive.ubuntu.com/ubuntu/ xenial-backports main restricted universe multiverse deb http://security.ubuntu.com/ubuntu/ xenial-security main restricted deb-src http://security.ubuntu.com/ubuntu/ xenial-security main restricted deb http://security.ubuntu.com/ubuntu/ xenial-security universe deb-src http://security.ubuntu.com/ubuntu/ xenial-security universe deb http://security.ubuntu.com/ubuntu/ xenial-security multiverse deb-src http://security.ubuntu.com/ubuntu/ xenial-security multiverse runcmd: - [echo, startup run $(date)]
packages: # SHOULD run apt-update; does not - git package_update: true package_upgrade: true package_reboot_if_required: true