Administration Guide
The Photon OS Administration Guide describes the fundamentals of administering Photon OS.
The Administration Guide covers the basics of managing packages, controlling services with systemd, setting up networking, initializing Photon OS with cloud-init, running Docker containers, and working with other technologies, such as Kubernetes.
Product version: 3.0
This documentation applies to all 3.0.x releases.
Intended Audiences
This information is intended for Photon OS administrators who install and set up Photon OS.
1 - Photon OS Packages
The design of Photon OS simplifies life-cycle management and improves the security of packages. Photon reduces the burden and complexity of managing clusters of Linux machines by providing curated package repositories and by securing packages with GPG signatures.
Photon OS is available in a variety of pre-built packages in binary formats.
1.1 - Examining the Packages in the SPECS Directory on Github
The SPECS directory of the GitHub website for Photon OS contains all the packages that can appear in Photon OS repositories. The following is the path to the SPECS directory :
https://github.com/vmware/photon/tree/master/SPECS
To see the version of a package, in the SPECS directory, click the name of the subdirectory of the package that you want to examine, and then click the .spec
filename in the subdirectory.
For example, the version of OpenJDK, which contains the openjre package that installs the Java class library and the javac Java compiler appears as follows:
%define _use_internal_dependency_generator 0
Summary: OpenJDK
Name: openjdk
Version: 1.8.0.72
Release: 1%{?dist}
License: GNU GPL
URL: https://openjdk.java.net
Group: Development/Tools
Vendor: VMware, Inc.
Distribution: Photon
AutoReqProv: no
Source0: http://anduin.linuxfromscratch.org/files/BLFS/OpenJDK-%{version}/OpenJDK-%{version}-x86_64-bin.tar.xz
%define sha1 OpenJDK=0c705d7b13f4e22611d2da654209f469a6297f26
%description
The OpenJDK package installs java class library and javac java compiler.
%package -n openjre
Summary: Jave runtime environment
AutoReqProv: no
%description -n openjre
It contains the libraries files for Java runtime environment
#%global __requires_exclude ^libgif.*$
#%filter_from_requires ^libgif.*$...
1.2 - Looking at the Differences Between the Minimal and the Full Version
The minimal version of Photon OS contains around 50 packages. As it is installed, the number of packages increases to nearly 100 to fulfill dependencies. The full version of Photon OS adds several hundred packages to those in the minimal version to deliver a more fully featured operating system.
You can view a list of the packages that appear in the minimal version by examining the following file:
https://github.com/vmware/photon/blob/master/common/data/packages_minimal.json
You can view a list of the packages that appear in the full version by examining the following file:
https://github.com/vmware/photon/blob/master/common/data/packages_full.json
If the minimal or the full version of Photon OS does not contain a package that you want, you can install it with tdnf, which appears in both the minimal and full versions of Photon OS by default. In the full version of Photon OS, you can also install packages by using yum.
One notable difference between the two versions of Photon OS pertains to OpenJDK, the package that contains not only the Java runtime environment (openjre
) but also the Java compiler (javac
). The OpenJDK package appears in the full but not the minimal version of Photon OS.
To add support for Java programs to the minimal version of Photon OS, install the Java packages and their dependencies by using the following command:
tdnf install openjdk
Installing:
openjre x86_64 1.8.0.92-1.ph1 95.09 M
openjdk x86_64 1.8.0.92-1.ph1 37.63 M
NOTE: openjdk
and openjre
are available as openjdk8 and openjre8 in Photon OS 3.0
For more information about tdnf
, see Tiny DNF for Package Management
1.3 - The Root Account and the 'sudo' and 'su' Commands
The Photon OS Administration Guide assumes that you are logged in to Photon OS with the root account and running commands as root.
On the minimal version, you must install sudo
with tdnf if you want to use it. As an alternative to installing sudo
, to run commands that require root privileges you can switch users as needed with the su
command.
1.4 - Examining Signed Packages
Photon OS signs its packages and repositories with GPG signatures to enhance security. The GPG signature uses keyed-hash authentication method codes, typically the SHA1 algorithm and an RSA Data Security, Inc. MD5 Message Digest Algorithm, to simultaneously verify the integrity of a package. A keyed-hash message authentication code combines a cryptographic hash function with a secret cryptographic key.
In Photon OS, GPG signature verification automatically takes place when you install or update a package with the default package manager, tdnf
. The default setting in the tdnf configuration file for checking the GPG is set to 1
for true:
cat /etc/tdnf/tdnf.conf
[main]
gpgcheck=1
installonly_limit=3
clean_requirements_on_remove=true
repodir=/etc/yum.repos.d
cachedir=/var/cache/tdnf
On Photon OS, you can view the key with which VMware signs packages by running the following command:
rpm -qa gpg-pubkey*
The command returns the GPG public key:
gpg-pubkey-66fd4949-4803fe57
Once you have the name of the key, you can view information about the key with the rpm -qi
command, as the following abridged output demonstrates:
rpm -qi gpg-pubkey-66fd4949-4803fe57
Name : gpg-pubkey
Version : 66fd4949
Release : 4803fe57
Architecture: (none)
Install Date: Thu Jun 16 11:51:39 2016
Group : Public Keys
Size : 0
License : pubkey
Signature : (none)
Source RPM : (none)
Build Date : Tue Apr 15 01:01:11 2008
Build Host : localhost
Relocations : (not relocatable)
Packager : VMware, Inc. -- Linux Packaging Key -- <linux-packages@vmware.com>
Summary : gpg(VMware, Inc. -- Linux Packaging Key -- <linux-packages@vmware. com>)
Description :
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: rpm-4.11.2 (NSS-3)
mI0ESAP+VwEEAMZylR8dOijUPNn3He3GdgM/kOXEhn3uQl+sRMNJUDm1qebi2D5b ...
If you have one of the RPMs from Photon OS on another Linux system, such as Ubuntu, you can use SHA and the RSA Data Security, Inc. MD5 Message Digest Algorithm for the package to verify that it has not been tampered with:
rpm -K /home/steve/workspace/photon/stage/SRPMS/kubernetes-1.1.8-4.ph1.src.rpm
/home/steve/workspace/photon/stage/SRPMS/kubernetes-1.1.8-4.ph1.src.rpm: sha1 md5 OK
You can view the SHA1 digest and the RSA Data Security, Inc. MD5 Message Digest Algorithm by running the following command:
rpm -Kv /home/steve/workspace/photon/stage/SRPMS/kubernetes-1.1.8-4.ph1.src.rpm
/home/steve/workspace/photon/stage/SRPMS/kubernetes-1.1.8-4.ph1.src.rpm:
Header SHA1 digest: OK (89b55443d4c9f67a61ae0c1ec9bf4ece2d6aa32b)
MD5 digest: OK (51eee659a8730e25fd2a52aff9a6c2c2)
The above examples show that the Kubernetes package has not been tampered with.
1.5 - Photon OS Package Repositories
The default installation of Photon OS includes four yum-compatible repositories plus the repository on the Photon OS ISO when it is available in a CD-ROM drive:
ls /etc/yum.repos.d/
lightwave.repo
photon-extras.repo
photon-iso.repo
photon-updates.repo
photon.repo
The Photon ISO repository (photon-iso.repo
) contains the installation packages for Photon OS. All the packages that Photon builds and publishes reside in the RPMs directory of the ISO when it is mounted. The RPMs directory contains metadata that lets it act as a yum repository. Mounting the ISO gives you all the packages corresponding to a Photon OS build. If, however, you built Photon OS yourself from the source code, the packages correspond only to your build, though they will typically be the latest. In contrast, the ISO that you obtain from the Bintray web site contains only the packages that are in the ISO at the point of publication. As a result, the packages may no longer match those on Bintray, which are updated regularly.
The main Photon OS repository (photon.repo
) contains all the packages that are built from the ISO or from another source. This repository points to a static batch of packages and spec files at the point of a release.
The updates repository (photon-updates.repo
) is irrelevant to a major release until after the release is installed. Thereafter, the updates repository holds the updated packages for that release. The repository points to updates for the installed version, such as a version of Kubernetes that supersedes the version installed during the major release.
The Photon extras repository (photon-extras.repo
) holds Likewise Open, an open source authentication engine, and other VMware software that you can add to Photon OS for free. Photon OS supports but does not build the packages in the extras repository.
Similarly, the Lightwave repository (lightwave.repo
) contains the packages that make up the VMware Lightwave security suite for cloud applications, including tools for identity management, access control, and certificate management.
1.6 - Building a Package from a Source RPM
This section describes how to install and build a package on the full version of Photon OS from the package’s source RPM. Obtain the source RPMs that Photon OS uses from the Packages location, https://packages.vmware.com/photon
Prerequisites
To build a package from its source RPM, or SRPM, Photon OS requires the following packages:
rpmbuild
. This package is installed by default on the full version of Photon OS, so you should not have to install it.
gcc
. This package is also installed by default on the full version of Photon OS, so you should not have to install it.
make
, Cmake
, automake
, or another make
package, depending on the package you are trying to install and build from its source RPM. Cmake is installed by default on Photon OS.
You can install other make packages by using tdnf or yum.
A local unprivileged user account other than the root account. You should build RPMs as an unprivileged user. Do not build a package as root
because building an RPM with the root account might damage your system.
Take a snapshot of your virtual machine before building the package if you are building a package on a virtual machine running Photon OS in VMware vSphere, VMware Workstation, or VMware Fusion.
Procedure
VMware recommends that you install and build packages from their source RPMs on the full version of Photon OS. Do not use the minimal version to work with source RPMs.
Perfrom the following steps to install and build an example package- sed
from its source RPM on Photon OS with an unprivileged account.
Check whether rpmbuild is installed by running the following command.
rpmbuild --version
If it is not installed, install it by running the following command as root.
tdnf install rpm-build
Create the directories for building RPMs under your local user account home directory and not under root.
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
Create a .rpmmacros
file under your home directory and override the default location of the RPM building tree with the new one. This command overwrites an existing .rpmmacros
file. Before running the following command, make sure you do not already have a .rpmmacros file
. If a .rpmmacros
file exists, back it up under a new name in case you want to restore it later.
echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros
Place the source RPM file that you want to install and build in the /tmp
directory.
Install the source file, run the following command with your unprivileged user account, replacing the sed example source RPM with the name of the one that you want to install.
rpm -i /tmp/sed-4.2.2-2.ph1.src.rpm
The above command unpacks the source RPM and places its .spec
file in your ~/rpmbuild/SPECS
directory. In the next step, the rpmbuild
tool uses the .spec
file to build the RPM.
Build the RPM, run the following commands with your unprivileged user account. Replace the sed.spec
example file with the name of the .spec
file that you want to build.
cd ~/rpmbuild/SPECS
rpmbuild -ba sed.spec
If successful, the rpmbuild -ba command builds the RPM and generates an RPM package file in your ~/rpmbuild/RPMS/x86_64
directory. For example:
ls RPMS/x86_64/
sed-4.2.2-2.x86_64.rpm sed-debuginfo-4.2.2-2.x86_64.rpm sed-lang-4.2.2-2.x86_64.rpm
The rpmbuild command also generates a new SRPM file and saves it in your ~/rpmbuild/SRPMS
directory. For example:
ls SRPMS/
sed-4.2.2-2.src.rpm
If the rpmbuild command is unsuccessful with an error that it cannot find a library, you must install the RPMs for the library that your source RPM depends on before you can successfully build your source RPM. Iterate through installing the libraries that your source RPM relies on until you can successfully build it.
To install the RPM, run the following command with your unprivileged user account.
rpm -i RPMS/x86_64/sed-4.2.2-2.x86_64.rpm
1.7 - Compiling C++ Code on the Minimal Version of Photon OS
As a minimalist Linux run-time environment, the minimal version of Photon OS lacks the packages that you need to compile the code for a C++ program. For example, without the requisite packages, trying to compile the file containing the following code with the gcc
command will generate errors:
#include <stdio.h>
int main()
{
return 0;
}
The errors appear as follows:
gcc test.c
-bash: gcc: command not found
tdnf install gcc -y
gcc test.c
test.c:1:19: fatal error: stdio.h: No such file or directory
compilation terminated.
To enable the minimal version of Photon OS to preprocess, compile, assemble, and link C++ code, you must install the following packages as root with tdnf:
To install the packages, use the following the tdnf
command:
tdnf install gcc glibc-devel binutils
2 - Package Management in Photon OS with `tdnf`
Photon OS manages packages with an open source, yum-compatible package manager called tdnf
, for Tiny Dandified Yum. Tdnf keeps the operating system as small as possible while preserving yum’s robust package-management capabilities.
2.1 - Introduction to 'tdnf'
On Photon OS, tdnf is the default package manager for installing new packages. It is a C implementation of the DNF package manager without Python dependencies. DNF is the next upcoming major version of yum.
Tdnf appears in the minimal and full versions of Photon OS. Tdnf reads yum repositories and works like yum. The full version of Photon OS also includes yum, and you can install packages by using yum if you want.
In the minimal version of Photon OS, you can manage packages by using yum, but you must install it first by running the following tdnf
command as root:
tdnf install yum
Tdnf implements a subset of the dnf
commands as listed in the dnf guide.
2.2 - Configuration Files and Repositories
The main configuration files reside in /etc/tdnf/tdnf.conf. The configuration file appears as follows:
cat /etc/tdnf/tdnf.conf
[main]
gpgcheck=1
installonly_limit=3
clean_requirements_on_remove=true
repodir=/etc/yum.repos.d
cachedir=/var/cache/tdnf
The cache files for data and metadata reside in /var/cache/tdnf.
The following repositories appear in /etc/yum.repos.d/ with .repo
file extensions:
ls /etc/yum.repos.d/
lightwave.repo
photon-extras.repo
photon-iso.repo
photon-updates.repo
photon.repo
You can list the the repositories by using the tdnf repolist
command. Tdnf filters the results with enabled
, disabled
, and all
. Running the command without specifying an argument returns the enabled repositories:
tdnf repolist
repo id repo name status
photon-updates VMware Photon Linux 2.0(x86_64)Updates enabled
photon-extras VMware Photon Extras 2.0(x86_64) enabled
photon VMware Photon Linux 2.0(x86_64) enabled
The photon-iso.repo
, however, does not appear in the list of repositories because it is unavailable on the virtual machine from which these examples are taken. The photon-iso.repo
is the default repository and it points to /media/cdrom. The photon-iso.repo
appears as follows:
cat /etc/yum.repos.d/photon-iso.repo
[photon-iso]
name=VMWare Photon Linux 2.0(x86_64)
baseurl=file:///mnt/cdrom/RPMS
gpgkey=file:///etc/pki/rpm-gpg/VMWARE-RPM-GPG-KEY
gpgcheck=1
enabled=0
skip_if_unavailable=True
The local cache is populated with data from the repository:
ls -l /var/cache/tdnf/photon
total 8
drwxr-xr-x 2 root root 4096 May 18 22:52 repodata
d-wxr----t 3 root root 4096 May 3 22:51 rpms
You can clear the cache to help troubleshoot a problem, but doing so might slow the performance of tdnf
until the cache becomes repopulated with data. To clear the cache, use the following command:
tdnf clean all
Cleaning repos: photon photon-extras photon-updates lightwave
Cleaning up everything
The command purges the repository data from the cache:
ls -l /var/cache/tdnf/photon
total 4
d-wxr----t 3 root root 4096 May 3 22:51 rpms
2.3 - Adding a New Repository
On Photon OS, you can add a new repository from which tdnf
installs packages. To add a new repository, you create a repository configuration file with a .repo
extension and place it in /etc/yum.repos.d
. The repository can be on either the Internet or a local server containing your in-house applications.
Be careful if you add a repository that is on the Internet. Installing packages from untrusted or unverified sources might put the security, stability, or compatibility of your system at risk. It might also make your system harder to maintain.
On Photon OS, the existing repositories appear in the /etc/yum.repos.d
directory:
ls /etc/yum.repos.d/
lightwave.repo
photon-extras.repo
photon-iso.repo
photon-updates.repo
photon.repo
To view the the format and information that a new repository configuration file should contain, see one of the .repo
files. The following is an example:
cat /etc/yum.repos.d/lightwave.repo
[lightwave]
name=VMware Lightwave 1.0(x86_64)
baseurl=https://packages.vmware.com/photon/1.0/lightwave
gpgkey=file:///etc/pki/rpm-gpg/VMWARE-RPM-GPG-KEY
gpgcheck=1
enabled=1
skip_if_unavailable=True
The minimal information needed to establish a repository is an ID and human-readable name of the repository and its base URL. The ID, which appears in square brackets, must be one word that is unique amoung the system’s repositories; in the example above, it is [lightwave]
.
The baseurl
is a URL for the repository’s repodata directory. For a repository on a local server that can be accessed directly or mounted as a file system, the base URL can be a file referenced by file://
. Example:
baseurl=file:///server/repo/
The gpgcheck
setting specifies whether to check the GPG signature. The gpgkey
setting furnishes the URL for the repository’s ASCII-armored GPG key file. Tdnf uses the GPG key to verify a package if its key has not been imported into the RPM database.
The enabled
setting tells tdnf
whether to poll the repository. If enabled
is set to 1
, tdnf
polls it; if it is set to 0
, tdnf
ignores it.
The skip_if_unavailable
setting instructs tdnf
to continue running if the repository goes offline.
You can use the skip metadata download settings to skip the download of metadata files for repositories with a lot of packages. When you skip the download of the metadata files, it improves the download time of the packages and the processing time of refreshing the cache.
The following list describes the skip metadata settings:
skip_md_filelists
: The skip_md_filelists=1
setting deactivates the download of the complete list of files in all packages. The default value is 0
.
skip_md_updateinfo
: The skip_md_updateinfo=1
setting deactivates the download of the update info data. The setting improves the download and processing time but affects the output of the updateinfo
command. The default value is 0
.
Other options and variables can appear in the repository file. The variables that are used with some of the options can reduce future changes to the repository configuration files. There are variables to replace the value of the version of the package and to replace the base architecture. For more information, see the man page for yum.conf
on the full version of Photon OS: man yum.conf
The following is an example of how to add a new repository for a local server that tdnf
polls for packages:
cat > /etc/yum.repos.d/apps.repo << "EOF"
[localapps]
name=Local In-House Applications(x86_64)
baseurl=file:///appserver/apps
enabled=1
skip_if_unavailable=True
EOF
Because this new repository resides on a local server, make sure the Photon OS machine can connect to it by mounting it.
After establishing a new repository, you must run the following command to update the cached binary metadata for the repositories that tdnf
polls:
tdnf makecache
Refreshing metadata for: 'VMware Lightwave 1.0(x86_64)'
Refreshing metadata for: 'VMware Photon Linux 1.0(x86_64)Updates'
Refreshing metadata for: 'VMware Photon Extras 1.0(x86_64)'
Refreshing metadata for: 'Local In-House Applications(x86_64)'
Refreshing metadata for: 'VMware Photon Linux 1.0(x86_64)'
Metadata cache created.
2.4 - Configure a Repository
Photon OS comes with a preconfigured repository called photon-iso
that resides in \etc\yum.repos.d.
If you receive an access error message when working with the photon-iso
repository, it is probably because you do not have the Photon OS ISO mounted. Mount the ISO and the run the following command to update the metadata for all known repositories, including photon-iso
:
mount /dev/cdrom /media/cdrom
tdnf makecache
Refreshing metadata for: 'VMware Lightwave 1.0(x86_64)'
Refreshing metadata for: 'VMware Photon Linux 1.0(x86_64)Updates'
Refreshing metadata for: 'VMware Photon Extras 1.0(x86_64)'
Refreshing metadata for: 'VMware Photon Linux 1.0(x86_64)'
Metadata cache created.
2.5 - Adding the Dev Repository to Get New Packages from the GitHub Dev Branch
To try out new packages or the latest versions of existing packages as they are merged into the dev branch of the Photon OS GitHub site, add the dev
repository to your repository list.
Perform th following steps:
- On your Photon OS machine, run the following command as root to create a repository configuration file named
photon-dev.repo
, place it in /etc/yum.repos.d
, and concatenate the repository information into the file.
cat > /etc/yum.repos.d/photon-dev.repo << "EOF"
[photon-dev]
name=VMware Photon Linux Dev(x86_64)
baseurl=https://dl.bintray.com/vmware/photon_dev_$basearch
gpgkey=file:///etc/pki/rpm-gpg/VMWARE-RPM-GPG-KEY
gpgcheck=1
enabled=1
skip_if_unavailable=True
EOF
- After establishing a new repository, run the following command to update the cached binary metadata for the repositories that
tdnf
polls:
tdnf makecache
2.6 - Standard Syntax for tdnf Commands
The standard syntax for tdnf
commands is the same as that for DNF and is as follows:
tdnf [options] <command> [<arguments>...]
You can view help information by using the following commands:
tdnf --help
tdnf -h
2.6.1 - tndf Commands
check: Checks for problems in installed and available packages for all enabled repositories. The command has no arguments. You can use --enablerepo
and --disablerepo
to control the repos used. Supported in Photon OS 2.0 (only).
check-local: This command resolves dependencies by using the local RPMs to help check RPMs for quality assurance before publishing them. To check RPMs with this command, you must create a local directory and place your RPMs in it. The command, which includes no options, takes the path to the local directory containing the RPMs as its argument. The command does not recursively parse directories. It checks the RPMs only in the directory that you specify. For example, after creating a directory named /tmp/myrpms
and placing your RPMs in it, you can run the following command to check them:
tdnf check-local /tmp/myrpms
Checking all packages from: /tmp/myrpms
Found 10 packages
Check completed without issues
check-update: This command checks for updates to packages. It takes no arguments. The tdnf list updates
command performs the same function. Here is an example of the check update
command:
tdnf check-update
rpm-devel.x86_64 4.11.2-8.ph1 photon
yum.noarch 3.4.3-3.ph1 photon
clean: This command cleans up temporary files, data, and metadata. It takes the argument all
. Example:
tdnf clean all
Cleaning repos: photon photon-extras photon-updates lightwave
Cleaning up everything
distro-sync: This command synchronizes the machine’s RPMs with the latest version of all the packages in the repository. The following is an abridged example:
tdnf distro-sync
Upgrading:
zookeeper x86_64 3.4.8-2.ph1 3.38 M
yum noarch 3.4.3-3.ph1 4.18 M
Total installed size: 113.01 M
Reinstalling:
zlib-devel x86_64 1.2.8-2.ph1 244.25 k
zlib x86_64 1.2.8-2.ph1 103.93 k
yum-metadata-parser x86_64 1.1.4-1.ph1 57.10 k
Total installed size: 1.75 G
Obsoleting:
tftp x86_64 5.2-3.ph1 32.99 k
Total installed size: 32.99 k
Is this ok [y/N]:
downgrade: This command downgrades the package that you specify as an argument to the next lower package version. The following is an example:
tdnf downgrade boost
Downgrading:
boost x86_64 1.56.0-2.ph1 8.20 M
Total installed size: 8.20 M
Is this ok [y/N]:y
Downloading:
boost 2591470 100%
Testing transaction
Running transaction
Complete!
To downgrade to a version lower than the next one, you must specify it by name, epoch, version, and release, all properly hyphenated. The following is an example:
tdnf downgrade boost-1.56.0-2.ph1
erase: This command removes the package that you specify as an argument.
To remove a package, run the following command:
tdnf erase pkgname
The following is an example:
tdnf erase vim
Removing:
vim x86_64 7.4-4.ph1 1.94 M
Total installed size: 1.94 M
Is this ok [y/N]:
You can also erase multiple packages:
tdnf erase docker cloud-init
info: This command displays information about packages. It can take the name of a package. Or it can take one of the following arguments: all, available, installed, extras, obsoletes, recent, upgrades. The following are examples:
tdnf info ruby
tdnf info obsoletes
tdnf info upgrades
install: This command takes the name of a package as its argument. It then installs the package and its dependencies.
To install a package, run the following command:
tdnf install pkgname
The following are examples:
tdnf install kubernetes
You can also install multiple packages:
tdnf install python-curses lsof audit gettext chkconfig ntsysv bindutils
wget gawk irqbalance lvm2 cifs-utils c-ares distrib-compat
list: This command lists the packages of the package that you specify as the argument. The command can take one of the following arguments: all, available, installed, extras, obsoletes, recent, upgrades.
tdnf list updates
The list of packages might be long. To more easily view it, you can concatenate it into a text file, and then open the text file in a text editor:
tdnf list all > pkgs.txt
vi pkgs.txt
To list enabled repositories, run the following command:
tdnf repolist
makecache: This command updates the cached binary metadata for all known repositories. The following is an example:
tdnf makecache
Refreshing metadata for: 'VMware Lightwave 1.0(x86_64)'
Refreshing metadata for: 'VMware Photon Linux 1.0(x86_64)Updates'
Refreshing metadata for: 'VMware Photon Extras 1.0(x86_64)'
Refreshing metadata for: 'VMware Photon Linux 1.0(x86_64)'
Metadata cache created.
provides: This command finds the packages that provide the package that you supply as an argument. The following is an example:
tdnf provides docker
docker-1.11.0-1.ph1.x86_64 : Docker
Repo : photon
docker-1.11.0-1.ph1.x86_64 : Docker
Repo : @System
reinstall: This command reinstalls the packages that you specify. If some packages are unavailable or not installed, the command fails. The following is an example:
tdnf reinstall docker kubernetes
Reinstalling:
kubernetes x86_64 1.1.8-1.ph1 152.95 M
docker x86_64 1.11.0-1.ph1 57.20 M
Total installed size: 210.15 M
remove: This command removes a package. When removing a package, tdnf by default also removes dependencies that are no longer used if they were was installed by tdnf as a dependency without being explicitly requested by a user. You can modify the dependency removal by changing the clean_requirements_on_remove
option in /etc/tdnf/tdnf.conf to false
.
tdnf remove packagename
search: This command searches for the attributes of packages. The argument can be the names of packages. The following is an example:
tdnf search docker kubernetes
docker : Docker
docker : Docker
docker-debuginfo : Debug information for package docker
docker : Docker
kubernetes : Kubernetes cluster management
kubernetes : Kubernetes cluster management
kubernetes-debuginfo : Debug information for package kubernetes
kubernetes : Kubernetes cluster management
The argument of the search command can also be a keyword or a combination of keywords and packages:
tdnf search terminal bash
rubygem-terminal-table : Simple, feature rich ascii table generation library
ncurses : Libraries for terminal handling of character screens
mingetty : A minimal getty program for virtual terminals
ncurses : Libraries for terminal handling of character screens
ncurses : Libraries for terminal handling of character screens
bash : Bourne-Again SHell
bash-lang : Additional language files for bash
bash-lang : Additional language files for bash
bash : Bourne-Again SHell
bash-debuginfo : Debug information for package bash
bash : Bourne-Again SHell
bash-lang : Additional language files for bash
upgrade: This command upgrades the package or packages that you specify to an available higher version that tdnf can resolve. If the package is already the latest version, the command returns Nothing to do
. The following is an example:
tdnf upgrade boost
Upgrading:
boost x86_64 1.60.0-1.ph1 8.11 M
Total installed size: 8.11 M
Is this ok [y/N]:y
Downloading:
boost 2785950 100%
Testing transaction
Running transaction
Complete!
You can also run the upgrade
command with the refresh
option to update the cached metadata with the latest information from the repositories. The following example refreshes the metadata and then checks for a new version of tdnf but does not find one, so tdnf takes no action:
tdnf upgrade tdnf --refresh
Refreshing metadata for: 'VMware Lightwave 1.0(x86_64)'
Refreshing metadata for: 'VMware Photon Linux 1.0(x86_64)Updates'
Refreshing metadata for: 'VMware Photon Extras 1.0(x86_64)'
Refreshing metadata for: 'VMware Photon Linux 1.0(x86_64)'
Nothing to do.
upgrade-to: This command upgrades to the version of the package that you specify. EThe following is an example:
tdnf upgrade-to ruby2.3
The commands and options of tdnf are a subset of those of dnf. For more help with tdnf
commands, see the DNF documentation.
2.6.2 - tndf Command Options
You can add the following options to tdnf
commands. If the option to override a configuration is unavailable in a command, you can add it to the /etc/tdnf/tdnf.conf
configuration file.
OPTION DESCRIPTION
--allowerasing Allow erasing of installed packages to resolve dependencies
--assumeno Answer no for all questions
--best Try the best available package versions in transactions
--debugsolver Dump data aiding in dependency solver debugging info.
--disablerepo=<repoid> Disable specific repositories by an id or a glob.
--enablerepo=<repoid> Enable specific repositories
-h, --help Display help
--refresh Set metadata as expired before running command
--nogpgcheck Skip gpg check on packages
--rpmverbosity=<debug level name>
Debug level for rpm
--version Print version and exit
-y, --assumeyes Answer yes to all questions
-q, --quiet Quiet operation
The following is an example that adds the short form of the assumeyes
option to the install command:
tdnf -y install gcc
Upgrading:
gcc x86_64 5.3.0-1.ph1 91.35 M
3 - Managing Services with `systemd`
Photon OS manages services with systemd
. By using systemd
, Photon OS adopts a contemporary Linux standard to bootstrap the user space and concurrently start services. This is an architecture that differs from traditional Linux systems such as SUSE Linux Enterprise Server.
A traditional Linux system contains an initialization system called SysVinit. With SLES 11, for instance, the SysVinit-style init programs control how the system starts up and shuts down. Init implements system runlevels. A SysVinit runlevel defines a state in which a process or service runs.
In contrast to a SysVinit system, systemd
defines no such runlevels. Instead, systemd
uses a dependency tree of targets to determine which services to start when. Combined with the declarative nature of systemd
commands, systemd
targets reduce the amount of code needed to run a command, leaving you with code that is easier to maintain and probably faster to execute. For an overview of systemd
, see systemd System and Service Manager and the man page for systemd.
On Photon OS, you must manage services with systemd and systemctl
, its command-line utility for inspecting and controlling the system, and not the deprecated commands of init.d
.
For more information, see the index of all the systemd man pages, including systemctl, at
https://www.freedesktop.org/software/systemd/man/
3.1 - Viewing Services
To view a description of all the loaded and active units, run the systemctl
command without any options or arguments:
systemctl
To see all the loaded, active, and inactive units and their description, run the following command:
systemctl --all
To see all the unit files and their current status but no description, run thie following command:
systemctl list-unit-files
The grep
command filters the services by a search term, a helpful tactic to recall the exact name of a unit file without looking through a long list of names. Example:
systemctl list-unit-files | grep network
org.freedesktop.network1.busname static
dbus-org.freedesktop.network1.service enabled
systemd-networkd-wait-online.service enabled
systemd-networkd.service enabled
systemd-networkd.socket enabled
network-online.target static
network-pre.target static
network.target static
3.2 - Controlling Services
To control services on Photon OS, use systemctl
command.
For example, instead of running the /etc/init.d/ssh
script to stop and start the OpenSSH server on a init.d-based Linux system, run the following systemctl
commands on Photon OS:
systemctl stop sshd
systemctl start sshd
The systemctl tool includes a range of commands and options for inspecting and controlling the state of systemd and the service manager. For more information, see the systemctl man page.
3.3 - Creating a Startup Service
Use systemd
to create a startup service.
The following example shows you how to create a systemd startup service that changes the maximum transmission unit (MTU) of the default Ethernet connection, eth0
.
- Concatenate the following block of code into a file:
cat << EOF >> /lib/systemd/system/eth0.service
[Unit]
Description=Network interface initialization
After=local-fs.target network-online.target network.target
Wants=local-fs.target network-online.target network.target
[Service]
ExecStart=/usr/sbin/ifconfig eth0 mtu 1460 up
Type=oneshot
[Install]
WantedBy=multi-user.target
EOF
- Set the service to auto-start when the system boots:
cd /lib/systemd/system/multi-user.target.wants/
ln -s ../eth0.service eth0.service
3.4 - Disabling the Photon OS httpd.service
If your application or appliance includes its own HTTP server, you must turn off and disable the HTTP server that comes with Photon OS so that it does not conflict with your own HTTP server.
To stop it and disable it, run the following commands as root:
systemctl stop httpd.service
systemctl disable httpd.service
3.5 - Installing Sendmail
Before you install Sendmail, you should set the fully qualified domain name (FQDN) of your Photon OS machine.
By default, Sendmail is not installed with either the minimal or full version of Photon OS. When you install Sendmail, it provides Photon OS with a systemd
service file that typically enables Sendmail. If the service is not enabled after installation, you must enable it.
Sendmail resides in the Photon extras repository. You can install it with tdnf
after setting the machine’s FQDN.
Procedure
- Check whether the FQDN of the machine is set by running the
hostnamectl status
command:
hostnamectl status
Static hostname: photon-d9ee400e194e
Icon name: computer-vm
Chassis: vm
Machine ID: a53b414142f944319bd0c8df6d811f36
Boot ID: 1f75baca8cc249f79c3794978bd82977
Virtualization: vmware
Operating System: VMware Photon/Linux
Kernel: Linux 4.4.8
Architecture: x86-64
Note
In the results above, the FQDN is not set. The Photon OS machine only has a short name. If the FQDN were set, the hostname would be in its full form, typically with a domain name.If the machine does not have an FQDN, set one by running hostnamectl set-hostname new-name
, replacing new-name
with the FQDN that you want. For example:
hostnamectl set-hostname photon-d9ee400e194e.corp.example.com
The hostnamectl status
command now shows that the machine has an FQDN:
root@photon-d9ee400e194e [ ~ ]# hostnamectl status
Static hostname: photon-d9ee400e194e.corp.example.com
Icon name: computer-vm
Chassis: vm
Machine ID: a53b414142f944319bd0c8df6d811f36
Boot ID: 1f75baca8cc249f79c3794978bd82977
Virtualization: vmware
Operating System: VMware Photon/Linux
Kernel: Linux 4.4.8
Architecture: x86-64
Install Sendmail:
Verify if Sendmail is enabled:
systemctl status sendmail
Enable Sendmail if it is disabled and then start it:
systemctl enable sendmail
systemctl start sendmail
3.6 - Auditing System Events with auditd
To manage security on Photon OS, the Linux auditing service auditd
is enabled and active by default on the full version of Photon OS.
The following command shows the security status:
systemctl status auditd
* auditd.service - Security Auditing Service
Loaded: loaded (/usr/lib/systemd/system/auditd.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2016-04-29 15:08:50 UTC; 1 months 9 days ago
Main PID: 250 (auditd)
CGroup: /system.slice/auditd.service
`-250 /sbin/auditd -n
To help improve security, the auditd
service can monitor file changes, system calls, executed commands, authentication events, and network access. After you implement an audit rule to monitor an event, the aureport
tool generates reports to display information about the events.
You can use the auditctl utility to set a rule that monitors the sudoers
file for changes:
auditctl -w /etc/sudoers -p wa -k sudoers_changes
This rule specifies that the auditd service must watch (-w
) the /etc/sudoers
file to log permissions changes (-p
) to the write access (w
) or attributes (a
) of the file and to identify them in logs as sudoers_changes
. The auditing logs appear in /var/log/audit/audit.log
. You can list the auditing rules as follows:
auditctl -l
-w /etc/sudoers -p wa -k sudoers_changes
For more information on the Linux Audit Daemon, see the auditd
man page:
man auditd
For more information on setting auditing rules and options, see the auditctl
man page:
man auditctl
For more information on viewing reports on audited events, see the aureport
man page:
man aureport
3.7 - Analyzing systemd Logs with journalctl
The journalctl
tool queries the contents of the systemd
journal.
The following command displays the messages that systemd
generated the last time the machine started:
journalctl -b
The following command reveals the messages for the systemd service unit specified by the -u
option:
journalctl -u auditd
In the above example, auditd
is the system service unit.
For more information, see the journalctl
man page by running the following command on Photon OS:
man journalctl
3.8 - Migrating Scripts to systemd
Although systemd
maintains compatibility with init.d
scripts, as a best practice, you must adapt the scripts that you want to run on Photon OS to systemd
to avoid potential problems.
Such a conversion standardizes the scripts, reduces the footprint of your code, makes the scripts easier to read and maintain, and improves their robustness on a systemd
system.
4 - Configure Wireless Networking
You can configure wireless networking in Photon OS. Connect to an open network or a WPA2 protected network using wpa_cli
and configure systemd-networkd
to assign an IP address to the network.
Connect Using wpa_cli
When you connect using wpa_cli
, you can scan for available networks and associate the network with a network ID.
Perform the following steps:
Ensure that the wpa_supplicant service
is running on the WLAN interface:
Systemctl status wpa_supplicant@<wlan-interface>.service
Connect to wpa_cli
:
wpa_cli -i wlan0
Scan for available networks:
scan
To see the list of networks, use the following command:
scan_results
Add the network:
add_network
This command returns a network ID.
Associate the network with the network ID.
set_network <network ID> ssid “<ssid-name>”
For a WPA2 network, set the passphrase:
set_network <network ID> psk “<passphrase>”
Enable the network:
enable_network <network ID>
Save the configuration file:
save_config
To exit the wpa_cli
, type ‘quit`.
Assign IP Address To Network
Configure systemd-networkd
to assign IP address to network. Perform the following steps:
Create a /etc/systemd/network/98-dhcp-wlan.network
file with the following contents:
[Match]
Name=wlan*
[Network]
DHCP=yes
IPv6AcceptRA=no
Restart systemd-networkd
using:
Systemctl restart systemd-networkd
5 - Managing the Network Configuration
The network service, which is enabled by default, starts when the system boots.
5.1 - Commands to Manage Network Service
You manage the network service by using systemd commands, such as systemd-networkd
, systemd-resolvd
, and networkctl
.
To check the status of the network service, run the following command:
systemctl status systemd-networkd
Output
* systemd-networkd.service - Network Service
Loaded: loaded (/usr/lib/systemd/system/systemd-networkd.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2016-04-29 15:08:51 UTC; 6 days ago
Docs: man:systemd-networkd.service(8)
Main PID: 291 (systemd-network)
Status: "Processing requests..."
CGroup: /system.slice/systemd-networkd.service
`-291 /lib/systemd/systemd-networkd
Because Photon OS relies on systemd to manage services, you must use the systemd
suite of commands and not the deprecated init.d
commands or other deprecated commands to manage networking.
5.2 - Using the Network Configuration Manager
The Network Configuration Manager library that ships with Photon OS 3.0 provides a collection of C, Python, and CLI APIs that simplify common onfiguration tasks for:
- interfaces
- IP addresses (IPv4 and IPv6 addresses)
- routes
- DNS server and domain settings
- DHCP DUID and IAID settings
- NTP server settings
- service management
- object parameters (interfaces and files)
For more information, see:
5.3 - Use `ip` and `ss` Commands
Use the ip
and ss
commands to view a list of network interfaces and information for IP addresses.
Although the ifconfig
command and the netstat
command work on Photon OS, VMware recommends that you use the ip
or ss
commands. The ipconfig
and netstat
commands are deprecated.
For example, to display a list of network interfaces, run the ss
command instead of netstat
. To display information for IP addresses, run the ip addr
command instead of ifconfig -a
.
Examples are as follows:
USE THIS IPROUTE COMMAND INSTEAD OF THIS NET-TOOL COMMAND
ip addr ifconfig -a
ss netstat
ip route route
ip maddr netstat -g
ip link set eth0 up ifconfig eth0 up
ip -s neigh arp -v
ip link set eth0 mtu 9000 ifconfig eth0 mtu 9000
Using the ip route
version of a command instead of the net-tools version often provides more complete and accurate information on Photon OS. Examples are as follows:
ip neigh
198.51.100.2 dev eth0 lladdr 00:50:56:e2:02:0f STALE
198.51.100.254 dev eth0 lladdr 00:50:56:e7:13:d9 STALE
198.51.100.1 dev eth0 lladdr 00:50:56:c0:00:08 DELAY
arp -a
? (198.51.100.2) at 00:50:56:e2:02:0f [ether] on eth0
? (198.51.100.254) at 00:50:56:e7:13:d9 [ether] on eth0
? (198.51.100.1) at 00:50:56:c0:00:08 [ether] on eth0
5.4 - Configuring Network Interfaces
Network configuration files for systemd-networkd reside in /etc/systemd/network
and /usr/lib/systemd/network
. Example:
root@photon-rc [ ~ ]# ls /etc/systemd/network/
99-dhcp-en.network
By default, when Photon OS starts, it creates a DHCP network configuration file, or rule, which appears in /etc/systemd/network, the highest priority directory for network configuration files with the lowest priority filename:
cat /etc/systemd/network/99-dhcp-en.network
[Match]
Name=e*
[Network]
DHCP=yes
Network configuration files can also appear in the system network directory, /usr/lib/systemd/network
, as the results of the following search illustrate:
root@photon-rc [ ~ ]# updatedb
root@photon-rc [ ~ ]# locate systemd/network
/etc/systemd/network
/etc/systemd/network/99-dhcp-en.network
/usr/lib/systemd/network
/usr/lib/systemd/network/80-container-host0.network
/usr/lib/systemd/network/80-container-ve.network
/usr/lib/systemd/network/99-default.link
root@photon-rc [ ~ ]#
In the above search, the /usr/lib/systemd/network
directory contains several network configuration files. Photon OS applies the configuration files in lexicographical order specified by the file names without regard for the network configuration directory in which the file resides unless the file name is the same. Photon OS processes files with identical names by giving precedence to files in the /etc
directory over the other directory. Thus, the settings in /etc/systemd/network
override those in /usr/lib/systemd/network
. Once Photon OS matches an interface in a file, Photon OS ignores the interface if it appears in files processed later in the lexicographical order.
Each .network file contains a matching rule and a configuration that Photon OS applies when a device matches the rule. Set the matching rule and the configuration as sections containing vertical sets of key-value pairs according to the information in systemd network configuration.
To configure Photon OS to handle a networking use case, such as setting a static IP address or adding a name server, create a configuration file with a .network
extension and place it in the /etc/systemd/network directory
.
After you create a network configuration file with a .network
extension, you must run the chmod
command to set the new file’s mode bits to 644
. Example:
chown systemd-network:systemd-network 10-static-en.network
For Photon OS to apply the new configuration, you must restart the systemd-networkd
service by running the following command:
systemctl restart systemd-networkd
For information about network configuration files, their processing order, and their matching rules, sections, and keys, see https://www.freedesktop.org/software/systemd/man/systemd.network.html.
For information about creating virtual network device files (.netdev
), see https://www.freedesktop.org/software/systemd/man/systemd.netdev.html.
5.5 - Setting a Static IP Address
Before you set a static IP address, obtain the name of your Ethernet link by running the following command:
networkctl
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier unmanaged
2 eth0 ether routable configured
In the results of the command, you can see the name of an Ethernet link, eth0
.
To create a network configuration file that systemd-networkd uses to establish a static IP address for the eth0 network interface, execute the following command as root:
cat > /etc/systemd/network/10-static-en.network << "EOF"
[Match]
Name=eth0
[Network]
Address=198.51.0.2/24
Gateway=198.51.0.1
EOF
Change the new file’s mode bits by running the chmod
command:
chmod 644 10-static-en.network
Apply the configuration by running the following command:
systemctl restart systemd-networkd
For more information, see the man page for systemd-networkd: man systemd.network
5.6 - Turning Off DHCP
By default, when Photon OS first starts, it creates a DHCP network configuration file or rule, which appears in /etc/systemd/network
, the highest priority directory for network configuration files with the lowest priority filename:
cat /etc/systemd/network/99-dhcp-en.network
[Match]
Name=e*
[Network]
DHCP=yes
To turn off DHCP for all Ethernet interfaces, change the value of DHCP
from yes
to no
, save the changes, and then restart the systemd-networkd
service:
systemctl restart systemd-networkd
If you create a configuration file with a higher priority filename (e.g. 10-static-en.network
), it is not necessary but still recommended to turn off DHCP.
5.7 - Adding a DNS Server
Photon OS uses systemd-resolved
to resolve domain names, IP addresses, and network names for local applications. The systemd-resolved
daemon automatically creates and maintains the /etc/resolv.conf
file, into which systemd-resolved places the IP address of the DNS server. You must not modify the /etc/resolv.conf
file.
Note: If you want to implement a local resolver like bind
instead of systemd-resolved
, stop the systemd-resolved
service and disable it.
If you open the default /etc/resolv.conf
file after you deploy Photon OS, it looks like this:
root@photon-rc [ ~ ]# cat /etc/resolv.conf
# This file is managed by systemd-resolved(8). Do not edit.
#
# Third party programs must not access this file directly, but
# only through the symlink at /etc/resolv.conf. To manage
# resolv.conf(5) in a different way, replace the symlink by a
# static file or a different symlink.
nameserver 198.51.100.2
To add a DNS server, insert a DNS key into the Network section of the static network configuration file, for example, /etc/systemd/network/10-eth0-static.network
and set it to the IP address of your DNS server:
[Match]
Name=e*
[Network]
Address=198.51.0.2/24
Gateway=198.51.0.1
DNS=198.51.0.1
Note: To apply the changes made to /etc/systemd/network/*.network
files, perform the following:
- Restart
systemd-networkd
and systemd-resolved
services by running the following commands:systemctl restart systemd-networkd
systemctl restart systemd-resolved
If your machine is working with DHCP, you can add a DNS server by modifying the /etc/systemd/resolved.conf--a
method.
For more information, see https://www.freedesktop.org/software/systemd/man/resolved.conf.html.
You can optionally activate the local DNS stub resolver of systemd-resolved by adding dns
and resolve
to the /etc/nsswitch.conf
file. To do so, make a backup copy of the /etc/nsswitch.conf
file and then execute the following command as root:
sed -i 's/^hosts.*$/hosts: files resolve dns/' /etc/nsswitch.conf
For more information about the systemd-resolved
service, see https://www.freedesktop.org/software/systemd/man/systemd-resolved.service.html.
5.8 - Setting Up Networking for Multiple NICs
If your machine contains multiple NICs, it is recommend that you create a .network
configuration file for each network interface. The following scenario demonstrates how to set one wired network interface to use a static IP address and another wired network interface to use a dynamic IP address obtained through DHCP.
Note: The following configurations are examples and you must change the IP addresses and other information to match your network and requirements.
First, create the .network
file for the static Ethernet connection in /etc/systemd/network
. A best practice is to match the exact name of the network interface, which is eth0
in this example. This example file also includes a DNS server for the static IP address. As a result, the configuration sets the UseDNS key to false in the DHCP column so that Photon OS ignores the DHCP server for DNS for this interface.
cat > /etc/systemd/network/10-eth0-static-en.network << "EOF"
[Match]
Name=eth0
[Network]
Address=10.137.20.11/19
Gateway=10.137.23.253
DNS=10.132.71.1
[DHCP]
UseDNS=false
EOF
Second, create the .network
file for the second network interface, which is eth1
in this example. This configuration file sets the eth1 interface to an IP address from DHCP and sets DHCP as the source for DNS lookups. Setting the DHCP key to yes
acquires an IP address for IPv4 and IPv6. To acquire an IP address for IPv4 only, set the DHCP key to ipv4
.
cat > /etc/systemd/network/50-eth1-dhcp-en.network << "EOF"
[Match]
Name=eth1
[Network]
DHCP=yes
[DHCP]
UseDNS=true
EOF
5.8.1 - Combining DHCP and Static IP Addresses with IPv4 and IPv6
You can combine DHCP and static IP addresses with both IPv4 and IPv6.
Examples
The following example shows how to use DHCP to allocate both IPv4 and IPv6 addresses:
[Network]
DHCP=yes
The following example shows how to use DHCP to allocate only IPv4 addresses:
[Network]
DHCP=ipv4
The following example shows how to use DHCP to allocate only IPv6 addresses:
[Network]
DHCP=ipv6
The following example shows how to use DHCP for IPv4 addresses and static IP addresses for IPv6 addresses:
[Network]
DHCP=ipv4
Address=fd00::1/48
Gateway=fd00::252
The following example shows how to use DHCP for IPv6 addresses and static IP addresses for IPv4:
[Network]
DHCP=ipv6
Address=10.10.10.1/24
Gateway=10.10.10.253
The following example shows how to use static IP addresses for both IPv4 and IPv6:
[Network]
DHCP=ipv6
Address=10.10.10.1/24
Gateway=10.10.10.253
Address=fd00::1/48
Gateway=fd00::252
5.9 - Clearing the Machine ID of a Cloned Instance for DHCP
Photon OS uses the contents of /etc/machine-id
to determine the DHCP unique identifier (duid) that is used for DHCP requests. If you use a Photon OS instance as the base system for cloning, to create additional Photon OS instances, you must clear the machine-id
with this command:
echo -n > /etc/machine-id
When the value is cleared, systemd
regenerates the machine-id and all DHCP requests will contain a unique duid.
5.10 - Using Predictable Network Interface Names
When you run Photon OS on a virtual machine or a bare-metal machine, the Ethernet network interface name might shift from one device to another if you add or remove a card and reboot the machine. For example, a device named eth2
might become eth1
after you remove a NIC and restart the machine.
You can prevent interface names from reordering by turning on predictable network interface names. The naming schemes that Photon OS uses can then assign fixed, predictable names to network interfaces even after you add or remove cards or other firmware and the restart the system.
When you enable predictable network interface names, you can use one of the following options to assign persistent names to network interfaces:
- Apply the
slot
name policy to set the name of networking devices in the ens
format with a statically assigned PCI slot number. - Apply the
mac
name policy to set the name of networking devices in the enx
format a unique MAC address. - Apply the
path
name policy to set the name of networking devices in the enpXsY
format derived from a device connector’s physical location.
Though Photon OS supports the onboard
name policy to set the name of networking devices from index numbers given by the firmware in the eno
format, the policy might result in nonpersistent names.
The option to choose depends on your use case and your unique networking requirements. For example, when you clone virtual machines and require the MAC addresses to be different from one another but the interface name to be the same, consider using ens
to keep the slot the same after system reboots.
Alternatively, if the cloning function supports enx
, you can use it to set a MAC address which persists after reboots.
Perform the following steps to turn on predictable network interface names:
Make a backup copy of the following file in case you need to restore it later:
cp /boot/grub/grub.cfg /boot/grub/grub.cfg.original
To turn on predictable network interface names, edit /boot/grub/grub.cfg
to remove the following string:
net.ifnames=0Item
The string appears near the bottom of the file in the menuentry
section:
menuentry "Photon" {
linux "/boot/"$photon_linux root=$rootpartition net.ifnames=0 $photon_cmdline
if [ "$photon_initrd" ]; then
initrd "/boot/"$photon_initrd
fi
}
# End /boot/grub2/grub.cfg
Edit out net.ifnames=0
, but make no other changes to the file, and then save it.
Specify the types of policies that you want to use for predictable interface names by modifying the NamePolicy
option in /lib/systemd/network/99-default.link
. The file contents are as follows:
cat /lib/systemd/network/99-default.link
[Link]
NamePolicy=kernel database
MACAddressPolicy=persistent
To use the ens
or enx
option, the slot
policy or the mac
policy can be added to the space-separated list of policies that follow the NamePolicy
option in the default link file, /lib/systemd/network/99-default.link
. The order of the policies matters. Photon OS applies the policy listed first before proceeding to the next policy if the first one fails.
For example:
/lib/systemd/network/99-default.link
[Link]
NamePolicy=slot mac kernel database
MACAddressPolicy=persistent
With the name policy specified in the above example, you might still have an Ethernet-style interface name if the two previous policies, slot
and mac
, fail.
For information on setting name policies, see systemd.link–network device configuration.
5.11 - Inspecting the Status of Network Links with `networkctl`
You can inspect information about network connections by using the networkctl
command. This can help you configure networking services and troubleshoot networking problems.
You can progressively add options and arguments to the networkctl
command to move from general information about network connections to specific information about a network connection.
networkctl
Command Without Options
Run the networkctl
command without options to default to the list command:
networkctl
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier unmanaged
2 eth0 ether routable configured
3 docker0 ether routable unmanaged
11 vethb0aa7a6 ether degraded unmanaged
4 links listed.
networkctl status
Command
Run networkctl
with the status command to display the following information:
root@photon-rc [ ~ ]# networkctl status
* State: routable
Address: 198.51.100.131 on eth0
172.17.0.1 on docker0
fe80::20c:29ff:fe55:3ca6 on eth0
fe80::42:f0ff:fef7:bd81 on docker0
fe80::4c84:caff:fe76:a23f on vethb0aa7a6
Gateway: 198.51.100.2 on eth0
DNS: 198.51.100.2
You can see that there are active network links with IP addresses for not only the Ethernet connection but also a Docker container.
networkctl status
Command With Network Link Option
You can add a network link, such as the Ethernet connection, as the argument of the status
command to show specific information about the link:
root@photon-rc [ ~ ]# networkctl status eth0
* 2: eth0
Link File: /usr/lib/systemd/network/99-default.link
Network File: /etc/systemd/network/99-dhcp-en.network
Type: ether
State: routable (configured)
Path: pci-0000:02:01.0
Driver: e1000
HW Address: 00:0c:29:55:3c:a6 (VMware, Inc.)
MTU: 1500
Address: 198.51.100.131
fe80::20c:29ff:fe55:3ca6
Gateway: 198.51.100.2
DNS: 198.51.100.2
CLIENTID: ffb6220feb00020000ab116724f520a0a77337
networkctl status
Command With Docker Option
You can add a Docker container as the argument of the status
command to show specific information about the container:
networkctl status docker0
* 3: docker0
Link File: /usr/lib/systemd/network/99-default.link
Network File: n/a
Type: ether
State: routable (unmanaged)
Driver: bridge
HW Address: 02:42:f0:f7:bd:81
MTU: 1500
Address: 172.17.0.1
fe80::42:f0ff:fef7:bd81
In the example above, the state of the Docker container is unmanaged because Docker handles managing the networking for the containers without using systemd-resolved or systemd-networkd. Docker manages the container connection by using its bridge drive.
For more information about networkctl
commands and options, see https://www.freedesktop.org/software/systemd/man/networkctl.html.
5.12 - Turning On Network Debugging
You can set systemd-networkd
to work in debug mode so that you can analyze log files with debugging information to help troubleshoot networking problems.
You can turn on network debugging by adding a drop-in file in /etc/systemd
to customize the default systemd configuration in /usr/lib/systemd
.
Procedure
- Run the following command as root to create a directory with the name
systemd-networkd.service.d
, including the .d
extension.
mkdir -p /etc/systemd/system/systemd-networkd.service.d/
- Run the following command as root to establish a
systemd
drop-in unit with a debugging configuration for the network service.
cat > /etc/systemd/system/systemd-networkd.service.d/10-loglevel-debug.conf << "EOF"
[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
EOF
- Reload the
systemctl
daemon and restart the systemd-networkd
service for the changes to take effect.
systemctl daemon-reload
systemctl restart systemd-networkd
- Verify your changes.
systemd-delta --type=extended
- View the log files by running this command.
journalctl -u systemd-networkd
- After debugging the network connections, turn debugging off by deleting the drop-in file.
rm /etc/systemd/system/systemd-networkd.service.d/10-loglevel-debug.conf
5.13 - Mounting a Network File System
To mount a network file system, Photon OS requires nfs-utils
. The nfs-utils
package contains the daemon, userspace server, and client tools for the kernel Network File System (NFS). The tools include mount.nfs
, umount.nfs
, and showmount
.
The nfs-utils
package is installed by default in the full version of Photon OS but not in the minimal version. To install nfs-utils
in the minimal version, run the following command as root:
tdnf install nfs-utils
For instructions on how to use nfs-utils
to share files over a network, see Photon OS nfs-utils.
5.14 - Network Configuration Manager - C API
Photon OS 2.0 provides a C API for the Network Configuration Manager.
About the Network Configuration Manager C API
Use the Network Configuration Manager C API to simplify common network configuration tasks for:
- interfaces
- IP addresses (IPv4 and IPv6 addresses)
- routes
- DNS server and domain settings
- DHCP DUID and IAID settings
- NTP server settings
- service management
- object parameters (interfaces and files)
Header files for all the C APIs are defined in the following location:
https://github.com/ vmware /pmd/tree/master/include
To install the Network Configuration Manager header file, run the following command:
tdnf install netmgmt-devel
n
Once installed, you can reference the header file in the following location:
/usr/include/netmgmt/netmgr.h
Freeing Memory
For all get APIs that take a pointer-to-pointer parameter, the caller has the responsibility to free the memory upon successful response from API by calling free().
Error Codes
All C API calls return 0 for success, or one of the following error codes for failure.
- 4097 - NM_ERR_INVALID_PARAMETER
- 4098 - NM_ERR_NOT_SUPPORTED
- 4099 - NM_ERR_OUT_OF_MEMORY
- 4100 - NM_ERR_VALUE_NOT_FOUND
- 4101 - NM_ERR_VALUE_EXISTS
- 4102 - NM_ERR_INVALID_INTERFACE
- 4103 - NM_ERR_INVALID_ADDRESS
- 4104 - NM_ERR_INVALID_MODE
- 4105 - NM_ERR_BAD_CONFIG_FILE
- 4106 - NM_ERR_WRITE_FAILED
- 4107 - NM_ERR_TIME_OUT
- 4108 - NM_ERR_DHCP_TIME_OUT
Use nm_get_error_info to retrieve information about an error code.
const char \*
nm_get_error_info(
uint32_t nmErrCode
);``
Interface Configuration APIs
The Photon OS 2.0 network manager C API enables you to manage network interfaces.
Structure Declarations
Link Mode
Description
Link mode. Available settings:
LINK_AUTO
- the specified interface is managed and configured by systemd network managerLINK_MANUAL
- systemd will not bring up or configure the specified interfaceLINK_MODE_UNKNOWN
- the link mode is unknown
Declaration
typedef enum _NET_LINK_MODE
{
LINK_AUTO = 0,
LINK_MANUAL,
LINK_MODE_UNKNOWN
} NET_LINK_MODE;``
Link State
Description
Link state. Available settings:
LINK_DOWN
- the link is being administratively down or has no carrier signalLINK_UP
- the link is configured up and has carrier signalLINK_STATE_UNKNOWN
- link state is unknown
Declaration
typedef enum _NET_LINK_STATE
{
LINK_DOWN = 0,
LINK_UP,
LINK_STATE_UNKNOWN,
} NET_LINK_STATE;
Description
Link information. Includes the following information:
pszInterfaceName
- interface namepszMacAddress
- interface hardware address specified in a colon-separated format (for example: “00:0c:29:99:a5:7b”)mtu
- maximum transmission unit (MTU)mode
- link mode (see above)state
- link state (see above)
Declaration
typedef struct _NET_LINK_INFO
{
struct _NET_LINK_INFO \*pNext;
char \*pszInterfaceName;
char \*pszMacAddress;
uint32_t mtu;
NET_LINK_MODE mode;
NET_LINK_STATE state;
} NET_LINK_INFO, \*PNET_LINK_INFO;
nm_set_link_mac_addr
Description
Set the MAC address of the interface.
Declaration
uint32_t
nm_set_link_mac_addr(
const char \*pszInterfaceName,
const char \*pszMacAddress
);
Arguments
pszInterfaceName
- interface namepszMacAddress
- interface hardware address specified in a colon-separated format (for example: “00:0c:29:99:a5:7b”)
Returns
- success: 0
- failure: error code
nm_get_link_mac_addr
Description
Get the MAC address of the interface.
Declaration
uint32_t
nm_get_link_mac_addr(
const char \*pszInterfaceName,
char \*\*ppszMacAddress
);
Arguments
pszInterfaceName
- interface nameppszMacAddress
- interface hardware address specified in a colon-separated format (for example: “00:0c:29:99:a5:7b”)
Returns
- success: 0
- failure: error code
nm_set_link_mode
Description
Set the mode of the interface (auto or manual).
Declaration
uint32_t
nm_set_link_mode(
const char \*pszInterfaceName,
NET_LINK_MODE mode
);
Arguments
pszInterfaceName
- interface namemode
- link mode. One of the following values:LINK_AUTO
- the specified interface is managed and configured by systemd network managerLINK_MANUAL
- systemd will not bring up or configure the specified interfaceLINK_MODE_UNKNOWN
- the link mode is unknown
Returns
- success: 0
- failure: error code
nm_get_link_mode
Description
Get the mode of the interface (auto or manual).
Declaration
uint32_t
nm_get_link_mode(
const char \*pszInterfaceName,
NET_LINK_MODE \*pLinkMode
);
Arguments
pszInterfaceName
- interface namepLinkMode
- link mode. One of the following values:LINK_AUTO
- the specified interface is managed and configured by systemd network managerLINK_MANUAL
- systemd will not bring up or configure the specified interfaceLINK_MODE_UNKNOWN
- the link mode is unknown
Returns
- success: 0
- failure: error code
nm_set_link_mtu
Description
Set the maximum transmission unit (MTU) of the interface.
Declaration
uint32_t
nm_set_link_mtu(
const char \*pszInterfaceName,
uint32_t mtu
);
Arguments
pszInterfaceName
- interface namemtu
- maximum transmission unit (MTU)
Returns
- success: 0
- failure: error code
nm_get_link_mtu
Description
Get the maximum transmission unit (MTU) of the interface.
Declaration
nm_get_link_mtu
uint32_t
nm_get_link_mtu(
const char \*pszInterfaceName,
uint32_t \*pMtu
);
Arguments
pszInterfaceName
- interface namepMtu
- maximum transmission unit (MTU)
Returns
- success: 0
- failure: error code
nm_set_link_state
Description
Set the link state of the interface (up or down).
Declaration
uint32_t
nm_set_link_state(
const char \*pszInterfaceName,
NET_LINK_STATE state
);
Arguments
pszInterfaceName
- interface namestate
- link state. One of the following values:LINK_DOWN
- the link is being administratively down or has no carrier signal.LINK_UP
- the link is configured up and has carrier signal.LINK_STATE_UNKNOWN
- the link state is unknown
Returns
- success: 0
- failure: error code
nm_get_link_state
Description
Get the link state of the interface (up or down).
Declaration
uint32_t
nm_get_link_state(
const char \*pszInterfaceName,
NET_LINK_STATE \*pLinkState
);
Arguments
pszInterfaceName
- interface namepLinkState
- link state. One of the following values:LINK_DOWN
- the link is being administratively down or has no carrier signalLINK_UP
- the link is configured up and has carrier signalLINK_STATE_UNKNOWN
- the link state is unknown
Returns
- success: 0
- failure: error code
nm_ifup
Description
Set the specified interface state to UP. Additionally, if the interface is configured to have an IP address, it waits for the interface to acquire the IP address, and then updates neighbors of its IP address via the address resolution protocol (ARP) messages.
Declaration
uint32_t
nm_ifup(
const char \*pszInterfaceName
);
Arguments
pszInterfaceName
- interface name
Returns
- success: 0
- failure: error code
nm_ifdown
Description
Set the specified interface state to DOWN.
Declaration
uint32_t
nm_ifdown(
const char \*pszInterfaceName
);
Arguments
pszInterfaceName
- interface name
Returns
- success: 0
- failure: error code
nm_get_link_info
Description
Get link information for the interface. The caller is responsible for freeing ppLinkInfo by calling nm_free_link_info.
Declaration
uint32_t
nm_get_link_info(
const char \*pszInterfaceName,
NET_LINK_INFO \*\*ppLinkInfo
);
Arguments
pszInterfaceName
- interface nameppLinkInfo
, which includes the following information:- *
pszInterfaceName
- interface name - *
pszMacAddress
- interface hardware address specified in a colon-separated format (for example: “00:0c:29:99:a5:7b”) mtu
- maximum transmission unit (MTU)mode
- One of the following values:LINK_AUTO
- the specified interface is managed and configured by systemd network managerLINK_MANUAL
- systemd will not bring up or configure the specified interfaceLINK_MODE_UNKNOWN
- the link mode is unknown
state
- One of the following values:LINK_DOWN
- the link is being administratively down or has no carrier signalLINK_UP
- the link is configured up and has carrier signalLINK_STATE_UNKNOWN
- the link state is unknown
Returns
- success: 0
- failure: error code
nm_free_link_info
Description
Frees the NET_LINK_INFO structure returned by a successful nm_get_link_info call.
Declaration
void
nm_free_link_info(
NET_LINK_INFO \*pNetLinkInfo
);
Arguments
pNetLinkInfo
, which includes the following information:- *
pszInterfaceName
- interface name - *
pszMacAddress
- interface hardware address specified in a colon-separated format (for example: “00:0c:29:99:a5:7b”) mtu
- maximum transmission unit (MTU)mode
- One of the following values:LINK_AUTO
- the specified interface is managed and configured by systemd network managerLINK_MANUAL
- systemd will not bring up or configure the specified interfaceLINK_MODE_UNKNOWN
- the link mode is unknown
state
- One of the following values:LINK_DOWN
- the link is being administratively down or has no carrier signalLINK_UP
- the link is configured up and has carrier signalLINK_STATE_UNKNOWN
- the link state is unknown
Returns
- success: 0
- failure: error code
IP Address Configuration APIs
The Photon OS 2.0 network manager C API enables you to manage IP addresses for interfaces that are managed by systemd network manager.
Structure Declarations
IP Address Mode
Description
Defines the IP address mode. One of the following values:
IPV4_ADDR_MODE_NONE
- no IPv4 address configured on the interfaceIPV4_ADDR_MODE_STATIC
- the interface is configured with a static IPv4 addressIPV4_ADDR_MODE_DHCP
- the interface is configured with a DHCP IPv4 address
Declaration
typedef enum _NET_IPV4_ADDR_MODE
{
IPV4_ADDR_MODE_NONE = 0,
IPV4_ADDR_MODE_STATIC,
IPV4_ADDR_MODE_DHCP,
IPV4_ADDR_MODE_MAX
} NET_IPV4_ADDR_MODE;
Address Type
Description
Defines the type of IP address. One of the following options:
STATIC_IPV4
- static IPv4 addressSTATIC_IPV6
- static IPv6 addressDHCP_IPV4
- DHCP IPv4 addressDHCP_IPV6
- DHCP IPv6 addressAUTO_IPV6
- stateless dynamic IPv6 addressLINK_LOCAL_IPV6
- link local IPv6 address
Declaration
typedef enum _NET_ADDR_TYPE
{
STATIC_IPV4 = 0x00000001,
STATIC_IPV6 = 0x00000002,
DHCP_IPV4 = 0x00000010,
DHCP_IPV6 = 0x00000020,
AUTO_IPV6 = 0x00000040,
LINK_LOCAL_IPV6 = 0x00000080,
} NET_ADDR_TYPE;
IP Addresses
Description
Defines IP addresses.
pszInterfaceName
- interface nametype
- address typepszIPAddrPrefix
- IP address
Declarations
typedef struct _NET_IP_ADDR
{
char \*pszInterfaceName;
NET_ADDR_TYPE type;
char \*pszIPAddrPrefix;
} NET_IP_ADDR, \*PNET_IP_ADDR;
nm_set_ipv4_addr_gateway
Description
Set the IPv4 address and (optionally) the default gateway address for the interface.
Declaration
uint32_t
nm_set_ipv4_addr_gateway(
const char \*pszInterfaceName,
NET_IPV4_ADDR_MODE mode,
const char \*pszIPv4AddrPrefix,
const char \*pszIPv4Gateway
);
Arguments
pszInterfaceName
- interface namemode
- IP address mode; one of the following values:IPV4_ADDR_MODE_NONE
IPV4_ADDR_MODE_STATIC
IPV4_ADDR_MODE_DHCP
pszIPv4AddrPrefix
- IPv4 address specified in dot-decimal / prefix notation (for example, 10.10.10.101/23). If the prefix is not specified, then a /32 prefix is assumed.pszIPv4Gateway
- IPv4 gateway (optional) specified in the dot-decimal format (for example,10.10.20.30).
Returns
- success: 0
- failure: error code
nm_get_ipv4_addr_gateway
Description
Get the IPv4 address and the default gateway address for the interface.
Declaration
uint32_t
nm_get_ipv4_addr_gateway(
const char \*pszInterfaceName,
NET_IPV4_ADDR_MODE \*pMode,
char \*\*ppszIPv4AddrPrefix,
char \*\*ppszIPv4Gateway
);
Arguments
pszInterfaceName
- interface namepmode
- IP mode; one of the following values:IPV4_ADDR_MODE_NONE
IPV4_ADDR_MODE_STATIC
IPV4_ADDR_MODE_DHCP
ppszIPv4AddrPrefix
- IPv4 address returned in dot-decimal / prefix notation (for example, 10.10.10.101/23). If the prefix is not specified, then a /32 prefix is assumed.ppszIPv4Gateway
- IPv4 gateway (optional) returned in the dot-decimal format (for example,10.10.10.250).
Returns
- success: 0
- failure: error code
nm_add_static_ipv6_addr
Description
Add an IPv6 address to the specified interface.
Declaration
uint32_t
nm_add_static_ipv6_addr(
const char \*pszInterfaceName,
const char \*pszIPv6AddrPrefix
);
Arguments
pszInterfaceName
- interface namepszIPv6AddrPrefix
- IPv6 address specified in the standard colon-separated IPv6 address format followed by the prefix (for example, 2010:a1:b2::25/64). If the not prefix is specified, then a /128 prefix is assumed.
Returns
- success: 0
- failure: error code
nm_delete_static_ipv6_addr
Description
Delete a static IPv6 address from the interface.
Declaration
uint32_t
nm_delete_static_ipv6_addr(
const char \*pszInterfaceName,
const char \*pszIPv6AddrPrefix
);
Arguments
pszInterfaceName
- interface namepszIPv6AddrPrefix
- IPv6 address specified in the standard colon-separated IPv6 address format followed by the prefix (for example, 2010:a1:b2::25/64). If the not prefix is specified, then a /128 prefix is assumed.
Returns
- success: 0
- failure: error code
nm_set_ipv6_addr_mode
Description
Set the mode for the interface.
Declaration
uint32_t
nm_set_ipv6_addr_mode(
const char \*pszInterfaceName,
uint32_t enableDhcp,
uint32_t enableAutoconf
);
Arguments
pszInterfaceName
- interface nameenableDhcp
- enable (1) or disable (0) DHCP; enabling configures the interface to acquire a DHCP IPv6 address.enableAutoconf
- enable (1) or disable (0) autoconf; enabling configures the interface to acquire a stateless autoconfiguration IPv6 address.
Returns
- success: 0
- failure: error code
nm_get_ipv6_addr_mode
Description
Get the mode for the interface.
Declaration
uint32_t
nm_get_ipv6_addr_mode(
const char \*pszInterfaceName,
uint32_t \*pDhcpEnabled,
uint32_t \*pAutoconfEnabled
);
Arguments
pszInterfaceName
- interface namepDhcpEnabled
- returns whether IPv6 DHCP is enabled (1) or disabled (0).pAutoconfEnabled
- returns whether IPv6 stateless autoconfiguration is enabled (1) or disabled (0).
Returns
- success: 0
- failure: error code
nm_get_ip_addr
Description
Get the IP address for the interface.
Declaration
uint32_t
nm_get_ip_addr(
const char \*pszInterfaceName,
uint32_t addrTypes,
size_t \*pCount,
NET_IP_ADDR \*\*\*pppIpAddrList
);
Arguments
pszInterfaceName
- interface nameaddrTypes
- type of IP address; one of the following values:STATIC_IPV4
STATIC_IPV6
DHCP_IPV4
DHCP_IPV6
AUTO_IPV6
LINK_LOCAL_IPV6
pCount
- number of IP address structures in the pppIpAddrList array returned by the API call.pppIpAddrList
- array of NET_IP_ADDR elements that includes the following:pszInterfaceName
type
pszIPAddrPrefix
Returns
- success: 0
- failure: error code
nm_set_ipv6_gateway
Description
Set the default IPv6 gateway for the interface.
Declaration
uint32_t
nm_set_ipv6_gateway(
const char \*pszInterfaceName,
const char \*pszIPv6Gateway
);
Arguments
pszInterfaceName
- interface namepszIPv6Gateway
- IPv6 gateway specified in the standard colon-separated IPv6 address format (for example, 2010:125::100)
Returns
- success: 0
- failure: error code
nm_get_ipv6_gateway
Description
Get the default IPv6 gateway for the interface.
Declaration
uint32_t
nm_get_ipv6_gateway(
const char \*pszInterfaceName,
char \*\*ppszIPv6Gateway
);
Arguments
pszInterfaceName
- interface nameppszIPv6Gateway
- IPv6 gateway specified in the standard colon-separated IPv6 address format (for example, 2010:125::100)
Returns
- success: 0
- failure: error code
Route Configuration APIs
The Photon OS 2.0 network manager C API enables you to manage static IP routes configuration.
Structure Declarations
Route Scope
Description
Defines the scope of a route. One of the following options.
GLOBAL_ROUTE
- route to a destination one or more hops awayLINK_ROUTE
- route to a destination on the local networkHOST_ROUTE
- route to a destination address on the local host
Declaration
typedef enum _NET_ROUTE_SCOPE
{
GLOBAL_ROUTE = 0,
LINK_ROUTE,
HOST_ROUTE,
NET_ROUTE_SCOPE_MAX
} NET_ROUTE_SCOPE;
IP Route
Description
Defines an IP route. Includes the following information:
pszInterfaceName
- interface through which the specified destination network can be reachedpszDestNetwork
- destination IP network reached by the specified routepszSourceNetwork
- source network for the specified routepszGateway
- IP gateway through which the specified destination network can be reachedscope
- scope of this route entry; one of the following values: GLOBAL_ROUTE, LINK_ROUTE, or HOST_ROUTE as defined abovemetric
- metric of this route, an unsigned integertable
- identifier for the route table to which this route belongs.
Declaration
typedef struct _NET_IP_ROUTE
{
char \*pszInterfaceName;
char \*pszDestNetwork;
char \*pszSourceNetwork;
char \*pszGateway;
NET_ROUTE_SCOPE scope;
uint32_t metric;
uint32_t table;
} NET_IP_ROUTE, \*PNET_IP_ROUTE;
nm_add_static_ip_route
Description
Add a static IP route.
Declaration
uint32_t
nm_add_static_ip_route(
NET_IP_ROUTE \*pRoute
);
Arguments
Returns
- success: 0
- failure: error code
nm_delete_static_ip_route
Description
Delete a static IP route.
Declaration
uint32_t
nm_delete_static_ip_route(
NET_IP_ROUTE \*pRoute
);
Arguments
Returns
- success: 0
- failure: error code
nm_get_static_ip_routes
Description
Get the static IP routes for an interface.
Declaration
uint32_t
nm_get_static_ip_routes(
const char \*pszInterfaceName,
size_t \*pCount,
NET_IP_ROUTE \*\*\*pppRouteList
);
Arguments
pszInterfaceName
- interface namepCount
- number of NET_IP_ROUTE elements returned in the pppRouteList array by the API call upon successpppRouteList
- array of static IP routes
Returns
- success: 0
- failure: error code
DNS Configuration APIs
The Photon OS 2.0 network manager C API enables you to manage the DNS and Domains configuration.
Structure Declarations
DNS Mode
Description
DNS mode. Any of the following values:
DNS_MODE_INVALID
- DNS mode is unknownSTATIC_DNS
- DNS servers are statically configuredDHCP_DNS
- DNS servers configuration is acquired from DHCP protocol.
Declaration
typedef enum _NET_DNS_MODE
{
DNS_MODE_INVALID = 0,
STATIC_DNS,
DHCP_DNS,
DNS_MODE_MAX,
} NET_DNS_MODE;
nm_set_dns_servers
Description
Set the DNS servers list for the interface.
Declaration
uint32_t
nm_set_dns_servers(
const char \*pszInterfaceName,
NET_DNS_MODE mode,
size_t count,
const char \*\*ppszDnsServers
);
Arguments
pszInterfaceName
- interface name (optional, can be NULL)mode
- DNS mode. One of the following values:DNS_MODE_INVALID
= 0DNS_MODE_MA
DHCP_DNS
STATIC_DNS
count
- number of NUL terminated DNS server entries passed in the ppszDnsServers array to the API call (for example, 10.10.10.200 or 2020::40)ppszDnsServers
- array of DNS servers
Returns
- success: 0
- failure: error code
nm_add_dns_server
Description
Add a server to the DNS servers list associated with an interface.
Declaration
uint32_t
nm_add_dns_server(
const char \*pszInterfaceName,
const char \*pszDnsServer
);
Arguments
pszInterfaceName
- interface name (optional, can be NULL)ppszDnsServer
- server to add to the DNS server list
Returns
- success: 0
- failure: error code
nm_delete_dns_server
Description
Delete a server from the DNS servers list associated with an interface.
Declaration
uint32_t
nm_delete_dns_server(
const char \*pszInterfaceName,
const char \*pszDnsServer
);
Arguments
pszInterfaceName
- interface name (optional, can be NULL)ppszDnsServer
- server to remove from the DNS server list
Returns
- success: 0
- failure: error code
nm_get_dns_servers
Description
Get the the DNS servers list for the interface.
Declaration
uint32_t
nm_get_dns_servers(
const char \*pszInterfaceName,
NET_DNS_MODE \*pMode,
size_t \*pCount,
char \*\*\*pppszDnsServers
);
Arguments
pszInterfaceName
- interface name (optional, can be NULL)pMode
- DNS mode. One of the following values:DNS_MODE_INVALID
DHCP_DNS
STATIC_DNS
pCount
- number of NUL terminated DNS server entries in the pppszDnsServers array returned by the API call (for example, 10.10.10.200 or 2020::40)pppszDnsServers
- array of DNS servers
Returns
- success: 0
- failure: error code
nm_set_dns_domains
Description
Set the DNS domain list.
Declaration
uint32_t
nm_set_dns_domains(
const char \*pszInterfaceName,
size_t count,
const char \*\*ppszDnsDomains
);
Arguments
pszInterfaceName
- interface name (optional, can be NULL)count
- number of DNS domains specified in the ppszDnsDomains array to the API call (for example, if count = 2, then there are two elements: ppszDnsDomains[0] and ppszDnsDomains[1])ppszDnsDomains
- array of DNS domains
Returns
- success: 0
- failure: error code
nm_add_dns_domain
Description
Add a DNS domain to the DNS domain list.
Declaration
uint32_t
nm_add_dns_domain(
const char \*pszInterfaceName,
const char \*pszDnsDomain
);
Arguments
pszInterfaceName
- interface name (optional, can be NULL)pszDnsDomain
- DNS domain to add to the list
Returns
- success: 0
- failure: error code
nm_delete_dns_domain
Description
Delete a DNS domain from the DNS domain list.
Declaration
uint32_t
nm_delete_dns_domain(
const char \*pszInterfaceName,
const char \*pszDnsDomain
);
Arguments
pszInterfaceName
- interface name (optional, can be NULL)pszDnsDomain
- DNS domain to remove from the list
Returns
- success: 0
- failure: error code
nm_get_dns_domains
Description
Get the list of DNS domains.
Declaration
uint32_t
nm_get_dns_domains(
const char \*pszInterfaceName,
size_t \*pCount,
char \*\*\*pppszDnsDomains
);
Arguments
pszInterfaceName
- interface name (optional, can be NULL)pCount
- number of DNS domains returned in the pppszDnsDomains from the API call (for example, if count = 2, then there are two elements: ppszDnsDomains[0] and ppszDnsDomains[1])pppszDnsDomains
- array of DNS domains
Returns
- success: 0
- failure: error code
DHCP Options DUID and IAID Configuration APIs
The Photon OS 2.0 network manager C API enables you to manage DHCP DUID and Interface IAID.
nm_set_iaid
Description
Set the IAID for the interface.
Declaration
uint32_t
nm_set_iaid(
const char \*pszInterfaceName,
uint32_t iaid
);
Arguments
pszInterfaceName
- interface nameiaid
- interface association identifier (IAID)
Returns
- success: 0
- failure: error code
nm_get_iaid
Description
Get the IAID for the interface.
Declaration
uint32_t
nm_get_iaid(
const char \*pszInterfaceName,
uint32_t \*pIaid
);
Arguments
pszInterfaceName
- interface namepIaid
- interface association identifier (IAID)
Returns
- success: 0
- failure: error code
nm_set_duid
Description
Set the DUID for the interface.
Declaration
uint32_t
nm_set_duid(
const char \*pszInterfaceName,
const char \*pszDuid
);
Arguments
pszInterfaceName
- interface name (optional, specify NULL to set system global DUID configuration)pszDuid
- DHCP unique identifier (DUID)
Returns
- success: 0
- failure: error code
nm_get_duid
Description
Get the DUID for the interface.
Declaration
uint32_t
nm_get_duid(
const char \*pszInterfaceName,
char \*\*ppszDuid
);
Arguments
pszInterfaceName
- interface name (optional, specify NULL to query system global DUID configuration)ppszDuid
- DHCP unique identifier (DUID)
Returns
- success: 0
- failure: error code
NTP Configuration APIs
The Photon OS 2.0 network manager C API enables you to manage NTP servers configured for the system.
nm_set_ntp_servers
Description
Set the list of NTP servers.
Declaration
uint32_t
nm_set_ntp_servers(
size_t count,
const char \*\*ppszNtpServers
);
Arguments
count
- number of NTP servers in the ppszNtpServers array passed to the API call.ppszNtpServers
- array of NTP servers
Returns
- success: 0
- failure: error code
nm_add_ntp_servers
Description
Add a server to the NTP servers list.
Declaration
uint32_t
nm_add_ntp_servers(
size_t count,
const char \*\*ppszNtpServers
);
Arguments
count
- number of NTP servers to add (specified in the ppszNtpServers array) passed to the API call.ppszNtpServers
- array of NTP servers to add
Returns
- success: 0
- failure: error code
nm_delete_ntp_servers
Description
Delete a server from the NTP servers list.
Declaration
uint32_t
nm_delete_ntp_servers(
size_t count,
const char \*\*ppszNtpServers
);
Arguments
count
- number of NTP servers to delete (specified in the ppszNtpServers array) passed to the API callppszNtpServers
- array of NTP servers to delete
Returns
- success: 0
- failure: error code
nm_get_ntp_servers
Description
Get the NTP servers list.
Declaration
uint32_t
nm_get_ntp_servers(
size_t \*pCount,
char \*\*\*pppszNtpServers
);
Arguments
pCount
- number of NTP servers in the pppszNtpServers array returned from the API callpppszNtpServers
- array of NTP servers
Returns
- success: 0
- failure: error code
Other APIs
nm_set_hostname
Description
Set the host name for the system.
Declaration
uint32_t
nm_set_hostname(
const char \*pszHostname
);
Arguments
Returns
- success: 0
- failure: error code
nm_get_hostname
Description
Get the host name for the system.
Declaration
uint32_t
nm_get_hostname(
char \*\*ppszHostname
);
Arguments
Returns
- success: 0
- failure: error code
nm_wait_for_link_up
Description
Wait for the specified interface to come up.
Declaration
uint32_t
nm_wait_for_link_up(
const char \*pszInterfaceName,
uint32_t timeout
);
Arguments
pszInterfaceName
- interface nametimeout
- maximum time (in seconds) to wait (until the link is up) before timing out of the request; specify 0 for no timeout (wait indefinitely)
Returns
- success: 0
- failure: error code
nm_wait_for_ip
Description
Wait for the interface to acquire an IP address of the specified IP address type.
Declaration
uint32_t
nm_wait_for_ip(
const char \*pszInterfaceName,
uint32_t timeout,
NET_ADDR_TYPE addrTypes
);
Arguments
pszInterfaceName
- interface nametimeout
- maximum time (in seconds) to wait (until the link has an IP address of the specified address type) before timing out of the request; specify 0 for no timeout (wait indefinitely)addrTypes
- type of IP address; one of the following values:STATIC_IPV4
STATIC_IPV6
DHCP_IPV4
DHCP_IPV6
AUTO_IPV6
LINK_LOCAL_IPV6
Returns
- success: 0
- failure: error code
nm_set_network_param
Description
Set the value of a network parameter for an object.
Declaration
uint32_t
nm_set_network_param(
const char \*pszObjectName,
const char \*pszParamName,
const char \*pszParamValue
);
Arguments
pszObjectName
- an interface name (for example, “eth0”) or a file name (for example, /etc/systemd/resolved.conf)pszParamName
- name of a parameter associated with the object; specified in the format SectionName_KeyName (for example, Link_MTUBytes represents the MtuBytes key in [Link] section in https://www.freedesktop.org/software/systemd/man/systemd.network.html)pszParamValue
- points to the parameter value to set; you can add (+) or remove (-) a parameter by prepending the parameter name with + or -. For example:
netmgr net_info –set –object eth1 –paramname +Network_Address –paramvalue “10.10.10.1/24”
Returns
- success: 0
- failure: error code
nm_get_network_param
Description
Get the value of a network parameter associated with an object.
Declaration
uint32_t
nm_get_network_param(
const char \*pszObjectName,
const char \*pszParamName,
char \*\*ppszParamValue
);
Arguments
pszObjectName
- an interface name (for example, “eth0”) or a file name (for example, /etc/systemd/resolved.conf)pszParamName
- name of a parameter associated with the object; returned in the format SectionName_KeyName (for example, Link_MTUBytes represents the MtuBytes key in [Link] section in https://www.freedesktop.org/software/systemd/man/systemd.network.html)ppszParamValue
- parameter value
Returns
- success: 0
- failure: error code
Service Management APIs
nm_stop_network_service
Description
Stop the network service.
Declaration
uint32_t
nm_stop_network_service();
Returns
- success: 0
- failure: error code
nm_restart_network_service
Description
Restart the network service.
Declaration
uint32_t
nm_restart_network_service();
Returns
- success: 0
- failure: error code
nm_stop_dns_service
Description
Stop the DNS service.
Declaration
uint32_t
nm_stop_dns_service();
Returns
- success: 0
- failure: error code
nm_restart_dns_service
Description
Restart the DNS service.
Declaration
uint32_t
nm_restart_dns_service();
Returns
- success: 0
- failure: error code
nm_stop_ntp_service
Description
Stop the NTP service.
Declaration
uint32_t
nm_stop_ntp_service();
Returns
- success: 0
- failure: error code
nm_restart_ntp_service
Description
Restart the NTP service.
Declaration
uint32_t
nm_restart_ntp_service();
Returns
- success: 0
- failure: error code
5.15 - Network Configuration Manager - Python API
Photon OS 2.0 provides a Python API for the Network Configuration Manager.
Setup Instructions
To set up and run the latest version of the Network Manager API for Python:
# tdnf install pmd pmd-python3
# systemctl start pmd
Initialization Steps
# python3
>>> import pmd
>>> net = pmd.server().net
Get Online Help
Get help for all commands.
>>> help(net)
Get help for a specific command.
>>> help(net.add_ntp_servers)
-in function add_ntp_servers:
add_ntp_servers(...) method of [server.net](http://server.net/) instance
net.add_ntp_servers(ntpservers = ["20.20.20.20", "25.30.40.70"])
adds ntp servers. returns success: 0, failure: exception.
(END)
get_system_network_info
Get network information details that are common to the entire system.
Syntax
net.get_system_network_info()
Returns
- details about the system network (DUID, DNS mode, DNS server list, DNS domain list, NTP server list)
Example
>>> system_network_info = netmgmt.get_system_network_info()
>>> print ( system_network_info)
[{DUID: 00:02:11:22:33:44:55:66:77:20, DNS Mode: (null), DNS ServerList: ['10.10.100.100', '20.20.200.10'], DNS domain list: [' [abcd.com](http://abcd.com)'], NTP ServerList: (null)}]
get_err_info
Get information about the specified error number.
Syntax
net.get_err_info(error = <error_number>)
Parameters
Here is the list of error numbers:
- 4097 - invalid parameter
- 4098 - not supported
- 4099 - out of memory
- 4100 - value not found
- 4101 - value exists
- 4102 - invalid interface
- 4103 - invalid mode
- 4104 - bad configuration file
- 4105 - write failed
- 4106 - timout
- 4107 - DCHP timeout
Returns
- success: 0
- failure: exception
Example
>> net.get_err_info(error = 4097)
'invalid parameter'
Interface Configuration
Use these commands to manage the configuration for a network interface.
get_link_info
Get the link info for the specified interface or for all interfaces (if no interface is specified).
Syntax
net.get_link_info(ifname = interface_name)
Parameters
ifname
- interface name (optional)
Returns
- success: link info
- failure: exception
get_link_macaddr
Get the MAC address for the specified interface or for all interfaces (if no interface is specified).
Syntax
net.get_link_macaddr(ifname = interface_name)
Parameters
ifname
- interface name (optional)
Returns
- success: MAC address
- failure: exception
get_link_mode
Get the link mode for the specified interface (auto or manual), or for all interfaces (if no interface is specified).
Syntax
net.get_link_mode(ifname = interface_name)
Parameters
ifname
- interface name (optional)
Returns
- success: link mode (auto, manual, or unknown)
- failure: exception
get_link_mtu
Get the MTU of the specified interface or for all interfaces (if no interface is specified).
Syntax
net.get_link_mtu(ifname = interface_name)
Parameters
ifname
- interface name (optional)
Returns
- success: link MTU
- failure: exception
get_link_state
Get the link state of the specified interface or for all interfaces (if no interface is specified).
Syntax
net.get_link_state(ifname = interface_name)
Parameters
ifname
- interface name (optional)
Returns
- success: link state (up, down, unknown)
- failure: exception
set_link_down
Bring down the specified interface.
Syntax
net.set_link_down(ifname = interface_name)
Parameters
Returns
- success: 0
- failure: exception
set_link_macaddr
Set the MAC address of the specified interface.
Syntax
net.set_link_macaddr(ifname = interface_name, macaddr = mac_address)
Parameters
ifname
- interface namemacaddr
= MAC address
Returns
- success: 0
- failure: exception
set_link_mode
Set the mode (auto or manual) of the specifed interface.
Syntax
net.set_link_mode(ifname = interface_name, link_mode = [auto, manual])
Parameters
ifname
- interface namelink_mode
- auto or manual
Returns
- success: 0
- failure: exception
set_link_mtu
Set the MTU for the specified interface.
Syntax
net.set_link_mtu(ifname = interface_name, mtu = mtu)
Parameters
ifname
- interface namemtu
- mtu
Returns
- success: 0
- failure: exception
set_link_state
Set the state (up or down) of the specified interface.
Syntax
net.set_link_state(ifname = interface_name, link_state = [down, up])
Parameters
ifname
- interface namelink_state
- down or up
Returns
- success: 0
- failure: exception
set_link_up
Brings up the specified interface.
Syntax
net.set_link_up(ifname = interface_name)
Parameters
ifname
- interface namelink_state
- down or up
Returns
- success: 0
- failure: exception
IP Address Configuration
Use these commands to manage IP address configuration for a network interface.
add_static_ipv6_addr
Add a static IPv6 address to the specified interface.
Syntax
net.add_static_ipv6_addr(ifname = interface_name, addr_prefix = ipv6address_prefix)
Parameters
ifname
- interface nameaddr_prefix
- IPv6 address prefix
Returns
- success: 0
- failure: exception
del_static_ipv6_addr
Delete a static IPv6 address from the specified interface.
Syntax
net.del_static_ipv6_addr(ifname = interface_name, addr_prefix = ipv6address_prefix)
Parameters
ifname
- interface nameaddr_prefix
- IPv6 address prefix
Returns
- success: 0
- failure: exception
get_ipv4_addr_gateway
Get the IPv4 address with the prefix and gateway for the specified interface.
Syntax
net.get_ipv4_addr_gateway(ifname = interface_name)
Parameters
Returns
- success: IPv4 address with the prefix and gateway
- failure: exception
get_ipv6_addr
Get the list of IPv6 addresses for the specified interface.
Syntax
net.get_ipv6_addr(ifname = interface_name)
Parameters
Returns
- success: IPv6 address list
- failure: exception
get_ipv6_addr_mode
Get the address mode for the specified interface to determine whether DHCPv6, autoconf are enabled or disabled.
Syntax
net.get_ipv6_addr_mode(ifname = interface_name)
Parameters
Returns
- Status for DHCPv6, autoconf (True=enabled, False=disabled)
- failure: exception
get_ipv6_gateway
Get the IPv6 gateway for the specified interface.
Syntax
net.get_ipv6_gateway(ifname = interface_name)
Parameters
Returns
- success: IPv6 gateway
- failure: exception
set_ipv4_addr_gateway
Set the IPv4 address with the prefix and gateway for the specified interface.
Syntax
net.get_ipv4_addr_gateway(ifname = interface_name, addr_mode = [dhcp, static, none], addr_prefix = ipv4addressprefix, gateway = ipv4gateway)
Parameters
ifname
- interface nameaddr_mode
- address mode - dhcp, static, or noneaddr_prefix
- IPv4 address or prefixgateway
- IPv4 gateway
Returns
- success: 0
- failure: exception
set_ipv6_addr_mode
Set the address mode for the specified interface.
Syntax
net.set_ipv6_addr_mode(ifname = interface_name, enable_dhcp = [True, False], enable_autoconf = [True, False])
Parameters
ifname
- interface nameenable_dhcp
- True to enable, False to disableenable_autoconf
- True to enable, False to disable
Returns
- success: 0
- failure: exception
set_ipv6_gateway
Set the IPv6 gateway for the specified interface.
Syntax
net.set_ipv6_gateway(ifname = interface_name, gateway = ipv6gateway)
Parameters
ifname
- interface namegateway
- IPv6 gateway
Returns
- success: 0
- failure: exception
DNS Configuration
Use these commands to manage DNS domains and servers for a network interface.
get_dns_domains
Get the list of DNS domains for the specified interface.
Syntax
net.get_dns_domains(ifname = interface_name)
Parameters
Returns
- success: list of DNS domains
- failure: exception
get_dns_servers
Get the list of DNS servers and the mode for the specified interface.
Syntax
net.get_dns_servers(ifname = interface_name)
Parameters
Returns
- success: list of DNS servers and mode
- failure: exception
set_dns_domains
Set the list of DNS domains for the specified interface.
Syntax
net.set_dns_domains(domains = ["domain1","domain2",...], ifname = interface_name)
Parameters
domains
- comma-separated list of one or more domainsifname
- interface name
Returns
- success: 0
- failure: exception
set_dns_servers
Set the list of DNS servers for the specified interface.
Syntax
net.set_dns_servers(dns_mode = [dhcp, static], servers = ["server1","server2", ...], ifname = interface_name)
Parameters
dns_mode
- dhcp or staticservers
- comma-separate list of one or more serversifname
- interface name
Returns
- success: 0
- failure: exception
DHCP Options DUID and IAID Configuration
get_link_iaid
Get the IAID for the specified interface.
Syntax
net.get_link_iaid(ifname = interface)
Parameters
Returns
- success: IAID
- failure: exception
set_link_iaid
Set the IAID for the specified interface.
Syntax
net.set_link_iaid(ifname = interface_name, iaid = <iaid>)
Parameters
ifname
- interface name- iaid - IAID
Returns
- success: 0
- failure: exception
get_dhcp_duid
Get the DCHP DUID.
Syntax
net.get_dhcp_duid(ifname = interface_name)
Parameters
ifname
- interface name (optional)
Returns
- success: DUID
- failure: exception
set_dhcp_duid
Set the DCHP DUID.
Syntax
net.set_dhcp_duid(ifname = interface_name duid = duid)
Parameters
ifname
- interface name (optional)duid
- DUID to set
Returns
- success: 0
- failure: exception
NTP Servers
Use these commands to manage the NTP servers list.
add_ntp_servers
Add one or more NTP servers to the NTP servers list.
Syntax
net.add_ntp_servers(ntpservers = ["server1", "server2", ...])
Parameters
ntpservers
- Comma-separated list of NTP servers to add to the list.
Returns
- success: 0
- failure: exception
del_ntp_servers
Remove one or more NTP servers from the NTP servers list.
Syntax
net.del_ntp_servers(ntpservers = ["server1", "server2", ...])
Parameters
ntpservers
- Comma-separated list of NTP servers to remove from the list.
Returns
- success: 0
- failure: exception
get_ntp_servers
Get the NTP servers list.
Syntax
net.get_ntp_servers()
Returns
- success: NTP servers list
- failure: exception
set_ntp_servers
Set the NTP servers list.
Syntax
net.set_ntp_servers(ntpservers = ["server1", "server2", ...])
Parameters
ntpservers
- Comma-separated list of NTP servers to set in the list.
Returns
- success: 0
- failure: exception
get_hostname
Get the host name.
Syntax
net.get_hostname()
Returns
- success: host name
- failure: exception
set_hostname
Set the host name.
Syntax
net.set_hostname(hostname)
Parameters
hostname
- name to assign to the host
Returns
- success: 0
- failure: exception
wait_for_ip
Wait for the specified interface to acquire a valid IP address of the specified IP address type.
Syntax
net.wait_for_ip(ifname = interface_name, timeout = timeout, addrtypes = [ipv4, ipv6, static_ipv4, static_ipv6, dhcp_ipv4, dhcp_ipv6, auto_ipv6, link_local_ipv6])
Parameters
ifname
- interface nametimeout
- maximum time (in seconds) to wait (until the link is up) before timing out of the request; specify 0 for no timeout (wait indefinitely)addrtypes
- one of the following address types: ipv4, ipv6, static_ipv4, static_ipv6, dhcp_ipv4, dhcp_ipv6, auto_ipv6, or link_local_ipv6
Returns
- success: 0 (when the link has an IP of the specified type)
- failure: exception (for example, timeout expired)
wait_for_link_up
Wait for the specified interface to come up.
Syntax
net.wait_for_link_up(ifname = interface_name, timeout = timeout)
Parameters
ifname
- interface nametimeout
- maximum time (in seconds) to wait (until the link is up) before timing out of the request; specify 0 for no timeout (wait indefinitely)
Returns
- success: 0 (when link is up)
- failure: exception (for example, timeout expired)
get_network_param
Get the specified network configuration parameter for the specified interface or filename.
Syntax
net.get_network_param(object = IfName or Filename, paramname = SectionName_KeyName)
Parameters
object
- an interface name (for example, "eth0") or a file name (for example, /etc/systemd/resolved.conf)paramname
- name of a parameter associated with the object; specified in the format SectionName_KeyName (for example, Link_MTUBytes represents the MtuBytes key in [Link] section in https://www.freedesktop.org/software/systemd/man/systemd.network.html)
Returns
- success: 0
- failure: exception
set_network_param
Set the value of a network configuration parameter for the specified interface or filename.
Syntax
net.set_network_param(object = interface_name or filename, paramname = SectionName_KeyName, paramvalue = key_value)
Parameters
object
- an interface name (for example, "eth0") or a file name (for example, /etc/systemd/resolved.conf)paramname
- name of a parameter associated with the object; specified in the format SectionName_KeyName (for example, Link_MTUBytes represents the MtuBytes key in [Link] section in https://www.freedesktop.org/software/systemd/man/systemd.network.html)
Returns
- success: 0
- failure: exception
5.16 -
Photon OS includes the following networking tools:
tcpdump. A networking tool that captures and analyzes packets on a network interface. tcpdump
is not available with the minimal version of Photon OS but available in the repository. The minimal version includes the iproute2
tools by default.
You can install tcpdump
and its accompanying package libpcap
, a C/C++ library for capturing network traffic, by using tdnf
:
tdnf install tcpdump
- **netcat**. A tool to send data over network connections with TCP or UDP. This tool is not included in either the minimal or the full version of Photon OS. But since `netcat` furnishes powerful options for analyzing, troubleshooting, and debugging network connections, you might want to install it. To install `netcat', run the following command:
```
tdnf install netcat
6 - Prioritize eth0 Route Over WLAN
You can prioritise the eth0 route over the WLAN route. Perform the following steps:
Modify the /etc/systemd/network/99-dhcp-en.network
file and add the following content:
[DHCP]
RouteMetric=512
Restart systemd-networkd
.
7 - Cloud-Init on Photon OS
The minimal and full versions of Photon OS include the cloud-init service as a built-in component. Cloud-init is a set of Python scripts that initialize cloud instances of Linux machines. The cloud-init scripts configure SSH keys and run commands to customize the machine without user interaction. The commands can set the root password, create a hostname, configure networking, write files to disk, upgrade packages, run custom scripts, and restart the system.
7.1 - Cloud-Init Overview
cloud-init
is a multi-distribution package that handles early initialization of a cloud instance.
In-depth documentation for cloud-init is available here:
https://cloudinit.readthedocs.org/en/latest/
Supported installations
Both the full version of and the minimal version of Photon OS support cloud-init.
Supported capabilities
Photon OS supports the following cloud-init capabilities:
- run commands: execute a list of commands with output to console.
- configure ssh keys: add an entry to ~/.ssh/authorized_keys for the configured user.
- install package: install additional packages on first boot.
- configure networking: update /etc/hosts, hostname, etc.
- write files: write arbitrary files to disk.
- add yum repository: add a yum repository to /etc/yum.repos.d.
- create groups and users: add groups and users to the system and set properties for them.
- run yum upgrade: upgrade all packages.
- reboot: reboot or power off when done with cloud-init.
Getting Started
The Amazon Machine Image of Photon OS has an ec2 datasource
turned on by default so an ec2
configuration is accepted.
However, for testing, the following methods provide ways to do cloud-init
with a standalone instance of Photon OS.
Using a Seed ISO
This will be using the nocloud
data source. In order to initialize the system in this way, an ISO file needs to be created with a meta-data file and an user-data file as shown below:
$ { echo instance-id: iid-local01; echo local-hostname: cloudimg; } > meta-data
$ printf "#cloud-config\nhostname: testhost\n" > user-data
$ genisoimage -output seed.iso -volid cidata -joliet -rock user-data meta-data
Attach the seed.iso
generated above to your machine and reboot for the init to take effect.
In this case, the hostname is set to testhost
.
Using a Seed Disk File
To init using local disk files, do the following:
mkdir /var/lib/cloud/seed/nocloud
cd /var/lib/cloud/seed/nocloud
$ { echo instance-id: iid-local01; echo local-hostname: cloudimg; } > meta-data
$ printf "#cloud-config\nhostname: testhost\n" > user-data
Reboot the machine and the hostname will be set to testhost
.
Frequencies
Cloud-init modules have predetermined frequencies. Based on the frequency setting, multiple runs will yield different results. For the scripts to always run, remove the instances
directory before rebooting.
rm -rf /var/lib/cloud/instances
Module Frequency Info
Name | Frequency |
---|
disable_ec2_metadata | Always |
users_groups | Instance |
write_files | Instance |
update_hostname | Always |
final_message | Always |
resolv_conf | Instance |
growpart | Always |
update_etc_hosts | Always |
power_state_change | Instance |
phone_home | Instance |
7.2 - Deploy Photon OS With `cloud-init`
You can deploy Photon OS with cloud-init
in the following ways:
- As a stand-alone Photon machine
- In Amazon Elastic Compute Cloud, called EC2
- In the Google cloud through the Google Compute Engine, or GCE
- In a VMware Vsphere private cloud
When a cloud instance of Photon OS starts, cloud-init
requires a data source. The data source can be an EC2 file for Amazon’s cloud platform, a seed.iso
file for a stand-alone instance of Photon OS, or the internal capabilities of a system for managing virtual machines, such as VMware vSphere or vCenter. Cloud-init also includes data sources for OpenStack, Apache CloudStack, and OVF. The data source comprises two parts:
- Metadata
- User data
The metadata gives the cloud service provider instructions on how to implement the Photon OS machine in the cloud infrastructure. Metadata typically includes the instance ID and the local host name.
The user data contains the commands and scripts that Photon OS executes when it starts in the cloud. The user data commonly takes the form of a shell script or a YAML file containing a cloud configuration. The cloud-init overview and cloud-init documentation contains information about the types of data sources and the formats for metadata and user data.
On Photon OS, cloud-init
is enabled and running by default. You can use the following command to check the status:
systemctl status cloud-init
The Photon OS directory that contains the local data and other resources for cloud-init is /var/lib/cloud
.
Photon OS stores the logs for cloud-init in the /var/log/cloud-init.log
file.
The following sections demonstrate how to use cloud-init to customize a stand-alone Photon OS machine, instantiate a Photon OS machine in the Amazon EC2 cloud, and deploy a virtual machine running Photon OS in vSphere. Each section uses a different combination of the available options for the metadata and the user data that make up the data source. Specifications, additional options, and examples appear in the cloud-init documentation.
7.3 - Customizing Guest OS using Cloud-Init
A guest operating system is an operating system that runs inside a virtual machine. You can install a guest operating system in a virtual machine and control guest operating system customization for virtual machines created from vApp templates.
When you customize your guest OS you can set up a virtual machine with the operating system that you want.
Procedure
- Perform the following steps before cloning or customizing the guest operating system:
- Ensure that
disable_vmware_customization
is set to false in the /etc/cloud/cloud.cfg
file. - Set
manage_etc_hosts: true
in the /etc/cloud/cloud.cfg
file. - Make a backup of the
99-disable-networking-config.cfg
file and delete the file from /etc/cloud/cloud.cfg.d
folder after backup. - Clone the VM or customize the guest operating system.
- After you clone your VM or customize the guest operating system, perform the following steps:
- Ensure that
disable_vmware_customization
is set to true in the /etc/cloud/cloud.cfg
file in the newly created VM and the VM from where cloning was initiated. - Remove
manage_etc_hosts: true
from the /etc/cloud/cloud.cfg
file in the newly created VM and the VM from where cloning was initiated. - Add a copy of the backed up file
99-disable-networking-config.cfg
to its original folder /etc/cloud/cloud.cfg.d
in the newly created VM and the VM from where cloning was initiated.
Note:
- The
disable_vmware_customization
flag in /etc/cloud/cloud.cfg.d
file decides which customization workflow to be initiated.
- Setting this to false invokes the Cloud-Init GOS customization workflow.
- Setting this to true invokes the traditional GOSC script based customization workflow.
When the manage_etc_hosts
flag is set to true, Cloud-Init can edit the /etc/hosts
file with the updated values.
When the flag is set to true Cloud-Init edits the /etc/hosts
file, even when there is no cloud config metadata available. Remove this entry once the Cloud-Init GOS customization is done, to stop Cloud-Init from editing /etc/hosts
file and set a fallback configuration.
The 99-disable-networking-config.cfg
file is packaged as part of Cloud-Init RPM in photon and it prevents Cloud-Init from configuring the network. Delete this file before starting the Cloud-Init customization and then paste the backup of the file in the /etc/cloud/cloud.cfg.d/
folder once the cloud-init workflow is complete. It is important to replace this file after Cloud-Init customization to avoid removal of network configuration in the Cloud-Init instance.
Result
Cloud-Init guest OS customization is now enabled.
7.4 - Creating a Stand-Alone Photon Machine With cloud-init
Cloud-init can customize a Photon OS virtual machine by using the nocloud
data source. The nocloud
data source bundles the cloud-init
metadata and user data into an ISO that acts as a seed when you boot the machine. The seed.iso
delivers the metadata and the user data without requiring a network connection.
Procedure
Create the metadata file with the following lines in the YAML format and name it meta-data
:
instance-id: iid-local01
local-hostname: cloudimg
Create the user data file with the following lines in YAML and name it user-data:
#cloud-config
hostname: testhost
packages:
- vim
Generate the ISO that will serve as the seed. The ISO must have the volume ID set to cidata
. In the following example, the ISO is generated on an Ubuntu 14.04 computer containing the files named meta-data
and user-data
in the local directory:
genisoimage -output seed.iso -volid cidata -joliet -rock user-data meta-data
The ISO now appears in the current directory:
```
steve@ubuntu:~$ ls
meta-data seed.iso user-data
Optionally, check the ISO that you generated on Ubuntu by transferring the ISO to the root directory of your Photon OS machine and then running the following command:
cloud-init --file seed.iso --debug init
After running the cloud-init
command above, check the cloud-init
log file:
more /var/log/cloud-init.log
Attach the ISO to the Photon OS virtual machine as a CD-ROM and reboot it so that the changes specified by seed.iso take effect. In this case, cloud-init
sets the hostname
and adds the vim
package.
7.5 - Customizing a Photon OS Machine on EC2
You can upload an ami
image of Photon OS to Amazon Elastic Compute Cloud (EC2) and customize the Photon OS machine by using cloud-init
with an EC2 data source. The Amazon machine image version of Photon OS is available as a free download on Packages URL at the location https://packages.vmware.com/photon/
.
The cloud-init
service is commonly used on EC2 to configure the cloud instance of a Linux image. On EC2, cloud-init
sets the .ssh/authorized_keys
file to let you log in with a private key from another computer, that is, a computer besides the workstation that you are already using to connect with the Amazon cloud.
Example
The cloud-config user-data file that appears in the following example contains abridged SSH authorized keys to show you how to set them.
Prerequisites
Procedure
- Upload the Photon OS
.ami
image to the Amazon cloud and configure it with cloud-init. The correct virtualization type for Photon OS is hvm
.
$ mkdir bundled
$ tar -zxvf ./photon-ami.tar.gz
$ ec2-bundle-image -c ec2-certificate.pem -k ec2-privatekey.pem -u <EC2 account id> --arch x86_64 --image photon-ami.raw --destination ./bundled/
$ aws s3 mb s3://<bucket-name>
$ ec2-upload-bundle --manifest ./bundled/photon-ami.manifest.xml --bucket <bucket-name> --access-key <Account Access Key> --secret-key <Account Secret key>
$ ec2-register <bucket-name>/photon-ami.manifest.xml --name photon-ami --architecture x86_64 --virtualization-type hvm
- Import the cloud-config data. In the following command, the
--user-data-file
option instructs cloud-init to import the cloud-config data in user-data.txt
. The command assumes you have uploaded the user-data.txt file
and created the keypair mykeypair
and the security group photon-sg
.
$ ec2-run-instances <ami-ID> --instance-type m3.medium -g photon-sg --key mykeypair --user-data-file user-data.txt
Describe the instance to see its ID:
$ ec2-describe-instances
- Run the following command to obtain its public IP address, which you can use to connect to the instance with SSH:
$ aws ec2 describe-instances --instance-ids <instance-id> --query 'Reservations[*].Instances[*].PublicIpAddress' --output=text
$ ec2-describe-images
- Run the following commands to terminate the machine. It is important to shut down the machine because Amazon charges you while the host is running down.
$ ec2-deregister <ami-image-identifier>
$ ec2-terminate-instances <instance-id>
Result
The following are the contents of the user-data.txt
file that cloud-init
applies to the machine the first time that it boots up in the cloud:
#cloud-config
hostname: photon-on-01
groups:
- cloud-admins
- cloud-users
users:
- default
- name: photonadmin
gecos: photon test admin user
primary-group: cloud-admins
groups: cloud-users
lock-passwd: false
passwd: vmware
- name: photonuser
gecos: photon test user
primary-group: cloud-users
groups: users
passwd: vmware
packages:
- vim
ssh_authorized_keys:
- ssh-rsa MIIEogIBAAKCAQEAuvHKAjBhpwuomcUTpIzJWRJAe71JyBgAWrwqyN1Mk5N+c9X5
Ru2fazFA7WxQSD1KyTEvcuf8JzdBfrEJ0v3/nT2x63pvJ8fCl6HRkZtHo8zRu8vY
KYTZS/sdvM/ruubHfq1ldRpgtYSqbkykoe6PCQIDAQABAoIBAEgveQtjVzHDhLTr
rmwJmO316ERfkQ/chLaElhi9qwYJG/jqlNIISWFyztqD1b3fxU6m5MOBIujh7Xpg
... ec3test@example.com
You can view the cloud-init output log file on EC2 at /var/log/cloud-init-output.log
.
For more information on using cloud-init user data on EC2, see Running Commands on Your Linux Instance at Launch.
For more information on how to get Photon OS up and running on EC2 and run a containerized application in the Docker engine, see Running Photon OS on Amazon Elastic Cloud Compute.
With Photon OS, you can also build cloud images on Google Compute Engine and other cloud providers. For more information, see Compatible Cloud Images.
7.6 - Running a Photon OS Machine on GCE
Photon OS comes in a preconfigured image ready for Google Cloud Engine.
Example
The example in this section shows how to create a Photon OS instance on Google Cloud Engine with and without cloud-init user data.
Prerequisites
- You must have set up a GCE account and are ready to pay Google for its cloud services. The GCE-ready version of Photon OS is licensed as described in the Photon OS LICENSE guide. GCE and other environment-specific Packages are stored in the open using the following URL pattern:
https://packages.vmware.com/photon/<release>/<revision>/gce
For example, the current GA revision of the 4.0 release would be located at the following URL: https://packages.vmware.com/photon/4.0/GA/gce/, and the 3.0 GA version would be located at: https://packages.vmware.com/photon/3.0/GA/gce/.
The GCE-ready image of Photon OS contains packages and scripts that prepare it for the Google cloud to save you time as you implement a compute cluster or develop cloud applications. The GCE-ready version of Photon OS adds the following packages to the [packages installed with the minimal version](https://github.com/vmware/photon/blob/master/common/data/packages_minimal.json):
```
sudo, tar, which, google-daemon, google-startup-scripts,
kubernetes, perl-DBD-SQLite, perl-DBIx-Simple, perl, ntp
- Verify that you have the `gcloud command-line tool`.
For more information see, [https://cloud.google.com/compute/docs/gcloud-compute](https://cloud.google.com/compute/docs/gcloud-compute).
### Procedure
1. Use the following commands to create an instance of Photon OS from the Photon GCE image without using cloud-init. In the commands, you must replace `<bucket-name>` with the name of your bucket and the path to the Photon GCE tar file.
```
$ gcloud compute instances list
$ gcloud compute images list
$ gcloud config list
$ gsutil mb gs://<bucket-name>
$ gsutil cp <path-to-photon-gce-image.tar.gz> gs://<bucket-name>/photon-gce.tar.gz
$ gcloud compute images create photon-gce-image --source-uri gs://<bucket-name>/photon-gce.tar.gz
$ gcloud compute instances create photon-gce-vm --machine-type "n1-standard-1" --image photon-gce-image
$ gcloud compute instances describe photon-gce-vm
To create a new instance of a Photon OS machine and configure it with a cloud-init user data file, replace the gcloud compute instances create
command in the example above with the following command. Before running this command, you must upload your user-data file to Google’s cloud infrastructure and replace <path-to-userdata-file>
with its path and file name.
gcloud compute instances create photon-gce-vm --machine-type "n1-standard-1" --image photon-gce-vm --metadata-from-file=user-data=<path-to-userdata-file>
You can also add a cloud-init user-data file to an existing instance of a Photon OS machine on GCE:
```
gcloud compute instances add-metadata photon-gce-vm --metadata-from-file=user-data=<path-to-userdata-file>
8 - Containers
A container is a process that runs on the Photon OS host with its own isolated application, file system, and networking.
Photon OS includes the open source version of Docker. With Docker, Photon OS becomes a Linux run-time host for containers, that is, a Linux cloud container.
The full version of Photon OS includes Kubernetes so you can manage clusters of containers.
8.1 - Docker Containers
On Photon OS, the Docker daemon is enabled by default. To view the status of the daemon, run the following command:
systemctl status docker
Docker is loaded and running by default on the full version of Photon OS. On the minimal version, it is loaded but not running by default. To start it, run the following command:
systemctl start docker
To obtain information about Docker, run the following command as root:
docker info
After Docker is enabled and started, you can create a container. For example, run the following docker command as root to create a container running Ubuntu 14.04 with an interactive terminal shell:
docker run -i -t ubuntu:14.04 /bin/bash
Photon OS also enables you to run a docker container that runs Photon OS:
docker run -i -t photon /bin/bash
8.2 - Kubernetes
The Kubernetes package provides several services: kube-apiserver, kube-scheduler, kube-controller-manager, kubelet, kube-proxy. These services are managed by systemd
. Their configuration resides in a central location: /etc/kubernetes
.
For more information, see Running Kubernetes on Photon OS.
9 - Changing the Locale
You can change the locale if the default locale does not meet your requirements.
To find the locale, run the the localectl
command:
localectl
System Locale: LANG=en_US.UTF-8
VC Keymap: n/a
X11 Layout: n/a
To change the locale, choose the languages that you want from /usr/share/locale/locale.alias
, add them to /etc/locale-gen.conf
, and then regenerate the locale list by running the following command as root:
locale-gen.sh
Finally, run the following command to set the new locale, replacing the example (en_US.UTF-8
) with the locale that you require:
localectl set-locale LANG="de_CH.UTF-8" LC_CTYPE="de_CH.UTF-8"
Changing the keyboard layout
See which keymaps are currently available on your system:
localectl list-keymaps
If the response to that command is the all-too-common Couldn't find any console keymaps
, install the key tables files and utilities:
tdnf install kbd
You should now be able to find a keymap matching your keyboard. As an example, here I’m searching for the German keyboard layout (so I’m expecting something with de
in the name) used in Switzerland:
localectl list-keymaps | grep de
...
de-latin1
de-latin1-nodeadkeys
de-mobii
de_CH-latin1
de_alt_UTF-8
...
de_CH-latin1
seems to be what we’re looking for, so change your current layout to that keymap:
localectl set-keymap de_CH-latin1
and confirm that the change has been made:
localectl
System Locale: LANG=de_CH.UTF-8
VC Keymap: de_CH-latin1
X11 Layout: n/a
10 - Security Policy
This section describes the security policy of Photon OS.
10.1 - Default Firewall Settings
The design of Photon OS emphasizes security. On the minimal and full versions of Photon OS, the default security policy turns on the firewall and drops packets from external interfaces and applications. As a result, you might need to add rules to iptables to permit forwarding, allow protocols like HTTP, and open ports. You must configure the firewall for your applications and requirements.
The default iptables on the full version have the following settings:
iptables --list
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
Chain FORWARD (policy DROP)
target prot opt source destination
Chain OUTPUT (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere
For more information on how to change the settings, see the man page for iptables.
Although the default iptables policy accepts SSH connections, the sshd
configuration file on the full version of Photon OS is set to reject SSH connections. See Permitting Root Login with SSH.
If you are unable to ping a Photon OS machine, check the firewall rules. To verify if the rules allow connectivity for the port and protocol, change the iptables
commands by using lsof
commands to see the processes listening on ports:
lsof -i -P -n
10.2 - Default Permissions and umask
The umask
on Photon OS is set to 0027
.
When you create a new file with the touch
command as root, the default on Photon OS is to set the permissions to 0640
–which translates to read-write
for user, read
for group, and no access for others. Here’s an example:
touch newfile.md
stat newfile.md
File: 'newfile.md'
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 801h/2049d Inode: 316454 Links: 1
Access: (0640/-rw-r-----) Uid: ( 0/ root) Gid: ( 0/ root)
When you create a directory as root, Photon OS sets the permissions to 0750
:
mkdir newdir
stat newdir
File: 'newdir'
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 801h/2049d Inode: 316455 Links: 2
Access: (0750/drwxr-x---) Uid: ( 0/ root) Gid: ( 0/ root)
Because the mkdir
command uses the umask to modify the permissions placed on newly created files or directories, you can see umask
at work in the permissions of the new directory. Its default permissions are set at 0750
after the umask subtracts 0027
from the full set of open permissions, 0777
.
Similarly, a new file begins as 0666
if you were to set umask to 0000
. But because umask is set by default to 0027
, a new file’s permissions are set to 0640
.
So be aware of the default permissions on the directories and files that you create. Some system services and applications might require permissions other than the default. The systemd
network service, for example, requires user-defined configuration files to be set to 644
, not the default of 640
. Thus, after you create a network configuration file with a .network
extension, you must run the chmod
command to set the new file’s mode bits to 644
. For example:
chmod 644 10-static-en.network
For more information on permissions, see the man pages for stat
, umask
, and acl
.
10.3 - Disabling TLS 1.0 to Improve Transport Layer Security
Photon OS includes GnuTLS to help secure the transport layer. GnuTLS is a library that implements the SSL and TLS protocols to secure communications.
On Photon OS, SSL 3.0, which contains a known vulnerability, is disabled by default.
However, TLS 1.0, which also contains known vulnerabilities, is enabled by default.
To turn off TLS 1.0, perform the following steps:
- Create a directory named
/etc/gnutls
. - In
/etc/gnutls
create a file named default-priorities
. - In the
default-priorities
file, specify GnuTLS priority strings that remove TLS 1.0 and SSL 3.0 but retain TLS 1.1 and TLS 1.2. - After adding a new
default-priorities
file or after modifying it, you must restart all applications, including SSH, with an open TLS session for the changes to take effect.
The following is an example of a default-priorities
file that contains GnuTLS priorities to disable TLS 1.0 and SSL 3.0:
cat /etc/gnutls/default-priorities
SYSTEM=NONE:!VERS-SSL3.0:!VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL
In this example, the priority string imposes system-specific policies. The NONE
keyword means that no algorithms, protocols, or compression methods are enabled, so that you can enable specific versions individually later in the string. The priority string then specifies that SSL version 3.0 and TLS version 1.0 be removed, as marked by the exclamation point. The priority string then enables, as marked by the plus sign, versions 1.1 and 1.2 of TLS. The cypher is AES-128-CBC. The key exchange is RSA. The MAC is SHA1. And the compression algorithm is COMP-NULL.
On Photon OS, you can verify the system-specific policies in the default-priorities
file as follows:
Concatenate the default-priorities
file to check its contents:
root@photon-rc [ ~ ]# cat /etc/gnutls/default-priorities
SYSTEM=NONE:!VERS-SSL3.0:!VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL
1. Run the following command to check the protocols that are enabled for the system:
```
root@photon-rc [ /etc/gnutls ]# gnutls-cli --priority @SYSTEM -l
Cipher suites for @SYSTEM
TLS_RSA_AES_128_CBC_SHA1 0x00, 0x2f SSL3.0
Certificate types: none
Protocols: VERS-TLS1.1, VERS-TLS1.2
Compression: COMP-NULL
Elliptic curves: none
PK-signatures: none
For information about the GnuTLS priority strings, see https://gnutls.org/manual/html_node/Priority-Strings.html.
For information about the vulnerability in SSL 3.0, see SSL 3.0 Protocol Vulnerability and POODLE Attack.
For information about the vulnerabilities in TLS 1.0, see Guidelines for the Selection, Configuration, and Use of Transport Layer Security (TLS) Implementations.
11 - Photon RPM OSTree: a simple guide
11.1 - Introduction
RPM-OSTree Overview
OSTree is a tool to manage bootable, immutable, versioned filesystem trees. Unlike traditional package managers like rpm or dpkg that know how to install, uninstall, configure packages, OSTree has no knowledge of the relationship between files. But when you add rpm capabilities on top of OSTree, it becomes RPM-OSTree, meaning a filetree replication system that is also package-aware.
The idea behind it is to use a client/server architecture to keep your Linux installed machines (physical or VM) in sync with the latest bits, in a predictable and reliable manner. To achieve that, OSTree uses a git-like repository that records the changes to any file and replicate them to any subscriber.
A system administrator or an image builder developer takes a base Linux image, prepares the packages and other configuration on a server box, executes a command to compose a filetree that the host machines will download and then incrementally upgrade whenever a new change has been committed.
You may read more about OSTree here.
Why use RPM-OSTree in Photon?
There are several important benefits:
- Reliable, efficient: The filetree replication is simple, reliable and efficient. It will only transfer deltas over the network. If you have deployed two almost identical bootable images on same box (differing just by several files), it will not take twice the space. The new tree will have a set of hardlinks to the old tree and only the different files will have a separate copy stored to disk.
- Atomic: the filetree replication is atomic. At the end of a deployment, you are either booting from one deployment, or the other. There is no “partial deployed bootable image”. If anything bad happens during replication or deployment- power loss, network failure, your machine boots from the old image. There is even a tool option to cleanup old deployed (successfully or not) image.
- Manageable: You are provided simple tools to figure out exactly what packages have been installed, to compare files, configuration and package changes between versions.
- Predictable, repeatable: A big headache for a system administrator is to maintain a farm of computers with different packages, files and configuration installed in different order, that will result in exponential set of test cases. With RPM-OStree, you get identical, predictable installed systems.
As drawbacks, I would mention:
- Some applications configured by user on host may have compatibility issues if they save configuration or download into read only directories like /usr.
- People not used with “read only” file systems will be disappointed that they could no longer use RPM, yum, tdnf to install whatever they want. Think of this as an “enterprise policy”. They may circumvent this by customizing the target directory to a writable directory like /var or using rpm to install packages and record them using a new RPM repository in a writable place.
- Administrators need to be aware about the directories re-mapping specific to OSTree and plan accordingly.
Photon with RPM-OSTree installation profiles
Photon takes advantage of RPM-OSTree and offers several installation choices:
- Photon RPM-OSTree server - used to compose customized Photon OS installations and to prepare updates. I will call it for short ‘server’.
- Photon RPM-OSTree host connected to a default online server repository via http or https, maintained by VMware Photon OS team, where future updates will be published. This will create a minimal installation profile, but with the option to self-upgrade. I will call it for short ‘default host’.
- Photon RPM-OSTree host connected to a custom server repository. It requires a Photon RPM-OSTree Server installed in advance. I will call it for short ‘custom host’.
Terminology
In this section, the term OSTree refers to the general use of this technology, the format of the repository or replication protocol.
The term RPM-OSTree emphasizes the layer that adds RedHat Package Manager compatibility on both ends - at server and at host. However, since Photon OS is an RPM-based Linux, there are places in the documentation and even in the installer menus where OSTree may be used instead of RPM-OSTree when the distinction is not obvious or does not matter in that context.
When ostree
and rpm-ostree
are encountered, they refer to the usage of the specific Unix commands.
Finally, Photon RPM-OSTree is the application or implementation of the RPM-OStree system into Photon OS, materialized into two options: Photon Server and Photon Host (or client). Server or Host may be used with or without the Photon and/or RPM-OStree qualifier, but it means the same thing.
Sample code
Codes samples used throughout the book are small commands that can be typed at shell command prompt and do not require downloading additional files. As an alternative, one can remote connect via ssh, so cut & paste sample code from outside sources or copy files via scp will work. See the Photon Administration guide to learn how to enable ssh.
The samples assume that the following VMs have been installed - see the steps in the next chapters:
- A default host VM named photon-host-def.
- Two server VMs named photon-srv1 and photon-srv2.
- Two custom host VMs named photon-host-cus1 and photon-host-cus2, connected each to the corresponding server during install.
How to read this book
The RPM OSTree guide is structured to be used both as a sequential read and as a reference documentation.
If you are just interested in deploying a host system and keeping it up to date, then read Installing a Photon RPM-OSTree host against default server repository and Host updating operations.
If you want to install your own server and experiment with customizing packages for your Photon hosts, then read [Installing a Photon RPM-OSTree server](../creating-a-rpm-ostree-
server/) onwards. There are references to the concepts discussed throughout the book, if you need to understand them better.
However, if you want to read page by page, information is presented from simple to complex, although as with any technical book, we occasionally run into the chicken and egg problem - forward references to concepts that have yet to be explained later. In other cases, concepts are introduced and presented in great detail that may be seem hard to follow at first, but I promise they will make sense in the later pages when you get to use them.
RPM OSTree in Photon OS 3.0
This book is relevant to RPM OSTree in Photon OS 3.0.
Version 3.0 supports the following features:
- Upgrade
- Rollback
- Remote, compose, and rebase server
- Installation and uninstallation of packages with URL
- Installation and uninstallation of packages from default repos
- Automatic updates
11.2 - Installing a host against default server repository
RPM-OSTree Host default server repo installation option in Photon 3.0 will setup a profile similar to Photon Minimal, with the added benefit of being able to self-upgrade.
Who is this for?
The RPM-OSTree ‘default host’ is the easiest way to deploy a Photon RPM-OSTree host from ISO/cdrom, without the need to deploy and maintain an RPM-OSTree server. It is targeted at the user who relies on VMware Photon OS team to keep his or her system up-to-date, configured to get its updates from the official Photon 3.0 OSTree repository.
This is also the fastest way to install a host, as we’ve included in the ISO/cdrom an identical copy of the Photon 3.0 “starter” RPM-OSTree repository that is published online by VMware Photon OS team. So rather than pulling from the online repository, the installer pulls the repo from cdrom, which saves bandwidth and also reduces to zero the chances of failing due to a networking problem. After successful installation, any updates are going to be pulled from the official online repository, when Photon OS team will make them available.
Note: It is also possible to install an RPM-OSTree host against the official online repo via PXE boot, without the benefit of fast, local pull from cdrom. This will be covered in the PXE boot/kickstart chapter, as it requires additional configuration.
Installing the ISO
User will first download Photon OS ISO file that contains the installer, which is able to deploy any of the supported Photon installation profiles.
There are some steps common to all Photon installation profiles, starting with adding a VM in VMware Fusion, Workstation or ESXi, selecting the OS family, then customizing for disk size, CPU, memory size, network interface etc. (or leaving the defaults) and selecting the ISO image as cdrom. The installer will launch, that will go through disk partitioning and accepting the license agreement screens, followed by selecting an installation profile.
These steps are described at the page linked below, so I won’t repeat them, just that instead of setting up a Photon Minimal profile, we will install a Photon OSTree host:
Running Project Photon on Fusion.
Select the Photon OSTree Host option.
Continue with setting up a host name like photon1-def and a root password, re-confirm.
Then, select “Default OSTree Server” and continue.
When installation is over, the VM will reboot and will show in grub VMWare Photon/Linux 3.0_minimal (ostree), which will reassure that it’s booting from an OSTree image!
Boot, login and you are ready to use it.
To upgrade your host, see Host updating operations.
11.3 - Concepts in Action
Now that we have a fresh installed host (either as [[default|Photon-RPM-OSTree:-2-Installing-a-host-against-default-server-repository]] or [[custom|Photon-RPM-OSTree:-7-Installing-a-host-against-a-custom-server-repository]]), I can explain better the OStree concepts and see them in action.
Querying the deployed filetrees
The first thing to do is to run a command that tells us what is installed on the machine and when. Since it’s a fresh install from the CD, there is only one bootable filetree image deployed.
root@photon-host [ ~ ]# rpm-ostree status
* ostree://photon:photon/3.0/x86_64/minimal
Version: 3.0_minimal (2019-08-29T11:20:19Z)
Commit: a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650
Bootable filetree version
3.0_minimal is not the Linux Photon OS release version, nor daily build, but rather a human readable, self-incrementing version associated with every commit that brings file/package updates. Think of this as version 0. The following versions are going to be 3.0_minimal.1, 3.0_minimal.2, 3.0_minimal.3 and so on.
Commit ID
The ID listed is actually the first 5 bytes (10 hex digits) of the commit hash. If you want to see the verbose mode, use the -v
option.
root@photon-host [ ~ ]# rpm-ostree status -v
State: idle
AutomaticUpdates: disabled
Deployments:
* ostree://photon:photon/3.0/x86_64/minimal
Version: 3.0_minimal (2019-08-29T11:20:19Z)
Commit: a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650
`- photon (2019-08-29T11:18:53Z)
Staged: no
StateRoot: photon
RPM OStree Options
To see the list of options available with the rpm-ostree command, use the -h option.
root@photon-host [ ~ ]# rpm-ostree -h
Usage:
rpm-ostree [OPTION?] COMMAND
Builtin Commands:
compose Commands to compose a tree
cleanup Clear cached/pending data
db Commands to query the RPM database
deploy Deploy a specific commit
rebase Switch to a different tree
rollback Revert to the previously booted tree
status Get the version of the booted system
upgrade Perform a system upgrade
reload Reload configuration
usroverlay Apply a transient overlayfs to /usr
cancel Cancel an active transaction
initramfs Enable or disable local initramfs regeneration
install Overlay additional packages
uninstall Remove overlayed additional packages
override Manage base package overrides
reset Remove all mutations
refresh-md Generate rpm repo metadata
kargs Query or modify kernel arguments
Help Options:
-h, --help Show help options
Application Options:
--version Print version information and exit
OSname
The OS Name identifies the operating system installed. All bootable filetrees for the same OS will share the /var directory, in other words applications installed in one booted image into this directory will be available in all other images.
If a new set of images are created for a different OS, they will receive a fresh copy of /var that is not shared with the previous OS images for the initial OS. In other words, if a machine is dual boot for different operating systems, they will not share each other’s /var content, however they will still merge 3-way /etc.
Refspec
The Refspec is a branch inside the repo, expressed in a hierarchical way. In this case, it’s the default branch that will receive package updates for the Photon OS 1.0 Minimal installation profile on Intel platforms. There could be other branches in the future, for example photon/3.0/x86_64/full that will match the Full installation profile (full set of packages installed).
Think of Refspec as the head of the minimal branch (just like in git) at the origin repo. On the replicated, local repo at the host, minimal is a file that contains the latest commit ID known for that branch.
root@photon-host [ ~ ]# cat /ostree/repo/refs/remotes/photon/photon/3.0/x86_64/minimal
a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650
Why are there two ‘photon’ directory levels in the remotes path? The photon: prefix in the Refspec listed by rpm-ostree status
corresponds to the first photon directory in the remotes path and is actually the name given to the remote that the host is connected to, which points to an http or https URL. We’ll talk about remotes later, but for now think of it as a namespace qualifier. The second photon is part of the Refspec path itself.
Deployments
We’ve used so far rpm-ostree
. The same information can be obtained running an ostree
command:
root@photon-host [ ~ ]# ostree admin status
* photon a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650.0
Version: 3.0_minimal
origin refspec: photon:photon/3.0/x86_64/minimal
But where is this information stored? As you may have guessed, the local repo stores the heads of the deployed trees - the most recent commitment ID, just like Git does:
root@photon-host [ ~ ]# cat /ostree/repo/refs/heads/ostree/0/1/0
a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650
This also where this command that lists the references (local heads and remotes) takes its data from:
root@photon-host [ ~ ]# ostree refs
ostree/0/1/0
photon:photon/3.0/x86_64/minimal
Based on that, it could find the root of the deployment that it boots from. The actual filetree is deployed right here:
root@photon-host [ ~ ]# ls -l /ostree/deploy/photon/deploy/a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650.0
total 36
lrwxrwxrwx 2 root root 7 Sep 4 04:58 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Jan 1 1970 boot
drwxr-xr-x 2 root root 4096 Jan 1 1970 dev
drwxr-xr-x 34 root root 4096 Sep 4 05:00 etc
lrwxrwxrwx 2 root root 8 Sep 4 04:58 home -> var/home
lrwxrwxrwx 3 root root 7 Sep 4 04:58 lib -> usr/lib
lrwxrwxrwx 3 root root 7 Sep 4 04:58 lib64 -> usr/lib
lrwxrwxrwx 2 root root 9 Sep 4 04:58 media -> run/media
lrwxrwxrwx 2 root root 7 Sep 4 04:58 mnt -> var/mnt
lrwxrwxrwx 2 root root 7 Sep 4 04:58 opt -> var/opt
lrwxrwxrwx 2 root root 14 Sep 4 04:58 ostree -> sysroot/ostree
drwxr-xr-x 2 root root 4096 Jan 1 1970 proc
lrwxrwxrwx 2 root root 12 Sep 4 04:58 root -> var/roothome
drwxr-xr-x 2 root root 4096 Jan 1 1970 run
lrwxrwxrwx 2 root root 8 Sep 4 04:58 sbin -> usr/sbin
lrwxrwxrwx 2 root root 7 Sep 4 04:58 srv -> var/srv
drwxr-xr-x 2 root root 4096 Jan 1 1970 sys
drwxr-xr-x 2 root root 4096 Jan 1 1970 sysroot
lrwxrwxrwx 2 root root 11 Sep 4 04:58 tmp -> sysroot/tmp
drwxr-xr-x 10 root root 4096 Jan 1 1970 usr
drwxr-xr-x 8 root root 4096 Sep 4 04:59 var
So how is a deployment linked to a specific branch, originating from a remote repo? Well, there is a file next to the deployed filetree root directory with the same name and .origin suffix, that contains exactly this info:
root@photon-host [ ~ ]# cat /ostree/deploy/photon/deploy/a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84
f20833650.0.origin
[origin]
refspec=photon:photon/3.0/x86_64/minimal
Fast forwarding a bit, if there is a new deployment due to an upgrade or rebase, a new filetree will be added at the same level, and a new .origin file will tie it to the remote branch it originated from.
The photon directory in the path is the actual OSname. Multiple deployments of same OS will share a writable /var folder.
root@photon-host [ ~ ]# ls -l /ostree/deploy/photon/var/
total 52
drwxr-xr-x 4 root root 4096 Sep 4 05:00 cache
drwxr-xr-x 2 root root 4096 Sep 4 05:00 home
drwxr-xr-x 14 root root 4096 Sep 4 05:00 lib
drwxr-xr-x 2 root root 4096 Sep 4 05:00 local
lrwxrwxrwx 1 root root 11 Sep 4 04:59 lock -> ../run/lock
drwxr-xr-x 4 root root 4096 Sep 4 05:00 log
drwxr-xr-x 2 root root 4096 Sep 4 05:00 mail
drwxr-xr-x 2 root root 4096 Sep 4 05:00 mnt
drwxr-xr-x 4 root root 4096 Sep 4 05:00 opt
drwx------ 3 root root 4096 Sep 4 05:25 roothome
lrwxrwxrwx 1 root root 6 Sep 4 04:59 run -> ../run
drwxr-xr-x 2 root root 4096 Sep 4 05:00 spool
drwxr-xr-x 2 root root 4096 Sep 4 05:00 srv
drwxrwxrwt 5 root root 4096 Sep 4 05:34 tmp
drwxr-xr-x 11 root root 4096 Sep 4 05:00 usrlocal
11.4 - Querying For Commit File and Package Metadata
There are several ostree and rpm-ostree commands that list file or package data based on either the Commit ID, or Refspec. If Refspec is passed as a parameter, it’s the same as passing the most recent commit ID (head) for that branch.
Commit history
For a host that is freshly installed, there is only one commit in the history for the only branch.
root@photon-host [ ~ ]# ostree log photon/3.0/x86_64/minimal
commit a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650
ContentChecksum: e91261daf8d60074f334a7ebf81d3b930c3fc88c765f994f79ab2445296f03c5
Date: 2019-08-29 11:20:19 +0000
Version: 3.0_minimal
This commit has no parent; if there was an older commit, it would have been listed too. We can get the same listing (either nicely formatted or raw variant data) by passing the Commit ID. Just the first several hex digits will suffice to identify the commit ID. We can either request to be displayed in a pretty format, or raw - the actual C struct.
root@photon-host [ ~ ]# ostree log a31a
commit a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650
ContentChecksum: e91261daf8d60074f334a7ebf81d3b930c3fc88c765f994f79ab2445296f03c5
Date: 2019-08-29 11:20:19 +0000
Version: 3.0_minimal
root@photon-host [ ~ ]# ostree log a31a --raw
commit a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650
({'rpmostree.inputhash': <'a3e8f3f6ef6e93c2ed6ce9edd1e9e80c93a36ecda0fed0d78f607e6ec3179d04'>, 'rpmostree.rpmmd-repos': <[{'id': <'photon'>, 'timestamp': <uint64 1567077533>}]>, 'version': <'3.0_minimal'>, 'rpmostree.rpmdb.pkglist': <[('Linux-PAM', '0', '1.3.0', '1.ph3', 'x86_64'), ('attr', '0', '2.4.48', '1.ph3', 'x86_64'), ('autogen-libopts', '0', '5.18.16', '1.ph3', 'x86_64'), ('bash', '0', '4.4.18', '1.ph3', 'x86_64'), ('bc', '0', '1.07.1', '1.ph3', 'x86_64'), ('binutils', '0', '2.31.1', '6.ph3', 'x86_64'), ('bridge-utils', '0', '1.6', '1.ph3', 'x86_64'), ('bubblewrap', '0', '0.3.0', '2.ph3', 'x86_64'), ('bzip2', '0', '1.0.6', '10.ph3', 'x86_64'), ('bzip2-libs', '0', '1.0.6', '10.ph3', 'x86_64'), ('ca-certificates', '0', '20190521', '1.ph3', 'x86_64'), ('ca-certificates-pki', '0', '20190521', '1.ph3', 'x86_64'), ('coreutils', '0', '8.30', '1.ph3', 'x86_64'), ('cpio', '0', '2.12', '4.ph3', 'x86_64'), ('cracklib', '0', '2.9.6', '8.ph3', 'x86_64'), ('cracklib-dicts', '0', '2.9.6', '8.ph3', 'x86_64'), ('curl', '0', '7.61.1', '4.ph3', 'x86_64'), ('curl-libs', '0', '7.61.1', '4.ph3', 'x86_64'), ('dbus', '0', '1.13.6', '1.ph3', 'x86_64'), ('device-mapper', '0', '2.02.181', '1.ph3', 'x86_64'), ('device-mapper-libs', '0', '2.02.181', '1.ph3', 'x86_64'), ('docker', '0', '18.06.2', '3.ph3', 'x86_64'), ('dracut', '0', '048', '1.ph3', 'x86_64'), ('dracut-tools', '0', '048', '1.ph3', 'x86_64'), ('e2fsprogs-libs', '0', '1.44.3', '2.ph3', 'x86_64'), ('elfutils', '0', '0.176', '1.ph3', 'x86_64'), ('elfutils-libelf', '0', '0.176', '1.ph3', 'x86_64'), ('expat', '0', '2.2.6', '2.ph3', 'x86_64'), ('expat-libs', '0', '2.2.6', '2.ph3', 'x86_64'), ('file', '0', '5.34', '1.ph3', 'x86_64'), ('file-libs', '0', '5.34', '1.ph3', 'x86_64'), ('filesystem', '0', '1.1', '4.ph3', 'x86_64'), ('findutils', '0', '4.6.0', '5.ph3', 'x86_64'), ('flex', '0', '2.6.4', '2.ph3', 'x86_64'), ('fuse', '0', '2.9.7', '5.ph3', 'x86_64'), ('gc', '0', '8.0.0', '1.ph3', 'x86_64'), ('glib', '0', '2.58.0', '4.ph3', 'x86_64'), ('glib-networking', '0', '2.59.1', '2.ph3', 'x86_64'), ('glibc', '0', '2.28', '4.ph3', 'x86_64'), ('glibc-iconv', '0', '2.28', '4.ph3', 'x86_64'), ('gmp', '0', '6.1.2', '2.ph3', 'x86_64'), ('gnupg', '0', '2.2.17', '1.ph3', 'x86_64'), ('gnutls', '0', '3.6.3', '3.ph3', 'x86_64'), ('gobject-introspection', '0', '1.58.0', '2.ph3', 'x86_64'), ('gpgme', '0', '1.11.1', '2.ph3', 'x86_64'), ('grep', '0', '3.1', '1.ph3', 'x86_64'), ('grub2', '0', '2.02', '13.ph3', 'x86_64'), ('grub2-efi', '0', '2.02', '13.ph3', 'x86_64'), ('grub2-pc', '0', '2.02', '13.ph3', 'x86_64'), ('guile', '0', '2.0.13', '2.ph3', 'x86_64'), ('gzip', '0', '1.9', '1.ph3', 'x86_64'), ('iana-etc', '0', '2.30', '2.ph3', 'noarch'), ('icu', '0', '61.1', '1.ph3', 'x86_64'), ('iproute2', '0', '4.18.0', '2.ph3', 'x86_64'), ('iptables', '0', '1.8.3', '1.ph3', 'x86_64'), ('js', '0', '1.8.5', '2.ph3', 'x86_64'), ('json-c', '0', '0.13.1', '1.ph3', 'x86_64'), ('json-glib', '0', '1.4.4', '1.ph3', 'x86_64'), ('kmod', '0', '25', '1.ph3', 'x86_64'), ('krb5', '0', '1.17', '1.ph3', 'x86_64'), ('libapparmor', '0', '2.13', '7.ph3', 'x86_64'), ('libarchive', '0', '3.3.3', '3.ph3', 'x86_64'), ('libassuan', '0', '2.5.1', '1.ph3', 'x86_64'), ('libcap', '0', '2.25', '8.ph3', 'x86_64'), ('libdb', '0', '5.3.28', '2.ph3', 'x86_64'), ('libffi', '0', '3.2.1', '6.ph3', 'x86_64'), ('libgcc', '0', '7.3.0', '4.ph3', 'x86_64'), ('libgcrypt', '0', '1.8.3', '2.ph3', 'x86_64'), ('libgomp', '0', '7.3.0', '4.ph3', 'x86_64'), ('libgpg-error', '0', '1.32', '1.ph3', 'x86_64'), ('libgsystem', '0', '2015.2', '2.ph3', 'x86_64'), ('libksba', '0', '1.3.5', '1.ph3', 'x86_64'), ('libltdl', '0', '2.4.6', '3.ph3', 'x86_64'), ('libmodulemd', '0', '2.4.0', '1.ph3', 'x86_64'), ('libpsl', '0', '0.20.2', '1.ph3', 'x86_64'), ('librepo', '0', '1.10.2', '1.ph3', 'x86_64'), ('libseccomp', '0', '2.4.0', '1.ph3', 'x86_64'), ('libselinux', '0', '2.8', '1.ph3', 'x86_64'), ('libsepol', '0', '2.8', '1.ph3', 'x86_64'), ('libsolv', '0', '0.6.35', '1.ph3', 'x86_64'), ('libsoup', '0', '2.64.0', '2.ph3', 'x86_64'), ('libssh2', '0', '1.9.0', '1.ph3', 'x86_64'), ('libstdc++', '0', '7.3.0', '4.ph3', 'x86_64'), ('libtasn1', '0', '4.13', '1.ph3', 'x86_64'), ('libtool', '0', '2.4.6', '3.ph3', 'x86_64'), ('libunistring', '0', '0.9.10', '1.ph3', 'x86_64'), ('libxml2', '0', '2.9.9', '1.ph3', 'x86_64'), ('libyaml', '0', '0.2.1', '2.ph3', 'x86_64'), ('linux', '0', '4.19.65', '3.ph3', 'x86_64'), ('m4', '0', '1.4.18', '2.ph3', 'x86_64'), ('mpfr', '0', '4.0.1', '1.ph3', 'x86_64'), ('ncurses', '0', '6.1', '1.ph3', 'x86_64'), ('ncurses-libs', '0', '6.1', '1.ph3', 'x86_64'), ('ncurses-terminfo', '0', '6.1', '1.ph3', 'x86_64'), ('net-tools', '0', '1.60', '11.ph3', 'x86_64'), ('nettle', '0', '3.4', '1.ph3', 'x86_64'), ('npth', '0', '1.6', '1.ph3', 'x86_64'), ('nspr', '0', '4.21', '1.ph3', 'x86_64'), ('nss-altfiles', '0', '2.23.0', '1.ph3', 'x86_64'), ('nss-libs', '0', '3.44', '2.ph3', 'x86_64'), ('openssh', '0', '7.8p1', '5.ph3', 'x86_64'), ('openssh-clients', '0', '7.8p1', '5.ph3', 'x86_64'), ('openssh-server', '0', '7.8p1', '5.ph3', 'x86_64'), ('openssl', '0', '1.0.2s', '1.ph3', 'x86_64'), ('ostree', '0', '2019.2', '1.ph3', 'x86_64'), ('ostree-grub2', '0', '2019.2', '1.ph3', 'x86_64'), ('ostree-libs', '0', '2019.2', '1.ph3', 'x86_64'), ('pcre', '0', '8.42', '1.ph3', 'x86_64'), ('pcre-libs', '0', '8.42', '1.ph3', 'x86_64'), ('photon-release', '0', '3.0', '3.ph3', 'noarch'), ('photon-repos', '0', '3.0', '3.ph3', 'noarch'), ('pinentry', '0', '1.1.0', '1.ph3', 'x86_64'), ('pkg-config', '0', '0.29.2', '2.ph3', 'x86_64'), ('polkit', '0', '0.113', '5.ph3', 'x86_64'), ('popt', '0', '1.16', '5.ph3', 'x86_64'), ('procps-ng', '0', '3.3.15', '1.ph3', 'x86_64'), ('python3', '0', '3.7.3', '2.ph3', 'x86_64'), ('python3-libs', '0', '3.7.3', '2.ph3', 'x86_64'), ('readline', '0', '7.0', '2.ph3', 'x86_64'), ('rpm-libs', '0', '4.14.2', '4.ph3', 'x86_64'), ('rpm-ostree', '0', '2019.3', '1.ph3', 'x86_64'), ('sed', '0', '4.5', '1.ph3', 'x86_64'), ('shadow', '0', '4.6', '3.ph3', 'x86_64'), ('shadow-tools', '0', '4.6', '3.ph3', 'x86_64'), ('sqlite-libs', '0', '3.27.2', '3.ph3', 'x86_64'), ('systemd', '0', '239', '13.ph3', 'x86_64'), ('util-linux', '0', '2.32', '1.ph3', 'x86_64'), ('util-linux-libs', '0', '2.32', '1.ph3', 'x86_64'), ('vim', '0', '8.1.0388', '4.ph3', 'x86_64'), ('which', '0', '2.21', '5.ph3', 'x86_64'), ('xz', '0', '5.2.4', '1.ph3', 'x86_64'), ('xz-libs', '0', '5.2.4', '1.ph3', 'x86_64'), ('zchunk', '0', '1.1.1', '1.ph3', 'x86_64'), ('zchunk-libs', '0', '1.1.1', '1.ph3', 'x86_64'), ('zlib', '0', '1.2.11', '1.ph3', 'x86_64')]>}, @ay [], @a(say) [], '', '', uint64 1567077619, [byte 0x1e, 0x0a, 0x85, 0x20, 0xa8, 0xe0, 0x18, 0x6a, 0x88, 0x15, 0xc0, 0xd9, 0xb0, 0xab, 0xc9, 0x98, 0x94, 0xa1, 0xfb, 0x0a, 0x48, 0xdf, 0xa0, 0x73, 0x32, 0x02, 0x9a, 0xdf, 0x49, 0xed, 0x13, 0x8d], [byte 0x44, 0x6a, 0x0e, 0xf1, 0x1b, 0x7c, 0xc1, 0x67, 0xf3, 0xb6, 0x03, 0xe5, 0x85, 0xc7, 0xee, 0xee, 0xb6, 0x75, 0xfa, 0xa4, 0x12, 0xd5, 0xec, 0x73, 0xf6, 0x29, 0x88, 0xeb, 0x0b, 0x6c, 0x54, 0x88])
Listing file mappings
This command lists the file relations between the original source Linux Photon filetree and the deployed filetree. The normal columns include file type type (regular file, directory, link), permissions in chmod octal format, userID, groupID, file size, file name.
root@photon-host [ ~ ]# ostree ls photon/3.0/x86_64/minimal
d00755 0 0 0 /
l00777 0 0 0 /bin -> usr/bin
l00777 0 0 0 /home -> var/home
l00777 0 0 0 /lib -> usr/lib
l00777 0 0 0 /lib64 -> usr/lib
l00777 0 0 0 /media -> run/media
l00777 0 0 0 /mnt -> var/mnt
l00777 0 0 0 /opt -> var/opt
l00777 0 0 0 /ostree -> sysroot/ostree
l00777 0 0 0 /root -> var/roothome
l00777 0 0 0 /sbin -> usr/sbin
l00777 0 0 0 /srv -> var/srv
l00777 0 0 0 /tmp -> sysroot/tmp
d00755 0 0 0 /boot
d00755 0 0 0 /dev
d00755 0 0 0 /proc
d00755 0 0 0 /run
d00755 0 0 0 /sys
d00755 0 0 0 /sysroot
d00755 0 0 0 /usr
d00755 0 0 0 /var
Extra columns can be added like checksum (-C) and extended attributes (-X).
root@photon-host [ /usr/share/man/man1 ]# ostree ls photon/3.0/x86_64/minimal -C
d00755 0 0 0 1e0a8520a8e0186a8815c0d9b0abc99894a1fb0a48dfa07332029adf49ed138d 446a0ef11b7cc167f3b603e585c7eeeeb675faa412d5ec73f62988eb0b6c5488 /
l00777 0 0 0 389846c2702216e1367c8dfb68326a6b93ccf5703c89c93979052a9bf359608e /bin -> usr/bin
l00777 0 0 0 4344c10bf4931483f918496534f12ed9b50dc6a2cead35e3cd9dd898d6ac9414 /home -> var/home
l00777 0 0 0 f11902ca9d69a80df33918534a3e443251fd0aa7f94b76301e1f55e52aed29dd /lib -> usr/lib
l00777 0 0 0 f11902ca9d69a80df33918534a3e443251fd0aa7f94b76301e1f55e52aed29dd /lib64 -> usr/lib
l00777 0 0 0 75317a3df11447c470ffdd63dde045450ca97dfb2a97a0f3f6a21a5da66f737c /media -> run/media
l00777 0 0 0 97c55dbe24e8f3aecfd3f3e5b3f44646fccbb39799807d37a217e9c871da108b /mnt -> var/mnt
l00777 0 0 0 46b1abbd27a846a9257a8d8c9fc4b384ac0888bdb8ac0d6a2d5de72715bd5092 /opt -> var/opt
l00777 0 0 0 d37269e3f46023fd0275212473e07011894cdf4148cbf3fb5758a7e9471dad8e /ostree -> sysroot/ostree
l00777 0 0 0 6f800e74eed172661278d1e1f09e389a6504dcd3358618e1c1618f91f9d33601 /root -> var/roothome
l00777 0 0 0 e0bead7be9323b06bea05cb9b66eb151839989e3a4e5d1a93e09a36919e91818 /sbin -> usr/sbin
l00777 0 0 0 5d4250bba1ed300f793fa9769474351ee5cebd71e8339078af7ebfbe6256d9b5 /srv -> var/srv
l00777 0 0 0 364fbd62f91ca1e06eb7dbd50c93de8976f2cea633658e2dbe803ce6f7490c09 /tmp -> sysroot/tmp
d00755 0 0 0 6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d 446a0ef11b7cc167f3b603e585c7eeeeb675faa412d5ec73f62988eb0b6c5488 /boot
d00755 0 0 0 6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d 446a0ef11b7cc167f3b603e585c7eeeeb675faa412d5ec73f62988eb0b6c5488 /dev
d00755 0 0 0 6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d 446a0ef11b7cc167f3b603e585c7eeeeb675faa412d5ec73f62988eb0b6c5488 /proc
d00755 0 0 0 6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d 446a0ef11b7cc167f3b603e585c7eeeeb675faa412d5ec73f62988eb0b6c5488 /run
d00755 0 0 0 6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d 446a0ef11b7cc167f3b603e585c7eeeeb675faa412d5ec73f62988eb0b6c5488 /sys
d00755 0 0 0 6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d 446a0ef11b7cc167f3b603e585c7eeeeb675faa412d5ec73f62988eb0b6c5488 /sysroot
d00755 0 0 0 ef1c0980e0d77f64e7f250a3e48f0b24e9285fc0716b80520dac6f98c148324a 446a0ef11b7cc167f3b603e585c7eeeeb675faa412d5ec73f62988eb0b6c5488 /usr
d00755 0 0 0 a3a987e053ea5a116f1e75a31cd7557fc6e57a3ae09e64171d7fea17ef71ec3e 446a0ef11b7cc167f3b603e585c7eeeeb675faa412d5ec73f62988eb0b6c5488 /var
By default, only the top folders are listed, but -R will list recursively. Instead of listing over 10,000 files, let’s filter to just all files that contain ‘rpm-ostree’, ‘rpmostree’ or ‘RpmOstree’, that must belong to rpm-ostree package itself.
root@photon-host [ /usr/share/rpm-ostree ]# ostree ls photon/3.0/x86_64/minimal -R | grep -e '[Rr]pm-\?[Oo]stree'
-00755 0 0 749000 /usr/bin/rpm-ostree
d00755 0 0 0 /usr/bin/rpm-ostree-host
-00644 0 0 1069 /usr/bin/rpm-ostree-host/function.inc
-00755 0 0 10507 /usr/bin/rpm-ostree-host/mk-ostree-host.sh
-00644 0 0 209 /usr/etc/rpm-ostreed.conf
-00644 0 0 1530 /usr/etc/dbus-1/system.d/org.projectatomic.rpmostree1.conf
l00777 0 0 0 /usr/lib/librpmostree-1.so.1 -> librpmostree-1.so.1.0.0
-00755 0 0 5278496 /usr/lib/librpmostree-1.so.1.0.0
-00644 0 0 2312 /usr/lib/girepository-1.0/RpmOstree-1.0.typelib
-00755 0 0 22 /usr/lib/kernel/install.d/00-rpmostree-skip.install
d00755 0 0 0 /usr/lib/rpm-ostree
-00755 0 0 1640704 /usr/lib/rpm-ostree/libdnf.so.2
-00644 0 0 622 /usr/lib/rpm-ostree/rpm-ostree-0-integration.conf
d00755 0 0 0 /usr/lib/sysimage/rpm-ostree-base-db
-00644 0 0 544768 /usr/lib/sysimage/rpm-ostree-base-db/Basenames
-00644 0 0 8192 /usr/lib/sysimage/rpm-ostree-base-db/Conflictname
-00644 0 0 110592 /usr/lib/sysimage/rpm-ostree-base-db/Dirnames
-00644 0 0 8192 /usr/lib/sysimage/rpm-ostree-base-db/Enhancename
-00644 0 0 8192 /usr/lib/sysimage/rpm-ostree-base-db/Filetriggername
-00644 0 0 8192 /usr/lib/sysimage/rpm-ostree-base-db/Group
-00644 0 0 12288 /usr/lib/sysimage/rpm-ostree-base-db/Installtid
-00644 0 0 8192 /usr/lib/sysimage/rpm-ostree-base-db/Name
-00644 0 0 8192 /usr/lib/sysimage/rpm-ostree-base-db/Obsoletename
-00644 0 0 2625536 /usr/lib/sysimage/rpm-ostree-base-db/Packages
-00644 0 0 86016 /usr/lib/sysimage/rpm-ostree-base-db/Providename
-00644 0 0 8192 /usr/lib/sysimage/rpm-ostree-base-db/Recommendname
-00644 0 0 69632 /usr/lib/sysimage/rpm-ostree-base-db/Requirename
-00644 0 0 20480 /usr/lib/sysimage/rpm-ostree-base-db/Sha1header
-00644 0 0 16384 /usr/lib/sysimage/rpm-ostree-base-db/Sigmd5
-00644 0 0 8192 /usr/lib/sysimage/rpm-ostree-base-db/Suggestname
-00644 0 0 8192 /usr/lib/sysimage/rpm-ostree-base-db/Supplementname
-00644 0 0 8192 /usr/lib/sysimage/rpm-ostree-base-db/Transfiletriggername
-00644 0 0 8192 /usr/lib/sysimage/rpm-ostree-base-db/Triggername
-00644 0 0 263 /usr/lib/systemd/system/rpm-ostree-bootstatus.service
-00644 0 0 257 /usr/lib/systemd/system/rpm-ostreed-automatic.service
-00644 0 0 227 /usr/lib/systemd/system/rpm-ostreed-automatic.timer
-00644 0 0 272 /usr/lib/systemd/system/rpm-ostreed.service
-00644 0 0 102 /usr/lib/systemd/system-preset/40-rpm-ostree-auto.preset
-00644 0 0 622 /usr/lib/tmpfiles.d/rpm-ostree-0-integration.conf
-00644 0 0 1082 /usr/lib/tmpfiles.d/rpm-ostree-1-autovar.conf
-00755 0 0 53 /usr/libexec/rpm-ostreed
-00644 0 0 3049 /usr/share/bash-completion/completions/rpm-ostree
-00644 0 0 15997 /usr/share/dbus-1/interfaces/org.projectatomic.rpmostree1.xml
-00644 0 0 133 /usr/share/dbus-1/system-services/org.projectatomic.rpmostree1.service
-00644 0 0 6160 /usr/share/polkit-1/actions/org.projectatomic.rpmostree1.policy
d00755 0 0 0 /usr/share/rpm-ostree
-00644 0 0 1169 /usr/share/rpm-ostree/treefile.json
atomic is really an alias for rpm-ostree command. The last file treefile.json is not installed by the rpm-ostree package, it is actually downloaded from the server, as we will see in the next chapter. For now, let us notice “osname” : “photon”, “ref” : “photon/1.0/x86_64/minimal”, “automatic_version_prefix” : “1.0_minimal”, that matches what we have known so far, and also the “documentation” : false setting, that explains why there are no manual files installed for rpm-ostree, and in fact for any package.
root@photon-host [ /usr/share/rpm-ostree ]# ls -l /usr/share/man/man1
total 0
Listing configuration changes
To diff the current /etc configuration versus default /etc (from the base image), this command will show the Modified, Added and Deleted files:
root@photon-host [ ~ ]# ostree admin config-diff
M ssh/sshd_config
M machine-id
M fstab
M hosts
M mtab
M shadow
A ssh/ssh_host_rsa_key
A ssh/ssh_host_rsa_key.pub
A ssh/ssh_host_dsa_key
A ssh/ssh_host_dsa_key.pub
A ssh/ssh_host_ecdsa_key
A ssh/ssh_host_ecdsa_key.pub
A ssh/ssh_host_ed25519_key
A ssh/ssh_host_ed25519_key.pub
A udev/hwdb.bin
A resolv.conf
A hostname
A localtime
A .pwd.lock
A .updated
Listing packages
The following is the rpm-ostree command that lists all the packages for that branch, extracted from RPM database.
root@photon-host [ ~ ]# rpm-ostree db list photon/3.0/x86_64/minimal
ostree commit: photon/3.0/x86_64/minimal (a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650)
Linux-PAM-1.3.0-1.ph3.x86_64
attr-2.4.48-1.ph3.x86_64
autogen-libopts-5.18.16-1.ph3.x86_64
bash-4.4.18-1.ph3.x86_64
bc-1.07.1-1.ph3.x86_64
binutils-2.31.1-6.ph3.x86_64
bridge-utils-1.6-1.ph3.x86_64
bubblewrap-0.3.0-2.ph3.x86_64
bzip2-1.0.6-10.ph3.x86_64
bzip2-libs-1.0.6-10.ph3.x86_64
ca-certificates-20190521-1.ph3.x86_64
ca-certificates-pki-20190521-1.ph3.x86_64
coreutils-8.30-1.ph3.x86_64
cpio-2.12-4.ph3.x86_64
cracklib-2.9.6-8.ph3.x86_64
cracklib-dicts-2.9.6-8.ph3.x86_64
curl-7.61.1-4.ph3.x86_64
curl-libs-7.61.1-4.ph3.x86_64
dbus-1.13.6-1.ph3.x86_64
device-mapper-2.02.181-1.ph3.x86_64
device-mapper-libs-2.02.181-1.ph3.x86_64
docker-18.06.2-3.ph3.x86_64
dracut-048-1.ph3.x86_64
dracut-tools-048-1.ph3.x86_64
e2fsprogs-libs-1.44.3-2.ph3.x86_64
elfutils-0.176-1.ph3.x86_64
elfutils-libelf-0.176-1.ph3.x86_64
expat-2.2.6-2.ph3.x86_64
expat-libs-2.2.6-2.ph3.x86_64
file-5.34-1.ph3.x86_64
file-libs-5.34-1.ph3.x86_64
filesystem-1.1-4.ph3.x86_64
findutils-4.6.0-5.ph3.x86_64
flex-2.6.4-2.ph3.x86_64
fuse-2.9.7-5.ph3.x86_64
gc-8.0.0-1.ph3.x86_64
glib-2.58.0-4.ph3.x86_64
glib-networking-2.59.1-2.ph3.x86_64
glibc-2.28-4.ph3.x86_64
glibc-iconv-2.28-4.ph3.x86_64
gmp-6.1.2-2.ph3.x86_64
gnupg-2.2.17-1.ph3.x86_64
gnutls-3.6.3-3.ph3.x86_64
gobject-introspection-1.58.0-2.ph3.x86_64
gpgme-1.11.1-2.ph3.x86_64
grep-3.1-1.ph3.x86_64
grub2-2.02-13.ph3.x86_64
grub2-efi-2.02-13.ph3.x86_64
grub2-pc-2.02-13.ph3.x86_64
guile-2.0.13-2.ph3.x86_64
gzip-1.9-1.ph3.x86_64
iana-etc-2.30-2.ph3.noarch
icu-61.1-1.ph3.x86_64
iproute2-4.18.0-2.ph3.x86_64
iptables-1.8.3-1.ph3.x86_64
js-1.8.5-2.ph3.x86_64
json-c-0.13.1-1.ph3.x86_64
json-glib-1.4.4-1.ph3.x86_64
kmod-25-1.ph3.x86_64
krb5-1.17-1.ph3.x86_64
libapparmor-2.13-7.ph3.x86_64
libarchive-3.3.3-3.ph3.x86_64
libassuan-2.5.1-1.ph3.x86_64
libcap-2.25-8.ph3.x86_64
libdb-5.3.28-2.ph3.x86_64
libffi-3.2.1-6.ph3.x86_64
libgcc-7.3.0-4.ph3.x86_64
libgcrypt-1.8.3-2.ph3.x86_64
libgomp-7.3.0-4.ph3.x86_64
libgpg-error-1.32-1.ph3.x86_64
libgsystem-2015.2-2.ph3.x86_64
libksba-1.3.5-1.ph3.x86_64
libltdl-2.4.6-3.ph3.x86_64
libmodulemd-2.4.0-1.ph3.x86_64
libpsl-0.20.2-1.ph3.x86_64
librepo-1.10.2-1.ph3.x86_64
libseccomp-2.4.0-1.ph3.x86_64
libselinux-2.8-1.ph3.x86_64
libsepol-2.8-1.ph3.x86_64
libsolv-0.6.35-1.ph3.x86_64
libsoup-2.64.0-2.ph3.x86_64
libssh2-1.9.0-1.ph3.x86_64
libstdc++-7.3.0-4.ph3.x86_64
libtasn1-4.13-1.ph3.x86_64
libtool-2.4.6-3.ph3.x86_64
libunistring-0.9.10-1.ph3.x86_64
libxml2-2.9.9-1.ph3.x86_64
libyaml-0.2.1-2.ph3.x86_64
linux-4.19.65-3.ph3.x86_64
m4-1.4.18-2.ph3.x86_64
mpfr-4.0.1-1.ph3.x86_64
ncurses-6.1-1.ph3.x86_64
ncurses-libs-6.1-1.ph3.x86_64
ncurses-terminfo-6.1-1.ph3.x86_64
net-tools-1.60-11.ph3.x86_64
nettle-3.4-1.ph3.x86_64
npth-1.6-1.ph3.x86_64
nspr-4.21-1.ph3.x86_64
nss-altfiles-2.23.0-1.ph3.x86_64
nss-libs-3.44-2.ph3.x86_64
openssh-7.8p1-5.ph3.x86_64
openssh-clients-7.8p1-5.ph3.x86_64
openssh-server-7.8p1-5.ph3.x86_64
openssl-1.0.2s-1.ph3.x86_64
ostree-2019.2-1.ph3.x86_64
ostree-grub2-2019.2-1.ph3.x86_64
ostree-libs-2019.2-1.ph3.x86_64
pcre-8.42-1.ph3.x86_64
pcre-libs-8.42-1.ph3.x86_64
photon-release-3.0-3.ph3.noarch
photon-repos-3.0-3.ph3.noarch
pinentry-1.1.0-1.ph3.x86_64
pkg-config-0.29.2-2.ph3.x86_64
polkit-0.113-5.ph3.x86_64
popt-1.16-5.ph3.x86_64
procps-ng-3.3.15-1.ph3.x86_64
python3-3.7.3-2.ph3.x86_64
python3-libs-3.7.3-2.ph3.x86_64
readline-7.0-2.ph3.x86_64
rpm-libs-4.14.2-4.ph3.x86_64
rpm-ostree-2019.3-1.ph3.x86_64
sed-4.5-1.ph3.x86_64
shadow-4.6-3.ph3.x86_64
shadow-tools-4.6-3.ph3.x86_64
sqlite-libs-3.27.2-3.ph3.x86_64
systemd-239-13.ph3.x86_64
util-linux-2.32-1.ph3.x86_64
util-linux-libs-2.32-1.ph3.x86_64
vim-8.1.0388-4.ph3.x86_64
which-2.21-5.ph3.x86_64
xz-5.2.4-1.ph3.x86_64
xz-libs-5.2.4-1.ph3.x86_64
zchunk-1.1.1-1.ph3.x86_64
zchunk-libs-1.1.1-1.ph3.x86_64
zlib-1.2.11-1.ph3.x86_64
Querying for package details
We are able to use the query option of rpm to make sure any package have been installed properly. The files list should match the previous file mappings in 4.2, so let’s check package rpm-ostree. As we’ve seen, manual files listed here are actually missing, they were not installed.
root@photon-host [ /usr/share/man/man1 ]# rpm -ql rpm-ostree
/usr/bin/atomic
/usr/bin/rpm-ostree
/usr/lib/girepository-1.0/RpmOstree-1.0.typelib
/usr/lib/librpmostree-1.so.1
/usr/lib/librpmostree-1.so.1.0.0
/usr/lib/rpm-ostree
/usr/lib/rpm-ostree/tmpfiles-ostree-integration.conf
/usr/share/man/man1/atomic.1.gz
/usr/share/man/man1/rpm-ostree.1.gz
Why am I unable to install, upgrade or uninstall packages?
The OSTree host installer needs the server URL or the server repository.
When you perform the installation using the repo, the install packages are located under the layer package. When you install with the URL, the packages are located under the local packages.
You can use the rpm-ostree uninstall
command to uninstall only the layered and local packages but not the base packages. To modify the base packages, you can use the rpm-ostree override
command.
When you run rpm-ostree upgrade
, the command will only upgrade packages based on the commit available in the server.
11.5 - Host Updating Operations
Upgrade overview
If you’ve used yum, dnf (and now tdnf for Photon) in RPM systems or apt-get in Debian based Unix, you understand what “install” is for packages and the subtle difference between “update” and “upgrade”.
OSTree and RPM-OSTree don’t distinguish between them and the term “upgrade” has a slightly different meaning - to bring the system in sync with the remote repo, to the top of the Refspec (branch), just like in Git, by pulling the latest changes.
In fact, ostree and rpm-ostree commands support a single “upgrade” verb for a file image tree and a package list in the same refspec (branch). rpm-ostree upgrade
will install a package if it doesn’t exist, will not touch it if it has same version in the new image, will upgrade it if the version number is higher and it may actually downgrade it, if the package has been downgraded in the new image. I wish this operation had a different name, to avoid any confusion.
The reverse operation of an upgrade is a “rollback” and fortunately it’s not named “downgrade” because it may upgrade packages in the last case describe above.
As we’ll see in a future chapter, a jump to a different Refspec (branch) is also supported and it’s named “rebase”.
Incremental upgrade
To check if there are any updates available, one would execute:
root@photon-host-def [ ~ ]# rpm-ostree upgrade
Updating from: photon:photon/3.0/x86_64/minimal
No upgrade available.
It is good idea to check periodically for updates.
To check if there are any new updates without actually applying them, we will pass the –check-diff flag, that would list the different packages as added, modified or deleted - if such operations were to happen.
root@photon-host [ ~ ]# rpm-ostree upgrade --check-diff
Updating from: photon:photon/3.0/x86_64/minimal
8 metadata, 13 content objects fetched; 1026 KiB transferred in 0 seconds
+gawk-4.1.3-2.ph1.x86_64
+sudo-1.8.15-3.ph1.x86_64
+wget-1.17.1-2.ph1.x86_64
We like what we see and now let’s upgrade for real. This command will deploy a new bootable filetree.
root@photon-host [ ~ ]# rpm-ostree upgrade
Receiving metadata objects: 134/(estimating) 14.1 MB/s 14.1 MB... done
Checking out tree c8f2b11... done
Enabled rpm-md repositories: repo photon-updates photon photon-extras
rpm-md repo 'repo' (cached); generated: 2019-09-18T05:26:00Z
rpm-md repo 'photon-updates' (cached); generated: 2019-09-11T00:02:44Z
rpm-md repo 'photon' (cached); generated: 2019-02-06T08:56:24Z
rpm-md repo 'photon-extras' (cached); generated: 2018-11-02T18:09:56Z
Importing rpm-md... done
Resolving dependencies... done
Checking out packages... done
Running pre scripts... done
Running post scripts... done
Writing rpmdb... done
Writing OSTree commit... done
Staging deployment... done
Freed: 20.7 MB (pkgcache branches: 0)
zlib 1.2.11-1.ph3 -> 1.2.11-2.ph3
Downgraded:
ostree 2019.2-15.ph3 -> 2019.2-2.ph3
ostree-grub2 2019.2-15.ph3 -> 2019.2-2.ph3
ostree-libs 2019.2-15.ph3 -> 2019.2-2.ph3
Removed:
chkconfig-1.9-1.ph3.x86_64
elasticsearch-6.7.0-2.ph3.x86_64
kibana-6.7.0-2.ph3.x86_64
logstash-6.7.0-2.ph3.x86_64
newt-0.52.20-1.ph3.x86_64
nodejs-10.15.2-1.ph3.x86_64
openjdk8-1.8.0.212-2.ph3.x86_64
openjre8-1.8.0.212-2.ph3.x86_64
ruby-2.5.3-2.ph3.x86_64
slang-2.3.2-1.ph3.x86_64
Added:
nss-3.44-2.ph3.x86_64
xmlsec1-1.2.26-2.ph3.x86_64
Run "systemctl reboot" to start a reboot
By looking at the commit history, notice that the new commit has the original commit as parent.
root@photon-host [ ~ ]# ostree log photon/3.0/x86_64/minimal
commit c8f2b116b067d7695f9033bf2a99505198269354e157c0f2d5b78266cb874239
ContentChecksum: 9bc2079ad70df6dc9373752b254711f3413ae8a07628016c7de7f7d3fa505a6f
Date: 2019-09-18 08:22:15 +0000
Version: 3.0_minimal.2
(no subject)
commit 28dc49ecb4604c0bc349e4445adc659491a1874c01198e6253a261f4d59708b7
ContentChecksum: c3650c76e2bb0e9b6b063cda2dd55939c965c54fd0b0f5ce2cfb7e801403e610
Date: 2019-09-16 09:51:33 +0000
Version: 3.0_minimal.1
Notice that now we have a new reference, that corresponds to the newly deployed image.
root@photon-host [ ~ ]# ostree refs
rpmostree/pkg/createrepo__c/0.11.1-2.ph3.x86__64
rpmostree/pkg/wget/1.20.3-1.ph3.x86__64
photon-1:photon/3.0/x86_64/minimal
rpmostree/base/0
rpmostree/base/1
ostree/0/0/0
ostree/0/0/1
ostree/0/0/2
rpmostree/pkg/rpm/4.14.2-4.ph3.x86__64
Let us look at the status. The new filetree version .1 has the expected Commit ID and a newer timestamp, that is actually the server date/time when the image has been generated, not the time/date when it was downloaded or installed at the host. The old image has a star next to it, showing that’s the image the system is booted currently into.
root@photon-host [ ~ ]# rpm-ostree status
State: idle
AutomaticUpdates: disabled
Deployments:
ostree://photon-1:photon/3.0/x86_64/minimal
Version: 3.0_minimal.2 (2019-09-18T08:22:15Z)
BaseCommit: c8f2b116b067d7695f9033bf2a99505198269354e157c0f2d5b78266cb874239
Diff: 1 upgraded, 3 downgraded, 10 removed, 2 added
LayeredPackages: createrepo_c rpm wget
* ostree://photon-1:photon/3.0/x86_64/minimal
Version: 3.0_minimal.1 (2019-09-16T09:51:33Z)
BaseCommit: 28dc49ecb4604c0bc349e4445adc659491a1874c01198e6253a261f4d59708b7
LayeredPackages: createrepo_c rpm wget
ostree://photon:photon/3.0/x86_64/minimal
Version: 3.0_minimal.1 (2019-09-16T09:51:33Z)
BaseCommit: 28dc49ecb4604c0bc349e4445adc659491a1874c01198e6253a261f4d59708b7
LayeredPackages: createrepo_c rpm wget
Now let’s type ‘reboot’. Grub will list the new filetree as the first image, marked with a star, as the default bootable image. If the keyboard is not touched and order is not changed, grub will timeout and will boot into that image.
Let’s look again at the status. It’s identical, just that the star is next to the newer image, to show it’s the current image it has booted from.
root@photon-host [ ~ ]# rpm-ostree status
State: idle
AutomaticUpdates: disabled
Deployments:
* ostree://photon-1:photon/3.0/x86_64/minimal
Version: 3.0_minimal.2 (2019-09-18T08:22:15Z)
BaseCommit: c8f2b116b067d7695f9033bf2a99505198269354e157c0f2d5b78266cb874239
LayeredPackages: createrepo_c rpm wget
ostree://photon-1:photon/3.0/x86_64/minimal
Version: 3.0_minimal.1 (2019-09-16T09:51:33Z)
BaseCommit: 28dc49ecb4604c0bc349e4445adc659491a1874c01198e6253a261f4d59708b7
LayeredPackages: createrepo_c rpm wget
Also, the current deployment directory is based on the new commit:
root@photon-host-def [ ~ ]# ostree admin config-diff --print-current-dir
/ostree/deploy/photon/deploy/63fd7a46dac6c169ee997039c229dd1d626f9b13eaf47b7a183f7a449eb4076f.0
A fresh upgrade for a new version will delete the older, original image and bring a new one, that will become the new default image. The previous ‘default’ image will move down one position as the backup image.
Listing file differences
Now we can look at what files have been Added, Modified, Deleted due to the addition of those three packages and switching of the boot directories, by comparing the two commits.
root@photon-host-def [ ~ ]# ostree diff 63fd 37e2
M /usr/etc/ld.so.cache
M /usr/lib/sysimage/rpm-ostree-base-db/Basenames
M /usr/lib/sysimage/rpm-ostree-base-db/Conflictname
M /usr/lib/sysimage/rpm-ostree-base-db/Dirnames
M /usr/lib/sysimage/rpm-ostree-base-db/Enhancename
M /usr/lib/sysimage/rpm-ostree-base-db/Filetriggername
M /usr/lib/sysimage/rpm-ostree-base-db/Group
M /usr/lib/sysimage/rpm-ostree-base-db/Installtid
M /usr/lib/sysimage/rpm-ostree-base-db/Name
M /usr/lib/sysimage/rpm-ostree-base-db/Obsoletename
M /usr/lib/sysimage/rpm-ostree-base-db/Packages
M /usr/lib/sysimage/rpm-ostree-base-db/Providename
M /usr/lib/sysimage/rpm-ostree-base-db/Recommendname
M /usr/lib/sysimage/rpm-ostree-base-db/Requirename
M /usr/lib/sysimage/rpm-ostree-base-db/Sha1header
M /usr/lib/sysimage/rpm-ostree-base-db/Sigmd5
M /usr/lib/sysimage/rpm-ostree-base-db/Suggestname
M /usr/lib/sysimage/rpm-ostree-base-db/Supplementname
M /usr/lib/sysimage/rpm-ostree-base-db/Transfiletriggername
M /usr/lib/sysimage/rpm-ostree-base-db/Triggername
M /usr/share/rpm/Basenames
M /usr/share/rpm/Conflictname
M /usr/share/rpm/Dirnames
M /usr/share/rpm/Enhancename
M /usr/share/rpm/Filetriggername
M /usr/share/rpm/Group
M /usr/share/rpm/Installtid
M /usr/share/rpm/Name
M /usr/share/rpm/Obsoletename
M /usr/share/rpm/Packages
M /usr/share/rpm/Providename
M /usr/share/rpm/Recommendname
M /usr/share/rpm/Requirename
M /usr/share/rpm/Sha1header
M /usr/share/rpm/Sigmd5
M /usr/share/rpm/Suggestname
M /usr/share/rpm/Supplementname
M /usr/share/rpm/Transfiletriggername
M /usr/share/rpm/Triggername
M /usr/share/rpm-ostree/treefile.json
D /usr/bin/certutil
D /usr/bin/nss-config
D /usr/bin/pk12util
D /usr/bin/xmlsec1
D /usr/lib/libfreebl3.chk
D /usr/lib/libfreebl3.so
D /usr/lib/libfreeblpriv3.chk
D /usr/lib/libgtest1.so
D /usr/lib/libgtestutil.so
D /usr/lib/libnssckbi.so
D /usr/lib/libnssdbm3.chk
D /usr/lib/libnssdbm3.so
D /usr/lib/libnsssysinit.so
D /usr/lib/libsmime3.so
D /usr/lib/libsoftokn3.chk
D /usr/lib/libssl3.so
D /usr/lib/libxmlsec1-nss.so
D /usr/lib/libxmlsec1-nss.so.1
D /usr/lib/libxmlsec1-nss.so.1.2.26
D /usr/lib/libxmlsec1-openssl.so
D /usr/lib/libxmlsec1-openssl.so.1
D /usr/lib/libxmlsec1-openssl.so.1.2.26
D /usr/lib/libxmlsec1.so
D /usr/lib/libxmlsec1.so.1
D /usr/lib/libxmlsec1.so.1.2.26
Listing package differences
We can also look at package differences, as you expect, using the right tool for the job.
root@photon-host-def [ ~ ]# rpm-ostree db diff 63fd 37e2
ostree diff commit old: rollback deployment (63fd7a46dac6c169ee997039c229dd1d626f9b13eaf47b7a183f7a449eb4076f)
ostree diff commit new: booted deployment (37e2ecfa34eb808962fdfed28623bbc457184bcd6bb788b79143d33e3569084f)
Removed:
nss-3.44-2.ph3.x86_64
xmlsec1-1.2.26-2.ph3.x86_64
Rollback
If we want to go back to the previous image, we can rollback. The order of the images will be changed, so the old filetree will become the default bootable image. If -r option is passed, the rollback will continue with a reboot.
root@photon-host-def [ ~ ]# rpm-ostree rollback
Moving 'e663b2872efa01d80e4c34c823431472beb653373af32de83c7d2480316b8a6a.0' to be first deployment
Transaction complete; bootconfig swap: yes; deployment count change: 0
Upgraded:
ostree 2019.2-2.ph3 -> 2019.2-15.ph3
ostree-grub2 2019.2-2.ph3 -> 2019.2-15.ph3
ostree-libs 2019.2-2.ph3 -> 2019.2-15.ph3
zlib 1.2.11-2.ph3 -> 1.2.11-1.ph3
Removed:
nss-3.44-2.ph3.x86_64
xmlsec1-1.2.26-2.ph3.x86_64
Added:
chkconfig-1.9-1.ph3.x86_64
elasticsearch-6.7.0-2.ph3.x86_64
kibana-6.7.0-2.ph3.x86_64
logstash-6.7.0-2.ph3.x86_64
newt-0.52.20-1.ph3.x86_64
nodejs-10.15.2-1.ph3.x86_64
openjdk8-1.8.0.212-2.ph3.x86_64
openjre8-1.8.0.212-2.ph3.x86_64
ruby-2.5.3-2.ph3.x86_64
slang-2.3.2-1.ph3.x86_64
Run "systemctl reboot" to start a reboot
In fact, we can repeat the rollback operation as many times as we want before reboot. On each execution, it’s going to change the order. It will not delete any image.
However, an upgrade will keep the current default image and will eliminate the other image, whichever that is. So if Photon installation rolled back to an older build, an upgrade will keep that, eliminate the newer version and will replace it with an even newer version at the next upgrade.
The boot order moved back to original:
root@photon-host-def [ ~ ]# rpm-ostree status
State: idle
AutomaticUpdates: disabled
Deployments:
* ostree://photon-2:photon/3.0/x86_64/minimal
Version: 3.0_minimal.3 (2019-09-18T12:48:03Z)
Commit: cf357c0f376decb3bae42326737db7e36bcf3568ab901c33dc57800c3718f07b
ostree://photon:photon/3.0/x86_64/minimal
Version: 3.0_minimal (2019-08-29T11:20:19Z)
Commit: a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650
The current bootable image path moved also back to the original value:
root@photon-host-def [ ~ ]# ostree admin config-diff --print-current-dir
/ostree/deploy/photon/deploy/47899767bdd4276266383fce13c4a26a51ca0304ae754609283d75f7d8aad36e.0
Installing Packages
You can add more packages onto the system that are not part of the commit composed on the server.
rpm-ostree install <packages>
Example:
rpm-ostree install https://kojipkgs.fedoraproject.org//packages/wget/1.19.5/5.fc29/x86_64/wget-1.19.5-5.fc29.x86_64.rpm
Uninstalling Packages
To remove layered packages installed from a repository, use
rpm-ostree uninstall <pkg>
To remove layered packages installed from a local package, you must specify the full NEVRA of the package.
For example:
rpm-ostree uninstall ltrace-0.7.91-16.fc22.x86_64
To uninstall a package that is a part of the base layer, use
rpm-ostree override remove <pkg>
For example:
rpm-ostree override remove firefox
Deleting a deployed filetree
It is possible to delete a deployed tree. You won’t need to do that normally, as upgrading to a new image will delete the old one, but if for some reason deploying failed (loss of power, networking issues), you’ll want to delete the partially deployed image.
The only supported index is 1. (If multiple bootable images will be supported in the future, a larger than one, zero-based index of the image to delete will be supported).
You cannot delete the default bootable filetree, so passing 0 will result in an error.
root@photon-host-def [ ~ ]# ostree admin undeploy -v 1
OT: Using bootloader: OstreeBootloaderGrub2
Transaction complete; bootconfig swap: yes deployment count change: -1
Deleted deployment a31a843985e314a9e70bcf09afe8d59f7351817d9fb743c2b6dab84f20833650
root@photon-host-cus1 [ ~ ]# ostree admin undeploy -v 0
OT: Deployment cf357c0f376decb3bae42326737db7e36bcf3568ab901c33dc57800c3718f07b.0 unlocked=0
error: Cannot undeploy currently booted deployment 0
Now, we can see that the newer image is gone, the deployment directory for commit a31a has been removed.
root@photon-host-def [ ~ ]# rpm-ostree status
State: idle
AutomaticUpdates: disabled
Deployments:
* ostree://photon-2:photon/3.0/x86_64/minimal
Version: 3.0_minimal.3 (2019-09-18T12:48:03Z)
Commit: cf357c0f376decb3bae42326737db7e36bcf3568ab901c33dc57800c3718f07b
root@photon-host-cus1 [ ~ ]# ls /ostree/deploy/photon/deploy/
cf357c0f376decb3bae42326737db7e36bcf3568ab901c33dc57800c3718f07b.0
cf357c0f376decb3bae42326737db7e36bcf3568ab901c33dc57800c3718f07b.0.origin
However the commit is still there in the OSTree repo.
root@photon-host-def [ ~ ]# ostree log cf35
commit cf357c0f376decb3bae42326737db7e36bcf3568ab901c33dc57800c3718f07b
ContentChecksum: c24d108c7b7451374b474456a47f512e648833040bfbd4f43d862456bd6d5a18
Date: 2019-09-18 12:48:03 +0000
Version: 3.0_minimal.3
But there is nothing to rollback to.
root@photon-host-def [ ~ ]# rpm-ostree rollback
error: Found 1 deployments, at least 2 required for rollback
If we were to upgrade again, it would bring these packages back, but let’s just check the differeneces.
root@photon-host-def [ ~ ]# rpm-ostree upgrade --check-diff
Updating from: photon:photon/3.0/x86_64/minimal
+gawk-4.1.0-2.ph1.x86_64
+sudo-1.8.11p1-4.ph1.x86_64
+wget-1.15-1.ph1.x86_64
Version skipping upgrade
Let’s assume that after a while, VMware releases version 2 that removes sudo and adds bison and tar. Now, an upgrade will skip version 1 and go directly to 2. Let’s first look at what packages are pulled (notice sudo missing, as expected), then upgrade with reboot option.
root@photon-host-def [ ~ ]# rpm-ostree upgrade --check-diff
Updating from: photon:photon/3.0/x86_64/minimal
7 metadata, 13 content objects fetched; 1287 KiB transferred in 0 seconds
+bison-3.0.2-2.ph1.x86_64
+gawk-4.1.0-2.ph1.x86_64
+tar-1.27.1-1.ph1.x86_64
+wget-1.15-1.ph1.x86_64
root@photon-host-def [ ~ ]# rpm-ostree upgrade -r
Updating from: photon:photon/3.0/x86_64/minimal
107 metadata, 512 content objects fetched; 13064 KiB transferred in 1 seconds
Copying /etc changes: 5 modified, 0 removed, 16 added
Transaction complete; bootconfig swap: yes deployment count change: 1
Freed objects: 19.3 MB
After reboot, let’s check the booting filetrees, the current dir for the current filetree and look at commit differences:
root@photon-host-def [ ~ ]# rpm-ostree status
State: idle
AutomaticUpdates: disabled
Deployments:
* ostree://photon-1:photon/3.0/x86_64/minimal
Version: 3.0_minimal.1 (2019-09-16T09:51:33Z)
BaseCommit: 28dc49ecb4604c0bc349e4445adc659491a1874c01198e6253a261f4d59708b7
LayeredPackages: createrepo_c rpm wget
ostree://photon:photon/3.0/x86_64/minimal
Version: 3.0_minimal.1 (2019-09-16T09:51:33Z)
BaseCommit: 28dc49ecb4604c0bc349e4445adc659491a1874c01198e6253a261f4d59708b7
LayeredPackages: createrepo_c rpm wget
root@photon-host-cus1 [ ~ ]# ostree admin config-diff --print-current-dir
/ostree/deploy/photon/deploy/e663b2872efa01d80e4c34c823431472beb653373af32de83c7d2480316b8a6a.0
root@photon-host-cus1 [ ~ ]# rpm-ostree db diff 8b4b e663
ostree diff commit old: rollback deployment (8b4b9d4ec033d1eb816711bfdda595d1013fecbe5cd340f6a619cdc9d83a3bf2)
ostree diff commit new: booted deployment (e663b2872efa01d80e4c34c823431472beb653373af32de83c7d2480316b8a6a)
root@photon-host-cus1 [ ~ ]# rpm-ostree db diff 82bc 092e
error: Refspec '82bc' not found
Interesting fact: The metadata for commit 82bc has been removed from the local repo.
Tracking parent commits
OSTree will display limited commit history - maximum 2 levels, so if you want to traverse the history even though it may not find a commitment by its ID, you can refer to its parent using ‘^’ suffix, grandfather via ‘^^’ and so on. We know that 82bc is the parent of 092e:
root@photon-host-def [ ~ ]# rpm-ostree db diff 092e^ 092e
error: No such metadata object 82bca728eadb7292d568404484ad6889c3f6303600ca8c743a4336e0a10b3817.commit
error: Refspec '82cb' not found
root@photon-host-def [ ~ ]# rpm-ostree db diff 092e^^ 092e
error: No such metadata object 82bca728eadb7292d568404484ad6889c3f6303600ca8c743a4336e0a10b3817.commit
So commit 092e knows who its parent is, but its metadata is no longer in the local repo, so it cannot traverse further to its parent to find an existing grandfather.
Resetting a branch to a previous commit
We can reset the head of a branch in a local repo to a previous commit, for example corresponding to version 0 (3.0_minimal).
root@photon-host-def [ ~ ]# ostree reset photon:photon/3.0/x86_64/minimal cf35
Now if we look again at the branch commit history, the head is at version 0.
root@photon-host-def [ ~ ]# ostree log photon/3.0/x86_64/minimal
commit cf357c0f376decb3bae42326737db7e36bcf3568ab901c33dc57800c3718f07b
ContentChecksum: c24d108c7b7451374b474456a47f512e648833040bfbd4f43d862456bd6d5a18
Date: 2019-09-18 12:48:03 +0000
Version: 3.0_minimal
11.6 - Creating a Server
Photon OS 3.0 includes a rpm-ostree-repo
package that can be installed on a VM.
This package provides an automated script that creates a repo tree that acts as a server.
Run the following commands to create a server:
tdnf install rpm-ostree-repo
A script is created, which provides options to create a server.
Script to create a Photon OSTree repo
Usage:
/usr/bin/rpm-ostree-server/mkostreerepo -r=<repo path>
/usr/bin/rpm-ostree-server/mkostreerepo -r=<repo path> -p=<json treefile>
/usr/bin/rpm-ostree-server/mkostreerepo -c -r=<repo path> -p=<json treefile>
-r|--repopath <Provide repo path>
-p|--jsonfile <Provide Json file>
-c|--customrepo <Provide custom repo file inside repo path directory>
Note
- Use PATH=$PATH:/usr/bin/rpm-ostree-server and then use mkostreerepo from any directory for ease of use.
- mkostreerepo is used to create the fresh tree for ostree.
- mkostreerepo is also used to update a new commit to the existing tree.
- You can also use custom repo as to create/append the tree.
Run the following command to initiate the script, choose different help options to create a server.
mkostreerepo
Manually Composing your OSTree repo
Use the following commands to initialize a new repo and to compose it.
root [ ~ ]# cd /srv/rpm-ostree
root [ /srv/rpm-ostree ]# ostree --repo=repo init --mode=archive-z2
root [ /srv/rpm-ostree ]# rpm-ostree compose tree --repo=repo photon-base.json
You can now deploy a host. For more information, see File oriented server operations and Package oriented server operations to learn create your own customized file tree.
11.7 - Installing a Photon RPM-OStree host against a custom server repository
Organizations that maintain their own OSTree servers create custom image trees suited to their needs from which hosts can be deployed and upgraded. One single server may make available several branches to install, for example “base”, “minimal” and “full”. Or, if you think in terms of Windows OS SKUs - “Home”, “Professional” or “Enterprise” edition.
So in fact there are two pieces of information the OSTree host installer needs - the server URL and the branch ref. Also, there are two ways to pass this info - manually via keyboard, when prompted and automated, by reading from a config file.
Manual install of a custom host
For Photon 1.0 or 1.0 Revision 2, installing a Photon RPM-OSTree host that will pull from a server repository of your choice is very similar to the way we installed the host against the default server repo in Chapter 2.
We will follow the same steps, selecting “Photon OSTree Host”, and after assigning a host name like photon-host and a root password, this time we will click on “Custom RPM-OSTree Server”.
An additional screen will ask for the URL of server repo - just enter the IP address or fully qualified domain name of the server installed in the previous step.
Once this is done and the installation finished, reboot and you are ready to use it.
You may verify - just like in Chapter 3.1 - that you can get an rpm-ostree status. The value for the CommitID should be identical to the host that installed from default repo, if the server has been installed fresh, from the same ISO.
Automated install of a custom host via kickstart
Photon 3.0 supports automated install that will not interact with the user, in other words installer will display its progress, but will not prompt for any keys to be clicked, and will boot at the end of installation.
If not familiar with the way kickstart works, visit Kickstart Support in Photon OS. The kickstart json config for OSTree is similar to minimal or full, except for these settings that should sound familiar:
...
"type": "ostree_host",
"ostree_repo_url": "http://192.168.218.249",
"ostree_repo_ref": "photon/3.0/x86_64/minimal",
...
Or, for default installation
....
"type": "ostree_host",
"default_repo": true,
....
If the server is a future version of Photon OS, say Photon OS 4.0, and the administrator composed trees for the included json files, the ostree_repo_ref will take either value: photon/4.0/x86_64/base, photon/4.0/x86_64/minimal, or photon/4.0/x86_64/full.
In most situations, kickstart file is accessed via http from PXE boot. That enables booting from network and end to end install of hosts from pre-defined server URL and branch without assistance from user.
11.8 - Automatic Updates
Automatic updates are disabled by default.
To verify this, run the status command.
root@photon-host-def [ ~ ]# rpm-ostree status
State: idle
AutomaticUpdates: disabled
Deployments:
* ostree://photon-1:photon/3.0/x86_64/minimal
Version: 3.0_minimal.1 (2019-09-16T09:51:33Z)
BaseCommit: 28dc49ecb4604c0bc349e4445adc659491a1874c01198e6253a261f4d59708b7
LayeredPackages: createrepo_c rpm wget
Enable Automatic Updates
- Run the following command:
$ systemctl restart rpm-ostreed
To enable automatic background updates, edit the /etc/rpm-ostreed.conf
, and include the below lines in the Daemon
section:
[Daemon]
AutomaticUpdatePolicy=stage
#IdleExitTimeout=60
Run the following commands:
$ systemctl reload rpm-ostreed
$ systemctl enable rpm-ostree-automatic.timer --now
$ systemctl restart rpm-ostree-automatic
Verify that the automatic update feature has been enabled:
$ rpm-ostree status -v
State: idle
AutomaticUpdates: stage; rpm-ostreed-automatic.timer: last run 16min ago
On the server machine, perform another commit on the base tree.
Automatic updates are now enabled and will automatically update the host system.
11.9 - File Oriented Server Operations
In this section, we will checkout a filetree into a writable directory structure on disk, make several file changes and commit the changes back into the repository. Then we will download this commit and apply at the host. As you may have guessed, this chapter is mostly about OSTree - the base technology. I’ve not mentioned anything about packages, although it is quite possible to install packages (afler all, packages are made of files, right?) and commit without the help of rpm-ostree, but it’s too much of a headache and not worth the effort, since rpm-ostree does it simpler and better.
When would you want to do that? When you want for all your hosts to get an application or configuration customization that is not encapsulated as part of a package upgrade.
Starting a fresh OSTree repo
If you want to start fresh with your own branch and/or versioning scheme, you can delete the OSTree repo created during the Photon 3.0 RPM-OSTree server install and re-create it empty.
root [ /srv/rpm-ostree ]# rm -rf repo/*
root [ /srv/rpm-ostree ]# ostree --repo=repo init --mode=archive-z2
root [ /srv/rpm-ostree ]# ls repo
config objects refs state tmp uncompressed-objects-cache
root [ /srv/rpm-ostree ]# cat repo/config
[core]
repo_version=1
mode=archive-z2
A newer ostree feature, available in Photon OS 2.0 and higher, allows the OSTree server admin to create server summary metadata, that includes among other things the list of available branches and the list of static deltas, so they could be discovered by hosts. To create a summary, run this command after you committed for your branches:
root [ /srv/rpm-ostree ]# ostree summary -u "This is BigData's OSTree server, it has three branches"
We will find out later how the hosts query for branches list.
11.10 - Package Oriented Server Operations
Now that we have a Photon RPM-OSTree server up and running (if not, see how to install), we will learn how to provide the desired set of packages as input and instruct rpm-ostree to compose a filetree, that will result in creation (or update) of an OSTree repo.
The simplest way to explain is to take a look at the files installed by the Photon RPM-OSTree server during setup.
root [ ~ ]# cd /srv/rpm-ostree/
root [ /srv/rpm-ostree ]# ls -l
total 16
lrwxrwxrwx 1 root root 31 Aug 28 19:06 lightwave-ostree.repo -> /etc/yum.repos.d/lightwave.repo
-rw-r--r-- 1 root root 7356 Aug 28 19:06 ostree-httpd.conf
-rw-r--r-- 1 root root 1085 Aug 28 19:06 photon-base.json
lrwxrwxrwx 1 root root 35 Aug 28 19:06 photon-extras-ostree.repo -> /etc/yum.repos.d/photon-extras.repo
lrwxrwxrwx 1 root root 32 Aug 28 19:06 photon-iso-ostree.repo -> /etc/yum.repos.d/photon-iso.repo
lrwxrwxrwx 1 root root 28 Aug 28 19:06 photon-ostree.repo -> /etc/yum.repos.d/photon.repo
lrwxrwxrwx 1 root root 36 Aug 28 19:06 photon-updates-ostree.repo -> /etc/yum.repos.d/photon-updates.repo
drwxr-xr-x 7 root root 4096 Aug 20 22:27 repo
JSON configuration file
How can we tell rpm-ostree what packages we want to include, where to get them from and how to compose the filetree? There is JSON file for that. Let’s take a look at photon-base.json used by the Photon OS team.
root [ /srv/rpm-ostree ]# cat photon-base.json
{
"comment": "Photon Minimal OSTree",
"osname": "photon",
"ref": "photon/3.0/x86_64/minimal",
"automatic_version_prefix": "3.0_minimal",
"repos": ["photon"],
"selinux": false,
"initramfs-args": ["--no-hostonly"],
"bootstrap_packages": ["filesystem"],
"documentation": false,
"packages": ["glibc", "zlib", "binutils", "gmp", "mpfr", "libgcc", "libstdc++","libgomp",
"pkg-config", "ncurses", "bash", "bzip2", "cracklib", "cracklib-dicts", "shadow",
"procps-ng", "iana-etc", "readline", "coreutils", "bc", "libtool", "net-tools",
"findutils", "xz", "grub2", "grub2-pc", "grub2-efi", "iproute2", "util-linux", "linux",
"attr", "libcap", "kmod", "expat", "dbus", "file",
"sed", "grep", "cpio", "gzip",
"openssl", "ca-certificates", "curl",
"systemd",
"openssh", "iptables",
"photon-release",
"vim", "photon-repos",
"docker", "bridge-utils",
"dracut", "dracut-tools", "rpm-ostree", "nss-altfiles", "which"]
}
There are some mandatory settings, some optional. I’m only going to explain the most important ones for our use case.
osname and ref should be familiar, they have been explained in previous sections OSname and Refspec. Basicaly, we are asking rpm-ostree
to compose a tree for photon OS and photon/3.0/x86_64/minimal branch.
For more information, see the OS Tree Documentation.
Package addition, removal, upgrade
packages is the list of packages that are to be added, in this case, in the “minimal” installation profile, on top of the packages already included by default. This is not quite the identical set of RPMS you get when you select the minimal profile in the ISO installer, but it’s pretty close and that’s why it’s been named the same.
Let’s add to the list three new packages: gawk, sudo and wget using vim photon-base.json
!!!Warning: do not remove any packages from the default list, even an “innocent” one, as it may bring the system to an unstable condition. During my testing, I’ve removed “which”; it turns out it was used to figure out the grub booting roots: on reboot, the system was left hanging at grub prompt.
RPMS repository
But where are these packages located? RPM-OStree uses the same standard RPMS repositories, that yum installs from.
root [ /srv/rpm-ostree ]# ls /etc/yum.repos.d/
photon-debuginfo.repo photon-extras.repo photon-iso.repo photon-updates.repo photon.repo
Going back to our JSON file, repos is a multi-value setting that tells RPM-OSTree in what RPMS repositories to look for packages. In this case, it looks in the current directory for a “photon” repo configuration file, that is a .repo file starting with a [photon] section. There is such a file: photon-ostree.repo, that is in fact a link to photon.repo in /etc/yum.repos.d directory.
root [ /srv/rpm-ostree ]# cat /etc/yum.repos.d/photon.repo
[photon]
name=VMware Photon Linux 3.0(x86_64)
baseurl=https://dl.bintray.com/vmware/photon_release_$releasever_$basearch
gpgkey=file:///etc/pki/rpm-gpg/VMWARE-RPM-GPG-KEY
gpgcheck=1
enabled=1
skip_if_unavailable=True
In this case, rpm-ostree
is instructed to download its packages in RPM format from the bintray URL, that is the location of an online RPMS repo maintained by the WMware Photon OS team. To make sure those packages are genuine, signed by VMware, the signature is checked against the official VMware public key.
So what’s in an RPMS repository? If we point the browser to https://packages.vmware.com/photon/3.0/photon_updates_3.0_x86_64, we can see there are three top directories:
- noarch - where all packages that don’t depend on the architecture reside. Those may contain scripts, platform neutral source files, configuration.
- x86_64 - platform dependent packages for Intel 32 and 64 bits CPUs.
- repodata - internal repo management data, like a catalog of all packages, and for every package its name, id, version, architecture and full path file/directory list. There is also a compressed XML file containing the history of changelogs extracted from github, as packages in RPM format were built by Photon OS team members from sources.
Fortunately, in order to compose a tree, you don’t need to download the packages from the online repository (which is time consuming - in the order of minutes), unless there are some new ones or updated versions of them, added by the Photon team after shipping 1.0 version or the 1.0 Refresh. A copy of the starter RPMS repository (as of 1.0 shipping date) has been included on the CD-ROM and you can access it.
root [ /srv/rpm-ostree ]# mount /dev/cdrom
root [ /srv/rpm-ostree ]# ls /mnt/cdrom/RPMS
noarch repodata x86_64
All you have to do now is to replace the "repos": ["photon"]
entry by "repos": ["photon-iso"]
, which will point to the RPMS repo on CD-ROM, rather than the online repo. This way, composing saves time, bandwidth and reduces to zero the risk of failure because of a networking issue.
root [ /srv/rpm-ostree ]# cat /etc/yum.repos.d/photon-iso.repo
[photon-iso]
name=VMWare Photon Linux ISO 3.0(x86_64)
baseurl=file:///mnt/cdrom/RPMS
gpgkey=file:///etc/pki/rpm-gpg/VMWARE-RPM-GPG-KEY
gpgcheck=1
enabled=0
skip_if_unavailable=True
There are already in current directory links created to all repositories in /etc/yum.repos.d, so they are found when tree compose command is invoked. You may add any other repo to the list and include packages found in that repo to be part of the image.
Composing a tree
After so much preparation, we can execute a tree compose. We have only added 3 new packages and changed the RPMS repo source. Assuming that the JSON file is editted, run the following:
root [ /srv/rpm-ostree ]# rpm-ostree compose tree --repo=repo photon-base.json
Previous commit: 2940e10c4d90ce6da572cbaeeff7b511cab4a64c280bd5969333dd2fca57cfa8
Downloading metadata [=========================================================================] 100%
Transaction: 117 packages
Linux-PAM-1.1.8-2.ph3.x86_64
attr-2.4.47-1.ph3.x86_64
...
gawk-4.1.0-2.ph3.x86_64
...
sudo-1.8.11p1-4.ph3.x86_64
...
wget-1.15-1.ph3.x86_64
which-2.20-1.ph3.x86_64
xz-5.0.5-2.ph3.x86_64
zlib-1.2.8-2.ph3.x86_64
Installing packages [==========================================================================] 100%
Writing '/var/tmp/rpm-ostree.TVO089/rootfs.tmp/usr/share/rpm-ostree/treefile.json'
Preparing kernel
Creating empty machine-id
Executing: /usr/bin/dracut -v --tmpdir=/tmp -f /var/tmp/initramfs.img 4.0.9 --no-hostonly
...
*** Including module: bash ***
*** Including module: kernel-modules ***
*** Including module: resume ***
*** Including module: rootfs-block ***
*** Including module: terminfo ***
*** Including module: udev-rules ***
Skipping udev rule: 91-permissions.rules
Skipping udev rule: 80-drivers-modprobe.rules
*** Including module: ostree ***
*** Including module: systemd ***
*** Including module: usrmount ***
*** Including module: base ***
/etc/os-release: line 1: Photon: command not found
*** Including module: fs-lib ***
*** Including module: shutdown ***
*** Including modules done ***
*** Installing kernel module dependencies and firmware ***
*** Installing kernel module dependencies and firmware done ***
*** Resolving executable dependencies ***
*** Resolving executable dependencies done***
*** Stripping files ***
*** Stripping files done ***
*** Store current command line parameters ***
*** Creating image file ***
*** Creating image file done ***
Image: /var/tmp/initramfs.img: 11M
========================================================================
Version: dracut-041-1.ph3
Arguments: -v --tmpdir '/tmp' -f --no-hostonly
dracut modules:
bash
kernel-modules
resume
rootfs-block
terminfo
udev-rules
ostree
systemd
usrmount
base
fs-lib
shutdown
========================================================================
drwxr-xr-x 12 root root 0 Sep 1 00:52 .
crw-r--r-- 1 root root 5, 1 Sep 1 00:52 dev/console
crw-r--r-- 1 root root 1, 11 Sep 1 00:52 dev/kmsg
... (long list of files removed)
========================================================================
Initializing rootfs
Migrating /etc/passwd to /usr/lib/
Migrating /etc/group to /usr/lib/
Moving /usr to target
Linking /usr/local -> ../var/usrlocal
Moving /etc to /usr/etc
Placing RPM db in /usr/share/rpm
Ignoring non-directory/non-symlink '/var/tmp/rpm-ostree.TVO089/rootfs.tmp/var/lib/nss_db/Makefile'
Ignoring non-directory/non-symlink '/var/tmp/rpm-ostree.TVO089/rootfs.tmp/var/cache/ldconfig/aux-cache'
Ignoring non-directory/non-symlink '/var/tmp/rpm-ostree.TVO089/rootfs.tmp/var/log/btmp'
Ignoring non-directory/non-symlink '/var/tmp/rpm-ostree.TVO089/rootfs.tmp/var/log/lastlog'
Ignoring non-directory/non-symlink '/var/tmp/rpm-ostree.TVO089/rootfs.tmp/var/log/wtmp'
Moving /boot
Using boot location: both
Copying toplevel compat symlinks
Adding tmpfiles-ostree-integration.conf
Committing '/var/tmp/rpm-ostree.TVO089/rootfs.tmp' ...
photon/1.0/x86_64/minimal => c505f4bddb4381e8b5213682465f1e5bb150a18228aa207d763cea45c6a81bbe
I’ve cut a big part of logging, but as you can see, the new filetree adds to the top of the previous (initial) commit 2940e10c4d and produces a new commit c505f4bddb. Our packages gawk-4.1.0-2.ph3.x86_64, sudo-1.8.11p1-4.ph3.x86_64 and wget-1.15-1.ph3.x86_64 have been added.
During compose, rpm-ostree
checks out the file tree into its uncompressed form, applies the package changes, places the updated RPM repo into /usr/share/rpm and calls ostree
to commit its changes back into the OSTree repo. If we were to look at the temp directory during this time:
root [ /srv/rpm-ostree ]# ls /var/tmp/rpm-ostree.TVO089/rootfs.tmp
bin dev lib media opt proc run srv sysroot usr
boot home lib64 mnt ostree root sbin sys tmp var
If we repeat the command, and there is no change in the JSON file settings and no change in metadata, rpm-ostree will figure out that nothing has changed and stop. You can force however to redo the whole composition.
root [ /srv/rpm-ostree ]# rpm-ostree compose tree --repo=repo photon-base.json
Previous commit: c505f4bddb4381e8b5213682465f1e5bb150a18228aa207d763cea45c6a81bbe
Downloading metadata [=========================================================================] 100%
No apparent changes since previous commit; use --force-nocache to override
This takes several minutes. Then why is the RPM-OSTree server installing so fast, in 45 seconds on my SSD? The server doesn’t compose the tree, it uses a pre-created OSTree repo that is stored on the CD-ROM. It comes of course at the expense of larger CD-ROM size. This OSTree repo is created from the same set of RPMS on the CD-ROM, so if you compose fresh, you will get the same exact tree, with same commit ID for the “minimal” ref.
Automatic version prefix
If you recall the filetree version explained earlier, this is where it comes into play. When a tree is composed from scratch, the first version (0) associated to the initial commit is going to get that human readable value. Any subsequent compose operation will auto-increment to .1, .2, .3 and so on.
It’s a good idea to start a versionning scheme of your own, so that your customized Photon builds that may get different packages of your choice don’t get the same version numbers as the official Photon team builds, coming from VMware’s bintray OSTree repository. There is no conflict, it’s just confusing to have same name for different commits coming from different repos,
So if you work for a company named Big Data Inc., you may want to switch to a new versioning scheme "automatic_version_prefix": "1.0_bigdata"
.
Installing package updates
If you want to provide hosts with the package updates that VMware periodically releases, all that you need to do is to add the photon-updates.repo to the list of repos in photon-base.json and then re-compose the usual way.
"repos": ["photon", "photon-updates"],
Even though you may have not modified the “packages” section in the json file, the newer versions of existing packages will be included in the new image and then downloaded by the host the usual way. Note that upgrading a package shows differently than adding (+) or removing (-). You may still see packages added (or removed) though because they are new dependencies (or no longer dependencies) for the newer versions of other packages, as libssh2 in the example below.
root [ ~ ]# rpm-ostree upgrade --check-diff
Updating from: photon:photon/3.0/x86_64/minimal
8 metadata, 13 content objects fetched; 1002 KiB transferred in 0 seconds
!bridge-utils-1.5-2.ph3.x86_64
=bridge-utils-1.5-3.ph3.x86_64
!bzip2-1.0.6-5.ph3.x86_64
=bzip2-1.0.6-6.ph3.x86_64
!curl-7.47.1-2.ph3.x86_64
=curl-7.51.0-2.ph3.x86_64
!docker-1.11.0-5.ph3.x86_64
=docker-1.12.1-1.ph3.x86_64
...
+libssh2-1.8.0-1.ph3.x86_64
...
root [ ~ ]# rpm-ostree upgrade
Updating from: photon:photon/1.0/x86_64/minimal
258 metadata, 1165 content objects fetched; 76893 KiB transferred in 8 seconds
Copying /etc changes: 6 modified, 0 removed, 14 added
Transaction complete; bootconfig swap: yes deployment count change: 1
Changed:
bridge-utils 1.5-2.ph3 -> 1.5-3.ph3
bzip2 1.0.6-5.ph3 -> 1.0.6-6.ph3
curl 7.47.1-2.ph3 -> 7.51.0-2.ph3
docker 1.11.0-5.ph3 -> 1.12.1-1.ph3
...
Added:
libssh2-1.8.0-1.ph3.x86_64
Upgrade prepared for next boot; run "systemctl reboot" to start a reboot
Now if we want to see what packages have been updated and what issues have been fixed, just run at the host the command that we learned about in chapter 5.4.
root [ ~ ]# rpm-ostree db diff 56ef 396e
ostree diff commit old: 56e (56ef687f1319604b7900a232715718d26ca407de7e1dc89251b206f8e255dcb4)
ostree diff commit new: 396 (396e1116ad94692b8c105edaee4fa12447ec3d8f73c7b3ade4e955163d517497)
Upgraded:
bridge-utils-1.5-3.ph3.x86_64
* Mon Sep 12 2016 Alexey Makhalov <amakhalov@vmware.com> 1.5-3
- Update patch to fix-2.
bzip2-1.0.6-6.ph3.x86_64
* Fri Oct 21 2016 Kumar Kaushik <kaushikk@vmware.com> 1.0.6-6
- Fixing security bug CVE-2016-3189.
curl-7.51.0-2.ph3.x86_64
* Wed Nov 30 2016 Xiaolin Li <xiaolinl@vmware.com> 7.51.0-2
- Enable sftp support.
* Wed Nov 02 2016 Anish Swaminathan <anishs@vmware.com> 7.51.0-1
- Upgrade curl to 7.51.0
* Thu Oct 27 2016 Anish Swaminathan <anishs@vmware.com> 7.47.1-4
- Patch for CVE-2016-5421
* Mon Sep 19 2016 Xiaolin Li <xiaolinl@vmware.com> 7.47.1-3
- Applied CVE-2016-7167.patch.
docker-1.12.1-1.ph3.x86_64
* Wed Sep 21 2016 Xiaolin Li <xiaolinl@vmware.com> 1.12.1-1
- Upgraded to version 1.12.1
* Mon Aug 22 2016 Alexey Makhalov <amakhalov@vmware.com> 1.12.0-2
- Added bash completion file
* Tue Aug 09 2016 Anish Swaminathan <anishs@vmware.com> 1.12.0-1
- Upgraded to version 1.12.0
* Tue Jun 28 2016 Anish Swaminathan <anishs@vmware.com> 1.11.2-1
- Upgraded to version 1.11.2
...
Added:
libssh2-1.8.0-1.ph3.x86_64
Composing for a different branch
RPM-OSTree makes it very easy to create and update new branches, by composing using json config files that include the Refspec as the new branch name, the list of packages and the other settings we are now familiar with. Photon OS 2.0 RPM-OSTRee Server installer adds two extra files photon-minimal.json and photon-full.json in addition to photon-base.json, that correspond almost identically to the minimal and full profiles installed via tdnf. It also makes ‘photon-base’ a smaller set of starter branch.
Of course, you can create your own config files for your branches with desired lists of packages. You may compose on top of the existing tree, or you can start fresh your own OSTRee repo, using your own customized versioning.
11.11 - Remotes
In Chapter 3 we talked about the Refspec that contains a photon: prefix, that is the name of a remote. When a Photon host is installed, a remote is added - which contains the URL for an OSTree repository that is the origin of the commits we are going to pull from and deploy filetrees, in our case the Photon RPM-OSTree server we installed the host from. This remote is named photon, which may be confusing, because it’s also the OS name and part of the Refspec (branch) path.
Listing remotes
A host repo can be configured to switch between multiple remotes to pull from, however only one remote is the “active” one at a time. We can list the remotes created so far, which brings back the expected result.
root@photon-host-def [ ~ ]# ostree remote list
photon
photon-1
We can inquiry about the URL for that remote name, which for the default host is the expected Photon OS online OSTree repo.
root@photon-host-def [ ~ ]# ostree remote show-url photon
https://<host-name>:8080/repo
But where is this information stored? The repo’s config file has it.
root@photon-host-def [ ~ ]# cat /ostree/repo/config
[core]
repo_version=1
mode=bare
[remote "photon"]
url=http:<Server-IP-Address:port>/repo
gpg-verify=false
If same command is executed on the custom host we’ve installed, it’s going to reveal the URL of the Photon RPM-OSTree server connected to during setup.
root@photon-host-cus [ ~ ]# ostree remote show-url photon
http://10.197.103.175:8000/repo
GPG signature verification
You may wonder what is the purpose of gpg-verify=false
in the config file, associated with the specific remote. This will instruct any host update to skip the signing verification for the updates that come from server, resulted from tree composed locally at the server, as they are not signed. Without this, host updating will fail.
There is a whole chapter about signing, importing keys and so on that I will not get into, but the idea is that signing adds an extra layer of security, by validating that everything you download comes from the trusted publisher and has not been altered. That is the case for all Photon OS artifacts downloaded from VMware official site. All OVAs and packages, either from the online RPMS repositories or included in the ISO file - are signed by VMware. We’ve seen a similar setting gpgcheck=1
in the RPMS repo configuration files that tdnf uses to validate or not the signature for all packages downloaded to be installed.
Switching repositories
Since mapping name/url is stored in the repo’s config file, in principle you can re-assign a different URL, connecting the host to a different server. The next upgrade will get the latest commit chain from the new server.
If we edit photon-host-def’s repo config and replace the bintray URL by photon-srv1’s IP address, all original packages in the original 3.0_minimal version will be preserved, but any new package change (addition, removal, upgrade) added after that (in 3.0_minimal.1, 3.0_minimal.2) will be reverted and all new commits from photon-srv1 (that may have same version) will be applied. This is because the two repos are identical copies, so they have the same original commit ID as a common ancestor, but they diverge from there.
If the old and new repo have nothing in common (no common ancestor commit), this will undo even the original commit, so all commits from the new tree will be applied.
A better solution would be to add a new remote that will identify where the commits come from.
Adding and removing remotes
A cleaner way to switch repositories is to add remotes that point to different servers. Let us add another server that we will refer to as photon2, along with (optional) the refspecs for branches that it provides (we will see later that in the newer OSTree versions, we don’t need to know the branch names, they could be queried at run-time).
root@photon-host-cus [ ~ ]# ostree remote add --repo=/ostree/repo -v --no-gpg-verify photon2 http://10.197.103.204:8080 photon/3.0/x86_64/minimal photon/3.0/x86_64/full
root@photon-host-cus [ ~ ]# ostree remote list
photon
photon2
root@photon-host-cus [ ~ ]# ostree remote show-url photon2
http://10.118.101.86
Where is this information stored? There is an extra config file created per each remote:
root@photon-host-cus [ ~ ]# cat /etc/ostree/remotes.d/photon2.conf
[remote "photon2"]
url=http://10.118.101.86
branches=photon/3.0/x86_64/minimal;photon/2.0/x86_64/full;
gpg-verify=false
You may have guessed what is the effect of --no-gpg-verify option
.
Obviously, remotes could also be deleted.
root@photon-host-cus [ ~ ]# ostree remote delete photon2
root@photon-host-cus [ ~ ]# ostree remote list
photon
List available branches
If a host has been deployed from a specific branch and would like to switch to a different one, maybe from a different server, how would it know what branches are available? In git, you would run git remote show origin
or git remote -a
(although last command would not show all branches, unless you ran git fetch
first).
Fortunately, in Photon OS 3.0 and higher, the hosts are able to query the server, if summary metadata has been generated, as we’ve seen in Creating summary metadata. This command lists all branches available for remote photon2.
root@photon-host-cus [ ~ ]# ostree remote refs photon2
photon2:photon/3.0/x86_64/base
photon2:photon/3.0/x86_64/full
photon2:photon/3.0/x86_64/minimal
Switching branches (rebasing)
If you have an installed Photon 1.0 or 1.0 Rev2 that you want to carry to 3.0, you need to rebase it.
See Rebasing a host from Photon 1.0 to 3.0.
11.12 - Running container applications between bootable images
In this chapter, we want to test a docker application and make sure that all the settings and downloads done in one bootable filetree are going to be saved into writable folders and be available in the other image, in other words after reboot from the other image, everything is available exactly the same way.
We are going to do this twice: first, to verify an existing bootable image installed in parallel and then create a new one.
Downloading a docker container appliance
Photon OS comes with docker package installed and configured, but we expect that the docker daemon is inactive (not started). Configuration file /usr/lib/systemd/system/docker.service is read-only (remember /usr is bound as read-only).
root@sample-host-def [ ~ ]# systemctl status docker
* docker.service - Docker Daemon
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled)
Active: inactive (dead)
root@sample-host-def [ ~ ]# cat /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
Now let’s enable docker daemon to start at boot time - this will create a symbolic link into writable folder /etc/systemd/system/multi-user.target.wants to its systemd configuration, as with all other systemd controlled services.
root@sample-host-def [ ~ ]# systemctl enable docker
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service -> /lib/systemd/system/docker.service.
root@sample-host-def [ ~ ]# ls -l /etc/systemd/system/multi-user.target.wants
total 0
lrwxrwxrwx 1 root root 34 Sep 10 10:48 docker.service -> /lib/systemd/system/docker.service
lrwxrwxrwx 1 root root 36 Sep 4 04:59 iptables.service -> /lib/systemd/system/iptables.service
lrwxrwxrwx 1 root root 35 Sep 4 04:59 machines.target -> /lib/systemd/system/machines.target
lrwxrwxrwx 1 root root 36 Sep 4 04:59 remote-fs.target -> /lib/systemd/system/remote-fs.target
lrwxrwxrwx 1 root root 39 Sep 4 04:59 sshd-keygen.service -> /lib/systemd/system/sshd-keygen.service
lrwxrwxrwx 1 root root 32 Sep 4 04:59 sshd.service -> /lib/systemd/system/sshd.service
lrwxrwxrwx 1 root root 44 Sep 4 04:59 systemd-networkd.service -> /lib/systemd/system/systemd-networkd.service
lrwxrwxrwx 1 root root 44 Sep 4 04:59 systemd-resolved.service -> /lib/systemd/system/systemd-resolved.service
To verify that the symbolic link points to a file in a read-only directory, try to make a change in this file using vim and save. you’ll get an error: “/usr/lib/systemd/system/docker.service” E166: Can’t open linked file for writing".
Finally, let’s start the daemon, check again that is active.
root@sample-host-def [ ~ ]# systemctl start docker
root@sample-host-def [ ~ ]# systemctl status -l docker
* docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2019-09-10 10:54:32 UTC; 14s ago
Docs: https://docs.docker.com
Main PID: 2553 (dockerd)
Tasks: 35 (limit: 4711)
Memory: 148.2M
CGroup: /system.slice/docker.service
|-2553 /usr/bin/dockerd
`-2566 docker-containerd --config /var/run/docker/containerd/containerd.toml
Sep 10 10:54:31 photon-76718dd2fa33 dockerd[2553]: time="2019-09-10T10:54:31.421759662Z" level=info msg="pickfirstBalancer: HandleSubConnStateChange: 0xc420312f90, CONNECTING" module=grpc
Sep 10 10:54:31 photon-76718dd2fa33 dockerd[2553]: time="2019-09-10T10:54:31.421935355Z" level=info msg="pickfirstBalancer: HandleSubConnStateChange: 0xc420312f90, READY" module=grpc
Sep 10 10:54:31 photon-76718dd2fa33 dockerd[2553]: time="2019-09-10T10:54:31.421980614Z" level=info msg="Loading containers: start."
Sep 10 10:54:31 photon-76718dd2fa33 dockerd[2553]: time="2019-09-10T10:54:31.886520281Z" level=info msg="Default bridge
(docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address"
Sep 10 10:54:32 photon-76718dd2fa33 dockerd[2553]: time="2019-09-10T10:54:32.027763113Z" level=info msg="Loading containers: done."
Sep 10 10:54:32 photon-76718dd2fa33 dockerd[2553]: time="2019-09-10T10:54:32.468277184Z" level=info msg="Docker daemon"
commit=6d37f41 graphdriver(s)=overlay2 version=18.06.2-ce
Sep 10 10:54:32 photon-76718dd2fa33 dockerd[2553]: time="2019-09-10T10:54:32.468441587Z" level=info msg="Daemon has completed initialization"
Sep 10 10:54:32 photon-76718dd2fa33 dockerd[2553]: time="2019-09-10T10:54:32.684925824Z" level=warning msg="Could not register builder git source: failed to find git binary: exec: \"git\": executable file not found in $PATH"
Sep 10 10:54:32 photon-76718dd2fa33 dockerd[2553]: time="2019-09-10T10:54:32.691070166Z" level=info msg="API listen on /var/run/docker.sock"
Sep 10 10:54:32 photon-76718dd2fa33 systemd[1]: Started Docker Application Container Engine.
We’ll ask docker to run Ubuntu Linux in a container. Since it’s not present locally, it’s going to be downloaded first from the official docker repository https://hub.docker.com/_/ubuntu/.
root@sample-host-def [ ~ ]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@sample-host-def [ ~ ]# docker run -it ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
35c102085707: Pull complete
251f5509d51d: Pull complete
8e829fe70a46: Pull complete
6001e1789921: Pull complete
Digest: sha256:d1d454df0f579c6be4d8161d227462d69e163a8ff9d20a847533989cf0c94d90
Status: Downloaded newer image for ubuntu:latest
When downloading is complete, it comes to Ubuntu root prompt with assigned host name 7029a64e7aa3, that is actually the Container ID. Let’s verify it’s indeed the expected OS.
root@sample-host-def [ ~ ]# docker run -it ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
d3a1f33e8a5a: Pull complete
c22013c84729: Pull complete
d74508fb6632: Pull complete
91e54dfb1179: Already exists
library/ubuntu:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:fde8a8814702c18bb1f39b3bd91a2f82a8e428b1b4e39d1963c5d14418da8fba
Status: Downloaded newer image for ubuntu:latest
root@7029a64e7aa3:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.3 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.3 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
root@7029a64e7aa3:/#
Now let’s write a file into Ubuntu home directory
echo "Ubuntu file" >> /home/myfile
root@7029a64e7aa3:/home# cat /home/myfile
Ubuntu file
We’ll exit back to the Photon prompt and if it’s stopped, we will re-start it.
root@7029a64e7aa3:/# exit
exit
root@sample-host-def [ ~ ]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7029a64e7aa3 ubuntu "/bin/bash" 6 minutes ago Exited (0) 11 seconds ago gifted_dijkstra
root@photon-host-cus1 [ ~ ]# docker start 7029a64e7aa3
7029a64e7aa3
root@photon-host-cus1 [ ~ ]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7029a64e7aa3 ubuntu "/bin/bash" 7 minutes ago Up 21 seconds gifted_dijkstra
Rebooting into an existing image
Now let’s reboot the machine and select the other image. First, we’ll verify that the docker daemon is automaically started.
root@photon-host-cus1 [ ~ ]# systemctl status docker
* docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2019-09-10 10:54:32 UTC; 13min ago
Docs: https://docs.docker.com
Main PID: 2553 (dockerd)
Tasks: 55 (limit: 4711)
Memory: 261.3M
CGroup: /system.slice/docker.service
|-2553 /usr/bin/dockerd
...
Next, is the Ubuntu OS container still there?
root@photon-host-cus1 [ ~ ]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7029a64e7aa3 ubuntu "/bin/bash" 9 minutes ago Up 2 minutes gifted_dijkstra
It is, so let’s start it, attach and verify that our file is persisted, then add another line to it and save, exit.
root@photon-host-cus1 [ ~ ]# docker start -i 7029a64e7aa3
root@7029a64e7aa3:/# cat /home/myfile
Ubuntu file
root@7029a64e7aa3:/# echo "booted into existing image" >> /home/myfile
root@7029a64e7aa3:/# exit
exit
Reboot into a newly created image
Let’s upgrade and replace the .0 image by a .3 build that contains git and also perl_YAML (because it is a dependency of git).
root@photon-host-cus1 [ ~ ]# rpm-ostree status
TIMESTAMP (UTC) VERSION ID OSNAME REFSPEC
* 2015-09-04 00:36:37 3.0_tp2_minimal.2 092e21d292 photon photon:photon/tp2/x86_64/minimal
2015-08-20 22:27:43 3.0_tp2_minimal 2940e10c4d photon photon:photon/tp2/x86_64/minimal
root@photon-host-cus1 [ ~ ]# rpm-ostree upgrade
Updating from: photon:photon/tp2/x86_64/minimal
43 metadata, 209 content objects fetched; 19992 KiB transferred in 0 seconds
Copying /etc changes: 5 modified, 0 removed, 19 added
Transaction complete; bootconfig swap: yes deployment count change: 0
Freed objects: 16.2 MB
Added:
git-2.1.2-1.ph3tp2.x86_64
perl-YAML-1.14-1.ph3tp2.noarch
Upgrade prepared for next boot; run "systemctl reboot" to start a reboot
root@photon-host-cus1 [ ~ ]# rpm-ostree status
TIMESTAMP (UTC) VERSION ID OSNAME REFSPEC
2015-09-06 18:12:08 3.0_tp2_minimal.3 d16aebd803 photon photon:photon/tp2/x86_64/minimal
* 2015-09-04 00:36:37 3.0_tp2_minimal.2 092e21d292 photon photon:photon/tp2/x86_64/minimal
After reboot from 3.0_tp2_minimal.3 build, let’s check that the 3-way /etc merge succeeded as expected. The docker.service slink is still there, and docker demon restarted at boot.
root@photon-host-cus1 [ ~ ]# ls -l /etc/systemd/system/multi-user.target.wants/docker.service
lrwxrwxrwx 1 root root 38 Sep 6 12:50 /etc/systemd/system/multi-user.target.wants/docker.service -> /usr/lib/systemd/system/docker.service
root@photon-host-cus1 [ ~ ]# systemctl status docker
* docker.service - Docker Daemon
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
Active: active (running) since Sun 2015-09-06 12:56:33 UTC; 1min 27s ago
Main PID: 292 (docker)
CGroup: /system.slice/docker.service
`-292 /bin/docker -d -s overlay
...
Let’s revisit the Ubuntu container. Is the container still there? is myfile persisted?
root@photon-host-cus1 [ ~ ]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7029a64e7aa3 ubuntu "/bin/bash" 5 days ago Exited (0) 5 days ago gifted_dijkstra
55825c961f95 ubuntu "/bin/bash" 5 days ago Exited (127) 5 days ago distracted_shannon
root@photon-host-cus1 [ ~ ]# docker start 57dcac5d0490
root@57dcac5d0490:/# cat /home/myfile
Ubuntu file
booted into existing image
root@57dcac5d0490:/# echo "booted into new image" >> /home/myfile
11.13 - Install or rebase to Photon OS 3.0
Photon OS 3.0 provides full RPM-OSTree functionality, it lets the user drive it, rather than provide a pre-defined solution as part of the installation.
The number of packages included in the RPMS repo in Photon OS 3.0 increased significantly, compared to 1.0. To keep the ISO at reasonable size, Photon OS 2.0 no longer includes the compressed ostree.repo file, that helped optimize both the server and host install in 1.0 or 1.0 Rev2. That decision affected the OSTree features we ship out of the box. Customer could achieve the same results by several additional simple steps, that will be explained in this chapter. In addition, there is a new way to create a host raw image at server.
Composing your own RPM-OSTree Server
You can compose your own RPM-OSTRee server in the following two ways:
By Manually executing the below command:
root [ /srv/rpm-ostree ]# ostree --repo=repo init --mode=archive-z2
root [ /srv/rpm-ostree ]# rpm-ostree compose tree --repo=repo photon-base.json
By installing rpm-ostree-repo package
. This provides the script to create the repo tree which act as server by executing a single command.
Installing an RPM-OSTree host
Automated host install is supported, as explained in Chapter 7.2 Automated install of a custom host via kickstart.
Rebasing a host from Photon 1.0 to 3.0
If kickstart sounds too complicated and we still want to go the UI way there is a workaround that requires an extra step. Also, if you have an installed Photon 1.0 or 1.0 Rev2 that you want to carry to 3.0, you need to rebase it. Notice that I didn’t say “upgrade”.
Basically the OSTree repo will switch to a different branch on a different server, following the new server’s branch versioning scheme. The net result is that the lots of packages will get changed to newer versions from newer OSTree repo, that has been composed from a newer Photon OS 3.0 RPMS repo. Again, I didn’t say “upgraded”, neither the rebase command output, that lists “changed” packages. Some obsolete packages will be removed, new packages will be added, either because they didn’t exist in 2.0 repo, or because the new config file includes them.
The OS name is the same (Photon), so the content in /var and /etc will be transferred over.
To install fresh, deploy a Photon 1.0 Rev2 host default, as described in Chapter 2. Of course, if you already have an existing Photon OS 1.0 host that you want to move to 2.0, skip this step.
Edit /ostree/repo/config and substitute the url, providing the IP address for the Photon OS 2.0 RPM-OSTree server installed above. This was explained in Chapter 10.
ostree should confirm that is the updated server IP for the “photon” remote.
root@ostree-host [ ~ ]# ostree remote show-url photon
http://10.197.103.175:8000/repo
Rebase your host to the new 2.0 server and Refspec.
root@ostree-host [ ~ ]# ostree remote add photon-2 http://10.197.103.204:8000/repo --no-gpg-verify
root@ostree-host [ ~ ]# rpm-ostree rebase photon-2:photon/3.0/x86_64/minimal
Rebasing to photon-2:photon/3.0/x86_64/minimal
⠉ Receiving objects: 99% (1541/1549) 478.3 kB/s 107.1 MB
Receiving objects: 99% (1541/1549) 478.3 kB/s 107.1 MB... done
Staging deployment... done
Upgraded:
docker 18.06.2-3.ph3 -> 18.06.2-4.ph3
gmp 6.1.2-2.ph3 -> 6.1.2-3.ph3
gobject-introspection 1.58.0-2.ph3 -> 1.58.0-3.ph3
gzip 1.9-1.ph3 -> 1.9-2.ph3
linux 4.19.65-3.ph3 -> 4.19.69-1.ph3
mpfr 4.0.1-1.ph3 -> 4.0.1-2.ph3
ostree 2019.2-1.ph3 -> 2019.2-2.ph3
ostree-grub2 2019.2-1.ph3 -> 2019.2-2.ph3
ostree-libs 2019.2-1.ph3 -> 2019.2-2.ph3
zlib 1.2.11-1.ph3 -> 1.2.11-2.ph3
Added:
efibootmgr-15-1.ph3.x86_64
efivar-36-1.ph3.x86_64
tar-1.30-3.ph3.x86_64
Run "systemctl reboot" to start a reboot
Check the status
root@ostree-host [ ~ ]# rpm-ostree status
State: idle
AutomaticUpdates: disabled
Deployments:
* ostree://photon-1:photon/3.0/x86_64/minimal
Version: 3.0_minimal.2 (2019-09-18T08:22:15Z)
BaseCommit: c8f2b116b067d7695f9033bf2a99505198269354e157c0f2d5b78266cb874239
LayeredPackages: createrepo_c rpm wget
ostree://photon:photon/1.0/x86_64/minimal
Version: 1.0_minimal.1 (2017-01-11T02:18:42)
BaseCommit: 28dc49ecb4604c0bc349e4445adc659491a1874c01198e6253a261f4d59708b7
LayeredPackages: createrepo_c rpm wget
You may now reboot to the new Photon OS 3.0 image.
Creating a host raw image
It is now possible to run at server a script that is part of RPM-OStree package, to create a host raw mage.