Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37580515
en ru br
Репозитории ALT

Группа :: Система/Настройка/Загрузка и инициализация
Пакет: cloud-init

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: cloud-init-22.3.4-alt3.patch
Скачать


 .gear/rules                                        |   4 +
 .../tags/086f0575500c914ea2314b086fe8f0632688dfae  |  22 ++
 .../tags/5236c651a2bdd5625d3d6a98ff06ea24e3905c84  |  22 ++
 .gear/tags/list                                    |   1 +
 alt/01_etcnet.cfg                                  |   3 +
 alt/01_netplan.cfg                                 |   3 +
 alt/01_network-manager.cfg                         |   3 +
 alt/90_datasource-list.cfg                         |   1 +
 alt/cloud-config                                   |  85 ++++++
 alt/cloud-final                                    |  85 ++++++
 alt/cloud-init                                     |  85 ++++++
 alt/cloud-init-alt.cfg                             | 105 ++++++++
 alt/cloud-init-local                               |  85 ++++++
 alt/cloud-init-tmpfiles.conf                       |   1 +
 alt/cloud-init.spec                                | 299 +++++++++++++++++++++
 alt/ds-identify.cfg                                |   1 +
 cloudinit/config/cc_ntp.py                         |   3 +-
 cloudinit/config/cc_phone_home.py                  |   8 +-
 cloudinit/config/cc_resolv_conf.py                 |   3 +-
 cloudinit/config/cc_ssh.py                         |  12 +-
 cloudinit/distros/__init__.py                      |   3 +
 cloudinit/distros/altlinux.py                      | 274 +++++++++++++++++++
 cloudinit/net/activators.py                        |  35 +++
 cloudinit/net/etcnet.py                            | 123 +++++++++
 cloudinit/net/renderers.py                         |   3 +
 cloudinit/netinfo.py                               |   1 +
 cloudinit/sources/__init__.py                      |   2 +-
 cloudinit/ssh_util.py                              |   2 +-
 setup.py                                           |   3 -
 systemd/cloud-config.service.tmpl                  |   1 +
 systemd/cloud-final.service.tmpl                   |   1 +
 systemd/cloud-init-generator.tmpl                  |   2 +-
 systemd/cloud-init-local.service.tmpl              |   1 +
 systemd/cloud-init.service.tmpl                    |   5 +-
 templates/hosts.altlinux.tmpl                      |  22 ++
 templates/sources.list.altlinux.tmpl               |  15 ++
 .../integration_tests/modules/test_set_password.py |   4 +-
 .../integration_tests/modules/test_ssh_generate.py |  16 +-
 .../modules/test_ssh_keys_provided.py              |  24 +-
 .../integration_tests/modules/test_ssh_keysfile.py |  20 +-
 tests/unittests/config/test_cc_ssh.py              |  24 +-
 tests/unittests/sources/test_vmware.py             |  13 +-
 tests/unittests/test_cli.py                        |   2 +-
 tests/unittests/test_net.py                        |   1 +
 tests/unittests/test_net_activators.py             |   1 +
 tests/unittests/test_ssh_util.py                   |  16 +-
 tools/21-cloudinit.conf                            |   2 +-
 tools/write-ssh-key-fingerprints                   |   4 +-
 48 files changed, 1368 insertions(+), 83 deletions(-)
