\documentclass[aspectratio=169]{beamer}
\usepackage{lmodern}
\usepackage[english]{babel}
\usepackage[utf8x]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{textpos}
\usepackage{tikz,calc}
\usepackage{graphicx}
\usepackage{wrapfig}
\usepackage{color}
\usepackage{mathtools}
\usepackage{hyperref}
\usepackage{epstopdf}
\usepackage{amsmath}
\usepackage{minted}
\hypersetup{
	colorlinks,
	citecolor=black,
	filecolor=black,
	linkcolor=black,
	urlcolor=black
}
\usepackage{pdflscape}

\input{theme/theme.tex}

\title{Update from Turris OS 3.x to 5.x or newer is a big leap}
\author{Karel Kočí}
\date{29.11.2021}

\begin{document}

\frame{\titlepage}

\begin{frame}{Turris OS 3.x migration for users}
	Documentation: https://docs.turris.cz/geek/tos3-migration/

	\vspace{0.3cm}

	\includegraphics[width=10cm]{migration.png}\\

	\vspace{0.3cm}
	Automatic migration is going to be in waves. The first wave for:
	\begin{itemize}
		\item Omnia with serial numbers ending with zero in decimal format
		\item Turris 1.x routers on BTRFS
	\end{itemize}
\end{frame}

\begin{frame}{Important changes}
	\begin{itemize}
		\item API tokens are no longer available and mobile application no longer works.
		\item Server side backups were dropped. Replacement is not yet provided.
		\item Majordomo is no longer available as well as its package list.
		\item Automation package list with Domoticz and Home-Assistant is no longer provided.
		\item Print server CUPS was dropped. Print server package list now provides only p910nd protocol.
		\item Webcam, sound card, Squid proxy and netutils packages list were dropped.
		\item Thermometer package was dropped. Use collectd or sensors as a replacement
		\item Network switch configuration now uses DSA.
		\item Attack statistics are presented on the Sentinel View instead of project.turris.cz.
	\end{itemize}
\end{frame}

\begin{frame}{Why we need migration?}
	Huge changes between years 2016 and 2018.

	Turris OS 3.x: OpenWrt 15.05 (latest merge January 2016)

	Turris OS 4.0: OpenWrt 18.06

	\begin{itemize}
		\item Huge changes in configuration
		\item Change of LibC on Turris 1.x
		\item Changes in repositories (different layout)
		\item Changes in packages
		\item Removal of some functionalities
	\end{itemize}
\end{frame}

\begin{frame}{Configuration}
	\begin{itemize}
		\item Migration from swconfig to DSA pro for switch configuration
		\item SFP support in kernel (missing switch in runtime)
		\item Change of Wi-Fi cards identifier
		\item Move away from UCI configuration to native for sshd
		\item Update LXC from 1.0 to 3.0 (4.0)
		\item Switch from uCollect to Sentinel
	\end{itemize}

	Load of changes in secondary software..
\end{frame}

\begin{frame}[fragile]{Configuration migration}
	Package \textit{tos3to4} with migration scripts in Turris OS 4.0+ due to
	future extension.

	\begin{minted}[frame=lines]{bash}
config_load wireless
wifi_handle() {
  local radio="$1"
  config_get path "$radio" path
  mac="$(cat /sys/devices/platform/"$path"/ieee80211/phy*/macaddress)"
  uci set "wireless.$radio.macaddr=$mac"
  uci delete "wireless.$radio.path"
}
config_foreach wifi_handle wifi-device
uci commit wireless
	\end{minted}
\end{frame}

\begin{frame}[fragile]{Offline upgrade}
	Load the new system, migrate configuration and perform reboot...

	\vspace{0.2cm}

	Advantages:
	\begin{itemize}
		\item Simple
		\item Atomic thanks to BTRFS
	\end{itemize}

	\vspace{0.2cm}

	Why not possible:
	\begin{minted}[frame=lines]{lua}
[ -n "$IPKG_INSTROOT" ] || {
  package_migration
}
\end{minted}
	⇒ Upgrade in runtime
\end{frame}

\begin{frame}[fragile]{Some theory... Updater}
	Lua directives/configuration from online source (updater lists).

	\begin{minted}[frame=lines]{lua}
Repository('turris/core', '../packages/core')
Install('updater-ng', 'updater-supervisor', { critical = true })
Package('updater-ng', { replan = 'finished' })
\end{minted}
\end{frame}

\begin{frame}[fragile]{Some theory... Package extras}
	\begin{minted}[frame=lines]{lua}
Package('updater-ng', { replan = 'finished' })
\end{minted}

	\begin{itemize}
		\item \textbf{virtual}: there is no binary package for this name
		\item \textbf{deps}: additional package dependencies
		\item \textbf{reboot}: performs \textit{delayed} reboot or unconditional
			one for \textit{finished}
		\item \textbf{replan}: \textit{finished} causes reexecution of updater
			immediately after exit or immediately after installation of that
			package for \textit{immediate}
		\item \textbf{abi\_change} and \textbf{abichange\_deep} causes reinstall
			of all dependent packages
		\item \textbf{order\_before} and \textbf{order\_after} never worked
	\end{itemize}
\end{frame}

\begin{frame}[fragile]{First iteration: "this won't work"}
	Package \textit{tos3to4} in Turris OS 3.x:
	\begin{minted}[frame=lines]{lua}
Script("https://repo.turris.cz/hbs/omnia/lists/migrate3x.lua", {
	security = "Local", ca = system_cas, crl = no_crl,
	pubkey = { "file:///etc/updater/keys/release.pub" }
})
\end{minted}

	\textit{migrate3x.lua} on server:
	\begin{minted}[frame=lines]{lua}
Repository("turris", "https://repo.turris.cz/hbs/"..board.."/packages", {
	priority = 60,
	subdirs = { "base", "core", "packages", "turrispackages"}
})
\end{minted}
\end{frame}

\begin{frame}[fragile]{Second iteration: "update updater"}
	\begin{minted}[frame=lines]{lua}
if version_match(self_version, "<64.0") then
  Repository("turris", "https://repo.turris.cz/hbs/"..board.."/packages", {
    priority = 60,
    subdirs = { "base", "core", "packages", "turrispackages"}
  })
  Install('updater-ng', { critical = true })
  Package('updater-ng', {
    replan = 'immediate',
    deps = { 'libgcc', 'busybox', 'tos3to4-early' }
  })
end
Package("libc", { abi_change_deep = true })
\end{minted}
\end{frame}

\begin{frame}[fragile]{Updater: welcome in hell}
	Check for collisions...
	\begin{minted}[frame=lines]{md}
DIE: [string "transaction"]:334: [string "transaction"]:158: Collisions:
• /usr/sbin/cron: vixie-cron (existing-file), cronie (new-file)
\end{minted}

	\vspace{0.4cm}

	Ok, then:
	\begin{minted}[frame=lines]{lua}
Package("cronie", { virtual = true })
\end{minted}
	\begin{minted}[frame=lines]{md}
ERROR: inconsistent: Candidate exists for virtual package gettext-tools
\end{minted}
\end{frame}

\begin{frame}[fragile]{Theory follow up... order of changes}
	\begin{minted}[frame=lines]{lua}
Install('updater-ng', { critical = true, priority = 50 })
\end{minted}

	Ordering rules (higher means earlier):
	\begin{enumerate}
		\item Dependent for any subsequent package
		\item Package conflicting with some of the subsequent packages
		\item Critically requested packages
		\item Priority (higher means earlier)
		\item Package installation (package removal are performed at the end)
	\end{enumerate}
	BTW, this applies just for newer versions of updater.
\end{frame}

\begin{frame}[fragile]{Third iteration "early later"}
	\begin{minted}[frame=lines]{lua}
  Package('updater-ng', {
    replan = 'immediate',
    deps = { 'libgcc', 'busybox' }
  })
else
  if version_match(installed["tos3to4"].version, "<2.0.0") then
    Install('tos3to4-early', { critical = true, priority = 100 })
    Package('tos3to4-early', { replan = 'immediate' })
  end
end
\end{minted}
\end{frame}

\begin{frame}[fragile]{Fourth iteration "ufff it takes sooo long"}
	OpenWrt uses procd as the init system which communicates over ubus.

	New version of ubus does not communicate with the old one. The timeout is
	two minutes.

	\begin{minted}[frame=lines]{bash}
[ -n "${IPKG_INSTROOT}" ] || {
  ubus call system info 2>/dev/null >&2 || killall ubusd
}
\end{minted}

	\begin{minted}[frame=lines]{lua}
if version_match(installed["ubus"].version, "<2018") then
  Package("ubus", { replan = 'immediate' })
end
\end{minted}
\end{frame}

\begin{frame}[fragile]{Fifth iteration "missing packages"}
	\begin{minted}[frame=lines]{lua}
Install("cups")
\end{minted}

	\begin{minted}[frame=lines]{md}
ERROR: inconsistent: Requested package cups that is not available.
\end{minted}

	\vspace{0.2cm}

	With new feature added to updater:
	\begin{minted}[frame=lines]{lua}
Mode("optional_installs")
\end{minted}
\end{frame}

\begin{frame}[fragile]{Sixth iteration "localrepo oh localrepo"}
	Localrepo stores packages that were not installed from repository.

	Those package won't be updated and won't most likely work after upgrade.

	\begin{minted}[frame=lines]{bash}
SOURCE="/usr/share/updater/localrepo"
COLLIDED="/usr/share/updater/collided$SOURCE"
mv "$SOURCE" "$COLLIDED"
\end{minted}

	\begin{minted}[frame=lines]{lua}
  Package('updater-ng', {
    replan = 'immediate',
    deps = { 'libgcc', 'busybox', 'tos3to4-earliest' }
  })
else
\end{minted}
\end{frame}

\begin{frame}[fragile]{Seventh iteration "brick"}
	The system is configured for DSA but there is no DSA in running kernel.

	\begin{minted}[frame=lines]{lua}
Package("tos3to4", { reboot = "finished" })
\end{minted}
\end{frame}

\begin{frame}[fragile]{Eighth iteration... well no, that would be too long}
	The complete update consists of:
	\begin{enumerate}
		\item Installation of \textit{tos3to4} in Turris OS 3.x
		\item Upgrade of updater to the newest version and installation of
			\textit{tos3to4-earliest}
		\item Upgrade of ubus (two minutes of waiting)
		\item Installation of \textit{tos3to4-early} and updater settings
			migration
		\item Upgrade of the rest of the system including removal of old
			packages
		\item The last replan
		\item Reboot
		\item Removal of \textit{tos3to4} a other migration packages
	\end{enumerate}
	Plus few other replans in the meantime and special packages (\textit{fix-*}).
\end{frame}

\begin{frame}
	\Large Thank you for attention. Questions?\\

	\vspace{0.5cm}
	\small karel.koci@nic.cz
\end{frame}

\end{document}