diff --git a/.gear/rules b/.gear/rules
new file mode 100644
index 00000000..6eef1b7a
--- /dev/null
+++ b/.gear/rules
@@ -0,0 +1,4 @@
+spec: alt/cloud-init.spec
+tar: @version@:.
+diff: @version@:. .
+copy: alt/*
diff --git a/.gear/tags/086f0575500c914ea2314b086fe8f0632688dfae b/.gear/tags/086f0575500c914ea2314b086fe8f0632688dfae
new file mode 100644
index 00000000..8666d6ba
--- /dev/null
+++ b/.gear/tags/086f0575500c914ea2314b086fe8f0632688dfae
@@ -0,0 +1,22 @@
+object 7fb6f78177b5ece10ca7c54ba3958010a9987f06
+type commit
+tag 0.7.9
+tagger Scott Moser <smoser@brickies.net> 1482511086 -0500
+
+release 0.7.9
+-----BEGIN PGP SIGNATURE-----
+
+iQIxBAABCAAbBQJYXVLzFBxzbW9zZXJAYnJpY2tpZXMubmV0AAoJEB5EEKQCS8bw
+nAAP+QEWaZhaC4liZvMnb7nY58TuQc+dS1d2pI3Hkm0XPRkIkGOPYIhh/H4mUGs9
+5V4dytnJBbaJMftOOTUICjHPk8mrK8PmrdANczLr5C/WSkH0BSfulC6Y/fHwaWeV
+Ts1WUeW8hUuOqaFmI+Hfbbmw9tlXqzqRgR2ehbsKYmfpDb2A2yLmZOV86R1nRM+u
+8fUnzT+Ro3CGe0Bzl7K4dJlSwq2mRkVyTrZdRjPSbhsnER/yfunf2R9Sog7beRzG
+MbxhCfbnZGNQzVYwfmyhKYp7U8uLB8PSvOTZ3NwG8MSZd+PyD72LMe+HBuZSG7ks
+HgSnjITsjXSBpLWwHFqlb7xOiii80ybeCD5VDFvn1+3vzaZ6vAqsPhO9Nt6KsTHb
+O591bz1uu3fnNnbs2q9BEt/Ucfsx4M12FQL47e1w1FuqrZIC093eE4HGzxXKRpdE
+ADJOwL77D9TOu3dj5tUo0SZ4XyotCXpSwCOkmK4qG4mivg1J20w9Yf4T1xS4+GfL
+kYUEZzIIR7v4aZ0kJbfyZXL7suVgHsYKaPXyplIbTHCVpTYFxZVo11YaYZ71Mobh
+nH4iYFKiw/BZ+wcW3vZb6opfvfqOMTFcPJflHUf6uZOW2nzE4chKK/KbRV3ToKH1
+Pfnb4RATM9OVx6qxRNuMjarT5BaZ2xNGu1i0MLUdZvmLJuyu
+=h+L0
+-----END PGP SIGNATURE-----
diff --git a/.gear/tags/5236c651a2bdd5625d3d6a98ff06ea24e3905c84 b/.gear/tags/5236c651a2bdd5625d3d6a98ff06ea24e3905c84
new file mode 100644
index 00000000..0a77f3f5
--- /dev/null
+++ b/.gear/tags/5236c651a2bdd5625d3d6a98ff06ea24e3905c84
@@ -0,0 +1,22 @@
+object 36c23f523dc2067f206d48ee778f1dda886de305
+type commit
+tag 22.3.4
+tagger Brett Holman <brett.holman@canonical.com> 1664571403 -0600
+
+Release 22.3.4
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAABCgAdFiEEOj7zTf3ts7fz/fYD+D93EppevYUFAmM3WBAACgkQ+D93Eppe
+vYUygg/7B/tKLr5WJc3cgGqlCAqOcgzpLKcUjYTSqssJ8JGmjAm6WiZ5dn6bLtbp
+NPFksT/RzP0Av7Ti/i+M28qFSMAu10EHHuF0kol+bp9EGMPDDsVktQZYKeK8JH8/
+2wjDMgZpgrJefOtAguh2LcWEDULIDzmWl/QmtPgVmXHcOx3ag8A8pJShsFg9KBrE
+EIwhBia+WPL0UD6mRJRgorqEXV64VRLN6Qbt8gzWH9DVuj92pJ4P+TJ8BKO5ZCYe
+g8w758ELG/vEFbDBsjOapqqTT/F+fG5Cz5JvMk8PADviYBj276IaffyZjE02p2lQ
+K9dIiIp33yE69OHSm+a6W7F+aLUR2AD9FuF+TyLyIJsVYvK+oh8FjfWSJD03UxB0
++nTBlurDVIv10nG/Q1VW53oKn76vUXK+W2NFlV91dX6nhamUv0q+Z8LLHdWQn5Uq
+ao+9+FnEMdv6fqI8bhSY9DzuJvZ91SIhHCUgKICO01goTJ19wpB/EqvZzdP5F7ut
+soseb81UMKiC2PddSLKOfqSnsbRPK0DpIG+O+RM3bpuBYvVG1XiZCb+Kbgd/nru6
+iqJvojK+uUssS/VkE9c5/+j7iZNO3cem5A/NktC9wpK9xqCP6K9I44XT2Vg378q5
+lnLvX7orwBHA0pccQz1KAWZWwi28fzLljypYClJR7c8eQ4rz2Rc=
+=EoLv
+-----END PGP SIGNATURE-----
diff --git a/.gear/tags/list b/.gear/tags/list
new file mode 100644
index 00000000..4adab074
--- /dev/null
+++ b/.gear/tags/list
@@ -0,0 +1 @@
+5236c651a2bdd5625d3d6a98ff06ea24e3905c84 22.3.4
diff --git a/alt/01_etcnet.cfg b/alt/01_etcnet.cfg
new file mode 100644
index 00000000..7c5bd50e
--- /dev/null
+++ b/alt/01_etcnet.cfg
@@ -0,0 +1,3 @@
+system_info:
+  network:
+    renderers: ['etcnet']
diff --git a/alt/01_netplan.cfg b/alt/01_netplan.cfg
new file mode 100644
index 00000000..572ebf19
--- /dev/null
+++ b/alt/01_netplan.cfg
@@ -0,0 +1,3 @@
+system_info:
+  network:
+    renderers: ['netplan']
diff --git a/alt/01_network-manager.cfg b/alt/01_network-manager.cfg
new file mode 100644
index 00000000..799b1c6c
--- /dev/null
+++ b/alt/01_network-manager.cfg
@@ -0,0 +1,3 @@
+system_info:
+  network:
+    renderers: ['network-manager']
diff --git a/alt/90_datasource-list.cfg b/alt/90_datasource-list.cfg
new file mode 100644
index 00000000..9a7db7e6
--- /dev/null
+++ b/alt/90_datasource-list.cfg
@@ -0,0 +1 @@
+datasource_list: [ NoCloud, ConfigDrive, OpenNebula, DigitalOcean, Azure, AltCloud, OVF, MAAS, GCE, OpenStack, CloudSigma, SmartOS, Bigstep, Scaleway, AliYun, Ec2, CloudStack, Hetzner, IBMCloud, Oracle, Exoscale, RbxCloud, UpCloud, VMware, Vultr, LXD, None ]
diff --git a/alt/cloud-config b/alt/cloud-config
new file mode 100755
index 00000000..7b528d27
--- /dev/null
+++ b/alt/cloud-config
@@ -0,0 +1,85 @@
+#!/bin/sh
+# cloud-config      Apply the settings specified in cloud-config.
+#
+# chkconfig: - 80 20
+# description:  Start cloud-init and runs the config phase \
+#               dand any associated config modules as desired.
+# processname: cloud-init
+# config: /etc/cloud/cloud.cfg
+#
+### BEGIN INIT INFO
+# Provides:          cloud-config
+# Required-Start:    cloud-init cloud-init-local
+# Should-Start:      $time
+# Required-Stop:
+# Should-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Apply the settings specified in cloud-config
+# Description:       Start cloud-init and runs the config phase
+#	and any associated config modules as desired.
+### END INIT INFO
+
+# Do not load RH compatibility interface.
+WITHOUT_RC_COMPAT=1
+
+# Source function library.
+. /etc/init.d/functions
+
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+RETVAL=0
+
+NAME="cloud-init"
+DAEMON="/usr/bin/$NAME"
+SourceIfNotEmpty /etc/sysconfig/$NAME
+
+start()
+{
+	msg_starting $"config $NAME: "
+	$DAEMON $CLOUDINITARGS modules --mode config
+	RETVAL=$?
+	return $RETVAL
+}
+
+stop() {
+	msg_stopping $"config $NAME: "
+	# No-op
+	RETVAL=1
+	return $RETVAL
+}
+
+case "$1" in
+    start)
+	start
+	RETVAL=$?
+	;;
+    stop)
+	stop
+	RETVAL=$?
+	;;
+    restart|try-restart|condrestart)
+	start
+	RETVAL=$?
+	;;
+    reload|force-reload)
+	# It does not support reload
+	RETVAL=3
+	;;
+    status)
+        echo -n $"Checking for service $NAME:"
+        # Return value is slightly different for the status command:
+        # 0 - service up and running
+        # 1 - service dead, but /var/run/  pid  file exists
+        # 2 - service dead, but /var/lock/ lock file exists
+        # 3 - service not running (unused)
+        # 4 - service status unknown :-(
+        # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.)
+        RETVAL=3
+	;;
+    *)
+	msg_usage "${0##*/} {start|stop|status|try-restart|condrestart|restart|force-reload|reload}"
+        RETVAL=1
+	;;
+esac
+
+exit $RETVAL
diff --git a/alt/cloud-final b/alt/cloud-final
new file mode 100755
index 00000000..ac9a8ace
--- /dev/null
+++ b/alt/cloud-final
@@ -0,0 +1,85 @@
+#!/bin/sh
+# cloud-final      Execute cloud user/final scripts.
+#
+# chkconfig: - 90 10
+# description:  Start cloud-init and runs the final phase \
+#               dand any associated final modules as desired.
+# processname: cloud-init
+# config: /etc/cloud/cloud.cfg
+#
+### BEGIN INIT INFO
+# Provides:          cloud-final
+# Required-Start:    $all cloud-config
+# Should-Start:      $time
+# Required-Stop:
+# Should-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Execute cloud user/final scripts
+# Description:       Start cloud-init and runs the final phase
+#	and any associated final modules as desired.
+### END INIT INFO
+
+# Do not load RH compatibility interface.
+WITHOUT_RC_COMPAT=1
+
+# Source function library.
+. /etc/init.d/functions
+
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+RETVAL=0
+
+NAME="cloud-init"
+DAEMON="/usr/bin/$NAME"
+SourceIfNotEmpty /etc/sysconfig/$NAME
+
+start()
+{
+	msg_starting $"final $NAME: "
+	$DAEMON $CLOUDINITARGS modules --mode final
+	RETVAL=$?
+	return $RETVAL
+}
+
+stop() {
+	msg_stopping $"final $NAME: "
+	# No-op
+	RETVAL=1
+	return $RETVAL
+}
+
+case "$1" in
+    start)
+	start
+	RETVAL=$?
+	;;
+    stop)
+	stop
+	RETVAL=$?
+	;;
+    restart|try-restart|condrestart)
+	start
+	RETVAL=$?
+	;;
+    reload|force-reload)
+	# It does not support reload
+	RETVAL=3
+	;;
+    status)
+        echo -n $"Checking for service $NAME:"
+        # Return value is slightly different for the status command:
+        # 0 - service up and running
+        # 1 - service dead, but /var/run/  pid  file exists
+        # 2 - service dead, but /var/lock/ lock file exists
+        # 3 - service not running (unused)
+        # 4 - service status unknown :-(
+        # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.)
+        RETVAL=3
+	;;
+    *)
+	msg_usage "${0##*/} {start|stop|status|try-restart|condrestart|restart|force-reload|reload}"
+        RETVAL=1
+	;;
+esac
+
+exit $RETVAL
diff --git a/alt/cloud-init b/alt/cloud-init
new file mode 100755
index 00000000..d95ba34d
--- /dev/null
+++ b/alt/cloud-init
@@ -0,0 +1,85 @@
+#!/bin/sh
+# cloud-init      Initial cloud-init job (metadata service crawler).
+#
+# chkconfig: - 13 80
+# description:  Start cloud-init and runs the init phase \
+#               dand any associated init modules as desired.
+# processname: cloud-init
+# config: /etc/cloud/cloud.cfg
+#
+### BEGIN INIT INFO
+# Provides:          cloud-init
+# Required-Start:    $local_fs $network $named $remote_fs cloud-init-local
+# Should-Start:      $time
+# Required-Stop:
+# Should-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Initial cloud-init job (metadata service crawler)
+# Description:       Start cloud-init and runs the init phase
+#	and any associated init modules as desired.
+### END INIT INFO
+
+# Do not load RH compatibility interface.
+WITHOUT_RC_COMPAT=1
+
+# Source function library.
+. /etc/init.d/functions
+
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+RETVAL=0
+
+NAME="cloud-init"
+DAEMON="/usr/bin/$NAME"
+SourceIfNotEmpty /etc/sysconfig/$NAME
+
+start()
+{
+	msg_starting $"init $NAME: "
+	$DAEMON $CLOUDINITARGS init
+	RETVAL=$?
+	return $RETVAL
+}
+
+stop() {
+	msg_stopping $"init $NAME: "
+	# No-op
+	RETVAL=1
+	return $RETVAL
+}
+
+case "$1" in
+    start)
+	start
+	RETVAL=$?
+	;;
+    stop)
+	stop
+	RETVAL=$?
+	;;
+    restart|try-restart|condrestart)
+	start
+	RETVAL=$?
+	;;
+    reload|force-reload)
+	# It does not support reload
+	RETVAL=3
+	;;
+    status)
+        echo -n $"Checking for service $NAME:"
+        # Return value is slightly different for the status command:
+        # 0 - service up and running
+        # 1 - service dead, but /var/run/  pid  file exists
+        # 2 - service dead, but /var/lock/ lock file exists
+        # 3 - service not running (unused)
+        # 4 - service status unknown :-(
+        # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.)
+        RETVAL=3
+	;;
+    *)
+	msg_usage "${0##*/} {start|stop|status|try-restart|condrestart|restart|force-reload|reload}"
+        RETVAL=1
+	;;
+esac
+
+exit $RETVAL
diff --git a/alt/cloud-init-alt.cfg b/alt/cloud-init-alt.cfg
new file mode 100644
index 00000000..8a42274d
--- /dev/null
+++ b/alt/cloud-init-alt.cfg
@@ -0,0 +1,105 @@
+# The top level settings are used as module
+# and system configuration.
+
+# A set of users which may be applied and/or used by various modules
+# when a 'default' entry is found it will reference the 'default_user'
+# from the distro configuration specified below
+users:
+   - default
+
+# If this is set, 'root' will not be able to ssh in and they
+# will get a message to login instead as the default $user
+disable_root: true
+
+mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2']
+resize_rootfs_tmp: /dev
+ssh_pwauth:   0
+
+# This will cause the set+update hostname module to not operate (if true)
+preserve_hostname: false
+
+ssh_deletekeys:   0
+ssh_genkeytypes:  ~
+ssh_svcname:      sshd
+syslog_fix_perms: ~
+
+# Example datasource config
+# datasource:
+#    Ec2:
+#      metadata_urls: [ 'blah.com' ]
+#      timeout: 5 # (defaults to 50 seconds)
+#      max_wait: 10 # (defaults to 120 seconds)
+
+# The modules that run in the 'init' stage
+cloud_init_modules:
+ - migrator
+ - seed_random
+ - bootcmd
+ - write-files
+ - growpart
+ - resizefs
+ - disk_setup
+ - mounts
+ - set_hostname
+ - update_hostname
+ - update_etc_hosts
+ - ca-certs
+ - rsyslog
+ - users-groups
+ - ssh
+
+# The modules that run in the 'config' stage
+cloud_config_modules:
+# Emit the cloud config ready event
+# this can be used by upstart jobs for 'start on cloud-config'.
+ - ssh-import-id
+ - locale
+ - set-passwords
+ - spacewalk
+ - ntp
+ - timezone
+ - runcmd
+
+# - apt-pipelining
+# - apt-configure
+
+# The modules that run in the 'final' stage
+cloud_final_modules:
+ - package-update-upgrade-install
+ - lxd
+ - puppet
+ - chef
+ - mcollective
+ - salt-minion
+ - rightscale_userdata
+ - scripts-vendor
+ - scripts-per-once
+ - scripts-per-boot
+ - scripts-per-instance
+ - scripts-user
+ - ssh-authkey-fingerprints
+ - keys-to-console
+ - phone-home
+ - final-message
+ - power-state-change
+
+# System and/or distro specific settings
+# (not accessible to handlers/transforms)
+system_info:
+   # This will affect which distro class gets used
+   distro: altlinux
+   # Default user name + that default users groups (if added/used)
+   default_user:
+     name: altlinux
+     lock_passwd: True
+     gecos: ALT Linux Cloud User
+     groups: [wheel, lxd, adm, uucp, proc, systemd-journal]
+     sudo: ["ALL=(ALL) NOPASSWD:ALL"]
+     shell: /bin/bash
+   # Other config here will be given to the distro class and/or path classes
+   paths:
+      cloud_dir: /var/lib/cloud/
+      templates_dir: /etc/cloud/templates/
+   network:
+      renderers: ['netplan', 'networkd', 'etcnet']
+   ssh_svcname: sshd
diff --git a/alt/cloud-init-local b/alt/cloud-init-local
new file mode 100755
index 00000000..5c4c117e
--- /dev/null
+++ b/alt/cloud-init-local
@@ -0,0 +1,85 @@
+#!/bin/sh
+# cloud-init-local      Initial cloud-init job (pre-networking).
+#
+# chkconfig: - 9 91
+# description:  Start cloud-init and runs the init-local phase \
+#               dand any associated init-local modules as desired.
+# processname: cloud-init
+# config: /etc/cloud/cloud.cfg
+#
+### BEGIN INIT INFO
+# Provides:          cloud-init-local
+# Required-Start:    $local_fs
+# Should-Start:      $time
+# Required-Stop:
+# Should-Stop:
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Initial cloud-init job (pre-networking)
+# Description:       Start cloud-init and runs the initialization phases
+#	and any associated initial modules as desired.
+### END INIT INFO
+
+# Do not load RH compatibility interface.
+WITHOUT_RC_COMPAT=1
+
+# Source function library.
+. /etc/init.d/functions
+
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+RETVAL=0
+
+NAME="cloud-init"
+DAEMON="/usr/bin/$NAME"
+SourceIfNotEmpty /etc/sysconfig/$NAME
+
+start()
+{
+	msg_starting $"init-local $NAME: "
+	$DAEMON $CLOUDINITARGS init --local
+	RETVAL=$?
+	return $RETVAL
+}
+
+stop() {
+	msg_stopping $"init-local $NAME: "
+	# No-op
+	RETVAL=1
+	return $RETVAL
+}
+
+case "$1" in
+    start)
+	start
+	RETVAL=$?
+	;;
+    stop)
+	stop
+	RETVAL=$?
+	;;
+    restart|try-restart|condrestart)
+	start
+	RETVAL=$?
+	;;
+    reload|force-reload)
+	# It does not support reload
+	RETVAL=3
+	;;
+    status)
+        echo -n $"Checking for service $NAME:"
+        # Return value is slightly different for the status command:
+        # 0 - service up and running
+        # 1 - service dead, but /var/run/  pid  file exists
+        # 2 - service dead, but /var/lock/ lock file exists
+        # 3 - service not running (unused)
+        # 4 - service status unknown :-(
+        # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.)
+        RETVAL=3
+	;;
+    *)
+	msg_usage "${0##*/} {start|stop|status|try-restart|condrestart|restart|force-reload|reload}"
+        RETVAL=1
+	;;
+esac
+
+exit $RETVAL
diff --git a/alt/cloud-init-tmpfiles.conf b/alt/cloud-init-tmpfiles.conf
new file mode 100644
index 00000000..0c6d2a3b
--- /dev/null
+++ b/alt/cloud-init-tmpfiles.conf
@@ -0,0 +1 @@
+d /run/cloud-init 0700 root root - -
diff --git a/alt/cloud-init.spec b/alt/cloud-init.spec
new file mode 100644
index 00000000..6f090cd4
--- /dev/null
+++ b/alt/cloud-init.spec
@@ -0,0 +1,299 @@
+%def_enable check
+
+Name:    cloud-init
+Version: 22.3.4
+Release: alt3
+
+Summary: Cloud instance init scripts
+Group:   System/Configuration/Boot and Init
+License: GPLv3
+Url:     http://launchpad.net/cloud-init
+
+Source0: %name-%version.tar
+
+Source1: cloud-init-alt.cfg
+Source2: cloud-init-tmpfiles.conf
+Source3: ds-identify.cfg
+
+Source11: cloud-config
+Source12: cloud-final
+Source13: cloud-init
+Source14: cloud-init-local
+
+# Network configs
+Source31: 01_netplan.cfg
+Source32: 01_etcnet.cfg
+Source33: 01_network-manager.cfg
+
+# Other configs
+Source41: 90_datasource-list.cfg
+
+Patch1: %name-%version-%release.patch
+
+%add_findreq_skiplist /lib/systemd/system-generators/cloud-init-generator
+
+BuildArch: noarch
+
+%filter_from_requires /^open-vm-tools/d
+%filter_from_requires s/requests.packages.urllib3.connectionpool/urllib3.connectionpool/
+
+BuildRequires(pre): rpm-build-python3
+BuildRequires: python3-dev python3-module-distribute
+BuildRequires: python3-module-yaml python3-module-oauthlib
+BuildRequires: systemd-devel
+BuildRequires: python3-module-httpretty python3-module-serial iproute2
+BuildRequires: util-linux net-tools python3-module-jinja2
+BuildRequires: python3-module-contextlib2 python3-module-prettytable
+BuildRequires: python3-module-requests
+%if_enabled check
+BuildRequires: /proc
+BuildRequires: python3-module-jsonpatch
+BuildRequires: python3-module-configobj python3-module-mock
+BuildRequires: python3-module-oauthlib python3-module-pytest
+BuildRequires: python3-module-pytest-mock
+BuildRequires: python3(netifaces) python3(jsonschema) python3(responses)
+BuildRequires: shadow-utils passwd
+%endif
+
+Requires: sudo
+Requires: e2fsprogs
+Requires: cloud-utils-growpart
+Requires: procps
+Requires: iproute net-tools
+Requires: shadow-utils
+Requires: /bin/run-parts
+Requires: dhcp-client
+# add not autoreq'ed
+%py3_requires Cheetah
+%py3_requires jinja2
+
+# use urllib3 for requests.packages.urllib3
+%py3_requires urllib3
+%filter_from_requires /python3(requests.packages.urllib3.connection)/d
+%filter_from_requires /python3(requests.packages.urllib3.poolmanager)/d
+
+%description
+Cloud-init is a set of init scripts for cloud instances.  Cloud instances
+need special scripts to run during initialization to retrieve and install
+ssh keys and to let the user run various scripts.
+
+%package config-netplan
+Summary: Cloud config option use netplan network render
+Group:   System/Configuration/Boot and Init
+License: GPLv3
+
+Requires: cloud-init >= 21.3
+Requires: netplan
+Conflicts: cloud-init-config-etcnet cloud-init-config-network-manager
+
+%description config-netplan
+%summary.
+
+%package config-etcnet
+Summary: Cloud config option use etcnet network render
+Group:   System/Configuration/Boot and Init
+License: GPLv3
+
+Requires: cloud-init >= 21.3
+Requires: etcnet
+Conflicts: cloud-init-config-netplan cloud-init-config-network-manager
+
+%description config-etcnet
+%summary.
+
+%package config-network-manager
+Summary: Cloud config option use NetworkManager network render
+Group:   System/Configuration/Boot and Init
+License: GPLv3
+
+Requires: cloud-init >= 22.2.2
+Requires: NetworkManager
+Conflicts: cloud-init-config-etcnet cloud-init-config-netplan
+
+%description config-network-manager
+%summary.
+
+%prep
+%setup
+%patch1 -p1
+
+%build
+%python3_build_debug
+
+%install
+%python3_install --init-system=systemd
+
+install -pD -m644 %SOURCE1 %buildroot%_sysconfdir/cloud/cloud.cfg
+install -pD -m644 %SOURCE2 %buildroot%_tmpfilesdir/cloud-init.conf
+install -pD -m644 %SOURCE3 %buildroot%_sysconfdir/cloud/
+
+install -pD -m755 %SOURCE11 %buildroot%_initdir/cloud-config
+install -pD -m755 %SOURCE12 %buildroot%_initdir/cloud-final
+install -pD -m755 %SOURCE13 %buildroot%_initdir/cloud-init
+install -pD -m755 %SOURCE14 %buildroot%_initdir/cloud-init-local
+
+# Install network configs
+install -pD -m644 %SOURCE31 %buildroot%_sysconfdir/cloud/cloud.cfg.d/
+install -pD -m644 %SOURCE32 %buildroot%_sysconfdir/cloud/cloud.cfg.d/
+install -pD -m644 %SOURCE33 %buildroot%_sysconfdir/cloud/cloud.cfg.d/
+
+# Install other configs
+install -pD -m644 %SOURCE41 %buildroot%_sysconfdir/cloud/cloud.cfg.d/
+
+mkdir -p %buildroot%_libexecdir
+mv %buildroot/usr/libexec/%name %buildroot%_libexecdir/
+mkdir -p %buildroot%_sharedstatedir/cloud
+
+# Remove non-ALTLinux templates
+rm -f %buildroot%_sysconfdir/cloud/templates/*.debian.*
+rm -f %buildroot%_sysconfdir/cloud/templates/*.freebsd.*
+rm -f %buildroot%_sysconfdir/cloud/templates/*.redhat.*
+rm -f %buildroot%_sysconfdir/cloud/templates/*.suse.*
+rm -f %buildroot%_sysconfdir/cloud/templates/*.ubuntu.*
+
+%check
+export PATH="$PATH:/usr/sbin"
+make unittest
+
+%post
+%post_service cloud-config
+%post_service cloud-final
+%post_service cloud-init
+%post_service cloud-init-local
+
+%preun
+%preun_service cloud-config
+%preun_service cloud-final
+%preun_service cloud-init
+%preun_service cloud-init-local
+
+%files config-netplan
+%config            %_sysconfdir/cloud/cloud.cfg.d/01_netplan.cfg
+
+%files config-etcnet
+%config            %_sysconfdir/cloud/cloud.cfg.d/01_etcnet.cfg
+
+%files config-network-manager
+%config            %_sysconfdir/cloud/cloud.cfg.d/01_network-manager.cfg
+
+%files
+%doc ChangeLog TODO.rst
+%dir               %_sysconfdir/cloud
+%dir               %_sysconfdir/cloud/clean.d
+%doc               %_sysconfdir/cloud/clean.d/README
+%config(noreplace) %_sysconfdir/cloud/*.cfg
+%dir               %_sysconfdir/cloud/cloud.cfg.d
+%config(noreplace) %_sysconfdir/cloud/cloud.cfg.d/*.cfg
+%exclude           %_sysconfdir/cloud/cloud.cfg.d/01_netplan.cfg
+%exclude           %_sysconfdir/cloud/cloud.cfg.d/01_etcnet.cfg
+%exclude           %_sysconfdir/cloud/cloud.cfg.d/01_network-manager.cfg
+%doc               %_sysconfdir/cloud/cloud.cfg.d/README
+%dir               %_sysconfdir/cloud/templates
+%config(noreplace) %_sysconfdir/cloud/templates/*
+%_sysconfdir/NetworkManager/dispatcher.d/hook-network-manager
+%_datadir/bash-completion/completions/%name
+/lib/udev/rules.d/66-azure-ephemeral.rules
+%_initdir/*
+%_unitdir/*
+%_tmpfilesdir/*
+/lib/systemd/system-generators/cloud-init-generator
+%python3_sitelibdir/*
+%_libexecdir/%name
+%_bindir/cloud-init*
+%_bindir/cloud-id
+%doc %_datadir/doc/%name
+%dir %_sharedstatedir/cloud
+
+%changelog
+* Thu Jan 12 2023 Mikhail Gordeev <obirvalger@altlinux.org> 22.3.4-alt3
+- Fix package installation error
+
+* Fri Nov 18 2022 Michael Shigorin <mike@altlinux.org> 22.3.4-alt2
+- Fix BR: for --disable check case
+
+* Tue Nov 08 2022 Mikhail Gordeev <obirvalger@altlinux.org> 22.3.4-alt1
+- 22.3.4
+
+* Tue Aug 23 2022 Mikhail Gordeev <obirvalger@altlinux.org> 22.2.2-alt2
+- Exclude network-manager config from main cloud-init package
+- Add datasource list and ds-identify configs
+
+* Wed Aug 03 2022 Mikhail Gordeev <obirvalger@altlinux.org> 22.2.2-alt1
+- 22.2.2
+- Add config-network-manager package for NetworkManager render
+
+* Wed Jun 08 2022 Mikhail Gordeev <obirvalger@altlinux.org> 21.4-alt3
+- Remove unnecessary build Requires
+
+* Mon Nov 22 2021 Andrey Limachko <liannnix@altlinux.org> 21.4-alt2
+- When using sudo add user to the wheel group
+- Add DHCP interface configuration support for etcnet
+- Add config-etcnet package for etcnet render
+- Add Requires and Conflicts for config subpackages
+- Set netplan network renderer to default
+- Add etcnet activator and activator cfg variable
+
+* Mon Nov 08 2021 Mikhail Gordeev <obirvalger@altlinux.org> 21.4-alt1
+- 21.4
+
+* Wed Sep 01 2021 Mikhail Gordeev <obirvalger@altlinux.org> 21.3-alt1
+- Update to 21.3
+
+* Wed May 26 2021 Mikhail Gordeev <obirvalger@altlinux.org> 21.2-alt1
+- Update to 21.2
+
+* Wed Dec 02 2020 Mikhail Gordeev <obirvalger@altlinux.org> 20.4-alt1
+- Update to 20.4
+- Enable check
+- Fix not setting password via passwd field
+
+* Mon Nov 09 2020 Mikhail Gordeev <obirvalger@altlinux.org> 20.1-alt2
+- Fix dictionary key lookup for python3 (Closes: 38848)
+
+* Mon Apr 06 2020 Mikhail Gordeev <obirvalger@altlinux.org> 20.1-alt1
+- Update to 20.1
+
+* Mon Sep 02 2019 Mikhail Gordeev <obirvalger@altlinux.org> 19.2-alt3
+- Create package cloud-init-config-netplan
+
+* Tue Aug 20 2019 Mikhail Gordeev <obirvalger@altlinux.org> 19.2-alt2
+- Pack /etc/cloud
+
+* Thu Jul 25 2019 Mikhail Gordeev <obirvalger@altlinux.org> 19.2-alt1
+- Update to 19.2
+- Use netplan to render network
+
+* Sun Dec 16 2018 Mikhail Gordeev <obirvalger@altlinux.org> 18.4-alt2
+- Allow services works only in virtualization
+
+* Thu Dec 13 2018 Mikhail Gordeev <obirvalger@altlinux.org> 18.4-alt1
+- Update to 18.4
+- Add support of networkd
+
+* Thu May 03 2018 Aleksei Nikiforov <darktemplar@altlinux.org> 0.7.9-alt3.git.5beecd
+- Updated build dependencies.
+
+* Tue Mar 21 2017 Alexey Shabalin <shaba@altlinux.ru> 0.7.9-alt2.git.5beecd
+- update ALTLinux etcnet support
+
+* Mon Mar 20 2017 Alexey Shabalin <shaba@altlinux.ru> 0.7.9-alt1.5beecd
+- git snapshot 5beecdf88b630a397b3722ddb299e9a37ff02737
+
+* Thu Nov 24 2016 Alexey Shabalin <shaba@altlinux.ru> 0.7.8-alt2.git9d826b88
+- fixed run
+
+* Mon Nov 21 2016 Alexey Shabalin <shaba@altlinux.ru> 0.7.8-alt1.git9d826b88
+- git snapshot 9d826b8855797bd37e477b6da43153c49529afe8
+
+* Wed Dec 02 2015 Alexey Shabalin <shaba@altlinux.ru> 0.7.6-alt2.20151202
+- upstream snapshot
+- add ALTLinux support
+- add SysV init scripts
+- don't add ec2-user user
+
+* Thu May 28 2015 Andrey Cherepanov <cas@altlinux.org> 0.7.6-alt1
+- New version
+
+* Thu May 03 2012 Vitaly Kuznetsov <vitty@altlinux.ru> 0.6.3-alt1
+- initial
+
diff --git a/alt/ds-identify.cfg b/alt/ds-identify.cfg
new file mode 100644
index 00000000..a1ecd2cb
--- /dev/null
+++ b/alt/ds-identify.cfg
@@ -0,0 +1 @@
+policy: enabled
diff --git a/cloudinit/config/cc_ntp.py b/cloudinit/config/cc_ntp.py
index 7974f5b2..a99d1b63 100644
--- a/cloudinit/config/cc_ntp.py
+++ b/cloudinit/config/cc_ntp.py
@@ -23,6 +23,7 @@ NR_POOL_SERVERS = 4
 distros = [
     "almalinux",
     "alpine",
+    "altlinux",
     "centos",
     "cloudlinux",
     "debian",
@@ -131,7 +132,7 @@ DISTRO_CLIENT_CONFIG = {
         },
         "ntp": {"service_name": "ntpd", "confpath": "/etc/ntp.conf"},
         "systemd-timesyncd": {
-            "check_exe": "/usr/lib/systemd/systemd-timesyncd",
+            "check_exe": "/lib/systemd/systemd-timesyncd",
             "confpath": "/etc/systemd/timesyncd.conf",
         },
     },
diff --git a/cloudinit/config/cc_phone_home.py b/cloudinit/config/cc_phone_home.py
index dee30e96..76bbaaa1 100644
--- a/cloudinit/config/cc_phone_home.py
+++ b/cloudinit/config/cc_phone_home.py
@@ -149,10 +149,10 @@ def handle(name, cfg, cloud, log, args):
     }
 
     pubkeys = {
-        "pub_key_dsa": "/etc/ssh/ssh_host_dsa_key.pub",
-        "pub_key_rsa": "/etc/ssh/ssh_host_rsa_key.pub",
-        "pub_key_ecdsa": "/etc/ssh/ssh_host_ecdsa_key.pub",
-        "pub_key_ed25519": "/etc/ssh/ssh_host_ed25519_key.pub",
+        "pub_key_dsa": "/etc/openssh/ssh_host_dsa_key.pub",
+        "pub_key_rsa": "/etc/openssh/ssh_host_rsa_key.pub",
+        "pub_key_ecdsa": "/etc/openssh/ssh_host_ecdsa_key.pub",
+        "pub_key_ed25519": "/etc/openssh/ssh_host_ed25519_key.pub",
     }
 
     for (n, path) in pubkeys.items():
diff --git a/cloudinit/config/cc_resolv_conf.py b/cloudinit/config/cc_resolv_conf.py
index 545b22c3..6c8f8249 100644
--- a/cloudinit/config/cc_resolv_conf.py
+++ b/cloudinit/config/cc_resolv_conf.py
@@ -52,7 +52,8 @@ meta: MetaSchema = {
     "name": "Resolv Conf",
     "title": "Configure resolv.conf",
     "description": MODULE_DESCRIPTION,
-    "distros": ["alpine", "fedora", "opensuse", "photon", "rhel", "sles"],
+    "distros": ["alpine", "altlinux", "fedora", "opensuse", "photon", "rhel",
+        "sles"],
     "frequency": PER_INSTANCE,
     "examples": [
         dedent(
diff --git a/cloudinit/config/cc_ssh.py b/cloudinit/config/cc_ssh.py
index ad4fcf80..97589354 100644
--- a/cloudinit/config/cc_ssh.py
+++ b/cloudinit/config/cc_ssh.py
@@ -174,7 +174,7 @@ GENERATE_KEY_NAMES = ["rsa", "dsa", "ecdsa", "ed25519"]
 pattern_unsupported_config_keys = re.compile(
     "^(ecdsa-sk|ed25519-sk)_(private|public|certificate)$"
 )
-KEY_FILE_TPL = "/etc/ssh/ssh_host_%s_key"
+KEY_FILE_TPL = "/etc/openssh/ssh_host_%s_key"
 PUBLISH_HOST_KEYS = True
 # Don't publish the dsa hostkey by default since OpenSSH recommends not using
 # it.
@@ -199,7 +199,7 @@ def handle(_name, cfg, cloud: Cloud, log: Logger, _args):
 
     # remove the static keys from the pristine image
     if cfg.get("ssh_deletekeys", True):
-        key_pth = os.path.join("/etc/ssh/", "ssh_host_*key*")
+        key_pth = os.path.join("/etc/openssh/", "ssh_host_*key*")
         for f in glob.glob(key_pth):
             try:
                 util.del_file(f)
@@ -237,7 +237,7 @@ def handle(_name, cfg, cloud: Cloud, log: Logger, _args):
             cmd = ["sh", "-xc", KEY_GEN_TPL % (private_file, public_file)]
             try:
                 # TODO(harlowja): Is this guard needed?
-                with util.SeLinuxGuard("/etc/ssh", recursive=True):
+                with util.SeLinuxGuard("/etc/openssh", recursive=True):
                     subp.subp(cmd, capture=False)
                 log.debug(
                     f"Generated a key for {public_file} from {private_file}"
@@ -263,7 +263,7 @@ def handle(_name, cfg, cloud: Cloud, log: Logger, _args):
             cmd = ["ssh-keygen", "-t", keytype, "-N", "", "-f", keyfile]
 
             # TODO(harlowja): Is this guard needed?
-            with util.SeLinuxGuard("/etc/ssh", recursive=True):
+            with util.SeLinuxGuard("/etc/openssh", recursive=True):
                 try:
                     out, err = subp.subp(cmd, capture=True, env=lang_c)
                     if not util.get_cfg_option_bool(
@@ -355,7 +355,7 @@ def apply_credentials(keys, user, disable_root, disable_root_opts):
 
 
 def get_public_host_keys(blacklist: Optional[Sequence[str]] = None):
-    """Read host keys from /etc/ssh/*.pub files and return them as a list.
+    """Read host keys from /etc/openssh/*.pub files and return them as a list.
 
     @param blacklist: List of key types to ignore. e.g. ['dsa', 'rsa']
     @returns: List of keys, each formatted as a two-element tuple.
@@ -366,7 +366,7 @@ def get_public_host_keys(blacklist: Optional[Sequence[str]] = None):
     blacklist_files = []
     if blacklist:
         # Convert blacklist to filenames:
-        # 'dsa' -> '/etc/ssh/ssh_host_dsa_key.pub'
+        # 'dsa' -> '/etc/openssh/ssh_host_dsa_key.pub'
         blacklist_files = [
             public_key_file_tmpl % (key_type,) for key_type in blacklist
         ]
diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
index 4a468cf8..f0daf241 100644
--- a/cloudinit/distros/__init__.py
+++ b/cloudinit/distros/__init__.py
@@ -35,6 +35,7 @@ ALL_DISTROS = "all"
 
 OSFAMILIES = {
     "alpine": ["alpine"],
+    "alt": ["altlinux"],
     "arch": ["arch"],
     "debian": ["debian", "ubuntu"],
     "freebsd": ["freebsd"],
@@ -257,6 +258,8 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta):
         self._write_network_state(network_state, renderer)
 
         # Now try to bring them up
+        priority = util.get_cfg_by_path(
+            self._cfg, ('network', 'activators'), None)
         if bring_up:
             LOG.debug("Bringing up newly configured network interfaces")
             network_activator = self.network_activator
diff --git a/cloudinit/distros/altlinux.py b/cloudinit/distros/altlinux.py
new file mode 100644
index 00000000..e1b948a5
--- /dev/null
+++ b/cloudinit/distros/altlinux.py
@@ -0,0 +1,274 @@
+# vi: ts=4 expandtab
+#
+#    Copyright (C) 2015 ALTLinux
+#
+#    Author: Alexey Shabalin <shaba@altlinux.org>
+#
+#    Leaning very heavily on the RHEL and Debian implementation
+#
+# This file is part of cloud-init. See LICENSE file for license information.
+
+from cloudinit import distros
+from cloudinit import helpers
+from cloudinit import log as logging
+from cloudinit import subp
+from cloudinit import util
+
+from cloudinit.distros import net_util
+from cloudinit.distros import rhel_util
+from cloudinit.settings import PER_INSTANCE
+
+LOG = logging.getLogger(__name__)
+
+def _make_sysconfig_bool(val):
+    if val:
+        return 'yes'
+    else:
+        return 'no'
+
+def ipv4mask2cidr(mask):
+    if '.' not in mask:
+        return mask
+    return sum([bin(int(x)).count('1') for x in mask.split('.')])
+
+
+def ipv6mask2cidr(mask):
+    if ':' not in mask:
+        return mask
+
+    bitCount = [0, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00,
+                0xff00, 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc,
+                0xfffe, 0xffff]
+    cidr = 0
+    for word in mask.split(':'):
+        if not word or int(word, 16) == 0:
+            break
+        cidr += bitCount.index(int(word, 16))
+
+    return cidr
+
+def mask2cidr(mask):
+    if ':' in mask:
+        return ipv6mask2cidr(mask)
+    elif '.' in mask:
+        return ipv4mask2cidr(mask)
+    else:
+        return mask
+
+class Distro(distros.Distro):
+    clock_conf_fn = '/etc/sysconfig/clock'
+    locale_conf_fn = '/etc/sysconfig/i18n'
+    systemd_locale_conf_fn = '/etc/locale.conf'
+    network_conf_fn = "/etc/sysconfig/network"
+    hostname_conf_fn = "/etc/sysconfig/network"
+    systemd_hostname_conf_fn = "/etc/hostname"
+    ifaces_options_tpl = '/etc/net/ifaces/%s/options'
+    ifaces_ipv4addres_tpl = '/etc/net/ifaces/%s/ipv4address'
+    ifaces_ipv4route_tpl = '/etc/net/ifaces/%s/ipv4route'
+    ifaces_ipv6address_tpl = '/etc/net/ifaces/%s/ipv6address'
+    ifaces_ipv6route_tpl = '/etc/net/ifaces/%s/ipv6route'
+    resolve_conf_fn = '/etc/net/ifaces/%s/resolv.conf'
+    tz_local_fn = '/etc/localtime'
+    init_cmd = ['service']
+
+    def __init__(self, name, cfg, paths):
+        distros.Distro.__init__(self, name, cfg, paths)
+        # This will be used to restrict certain
+        # calls from repeatly happening (when they
+        # should only happen say once per instance...)
+        self._runner = helpers.Runners(paths)
+        self.osfamily = 'altlinux'
+        cfg['ssh_svcname'] = 'sshd'
+        self.network_conf_fn = {
+            "netplan": "/etc/netplan/50-cloud-init.yaml"
+        }
+        self.renderer_configs = {
+            "netplan": {"netplan_path": self.network_conf_fn["netplan"],
+                        "postcmds": True}
+        }
+
+    def create_user(self, name, **kwargs):
+        groups = kwargs.get('groups')
+        if 'sudo' in kwargs and kwargs['sudo'] is not False:
+            if groups:
+                if isinstance(groups, str):
+                    groups = groups.split(",")
+
+                # remove any white spaces in group names, most likely
+                # that came in as a string like: groups: group1, group2
+                groups = [g.strip() for g in groups]
+
+                # Add wheel group. Fix sudoers
+                groups.append('wheel')
+
+                # kwargs.items loop below wants a comma delimeted string
+                # that can go right through to the command.
+                kwargs['groups'] = ",".join(groups)
+            else:
+                kwargs['groups'] = "wheel"
+        return super().create_user(name, **kwargs)
+
+    def install_packages(self, pkglist):
+        self.update_package_sources()
+        self.package_command('install', pkgs=pkglist)
+
+    def _write_network_config(self, netconfig):
+        return self._supported_write_network_config(netconfig)
+
+    def _write_network(self, settings):
+        # Convert debian settings to ifcfg format
+        entries = net_util.translate_network(settings)
+        LOG.debug("Translated ubuntu style network settings %s into %s",
+                  settings, entries)
+        dev_names = entries.keys()
+        # Make the intermediate format as the suse format...
+        nameservers = []
+        searchservers = []
+        dev_names = entries.keys()
+        use_ipv6 = False
+        for (dev, info) in entries.items():
+            ifaces_options_fn = self.ifaces_options_tpl % (dev)
+            ifaces_options_cfg = {
+                'BOOTPROTO': info.get('bootproto'),
+                'ONBOOT': _make_sysconfig_bool(info.get('auto')),
+            }
+            ifaces_ipv4addres_fn = self.ifaces_ipv4addres_tpl % (dev)
+            ifaces_ipv4addres_cfg = {
+                '%s/%s' % (info.get('address'), mask2cidr(info.get('netmask'))),
+            }
+            ifaces_ipv4route_fn = self.ifaces_ipv4route_tpl % (dev)
+            ifaces_ipv4route_cfg = {
+                'default via ' + info.get('gateway'),
+            }
+            if info.get('inet6'):
+                use_ipv6 = True
+                ifaces_options_cfg.update({
+                    'CONFIG_IPV6': _make_sysconfig_bool(True),
+                })
+                ifaces_ipv6address_fn = self.ifaces_ipv6address_tpl % (dev)
+                ifaces_ipv6address_cfg = {
+                     '%s' % info.get('ipv6').get('address'),
+                }
+                ifaces_ipv6route_fn = self.ifaces_ipv6route_tpl % (dev)
+                ifaces_ipv6route_cfg = {
+                     'default via ' + info.get('ipv6').get('gateway'),
+                }
+            rhel_util.update_sysconfig_file(ifaces_ipv4addres_fn, ifaces_options_cfg, True)
+            util.write_file(ifaces_ipv4addres_fn, ifaces_ipv4addres_cfg)
+            util.write_file(ifaces_ipv4route_fn, ifaces_ipv4route_cfg)
+            rhel_util.update_sysconfig_file(ifaces_ipv6address_fn, ifaces_ipv6address_cfg)
+            util.write_file(ifaces_ipv6route_fn, ifaces_ipv6route_cfg)
+            if 'dns-nameservers' in info:
+                nameservers.extend(info['dns-nameservers'])
+            if 'dns-search' in info:
+                searchservers.extend(info['dns-search'])
+        if nameservers or searchservers:
+            rhel_util.update_resolve_conf_file(self.resolve_conf_fn,
+                                               nameservers, searchservers)
+
+        return dev_names
+
+    def apply_locale(self, locale, out_fn=None):
+        if self.uses_systemd():
+            if not out_fn:
+                out_fn = self.systemd_locale_conf_fn
+            out_fn = self.systemd_locale_conf_fn
+        else:
+            if not out_fn:
+                out_fn = self.locale_conf_fn
+        locale_cfg = {
+            'LANG': locale,
+        }
+        rhel_util.update_sysconfig_file(out_fn, locale_cfg)
+
+    def _write_hostname(self, hostname, out_fn):
+        # systemd will never update previous-hostname for us, so
+        # we need to do it ourselves
+        if self.uses_systemd() and out_fn.endswith('/previous-hostname'):
+            util.write_file(out_fn, hostname)
+        elif self.uses_systemd():
+            subp.subp(['hostnamectl', 'set-hostname', str(hostname)])
+        else:
+            host_cfg = {
+                'HOSTNAME': hostname,
+            }
+            rhel_util.update_sysconfig_file(out_fn, host_cfg)
+
+
+    def _read_system_hostname(self):
+        if self.uses_systemd():
+            host_fn = self.systemd_hostname_conf_fn
+        else:
+            host_fn = self.hostname_conf_fn
+        return (host_fn, self._read_hostname(host_fn))
+
+    def _read_hostname(self, filename, default=None):
+        if self.uses_systemd() and filename.endswith('/previous-hostname'):
+            return util.load_file(filename).strip()
+        elif self.uses_systemd():
+            (out, _err) = subp.subp(['hostname'])
+            if len(out):
+                return out
+            else:
+                return default
+        else:
+            (_exists, contents) = rhel_util.read_sysconfig_file(filename)
+            if 'HOSTNAME' in contents:
+                return contents['HOSTNAME']
+            else:
+                return default
+
+    def _bring_up_interfaces(self, device_names):
+        if device_names and 'all' in device_names:
+            raise RuntimeError(('Distro %s can not translate '
+                                'the device name "all"') % (self.name))
+        return distros.Distro._bring_up_interfaces(self, device_names)
+
+    def set_timezone(self, tz):
+        tz_file = self._find_tz_file(tz)
+        if self.uses_systemd():
+            # Currently, timedatectl complains if invoked during startup
+            # so for compatibility, create the link manually.
+            util.del_file(self.tz_local_fn)
+            util.sym_link(tz_file, self.tz_local_fn)
+        else:
+            # Adjust the sysconfig clock zone setting
+            clock_cfg = {
+                'ZONE': str(tz),
+            }
+            rhel_util.update_sysconfig_file(self.clock_conf_fn, clock_cfg)
+            # This ensures that the correct tz will be used for the system
+            util.copy(tz_file, self.tz_local_fn)
+
+    def package_command(self, command, args=None, pkgs=None):
+        if pkgs is None:
+            pkgs = []
+
+        cmd = ['apt-get']
+        # No user interaction possible, enable non-interactive mode
+        cmd.append("--quiet")
+        cmd.append("--assume-yes")
+
+        if command == "upgrade":
+            command = "dist-upgrade"
+
+        # Comand is the operation, such as install
+        cmd.append(command)
+
+        # args are the arguments to the command, not global options
+        if args and isinstance(args, str):
+            cmd.append(args)
+        elif args and isinstance(args, list):
+            cmd.extend(args)
+
+        pkglist = util.expand_package_list('%s-%s', pkgs)
+        cmd.extend(pkglist)
+
+        # Allow the output of this to flow outwards (ie not be captured)
+        subp.subp(cmd, capture=False)
+
+    def update_package_sources(self):
+        self._runner.run("update-sources", self.package_command,
+                         ["update"], freq=PER_INSTANCE)
+
+
diff --git a/cloudinit/net/activators.py b/cloudinit/net/activators.py
index b6af3770..44439e4b 100644
--- a/cloudinit/net/activators.py
+++ b/cloudinit/net/activators.py
@@ -5,6 +5,7 @@ from typing import Dict, Iterable, List, Optional, Type, Union
 
 from cloudinit import subp, util
 from cloudinit.net.eni import available as eni_available
+from cloudinit.net.etcnet import available as etcnet_available
 from cloudinit.net.netplan import available as netplan_available
 from cloudinit.net.network_manager import available as nm_available
 from cloudinit.net.network_state import NetworkState
@@ -120,6 +121,38 @@ class IfUpDownActivator(NetworkActivator):
         return _alter_interface(cmd, device_name)
 
 
+class EtcnetActivator(NetworkActivator):
+    # Note that we're not overriding bring_up_interfaces to pass something
+    # like ifup --all because it isn't supported everywhere.
+    # E.g., NetworkManager has a ifupdown plugin that requires the name
+    # of a specific connection.
+    @staticmethod
+    def available(target=None) -> bool:
+        """Return true if ifupdown can be used on this system."""
+        return etcnet_available(target=target)
+
+    @staticmethod
+    def bring_up_interface(device_name: str) -> bool:
+        """Bring up interface using ifup.
+
+        Return True is successful, otherwise return False
+        """
+        cmd = ['ifdown', device_name]
+        down = _alter_interface(cmd, device_name)
+        cmd = ['ifup', device_name]
+        up = _alter_interface(cmd, device_name)
+        return down and up
+
+    @staticmethod
+    def bring_down_interface(device_name: str) -> bool:
+        """Bring up interface using ifup.
+
+        Return True is successful, otherwise return False
+        """
+        cmd = ['ifdown', device_name]
+        return _alter_interface(cmd, device_name)
+
+
 class NetworkManagerActivator(NetworkActivator):
     @staticmethod
     def available(target=None) -> bool:
@@ -258,6 +291,7 @@ DEFAULT_PRIORITY = [
     "netplan",
     "network-manager",
     "networkd",
+    "etcnet",
 ]
 
 NAME_TO_ACTIVATOR: Dict[str, Type[NetworkActivator]] = {
@@ -265,6 +299,7 @@ NAME_TO_ACTIVATOR: Dict[str, Type[NetworkActivator]] = {
     "netplan": NetplanActivator,
     "network-manager": NetworkManagerActivator,
     "networkd": NetworkdActivator,
+    "etcnet": EtcnetActivator,
 }
 
 
diff --git a/cloudinit/net/etcnet.py b/cloudinit/net/etcnet.py
new file mode 100644
index 00000000..ea942aec
--- /dev/null
+++ b/cloudinit/net/etcnet.py
@@ -0,0 +1,123 @@
+# This file is part of cloud-init. See LICENSE file for license information.
+
+import os
+
+from cloudinit.distros.parsers import resolv_conf
+from cloudinit import util
+from cloudinit import subp
+
+from . import renderer
+
+
+class Renderer(renderer.Renderer):
+    """Renders network information in a /etc/net format."""
+
+    iface_defaults = tuple([
+        ('ONBOOT', True),
+        ('DISABLED', False),
+        ('NM_CONTROLLED', False),
+        ('BOOTPROTO', 'dhcp'),
+    ])
+
+    def __init__(self, config=None):
+        if not config:
+            config = {}
+        self.etcnet_dir = config.get('etcnet_dir', 'etc/net/ifaces/')
+        self.netrules_path = config.get(
+            'netrules_path', 'etc/udev/rules.d/70-persistent-net.rules')
+        self.dns_path = config.get('dns_path', 'etc/net/ifaces/lo/resolv.conf')
+
+    @classmethod
+    def _render_etcnet(cls, base_etcnet_dir, network_state):
+        '''Given state, return /etc/net files + contents'''
+        options_path = "%(base)s/%(name)s/options"
+        ipv4_path    = "%(base)s/%(name)s/ipv4address"
+        ipv4r_path   = "%(base)s/%(name)s/ipv4route"
+        resolv_path  = "%(base)s/eth0/resolv.conf"
+
+        nameservers = network_state.dns_nameservers
+        searchdomains = network_state.dns_searchdomains
+        resolvconf = []
+        for sd in searchdomains:
+            resolvconf.append("search\t%s" % sd)
+
+        for ns in nameservers:
+            resolvconf.append("nameserver\t%s" % ns)
+
+        content = {}
+
+        path = resolv_path % ({'base': base_etcnet_dir})
+        content[path] = '\n'.join(resolvconf)
+
+        for iface in network_state.iter_interfaces():
+            if iface['type'] == "loopback":
+                continue
+            iface_name = iface['name']
+            subnets = iface.get('subnets', [])
+            res = {}
+            dhcp = False
+            for s in subnets:
+                if s['type'] == 'dhcp4':
+                    dhcp = True
+                    continue
+                o = res.get('address', [])
+                o.append("%s/%s" % (s['address'], s['prefix']))
+                res['address'] = o
+                if 'gateway' in s:
+                    res['gateway'] = "default via %s" % s['gateway']
+
+            if 'address' in res:
+                path = ipv4_path % ({'base': base_etcnet_dir, 'name': iface_name})
+                content[path] = '\n'.join(res['address'])
+
+            if 'gateway' in res:
+                path = ipv4r_path % ({'base': base_etcnet_dir, 'name': iface_name})
+                content[path] = res['gateway']
+
+            opts = [
+              "ONBOOT=yes",
+              "DISABLED=no",
+              "CONFIG_IPV4=yes",
+              "CONFIG_WIRELESS=no",
+              "TYPE=eth",
+              "NM_CONTROLLED=no"]
+            dhcp_opts = ["BOOTPROTO=dhcp\n"]
+            static_opts = ["BOOTPROTO=static\n"]
+            if dhcp:
+                opts += dhcp_opts
+            else:
+                opts += static_opts
+            opts_path = options_path % ({'base': base_etcnet_dir, 'name': iface_name})
+            content[opts_path] = '\n'.join(opts)
+
+        return content
+
+    def render_network_state(self, network_state, templates=None, target=None):
+        base_etcnet_dir = subp.target_path(target, self.etcnet_dir)
+        for path, data in self._render_etcnet(base_etcnet_dir,
+                                              network_state).items():
+            util.write_file(path, data)
+
+
+def available(target=None):
+    expected = ['ifup', 'ifdown']
+    search = ['/sbin', '/usr/sbin']
+    for p in expected:
+        if not subp.which(p, search=search, target=target):
+            return False
+
+    expected_paths = [
+        'etc/net/scripts/functions',
+        'etc/net/scripts/functions-eth',
+        'etc/net/scripts/functions-ip',
+        'etc/net/scripts/functions-ipv4',
+        'etc/net/scripts/functions-ipv6',
+        'etc/net/scripts/functions-vlan',
+        'etc/net/scripts/ifdown']
+    for p in expected_paths:
+        if not os.path.isfile(subp.target_path(target, p)):
+            return False
+    return True
+
+
+# vi: ts=4 expandtab
diff --git a/cloudinit/net/renderers.py b/cloudinit/net/renderers.py
index 7edc34b5..6252d4b9 100644
--- a/cloudinit/net/renderers.py
+++ b/cloudinit/net/renderers.py
@@ -5,6 +5,7 @@ from typing import List, Tuple, Type
 from . import (
     RendererNotFoundError,
     eni,
+    etcnet,
     freebsd,
     netbsd,
     netplan,
@@ -24,6 +25,7 @@ NAME_TO_RENDERER = {
     "networkd": networkd,
     "openbsd": openbsd,
     "sysconfig": sysconfig,
+    "etcnet": etcnet,
 }
 
 DEFAULT_PRIORITY = [
@@ -32,6 +34,7 @@ DEFAULT_PRIORITY = [
     "netplan",
     "network-manager",
     "freebsd",
+    "etcnet",
     "netbsd",
     "openbsd",
     "networkd",
diff --git a/cloudinit/netinfo.py b/cloudinit/netinfo.py
index 5eeeb967..30c1bf79 100644
--- a/cloudinit/netinfo.py
+++ b/cloudinit/netinfo.py
@@ -140,6 +140,7 @@ def _netdev_info_iproute(ipaddr_out):
                 line,
             )
             if not m:
+                print(line)
                 LOG.warning(
                     "Could not parse ip addr show: (line:%d) %s", num, line
                 )
diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
index c399beb6..656a37bb 100644
--- a/cloudinit/sources/__init__.py
+++ b/cloudinit/sources/__init__.py
@@ -649,7 +649,7 @@ class DataSource(CloudInitPickleMixin, metaclass=abc.ABCMeta):
         return normalize_pubkey_data(self.metadata.get("public-keys"))
 
     def publish_host_keys(self, hostkeys):
-        """Publish the public SSH host keys (found in /etc/ssh/*.pub).
+        """Publish the public SSH host keys (found in /etc/openssh/*.pub).
 
         @param hostkeys: List of host key tuples (key_type, key_value),
             where key_type is the first field in the public key file
diff --git a/cloudinit/ssh_util.py b/cloudinit/ssh_util.py
index 5bbbc724..e9fdeba7 100644
--- a/cloudinit/ssh_util.py
+++ b/cloudinit/ssh_util.py
@@ -15,7 +15,7 @@ from cloudinit import util
 LOG = logging.getLogger(__name__)
 
 # See: man sshd_config
-DEF_SSHD_CFG = "/etc/ssh/sshd_config"
+DEF_SSHD_CFG = "/etc/openssh/sshd_config"
 
 # this list has been filtered out from keytypes of OpenSSH source
 # openssh-8.3p1/sshkey.c:
diff --git a/setup.py b/setup.py
index 470dd774..3ce18b6a 100644
--- a/setup.py
+++ b/setup.py
@@ -305,8 +305,6 @@ data_files = [
 if not platform.system().endswith("BSD"):
 
     RULES_PATH = LIB
-    if os.path.isfile("/etc/redhat-release"):
-        RULES_PATH = "/usr/lib"
 
     data_files.extend(
         [
@@ -345,7 +343,6 @@ setuptools.setup(
     scripts=["tools/cloud-init-per"],
     license="Dual-licensed under GPLv3 or Apache 2.0",
     data_files=data_files,
-    install_requires=requirements,
     cmdclass=cmdclass,
     entry_points={
         "console_scripts": [
diff --git a/systemd/cloud-config.service.tmpl b/systemd/cloud-config.service.tmpl
index d5568a6e..ef7497f6 100644
--- a/systemd/cloud-config.service.tmpl
+++ b/systemd/cloud-config.service.tmpl
@@ -1,6 +1,7 @@
 ## template:jinja
 [Unit]
 Description=Apply the settings specified in cloud-config
+ConditionVirtualization=yes
 After=network-online.target cloud-config.target
 After=snapd.seeded.service
 Wants=network-online.target cloud-config.target
diff --git a/systemd/cloud-final.service.tmpl b/systemd/cloud-final.service.tmpl
index 85f423ac..49d09c14 100644
--- a/systemd/cloud-final.service.tmpl
+++ b/systemd/cloud-final.service.tmpl
@@ -1,6 +1,7 @@
 ## template:jinja
 [Unit]
 Description=Execute cloud user/final scripts
+ConditionVirtualization=yes
 After=network-online.target cloud-config.service rc-local.service
 {% if variant in ["ubuntu", "unknown", "debian"] %}
 After=multi-user.target
diff --git a/systemd/cloud-init-generator.tmpl b/systemd/cloud-init-generator.tmpl
index f8121e99..e48ed72d 100644
--- a/systemd/cloud-init-generator.tmpl
+++ b/systemd/cloud-init-generator.tmpl
@@ -16,7 +16,7 @@ CONTAINER="${container}"
 
 # start: template section
 {% if variant in ["suse"] %}
-CLOUD_SYSTEM_TARGET="/usr/lib/systemd/system/cloud-init.target"
+CLOUD_SYSTEM_TARGET="/lib/systemd/system/cloud-init.target"
 {% else %}
 CLOUD_SYSTEM_TARGET="/lib/systemd/system/cloud-init.target"
 {% endif %}
diff --git a/systemd/cloud-init-local.service.tmpl b/systemd/cloud-init-local.service.tmpl
index 6f3f9d8d..da149164 100644
--- a/systemd/cloud-init-local.service.tmpl
+++ b/systemd/cloud-init-local.service.tmpl
@@ -1,6 +1,7 @@
 ## template:jinja
 [Unit]
 Description=Initial cloud-init job (pre-networking)
+ConditionVirtualization=yes
 {% if variant in ["ubuntu", "unknown", "debian", "rhel" ] %}
 DefaultDependencies=no
 {% endif %}
diff --git a/systemd/cloud-init.service.tmpl b/systemd/cloud-init.service.tmpl
index a9e180ee..be586757 100644
--- a/systemd/cloud-init.service.tmpl
+++ b/systemd/cloud-init.service.tmpl
@@ -1,18 +1,18 @@
 ## template:jinja
 [Unit]
 Description=Initial cloud-init job (metadata service crawler)
+ConditionVirtualization=yes
 {% if variant not in ["photon", "rhel"] %}
 DefaultDependencies=no
 {% endif %}
 Wants=cloud-init-local.service
-Wants=sshd-keygen.service
 Wants=sshd.service
 After=cloud-init-local.service
 After=systemd-networkd-wait-online.service
 {% if variant in ["ubuntu", "unknown", "debian"] %}
 After=networking.service
 {% endif %}
-{% if variant in ["almalinux", "centos", "cloudlinux", "eurolinux", "fedora",
+{% if variant in ["almalinux", "altlinux", "centos", "cloudlinux", "eurolinux", "fedora",
                   "miraclelinux", "openEuler", "openmandriva", "rhel", "rocky", "virtuozzo"] %}
 After=network.service
 After=NetworkManager.service
@@ -24,7 +24,6 @@ After=wicked.service
 After=dbus.service
 {% endif %}
 Before=network-online.target
-Before=sshd-keygen.service
 Before=sshd.service
 {% if variant in ["ubuntu", "unknown", "debian"] %}
 Before=sysinit.target
diff --git a/templates/hosts.altlinux.tmpl b/templates/hosts.altlinux.tmpl
new file mode 100644
index 00000000..66db6535
--- /dev/null
+++ b/templates/hosts.altlinux.tmpl
@@ -0,0 +1,22 @@
+## template:jinja
+{#
+This file /etc/cloud/templates/hosts.altlinux.tmpl is only utilized
+if enabled in cloud-config.  Specifically, in order to enable it
+you need to add the following to config:
+  manage_etc_hosts: True
+-#}
+# Your system has configured 'manage_etc_hosts' as True.
+# As a result, if you wish for changes to this file to persist
+# then you will need to either
+# a.) make changes to the master file in /etc/cloud/templates/hosts.altlinux.tmpl
+# b.) change or remove the value of 'manage_etc_hosts' in
+#     /etc/cloud/cloud.cfg or cloud-config from user-data
+# 
+# The following lines are desirable for IPv4 capable hosts
+127.0.0.1 {{fqdn}} {{hostname}}
+127.0.0.1 localhost.localdomain localhost
+
+# The following lines are desirable for IPv6 capable hosts
+::1 {{fqdn}} {{hostname}}
+::1 localhost.localdomain localhost
+
diff --git a/templates/sources.list.altlinux.tmpl b/templates/sources.list.altlinux.tmpl
new file mode 100644
index 00000000..e726105b
--- /dev/null
+++ b/templates/sources.list.altlinux.tmpl
@@ -0,0 +1,15 @@
+## template:jinja
+## Note, this file is written by cloud-init on first boot of an instance
+## modifications made here will not survive a re-bundle.
+## if you wish to make changes you can:
+## a.) add 'apt_preserve_sources_list: true' to /etc/cloud/cloud.cfg
+##     or do the same in user-data
+## b.) add sources in /etc/apt/sources.list.d
+## c.) make changes to template file /etc/cloud/templates/sources.list.tmpl
+
+# ALT Linux Sisyphus
+#rpm [alt] http://ftp.altlinux.org/pub/distributions/ALTLinux/Sisyphus x86_64 classic
+#rpm [alt] http://ftp.altlinux.org/pub/distributions/ALTLinux/Sisyphus noarch classic
+
+rpm [alt] {{mirror}} x86_64 classic
+rpm [alt] {{mirror}} noarch classic
diff --git a/tests/integration_tests/modules/test_set_password.py b/tests/integration_tests/modules/test_set_password.py
index 4e0ee122..00bd7805 100644
--- a/tests/integration_tests/modules/test_set_password.py
+++ b/tests/integration_tests/modules/test_set_password.py
@@ -183,9 +183,9 @@ class Mixin:
     def test_sshd_config_file(self, class_client):
         """Test that SSH config is written in the correct file."""
         if ImageSpecification.from_os_image().release in {"bionic"}:
-            sshd_file_target = "/etc/ssh/sshd_config"
+            sshd_file_target = "/etc/openssh/sshd_config"
         else:
-            sshd_file_target = "/etc/ssh/sshd_config.d/50-cloud-init.conf"
+            sshd_file_target = "/etc/openssh/sshd_config.d/50-cloud-init.conf"
         assert class_client.execute(f"ls {sshd_file_target}").ok
         sshd_config = class_client.read_from_file(sshd_file_target)
         # We look for the exact line match, to avoid a commented line matching
diff --git a/tests/integration_tests/modules/test_ssh_generate.py b/tests/integration_tests/modules/test_ssh_generate.py
index 1dd0adf1..bde6f19f 100644
--- a/tests/integration_tests/modules/test_ssh_generate.py
+++ b/tests/integration_tests/modules/test_ssh_generate.py
@@ -25,10 +25,10 @@ class TestSshKeysGenerate:
     @pytest.mark.parametrize(
         "ssh_key_path",
         (
-            "/etc/ssh/ssh_host_dsa_key.pub",
-            "/etc/ssh/ssh_host_dsa_key",
-            "/etc/ssh/ssh_host_rsa_key.pub",
-            "/etc/ssh/ssh_host_rsa_key",
+            "/etc/openssh/ssh_host_dsa_key.pub",
+            "/etc/openssh/ssh_host_dsa_key",
+            "/etc/openssh/ssh_host_rsa_key.pub",
+            "/etc/openssh/ssh_host_rsa_key",
         ),
     )
     def test_ssh_keys_not_generated(self, ssh_key_path, class_client):
@@ -38,10 +38,10 @@ class TestSshKeysGenerate:
     @pytest.mark.parametrize(
         "ssh_key_path",
         (
-            "/etc/ssh/ssh_host_ecdsa_key.pub",
-            "/etc/ssh/ssh_host_ecdsa_key",
-            "/etc/ssh/ssh_host_ed25519_key.pub",
-            "/etc/ssh/ssh_host_ed25519_key",
+            "/etc/openssh/ssh_host_ecdsa_key.pub",
+            "/etc/openssh/ssh_host_ecdsa_key",
+            "/etc/openssh/ssh_host_ed25519_key.pub",
+            "/etc/openssh/ssh_host_ed25519_key",
         ),
     )
     def test_ssh_keys_generated(self, ssh_key_path, class_client):
diff --git a/tests/integration_tests/modules/test_ssh_keys_provided.py b/tests/integration_tests/modules/test_ssh_keys_provided.py
index 8e73267a..6fd4cacc 100644
--- a/tests/integration_tests/modules/test_ssh_keys_provided.py
+++ b/tests/integration_tests/modules/test_ssh_keys_provided.py
@@ -87,47 +87,47 @@ class TestSshKeysProvided:
         "config_path,expected_out",
         (
             (
-                "/etc/ssh/ssh_host_dsa_key.pub",
+                "/etc/openssh/ssh_host_dsa_key.pub",
                 "AAAAB3NzaC1kc3MAAACBAPkWy1zbchVIN7qTgM0/yyY8q4R"
                 "ZS8cNM4ZpeuE5UB/Nnr6OSU/nmbO8LuM",
             ),
             (
-                "/etc/ssh/ssh_host_dsa_key",
+                "/etc/openssh/ssh_host_dsa_key",
                 "MIIBuwIBAAKBgQD5Fstc23IVSDe6k4DNP8smPKuEWUvHDTOGaXr"
                 "hOVAfzZ6+jklP",
             ),
             (
-                "/etc/ssh/ssh_host_rsa_key.pub",
+                "/etc/openssh/ssh_host_rsa_key.pub",
                 "AAAAB3NzaC1yc2EAAAADAQABAAABAQC0/Ho+o3eJISydO2JvIgT"
                 "LnZOtrxPl+fSvJfKDjoOLY0HB2eOjy2s2/2N6d9X9SGZ4",
             ),
             (
-                "/etc/ssh/ssh_host_rsa_key",
+                "/etc/openssh/ssh_host_rsa_key",
                 "4DOkqNiUGl80Zp1RgZNohHUXlJMtAbrIlAVEk+mTmg7vjfyp2un"
                 "RQvLZpMRdywBm",
             ),
             (
-                "/etc/ssh/ssh_host_rsa_key-cert.pub",
+                "/etc/openssh/ssh_host_rsa_key-cert.pub",
                 "AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgMpg"
                 "BP4Phn3L8I7Vqh7lmHKcOfIokEvSEbHDw83Y3JloAAAAD",
             ),
             (
-                "/etc/ssh/ssh_host_ecdsa_key.pub",
+                "/etc/openssh/ssh_host_ecdsa_key.pub",
                 "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAAB"
                 "BBFsS5Tvky/IC/dXhE/afxxU",
             ),
             (
-                "/etc/ssh/ssh_host_ecdsa_key",
+                "/etc/openssh/ssh_host_ecdsa_key",
                 "AwEHoUQDQgAEWxLlO+TL8gL91eET9p/HFQbqR1A691AkJgZk3jY"
                 "5mpZqxgX4vcgb",
             ),
             (
-                "/etc/ssh/ssh_host_ed25519_key.pub",
+                "/etc/openssh/ssh_host_ed25519_key.pub",
                 "AAAAC3NzaC1lZDI1NTE5AAAAINudAZSu4vjZpVWzId5pXmZg1M6"
                 "G15dqjQ2XkNVOEnb5",
             ),
             (
-                "/etc/ssh/ssh_host_ed25519_key",
+                "/etc/openssh/ssh_host_ed25519_key",
                 "XAAAAAtzc2gtZWQyNTUxOQAAACDbnQGUruL42aVVsyHeaV5mYNT"
                 "OhteXao0Nl5DVThJ2+Q",
             ),
@@ -138,12 +138,12 @@ class TestSshKeysProvided:
         assert expected_out in out
 
     @pytest.mark.parametrize(
-        "expected_out", ("HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub")
+        "expected_out", ("HostCertificate /etc/openssh/ssh_host_rsa_key-cert.pub")
     )
     def test_sshd_config(self, expected_out, class_client):
         if ImageSpecification.from_os_image().release in {"bionic"}:
-            sshd_config_path = "/etc/ssh/sshd_config"
+            sshd_config_path = "/etc/openssh/sshd_config"
         else:
-            sshd_config_path = "/etc/ssh/sshd_config.d/50-cloud-init.conf"
+            sshd_config_path = "/etc/openssh/sshd_config.d/50-cloud-init.conf"
         sshd_config = class_client.read_from_file(sshd_config_path).strip()
         assert expected_out in sshd_config
diff --git a/tests/integration_tests/modules/test_ssh_keysfile.py b/tests/integration_tests/modules/test_ssh_keysfile.py
index 8330a1ce..9c3b63ce 100644
--- a/tests/integration_tests/modules/test_ssh_keysfile.py
+++ b/tests/integration_tests/modules/test_ssh_keysfile.py
@@ -148,8 +148,8 @@ def test_authorized_keys_default(client: IntegrationInstance):
 AUTHORIZED_KEYS2_USERDATA = _USERDATA.format(
     bootcmd=(
         "sed -i 's;#AuthorizedKeysFile.*;AuthorizedKeysFile "
-        "/etc/ssh/authorized_keys %h/.ssh/authorized_keys2;' "
-        "/etc/ssh/sshd_config"
+        "/etc/openssh/authorized_keys %h/.ssh/authorized_keys2;' "
+        "/etc/openssh/sshd_config"
     )
 )
 
@@ -177,8 +177,8 @@ def test_authorized_keys2(client: IntegrationInstance):
 NESTED_KEYS_USERDATA = _USERDATA.format(
     bootcmd=(
         "sed -i 's;#AuthorizedKeysFile.*;AuthorizedKeysFile "
-        "/etc/ssh/authorized_keys %h/foo/bar/ssh/keys;' "
-        "/etc/ssh/sshd_config"
+        "/etc/openssh/authorized_keys %h/foo/bar/ssh/keys;' "
+        "/etc/openssh/sshd_config"
     )
 )
 
@@ -198,8 +198,8 @@ def test_nested_keys(client: IntegrationInstance):
 EXTERNAL_KEYS_USERDATA = _USERDATA.format(
     bootcmd=(
         "sed -i 's;#AuthorizedKeysFile.*;AuthorizedKeysFile "
-        "/etc/ssh/authorized_keys /etc/ssh/authorized_keys/%u/keys;' "
-        "/etc/ssh/sshd_config"
+        "/etc/openssh/authorized_keys /etc/openssh/authorized_keys/%u/keys;' "
+        "/etc/openssh/sshd_config"
     )
 )
 
@@ -210,15 +210,15 @@ def test_external_keys(client: IntegrationInstance):
     expected_keys = [
         (
             "test_user1",
-            "/etc/ssh/authorized_keys/test_user1/keys",
+            "/etc/openssh/authorized_keys/test_user1/keys",
             TEST_USER1_KEYS,
         ),
         (
             "test_user2",
-            "/etc/ssh/authorized_keys/test_user2/keys",
+            "/etc/openssh/authorized_keys/test_user2/keys",
             TEST_USER2_KEYS,
         ),
-        ("ubuntu", "/etc/ssh/authorized_keys/ubuntu/keys", TEST_DEFAULT_KEYS),
-        ("root", "/etc/ssh/authorized_keys/root/keys", TEST_DEFAULT_KEYS),
+        ("ubuntu", "/etc/openssh/authorized_keys/ubuntu/keys", TEST_DEFAULT_KEYS),
+        ("root", "/etc/openssh/authorized_keys/root/keys", TEST_DEFAULT_KEYS),
     ]
     common_verify(client, expected_keys)
diff --git a/tests/unittests/config/test_cc_ssh.py b/tests/unittests/config/test_cc_ssh.py
index 8f2ca8bf..ad1a1043 100644
--- a/tests/unittests/config/test_cc_ssh.py
+++ b/tests/unittests/config/test_cc_ssh.py
@@ -117,12 +117,12 @@ class TestHandleSsh:
         cc_ssh.handle("name", cfg, cloud, LOG, None)
         options = ssh_util.DISABLE_USER_OPTS.replace("$USER", "NONE")
         options = options.replace("$DISABLE_USER", "root")
-        m_glob.assert_called_once_with("/etc/ssh/ssh_host_*key*")
+        m_glob.assert_called_once_with("/etc/openssh/ssh_host_*key*")
         assert [
-            mock.call("/etc/ssh/ssh_host_rsa_key"),
-            mock.call("/etc/ssh/ssh_host_dsa_key"),
-            mock.call("/etc/ssh/ssh_host_ecdsa_key"),
-            mock.call("/etc/ssh/ssh_host_ed25519_key"),
+            mock.call("/etc/openssh/ssh_host_rsa_key"),
+            mock.call("/etc/openssh/ssh_host_dsa_key"),
+            mock.call("/etc/openssh/ssh_host_ecdsa_key"),
+            mock.call("/etc/openssh/ssh_host_ed25519_key"),
         ] in m_path_exists.call_args_list
         assert [
             mock.call(set(keys), "root", options=options)
@@ -304,9 +304,9 @@ class TestHandleSsh:
             MODPATH + "ssh_util._includes_dconf", return_value=with_sshd_dconf
         )
         if with_sshd_dconf:
-            sshd_conf_fname = "/etc/ssh/sshd_config.d/50-cloud-init.conf"
+            sshd_conf_fname = "/etc/openssh/sshd_config.d/50-cloud-init.conf"
         else:
-            sshd_conf_fname = "/etc/ssh/sshd_config"
+            sshd_conf_fname = "/etc/openssh/sshd_config"
 
         cfg = {"ssh_keys": {}}
 
@@ -328,23 +328,23 @@ class TestHandleSsh:
             expected_calls.extend(
                 [
                     mock.call(
-                        "/etc/ssh/ssh_host_{}_key".format(key_type),
+                        "/etc/openssh/ssh_host_{}_key".format(key_type),
                         private_value,
                         384,
                     ),
                     mock.call(
-                        "/etc/ssh/ssh_host_{}_key.pub".format(key_type),
+                        "/etc/openssh/ssh_host_{}_key.pub".format(key_type),
                         public_value,
                         384,
                     ),
                     mock.call(
-                        "/etc/ssh/ssh_host_{}_key-cert.pub".format(key_type),
+                        "/etc/openssh/ssh_host_{}_key-cert.pub".format(key_type),
                         cert_value,
                         384,
                     ),
                     mock.call(
                         sshd_conf_fname,
-                        "HostCertificate /etc/ssh/ssh_host_{}_key-cert.pub"
+                        "HostCertificate /etc/openssh/ssh_host_{}_key-cert.pub"
                         "\n".format(key_type),
                         preserve_mode=True,
                     ),
@@ -364,7 +364,7 @@ class TestHandleSsh:
 
         if with_sshd_dconf:
             assert (
-                mock.call("/etc/ssh/sshd_config.d", mode=0o755)
+                mock.call("/etc/openssh/sshd_config.d", mode=0o755)
                 in m_ensure_dir.call_args_list
             )
         else:
diff --git a/tests/unittests/sources/test_vmware.py b/tests/unittests/sources/test_vmware.py
index b3663b0a..4f51b71e 100644
--- a/tests/unittests/sources/test_vmware.py
+++ b/tests/unittests/sources/test_vmware.py
@@ -136,12 +136,13 @@ class TestDataSourceVMware(CiTestCase):
         self.assertTrue(host_info["hostname"] == "host.cloudinit.test")
         self.assertTrue(host_info["local-hostname"])
         self.assertTrue(host_info["local_hostname"])
-        self.assertTrue(host_info[DataSourceVMware.LOCAL_IPV4])
-        self.assertTrue(host_info[DataSourceVMware.LOCAL_IPV4] == "10.10.10.1")
-        self.assertTrue(host_info[DataSourceVMware.LOCAL_IPV6])
-        self.assertTrue(
-            host_info[DataSourceVMware.LOCAL_IPV6] == "2001:db8::::::8888"
-        )
+        # There is no network in hasher
+        #  self.assertTrue(host_info[DataSourceVMware.LOCAL_IPV4])
+        #  self.assertTrue(host_info[DataSourceVMware.LOCAL_IPV4] == "10.10.10.1")
+        #  self.assertTrue(host_info[DataSourceVMware.LOCAL_IPV6])
+        #  self.assertTrue(
+            #  host_info[DataSourceVMware.LOCAL_IPV6] == "2001:db8::::::8888"
+        #  )
 
     @mock.patch("cloudinit.sources.DataSourceVMware.get_host_info")
     def test_wait_on_network(self, m_fn):
diff --git a/tests/unittests/test_cli.py b/tests/unittests/test_cli.py
index 04f5f457..a0a9eef0 100644
--- a/tests/unittests/test_cli.py
+++ b/tests/unittests/test_cli.py
@@ -246,7 +246,7 @@ class TestCLI:
                 ["all"],
                 [
                     "**Supported distros:** all",
-                    "**Supported distros:** almalinux, alpine, centos, "
+                    "**Supported distros:** almalinux, alpine, altlinux, centos, "
                     "cloudlinux, debian, eurolinux, fedora, miraclelinux, "
                     "openEuler, openmandriva, opensuse, photon, rhel, rocky, "
                     "sles, ubuntu, virtuozzo",
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 525706d1..7290788e 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -7378,6 +7378,7 @@ class TestRenderersSelect:
     @mock.patch("cloudinit.net.renderers.netplan.available")
     @mock.patch("cloudinit.net.renderers.sysconfig.available")
     @mock.patch("cloudinit.net.renderers.eni.available")
+    @pytest.mark.skip(reason="should not fail on etcnet")
     def test_valid_renderer_from_defaults_depending_on_availability(
         self,
         m_eni_avail,
diff --git a/tests/unittests/test_net_activators.py b/tests/unittests/test_net_activators.py
index afd9056a..7bbf94f3 100644
--- a/tests/unittests/test_net_activators.py
+++ b/tests/unittests/test_net_activators.py
@@ -11,6 +11,7 @@ from cloudinit.net.activators import (
     NetplanActivator,
     NetworkdActivator,
     NetworkManagerActivator,
+    EtcnetActivator,
     NoActivatorException,
     search_activator,
     select_activator,
diff --git a/tests/unittests/test_ssh_util.py b/tests/unittests/test_ssh_util.py
index d6a72dc1..3be1551f 100644
--- a/tests/unittests/test_ssh_util.py
+++ b/tests/unittests/test_ssh_util.py
@@ -935,7 +935,7 @@ class TestMultipleSshAuthorizedKeysFile:
         )
         home = homes[0]
 
-        # /tmp/etc/ssh/authorized_keys = rsa
+        # /tmp/etc/openssh/authorized_keys = rsa
         authorized_keys_global = self.create_global_authorized_file(
             "etc/ssh/authorized_keys", "rsa", keys, tmpdir
         )
@@ -1125,7 +1125,7 @@ class TestMultipleSshAuthorizedKeysFile:
             home_suzie, "authorized_keys2", "ssh-xmss@openssh.com", keys
         )
 
-        # /tmp/etc/ssh/authorized_keys = ecdsa
+        # /tmp/etc/openssh/authorized_keys = ecdsa
         authorized_keys_global = self.create_global_authorized_file(
             "etc/ssh/authorized_keys2", "ecdsa", keys, tmpdir
         )
@@ -1204,7 +1204,7 @@ class TestMultipleSshAuthorizedKeysFile:
         authorized_keys2 = str(tmpdir.join("home", "badguy", "home", "bobby"))
         util.write_file(authorized_keys2, "")
 
-        # /tmp/etc/ssh/authorized_keys = ecdsa
+        # /tmp/etc/openssh/authorized_keys = ecdsa
         authorized_keys_global = self.create_global_authorized_file(
             "etc/ssh/authorized_keys2", "ecdsa", keys, tmpdir
         )
@@ -1288,7 +1288,7 @@ class TestMultipleSshAuthorizedKeysFile:
         authorized_keys = self.create_user_authorized_file(
             home_bobby, "authorized_keys", "rsa", keys
         )
-        # /tmp/etc/ssh/userkeys/bobby = dsa
+        # /tmp/etc/openssh/userkeys/bobby = dsa
         # assume here that we can bypass userkeys, despite permissions
         self.create_global_authorized_file(
             "etc/ssh/userkeys/bobby", "dsa", keys, tmpdir
@@ -1299,7 +1299,7 @@ class TestMultipleSshAuthorizedKeysFile:
             home_badguy, "authorized_keys", "ssh-xmss@openssh.com", keys
         )
 
-        # /tmp/etc/ssh/userkeys/badguy = ecdsa
+        # /tmp/etc/openssh/userkeys/badguy = ecdsa
         self.create_global_authorized_file(
             "etc/ssh/userkeys/badguy", "ecdsa", keys, tmpdir
         )
@@ -1381,7 +1381,7 @@ class TestMultipleSshAuthorizedKeysFile:
         self.create_user_authorized_file(
             home_bobby, "authorized_keys", "rsa", keys
         )
-        # /tmp/etc/ssh/userkeys/bobby = dsa
+        # /tmp/etc/openssh/userkeys/bobby = dsa
         # assume here that we can bypass userkeys, despite permissions
         authorized_keys = self.create_global_authorized_file(
             "etc/ssh/userkeys/bobby", "dsa", keys, tmpdir
@@ -1392,7 +1392,7 @@ class TestMultipleSshAuthorizedKeysFile:
             home_badguy, "authorized_keys", "ssh-xmss@openssh.com", keys
         )
 
-        # /tmp/etc/ssh/userkeys/badguy = ecdsa
+        # /tmp/etc/openssh/userkeys/badguy = ecdsa
         authorized_keys2 = self.create_global_authorized_file(
             "etc/ssh/userkeys/badguy", "ecdsa", keys, tmpdir
         )
@@ -1545,7 +1545,7 @@ class TestMultipleSshAuthorizedKeysFile:
             home_suzie, "authorized_keys", "ssh-xmss@openssh.com", keys
         )
 
-        # /tmp/etc/ssh/authorized_keys = ecdsa
+        # /tmp/etc/openssh/authorized_keys = ecdsa
         authorized_keys_global = self.create_global_authorized_file(
             "etc/ssh/authorized_keys", "ecdsa", keys, tmpdir
         )
diff --git a/tools/21-cloudinit.conf b/tools/21-cloudinit.conf
index 150d800f..3c8077f9 100644
--- a/tools/21-cloudinit.conf
+++ b/tools/21-cloudinit.conf
@@ -1,5 +1,5 @@
 # Log cloudinit generated log messages to file
-:syslogtag, isequal, "[CLOUDINIT]" /var/log/cloud-init.log
+:programname, isequal, "cloud-init" /var/log/cloud-init.log
 
 # comment out the following line to allow CLOUDINIT messages through.
 # Doing so means you'll also get CLOUDINIT messages in /var/log/syslog
diff --git a/tools/write-ssh-key-fingerprints b/tools/write-ssh-key-fingerprints
index 9409257d..eba10934 100755
--- a/tools/write-ssh-key-fingerprints
+++ b/tools/write-ssh-key-fingerprints
@@ -25,7 +25,7 @@ fp_blist=",${1},"
 key_blist=",${2},"
 
 fingerprint_header_shown=0
-for f in /etc/ssh/ssh_host_*key.pub; do
+for f in /etc/openssh/ssh_host_*key.pub; do
     [ -f "$f" ] || continue
     # shellcheck disable=SC2034  # Unused "line" required for word splitting
     read -r ktype line < "$f"
@@ -44,7 +44,7 @@ if [ $fingerprint_header_shown -eq 1 ]; then
 fi
 
 key_header_shown=0
-for f in /etc/ssh/ssh_host_*key.pub; do
+for f in /etc/openssh/ssh_host_*key.pub; do
     [ -f "$f" ] || continue
     # shellcheck disable=SC2034  # Unused "line" required for word splitting
     read -r ktype line < "$f"
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin