This the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

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: 5.0

This documentation applies to all 5.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, python3.spec appears as follows::

%global VER 3.11
%global with_gdb_hooks 1

Summary:        A high-level scripting language
Name:           python3
Version:        3.11.0
Release:        6%{?dist}
License:        PSF
URL:            http://www.python.org
Group:          System Environment/Programming
Vendor:         VMware, Inc.
Distribution:   Photon

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 (aka “developer”) version by examining the following file:

https://github.com/vmware/photon/blob/master/common/data/packages_full.json

If the minimal or the developer 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:

```console
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 and later.

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
gpg-pubkey-8a6a826d-596882ca

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 ...
rpm -qi gpg-pubkey-8a6a826d-596882ca
Name        : gpg-pubkey
Version     : 8a6a826d
Release     : 596882ca
Architecture: (none)
Install Date: Tue 18 Apr 2023 10:17:59 AM UTC
Group       : Public Keys
Size        : 0
License     : pubkey
Signature   : (none)
Source RPM  : (none)
Build Date  : Fri 14 Jul 2017 08:37:30 AM UTC
Build Host  : localhost
Packager    : VMware, Inc. (Linux Packaging Key) <linux-packages@vmware.com>
Summary     : VMware, Inc. (Linux Packaging Key) <linux-packages@vmware.com> public key
Description :
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: rpm-4.18.0

mQINBFlogsoBEACylcZdKvVdq+XZZ5oXyV7+Wk4wYo9ALIy5Y/TlQ7YoJndF3A6d
j3KXLFZ3xLMYuktUwqEiVN24s2loAG3kcS5c8bb7LxiZMFoEfo8bUm8mcfcPKCdy
ZgE0TNwYejn6w9tuEOLtewVtFaP3FrCjzZz2VMXi5c9sNxmIxfrBuuDZP8MLoDKr
fv4Zzif2K6J4nRMBY2t8SSj8Z4zDUCLQ36wYlD2slONdmX8Ufd86rt/ZJ156xsCX
2UgTb62uUVESlWfsuMhv5CBO2JEbbnMBjfZdI5qplwEt54kq34PzP6fRCa8yrLR8
FlZsAQO32A0SDNUWHphDP3d2W64XtttjRJPsWv16IXss1YwyjUd1CBYDpefXvzW2
h8Ca6HDgLRG0eoVZdY8gx1geF64wuGjSA+4gnjTaMeLQSBfeAzm6Pe4eB6bEc/iX
NiZY9KlA1orRcuHxXIzjsHR5f1JCK0Fgl76aNzxnztuU0uRSLZRxUMUpszCOyqy9
ufsbMeklbKtobfVqRulQEJwCXHL99t+Ln14L3PgXKeLqaj/LReIqWlWiFtm6Zgyf
a45z8lf8Z3lRK+orrNJ8fVJr/8T9O/vgpbwwqEZ2bflzqXcUPyWnMl6Cu8SNbtwK
orvZ1bwNkz5T9myW+6pXcr9sB/IiNmyfTS1rXqwUlRN60vwD+a52MpnCGwARAQAB
tD5WTXdhcmUsIEluYy4gKExpbnV4IFBhY2thZ2luZyBLZXkpIDxsaW51eC1wYWNr
YWdlc0B2bXdhcmUuY29tPokCNgQTAQIAIAUCWWiCygIbAwYLCQgHAwIEFQIIAwQW
AgMBAh4BAheAAAoJEHXACeqKaoJtIYIP/3y2+xIZ3ZArdhH6NR3ilMPGSVoe1M2+
10XlL9wydgXPdKrq8IZUNg5/VBEjpOZML82aD9VRkMXI6XdbrdRw+5G2D5ZOtWRp
ha8KPuFxax2YuB8ifRgcrgR0kq4v+p3XHaT88UQxk/gDpJVOMJaLhyn8KNBPVkPq
zJ3IXC/A/rWv6rbDAnyyt20GpCqWuoCJCQDMCbBItyaL42OWY3yk3WlfFOjQU1Sq
zIYCCJGM87rNHpwErHDIanFu0gXCarFB6uRT9ixgyJqg7dtPAyBdydxo0JesH0Fc
t30NYkRiqqeSz6ImWlcvDHZkiDXNvP0D9utyOPQDoIaX+G0gCnf+UpHTgc0eGc6U
+aHIyHMK7Du+cfTXL8W5LAbSw7pTPSPc/sZal1ijDvk1lyMhT6kZ22v2IXYadosp
eA7+9ykSk3Iy9qhjUTQ+qG/KMgUTMVqWUp6IEze80892w3yNFi8tEvdRzORbOHuP
IhyoLek4vQj+ziDm4C1ARrYk8AiW40ioRJuT73DF8RhuzD8hBt1tH6mjeIANz8Lf
1big996JofkxU2eN99MnhUeBxFrOCPef7y9h0rM7UqZHDo1HGxCZxd12COyspWkG
WsFN4VrLxkXhPfa8jc5TBY5e1632JoL+VuWFjKd0CddgtSm2bqfX355BQi6+eJ4A
kJ3L8QRJSNeY
=ogBe
-----END PGP PUBLIC KEY BLOCK-----

#

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 GConf-3.2.6-1.ph5.src.rpm
GConf-3.2.6-1.ph5.src.rpm: digests signatures OK

You can view the SHA1 digest and the RSA Data Security, Inc. MD5 Message Digest Algorithm by running the following command:

rpm -Kv GConf-3.2.6-1.ph5.src.rpm
GConf-3.2.6-1.ph5.src.rpm:
    Header V3 RSA/SHA256 Signature, key ID 66fd4949: OK
    Header SHA256 digest: OK
    Header SHA1 digest: OK
    Payload SHA256 digest: OK
    V3 RSA/SHA256 Signature, key ID 66fd4949: OK
    MD5 digest: OK
#

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 yum-compatible repositories and the repository on the Photon OS ISO when it is available on a CD-ROM drive:

# ls -l /etc/yum.repos.d/
total 24
-rw-r--r-- 1 root root 313 Apr 17 13:19 photon-debuginfo.repo
-rw-r--r-- 1 root root 238 Apr 17 13:19 photon-iso.repo
-rw-r--r-- 1 root root 299 Apr 17 13:19 photon-release.repo
-rw-r--r-- 1 root root 303 Apr 17 13:19 photon.repo
-rw-r--r-- 1 root root 331 Apr 17 13:19 photon-srpms.repo
-rw-r--r-- 1 root root 305 Apr 19 06:00 photon-updates.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 VMware Photon Packages 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 in the ISO, because they are updated more frequently.

The Photon repository (photon.repo) contains all the rpms released for a particular Photon release. This repository is disabled by default but can be enabled in case the end user wants to install an older version of an rpm.

The Photon Updates repository (photon-updates.repo) contains the latest versions of all the rpms for a particular Photon release. This repository is updated with the new rpm releases. This repository is enabled by default.

The Photon debuginfo repository (photon-debuginfo.repo) contains the debuginfo rpms which can be installed for debugging coredumps or issues. This repository is disabled by default.

The Photon release repository (photon-release.repo) contains the rpms snapped at the major release time. This repository is not updated after GA. This repository is disabled by default.

The Photon SRPM repository (photon-srpms.repo) contains all the source rpms for a particular Photon release. This can be used to extract the source which was used to build the rpm. This repository is disabled by default.

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 VMWare Packages repository: 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 becau–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.

Perform the following steps to install and build an example package- sed from its source RPM on Photon OS with an unprivileged account.

  1. 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
    
  2. 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}
    
  3. 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
    
  4. Place the source RPM file that you want to install and build in the /tmp directory.

  5. 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.

  6. 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.

  7. 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:

  • gcc
  • glibc-devel
  • binutils

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.

Tdnf appears in the minimal and full versions of Photon OS.

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/
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/
photon-extras.repo
photon-iso.repo
photon-updates.repo
photon.repo 

To view the format and information that a new repository configuration file should contain, see one of the .repo files. The following is an example:

[photon-release]
name=VMware Photon Linux $releasever ($basearch)
baseurl=https://packages.vmware.com/photon/$releasever/photon_release_$releasever_$basearch
gpgkey=file:///etc/pki/rpm-gpg/VMWARE-RPM-GPG-KEY
gpgcheck=1
enabled=1
skip_if_unavailable=True

You can configure multiple repositories in one repository configuration file. Configuration for each of the repositories must have a separate section and ID.

The repository settings details are as follows:

  • 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 among the system’s repositories; `.

  • The username setting specifies a username for the repository, if required.

  • The password setting sets a password for the repository, if required.

  • 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/

    You can also use the following protocols: http: https: ftp: ftps: file: You can add multiple URLs separated by commas. If download fails for one URL, the next URL is used. The URL can contain the variables $releasever and $basearch, which refers to the current release of the distribution (for example, 5.0) and the architecture (for example, x86_64 or aarch64).

  • You can use the metalink file to set hashes and priorities for URLs. To use the metalink feature, the tdnf-metalink plugin must be installed and loaded. A sample metalink file is as follows:

    cat metalink

    <?xml version="1.0" encoding="utf-8"?>
    
    <metalink version="3.0" xmlns="http://www.metalinker.org/" type="dynamic" pubdate="Wed, 05 Feb 2020 08:14:56 GMT" generator="mirrormanager" xmlns:mm0="http://fedorahosted.org/mirrormanager">
    
     <files>
    
      <file name="repomd.xml">
    
       <size>2035</size>
    
       <verification>
    
    <hash type="sha1">478437547dac9f5a73fe905d2ed2a0a5b153ef46</hash>
    
    <hash type="sha512">6c6fbfba288ec90905a8d2220a0bfd2a50e835b7faaefedb6978df6ca59c5bce25cc1ddd33023e305b20bcffc702ee2bd61d0855f4f1b2fd7c8f5109e428a764</hash>
    
       </verification>
    
       <resources maxconnections="1">
    
    <url protocol="http" type="http" location="IN" preference=“100”>https://packages.vmware.com/photon/3.0/photon_updates_3.0_x86_64/repodata/repomd.xml</url>
    
       </resources>
    
      </file>
    
     </files>
    
    </metalink>
    

    In the metalink file, provide the preference for each url, so tdnf first tries to sync the repository data from the mirror which has the highest preference. If it fails for any reason, tdnf will use the next mirror URL.

    Note: Ensure that the shasum for respomd.xml in all the mirrors should be same.

  • The metadata_expire setting specifies the expiry time limit for the downloaded metadata in seconds. After the set limit expires, metadata is refreshed on the next action that requires them. The default value is 172800 seconds.

  • The priority setting specifies the priority of the repositories.

  • The gpgcheck setting specifies whether to check the GPG signature. The default value is true. If you enable this setting, set the gpgkey.

  • The repo_gpgcheck setting allows tdnf to verify the signature of a repository metadata before downloading the repository artifacts. When repo_gpgcheck is set to 1 in the tdnf.conf file, all repositories are checked for the metadata signatures. The default value is 0. To use the repo_gpgcheck feature, the tdnf repogpgcheck plugin must be installed and enabled. If a repository has repo_gpgcheck enabled,a repomd.xml.asc file is downloaded and the API equivalent of gpg --verify repomd.xml.asc repomd.xml is done. If repomd.xml.asc is missing, repository is deactivated. If repomd.xml.asc fails to verify, the repository is deactivated. The public key for verification must be manually installed for the initial implementation.

    Note: Ensure that you have installed libgcrypt for this implementation.

  • 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 repository configuration also supports public keys that are remote for the gpgkey option. So, the URLs starting with http, https, or ftp can be used for gpgkey.

    For example: gpgkey=http://build-squid.eng.vmware.com/build/mts/release/bora-16633979/publish/packages/keys/vmware.asc

  • You can use the enabled setting to enable the repository. The default value is false. You can override this setting with --disablerepo, --enablerepo, and --repoid options on the command line.

  • The skip_if_unavailable setting instructs tdnf to continue running if the repository goes offline.

  • The retries setting in the repository configuration specifies the number of retries when downloading a file throws an error. The default is 10.

  • The timeout setting specifies the number of seconds that a download is allowed to take or 0 for no limit. Note that this is an absolute value and may interrupt large file downloads.

  • The minrate setting specifies the limit below which if the download rate falls, tdnf aborts the download. The default value is 0 (no limit).

  • The maxrate setting specifies the maximum download rate (throttle). The default value is 0 (no limit).

  • 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 benefits and drawbacks of 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 setting improves the download and processing time but affects the repoquery queries for files. The default value is 0.

    • skip_md_other: The skip_md_other=1 setting deactivates the download of miscellaneous data like the changelog data of packages. The setting improves the download and processing time but affects the repoquery queries for changelogs. 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 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.

You can also specify the SSL Certificate details in the following settings:

  • sslcacert: Use a string value.
  • sslclientcert: Use a string value.
  • sslclientkey: Use a string value.
  • sslverify: Specify whether to perform the SSL verification. The default value is true.

2.4 - Mount the Photon ISO Image for the Photon-ISO 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 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:

  1. 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://packages.vmware.com/photon/dev/photon_dev_$basearch
    gpgkey=file:///etc/pki/rpm-gpg/VMWARE-RPM-GPG-KEY
    gpgcheck=1
    enabled=1
    skip_if_unavailable=True
    EOF
    .
  1. 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 - tdnf-automatic

tdnf-automatic is an alternative Command Line Interface (CLI) to tdnf upgrade/tdnf update with specific features so that it is suitable to be executed automatically and regularly from systemd timers, cron jobs, and so on.

The operation of the tool is usually controlled by the configuration file or the function-specific timer units. The command only accepts a single optional argument pointing to the config file, and some control arguments intended for use by the services that back the timer units. If no configuration file is passed from the command line,then /etc/tdnf/automatic.conf is used.

The tool synchronizes package metadata as needed and then checks for the updates available for the given system and then either exits or shows available updates or downloads and installs the packages.

The outcome of the operation is then reported through stdio.

The systemd timer unit tdnf-automatic.timer behaves as the configuration file specifies whether to download and apply updates. Some other timer units are provided which override the configuration file with some standard behaviors:

* tdnf-automatic-notifyonly

* tdnf-automatic-install

Irrespective of the configuration file settings, the first only notifies of available updates. The second one downloads and installs the updates.

Run tdnf-automatic

You can select one that most closely fits your needs, customize /etc/tdnf/automatic.conf for any specific behaviors, and enable the timer unit.

For example: systemctl enable –now tdnf-automatic-notifyonly.timer

Configuration file format

The configuration file is separated into two sections. This basically gives info on what can be put in /etc/tdnf/automatic.conf. ‘automatic.conf’ is a configuration INI file.

Format

tdnf-automatic help:

tdnf-automatic [{-c|--conf config-file}(optional)] [{-i|--install}] [{-n|--notify}] [{-h|--help}] [{-v|--version}]



-c, --conftdnf-automatic configuration file (Optional argument)

-i, --installOverride automatic.conf apply_updates and install updates

-n, --notifyShow available updates

-h, --helpShow this help message

-v, --versionShow tdnf-automatic version information

Commands

To set the mode of the operation of the program:

  • apply_updates (boolean, default: no) Whether packages comprising the available updates should be applied by tdnf-automatic.timer, i.e. installed via RPM. Note that the other timer units override this setting.

  • show_updates (boolean, default: yes) To just receive updates use tdnf-automatic-notifyonly.timer

  • network_online_timeout (time in seconds, default: 60) Maximum time tdnf-automatic will wait until the system is online. 0 means that network availability detection will be skipped.

  • random_sleep (time in seconds, default: 0) Maximum random delay before downloading. Note that, by default, the systemd timers also apply a random delay of up to 1 hour.

  • upgrade_type (either one of all or security. default: all) Looks at the kind of upgrades. all signals looking for all available updates. security indicates only those with an issued security advisory.

  • tdnf_conf (string, default: /etc/tdnf/tdnf.conf) Configurations to override default tdnf configuration.

Reports

To select how the results should be reported:

  • emit_to_stdio (boolean, default: yes) Report the results through stdio. If no, no report will be shown.

  • system_name (string, default: hostname of the given system) How the system is called in the reports.

  • emit_to_file (string, absolute path of file) If we want to capture the logs in a file

2.7 - Install Packages from CLI

You can install the packages from the command line. The package can be a file or a URL. The dependencies are installed automatically.

For example:

  • Using a URL:

      tdnf install https://packages.vmware.com/photon/5.0/photon_release_5.0_x86_64/x86_64/open-vm-tools-11.2.5-1.ph5.x86_64.rpm
    
      open-vm-tools-11.2.5-1.ph5.x86_64.rpm 763014   100%
    
      Installing:
    
      attrx86_642.4.48-1.ph5  photon  88.65k 90778
    
      nss x86_643.57-2.ph5photon  1.69M 1768005
    
      ...
    
      open-vm-tools   x86_6411.2.5-1.ph5  @cmdline2.65M 2779392
    
    
      Total installed size:  91.57M 96019175
    
    
      Upgrading:
    
      nss-libsx86_643.57-2.ph5photon  2.48M 2601790
    
      util-linux-libs x86_642.36-2.ph5photon752.75k 770816
    
      pcre-libs   x86_648.44-2.ph5photon275.60k 282216
    
    
    
      Total installed size:   3.49M 3654822
    
      Is this ok [y/N]: 
    
  • Using a file:

      tdnf install ../lsof-4.91-1.ph5.x86_64.rpm 
    
    
      Installing:
    
      libtirpcx86_641.2.6-1.ph5   photon193.56k 198209
    
      lsofx86_644.91-1.ph5@cmdline  196.10k 200810
    
      Total installed size: 389.67k 399019

2.8 - SSL Options

Photon OS offers support for the SSL Options.

You can set the following SSL options in the repository configuration file:

  • sslverify When downloading using https, this option helps to verify the SSL certificate of the server. You can set it to 0 or 1. The default is 1.

  • sslcacert You can use this option to set the path to a certificate file to verify the server.

  • sslclientcert You can use this option to set the path to a client certificate file.

  • sslclientkey You can set this path to the client key file.

2.9 - 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.9.1 - tdnf Commands

autoremove [pkg-spec]: This command removes a package with its dependencies. This is similar to the erase/remove command. You can use this command to remove the packages that are no longer needed regardless of the clean_requirements_on_remove option.

autoremove without any arguments removes all automatically installed packages that are no longer required.

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
Cleaning up everything

You can use this command to clean all configured repositories.

You can also use the following sub-commands or arguments to clean specific files:

metadata: This sub-command cleans up downloaded metadata from the repositories.

dbcache: This sub-command cleans up metadata generated from libsolv

packages: This sub-command removes downloaded packages from the cache.

keys: This sub-command removes downloaded keys from the cache.

expire-cache: This sub-command removes the cache expiry marker. This triggers a download of metadata on the next action that needs them.

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

When you remove a package, by default, tdnf does not remove the dependencies that are no longer used if tdnf installed them as dependencies. To remove the dependencies, modify the clean_requirements_on_remove option in the /etc/tdnf/tdnf.conf file to true, or use the autoremove command.

history: This command allows you to record every transaction (commands that install, update, or remove packages) in a database. You can roll back the transactions to a past state, or undo or redo a range of transactions.

There are five sub-commands or arguments that you can use with the history command:

history init/update: The sub-commands init or update initializes the history database. It is recommended that you use these commands right after tdnf is installed. If the database is not already initialized, any altering commands such as install or erase initializes the database.

If the database is already initialized, the commands have no effect unless an application such as an RPM command adds or removes any packages after the last recorded transaction.

history list: This command lists the history of transactions. Note that this result is similar when you use the history command without an argument or sub-command.

The following example shows the use of the command:

# tdnf history
ID   cmd line                                 date/time             +added / -removed
   1 (set)                                    Thu May 05 2022 19:14 +152 / -0
   2 -y install less                          Thu May 05 2022 19:14 +1 / -0
   3 -y install lsof                          Thu May 05 2022 19:18 +2 / -0

You can specify the following options for this sub-command:

  • --info: Use this option to list a more detailed history that includes added or removed packages.
  • --reverse Use this option to list the history in reverse order.
  • --from <id> and --to <id>: Use this option to list a range of transactions. You can specify the transaction IDs of the range in this option.

The following example shows how to use the options:

# tdnf history --info --from 2 --to 3
ID   cmd line                                 date/time             +added / -removed
   2 -y install less                          Thu May 05 2022 19:14 +1 / -0
added: less-551-2.ph4.aarch64

   3 -y install lsof                          Thu May 05 2022 19:18 +2 / -0
added: libtirpc-1.2.6-2.ph4.aarch64, lsof-4.91-1.ph4.aarch64

history rollback –to trans_id: This command allows you to revert to a previous state. You must specify the ID of the desired state with the --to parameter.

Example:

# tdnf history rollback --to 49

Upgrading:
curl-devel                               aarch64              7.82.0-3.ph4                photon-updates       885.16k 906404
curl                                     aarch64              7.82.0-3.ph4                photon-updates       256.73k 262896
...

Total installed size:   3.52M 3688748
Is this ok [y/N]: y

Downloading:
curl-devel                              793306 100%
curl                                    148725 100%
...
Testing transaction
Running transaction
Installing/Updating: rpm-libs-4.16.1.3-9.ph4.aarch64
Installing/Updating: rpm-4.16.1.3-9.ph4.aarch64
...
Complete!

history undo –from trans_id [–to trans_id]: You can use this command to undo a transaction. The parameter --from is mandatory, and the specified transaction in the parameter is reversed. Optionally, you can specify a range with the parameter --to to reverse all the specified transactions. Note that the range you specify is inclusive. For example, if you specify the range as 2 to 4, the transactions in 2, 3, and 4 are reversed.

history redo –from trans_id [–to trans_id]: You can use this command to redo a transaction. The parameter --from is mandatory, and the specified transaction in the parameter is redone. Optionally, you can specify a range with the parameter --to to redo all the specified transactions. The range you specify in the parameters is inclusive.

NOTE

Deltas: When you make changes using history commands, the changes are resolved based on the total deltas between the start and the target states. For each range of transactions, the intermediate states are irrelevant. For example, in a range of transactions where one transaction installs a package and the last one removes the package, the final installed state of the package remains the same from start to end.

Unresolved Packages: If a package is not found, tdnf fails with an error message. For instance, when you roll back to a state before an update, the system might not find all the required installation packages in the repository. In such a case, you can enable the additional repositories to successfully revert.

Example:

The following example shows how the tdnf fails with an error message for the unavilable packages:

# tdnf history rollback --to 1
The following packages could not be resolved:

curl-libs-7.82.0-1.ph4.aarch64
rpm-libs-4.16.1.3-7.ph4.aarch64
...

The package(s) may have been moved out of the enabled repositories since the
last time they were installed. You may be able to resolve this by enabling
additional repositories.
Error(1011) : No matching packages

The following example shows how you can enable the repository to resolve the issue:

tdnf --enablerepo=photon history rollback --to 1

Downgrading:
curl-devel                               aarch64              7.82.0-1.ph4                photon               885.16k 906404
rpm-build                                aarch64              4.16.1.3-7.ph4              photon               434.00k 444418
...

Total installed size:   4.26M 4463905

Removing:
wget                                     aarch64              1.21.3-1.ph4                @System                3.02M 3168291
tdnf-test-cleanreq-required              aarch64              1.0.1-3                     @System                    0.00b 0
lsof                                     aarch64              4.91-1.ph4                  @System              202.36k 207218
libtirpc                                 aarch64              1.2.6-2.ph4                 @System              193.33k 197970
gdb                                      aarch64              10.1-2.ph4                  @System               12.60M 13214814

Total installed size:  16.01M 16788293
Is this ok [y/N]: 

Transactions outside tdnf: tdnf keeps track of the transactions it performs. However, other tools such as rpm can also add or remove packages. While performing the next transaction, if tdnf detects transactions performed by other tools, it records such transactions as pseudo transactions.

Example:

# tdnf history --info --from 49 --to 49
ID   cmd line                                 date/time.            +added / -removed
  49 (unknown)                                Thu May 05 2022 23:38 +1 / -0
added: gdb-10.1-2.ph4.aarch64

Dependencies: The undo and redo actions might need to install additional depedencies apart from the previously existing packages. For example, when you redo a transaction that installs a single package which was earlier removed along with its depedencies, the command also attempts to install the dependecies.

Note that this is not an issue for the rollback command because the entire set of packages is restored assuming that the dependecies are also satisfied at the state.

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.

mark install|remove pkg_spec: Mark one or more packages as auto installed (remove) or unmark as auto installed (install), which means it is user-installed. This is used to determine if this package gets removed on autoinstall.

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

repoquery [args]: The repoquery command allows you to query packages from the repositories and installed packages with different criteria and output options. It can take multiple package specifications as arguments.

Example:

$ tdnf repoquery vim 
vim-8.2.4925-1.ph4.aarch64
vim-8.2.1361-1.ph4.aarch64

$ tdnf repoquery vim*
vim-8.2.4925-1.ph4.aarch64
vim-8.2.1361-1.ph4.aarch64
vim-extra-8.2.4925-1.ph4.aarch64
vim-extra-8.2.1361-1.ph4.aarch64

$ tdnf repoquery --installed vim
vim-8.2.4925-1.ph4.aarch64

$ tdnf repoquery --requires vim
ld-linux-aarch64.so.1()(64bit)
ld-linux-aarch64.so.1(GLIBC_2.17)(64bit)
libc.so.6(GLIBC_2.17)(64bit)
...

The following groups of options are available for repoquery:

  • select option: Use this option to filter the list of packages. You can use the following parameters with the select option:

    • --available: Use this parameter to show available packages in the repositories.

    • --duplicates: Use this parameter to show duplicate installed packages.

    • --extras: Use this parameter to show the packages that are installed but not in any repositories.

    • --file file: Use this parameter to show packages that contain the specified files.

    • --installed: Use this parameter to show the installed packages.

    • --userinstalled: Use this parameter to show the user-installed packages.

    • --whatdepends, --whatenhances, --whatobsoletes, --whatprovides, --whatrecommends, whatrequires, --whatsuggests, --whatsupplements capability: Use these parameters to show packages that have the specified dependency on capability.

      Example:

      $ tdnf repoquery --whatrequires vim
      minimal-0.1-6.ph4.aarch64
      vim-extra-8.2.4925-1.ph4.aarch64
      minimal-0.1-4.ph4.aarch64
      
  • query option: Use this option to control what you want the command to display. The query option lists the selected packages by default. You can use the following parameters to get the required output:

    • --list: Use this parameter to list all files of the selected packages.
    • --depends, --enhances, --obsoletes, --provides, --recommends, requires, requires-pre, --suggests, --supplements: Use these parameters to list specified dependencies.

reoposync: This command synchronizes a remote repository with a local one. By default, all packages are downloaded to a local directory unless they already exist. Optionally, metadata is also downloaded.

You can use the following options with the command:

--delete: Use this option to remove old packages that are not part of the repository any more.

--download-metadata: Use this option to download the metadata. After you download the the metadata, you can use the directory as a repository.

--gpgcheck: Use this option to check the gpg signature. If invalid, the package is deleted.

--norepopath: When you use this option, no subdirectory with the repo name is created. This option is only valid if you configure more than one repository.

--urls: When you use this option, instead of downloading, the URLs of all files are printed to stdout.

--download-path: Use this option to specify the download path. By default, files are downloaded relative to the current directory.

--metadata-path: Use this option to specify the download path. You can download metadata to a different directory.

--arch: Use this option to download specific architectures. You can use this option repeatedly.

--source: Use this option to download only source packages. This option is similar to --arch src. Note that this option is incompatible with the --arch option.

--newest-only: Use this option to download only the latest versions of the repository.

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

updateinfo: This command displays security advisories about packages. The following is an example:

tdnf updateinfo info

Name : unzip-6.0-15.ph3.x86_64.rpm
Update ID : patch:PHSA-2020-3.0-0083
Type : Security
Updated : Fri Apr 24 01:15:03 2020
Needs Reboot: 0
Description : Security fixes for {'CVE-2018-1000035'}
Name : runc-1.0.0.rc9-3.ph3.x86_64.rpm
Update ID : patch:PHSA-2020-3.0-0102
Type : Security
Updated : Tue Jun  9 06:01:28 2020
Needs Reboot: 0
Description : Security fixes for {'CVE-2019-19921'}
Name : ruby-2.5.8-2.ph3.x86_64.rpm
Update ID : patch:PHSA-2020-3.0-0163
Type : Security
Updated : Thu Nov 19 17:21:29 2020
Needs Reboot: 0

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. The 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.9.2 - tdnf 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.

OPTIONDESCRIPTION
–allowerasingAllow erasing of installed packages to resolve dependencies
–assumenoAnswer no for all questions
–bestTry the best available package versions in transactions
–debugsolverDump data aiding in dependency solver debugging info.
–disablerepo=Disable specific repositories by an id or a glob.
–enablerepo=Enable specific repositories
-h, –helpDisplay help
–refreshSet metadata as expired before running command
–nogpgcheckSkip gpg check on packages
rpmverbosity=<debug level name>Debug level for rpm
–versionDisplays the tdnf version and exit
-y, –assumeyesAnswer yes to all questions
-q, –quietQuiet operation
–downloadonlyEnables you to download the packages and dependencies that are not installed to the cache.
–alldepsEnables you to downloads all dependencies for a package regardless of whether they are installed. This command is valid when used together with –downloadonly command.
–downloaddir=dirDownloads the packages to the specified directory
-C, –cacheonlyDisables downloading metadata, and enables usage of the cached metadata even if it is expired.
–config file, -c fileUse an alternative configuration file
–exclude=package1[,package2[…]]Enables you to list the packages that you want to exclude from the operations.
–disableexcludesDisables excludes even if the excludes option is present in the configuration file.
–disablerepo=patternDisables one or more repositories. You can set it to a repoid or a pattern. You can also use it together with --enablerepo, but it is mutually exclusive with --repo/--repoid. For example, tdnf --disablerepo=* --enablerepo=photon list.
–enablerepo=patternEnables one or more repositories. You can set it to a repoid or a pattern. This command is mutually exclusive with --repo/--repoid.
–downloaddir=directorySpecifies a directory where to download the packages. If the directory is not specified, the package is downloaded in the cache directory. You can only use it together with --downloadonly.
–installroot=directoryAllows you to install packages relative to this directory. Unless you specify with -c or --config, tdnf uses the following configuration file in this directory: etc/tdnf/tdnf.conf. If the configuration file is not present in this directory, tdnf uses the following configuration file in the host: /etc/tdnf/tdnf.conf. This is the same for the repository configurations. The cache directory is relative to the installroot. Note that the cache directory is created, if necessary.
–json, -jEnables you to get the output information in JSON format. Using tdnf with its alias tdnfj is similar to using tdnf with tdnf -j -y.
–noautoremoveDisables automatic removal of orphaned dependencies regardless of the clean_requirements_on_remove option.
–repofrompath=repoid,baseurlAdds a repository with the id repoid and baseurl as the base url. This is equivalent to adding a repository with the repoid and the baseurl. You can reference the repository with the id, for example, with --repoid.

Example: tdnf repofrompath=local,file:///usr/src/photon/RPMS --repoid=local install lsof to install packages from usr/src/photon/RPMS (after using createrepo /usr/src/photon/RPMS).

You can use this multiple times to add multiple repositories.

–repoid id, –repo idEnables you to select a particular repository based on its ID. For example, --repoid=photon is equivalent to --disablerepo=* --enablerepo=photon. You can specify the repository multiple times.
–releaseverEnables you to specify the release version of the distribution. If installed, the version is taken from the package that provides the system-release unless configured otherwise. Setting this is useful while installing the distribution when you use --installroot.
–skip-brokenAllows skipping failures if a package is not available or has broken dependencies.
–testonlyTests RPM transactions. Note that this command does not install anything.

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

The following is an example for the downloadonly option with the install command:

tdnf install --downloadonly less
    
Installing:
    
lessx86_64551-2.ph4 photon234.35k 239976
       
Total installed size: 234.35k 239976
  
tdnf will only download packages needed for the transaction
   
Is this ok [y/N]: y

Downloading:
   
less117650   100%
    
Complete!
   
Packages have been downloaded to cache.

The following is an example for the downloaddir=dir option with the install command:

tdnf install --downloadonly --downloaddir=/tmp less
 
Installing:

lessx86_64551-2.ph4 photon234.35k 239976
        
Total installed size: 234.35k 239976

tdnf will only download packages needed for the transaction

Is this ok [y/N]: y

Downloading:

less117650   100%

    
Complete!

Packages have been downloaded to /tmp.

root [ /build/build ]# ls -l /tmp/less-551-2.ph4.x86_64.rpm 

-rw-r--r-- 1 root root 117650 Feb 22 18:43 /tmp/less-551-2.ph4.x86_64.rpm

2.10 - Configuration Options

You can use the configuration file to set and modify the tdnf configuration. The tdnf configuration file is located in the following directory: /etc/tdnf/tdnf.conf

The following table lists the configuration options that you can set in the tdnf configuration file:

ConfigurationDescription
cachedirType: string
Default value: /var/cache/tdnf
This is the location of the cache directory. The cache directory stores the metadata. After downloading the RPMs, the cache directory also stores the RPMs temporarily.
clean_requirements_on_removeType: boolean
Default value: false
Available from tdnf 3.3.1 onwards.

This option determines whether the automatically installed dependencies are removed when a package is removed.
distroarchpkgType: distroarchpkg
Default value: x86_64

The architecture of the distribution.
distroverpkgType: string
Default value: system-release
excludepkgsType: list
Default value: none

The list of packages that you want to exclude from any operations. Packages in this list are not installed, updated, or downgraded.
gpgcheckType: boolean
Default: false

This option determines whether the packages are checked for their gpg signature.
gpgcheckType: boolean
Default value: false

This option determines whether the packages are checked for their gpg signature.
installonly_limitType: integer
Currently not implemented.
This option limits the number of concurrently install only packages.
keepcacheType: boolean
Default value: false

This option determines whether to keep the downloaded packages after installation.
minversionsType: list
Default: none

This option refers to the list of packages with a minimum version number. When you set the minimum version number, packages are not downgraded below that version.
Example: minversions=tdnf=3.1.5 foo=1.2.3.
This can also be configured with the .conf extension files located in the directory named minversions.d. The directory is the same as the directory of the configuration file (usually, /etc/tdnf/minversions.d).
Example:
mkdir -p /etc/tdnf/minversions.d
echo tdnf=3.1.5 > /etc/tdnf/minversions.d/tdnf.conf
nopluginsWhen you set this option, plugins are disabled.
pluginpathType: string
Default value: /usr/lib/tdnf-plugins (or the modified value at the time of build with SYSTEM_LIBDIR option)

The path for plugins.
pluginconfpathType: string
Default value: /etc/tdnf/pluginconf.d

The path for the plugin configuration.
proxyType: string
Default value: none

Set this to a proxy, if any.
proxy_passwordType: string
Default value: none

The proxy password, if any.
proxy_usernameType: string
Default value: none

The proxy user name, if any.
repodirType: string
Default value: /etc/yum.repos.d

The location where the .repo files reside.

Configuration in sub-directories

There are other configurations that you can set in the subdirectories of /etc/tdnf.

Package Locks

You can configure to lock packages in the following directory: /etc/tdnf/locks.d. You cannot remove, upgrade, or downgrade a locked package. You can create multiple files with multiple lines. Each line can contain a package name.

Note: A locked package is considered locked only after it is installed. If a package is not installed, the features of a locked package do not apply.

Minimal Versions

You can configure a minimum version for a package in the following directory: /etc/tdnf/minversions.d. You can create multiple files with multiple lines in them. Each line can contain a package name. The package name must include a version number, and an = symbol must separate the name and version number.

Example:

# cat /etc/tdnf/minversions.d/rpm.conf 
rpm-libs=4.16.1.3-1

You can also configure this option in the main configuration file as mentioned in the table previously.

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.

  1. 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
  1. 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

  1. 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
  1. 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
    
  2. Install Sendmail:

    tdnf install sendmail
    
  3. Verify if Sendmail is enabled:

    systemctl status sendmail
    
  4. 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:

  1. Ensure that the wpa_supplicant service is running on the WLAN interface:

    systemctl status wpa_supplicant@<wlan-interface>.service

  2. Connect to wpa_cli:

    wpa_cli -i wlan0

  3. Scan for available networks:

    scan

  4. To see the list of networks, use the following command:

    scan_results

  5. Add the network:

    add_network

    This command returns a network ID.

  6. Associate the network with the network ID.

    set_network <network ID> ssid “<ssid-name>”

  7. For a WPA2 network, set the passphrase:

    set_network <network ID> psk “<passphrase>”

  8. Enable the network:

    enable_network <network ID>

  9. 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:

  1. Create a /etc/systemd/network/98-dhcp-wlan.network file with the following contents:

    [Match]
    Name=wlan*
    [Network]
    DHCP=yes
    IPv6AcceptRA=no
    
  2. 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-config-manager nmctl allows to configure and introspect the state of the network links as seen by systemd-networkd. nmctl can be used to query and configure links for Address, Routes, Gateways and also hostname, DNS, NTP or Domain. nmctl uses sd-bus, libudev APIs to interact with systemd, systemd-networkd, systemd-resolved, systemd-hostnamed, and systemd-timesyncd via dbus. nmctl uses networkd verbs to explain output. nmctl can generate configurations for required network links from YAML description. It also understands kernel command line specified in dracut network configuration format and can generate systemd-networkd configuration while the system boots and will persist between reboots.

Note: See systemd.network for more information.

nmctl is used to configure:

  • Static IPv4 and IPv6 Address, Routes, Gateway
  • DHCP type (IPv4/IPv6), DHCP4 Client Identifier, UseMTU/UseDNS/UseDomains/UseNTP/UseRoutes. LLDP, Link Local Addressing, IPv4LLRoute, LLMNR
  • DNS, Domains and NTP
  • Link MAC, MTU
  • Create netdevs, vlan, vxlan, bridge, bond, veth, macvlan/macvtap, ipvlap/ipvtap, veth, tunnels(ipip, sit, gre, sit, vti), wireguard
  • Hostname
  • Can delete and view nftables table, chains and rules.

You can use nmctl to generate network configurations from the following:

  • YAML file: nmctl can generate configurations for required network links from YAML description. Configuration written to disk under /etc/systemd/network will persist between reboots. When network-config-manager-yaml-generator.service is enabled it reads YAML files from /etc/network-config-manager/yaml and generates systemd-networkd configuration files.

    nmctl uses similar format as defined by different YAML format.

    nmctl can generate WPA Supplicant configuration from YAML file. When a YAML file with wifi configuration is found, it generates a configuration file found in /etc/network-config-manager/wpa_supplicant_photon_os.conf which is understood by wpa_supplicant.

  • Dracut kernel command line network configuration: nmctl understands kernel command line specified in dracut’s network configuration format and can generate systemd-networkd’s configuration while the system boots and will persist between reboots.

Network
       ip={dhcp|on|any|dhcp6|auto6}
           dhcp|on|any: get ip from dhcp server from all links. If root=dhcp, loop
           sequentially through all links (eth0, eth1, ...) and use the first with a valid
           DHCP root-path.

           auto6: IPv6 autoconfiguration

           dhcp6: IPv6 DHCP

       ip=<link>:{dhcp|on|any|dhcp6|auto6}
           dhcp|on|any|dhcp6: get ip from dhcp server on a specific link

           auto6: do IPv6 autoconfiguration

           This parameter can be specified multiple times.

       ip=<client-IP>:[ <server-id>]:<gateway-IP>:<netmask>:<client_hostname>:<link>:{none|off}
           explicit network configuration.

       ifname=<link>:<MAC>
           Assign network device name <link> (ie eth0) to the NIC with MAC <MAC>. Note
           letters in the MAC-address must be lowercase!  Note: If you use this option you must
           specify an ifname= argument for all links used in ip= or fcoe= arguments.  This
           parameter can be specified multiple times.

       nameserver=<IP>[nameserver=<IP> ...]
           specify nameserver(s) to use

      cat /proc/cmdline
       BOOT_IMAGE=/boot/vmlinuz-4.19.52-2.ph3-esx root=PARTUUID=ebf01b6d-7e9c-4345-93f4-122f44eb2726
       init=/lib/systemd/systemd rcupdate.rcu_expedited=1 rw systemd.show_status=0 quiet noreplace-smp
       cpu_init_udelay=0 net.ifnames=0 plymouth.enable=0 systemd.legacy_systemd_cgroup_controller=yes
       ip=dhcp

network-config-manager-generator.service is a oneshot type systemd service unit which runs while the system boots. It parses the kernel command line and generates networkd config in /etc/systemd/network:

systemctl enable network-config-manager-generator.service

It creates symlink /etc/systemd/system/network.target.wants/network-config-manager-generator.service → /usr/lib/systemd/system/network-config-manager-generator.service.

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 either the first or the second step:

  1. systemctl restart systemd-networkd

  2. networkctl reload networkctl reconfigure *interface_name/index_number*

Note: The advantage of using reload and reconfigure is that the settings of other interfaces are not disturbed and only the settings of the specific interface are reloaded and reconfigured.

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

Or you can reload and reconfigure the settings:

networkctl reload
networkctl reconfigure <interface_name>/<index_number>`

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.

You can also check the status of a specific interface:

networkctl status <interface_name>/<index_number>

(eth0 is an example)

❯ networkctl status eth0
● 2: eth0
                     Link File: /usr/lib/systemd/network/99-default.link
                  Network File: /etc/systemd/network/50-dhcp-en.network
                         State: routable (configured)
                  Online state: online
                          Type: ether
                          Path: pci-0000:0b:00.0
                        Driver: vmxnet3
                        Vendor: VMware
                         Model: VMXNET3 Ethernet Controller
             Alternative Names: eno1
                                enp11s0
                                ens192
              Hardware Address: 00:50:56:ba:43:98 (VMware, Inc.)
                           MTU: 1500 (min: 60, max: 9000)
                         QDisc: fq_codel
  IPv6 Address Generation Mode: eui64
      Number of Queues (Tx/Rx): 1/1
              Auto negotiation: no
                         Speed: 10Gbps
                        Duplex: full
                          Port: tp
                       Address: 192.168.1.8/24 (DHCPv4 via 192.168.1.1)
                                fe80::250:56ff:feba:4398
                       Gateway: 192.168.1.1
                           DNS: 192.168.1.1
                                192.168.1.2
                                192.168.1.3
                           NTP: 192.168.1.1
                                192.168.1.2
                                192.168.1.3
                                192.168.1.4
             Activation Policy: up
           Required For Online: yes
               DHCP4 Client ID: IAID:0xb6220feb/DUID

May 04 10:37:14 photon systemd-networkd[625]: eth0: found matching network '/etc/systemd/network/50-dhcp-en.network', based on potentially unpredictable interface name.
May 04 10:37:14 photon systemd-networkd[625]: eth0: Configuring with /etc/systemd/network/50-dhcp-en.network.
May 04 10:37:14 photon systemd-networkd[625]: eth0: Link UP
May 04 10:37:14 photon systemd-networkd[625]: eth0: Gained carrier
May 04 10:37:14 photon systemd-networkd[625]: eth0: found matching network '/etc/systemd/network/50-dhcp-en.network', based on potentially unpredictable interface name.

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
  • Or you can reload and reconfigure the settings by running the following commands: networkctl reload networkctl reconfigure *interface_name/index_number*

Note: The advantage of using reload and reconfigure is that the settings of other interfaces are not disturbed and only the settings of the specific interface are reloaded and reconfigured.

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

How to configure two gateways for two different NIC ?

This is an IP routing policy feature of kernel and is supported by systemd-networkd. You have to add two routes. One is for the subnet so that the IP address can find its gateway. The other route is for specifying the default gateway for that interface. Finally, we add policy route rules for that IP address that we want to use that table. This will not only ensure that the IP address you are trying to communicate with on that one interface can respond properly, but it will also ensure that you do not route information between subnets.

[Match]
Name=eth2
 
[Network]
Address=192.168.60.70/24
DHCP=no
 
[Route]
PreferredSource=192.168.60.70
Destination=192.168.60.0/24
Table=10
 
 
[Route]
Gateway=192.168.60.1
Table=10
 
[RoutingPolicyRule]
Table=10
To=192.168.60.70/24
 
[RoutingPolicyRule]
Table=10
From=192.168.60.70/24

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, machine-id can be regenerated by calling systemd-machine-id-setup.

systemd-machine-id-setup

This command initializes the machine ID stored in /etc/machine-id during installation. For more information on this command, see https://www.freedesktop.org/software/systemd/man/systemd-machine-id-setup.html.

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:

  1. 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
  1. 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.

  1. 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: 10.197.103.56 on eno1
           172.17.0.1 on docker0
           fe80::20c:29ff:fe44:f92c on eno1
  Gateway: 10.197.103.253 (Cisco Systems, Inc) on eno1
      DNS: 10.142.7.1
           10.132.7.1
           10.166.17.90
      NTP: 10.128.152.81
           10.166.1.120
           10.188.26.119
           10.84.55.42

You can see that there are active network links with IP addresses for not only the Ethernet connection but also a Docker container.

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 ens33
	* 2: ens33
	         Link File: /usr/lib/systemd/network/99-default.link                                      
                  Network File: /usr/lib/systemd/network/10-eth.network                                       
                          Type: ether                                                                         
                         State: routable (configured)                               
             Alternative Names: enp2s1                                                                        
                          Path: pci-0000:02:01.0                                                              
                        Driver: e1000                                                                         
                        Vendor: Intel Corporation                                                             
                         Model: 82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Single Port Adapter)
                    HW Address: 00:0c:29:5f:d1:39 (VMware, Inc.)                                              
                           MTU: 1500 (min: 46, max: 16110)                                                    
                         QDisc: fq_codel                                                                      
  IPv6 Address Generation Mode: eui64                                                                         
          Queue Length (Tx/Rx): 1/1                                                                           
              Auto negotiation: yes                                                                           
                         Speed: 1Gbps                                                                         
                        Duplex: full                                                                          
                          Port: tp                                                                            
                       Address: 172.16.85.225 (DHCP4 via 172.16.85.254)                                       
                                fe80::20c:29ff:fe5f:d139                                                      
                       Gateway: 172.16.85.2 (VMware, Inc.)                                                    
                           DNS: 172.16.85.2                                                                   
               DHCP4 Client ID: IAID:0x2b9434c1/DUID                                                          
             DHCP6 Client DUID: DUID-EN/Vendor:0000ab11d258482fc7eee6510000                                   
Feb 26 10:19:44 photon systemd-networkd[650]: ens33: Link UP
Feb 26 10:19:44 photon systemd-networkd[650]: ens33: Gained carrier
Feb 26 10:19:45 photon systemd-networkd[650]: ens33: DHCPv4 address 172.16.85.225/24 via 172.16.85.2
Feb 26 10:19:46 photon systemd-networkd[650]: ens33: Gained IPv6LL

’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

  1. Run the following command as root to create a directory with the name systemd-networkd.service.d, including the .d extension:

    systemctl edit systemd-networkd.service
    
  2. Add following configuration in the file override.conf to establish a systemd drop-in unit with a debugging configuration for the network service:

    	[Service]
    	Environment=SYSTEMD_LOG_LEVEL=debug
    
  3. Reload the systemctl daemon and restart the systemd-networkd service for the changes to take effect:

    systemctl daemon-reload
    systemctl restart systemd-networkd
    
  4. Verify your changes:

    systemd-delta --type=extended
    
  5. View the log files by running this command:

    journalctl -u systemd-networkd
    
  6. 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 - Installing packages for 'tcpdump' and 'netcat'

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

5.14 - 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.15 - Configuring a Secondary Network Interface using Cloud-Network

When you add a secondary network interface to a linux instance in the cloud environment, you need to configure the network parameters for the secondary interface in the linux instance. The configuration ensures that you do not face any routing issues while using the secondary network interface. Configuring the secondary network interface involves several manual processes that include configuring a new routing table, setting up rules in the routing table and so on.

cloud-network automates the whole manual process of configuring the secondary network interface. It configures the network parameters required for any network interfaces that you create or add to the linux instance. In a cloud environment, instances are set to public IPs and private IPs. If you add more than one private IP for the secondary network interface, the IP other than the one provided by DHCP cannot be fetched and configured for your virtual machine. The cloud-network project is designed to adapt the cloud-network environments such as Azure, GCP, and Amazon EC2. cloud-network fetches the metadata from the metadata server endpoint, parses the metadata, and then assigns IPs and routes. When cloud-network is installed, it automatically configures network interfaces in the cloud frameworks. It detects the available interfaces using netlink. Additionally, for all the interfaces, including the primary one, it looks for any secondary IP addresses from the metadata server endpoint and configures them on the interface, if any.

A local RESTful JSON server runs on the address 127.0.0.1:5209 and the instance metadata is saved on per link basis in the following directory: /run/cloud-network.

The network parameters in the cloud framework are checked periodically for any changes, and in case of a change, the interface is reconfigured accordingly.

The image below illustrates the communication of cloud-network and the instance metadata server:

Cloud Network tool communicating with the IMDS


Use Case: Making a secondary network interface work in a cloud instance.

This functionality is scattered across different scripts/tools that are cloud provider dependent. cloud-network provides a cloud-agnostic mechanism to retrieve the metadata like network parameters, and configure the interfaces. This means that there is no need to manually edit and update the configuration when there are changes in the network parameters. cloud-network automatically configures the interfaces since it has the metadata information.

The image below illustrates how cloud-network fetches the network parameters to configure the secondary network interface (eth1) in a cloud instance:

Cloud Network tool configuring the secondary network instance


Installing Cloud Network Setup

Type the following command to install cloud network in your system:

tdnf install cloud-network-setup


Configuration

To manage the configuration, use the configuration file named cloud-network.toml located in the following directory: /etc/cloud-network/

[System] Section

You can set values for the following keys in the [System] section:

LogLevel=
Specifies the log level. The key takes one of the following values: Trace, Debug, Info, Warning, Error, Fatal and Panic. Default is info.

LogFormat=
Specifies the log format. The key takes one of the following values: text or JSON. Takes one of text or json, Default is text.

RefreshTimer=
Specifies the time interval. The time interval indicates the amount of time taken to retrieve the data from the metadata endpoint.

[Network] Section

You can set values for the following keys in the [Network] section:

Listen=

Specifies the IP address and the port that the local REST API server listens. You can specify the IP address and the port in the following format ip:port. Defaults is 127.0.0.1:5209.

Supplementary=
A whitespace-separated list of interfaces matching the device name. Specifies the interfaces you want to configure with a default gateway and routing policy rules for each IP address including the primary IP address. No default value is set for this key.

Note When there are multiple interfaces, the secondary interface becomes unreachable. When you set a value for Supplementary= key, the default route and routing policy rules are automatically configured.


The following example shows a sample configuration of the key values in the cloud-network.toml file:

> cat /etc/cloud-network/cloud-network.toml
[System]
RefreshTimer="300s"
LogLevel="info"
LogFormat="text"

[Network]
Listen="127.0.0.1:5209"
Supplementary="eth0"

After you set the configuration, use the sudo systemctl status cloud-network command to check the network status of the cloud-network service. Following example shows the command output of the sudo systemctl status cloud-network command:

❯ > sudo systemctl status cloud-network
● cloud-network.service - Configures network in cloud enviroment
     Loaded: loaded (/usr/lib/systemd/system/cloud-network.service; disabled; vendor preset: enabled)
     Active: active (running) since Mon 2021-05-31 22:54:50 UTC; 3min 31s ago
   Main PID: 19754 (cloud-network)
      Tasks: 5 (limit: 4400)
     Memory: 8.7M
     CGroup: /system.slice/cloud-network.service
             └─19754 /usr/bin/cloud-network

May 31 22:54:50 zeus-final-2 systemd[1]: Started Configures network in cloud enviroment.

cnctl

Use the cnctl CLI tool to view the metadata that is retrieved from the endpoint metadata server. The Following examples show the output of the cnctl status command for the network and system:

❯ cnctl status system
    Cloud provider: aws
             AmiID: ami-005f15863xxxxxxxx  
          Location: 0
BlockDeviceMapping: Ami:xvda Root:/dev/xvda
          Hostname: Zeus.us-west-2.compute.internal
    PublicHostname: Zeuspublic.us-west-2.compute.amazonaws.com
     LocalHostname: Zeus.us-west-2.compute.internal
    InstanceAction: none
    InstanceID: i-0c8c1test
 InstanceLifeCycle: on-demand
      InstanceType: t4g.micro
         Placement: AvailabilityZone:us-west-2d AvailabilityZoneID:usw2-az4 Region:us-west-2
           Profile: default-hvm
       Mac Address: 0e:c5:3f:c5:33:a5
         LocalIpv4: 192.31.63.114
        PublicIpv4: 02:42:8d:4c:0c:cf
   Services Domain: amazonaws.com
Services Partition: aws  

❯ cnctl status network
            Name: ens33
     MAC Address: 00:0c:29:5f:d1:39
       Public IP: 104.42.20.194
      Private IP: 10.0.0.4/24 10.0.0.6/24 10.0.0.7/24
          Subnet: 10.0.0.0

5.16 - Using Network Event Broker

network-event-broker is a daemon that configures network and executes scripts on network events such as systemd-networkd’s DBus events, dhclient lease gains, and so on.

network-event-broker also detects the following events:

  • An IP address is added/removed/modified
  • A link is added or removed

In the /etc/network-event-broker directory, network-event-broker creates the link state directories such as carrier.d, configured.d, degraded.d, no-carrier.d, routable.d and manager state directory such as manager.d . You can also keep the executable scripts in these directories.

Use Case: Running command when a new address is acquired via DHCP.

  1. systemd-networkd: systemd-networkd’s scripts are executed when the daemon receives the relevant event from systemd-networkd.

     May 14 17:08:13 Zeus cat[273185]: OperationalState="routable"  
     May 14 17:08:13 Zeus cat[273185]: LINK=ens33
    
  2. dhclient: For dhclient, scripts are executed in the routable.d directory when dhclient modifies the /var/lib/dhclient/dhclient.leases file and lease information is passed to the scripts as environmental arguments.

Environment variables such as LINK, LINKINDEX= and DHCP lease information DHCP_LEASE= are passed to the scripts.

Configuration

To manage the network-event-broker configuration, use the configuration file named network-broker.toml located in the following directory: /etc/network-broker/

[System] section

You can set values for the following keys in the [System] section:

LogLevel=
Specifies the log level. The key takes one of the following values: info, warn, error, debug and fatal. Default is info.

Generator=
Specifies the network event generator source. The key takes one of the following values: systemd-networkd or dhclient. Default is systemd-networkd.

[Network] section

You can set values for the following keys in the [Network] section:

Links=
A whitespace-separated list of links whose events should be monitored. No default value is set for this key.

RoutingPolicyRules=
A whitespace-separated list of links for which you want to configure the routing policy rules per address. When you set this configuration, network-event-broker automatically adds the to and from routing policy rules in another routing table (ROUTE_TABLE_BASE = 9999 + ifindex). When these addresses are removed, the routing policy rules are dropped. No default value is set for this key.

UseDNS=
Specifies whether you want to send the DNS server details to systemd-resolved. The key takes one of the following values: true, false. When set to true, the DNS server details are sent to systemd-resolved via DBus. This is applicable only to the DHClient. Default is false.

UseDomain=
Specifies whether you want to send the DNS domain details to systemd-resolved. The key takes one of the following values: true, false. When set to true, the DNS domain details are sent to systemd-resolved via DBus. This is applicable only to the DHClient. Default is false.

UseHostname=
Specifies whether you want to send the host name to systemd-hostnamed. The key takes one of the following values: true, false. When set to true, the host name is sent to systemd-hostnamed via DBus. This is applicable only to the DHClient. Default is false.

The following example shows a sample configuration of the key values in the network-broker.toml file:

❯ sudo cat /etc/network-broker/network-broker.toml 
[System]
LogLevel="debug"
Generator="dhclient"

[Network]
Links="ens33 ens37"
RoutingPolicyRules="ens33 ens37"
UseDNS="true"
UseDomain="true"

5.17 - Configuring a Network Using Network Configuration Manager

You can use network-configuration-manager to configure a network in Photon OS. The YAML-based configuration system in network-config-manager makes the network configuration easy and simple.

The following sections in the document demonstrate the configuration of a network in Photon OS using network-config-manager.

You can find the YAML network configuration files at the following location:

/etc/network-config-manager/yaml/ 

When you install network-configuration-manager, it generates the network-config-manager configuration file for systemd-networkd named 99-dhcp.yaml.example.

Perform the following steps to configure static or dynamic IP addressing in Photon OS:

  1. To find the name of the active network interfaces that you want to configure, execute the following command:
❯ ip a   
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:5f:d1:39 brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    inet 192.168.1.4/24 metric 1024 brd 192.168.1.255 scope global dynamic ens33
       valid_lft 82465sec preferred_lft 82465sec
    inet6 fe80::20c:29ff:fe5f:d139/64 scope link 
       valid_lft forever preferred_lft forever

Note the name of the interface that you want to configure using network-config-manager.

  1. To find the network-configuration-manager default configuration file, execute the following command:

    ❯ ls /etc/network-config-manager/yaml
    
  2. To view the content of the network-config-manager network configuration file, execute the following command:

    ❯ cat /etc/network-config-manager/yaml/*.yaml
    
  3. Open the configuration file in an editor.
    For example, if you use vim editor, execute the following command to open the configuration file in an editor:

    ❯ sudo vim /etc/network-config-manager/yaml/99-dhcp.yaml
    
  4. Use the following syntax to update the configuration file as per your networking needs:

    network:
    Version: 2
    Renderer: networkd
    ethernets:
       device:
          dhcp4: yes/no
          nameservers:
             addresses: [NAMESERVER, NAMESERVER, ...]
          addresses: [IPADDRESS/PREFIX]
           routes:
          - to: DESTINATION
            via: GATEWAY
    

    Note that for static IP addressing, add the IP address, Gateway, and DNS details. For dynamic IP addressing, you need not add these details as it is fetched from the DHCP server.

    The following table describes the properties used in the syntax to update the configuration file.

    PropertiesDescription
    device: |Name of the interface.
    dhcp4: |yes or no depending upon dynamic or static IP addressing
    addresses: |IP address of the device in prefix notation.
    routes: to: destination via: |gateway IP address to connect to an outside network
    nameservers: |Address of DNS name servers

Note: It is recommended that you use spaces for indentation instead of tabs in the YAML configuration file. If you use a tab instead of spaces for indentation, you might encounter errors.

Configuring static IP address in Photon OS

To manually configure an IP address, use the previously mentioned file syntax in this topic, and add the IP address, Gateway, and DNS server details.

The following is a sample configuration for the static IP addressing:

network:
    ethernets:
        eth0:
            dhcp4: false
            addresses: [192.168.1.202/24]
            nameservers:
              addresses: [8.8.8.8,8.8.4.4,192.168.1.1]
            routes:
            - to: 172.16.0.0/24
              via: 192.168.1.100

Configure Dynamic IP address in Photon OS

To get the IP address from the DHCP server, use the previously mentioned file syntax in this topic. You need not add the IP address, Gateway, and DNS server details here.

The following is a sample configuration for the dynamic IP addressing:

network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: true

After configuring the IP address, you need to apply the new configuration. Execute the following command as sudo to apply the configuration:

$ sudo nmctl apply

To verify that the configurations are successfully applied, execute the following command and verify the IP address:

❯ nmctl status eth0
                       Flags: UP BROADCAST RUNNING NOARP LOWERUP 
                        Kind: dummy
                        Type: ether
                      Driver: dummy
                   Link File: /usr/lib/systemd/network/99-default.link
                Network File: /etc/systemd/network/10-eth0.network
                       State: routable (configured) 
               Address State: routable
          IPv4 Address State: routable
          IPv6 Address State: degraded
                Online State: online
         Required for Online: yes
           Activation Policy: up
                  HW Address: 56:d3:b9:4f:03:38 ((null))
                         MTU: 1500 (min: 0 max: 0) 
                       QDISC: noqueue 
              Queues (Tx/Rx): 1/1 
             Tx Queue Length: 1000 
IPv6 Address Generation Mode: eui64 
                GSO Max Size: 65536 GSO Max Segments: 65535 
                     Address: fe80::54d3:b9ff:fe4f:338/64
                              192.168.1.202/24
                     Gateway: 192.168.1.100
                         DNS: 8.8.4.4 192.168.1.1 8.8.8.8
           DHCP6 Client DUID: DUID-EN/Vendor:0000ab11d258482fc7eee6510000

To see the routes, execute the following command:

❯ ip r show dev eth0
172.16.0.0/24 via 192.168.1.100 proto static 

6 - Prioritize eth0 Route Over WLAN

You can prioritise the eth0 route over the WLAN route. Perform the following steps:

  1. Modify the /etc/systemd/network/99-dhcp-en.network file and add the following content:

    [DHCP]
    RouteMetric=512
    
  2. Restart systemd-networkd.

7 - Configuring Photon Real-Time Operating System for Real-Time Applications

Photon Real-Time (RT) Operating System (OS) (and the Linux kernel PREEMPT_RT patchset that it is based on) is optimized to support low-latency real-time scheduling and minimize the OS jitter as observed by real-time applications. However, to get the most out of Photon RT OS, it is must to have a proper system configuration. To run low-latency real time applications effectively, the sources of jitter have to be identified and eliminated across all layers of the underlying system, spanning the BIOS / firmware, the hypervisor, and the guest operating system (Photon RT).

BIOS/Firmware

Tuning a system for real time operation starts from the lowest layers of the software stack, namely the System BIOS or Platform Firmware. The goal is to configure the settings for the following functions:

  • Maximize Performance Ex: Set CPU, memory and device power management modes to maximum performance, disable CPU idle states

  • Minimize Computational Jitter Ex: Disable Turbo Boost, disable Hyper-Threading

  • Minimize System Management Interrupts Ex: Disable options such as Processor Power and Utilization Monitoring, memory Pre-Failure Notification, and so on

Platform vendors often publish low-latency tuning guides for their BIOS/firmware. Refer documentation to learn about the recommended low-latency settings specific to your platform.

Deploying Real-Time Applications on Photon Real-Time Operating System

A general strategy to deploy real-time applications on Photon RT is described as follows:

  • Partition CPUs between the OS and the RT workload: Among the available CPUs in the system, isolate a subset of CPUs, designated to run the RT workload. By default, the Linux scheduler will only run tasks on non-isolated CPUs, leaving the isolated CPUs to those tasks that are explicitly bound to them. Thus, all the housekeeping tasks of the OS will execute on non-isolated CPUs (with a few exceptions, such as per-CPU kernel threads). Then bind the RT workload to the isolated CPUs.

  • Steer unrelated interrupts away from the CPUs running the RT workload: Linux supports the ability to affine most interrupts to specific CPUs in the system. By using this mechanism, interrupts that are not relevant to the real-time workload can be affined to non-isolated CPUs, thus avoiding the jitter caused by interrupt handling latency on the isolated CPUs.

This strategy provides two important benefits:

  1. It limits OS interference with the RT workload.

  2. It protects the OS services from getting starved by the CPU-intensive RT tasks.

This configuration can be achieved using a combination of kernel command-line options, and user space packages, as discussed in the following sections.

Kernel Command-Line Parameters

  • CPU isolation

    isolcpus=X,Y-Z (Ex: isolcpus=2,4-5)

  • Interrupt affinity

    irqaffinity=X,Y-Z (Ex: irqaffinity=0-1,3) [ Usually it is the inverse of isolcpus.]

  • RCU callbacks

rcu_nocbs=X,Y-Z [ Usually it is same as isolcpus. ] rcu_nocb_poll=1

  • NOHZ (Eliminating the periodic timer)

    nohz=on nohz_full=X,Y-Z [ Usually it is same as isolcpus. ]

  • CPU idle

    idle=halt or idle=poll intel_idle.max_cstate=0 cpuidle.off=1

  • CPU frequency

    intel_pstate=disable

  • Lockup detectors

    nosoftlockup nowatchdog nmi_watchdog=0

  • Timer skew detection

      skew_tick=1
      clocksource=tsc
      tsc=reliable
    

The full list of kernel command-line parameters and their descriptions are available at https://www.kernel.org/doc/html/v6.1/admin-guide/kernel-parameters.html

Tuned configuration

Tuned is a system tuning daemon that offers several profiles to tailor the OS to various usecases, including a ‘realtime’ profile for low-latency workloads.

The realtime tuned profile can be applied as shown below:

  • tdnf install tuned

  • systemctl enable tuned

  • systemctl start tuned

Add isolcpus to /etc/tuned/realtime-variables.conf (by uncommenting the isolated_cores= parameter):

$ cat /etc/tuned/realtime-variables.conf

Examples:

# isolated_cores=2,4-7

Note: The cores configured as isolated in tuned should be consistent with isolcpus in the kernel command-line.

tuned-adm profile realtime

Stalld configuration

The stalld daemon monitors the system for starved tasks and revives them by giving them a temporary boost using the SCHED_DEADLINE policy. stalld offers fine-grained controls to give starved tasks a user-specified amount of CPU time.

The stalld configuration file is /etc/sysconfig/stalld.

The key parameters are Starving Threshold (THRESH), Boost Period (BP), Boost Runtime (BR), and Boost Duration (BD).

The mode of operation is as follows:

If a task is starved for at least THRESH seconds, it is scheduled using SCHED_DEADLINE scheduling policy, so that it will run at least BR nanoseconds in every BP nanoseconds time period, and this repeats up to BD seconds, after which the task gets back its original scheduler policy/priority settings.

Real Time Scheduling Policies

The Linux kernel offers several scheduling policies to support various applications, among which the real time policies are highlighted below:

  • SCHED_OTHER (default policy), SCHED_BATCH, SCHED_IDLE (non real-time policies)

  • SCHED_FIFO (First-In First-Out Real Time Scheduling)

  1. Priority Range: 1 to 99 (highest)

  2. Algorithm: The scheduler runs the highest-priority runnable task in the SCHED_FIFO scheduling class, until it yields (blocks/waits) the CPU voluntarily.

  • SCHED_RR (Round-Robin Real Time Scheduling)
  1. Priority Range: 1 to 99 (highest)

  2. Algorithm: The scheduler runs the highest-priority SCHED_RR task, and time-slices between equal-priority SCHED_RR tasks in configurable intervals.

  • SCHED_DEADLINE ( Earliest Deadline First Real Time Scheduling)
  1. Key parameters: Runtime, Period and Deadline, which can be configured on a per-task basis.

  2. Algorithm: The scheduler gives a SCHED_DEADLINE task at least Runtime amount of time on the CPU in every Period time period, before Deadline time is up.

Real Time Throttling

The Linux kernel offers proc file system (procfs) controls to influence real-time task scheduling and throttling.

The RT throttling algorithm is as follows:

  • All real-time tasks are throttled to run up to runtime microseconds, in every period microseconds. The remaining time in period microseconds is used to run non-RT tasks in the system.

  • runtime and period values can be configured by writing to the files listed as follows:

  1. /proc/sys/kernel/sched_rt_runtime_us Default: 95% (950000) Range: -1 to (INT_MAX -1) [ -1 implies no limit, i.e., no throttling ]

  2. /proc/sys/kernel/sched_rt_period_us Default: 1s (1000000) Range: 1 to INT_MAX

Note: See Command Line Reference for the commands for manipulating real-time properties of processes.

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 - Docker Rootless Support

Run the Docker daemon as a non-root user (Rootless mode)

The Rootless mode allows you to run the Docker daemon and containers as a non-root user. This mitigates the potential vulnerabilities in the daemon and the container runtime.

As long as the prerequisites are met, rootless mode does not require root privileges even during the installation of the Docker daemon.

After its introduction in Docker Engine v19.03 as an experimental feature, the rootless mode was available in Docker Engine v20.10 as a more stable feature.

This feature is available in Photon OS 4.0 and above versions starting from the docker-20.10.14-1 version (in Ph4).

Prerequisites:

  • You must install newuidmap and newgidmap on the host. - Provided by the shadow package in Photon

  • /etc/subuid and /etc/subgid should contain at least 65,536 subordinate UIDs/GIDs for the user. In the following example, the user called testuser has 65,536 subordinate UIDs/GIDs (100000-165535).

  • You can install the pre-required packages using the following command:

    tdnf install -y shadow fuse slirp4netns libslirp
    
  • Photon 3 or above with docker-20.10.14-1 version (this version is specific to Ph4. For higher versions please refer spec file in the Photon source).

Usage:

You can perform the following tasks with the respective commands for them:

  1. Install docker-rootless using the following command:

    tdnf install -y docker-rootless
    
  2. Use the following command to add a new user:

    useradd -m test_user
    
  3. Use the following command to set a password for the new user:

    passwd test_user
    
  4. Use the following command to log in as the user you created:

    `ssh test_user@localhost`
    
  5. Run the following command:

    dockerd-rootless-setuptool.sh --help`
    

    The above command shows something like the following output:

    test_user@photon [ ~ ]$ dockerd-rootless-setuptool.sh --help
    Usage: /usr/bin/dockerd-rootless-setuptool.sh [OPTIONS] COMMAND
    
    A setup tool for Rootless Docker (dockerd-rootless.sh).
    
    Documentation: https://docs.docker.com/go/rootless/
    
    Options:
    -f, --force Ignore rootful Docker (/var/run/docker.sock)
    --skip-iptables Ignore missing iptables
    
    Commands:
    check Check prerequisites
    install Install systemd unit (if systemd is available) and show how to manage the service
    uninstall Uninstall systemd unit
    
  6. Run the following command, and then check and fix the errors and warnings, if any:

    dockerd-rootless-setuptool.sh`
    

    Run the following commands:

    a. echo "test_user:100000:65536" >> /etc/subuid

    b. echo "test_user:100000:65536" >> /etc/subgid

    c. echo "kernel.unprivileged_userns_clone = 1" >> /etc/sysctl.d/50-rootless.conf

    d. chmod 644 /etc/subuid /etc/subgid /etc/sysctl.d/50-rootless.conf

    e. sysctl --system

    After you run the above commands, the dockerd-rootless-setuptool.sh check shows the following output:

    test_user@photon [ ~ ]$ dockerd-rootless-setuptool.sh check
    
    [INFO] Requirements are satisfied
    
  7. After the Requirements are satisfied message appears, run the following command:

    dockerd-rootless-setuptool.sh install
    
  8. Carefully, go through the output messages of the above command and ensure that everything is fine. Follow the instructions that appear, if any.

  9. Add the following to your .bashrc or .bash_profile:

    export PATH=/usr/bin:$PATH
    export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
    

Now, you can run docker run -it photon as a regular user.

Limitations:

Exposing Network Ports Be aware that port numbers below 1024 are called privileged ports and are not available for rootless users. So, you need to use the unprivileged ports such as 8080, and so on. If you want to run an HTTP server, you need to run docker run -p 8080:80. However, if you really need to expose privileged ports, you can do that by adjusting sysctl /proc/sys/net/ipv4/ip_unprivileged_port_start or by setting CAP_NET_BIND SERVICE capability on the binary rootlesskit.

Limiting Resources such as CPU, Memory

Limiting resources with cgroup-related docker run flags such as --cpus, --memory, --pids-limit is supported only while running with cgroup v2 and systemd.

If docker info shows none as Cgroup Driver, the conditions are not satisfied. When these conditions are not satisfied, rootless mode ignores the cgroup-related docker run flags.

8.3 - 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.

8.4 - Support for distributed builds using Kubernetes

The distributed system using Kubernetes allows the build system to utilize the maximum CPU power across a kubernetes cluster (pods) for faster build process.

Prerequisites

  • Ensure that the NFS server is running
  • Ensure that you have the Kubernetes cluster ready that has access to the NFS server
  • Ensure that you have installed Kubernetes package and have kubeconfig accessible in the build VM.

Triggering Distributed Photon Builds

Perform the following steps in the Photon OS repository:

  1. Update the 'common/data/distributed_build_options.json' configuration file . The following parameters need to be filled:
  • command→ target to run like 'make packages' or 'make packages-minimal' or 'make toolchain-stage-1' or so on. Note: Keep the command with flag 'SCHEDULER_SERVER=enable'.

  • nfs-server-ip→ IP address of the nfs server

  • pods→ number of builder/worker pods you want such as 10 or 20. The default value is 1.

  • nfs-server-path-> path of the nfs mount. For example,/mnt/NFS_PATH/MY_DIR

  1. Run make distributed-build.

Note:

  • This process will make use of the kubeconfig file present under the home directory and start building packages over the specified cluster.
  • It creates one Master pod and multiple worker pods (numbers defined in config.json).
  • The master pod runs the scheduler while the worker or the builder pods build the packages.
  • Distributed Builder monitors the build mob and deletes everything when build has either completed successfully or failed.

The master starts the scheduler server to schedule the packages that have to be built. The worker makes REST calls to scheduler server.get package and notify after the build.

The distributed build also builds cloud images.

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

Note: Photon OS comes with a minimal set of locales by default. If you need a full set of locales, you need to install the glibc-i18n package using the following command:

tdnf install -y glibc-i18n

10 - 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.

10.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 tdnf repository: add a tdnf repository to /etc/yum.repos.d.
  • create groups and users: add groups and users to the system and set properties for them.
  • run tdnf 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

NameFrequency
disable_ec2_metadataAlways
users_groupsInstance
write_filesInstance
update_hostnameAlways
final_messageAlways
resolv_confInstance
growpartAlways
update_etc_hostsAlways
power_state_changeInstance
phone_homeInstance

10.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:

  1. Metadata
  2. 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.

10.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

  1. Perform the following steps before cloning or customizing the guest operating system:
  2. Ensure that disable_vmware_customization is set to false in the /etc/cloud/cloud.cfg file.
  3. Set manage_etc_hosts: true in the /etc/cloud/cloud.cfg file.
  4. Make a backup of the 99-disable-networking-config.cfg file and delete the file from /etc/cloud/cloud.cfg.d folder after backup.
  5. Clone the VM or customize the guest operating system.
  6. After you clone your VM or customize the guest operating system, perform the following steps:
  7. 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.
  8. 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.
  9. 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:

  1. 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.
  1. 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.

  2. 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.

10.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

  1. Create the metadata file with the following lines in the YAML format and name it meta-data:

    instance-id: iid-local01
       local-hostname: cloudimg
    
  2. Create the user data file with the following lines in YAML and name it user-data:

      #cloud-config
      hostname: testhost
      packages:
       - vim
    
  3. 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
    
  4. 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
    
  5. 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.

10.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 at the location 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

  1. 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
  1. 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
  1. 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
  1. 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.

10.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 a free image and is free. You can download Photon OS for GCE from https://packages.vmware.com/photon/5.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:

    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./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
    
  2. 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>
    

11 - Security Policy

This section describes the security policy of Photon OS.

11.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

11.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.

11.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:

  1. Create a directory named /etc/gnutls.
  2. In /etc/gnutls create a file named default-priorities.
  3. 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.
  4. 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:
console 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:

  1. 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.

12 - Support for zstd Compression

Zstandard (zstd) is a fast compression algorithm that provides high compression ratios. Photon OS offers support for the zstd compression and allows you to define which compression algorithm you want.

By using the zstd compression, the following benefits are seen:

  • Faster installation of RPMs and the overall system

  • Faster builds

  • Reduction in the size of artifacts created

13 - Photon RPM OSTree: a simple guide

13.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 document

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 onwards. There are references to the concepts discussed throughout the book, if you need to understand them better.

RPM OSTree in Photon OS

This section is relevant to RPM OSTree in Photon OS.

Photon OS 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

13.2 - Installing a host against default server repository

RPM-OSTree Host default server repo installation option in Photon OS 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 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 “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.

PhotonChooseHost

Continue with setting up a host name like photon1-def and a root password, re-confirm. Then, select “Default OSTree Server” and continue.

PhotonChooseHostDefault

PhotonHostDefaultFinish

When installation is over, the VM will reboot and will show in grub VMWare Photon/Linux 5.0_minimal (ostree), which will reassure that it’s booting from an OSTree image!

PhotonHostFirstRebootGrub

Boot, login and you are ready to use it.

To upgrade your host, see Host updating operations.

13.3 - Concepts in Action

Now that we have a fresh installed host (either as default or custom), we can better explain 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-7c2d910d79e9 [ ~ ]# rpm-ostree status 
State: idle
Deployments:
● ostree://photon:photon/5.0/x86_64/minimal
    Version: 5.0_minimal (2021-02-20T07:15:43Z)
Commit: 965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f

Bootable filetree version

5.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 5.0_minimal.1, 5.0_minimal.2, 5.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-7c2d910d79e9 [ ~ ]# rpm-ostree status -v
State: idle
AutomaticUpdates: disabled
Deployments:
● ostree://photon:photon/5.0/x86_64/minimal
    Version: 5.0_minimal (2021-02-20T07:15:43Z)
Commit: 965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f
└─ photon (2021-02-20T07:11:24Z)
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-7c2d910d79e9 [ ~ ]# 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
    initramfsEnable or disable local initramfs regeneration
    install  Overlay additional packages
    uninstallRemove overlayed additional packages
    override Manage base package overrides
    resetRemove all mutations
    refresh-md   Generate rpm repo metadata
    kargsQuery or modify kernel arguments

Help Options:
    -h, --help   Show help options

Application Options:
    --versionPrint 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-7c2d910d79e9 [ ~ ]# cat /ostree/repo/refs/remotes/photon/photon/5.0/x86_64/minimal
820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88

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-7c2d910d79e9 [ ~ ]# ostree admin status
* photon 965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f.0
Version: 5.0_minimal
origin refspec: photon:photon/5.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-7c2d910d79e9 [ ~ ]# cat /ostree/repo/refs/heads/ostree/0/1/0 
965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f

This also where this command that lists the references (local heads and remotes) takes its data from:

root@photon-7c2d910d79e9 [ ~ ]# ostree refs
photon:photon/5.0/x86_64/minimal
ostree/0/1/0

Based on that, it could find the root of the deployment that it boots from. The actual filetree is deployed right here:

root@photon-7c2d910d79e9 [ ~ ]# ls -l /ostree/deploy/photon/deploy/965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f.0
total 36
lrwxrwxrwx  2 root root7 Feb 23 05:43 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 45 root root 4096 Feb 23 06:08 etc
lrwxrwxrwx  2 root root8 Feb 23 05:43 home -> var/home
lrwxrwxrwx  3 root root7 Feb 23 05:43 lib -> usr/lib
lrwxrwxrwx  3 root root7 Feb 23 05:43 lib64 -> usr/lib
lrwxrwxrwx  2 root root9 Feb 23 05:43 media -> run/media
lrwxrwxrwx  2 root root7 Feb 23 05:43 mnt -> var/mnt
lrwxrwxrwx  2 root root7 Feb 23 05:43 opt -> var/opt
lrwxrwxrwx  2 root root   14 Feb 23 05:43 ostree -> sysroot/ostree
drwxr-xr-x  2 root root 4096 Jan  1  1970 proc
lrwxrwxrwx  2 root root   12 Feb 23 05:43 root -> var/roothome
drwxr-xr-x  2 root root 4096 Jan  1  1970 run
lrwxrwxrwx  2 root root8 Feb 23 05:43 sbin -> usr/sbin
lrwxrwxrwx  2 root root7 Feb 23 05:43 srv -> var/srv
drwxr-xr-x  2 root root 4096 Jan  1  1970 sys
drwxr-xr-x  4 root root 4096 Feb 23 05:44 sysroot
lrwxrwxrwx  2 root root   11 Feb 23 05:43 tmp -> sysroot/tmp
drwxr-xr-x 10 root root 4096 Jan  1  1970 usr
drwxr-xr-x  8 root root 4096 Feb 23 05:44 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-7c2d910d79e9 [ ~ ]# cat /ostree/deploy/photon/deploy/965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f.0.origin 
[origin]
refspec=photon:photon/5.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-7c2d910d79e9 [ ~ ]# ls -l /ostree/deploy/photon/var/
total 52
drwxr-xr-x   5 root root 4096 Feb 23 05:44 cache
drwxr-xr-x   2 root root 4096 Feb 23 05:44 home
drwxr-xr-x. 17 root root 4096 Feb 23 05:44 lib
drwxr-xr-x   2 root root 4096 Feb 23 05:44 local
lrwxrwxrwx.  1 root root   11 Feb 23 05:44 lock -> ../run/lock
drwxr-xr-x.  4 root root 4096 Feb 23 05:44 log
drwxr-xr-x   2 root root 4096 Feb 23 05:44 mail
drwxr-xr-x   2 root root 4096 Feb 23 05:44 mnt
drwxr-xr-x   4 root root 4096 Feb 23 05:44 opt
drwx------   4 root root 4096 Feb 23 06:09 roothome
lrwxrwxrwx.  1 root root6 Feb 23 05:44 run -> ../run
drwxr-xr-x   3 root root 4096 Feb 23 05:44 spool
drwxr-xr-x   2 root root 4096 Feb 23 05:44 srv
drwxrwxrwt.  5 root root 4096 Feb 23 06:08 tmp
drwxr-xr-x  11 root root 4096 Feb 23 05:44 usrlocal

13.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-7c2d910d79e9 [ ~ ]# ostree log photon/5.0/x86_64/minimal
commit 820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88
ContentChecksum:  c7956cedc5c1b8c07a06e10789c17364a5b7a4b970daab64f3398b7c42bd97d9
Date:  2020-11-04 02:21:47 +0000
Version: 5.0_minimal
(no subject)

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-7c2d910d79e9 [ ~ ]# ostree log 820b
commit 820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88
ContentChecksum:  c7956cedc5c1b8c07a06e10789c17364a5b7a4b970daab64f3398b7c42bd97d9
Date:  2020-11-04 02:21:47 +0000
Version: 5.0_minimal
(no subject)
root@photon-7c2d910d79e9 [ ~ ]# ostree log 820b --raw
commit 820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88
({'rpmostree.inputhash': <'1ce3f6d518ec2cbaebc2de2ccb01888e59fc7efb482caba590bc96a604e54f82'>, 'rpmostree.rpmmd-repos': <[{'id': <'photon'>, 'timestamp': <uint64 1604456423>}]>, 'version': <'5.0_minimal'>, 'rpmostree.rpmdb.pkglist': <[('Linux-PAM', '0', '1.4.0', '2.ph5', 'x86_64'), ('attr', '0', '2.4.48', '1.ph5', 'x86_64'), ('audit', '0', '2.8.5', '3.ph5', 'x86_64'), ('autogen-libopts', '0', '5.18.16', '3.ph5', 'x86_64'), ('bash', '0', '5.0', '1.ph5', 'x86_64'), ('bc', '0', '1.07.1', '4.ph5', 'x86_64'), ('bridge-utils', '0', '1.6', '1.ph5', 'x86_64'), ('bubblewrap', '0', '0.4.1', '1.ph5', 'x86_64'), ('bzip2', '0', '1.0.8', '3.ph5', 'x86_64'), ('bzip2-libs', '0', '1.0.8', '3.ph5', 'x86_64'), ('ca-certificates', '0', '20201001', '1.ph5', 'x86_64'), ('ca-certificates-pki', '0', '20201001', '1.ph5', 'x86_64'), ('cloud-init', '0', '20.3', '2.ph5', 'noarch'), ('coreutils-selinux', '0', '8.32', '2.ph5', 'x86_64'), ('cpio', '0', '2.13', '1.ph5', 'x86_64'), ('cracklib', '0', '2.9.7', '1.ph5', 'x86_64'), ('cracklib-dicts', '0', '2.9.7', '1.ph5', 'x86_64'), ('curl', '0', '7.72.0', '2.ph5', 'x86_64'), ('curl-libs', '0', '7.72.0', '2.ph5', 'x86_64'), ('cyrus-sasl', '0', '2.1.27', '3.ph5', 'x86_64'), ('dbus', '0', '1.13.18', '1.ph5', 'x86_64'), ('device-mapper', '0', '2.03.10', '2.ph5', 'x86_64'), ('device-mapper-libs', '0', '2.03.10', '2.ph5', 'x86_64'), ('dhcp-client', '0', '4.4.2', '1.ph5', 'x86_64'), ('dhcp-libs', '0', '4.4.2', '1.ph5', 'x86_64'), ('dracut', '0', '050', '5.ph5', 'x86_64'), ('dracut-tools', '0', '050', '5.ph5', 'x86_64'), ('e2fsprogs', '0', '1.45.6', '2.ph5', 'x86_64'), ('e2fsprogs-libs', '0', '1.45.6', '2.ph5', 'x86_64'), ('elfutils', '0', '0.181', '2.ph5', 'x86_64'), ('elfutils-libelf', '0', '0.181', '2.ph5', 'x86_64'), ('expat', '0', '2.2.9', '2.ph5', 'x86_64'), ('expat-libs', '0', '2.2.9', '2.ph5', 'x86_64'), ('file', '0', '5.39', '1.ph5', 'x86_64'), ('file-libs', '0', '5.39', '1.ph5', 'x86_64'), ('filesystem', '0', '1.1', '4.ph5', 'x86_64'), ('findutils', '0', '4.7.0', '1.ph5', 'x86_64'), ('finger', '0', '0.17', '3.ph5', 'x86_64'), ('flex', '0', '2.6.4', '3.ph5', 'x86_64'), ('fuse', '0', '2.9.9', '1.ph5', 'x86_64'), ('gawk', '0', '5.1.0', '1.ph5', 'x86_64'), ('gc', '0', '8.0.4', '1.ph5', 'x86_64'), ('gdbm', '0', '1.18.1', '1.ph5', 'x86_64'), ('glib', '0', '2.66.1', '1.ph5', 'x86_64'), ('glib-networking', '0', '2.66.0', '1.ph5', 'x86_64'), ('glibc', '0', '2.32', '1.ph5', 'x86_64'), ('glibc-iconv', '0', '2.32', '1.ph5', 'x86_64'), ('gmp', '0', '6.2.0', '1.ph5', 'x86_64'), ('gnupg', '0', '2.2.23', '1.ph5', 'x86_64'), ('gnutls', '0', '3.6.15', '3.ph5', 'x86_64'), ('gobject-introspection', '0', '1.66.0', '1.ph5', 'x86_64'), ('gpgme', '0', '1.14.0', '1.ph5', 'x86_64'), ('grep', '0', '3.4', '1.ph5', 'x86_64'), ('grub2', '0', '2.04', '2.ph5', 'x86_64'), ('grub2-efi', '0', '2.04', '2.ph5', 'x86_64'), ('grub2-efi-image', '0', '2.04', '2.ph5', 'x86_64'), ('grub2-pc', '0', '2.04', '2.ph5', 'x86_64'), ('grub2-theme', '0', '5.0', '1.ph5', 'noarch'), ('grub2-theme-ostree', '0', '5.0', '1.ph5', 'noarch'), ('guile', '0', '2.0.13', '3.ph5', 'x86_64'), ('gzip', '0', '1.10', '1.ph5', 'x86_64'), ('iana-etc', '0', '2.30', '2.ph5', 'noarch'), ('icu', '0', '67.1', '1.ph5', 'x86_64'), ('iproute2', '0', '5.8.0', '1.ph5', 'x86_64'), ('iptables', '0', '1.8.4', '1.ph5', 'x86_64'), ('iputils', '0', '20200821', '1.ph5', 'x86_64'), ('json-c', '0', '0.15', '2.ph5', 'x86_64'), ('json-glib', '0', '1.6.0', '1.ph5', 'x86_64'), ('kmod', '0', '27', '1.ph5', 'x86_64'), ('krb5', '0', '1.17', '4.ph5', 'x86_64'), ('libacl', '0', '2.2.53', '1.ph5', 'x86_64'), ('libarchive', '0', '3.4.3', '3.ph5', 'x86_64'), ('libassuan', '0', '2.5.3', '1.ph5', 'x86_64'), ('libcap', '0', '2.43', '1.ph5', 'x86_64'), ('libcap-ng', '0', '0.8', '1.ph5', 'x86_64'), ('libdb', '0', '5.3.28', '2.ph5', 'x86_64'), ('libdnet', '0', '1.11', '7.ph5', 'x86_64'), ('libffi', '0', '3.3', '1.ph5', 'x86_64'), ('libgcc', '0', '8.4.0', '1.ph5', 'x86_64'), ('libgcrypt', '0', '1.8.6', '2.ph5', 'x86_64'), ('libgpg-error', '0', '1.39', '1.ph5', 'x86_64'), ('libgpg-error-devel', '0', '1.39', '1.ph5', 'x86_64'), ('libksba', '0', '1.4.0', '1.ph5', 'x86_64'), ('libltdl', '0', '2.4.6', '3.ph5', 'x86_64'), ('libmetalink', '0', '0.1.3', '2.ph5', 'x86_64'), ('libmicrohttpd', '0', '0.9.71', '2.ph5', 'x86_64'), ('libmodulemd', '0', '2.9.4', '1.ph5', 'x86_64'), ('libmspack', '0', '0.10.1alpha', '1.ph5', 'x86_64'), ('libnsl', '0', '1.3.0', '1.ph5', 'x86_64'), ('libpsl', '0', '0.21.1', '1.ph5', 'x86_64'), ('libpwquality', '0', '1.4.2', '1.ph5', 'x86_64'), ('librepo', '0', '1.12.1', '3.ph5', 'x86_64'), ('libseccomp', '0', '2.5.0', '2.ph5', 'x86_64'), ('libselinux', '0', '3.1', '1.ph5', 'x86_64'), ('libsemanage', '0', '3.1', '1.ph5', 'x86_64'), ('libsepol', '0', '3.1', '1.ph5', 'x86_64'), ('libsolv', '0', '0.6.35', '5.ph5', 'x86_64'), ('libsoup', '0', '2.72.0', '1.ph5', 'x86_64'), ('libssh2', '0', '1.9.0', '2.ph5', 'x86_64'), ('libstdc++', '0', '8.4.0', '1.ph5', 'x86_64'), ('libtasn1', '0', '4.14', '1.ph5', 'x86_64'), ('libtirpc', '0', '1.2.6', '1.ph5', 'x86_64'), ('libtool', '0', '2.4.6', '3.ph5', 'x86_64'), ('libunistring', '0', '0.9.10', '1.ph5', 'x86_64'), ('libxml2', '0', '2.9.10', '3.ph5', 'x86_64'), ('libxml2-devel', '0', '2.9.10', '3.ph5', 'x86_64'), ('libxslt', '0', '1.1.34', '1.ph5', 'x86_64'), ('libyaml', '0', '0.2.5', '1.ph5', 'x86_64'), ('linux', '0', '5.9.0', '3.ph5', 'x86_64'), ('lua', '0', '5.3.5', '1.ph5', 'x86_64'), ('lz4', '0', '1.9.2', '1.ph5', 'x86_64'), ('m4', '0', '1.4.18', '3.ph5', 'x86_64'), ('motd', '0', '0.1.3', '6.ph5', 'noarch'), ('mozjs', '0', '78.3.1', '1.ph5', 'x86_64'), ('mpfr', '0', '4.1.0', '1.ph5', 'x86_64'), ('ncurses', '0', '6.2', '2.ph5', 'x86_64'), ('ncurses-libs', '0', '6.2', '2.ph5', 'x86_64'), ('ncurses-terminfo', '0', '6.2', '2.ph5', 'x86_64'), ('net-tools', '0', '1.60', '12.ph5', 'x86_64'), ('nettle', '0', '3.6', '1.ph5', 'x86_64'), ('npth', '0', '1.6', '1.ph5', 'x86_64'), ('nspr', '0', '4.29', '1.ph5', 'x86_64'), ('nss', '0', '3.57', '1.ph5', 'x86_64'), ('nss-altfiles', '0', '2.23.0', '1.ph5', 'x86_64'), ('nss-libs', '0', '3.57', '1.ph5', 'x86_64'), ('open-vm-tools', '0', '11.1.5', '4.ph5', 'x86_64'), ('openldap', '0', '2.4.53', '2.ph5', 'x86_64'), ('openssh', '0', '8.4p1', '2.ph5', 'x86_64'), ('openssh-clients', '0', '8.4p1', '2.ph5', 'x86_64'), ('openssh-server', '0', '8.4p1', '2.ph5', 'x86_64'), ('openssl', '0', '1.1.1g', '3.ph5', 'x86_64'), ('ostree', '0', '2020.6', '1.ph5', 'x86_64'), ('ostree-grub2', '0', '2020.6', '1.ph5', 'x86_64'), ('ostree-libs', '0', '2020.6', '1.ph5', 'x86_64'), ('pcre', '0', '8.44', '1.ph5', 'x86_64'), ('pcre-libs', '0', '8.44', '1.ph5', 'x86_64'), ('photon-release', '0', '5.0', '1.ph5', 'noarch'), ('photon-repos', '0', '5.0', '1.ph5', 'noarch'), ('pinentry', '0', '1.1.0', '1.ph5', 'x86_64'), ('pkg-config', '0', '0.29.2', '3.ph5', 'x86_64'), ('policycoreutils', '0', '3.1', '1.ph5', 'x86_64'), ('polkit', '0', '0.118', '1.ph5', 'x86_64'), ('popt', '0', '1.16', '5.ph5', 'x86_64'), ('procps-ng', '0', '3.3.16', '1.ph5', 'x86_64'), ('python3', '0', '3.8.6', '1.ph5', 'x86_64'), ('python3-PyYAML', '0', '5.3.1', '1.ph5', 'x86_64'), ('python3-asn1crypto', '0', '1.4.0', '1.ph5', 'noarch'), ('python3-attrs', '0', '20.2.0', '2.ph5', 'noarch'), ('python3-certifi', '0', '2020.6.20', '1.ph5', 'noarch'), ('python3-cffi', '0', '1.14.3', '2.ph5', 'x86_64'), ('python3-chardet', '0', '3.0.4', '2.ph5', 'noarch'), ('python3-configobj', '0', '5.0.6', '5.ph5', 'noarch'), ('python3-cryptography', '0', '3.1.1', '2.ph5', 'x86_64'), ('python3-gobject-introspection', '0', '1.66.0', '1.ph5', 'x86_64'), ('python3-idna', '0', '2.10', '1.ph5', 'noarch'), ('python3-jinja2', '0', '2.11.2', '1.ph5', 'noarch'), ('python3-jsonpatch', '0', '1.26', '1.ph5', 'noarch'), ('python3-jsonpointer', '0', '2.0', '2.ph5', 'noarch'), ('python3-jsonschema', '0', '3.2.0', '1.ph5', 'noarch'), ('python3-libs', '0', '3.8.6', '1.ph5', 'x86_64'), ('python3-markupsafe', '0', '1.1.1', '1.ph5', 'x86_64'), ('python3-netifaces', '0', '0.10.9', '2.ph5', 'x86_64'), ('python3-oauthlib', '0', '3.1.0', '1.ph5', 'noarch'), ('python3-packaging', '0', '20.4', '2.ph5', 'noarch'), ('python3-prettytable', '0', '0.7.2', '7.ph5', 'noarch'), ('python3-pyOpenSSL', '0', '19.1.0', '2.ph5', 'noarch'), ('python3-pyasn1', '0', '0.4.8', '1.ph5', 'noarch'), ('python3-pycparser', '0', '2.20', '1.ph5', 'noarch'), ('python3-pyparsing', '0', '2.4.7', '1.ph5', 'noarch'), ('python3-pyrsistent', '0', '0.17.3', '1.ph5', 'x86_64'), ('python3-requests', '0', '2.24.0', '1.ph5', 'noarch'), ('python3-setuptools', '0', '3.8.6', '1.ph5', 'noarch'), ('python3-six', '0', '1.15.0', '2.ph5', 'noarch'), ('python3-urllib3', '0', '1.25.10', '2.ph5', 'noarch'), ('python3-xml', '0', '3.8.6', '1.ph5', 'x86_64'), ('readline', '0', '7.0', '3.ph5', 'x86_64'), ('rpcsvc-proto', '0', '1.4.2', '1.ph5', 'x86_64'), ('rpm', '0', '4.14.2', '11.ph5', 'x86_64'), ('rpm-libs', '0', '4.14.2', '11.ph5', 'x86_64'), ('rpm-ostree', '0', '2020.5', '4.ph5', 'x86_64'), ('sed', '0', '4.8', '1.ph5', 'x86_64'), ('selinux-policy', '0', '3.14.7', '1.ph5', 'noarch'), ('shadow', '0', '4.8.1', '2.ph5', 'x86_64'), ('shadow-tools', '0', '4.8.1', '2.ph5', 'x86_64'), ('shim-signed', '0', '15', '1.ph5', 'x86_64'), ('sqlite-libs', '0', '3.33.0', '1.ph5', 'x86_64'), ('sudo', '0', '1.8.30', '2.ph5', 'x86_64'), ('systemd', '0', '245.5', '3.ph5', 'x86_64'), ('tcp_wrappers', '0', '7.6', '7.ph5', 'x86_64'), ('tzdata', '0', '2020a', '1.ph5', 'noarch'), ('util-linux', '0', '2.36', '1.ph5', 'x86_64'), ('util-linux-libs', '0', '2.36', '1.ph5', 'x86_64'), ('vim', '0', '8.2.1361', '1.ph5', 'x86_64'), ('which', '0', '2.21', '6.ph5', 'x86_64'), ('xmlsec1', '0', '1.2.30', '3.ph5', 'x86_64'), ('xz', '0', '5.2.5', '1.ph5', 'x86_64'), ('xz-libs', '0', '5.2.5', '1.ph5', 'x86_64'), ('zchunk', '0', '1.1.7', '1.ph5', 'x86_64'), ('zchunk-libs', '0', '1.1.7', '1.ph5', 'x86_64'), ('zlib', '0', '1.2.11', '2.ph5', 'x86_64'), ('zstd', '0', '1.4.5', '2.ph5', 'x86_64'), ('zstd-libs', '0', '1.4.5', '2.ph5', 'x86_64')]>}, @ay [], @a(say) [], '', '', uint64 1604456507, [byte 0xca, 0x99, 0x35, 0xe5, 0xaa, 0xc6, 0xbd, 0xb3, 0x52, 0xb4, 0x81, 0x62, 0xbb, 0x3f, 0xba, 0x44, 0x0e, 0x3c, 0xa0, 0x00, 0xc8, 0x6f, 0x7c, 0x32, 0xa0, 0xa0, 0x8b, 0xc6, 0xf0, 0xd5, 0x06, 0x0e], [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-7c2d910d79e9 [ ~ ]# ostree ls photon/5.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-7c2d910d79e9 [ ~ ]# ostree ls photon/5.0/x86_64/minimal -C
d00755 0 0  0 ca9935e5aac6bdb352b48162bb3fba440e3ca000c86f7c32a0a08bc6f0d5060e 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 83902b1171980665a74c9ea4d3817add50e9fd3279d3ee92381fb2c0098f7ab0 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-7c2d910d79e9 [ ~ ]# ostree ls photon/5.0/x86_64/minimal -R | grep -e '[Rr]pm-\?[Oo]stree'
-00755 0 0 787208 /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
d00755 0 0  0 /usr/bin/rpm-ostree-server
-00755 0 0   6452 /usr/bin/rpm-ostree-server/mkostreerepo
-00644 0 0209 /usr/etc/rpm-ostreed.conf
l00777 0 0  0 /usr/lib/librpmostree-1.so.1 -> librpmostree-1.so.1.0.0
-00755 0 0 9878248 /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 1846216 /usr/lib/rpm-ostree/libdnf.so.2
-00644 0 0622 /usr/lib/rpm-ostree/rpm-ostree-0-integration.conf
d00755 0 0  0 /usr/lib/sysimage/rpm-ostree-base-db
-00644 0 0 1069056 /usr/lib/sysimage/rpm-ostree-base-db/Basenames
-00644 0 0   8192 /usr/lib/sysimage/rpm-ostree-base-db/Conflictname
-00644 0 0 159744 /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  16384 /usr/lib/sysimage/rpm-ostree-base-db/Name
-00644 0 0   8192 /usr/lib/sysimage/rpm-ostree-base-db/Obsoletename
-00644 0 0 4313088 /usr/lib/sysimage/rpm-ostree-base-db/Packages
-00644 0 0 102400 /usr/lib/sysimage/rpm-ostree-base-db/Providename
-00644 0 0   8192 /usr/lib/sysimage/rpm-ostree-base-db/Recommendname
-00644 0 0 106496 /usr/lib/sysimage/rpm-ostree-base-db/Requirename
-00644 0 0  24576 /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 0263 /usr/lib/systemd/system/rpm-ostree-bootstatus.service
-00644 0 0257 /usr/lib/systemd/system/rpm-ostreed-automatic.service
-00644 0 0227 /usr/lib/systemd/system/rpm-ostreed-automatic.timer
-00644 0 0325 /usr/lib/systemd/system/rpm-ostreed.service
-00644 0 0102 /usr/lib/systemd/system-preset/40-rpm-ostree-auto.preset
-00644 0 0622 /usr/lib/tmpfiles.d/rpm-ostree-0-integration.conf
-00644 0 0   1572 /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  17210 /usr/share/dbus-1/interfaces/org.projectatomic.rpmostree1.xml
-00644 0 0133 /usr/share/dbus-1/system-services/org.projectatomic.rpmostree1.service
-00644 0 0   1530 /usr/share/dbus-1/system.d/org.projectatomic.rpmostree1.conf
-00644 0 0   6593 /usr/share/polkit-1/actions/org.projectatomic.rpmostree1.policy
d00755 0 0  0 /usr/share/rpm-ostree
-00644 0 0   1199 /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-7c2d910d79e9 [ ~ ]# ostree admin config-diff
M  ssh/sshd_config
M  udev/hwdb.bin
M  fstab
M  machine-id
M  gshadow
M  hosts
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  hostname
A  group-
A  locale.conf
A  .pwd.lock
A  gshadow-
A  shadow-
A  resolv.conf
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-7c2d910d79e9 [ ~ ]# rpm-ostree db list photon/5.0/x86_64/minimal
    ostree commit: photon/5.0/x86_64/minimal (820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88)
     Linux-PAM-1.4.0-2.ph5.x86_64
     attr-2.4.48-1.ph5.x86_64
     audit-2.8.5-3.ph5.x86_64
     autogen-libopts-5.18.16-3.ph5.x86_64
     bash-5.0-1.ph5.x86_64
     bc-1.07.1-4.ph5.x86_64
     bridge-utils-1.6-1.ph5.x86_64
     bubblewrap-0.4.1-1.ph5.x86_64
     bzip2-1.0.8-3.ph5.x86_64
     bzip2-libs-1.0.8-3.ph5.x86_64
     ca-certificates-20201001-1.ph5.x86_64
     ca-certificates-pki-20201001-1.ph5.x86_64
     cloud-init-20.3-2.ph5.noarch
     coreutils-selinux-8.32-2.ph5.x86_64
     cpio-2.13-1.ph5.x86_64
     cracklib-2.9.7-1.ph5.x86_64
     cracklib-dicts-2.9.7-1.ph5.x86_64
     curl-7.72.0-2.ph5.x86_64
     curl-libs-7.72.0-2.ph5.x86_64
     cyrus-sasl-2.1.27-3.ph5.x86_64
     dbus-1.13.18-1.ph5.x86_64
     device-mapper-2.03.10-2.ph5.x86_64
     device-mapper-libs-2.03.10-2.ph5.x86_64
     dhcp-client-4.4.2-1.ph5.x86_64
     dhcp-libs-4.4.2-1.ph5.x86_64
     dracut-050-5.ph5.x86_64
     dracut-tools-050-5.ph5.x86_64
     e2fsprogs-1.45.6-2.ph5.x86_64
     e2fsprogs-libs-1.45.6-2.ph5.x86_64
     elfutils-0.181-2.ph5.x86_64
     elfutils-libelf-0.181-2.ph5.x86_64
     expat-2.2.9-2.ph5.x86_64
     expat-libs-2.2.9-2.ph5.x86_64
     file-5.39-1.ph5.x86_64
     file-libs-5.39-1.ph5.x86_64
     filesystem-1.1-4.ph5.x86_64
     findutils-4.7.0-1.ph5.x86_64
     finger-0.17-3.ph5.x86_64
     flex-2.6.4-3.ph5.x86_64
     fuse-2.9.9-1.ph5.x86_64
     gawk-5.1.0-1.ph5.x86_64
     gc-8.0.4-1.ph5.x86_64
     gdbm-1.18.1-1.ph5.x86_64
     glib-2.66.1-1.ph5.x86_64
     glib-networking-2.66.0-1.ph5.x86_64
     glibc-2.32-1.ph5.x86_64
     glibc-iconv-2.32-1.ph5.x86_64
     gmp-6.2.0-1.ph5.x86_64
     gnupg-2.2.23-1.ph5.x86_64
     gnutls-3.6.15-3.ph5.x86_64
     gobject-introspection-1.66.0-1.ph5.x86_64
     gpgme-1.14.0-1.ph5.x86_64
     grep-3.4-1.ph5.x86_64
     grub2-2.04-2.ph5.x86_64
     grub2-efi-2.04-2.ph5.x86_64
     grub2-efi-image-2.04-2.ph5.x86_64
     grub2-pc-2.04-2.ph5.x86_64
     grub2-theme-5.0-1.ph5.noarch
     grub2-theme-ostree-5.0-1.ph5.noarch
     guile-2.0.13-3.ph5.x86_64
     gzip-1.10-1.ph5.x86_64
     iana-etc-2.30-2.ph5.noarch
     icu-67.1-1.ph5.x86_64
     iproute2-5.8.0-1.ph5.x86_64
     iptables-1.8.4-1.ph5.x86_64
     iputils-20200821-1.ph5.x86_64
     json-c-0.15-2.ph5.x86_64
     json-glib-1.6.0-1.ph5.x86_64
     kmod-27-1.ph5.x86_64
     krb5-1.17-4.ph5.x86_64
     libacl-2.2.53-1.ph5.x86_64
     libarchive-3.4.3-3.ph5.x86_64
     libassuan-2.5.3-1.ph5.x86_64
     libcap-2.43-1.ph5.x86_64
     libcap-ng-0.8-1.ph5.x86_64
     libdb-5.3.28-2.ph5.x86_64
     libdnet-1.11-7.ph5.x86_64
     libffi-3.3-1.ph5.x86_64
     libgcc-8.4.0-1.ph5.x86_64
     libgcrypt-1.8.6-2.ph5.x86_64
     libgpg-error-1.39-1.ph5.x86_64
     libgpg-error-devel-1.39-1.ph5.x86_64
     libksba-1.4.0-1.ph5.x86_64
     libltdl-2.4.6-3.ph5.x86_64
     libmetalink-0.1.3-2.ph5.x86_64
     libmicrohttpd-0.9.71-2.ph5.x86_64
     libmodulemd-2.9.4-1.ph5.x86_64
     libmspack-0.10.1alpha-1.ph5.x86_64
     libnsl-1.3.0-1.ph5.x86_64
     libpsl-0.21.1-1.ph5.x86_64
     libpwquality-1.4.2-1.ph5.x86_64
     librepo-1.12.1-3.ph5.x86_64
     libseccomp-2.5.0-2.ph5.x86_64
     libselinux-3.1-1.ph5.x86_64
     libsemanage-3.1-1.ph5.x86_64
     libsepol-3.1-1.ph5.x86_64
     libsolv-0.6.35-5.ph5.x86_64
     libsoup-2.72.0-1.ph5.x86_64
     libssh2-1.9.0-2.ph5.x86_64
     libstdc++-8.4.0-1.ph5.x86_64
     libtasn1-4.14-1.ph5.x86_64
     libtirpc-1.2.6-1.ph5.x86_64
     libtool-2.4.6-3.ph5.x86_64
     libunistring-0.9.10-1.ph5.x86_64
     libxml2-2.9.10-3.ph5.x86_64
     libxml2-devel-2.9.10-3.ph5.x86_64
     libxslt-1.1.34-1.ph5.x86_64
     libyaml-0.2.5-1.ph5.x86_64
     linux-5.9.0-3.ph5.x86_64
     lua-5.3.5-1.ph5.x86_64
     lz4-1.9.2-1.ph5.x86_64
     m4-1.4.18-3.ph5.x86_64
     motd-0.1.3-6.ph5.noarch
     mozjs-78.3.1-1.ph5.x86_64
     mpfr-4.1.0-1.ph5.x86_64
     ncurses-6.2-2.ph5.x86_64
     ncurses-libs-6.2-2.ph5.x86_64
     ncurses-terminfo-6.2-2.ph5.x86_64
     net-tools-1.60-12.ph5.x86_64
     nettle-3.6-1.ph5.x86_64
     npth-1.6-1.ph5.x86_64
     nspr-4.29-1.ph5.x86_64
     nss-3.57-1.ph5.x86_64
     nss-altfiles-2.23.0-1.ph5.x86_64
     nss-libs-3.57-1.ph5.x86_64
     open-vm-tools-11.1.5-4.ph5.x86_64
     openldap-2.4.53-2.ph5.x86_64
     openssh-8.4p1-2.ph5.x86_64
     openssh-clients-8.4p1-2.ph5.x86_64
     openssh-server-8.4p1-2.ph5.x86_64
     openssl-1.1.1g-3.ph5.x86_64
     ostree-2020.6-1.ph5.x86_64
     ostree-grub2-2020.6-1.ph5.x86_64
     ostree-libs-2020.6-1.ph5.x86_64
     pcre-8.44-1.ph5.x86_64
     pcre-libs-8.44-1.ph5.x86_64
     photon-release-5.0-1.ph5.noarch
     photon-repos-5.0-1.ph5.noarch
     pinentry-1.1.0-1.ph5.x86_64
     pkg-config-0.29.2-3.ph5.x86_64
     policycoreutils-3.1-1.ph5.x86_64
     polkit-0.118-1.ph5.x86_64
     popt-1.16-5.ph5.x86_64
     procps-ng-3.3.16-1.ph5.x86_64
     python3-3.8.6-1.ph5.x86_64
     python3-PyYAML-5.3.1-1.ph5.x86_64
     python3-asn1crypto-1.4.0-1.ph5.noarch
     python3-attrs-20.2.0-2.ph5.noarch
     python3-certifi-2020.6.20-1.ph5.noarch
     python3-cffi-1.14.3-2.ph5.x86_64
     python3-chardet-3.0.4-2.ph5.noarch
     python3-configobj-5.0.6-5.ph5.noarch
     python3-cryptography-3.1.1-2.ph5.x86_64
     python3-gobject-introspection-1.66.0-1.ph5.x86_64
     python3-idna-2.10-1.ph5.noarch
     python3-jinja2-2.11.2-1.ph5.noarch
     python3-jsonpatch-1.26-1.ph5.noarch
     python3-jsonpointer-2.0-2.ph5.noarch
     python3-jsonschema-3.2.0-1.ph5.noarch
     python3-libs-3.8.6-1.ph5.x86_64
     python3-markupsafe-1.1.1-1.ph5.x86_64
     python3-netifaces-0.10.9-2.ph5.x86_64
     python3-oauthlib-3.1.0-1.ph5.noarch
     python3-packaging-20.4-2.ph5.noarch
     python3-prettytable-0.7.2-7.ph5.noarch
     python3-pyOpenSSL-19.1.0-2.ph5.noarch
     python3-pyasn1-0.4.8-1.ph5.noarch
     python3-pycparser-2.20-1.ph5.noarch
     python3-pyparsing-2.4.7-1.ph5.noarch
     python3-pyrsistent-0.17.3-1.ph5.x86_64
     python3-requests-2.24.0-1.ph5.noarch
     python3-setuptools-3.8.6-1.ph5.noarch
     python3-six-1.15.0-2.ph5.noarch
     python3-urllib3-1.25.10-2.ph5.noarch
     python3-xml-3.8.6-1.ph5.x86_64
     readline-7.0-3.ph5.x86_64
     rpcsvc-proto-1.4.2-1.ph5.x86_64
     rpm-4.14.2-11.ph5.x86_64
     rpm-libs-4.14.2-11.ph5.x86_64
     rpm-ostree-2020.5-4.ph5.x86_64
     sed-4.8-1.ph5.x86_64
     selinux-policy-3.14.7-1.ph5.noarch
     shadow-4.8.1-2.ph5.x86_64
     shadow-tools-4.8.1-2.ph5.x86_64
     shim-signed-15-1.ph5.x86_64
     sqlite-libs-3.33.0-1.ph5.x86_64
     sudo-1.8.30-2.ph5.x86_64
     systemd-245.5-3.ph5.x86_64
     tcp_wrappers-7.6-7.ph5.x86_64
     tzdata-2020a-1.ph5.noarch
     util-linux-2.36-1.ph5.x86_64
     util-linux-libs-2.36-1.ph5.x86_64
     vim-8.2.1361-1.ph5.x86_64
     which-2.21-6.ph5.x86_64
     xmlsec1-1.2.30-3.ph5.x86_64
     xz-5.2.5-1.ph5.x86_64
     xz-libs-5.2.5-1.ph5.x86_64
     zchunk-1.1.7-1.ph5.x86_64
     zchunk-libs-1.1.7-1.ph5.x86_64
     zlib-1.2.11-2.ph5.x86_64
     zstd-1.4.5-2.ph5.x86_64
     zstd-libs-1.4.5-2.ph5.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-7c2d910d79e9 [ ~ ]# rpm -ql  rpm-ostree
    /etc/rpm-ostreed.conf
    /usr/bin/rpm-ostree
    /usr/bin/rpm-ostree-host
    /usr/bin/rpm-ostree-host/function.inc
    /usr/bin/rpm-ostree-host/mk-ostree-host.sh
    /usr/bin/rpm-ostree-server
    /usr/bin/rpm-ostree-server/mkostreerepo
    /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/libdnf.so.2
    /usr/lib/rpm-ostree/rpm-ostree-0-integration.conf
    /usr/lib/systemd/system/rpm-ostree-bootstatus.service
    /usr/lib/systemd/system/rpm-ostreed-automatic.service
    /usr/lib/systemd/system/rpm-ostreed-automatic.timer
    /usr/lib/systemd/system/rpm-ostreed.service
    /usr/libexec/rpm-ostreed
    /usr/share/bash-completion/completions/rpm-ostree
    /usr/share/dbus-1/interfaces/org.projectatomic.rpmostree1.xml
    /usr/share/dbus-1/system-services/org.projectatomic.rpmostree1.service
    /usr/share/dbus-1/system.d/org.projectatomic.rpmostree1.conf
    /usr/share/man/man1/rpm-ostree.1.gz
    /usr/share/man/man5/rpm-ostreed.conf.5.gz
    /usr/share/man/man8/rpm-ostreed-automatic.service.8.gz
    /usr/share/man/man8/rpm-ostreed-automatic.timer.8.gz
    /usr/share/polkit-1/actions/org.projectatomic.rpmostree1.policy

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.

13.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/5.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/5.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-7c2d910d79e9 [ ~ ]# rpm-ostree upgrade --allow-downgrade
⠂ Receiving metadata objects: 0/(estimating) -/s 0 bytes... 
Receiving metadata objects: 0/(estimating) -/s 0 bytes... done
Staging deployment... done
Downgraded:
  audit 2.8.5-6.ph5 -> 2.8.5-3.ph5
  cloud-init 20.4.1-1.ph5 -> 20.3-2.ph5
  cpio 2.13-3.ph5 -> 2.13-1.ph5
  curl 7.74.0-1.ph5 -> 7.72.0-2.ph5
  curl-libs 7.74.0-1.ph5 -> 7.72.0-2.ph5
  cyrus-sasl 2.1.27-4.ph5 -> 2.1.27-3.ph5
  dhcp-client 4.4.2-2.ph5 -> 4.4.2-1.ph5
  dhcp-libs 4.4.2-2.ph5 -> 4.4.2-1.ph5
  dracut 050-7.ph5 -> 050-5.ph5
  dracut-tools 050-7.ph5 -> 050-5.ph5
  file 5.39-2.ph5 -> 5.39-1.ph5
  file-libs 5.39-2.ph5 -> 5.39-1.ph5
  gdbm 1.19-1.ph5 -> 1.18.1-1.ph5
  glibc 2.32-2.ph5 -> 2.32-1.ph5
  glibc-iconv 2.32-2.ph5 -> 2.32-1.ph5
  gobject-introspection 1.66.0-3.ph5 -> 1.66.0-1.ph5
  grub2-theme 5.0-2.ph5 -> 5.0-1.ph5
  grub2-theme-ostree 5.0-2.ph5 -> 5.0-1.ph5
  iproute2 5.10.0-1.ph5 -> 5.8.0-1.ph5
  iptables 1.8.7-1.ph5 -> 1.8.4-1.ph5
  json-c 0.15-3.ph5 -> 0.15-2.ph5
  libgcc 10.2.0-1.ph5 -> 8.4.0-1.ph5
  libmetalink 0.1.3-3.ph5 -> 0.1.3-2.ph5
  libmodulemd 2.11.0-1.ph5 -> 2.9.4-1.ph5
  librepo 1.12.1-4.ph5 -> 1.12.1-3.ph5
  libsepol 3.1-2.ph5 -> 3.1-1.ph5
  libsolv 0.6.35-7.ph5 -> 0.6.35-5.ph5
  libssh2 1.9.0-3.ph5 -> 1.9.0-2.ph5
  libstdc++ 10.2.0-1.ph5 -> 8.4.0-1.ph5
  libxml2 2.9.10-6.ph5 -> 2.9.10-3.ph5
  libxml2-devel 2.9.10-6.ph5 -> 2.9.10-3.ph5
  libxslt 1.1.34-2.ph5 -> 1.1.34-1.ph5
  linux 5.10.4-15.ph5 -> 5.9.0-3.ph5
  ncurses 6.2-3.ph5 -> 6.2-2.ph5
  ncurses-libs 6.2-3.ph5 -> 6.2-2.ph5
  ncurses-terminfo 6.2-3.ph5 -> 6.2-2.ph5
  nss 3.57-2.ph5 -> 3.57-1.ph5
  nss-libs 3.57-2.ph5 -> 3.57-1.ph5
  open-vm-tools 11.2.5-1.ph5 -> 11.1.5-4.ph5
  openldap 2.4.53-3.ph5 -> 2.4.53-2.ph5
  openssl 1.1.1i-2.ph5 -> 1.1.1g-3.ph5
  pcre 8.44-2.ph5 -> 8.44-1.ph5
  pcre-libs 8.44-2.ph5 -> 8.44-1.ph5
  python3 3.9.1-2.ph5 -> 3.8.6-1.ph5
  python3-PyYAML 5.4.1-1.ph5 -> 5.3.1-1.ph5
  python3-attrs 20.3.0-2.ph5 -> 20.2.0-2.ph5
  python3-cryptography 3.2.1-1.ph5 -> 3.1.1-2.ph5
  python3-gobject-introspection 1.66.0-3.ph5 -> 1.66.0-1.ph5
  python3-libs 3.9.1-2.ph5 -> 3.8.6-1.ph5
  python3-packaging 20.4-3.ph5 -> 20.4-2.ph5
  python3-pyrsistent 0.17.3-2.ph5 -> 0.17.3-1.ph5
  python3-setuptools 3.9.1-2.ph5 -> 3.8.6-1.ph5
  python3-urllib3 1.25.11-1.ph5 -> 1.25.10-2.ph5
  python3-xml 3.9.1-2.ph5 -> 3.8.6-1.ph5
  rpm 4.16.1.2-1.ph5 -> 4.14.2-11.ph5
  rpm-libs 4.16.1.2-1.ph5 -> 4.14.2-11.ph5
  rpm-ostree 2020.5-5.ph5 -> 2020.5-4.ph5
  shadow 4.8.1-3.ph5 -> 4.8.1-2.ph5
  shadow-tools 4.8.1-3.ph5 -> 4.8.1-2.ph5
  sudo 1.9.5-1.ph5 -> 1.8.30-2.ph5
  systemd 247.3-1.ph5 -> 245.5-3.ph5
  util-linux 2.36-2.ph5 -> 2.36-1.ph5
  util-linux-libs 2.36-2.ph5 -> 2.36-1.ph5
Removed:
  libpcap-1.10.0-1.ph5.x86_64
  python3-Pygments-2.7.2-2.ph5.noarch
  python3-alabaster-0.7.12-1.ph5.noarch
  python3-babel-2.8.0-3.ph5.noarch
  python3-docutils-0.16-1.ph5.noarch
  python3-imagesize-1.2.0-2.ph5.noarch
  python3-pytz-2020.4-2.ph5.noarch
  python3-snowballstemmer-2.0.0-1.ph5.noarch
  python3-sphinx-3.3.0-2.ph5.noarch
  python3-sphinxcontrib-applehelp-1.0.2-1.ph5.noarch
  python3-sphinxcontrib-devhelp-1.0.2-1.ph5.noarch
  python3-sphinxcontrib-htmlhelp-1.0.3-1.ph5.noarch
  python3-sphinxcontrib-jsmath-1.0.1-1.ph5.noarch
  python3-sphinxcontrib-qthelp-1.0.3-1.ph5.noarch
  python3-sphinxcontrib-serializinghtml-1.1.4-1.ph5.noarch
  python3-typing-3.7.4.3-1.ph5.noarch
  systemd-libs-247.3-1.ph5.x86_64
  systemd-pam-247.3-1.ph5.x86_64
  systemd-rpm-macros-247.3-1.ph5.noarch
  systemd-udev-247.3-1.ph5.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-7c2d910d79e9 [ ~ ]# ostree log photon/5.0/x86_64/minimal
commit 820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88
ContentChecksum:  c7956cedc5c1b8c07a06e10789c17364a5b7a4b970daab64f3398b7c42bd97d9
Date:  2020-11-04 02:21:47 +0000
Version: 5.0_minimal
(no subject)

Notice that now we have a new reference, that corresponds to the newly deployed image.

root@photon-7c2d910d79e9 [ ~ ]# ostree refs
ostree/0/1/1
photon:photon/5.0/x86_64/minimal
ostree/0/1/0

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-7c2d910d79e9 [ ~ ]# rpm-ostree status
State: idle
Deployments:
  ostree://photon:photon/5.0/x86_64/minimal
    Version: 5.0_minimal (2020-11-04T02:21:47Z)
Commit: 820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88
  Diff: 63 downgraded, 20 removed

● ostree://photon:photon/5.0/x86_64/minimal
    Version: 5.0_minimal (2021-02-20T07:15:43Z)
Commit: 965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f

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.

Grub-dual-boot-1-0

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-7c2d910d79e9 [ ~ ]# rpm-ostree status
State: idle
Deployments:
● ostree://photon:photon/5.0/x86_64/minimal
    Version: 5.0_minimal (2020-11-04T02:21:47Z)
Commit: 820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88
  Diff: 63 downgraded, 20 removed

  ostree://photon:photon/5.0/x86_64/minimal
    Version: 5.0_minimal (2021-02-20T07:15:43Z)
Commit: 965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f

Also, the current deployment directory is based on the new commit:

root@photon-7c2d910d79e9 [ ~ ]# ostree admin config-diff --print-current-dir
/ostree/deploy/photon/deploy/820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88.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-7c2d910d79e9 [ ~ ]# ostree diff 820b 965c
M    /usr/bin/VGAuthService
M    /usr/bin/[
M    /usr/bin/asn1Coding
M    /usr/bin/asn1Decoding
M    /usr/bin/asn1Parser
M    /usr/bin/attr
M    /usr/bin/aulast
M    /usr/bin/aulastlog
M    /usr/bin/ausyscall
M    /usr/bin/auvirt
M    /usr/bin/b2sum
M    /usr/bin/base32
M    /usr/bin/base64
M    /usr/bin/basename
M    /usr/bin/basenc
M    /usr/bin/bash
M    /usr/bin/bc
M    /usr/bin/bootctl
M    /usr/bin/bsdcat
M    /usr/bin/bsdcpio
M    /usr/bin/bsdtar
M    /usr/bin/busctl
M    /usr/bin/bwrap
M    /usr/bin/bzip2
M    /usr/bin/bzip2recover
M    /usr/bin/cal
M    /usr/bin/captest
M    /usr/bin/cat
M    /usr/bin/certtool
M    /usr/bin/certutil
M    /usr/bin/chage
M    /usr/bin/chattr
M    /usr/bin/chcon
M    /usr/bin/chfn
M    /usr/bin/chgrp
M    /usr/bin/chmem
M    /usr/bin/chmod
M    /usr/bin/choom
M    /usr/bin/chown
M    /usr/bin/chrt
M    /usr/bin/chsh
M    /usr/bin/cksum
M    /usr/bin/clear
M    /usr/bin/cloud-id
M    /usr/bin/cloud-init
M    /usr/bin/col
M    /usr/bin/colcrt
M    /usr/bin/colrm
M    /usr/bin/column
M    /usr/bin/comm
M    /usr/bin/coredumpctl
M    /usr/bin/cp
M    /usr/bin/cpio
M    /usr/bin/csplit
M    /usr/bin/curl
M    /usr/bin/curl-config
M    /usr/bin/cut
M    /usr/bin/cvtsudoers
M    /usr/bin/date
M    /usr/bin/dbus-cleanup-sockets
M    /usr/bin/dbus-daemon
M    /usr/bin/dbus-launch
M    /usr/bin/dbus-monitor
M    /usr/bin/dbus-run-session
M    /usr/bin/dbus-send
M    /usr/bin/dbus-test-tool
M    /usr/bin/dbus-update-activation-environment
M    /usr/bin/dbus-uuidgen
M    /usr/bin/dc
M    /usr/bin/dd
M    /usr/bin/debuginfod
M    /usr/bin/debuginfod-find
M    /usr/bin/deltainfoxml2solv
M    /usr/bin/derb
M    /usr/bin/df
M    /usr/bin/dir
M    /usr/bin/dircolors
M    /usr/bin/dirmngr
M    /usr/bin/dirmngr-client
M    /usr/bin/dirname
M    /usr/bin/dmesg
M    /usr/bin/du
M    /usr/bin/dumpsexp
M    /usr/bin/dumpsolv
M    /usr/bin/echo
M    /usr/bin/eject
M    /usr/bin/env
M    /usr/bin/eu-addr2line
M    /usr/bin/eu-ar
M    /usr/bin/eu-elfclassify
M    /usr/bin/eu-elfcmp
M    /usr/bin/eu-elfcompress
M    /usr/bin/eu-elflint
M    /usr/bin/eu-findtextrel
M    /usr/bin/eu-nm
M    /usr/bin/eu-objdump
M    /usr/bin/eu-ranlib
M    /usr/bin/eu-readelf
M    /usr/bin/eu-size
M    /usr/bin/eu-stack
M    /usr/bin/eu-strings
M    /usr/bin/eu-strip
M    /usr/bin/eu-unstrip
M    /usr/bin/expand
M    /usr/bin/expiry
M    /usr/bin/expr
M    /usr/bin/factor
M    /usr/bin/faillog
M    /usr/bin/fallocate
M    /usr/bin/false
M    /usr/bin/file
M    /usr/bin/filecap
M    /usr/bin/fincore
M    /usr/bin/find
M    /usr/bin/findmnt
M    /usr/bin/finger
M    /usr/bin/flex
M    /usr/bin/flock
M    /usr/bin/fmt
M    /usr/bin/fold
M    /usr/bin/free
M    /usr/bin/fusermount
M    /usr/bin/gawk
M    /usr/bin/gawk-5.1.0
M    /usr/bin/gdbm_dump
M    /usr/bin/gdbm_load
M    /usr/bin/gdbmtool
M    /usr/bin/genbrk
M    /usr/bin/gencat
M    /usr/bin/gencfu
M    /usr/bin/gencnval
M    /usr/bin/gendict
M    /usr/bin/gendiff
M    /usr/bin/genrb
M    /usr/bin/getconf
M    /usr/bin/getent
M    /usr/bin/getfattr
M    /usr/bin/getopt
M    /usr/bin/gnutls-cli
M    /usr/bin/gnutls-cli-debug
M    /usr/bin/gnutls-serv
M    /usr/bin/gpasswd
M    /usr/bin/gpg
M    /usr/bin/gpg-agent
M    /usr/bin/gpg-connect-agent
M    /usr/bin/gpg-error
M    /usr/bin/gpg-wks-server
M    /usr/bin/gpgconf
M    /usr/bin/gpgparsemail
M    /usr/bin/gpgscm
M    /usr/bin/gpgsm
M    /usr/bin/gpgsplit
M    /usr/bin/gpgtar
M    /usr/bin/gpgv
M    /usr/bin/grep
M    /usr/bin/groups
M    /usr/bin/grub2-editenv
M    /usr/bin/grub2-file
M    /usr/bin/grub2-fstest
M    /usr/bin/grub2-glue-efi
M    /usr/bin/grub2-menulst2cfg
M    /usr/bin/grub2-mkimage
M    /usr/bin/grub2-mklayout
M    /usr/bin/grub2-mknetdir
M    /usr/bin/grub2-mkpasswd-pbkdf2
M    /usr/bin/grub2-mkrelpath
M    /usr/bin/grub2-mkrescue
M    /usr/bin/grub2-mkstandalone
M    /usr/bin/grub2-render-label
M    /usr/bin/grub2-script-check
M    /usr/bin/grub2-syslinux2cfg
M    /usr/bin/gss-client
M    /usr/bin/guile
M    /usr/bin/gzip
M    /usr/bin/hardlink
M    /usr/bin/head
M    /usr/bin/hexdump
M    /usr/bin/hmac256
M    /usr/bin/hostid
M    /usr/bin/hostname
M    /usr/bin/hostnamectl
M    /usr/bin/iconv
M    /usr/bin/icuinfo
M    /usr/bin/id
M    /usr/bin/infocmp
M    /usr/bin/install
M    /usr/bin/installcheck
M    /usr/bin/ionice
M    /usr/bin/ipcmk
M    /usr/bin/ipcrm
M    /usr/bin/ipcs
M    /usr/bin/irqtop
M    /usr/bin/isosize
M    /usr/bin/join
M    /usr/bin/journalctl
M    /usr/bin/js78
M    /usr/bin/json-glib-format
M    /usr/bin/json-glib-validate
M    /usr/bin/kadmin
M    /usr/bin/kbxutil
M    /usr/bin/kdestroy
M    /usr/bin/kernel-install
M    /usr/bin/kill
M    /usr/bin/kinit
M    /usr/bin/klist
M    /usr/bin/kmod
M    /usr/bin/kpasswd
M    /usr/bin/kswitch
M    /usr/bin/ktutil
M    /usr/bin/kvno
M    /usr/bin/last
M    /usr/bin/lastlog
M    /usr/bin/ldapcompare
M    /usr/bin/ldapdelete
M    /usr/bin/ldapexop
M    /usr/bin/ldapmodify
M    /usr/bin/ldapmodrdn
M    /usr/bin/ldappasswd
M    /usr/bin/ldapsearch
M    /usr/bin/ldapurl
M    /usr/bin/ldapwhoami
M    /usr/bin/libtool
M    /usr/bin/link
M    /usr/bin/ln
M    /usr/bin/locale
M    /usr/bin/localectl
M    /usr/bin/localedef
M    /usr/bin/locate
M    /usr/bin/logger
M    /usr/bin/login
M    /usr/bin/loginctl
M    /usr/bin/logname
M    /usr/bin/look
M    /usr/bin/ls
M    /usr/bin/lsattr
M    /usr/bin/lsblk
M    /usr/bin/lscpu
M    /usr/bin/lsipc
M    /usr/bin/lsirq
M    /usr/bin/lslocks
M    /usr/bin/lslogins
M    /usr/bin/lsmem
M    /usr/bin/lsns
M    /usr/bin/lua
M    /usr/bin/luac
M    /usr/bin/lz4
M    /usr/bin/lzmadec
M    /usr/bin/lzmainfo
M    /usr/bin/m4
M    /usr/bin/makeconv
M    /usr/bin/makedb
M    /usr/bin/mcookie
M    /usr/bin/md5sum
M    /usr/bin/mergesolv
M    /usr/bin/mesg
M    /usr/bin/mkdir
M    /usr/bin/mkfifo
M    /usr/bin/mkinitrd
M    /usr/bin/mknod
M    /usr/bin/mktemp
M    /usr/bin/modulemd-validator
M    /usr/bin/more
M    /usr/bin/mount
M    /usr/bin/mountpoint
M    /usr/bin/mpicalc
M    /usr/bin/mt
M    /usr/bin/mv
M    /usr/bin/namei
M    /usr/bin/netcap
M    /usr/bin/netstat
M    /usr/bin/nettle-hash
M    /usr/bin/nettle-lfib-stream
M    /usr/bin/nettle-pbkdf2
M    /usr/bin/networkctl
M    /usr/bin/newgidmap
M    /usr/bin/newgrp
M    /usr/bin/newrole
M    /usr/bin/newuidmap
M    /usr/bin/nice
M    /usr/bin/nl
M    /usr/bin/nohup
M    /usr/bin/nproc
M    /usr/bin/nsenter
M    /usr/bin/numfmt
M    /usr/bin/ocsptool
M    /usr/bin/od
M    /usr/bin/openssl
M    /usr/bin/ostree
M    /usr/bin/passwd
M    /usr/bin/paste
M    /usr/bin/pathchk
M    /usr/bin/pcregrep
M    /usr/bin/pcretest
M    /usr/bin/pgrep
M    /usr/bin/pidof
M    /usr/bin/pinentry-curses
M    /usr/bin/pinentry-tty
M    /usr/bin/ping
M    /usr/bin/pinky
M    /usr/bin/pk-example-frobnicate
M    /usr/bin/pk12util
M    /usr/bin/pkaction
M    /usr/bin/pkcheck
M    /usr/bin/pkcs1-conv
M    /usr/bin/pkexec
M    /usr/bin/pkg-config
M    /usr/bin/pkgdata
M    /usr/bin/pkill
M    /usr/bin/pkttyagent
M    /usr/bin/pmap
M    /usr/bin/portablectl
M    /usr/bin/pr
M    /usr/bin/printenv
M    /usr/bin/printf
M    /usr/bin/prlimit
M    /usr/bin/ps
M    /usr/bin/pscap
M    /usr/bin/psktool
M    /usr/bin/ptx
M    /usr/bin/pwd
M    /usr/bin/pwdx
M    /usr/bin/pwmake
M    /usr/bin/pwscore
M    /usr/bin/pydoc3
M    /usr/bin/python3
M    /usr/bin/readlink
M    /usr/bin/realpath
M    /usr/bin/rename
M    /usr/bin/renice
M    /usr/bin/repo2solv
M    /usr/bin/repomdxml2solv
M    /usr/bin/resolvectl
M    /usr/bin/rev
M    /usr/bin/rm
M    /usr/bin/rmdir
M    /usr/bin/rofiles-fuse
M    /usr/bin/rpcgen
M    /usr/bin/rpm
M    /usr/bin/rpm-ostree
M    /usr/bin/rpm2archive
M    /usr/bin/rpm2cpio
M    /usr/bin/rpmdb
M    /usr/bin/rpmdb2solv
M    /usr/bin/rpmgraph
M    /usr/bin/rpmkeys
M    /usr/bin/rpmmd2solv
M    /usr/bin/rpms2solv
M    /usr/bin/runcon
M    /usr/bin/sclient
M    /usr/bin/scp
M    /usr/bin/script
M    /usr/bin/scriptlive
M    /usr/bin/scriptreplay
M    /usr/bin/secon
M    /usr/bin/sed
M    /usr/bin/seq
M    /usr/bin/setarch
M    /usr/bin/setfattr
M    /usr/bin/setsid
M    /usr/bin/setterm
M    /usr/bin/sexp-conv
M    /usr/bin/sftp
M    /usr/bin/sha1sum
M    /usr/bin/sha224sum
M    /usr/bin/sha256sum
M    /usr/bin/sha384sum
M    /usr/bin/sha512sum
M    /usr/bin/shred
M    /usr/bin/shuf
M    /usr/bin/sim_client
M    /usr/bin/slabtop
M    /usr/bin/sleep
M    /usr/bin/sort
M    /usr/bin/split
M    /usr/bin/srptool
M    /usr/bin/ssh
M    /usr/bin/ssh-add
M    /usr/bin/ssh-agent
M    /usr/bin/ssh-keygen
M    /usr/bin/ssh-keyscan
M    /usr/bin/stat
M    /usr/bin/stdbuf
M    /usr/bin/stty
M    /usr/bin/su
M    /usr/bin/sudo
M    /usr/bin/sudoreplay
M    /usr/bin/sum
M    /usr/bin/sync
M    /usr/bin/systemctl
M    /usr/bin/systemd-analyze
M    /usr/bin/systemd-ask-password
M    /usr/bin/systemd-cat
M    /usr/bin/systemd-cgls
M    /usr/bin/systemd-cgtop
M    /usr/bin/systemd-delta
M    /usr/bin/systemd-detect-virt
M    /usr/bin/systemd-escape
M    /usr/bin/systemd-hwdb
M    /usr/bin/systemd-id128
M    /usr/bin/systemd-inhibit
M    /usr/bin/systemd-machine-id-setup
M    /usr/bin/systemd-mount
M    /usr/bin/systemd-notify
M    /usr/bin/systemd-path
M    /usr/bin/systemd-repart
M    /usr/bin/systemd-run
M    /usr/bin/systemd-socket-activate
M    /usr/bin/systemd-stdio-bridge
M    /usr/bin/systemd-tmpfiles
M    /usr/bin/systemd-tty-ask-password-agent
M    /usr/bin/tabs
M    /usr/bin/tac
M    /usr/bin/tail
M    /usr/bin/taskset
M    /usr/bin/tee
M    /usr/bin/test
M    /usr/bin/testsolv
M    /usr/bin/tic
M    /usr/bin/timedatectl
M    /usr/bin/timeout
M    /usr/bin/tload
M    /usr/bin/toe
M    /usr/bin/top
M    /usr/bin/touch
M    /usr/bin/tput
M    /usr/bin/tr
M    /usr/bin/tracepath
M    /usr/bin/traceroute6
M    /usr/bin/true
M    /usr/bin/truncate
M    /usr/bin/tset
M    /usr/bin/tsort
M    /usr/bin/tty
M    /usr/bin/uconv
M    /usr/bin/udevadm
M    /usr/bin/ul
M    /usr/bin/ulockmgr_server
M    /usr/bin/umount
M    /usr/bin/uname
M    /usr/bin/unexpand
M    /usr/bin/uniq
M    /usr/bin/unlink
M    /usr/bin/unshare
M    /usr/bin/unzck
M    /usr/bin/updateinfoxml2solv
M    /usr/bin/uptime
M    /usr/bin/userdbctl
M    /usr/bin/users
M    /usr/bin/utmpdump
M    /usr/bin/uuclient
M    /usr/bin/uuidgen
M    /usr/bin/uuidparse
M    /usr/bin/vdir
M    /usr/bin/vim
M    /usr/bin/vmhgfs-fuse
M    /usr/bin/vmstat
M    /usr/bin/vmtoolsd
M    /usr/bin/vmware-checkvm
M    /usr/bin/vmware-hgfsclient
M    /usr/bin/vmware-namespace-cmd
M    /usr/bin/vmware-rpctool
M    /usr/bin/vmware-toolbox-cmd
M    /usr/bin/vmware-vgauth-cmd
M    /usr/bin/vmware-vgauth-smoketest
M    /usr/bin/vmware-vmblock-fuse
M    /usr/bin/vmware-xferlogs
M    /usr/bin/w
M    /usr/bin/wall
M    /usr/bin/watch
M    /usr/bin/watchgnupg
M    /usr/bin/wc
M    /usr/bin/wdctl
M    /usr/bin/whereis
M    /usr/bin/which
M    /usr/bin/who
M    /usr/bin/whoami
M    /usr/bin/xargs
M    /usr/bin/xmlcatalog
M    /usr/bin/xmllint
M    /usr/bin/xmlsec1
M    /usr/bin/xmlwf
M    /usr/bin/xsltproc
M    /usr/bin/xz
M    /usr/bin/xzdec
M    /usr/bin/yat2m
M    /usr/bin/yes
M    /usr/bin/zck
M    /usr/bin/zck_delta_size
M    /usr/bin/zck_gen_zdict
M    /usr/bin/zck_read_header
M    /usr/bin/zckdl
M    /usr/bin/zstd
M    /usr/bin/rpm-ostree-server/mkostreerepo
M    /usr/etc/ld.so.cache
M    /usr/etc/photon-release
M    /usr/etc/shadow
M    /usr/etc/sudoers
M    /usr/etc/cloud/cloud.cfg
M    /usr/etc/iproute2/rt_protos
M    /usr/etc/pam.d/vmtoolsd
M    /usr/etc/systemd/journald.conf
M    /usr/etc/systemd/logind.conf
M    /usr/etc/systemd/networkd.conf
M    /usr/etc/systemd/resolved.conf
M    /usr/etc/systemd/system.conf
M    /usr/etc/systemd/user.conf
M    /usr/etc/udev/hwdb.bin
M    /usr/etc/udev/udev.conf
M    /usr/etc/udev/rules.d/99-vmware-hotplug.rules
M    /usr/etc/vmware-tools/tools.conf.example
M    /usr/etc/vmware-tools/vgauth.conf
M    /usr/include/sudo_plugin.h
M    /usr/lib/e2initrd_helper
M    /usr/lib/ld-2.32.so
M    /usr/lib/libBrokenLocale-2.32.so
M    /usr/lib/libDeployPkg.so.0.0.0
M    /usr/lib/libSegFault.so
M    /usr/lib/libacl.so.1.1.2253
M    /usr/lib/libanl-2.32.so
M    /usr/lib/libarchive.so.13.4.3
M    /usr/lib/libasm-0.181.so
M    /usr/lib/libassuan.so.0.8.3
M    /usr/lib/libattr.so.1.1.2448
M    /usr/lib/libaudit.so.1.0.0
M    /usr/lib/libauparse.so.0.0.0
M    /usr/lib/libblkid.so.1.1.0
M    /usr/lib/libbz2.so.1.0.8
M    /usr/lib/libc-2.32.so
M    /usr/lib/libcap-ng.so.0.0.0
M    /usr/lib/libcap.so.2.43
M    /usr/lib/libcom_err.so.2.1
M    /usr/lib/libcord.so.1.4.0
M    /usr/lib/libcrack.so.2.9.0
M    /usr/lib/libcrypt-2.32.so
M    /usr/lib/libcrypto.so.1.1
M    /usr/lib/libcurl.so.4
M    /usr/lib/libdb-5.3.so
M    /usr/lib/libdbus-1.so.3.29.0
M    /usr/lib/libdebuginfod-0.181.so
M    /usr/lib/libdevmapper.so.1.02
M    /usr/lib/libdhcp.a
M    /usr/lib/libdhcpctl.a
M    /usr/lib/libdl-2.32.so
M    /usr/lib/libdnet.1.0.1
M    /usr/lib/libdw-0.181.so
M    /usr/lib/libe2p.so.2.3
M    /usr/lib/libelf-0.181.so
M    /usr/lib/libexpat.so.1.6.11
M    /usr/lib/libexslt.so.0.8.20
M    /usr/lib/libext2fs.so.2.4
M    /usr/lib/libfdisk.so.1.1.0
M    /usr/lib/libffi.so.7.1.0
M    /usr/lib/libfl.so.2.0.0
M    /usr/lib/libformw.so.6.2
M    /usr/lib/libfreebl3.chk
M    /usr/lib/libfreebl3.so
M    /usr/lib/libfreeblpriv3.chk
M    /usr/lib/libfreeblpriv3.so
M    /usr/lib/libfuse.so.2.9.9
M    /usr/lib/libgc.so.1.4.3
M    /usr/lib/libgcc_s.so.1
M    /usr/lib/libgccpp.so.1.4.0
M    /usr/lib/libgcrypt.so.20.2.6
M    /usr/lib/libgdbm.so.6.0.0
M    /usr/lib/libgdbm_compat.so.4.0.0
M    /usr/lib/libgio-2.0.so.0.6600.1
M    /usr/lib/libgirepository-1.0.so.1.0.0
M    /usr/lib/libglib-2.0.so.0.6600.1
M    /usr/lib/libgmodule-2.0.so.0.6600.1
M    /usr/lib/libgmp.so.10.4.0
M    /usr/lib/libgnutls.so.30.28.1
M    /usr/lib/libgnutlsxx.so.28.1.0
M    /usr/lib/libgobject-2.0.so.0.6600.1
M    /usr/lib/libgpg-error.so.0.30.0
M    /usr/lib/libgpgme.so.11.23.0
M    /usr/lib/libgssapi_krb5.so.2.2
M    /usr/lib/libgssrpc.so.4.2
M    /usr/lib/libgthread-2.0.so.0.6600.1
M    /usr/lib/libguestlib.so.0.0.0
M    /usr/lib/libguile-2.0.so.22.8.1
M    /usr/lib/libguilereadline-v-18.so.18.0.0
M    /usr/lib/libhgfs.so.0.0.0
M    /usr/lib/libhistory.so.7.0
M    /usr/lib/libhogweed.so.6.0
M    /usr/lib/libicui18n.so.67.1
M    /usr/lib/libicuio.so.67.1
M    /usr/lib/libicutest.so.67.1
M    /usr/lib/libicutu.so.67.1
M    /usr/lib/libicuuc.so.67.1
M    /usr/lib/libip4tc.so.2.0.0
M    /usr/lib/libip6tc.so.2.0.0
M    /usr/lib/libipq.so.0.0.0
M    /usr/lib/libjson-c.so.5.1.0
M    /usr/lib/libjson-glib-1.0.so.0.600.0
M    /usr/lib/libk5crypto.so.3.1
M    /usr/lib/libkadm5clnt_mit.so.11.0
M    /usr/lib/libkadm5srv_mit.so.11.0
M    /usr/lib/libkdb5.so.9.0
M    /usr/lib/libkmod.so.2.3.5
M    /usr/lib/libkrad.so.0.0
M    /usr/lib/libkrb5.so.3.3
M    /usr/lib/libkrb5support.so.0.1
M    /usr/lib/libksba.so.8.12.0
M    /usr/lib/liblber-2.4.so.2.11.1
M    /usr/lib/libldap-2.4.so.2.11.1
M    /usr/lib/libldap_r-2.4.so.2.11.1
M    /usr/lib/libltdl.so.7.3.1
M    /usr/lib/liblua.so.5.3.4
M    /usr/lib/liblz4.so.1.9.2
M    /usr/lib/liblzma.so.5.2.5
M    /usr/lib/libm-2.32.so
M    /usr/lib/libmagic.so.1.0.0
M    /usr/lib/libmemusage.so
M    /usr/lib/libmenuw.so.6.2
M    /usr/lib/libmetalink.so.3.1.0
M    /usr/lib/libmicrohttpd.so.12.56.0
M    /usr/lib/libmodulemd.so.2
M    /usr/lib/libmount.so.1.1.0
M    /usr/lib/libmozjs-78.so
M    /usr/lib/libmpfr.so.6.1.0
M    /usr/lib/libmspack.so.0.1.0
M    /usr/lib/libmvec-2.32.so
M    /usr/lib/libncursesw.so.6.2
M    /usr/lib/libnettle.so.8.0
M    /usr/lib/libnpth.so.0.1.2
M    /usr/lib/libnsl-2.32.so
M    /usr/lib/libnsl.so.2.0.1
M    /usr/lib/libnspr4.so
M    /usr/lib/libnss3.so
M    /usr/lib/libnss_altfiles.so.2
M    /usr/lib/libnss_compat-2.32.so
M    /usr/lib/libnss_db-2.32.so
M    /usr/lib/libnss_dns-2.32.so
M    /usr/lib/libnss_files-2.32.so
M    /usr/lib/libnss_hesiod-2.32.so
M    /usr/lib/libnss_myhostname.so.2
M    /usr/lib/libnss_mymachines.so.2
M    /usr/lib/libnss_resolve.so.2
M    /usr/lib/libnss_systemd.so.2
M    /usr/lib/libnssckbi-testlib.so
M    /usr/lib/libnssckbi.so
M    /usr/lib/libnssdbm3.chk
M    /usr/lib/libnssdbm3.so
M    /usr/lib/libnsssysinit.so
M    /usr/lib/libnssutil3.so
M    /usr/lib/libomapi.a
M    /usr/lib/libopts.so.25.17.1
M    /usr/lib/libostree-1.so.1.0.0
M    /usr/lib/libpam.so.0.85.1
M    /usr/lib/libpam_misc.so.0.82.1
M    /usr/lib/libpamc.so.0.82.1
M    /usr/lib/libpanelw.so.6.2
M    /usr/lib/libpcre.so.1.2.12
M    /usr/lib/libpcre16.so.0.2.12
M    /usr/lib/libpcre32.so.0.0.12
M    /usr/lib/libpcrecpp.so.0.0.2
M    /usr/lib/libpcreposix.so.0.0.7
M    /usr/lib/libpkcs11testmodule.so
M    /usr/lib/libplc4.so
M    /usr/lib/libplds4.so
M    /usr/lib/libpolkit-agent-1.so.0.0.0
M    /usr/lib/libpolkit-gobject-1.so.0.0.0
M    /usr/lib/libpopt.so.0.0.0
M    /usr/lib/libprocps.so.8.0.2
M    /usr/lib/libpsl.so.5.3.3
M    /usr/lib/libpthread-2.32.so
M    /usr/lib/libpwquality.so.1.0.2
M    /usr/lib/libpython3.so
M    /usr/lib/libreadline.so.7.0
M    /usr/lib/librepo.so.0
M    /usr/lib/libresolv-2.32.so
M    /usr/lib/librpmostree-1.so.1.0.0
M    /usr/lib/librt-2.32.so
M    /usr/lib/libsasl2.so.3.0.0
M    /usr/lib/libseccomp.so.2.5.0
M    /usr/lib/libselinux.so.1
M    /usr/lib/libsemanage.so.1
M    /usr/lib/libsepol.so.1
M    /usr/lib/libsmartcols.so.1.1.0
M    /usr/lib/libsmime3.so
M    /usr/lib/libsoftokn3.chk
M    /usr/lib/libsoftokn3.so
M    /usr/lib/libsolv.so.0
M    /usr/lib/libsolvext.so.0
M    /usr/lib/libsoup-2.4.so.1.11.0
M    /usr/lib/libsoup-gnome-2.4.so.1.11.0
M    /usr/lib/libsqlite3.so.0.8.6
M    /usr/lib/libss.so.2.0
M    /usr/lib/libssh2.so.1.0.1
M    /usr/lib/libssl.so.1.1
M    /usr/lib/libssl3.so
M    /usr/lib/libstdc++.so.6
M    /usr/lib/libsystemd.so.0
M    /usr/lib/libtasn1.so.6.5.6
M    /usr/lib/libthread_db-1.0.so
M    /usr/lib/libtirpc.so.3.0.0
M    /usr/lib/libudev.so.1
M    /usr/lib/libulockmgr.so.1.0.1
M    /usr/lib/libunistring.a
M    /usr/lib/libunistring.so.2.1.0
M    /usr/lib/libutil-2.32.so
M    /usr/lib/libuuid.so.1.3.0
M    /usr/lib/libverto.so.0.0
M    /usr/lib/libvgauth.so.0.0.0
M    /usr/lib/libvmtools.so.0.0.0
M    /usr/lib/libwrap.a
M    /usr/lib/libwrap.so.0.7.6
M    /usr/lib/libxml2.so.2.9.10
M    /usr/lib/libxmlsec1-nss.so.1.2.30
M    /usr/lib/libxmlsec1-openssl.so.1.2.30
M    /usr/lib/libxmlsec1.so.1.2.30
M    /usr/lib/libxslt.so.1.1.34
M    /usr/lib/libxtables.so.12
M    /usr/lib/libyaml-0.so.2.0.9
M    /usr/lib/libz.so.1.2.11
M    /usr/lib/libzck.so.1.1.7
M    /usr/lib/libzstd.so.1.4.5
M    /usr/lib/bash/basename
M    /usr/lib/bash/dirname
M    /usr/lib/bash/fdflags
M    /usr/lib/bash/finfo
M    /usr/lib/bash/head
M    /usr/lib/bash/id
M    /usr/lib/bash/ln
M    /usr/lib/bash/logname
M    /usr/lib/bash/mkdir
M    /usr/lib/bash/mypid
M    /usr/lib/bash/pathchk
M    /usr/lib/bash/print
M    /usr/lib/bash/printenv
M    /usr/lib/bash/push
M    /usr/lib/bash/realpath
M    /usr/lib/bash/rmdir
M    /usr/lib/bash/seq
M    /usr/lib/bash/setpgid
M    /usr/lib/bash/sleep
M    /usr/lib/bash/strftime
M    /usr/lib/bash/sync
M    /usr/lib/bash/tee
M    /usr/lib/bash/truefalse
M    /usr/lib/bash/tty
M    /usr/lib/bash/uname
M    /usr/lib/bash/unlink
M    /usr/lib/bash/whoami
M    /usr/lib/cloud-init/ds-identify
M    /usr/lib/dracut/dracut-install
M    /usr/lib/dracut/dracut-version.sh
M    /usr/lib/dracut/skipcpio
M    /usr/lib/engines-1.1/afalg.so
M    /usr/lib/engines-1.1/capi.so
M    /usr/lib/engines-1.1/padlock.so
M    /usr/lib/gawk/filefuncs.so
M    /usr/lib/gawk/fnmatch.so
M    /usr/lib/gawk/fork.so
M    /usr/lib/gawk/inplace.so
M    /usr/lib/gawk/intdiv.so
M    /usr/lib/gawk/ordchr.so
M    /usr/lib/gawk/readdir.so
M    /usr/lib/gawk/readfile.so
M    /usr/lib/gawk/revoutput.so
M    /usr/lib/gawk/revtwoway.so
M    /usr/lib/gawk/rwarray.so
M    /usr/lib/gawk/time.so
M    /usr/lib/gconv/ANSI_X3.110.so
M    /usr/lib/gconv/ARMSCII-8.so
M    /usr/lib/gconv/ASMO_449.so
M    /usr/lib/gconv/BIG5.so
M    /usr/lib/gconv/BIG5HKSCS.so
M    /usr/lib/gconv/BRF.so
M    /usr/lib/gconv/CP10007.so
M    /usr/lib/gconv/CP1125.so
M    /usr/lib/gconv/CP1250.so
M    /usr/lib/gconv/CP1251.so
M    /usr/lib/gconv/CP1252.so
M    /usr/lib/gconv/CP1253.so
M    /usr/lib/gconv/CP1254.so
M    /usr/lib/gconv/CP1255.so
M    /usr/lib/gconv/CP1256.so
M    /usr/lib/gconv/CP1257.so
M    /usr/lib/gconv/CP1258.so
M    /usr/lib/gconv/CP737.so
M    /usr/lib/gconv/CP770.so
M    /usr/lib/gconv/CP771.so
M    /usr/lib/gconv/CP772.so
M    /usr/lib/gconv/CP773.so
M    /usr/lib/gconv/CP774.so
M    /usr/lib/gconv/CP775.so
M    /usr/lib/gconv/CP932.so
M    /usr/lib/gconv/CSN_369103.so
M    /usr/lib/gconv/CWI.so
M    /usr/lib/gconv/DEC-MCS.so
M    /usr/lib/gconv/EBCDIC-AT-DE-A.so
M    /usr/lib/gconv/EBCDIC-AT-DE.so
M    /usr/lib/gconv/EBCDIC-CA-FR.so
M    /usr/lib/gconv/EBCDIC-DK-NO-A.so
M    /usr/lib/gconv/EBCDIC-DK-NO.so
M    /usr/lib/gconv/EBCDIC-ES-A.so
M    /usr/lib/gconv/EBCDIC-ES-S.so
M    /usr/lib/gconv/EBCDIC-ES.so
M    /usr/lib/gconv/EBCDIC-FI-SE-A.so
M    /usr/lib/gconv/EBCDIC-FI-SE.so
M    /usr/lib/gconv/EBCDIC-FR.so
M    /usr/lib/gconv/EBCDIC-IS-FRISS.so
M    /usr/lib/gconv/EBCDIC-IT.so
M    /usr/lib/gconv/EBCDIC-PT.so
M    /usr/lib/gconv/EBCDIC-UK.so
M    /usr/lib/gconv/EBCDIC-US.so
M    /usr/lib/gconv/ECMA-CYRILLIC.so
M    /usr/lib/gconv/EUC-CN.so
M    /usr/lib/gconv/EUC-JISX0213.so
M    /usr/lib/gconv/EUC-JP-MS.so
M    /usr/lib/gconv/EUC-JP.so
M    /usr/lib/gconv/EUC-KR.so
M    /usr/lib/gconv/EUC-TW.so
M    /usr/lib/gconv/GB18030.so
M    /usr/lib/gconv/GBBIG5.so
M    /usr/lib/gconv/GBGBK.so
M    /usr/lib/gconv/GBK.so
M    /usr/lib/gconv/GEORGIAN-ACADEMY.so
M    /usr/lib/gconv/GEORGIAN-PS.so
M    /usr/lib/gconv/GOST_19768-74.so
M    /usr/lib/gconv/GREEK-CCITT.so
M    /usr/lib/gconv/GREEK7-OLD.so
M    /usr/lib/gconv/GREEK7.so
M    /usr/lib/gconv/HP-GREEK8.so
M    /usr/lib/gconv/HP-ROMAN8.so
M    /usr/lib/gconv/HP-ROMAN9.so
M    /usr/lib/gconv/HP-THAI8.so
M    /usr/lib/gconv/HP-TURKISH8.so
M    /usr/lib/gconv/IBM037.so
M    /usr/lib/gconv/IBM038.so
M    /usr/lib/gconv/IBM1004.so
M    /usr/lib/gconv/IBM1008.so
M    /usr/lib/gconv/IBM1008_420.so
M    /usr/lib/gconv/IBM1025.so
M    /usr/lib/gconv/IBM1026.so
M    /usr/lib/gconv/IBM1046.so
M    /usr/lib/gconv/IBM1047.so
M    /usr/lib/gconv/IBM1097.so
M    /usr/lib/gconv/IBM1112.so
M    /usr/lib/gconv/IBM1122.so
M    /usr/lib/gconv/IBM1123.so
M    /usr/lib/gconv/IBM1124.so
M    /usr/lib/gconv/IBM1129.so
M    /usr/lib/gconv/IBM1130.so
M    /usr/lib/gconv/IBM1132.so
M    /usr/lib/gconv/IBM1133.so
M    /usr/lib/gconv/IBM1137.so
M    /usr/lib/gconv/IBM1140.so
M    /usr/lib/gconv/IBM1141.so
M    /usr/lib/gconv/IBM1142.so
M    /usr/lib/gconv/IBM1143.so
M    /usr/lib/gconv/IBM1144.so
M    /usr/lib/gconv/IBM1145.so
M    /usr/lib/gconv/IBM1146.so
M    /usr/lib/gconv/IBM1147.so
M    /usr/lib/gconv/IBM1148.so
M    /usr/lib/gconv/IBM1149.so
M    /usr/lib/gconv/IBM1153.so
M    /usr/lib/gconv/IBM1154.so
M    /usr/lib/gconv/IBM1155.so
M    /usr/lib/gconv/IBM1156.so
M    /usr/lib/gconv/IBM1157.so
M    /usr/lib/gconv/IBM1158.so
M    /usr/lib/gconv/IBM1160.so
M    /usr/lib/gconv/IBM1161.so
M    /usr/lib/gconv/IBM1162.so
M    /usr/lib/gconv/IBM1163.so
M    /usr/lib/gconv/IBM1164.so
M    /usr/lib/gconv/IBM1166.so
M    /usr/lib/gconv/IBM1167.so
M    /usr/lib/gconv/IBM12712.so
M    /usr/lib/gconv/IBM1364.so
M    /usr/lib/gconv/IBM1371.so
M    /usr/lib/gconv/IBM1388.so
M    /usr/lib/gconv/IBM1390.so
M    /usr/lib/gconv/IBM1399.so
M    /usr/lib/gconv/IBM16804.so
M    /usr/lib/gconv/IBM256.so
M    /usr/lib/gconv/IBM273.so
M    /usr/lib/gconv/IBM274.so
M    /usr/lib/gconv/IBM275.so
M    /usr/lib/gconv/IBM277.so
M    /usr/lib/gconv/IBM278.so
M    /usr/lib/gconv/IBM280.so
M    /usr/lib/gconv/IBM281.so
M    /usr/lib/gconv/IBM284.so
M    /usr/lib/gconv/IBM285.so
M    /usr/lib/gconv/IBM290.so
M    /usr/lib/gconv/IBM297.so
M    /usr/lib/gconv/IBM420.so
M    /usr/lib/gconv/IBM423.so
M    /usr/lib/gconv/IBM424.so
M    /usr/lib/gconv/IBM437.so
M    /usr/lib/gconv/IBM4517.so
M    /usr/lib/gconv/IBM4899.so
M    /usr/lib/gconv/IBM4909.so
M    /usr/lib/gconv/IBM4971.so
M    /usr/lib/gconv/IBM500.so
M    /usr/lib/gconv/IBM5347.so
M    /usr/lib/gconv/IBM803.so
M    /usr/lib/gconv/IBM850.so
M    /usr/lib/gconv/IBM851.so
M    /usr/lib/gconv/IBM852.so
M    /usr/lib/gconv/IBM855.so
M    /usr/lib/gconv/IBM856.so
M    /usr/lib/gconv/IBM857.so
M    /usr/lib/gconv/IBM858.so
M    /usr/lib/gconv/IBM860.so
M    /usr/lib/gconv/IBM861.so
M    /usr/lib/gconv/IBM862.so
M    /usr/lib/gconv/IBM863.so
M    /usr/lib/gconv/IBM864.so
M    /usr/lib/gconv/IBM865.so
M    /usr/lib/gconv/IBM866.so
M    /usr/lib/gconv/IBM866NAV.so
M    /usr/lib/gconv/IBM868.so
M    /usr/lib/gconv/IBM869.so
M    /usr/lib/gconv/IBM870.so
M    /usr/lib/gconv/IBM871.so
M    /usr/lib/gconv/IBM874.so
M    /usr/lib/gconv/IBM875.so
M    /usr/lib/gconv/IBM880.so
M    /usr/lib/gconv/IBM891.so
M    /usr/lib/gconv/IBM901.so
M    /usr/lib/gconv/IBM902.so
M    /usr/lib/gconv/IBM903.so
M    /usr/lib/gconv/IBM9030.so
M    /usr/lib/gconv/IBM904.so
M    /usr/lib/gconv/IBM905.so
M    /usr/lib/gconv/IBM9066.so
M    /usr/lib/gconv/IBM918.so
M    /usr/lib/gconv/IBM921.so
M    /usr/lib/gconv/IBM922.so
M    /usr/lib/gconv/IBM930.so
M    /usr/lib/gconv/IBM932.so
M    /usr/lib/gconv/IBM933.so
M    /usr/lib/gconv/IBM935.so
M    /usr/lib/gconv/IBM937.so
M    /usr/lib/gconv/IBM939.so
M    /usr/lib/gconv/IBM943.so
M    /usr/lib/gconv/IBM9448.so
M    /usr/lib/gconv/IEC_P27-1.so

Listing package differences

We can also look at package differences, as you expect, using the right tool for the job.

root@photon-7c2d910d79e9 [ ~ ]# rpm-ostree db diff 820b 965c
ostree diff commit from: 820b (820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88)
ostree diff commit to:   965c (965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f)
Upgraded:
audit 2.8.5-3.ph5 -> 2.8.5-6.ph5
cloud-init 20.3-2.ph5 -> 20.4.1-1.ph5
cpio 2.13-1.ph5 -> 2.13-3.ph5
curl 7.72.0-2.ph5 -> 7.74.0-1.ph5
curl-libs 7.72.0-2.ph5 -> 7.74.0-1.ph5
cyrus-sasl 2.1.27-3.ph5 -> 2.1.27-4.ph5
dhcp-client 4.4.2-1.ph5 -> 4.4.2-2.ph5
dhcp-libs 4.4.2-1.ph5 -> 4.4.2-2.ph5
dracut 050-5.ph5 -> 050-7.ph5
dracut-tools 050-5.ph5 -> 050-7.ph5
file 5.39-1.ph5 -> 5.39-2.ph5
file-libs 5.39-1.ph5 -> 5.39-2.ph5
gdbm 1.18.1-1.ph5 -> 1.19-1.ph5
glibc 2.32-1.ph5 -> 2.32-2.ph5
glibc-iconv 2.32-1.ph5 -> 2.32-2.ph5
gobject-introspection 1.66.0-1.ph5 -> 1.66.0-3.ph5
grub2-theme 5.0-1.ph5 -> 4.0-2.ph5
grub2-theme-ostree 5.0-1.ph5 -> 5.0-2.ph5
iproute2 5.8.0-1.ph5 -> 5.10.0-1.ph5
iptables 1.8.4-1.ph5 -> 1.8.7-1.ph5
json-c 0.15-2.ph5 -> 0.15-3.ph5
libgcc 8.4.0-1.ph5 -> 10.2.0-1.ph5
libmetalink 0.1.3-2.ph5 -> 0.1.3-3.ph5
libmodulemd 2.9.4-1.ph5 -> 2.11.0-1.ph5
librepo 1.12.1-3.ph5 -> 1.12.1-4.ph5
libsepol 3.1-1.ph5 -> 3.1-2.ph5
libsolv 0.6.35-5.ph5 -> 0.6.35-7.ph5
libssh2 1.9.0-2.ph5 -> 1.9.0-3.ph5
libstdc++ 8.4.0-1.ph5 -> 10.2.0-1.ph5
libxml2 2.9.10-3.ph5 -> 2.9.10-6.ph5
libxml2-devel 2.9.10-3.ph5 -> 2.9.10-6.ph5
libxslt 1.1.34-1.ph5 -> 1.1.34-2.ph5
linux 5.9.0-3.ph5 -> 5.10.4-15.ph5
ncurses 6.2-2.ph5 -> 6.2-3.ph5
ncurses-libs 6.2-2.ph5 -> 6.2-3.ph5
ncurses-terminfo 6.2-2.ph5 -> 6.2-3.ph5
nss 3.57-1.ph5 -> 3.57-2.ph5
nss-libs 3.57-1.ph5 -> 3.57-2.ph5
open-vm-tools 11.1.5-4.ph5 -> 11.2.5-1.ph5
openldap 2.4.53-2.ph5 -> 2.4.53-3.ph5
openssl 1.1.1g-3.ph5 -> 1.1.1i-2.ph5
pcre 8.44-1.ph5 -> 8.44-2.ph5
pcre-libs 8.44-1.ph5 -> 8.44-2.ph5
python3 3.8.6-1.ph5 -> 3.9.1-2.ph5
python3-PyYAML 5.3.1-1.ph5 -> 5.4.1-1.ph5
python3-attrs 20.2.0-2.ph5 -> 20.3.0-2.ph5
python3-cryptography 3.1.1-2.ph5 -> 3.2.1-1.ph5
python3-gobject-introspection 1.66.0-1.ph5 -> 1.66.0-3.ph5
python3-libs 3.8.6-1.ph5 -> 3.9.1-2.ph5
python3-packaging 20.4-2.ph5 -> 20.4-3.ph5
python3-pyrsistent 0.17.3-1.ph5 -> 0.17.3-2.ph5
python3-setuptools 3.8.6-1.ph5 -> 3.9.1-2.ph5
python3-urllib3 1.25.10-2.ph5 -> 1.25.11-1.ph5
python3-xml 3.8.6-1.ph5 -> 3.9.1-2.ph5
rpm 4.14.2-11.ph5 -> 4.16.1.2-1.ph5
rpm-libs 4.14.2-11.ph5 -> 4.16.1.2-1.ph5
rpm-ostree 2020.5-4.ph5 -> 2020.5-5.ph5
shadow 4.8.1-2.ph5 -> 4.8.1-3.ph5
shadow-tools 4.8.1-2.ph5 -> 4.8.1-3.ph5
sudo 1.8.30-2.ph5 -> 1.9.5-1.ph5
systemd 245.5-3.ph5 -> 247.3-1.ph5
util-linux 2.36-1.ph5 -> 2.36-2.ph5
util-linux-libs 2.36-1.ph5 -> 2.36-2.ph5
Added:
libpcap-1.10.0-1.ph5.x86_64
python3-Pygments-2.7.2-2.ph5.noarch
python3-alabaster-0.7.12-1.ph5.noarch
python3-babel-2.8.0-3.ph5.noarch
python3-docutils-0.16-1.ph5.noarch
python3-imagesize-1.2.0-2.ph5.noarch
python3-pytz-2020.4-2.ph5.noarch
python3-snowballstemmer-2.0.0-1.ph5.noarch
python3-sphinx-3.3.0-2.ph5.noarch
python3-sphinxcontrib-applehelp-1.0.2-1.ph5.noarch
python3-sphinxcontrib-devhelp-1.0.2-1.ph5.noarch
python3-sphinxcontrib-htmlhelp-1.0.3-1.ph5.noarch
python3-sphinxcontrib-jsmath-1.0.1-1.ph5.noarch
python3-sphinxcontrib-qthelp-1.0.3-1.ph5.noarch
python3-sphinxcontrib-serializinghtml-1.1.4-1.ph5.noarch
python3-typing-3.7.4.3-1.ph5.noarch
systemd-libs-247.3-1.ph5.x86_64
systemd-pam-247.3-1.ph5.x86_64
systemd-rpm-macros-247.3-1.ph5.noarch
systemd-udev-247.3-1.ph5.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-7c2d910d79e9 [ ~ ]# rpm-ostree rollback
Moving '965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f.0' to be first deployment
Transaction complete; bootconfig swap: yes; deployment count change: 0
Upgraded:
  audit 2.8.5-3.ph5 -> 2.8.5-6.ph5
  cloud-init 20.3-2.ph5 -> 20.4.1-1.ph5
  cpio 2.13-1.ph5 -> 2.13-3.ph5
  curl 7.72.0-2.ph5 -> 7.74.0-1.ph5
  curl-libs 7.72.0-2.ph5 -> 7.74.0-1.ph5
  cyrus-sasl 2.1.27-3.ph5 -> 2.1.27-4.ph5
  dhcp-client 4.4.2-1.ph5 -> 4.4.2-2.ph5
  dhcp-libs 4.4.2-1.ph5 -> 4.4.2-2.ph5
  dracut 050-5.ph5 -> 050-7.ph5
  dracut-tools 050-5.ph5 -> 050-7.ph5
  file 5.39-1.ph5 -> 5.39-2.ph5
  file-libs 5.39-1.ph5 -> 5.39-2.ph5
  gdbm 1.18.1-1.ph5 -> 1.19-1.ph5
  glibc 2.32-1.ph5 -> 2.32-2.ph5
  glibc-iconv 2.32-1.ph5 -> 2.32-2.ph5
  gobject-introspection 1.66.0-1.ph5 -> 1.66.0-3.ph5
  grub2-theme 5.0-1.ph5 -> 5.0-2.ph5
  grub2-theme-ostree 5.0-1.ph5 -> 5.0-2.ph5
  iproute2 5.8.0-1.ph5 -> 5.10.0-1.ph5
  iptables 1.8.4-1.ph5 -> 1.8.7-1.ph5
  json-c 0.15-2.ph5 -> 0.15-3.ph5
  libgcc 8.4.0-1.ph5 -> 10.2.0-1.ph5
  libmetalink 0.1.3-2.ph5 -> 0.1.3-3.ph5
  libmodulemd 2.9.4-1.ph5 -> 2.11.0-1.ph5
  librepo 1.12.1-3.ph5 -> 1.12.1-4.ph5
  libsepol 3.1-1.ph5 -> 3.1-2.ph5
  libsolv 0.6.35-5.ph5 -> 0.6.35-7.ph5
  libssh2 1.9.0-2.ph5 -> 1.9.0-3.ph5
  libstdc++ 8.4.0-1.ph5 -> 10.2.0-1.ph5
  libxml2 2.9.10-3.ph5 -> 2.9.10-6.ph5
  libxml2-devel 2.9.10-3.ph5 -> 2.9.10-6.ph5
  libxslt 1.1.34-1.ph5 -> 1.1.34-2.ph5
  linux 5.9.0-3.ph5 -> 5.10.4-15.ph5
  ncurses 6.2-2.ph5 -> 6.2-3.ph5
  ncurses-libs 6.2-2.ph5 -> 6.2-3.ph5
  ncurses-terminfo 6.2-2.ph5 -> 6.2-3.ph5
  nss 3.57-1.ph5 -> 3.57-2.ph5
  nss-libs 3.57-1.ph5 -> 3.57-2.ph5
  open-vm-tools 11.1.5-4.ph5 -> 11.2.5-1.ph5
  openldap 2.4.53-2.ph5 -> 2.4.53-3.ph5
  openssl 1.1.1g-3.ph5 -> 1.1.1i-2.ph5
  pcre 8.44-1.ph5 -> 8.44-2.ph5
  pcre-libs 8.44-1.ph5 -> 8.44-2.ph5
  python3 3.8.6-1.ph5 -> 3.9.1-2.ph5
  python3-PyYAML 5.3.1-1.ph5 -> 5.4.1-1.ph5
  python3-attrs 20.2.0-2.ph5 -> 20.3.0-2.ph5
  python3-cryptography 3.1.1-2.ph5 -> 3.2.1-1.ph5
  python3-gobject-introspection 1.66.0-1.ph5 -> 1.66.0-3.ph5
  python3-libs 3.8.6-1.ph5 -> 3.9.1-2.ph5
  python3-packaging 20.4-2.ph5 -> 20.4-3.ph5
  python3-pyrsistent 0.17.3-1.ph5 -> 0.17.3-2.ph5
  python3-setuptools 3.8.6-1.ph5 -> 3.9.1-2.ph5
  python3-urllib3 1.25.10-2.ph5 -> 1.25.11-1.ph5
  python3-xml 3.8.6-1.ph5 -> 3.9.1-2.ph5
  rpm 4.14.2-11.ph5 -> 4.16.1.2-1.ph5
  rpm-libs 4.14.2-11.ph5 -> 4.16.1.2-1.ph5
  rpm-ostree 2020.5-4.ph5 -> 2020.5-5.ph5
  shadow 4.8.1-2.ph5 -> 4.8.1-3.ph5
  shadow-tools 4.8.1-2.ph5 -> 4.8.1-3.ph5
  sudo 1.8.30-2.ph5 -> 1.9.5-1.ph5
  systemd 245.5-3.ph5 -> 247.3-1.ph5
  util-linux 2.36-1.ph5 -> 2.36-2.ph5
  util-linux-libs 2.36-1.ph5 -> 2.36-2.ph5
Added:
  libpcap-1.10.0-1.ph5.x86_64
  python3-Pygments-2.7.2-2.ph5.noarch
  python3-alabaster-0.7.12-1.ph5.noarch
  python3-babel-2.8.0-3.ph5.noarch
  python3-docutils-0.16-1.ph5.noarch
  python3-imagesize-1.2.0-2.ph5.noarch
  python3-pytz-2020.4-2.ph5.noarch
  python3-snowballstemmer-2.0.0-1.ph5.noarch
  python3-sphinx-3.3.0-2.ph5.noarch
  python3-sphinxcontrib-applehelp-1.0.2-1.ph5.noarch
  python3-sphinxcontrib-devhelp-1.0.2-1.ph5.noarch
  python3-sphinxcontrib-htmlhelp-1.0.3-1.ph5.noarch
  python3-sphinxcontrib-jsmath-1.0.1-1.ph5.noarch
  python3-sphinxcontrib-qthelp-1.0.3-1.ph5.noarch
  python3-sphinxcontrib-serializinghtml-1.1.4-1.ph5.noarch
  python3-typing-3.7.4.3-1.ph5.noarch
  systemd-libs-247.3-1.ph5.x86_64
  systemd-pam-247.3-1.ph5.x86_64
  systemd-rpm-macros-247.3-1.ph5.noarch
  systemd-udev-247.3-1.ph5.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-7c2d910d79e9 [ ~ ]# rpm-ostree status
State: idle
Deployments:
  ostree://photon:photon/5.0/x86_64/minimal
    Version: 5.0_minimal (2021-02-20T07:15:43Z)
Commit: 965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f
  Diff: 63 upgraded, 20 added

● ostree://photon:photon/5.0/x86_64/minimal
    Version: 5.0_minimal (2020-11-04T02:21:47Z)
Commit: 820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88

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/5.0/x86_64/minimal
      Version: 5.0_minimal (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-7c2d910d79e9 [ ~ ]# ostree log 965c
  commit 965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f
  ContentChecksum:  9bc85673bd8d5599d61a02a99accce9bc9b72612c7a3cebd35427875f6514288
  Date:  2021-02-20 07:15:43 +0000
  Version: 5.0_minimal
  (no subject)

But there is nothing to rollback to.

root@photon-7c2d910d79e9 [ ~ ]# rpm-ostree rollback
Moving '820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88.0' to be first deployment
Transaction complete; bootconfig swap: yes; deployment count change: 0
Run "systemctl reboot" to start a reboot

If we were to upgrade again, it would bring these packages back, but let’s just check the differences.

root@photon-7c2d910d79e9 [ ~ ]# rpm-ostree upgrade --check-diff
  ⠚ Receiving metadata objects: 0/(estimating) -/s 0 bytes... 
  Receiving metadata objects: 0/(estimating) -/s 0 bytes... done
  No updates available.

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/5.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-7c2d910d79e9 [ ~ ]# rpm-ostree upgrade -r
⠒ Receiving metadata objects: 0/(estimating) -/s 0 bytes... 
Receiving metadata objects: 0/(estimating) -/s 0 bytes... done
No upgrade available.

After reboot, let’s check the booting filetrees, the current dir for the current filetree and look at commit differences:

root@photon-7c2d910d79e9 [ ~ ]# rpm-ostree status
State: idle
Deployments:
● ostree://photon:photon/5.0/x86_64/minimal
    Version: 5.0_minimal (2020-11-04T02:21:47Z)
Commit: 820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88

  ostree://photon:photon/5.0/x86_64/minimal
    Version: 5.0_minimal (2021-02-20T07:15:43Z)
Commit: 965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f


root@photon-7c2d910d79e9 [ ~ ]# ostree admin config-diff --print-current-dir
/ostree/deploy/photon/deploy/820b584a6f90bf6b9b8cb6aad8c093064b88d0ab686be8130baa03d68917ad88.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-7c2d910d79e9 [ ~ ]# ostree reset photon:photon/5.0/x86_64/minimal 965c

Now if we look again at the branch commit history, the head is at version 0.

root@photon-7c2d910d79e9 [ ~ ]# ostree log photon/5.0/x86_64/minimal
commit 965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f
ContentChecksum:  9bc85673bd8d5599d61a02a99accce9bc9b72612c7a3cebd35427875f6514288
Date:  2021-02-20 07:15:43 +0000
Version: 5.0_minimal
(no subject)

Note: The outputs listed above are only for reference. The version numbers in the outputs might vary from the actual outputs.

13.6 - Creating a Server

Photon OS 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 how to create your own customized file tree.

13.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

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 this document.

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”.

PhotonHostCustom

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.

PhotonHostCustomURL

Once this is done and the installation finished, reboot and you are ready to use it. You may verify - just like in this document - 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 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/5.0/x86_64/minimal",
    ...

See sample kickstart configuration in sample_ks_ostree_client_from_server file for ostree deployement from official photon-os ostree server.

Or, for default installation

    ....
    "type": "ostree_host",
    "default_repo": true,
    ....

See sample kickstart configuration in sample_ks_ostree_client_from_default file for ostree deployment.

If the server is a future version of Photon OS, say Photon OS 5.0, and the administrator composed trees for the included json files, the ostree_repo_ref will take either value: photon/5.0/x86_64/base, photon/5.0/x86_64/minimal, or photon/5.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.

13.8 - Automatic Updates

Automatic updates are disabled by default.

To verify this, run the status command.

root@photon-7c2d910d79e9 [ ~ ]# rpm-ostree status 
State: idle
Deployments:
● ostree://photon:photon/5.0/x86_64/minimal
   Version: 5.0_minimal (2021-02-20T07:15:43Z)
Commit: 965c1abeb048e1a8ff77e9cd34ffccc5e3356176cda3332b4ff0e7a6c66b661f

Enable Automatic Updates

  1. Run the following command:
$ systemctl restart rpm-ostreed
  1. 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
    
  2. Run the following commands:

    $ systemctl reload rpm-ostreed
    $ systemctl enable rpm-ostree-automatic.timer --now  
    $ systemctl restart rpm-ostree-automatic
    
  3. 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
    
  4. On the server machine, perform another commit on the base tree.

Automatic updates are now enabled and will automatically update the host system.

13.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 (after 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

Creating summary metadata

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.

13.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
-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/5.0/x86_64/minimal",

    "automatic_version_prefix": "5.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 5.0(x86_64)
baseurl=https://packages.vmware.com/photon/5.0/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 VMware Photon Packages URL, which is the location of an online RPMS repo maintained by the VMware Photon OS team. To ensure those packages can be validated as being genuine and 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 packages.vmware.com/photon/photon_publish_rpms/, 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 5.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.ph5.x86_64
  attr-2.4.47-1.ph5.x86_64
  ...
  gawk-4.1.0-2.ph5.x86_64
  ...
  sudo-1.8.11p1-4.ph5.x86_64
  ...
  wget-1.15-1.ph5.x86_64
  which-2.20-1.ph5.x86_64
  xz-5.0.5-2.ph5.x86_64
  zlib-1.2.8-2.ph5.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.ph5

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

We’ve omitted a large portion of the logging output, however you can see that 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.ph5.x86_64, sudo-1.8.11p1-4.ph5.x86_64 and wget-1.15-1.ph5.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 versioning 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 OSTree Packages 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/5.0/x86_64/minimal

8 metadata, 13 content objects fetched; 1002 KiB transferred in 0 seconds
!bridge-utils-1.5-2.ph5.x86_64
=bridge-utils-1.5-3.ph5.x86_64
!bzip2-1.0.6-5.ph5.x86_64
=bzip2-1.0.6-6.ph5.x86_64
!curl-7.47.1-2.ph5.x86_64
=curl-7.51.0-2.ph5.x86_64
!docker-1.11.0-5.ph5.x86_64
=docker-1.12.1-1.ph5.x86_64
...
+libssh2-1.8.0-1.ph5.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.ph5 -> 1.5-3.ph5
  bzip2 1.0.6-5.ph5 -> 1.0.6-6.ph5
  curl 7.47.1-2.ph5 -> 7.51.0-2.ph5
  docker 1.11.0-5.ph5 -> 1.12.1-1.ph5
  ...
Added:
  libssh2-1.8.0-1.ph5.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.ph5.x86_64
* Mon Sep 12 2016 user1 <user1@vmware.com> 1.5-3
-	Update patch to fix-2.

 bzip2-1.0.6-6.ph5.x86_64
* Fri Oct 21 2016 user2 <user2@vmware.com> 1.0.6-6
-       Fixing security bug CVE-2016-3189.

 curl-7.51.0-2.ph5.x86_64
* Wed Nov 30 2016 user3 <user3@vmware.com> 7.51.0-2
-   Enable sftp support.

* Wed Nov 02 2016 user4 <user4@vmware.com> 7.51.0-1
-   	Upgrade curl to 7.51.0

* Thu Oct 27 2016 user4 <user4@vmware.com> 7.47.1-4
-   	Patch for CVE-2016-5421

* Mon Sep 19 2016 user3 <user3@vmware.com> 7.47.1-3
-   	Applied CVE-2016-7167.patch.

 docker-1.12.1-1.ph5.x86_64
* Wed Sep 21 2016 user3 <user3@vmware.com> 1.12.1-1
-   Upgraded to version 1.12.1

* Mon Aug 22 2016 user1 <user1@vmware.com> 1.12.0-2
-   Added bash completion file

* Tue Aug 09 2016 user4 <user4@vmware.com> 1.12.0-1
-   Upgraded to version 1.12.0

* Tue Jun 28 2016 user4 <user4@vmware.com> 1.11.2-1
-   Upgraded to version 1.11.2
...
Added:
 libssh2-1.8.0-1.ph5.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 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.

Note: The outputs listed above are only for reference. The version numbers in the outputs might vary from the actual outputs.

13.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-7c2d910d79e9 [ ~ ]# ostree remote list
photon

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-7c2d910d79e9 [ ~ ]# ostree remote show-url photon
https://packages.vmware.com/photon/rpm-ostree/base/5.0/x86_64/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 VMware Photon Packages URL by photon-srv1’s IP address, all original packages in the original 5.0_minimal version will be preserved, but any new package change (addition, removal, upgrade) added after that (in 5.0_minimal.1, 5.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/5.0/x86_64/minimal photon/5.0/x86_64/full
root@photon-host-cus [ ~ ]# ostree remote list
photon
photon2
root@photon-host-cus [ ~ ]# ostree remote show-url photon2
http://10.0.0.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.0.0.86
branches=photon/5.0/x86_64/minimal;photon/5.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).

In Photon OS, 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/5.0/x86_64/base
photon2:photon/5.0/x86_64/full
photon2:photon/5.0/x86_64/minimal

Switching branches (rebasing)

If you have an installed Photon 4.0 that you want to carry to 5.0, you need to rebase it.

See rebasing.

13.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 automatically 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 .4 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     5.0_minimal     092e21d292     photon     photon:photon/x86_64/minimal
  2015-08-20 22:27:43     5.0_minimal       2940e10c4d     photon     photon:photon/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.ph5tp2.x86_64
  perl-YAML-1.14-1.ph5tp2.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     5.0_minimal     d16aebd803     photon     photon:photon/x86_64/minimal
* 2015-09-04 00:36:37     5.0_minimal     092e21d292     photon     photon:photon/x86_64/minimal

After reboot from 5.0_minimal. 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

13.13 - Install or rebase to Photon OS

Photon OS 5.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 5.0 increased significantly, compared to 1.0. To keep the ISO at reasonable size, the previous versions no longer include 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:

  1. 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
  1. 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 Automated install of a custom host via kickstart.

Rebasing a host from Photon 1.0 to 5.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 5.0, you need to rebase it. Notice that we didn’t say “upgrade”.

Practically, 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 listed in the newer OSTree repo, which has been composed from a newer Photon OS 5.0 RPMS repo. Again, we 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 older 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.

  1. To install fresh, deploy a Photon OS host default, as described in the section Installing A Host Against the Default Server Repository. Of course, if you already have an existing Photon OS 4.0 host that you want to move to 5.0, skip this step.

  2. Edit /ostree/repo/config and substitute the url, providing the IP address for the Photon OS RPM-OSTree server installed above. This was explained in the “Switching Repositories” section of the Remotes document.
    Ostree should confirm that is the updated server IP for the “photon” remote.

root@ostree-host [ ~ ]# ostree remote show-url photon
http://10.20.30.175:8000/repo
  1. Rebase your host to the new 5.0 server and Refspec.
root@ostree-host [ ~ ]# ostree remote add photon-5 http://10.20.30.204:8000/repo --no-gpg-verify
root@ostree-host [ ~ ]# rpm-ostree rebase photon-5:photon/5.0/x86_64/minimal

Rebasing to photon-5:photon/5.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.ph5 -> 18.06.2-4.ph5
  gmp 6.1.2-2.ph5 -> 6.1.2-3.ph5
  gobject-introspection 1.58.0-2.ph5 -> 1.58.0-3.ph5
  gzip 1.9-1.ph5 -> 1.9-2.ph5
  linux 4.19.65-3.ph5 -> 4.19.69-1.ph5
  mpfr 4.0.1-1.ph5 -> 4.0.1-2.ph5
  ostree 2019.2-1.ph5 -> 2019.2-2.ph5
  ostree-grub2 2019.2-1.ph5 -> 2019.2-2.ph5
  ostree-libs 2019.2-1.ph5 -> 2019.2-2.ph5
  zlib 1.2.11-1.ph5 -> 1.2.11-2.ph5
Added:
  efibootmgr-15-1.ph5.x86_64
  efivar-36-1.ph5.x86_64
  tar-1.30-3.ph5.x86_64
Run "systemctl reboot" to start a reboot
  1. Check the status
root@ostree-host [ ~ ]# rpm-ostree status
State: idle
AutomaticUpdates: disabled
Deployments:
* ostree://photon-1:photon/5.0/x86_64/minimal
                Version: 5.0_minimal (2019-09-18T08:22:15Z)
            BaseCommit: c8f2b116b067d7695f9033bf2a99505198269354e157c0f2d5b78266cb874239
        LayeredPackages: createrepo_c rpm wget

  ostree://photon:photon/5.0/x86_64/minimal
                Version: 5.0_minimal.1 (2017-01-11T02:18:42)
            BaseCommit: 28dc49ecb4604c0bc349e4445adc659491a1874c01198e6253a261f4d59708b7
        LayeredPackages: createrepo_c rpm wget

You may now reboot to the new Photon OS 5.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.

14 - Support for SELinux

SELinux is a labelling system to implement MAC(mandatory access control) for subjects(user, process) over objects (files, dirs, sockets) and to protect the confidentiality of objects. It is a policy driven system where rules can be mapped to the labels which have been given to subjects, objects. It is an extra level of security provided on top of Linux normal file ownership/permissions.

Photon OS offersx support for SELinux. The support covers a minimal set of policies for the container runtime case and it is referred to as the default policy. It is a Multi-Category Security (MCS) policy. So the files on the filesystem can be labeled with multiple categories.The MCS policy is actively used by container runtime as runc/containerd/docker/kubernetes to assign the per-container category.

The default policy in Photon OS does not use user, role (RBAC) and level (MLS) fields of the file labels.It operates only with the context and category fields. It consists of several modules loaded with priority as 100. The user-defined policy can overwrite default modules by using the higher priority.

Enabling SELinux

To enable SELinux on Photon OS:

  1. Install default policy and its dependencies. Initial filesystem labeling will be done as RPM post action.

    tdnf install -y selinux-policy

  2. Enable SELinux security model in kernel by adding 2 kernel parameters:

  • security=selinux
  • selinux=1

Ensure that you reboot after adding the kernel parameters.

  1. After reboot, the system runs in SELinux permissive mode. To confirm, check the journal:

    journalctl -b0 | grep -i selinux
    
    Feb 26 21:42:09 photon-machine kernel: SELinux:  Initializing.
    Feb 26 21:42:09 photon-machine kernel: SELinux:  policy capability ...
    Feb 26 21:42:09 photon-machine kernel: audit: type=1403 audit(1589406128.920:2): auid=4294967295 ses=4294967295 lsm=selinux res=1
    Feb 26 21:42:09 photon-machine systemd[1]: Successfully loaded SELinux policy in 322.475ms.
    

Switch SELinux to enforcing mode

The three methods to toggle enforcing mode are as follows:

  1. Run the setenforce 1 command (libselinux-utils rpm), Enforcing mode will be set immediately, but it is not preserved on reboot.
  2. Edit the /etc/selinux/config file to set SELINUX=enforcing and reboot.
  3. Add the enforcing=1 kernel parameter and reboot.

Developing Customized Policy

Photon OS provides an ability to develop customized additional policy on top of existing default policy. The following example is for adding the sys_admin capability policy:

  1. Install policy development packages:

    tdnf install -y selinux-policy-devel semodule-utils
    
  2. Create .te file

    cat getty_local.te
    policy_module(getty_local, 1.0)
    
    gen_require(`
        type getty_t;
          ')
    
    allow getty_t self:capability sys_admin;
    
  3. Compile it into .pp file

    make -f /usr/share/selinux/devel/Makefile getty_local.pp
    
  4. Load it with priority 200. It will permanently alter default policy. And this change will survive reboot cycle.

    semodule -i getty_local.pp -X 200
    
  5. Check result

    sesearch -A -s getty_t -t getty_t -c capability
    allow getty_t getty_t:capability { chown dac_override dac_read_search fowner fsetid setgid sys_admin sys_resource sys_tty_config };
    
  6. List of loaded modules and their priorities

    semodule -lfull
    

Debugging SELinux

Install the debugging tools as follows:

tdnf install -y setools python3-pip

pip3 install networkx

List all actions denied by Selinux using the following command:

journalctl _TRANSPORT=audit -b 0 | grep denied

Feb 26 21:42:43 photon-machine audit[445]: AVC avc:  denied  { sys_admin } for  pid=445 comm="agetty" capability=21
scontext=system_u:system_r:getty_t:s0-s0:c0.c1023 tcontext=system_u:system_r:getty_t:s0-s0:c0.c1023 tclass=capability permissive=0

You can see that the agetty process running in the getty_t context tries to change the capability of getty_t target to obtain sys_admin. To view the capability that getty_t can obtain:

sesearch -A -s getty_t -t getty_t -c capability

allow getty_t getty_t:capability { chown dac_override dac_read_search fowner fsetid setgid sys_resource sys_tty_config };

Important SELinux Files

Here are some of the important SELinux files:

  • SELinux config /etc/selinux/config

  • default policy folder /etc/selinux/default/

  • Binary policy blob to be loaded to kernel on every boot /etc/selinux/default/policy/policy.32

  • List of file labels used by the policy /etc/selinux/default/contexts/files/file_contexts

Troubleshooting Compilation Error

If compilation fails by any reason and it complains on some line number in the .cil file. You can run the pp compiler to get the plain text cil output.

/usr/libexec/selinux/hll/pp getty_local.pp
(roleattributeset cil_gen_require system_r)
(typeattributeset cil_gen_require getty_t)
(allow getty_t self (capability (sys_admin)))

15 - pmd-nextgen Overview

The pmd-nextgen package contains the photon-mgmtd tool. photon-mgmtd is a high-performing, open-source, lightweight, pluggable REST API gateway designed with stateless architecture. photon-mgmtd is written in Go and built with performance in mind. It facilitates real-time configuration, performance analysis, and health monitoring of systems, networks, services, and applications.

photon-mgmtd is optimized to provide the following benefits:

  • The proactive monitoring and analytics features help the administrator to efficiently collect analytical data for performance and health management of systems.
  • For remote access, you can use the platform-independent REST APIs via any application on any Operating system. For example, you can use applications such as Curl/Chrome/Postman on any operating system such as Linux/iOS/Android/Windows and so on.
  • Minimal data transfer using JSON.
  • Plugin based architecture for easier operation.

15.1 - Features

The following table lists the photon-mgmtd features details:

FeatureDetails
systemdInformation, services (start, stop, restart, status), service properties such as CPUShares
see information from /proc fsnetstat, netdev, memory and much more

15.2 - Installing photon-mgmtd

You can install photon-mgmtd using the pmd-nextgen package. The pmd-nextgen package is included in your Photon OS 4.0 Rev 2 distribution. To install pmd-nextgen, run the following command:

# tdnf install pmd-ng
# systemctl start photon-mgmtd.service

15.3 - Configuration

To configure photon-mgmtd, use the mgmt.toml file located in the following directory: /etc/photon-mgmt/

You can set values for the following keys in the [System] section:

LogLevel= Specifies the log level. The key takes one of the following: values: Trace, Debug, Info, Warning, Error, Fatal and Panic. Default is info.

UseAuthentication= Specifies whether a user needs authentication. This is a boolean key and takes the following values: true, false. Default is true.

You can set values for the following keys in the [Network] section:

Listen= Specifies the IP address and port that the REST API server listens to. When enabled, the default is 127.0.0.1:5208.

ListenUnixSocket= Specifies whether you want the server to listen on a unix domain socket /run/photon-mgmt/mgmt.sock. This is a boolean key and takes the following values: true, false. Default is true.

Note: When you enable both ListenUnixSocket= and Listen=, server listens on the unix domain socket by default.

❯ sudo cat /etc/photon-mgmt/mgmt.toml
[System]
LogLevel="info"
UseAuthentication="false"

[Network]
ListenUnixSocket="true"


❯ sudo systemctl status photon-mgmtd.service
● photon-mgmtd.service - A REST API based configuration management microservice gateway
     Loaded: loaded (/usr/lib/systemd/system/photon-mgmtd.service; disabled; vendor preset: disabled)
     Active: active (running) since Thu 2022-01-06 16:32:19 IST; 4s ago
   Main PID: 230041 (photon-mgmtd)
      Tasks: 6 (limit: 15473)
     Memory: 2.9M
        CPU: 7ms
     CGroup: /system.slice/photon-mgmtd.service
             └─230041 /usr/bin/photon-mgmtd

Jan 06 16:32:19 Zeus systemd[1]: photon-mgmtd.service: Passing 0 fds to service
Jan 06 16:32:19 Zeus systemd[1]: photon-mgmtd.service: About to execute /usr/bin/photon-mgmtd
Jan 06 16:32:19 Zeus systemd[1]: photon-mgmtd.service: Forked /usr/bin/photon-mgmtd as 230041
Jan 06 16:32:19 Zeus systemd[1]: photon-mgmtd.service: Changed failed -> running
Jan 06 16:32:19 Zeus systemd[1]: photon-mgmtd.service: Job 56328 photon-mgmtd.service/start finished, result=done
Jan 06 16:32:19 Zeus systemd[1]: Started photon-mgmtd.service - A REST API based configuration management microservice gateway.
Jan 06 16:32:19 Zeus systemd[230041]: photon-mgmtd.service: Executing: /usr/bin/photon-mgmtd
Jan 06 16:32:19 Zeus photon-mgmtd[230041]: time="2022-01-06T16:32:19+05:30" level=info msg="photon-mgmtd: v0.1 (built go1.18beta1)"
Jan 06 16:32:19 Zeus photon-mgmtd[230041]: time="2022-01-06T16:32:19+05:30" level=info msg="Starting photon-mgmtd... Listening on unix domain socket='/run/photon-mgmt/mgmt.sock' in HTTP mode pid=103575">

How to Configure Users?

Unix domain socket

When you add users to the photon-mgmt group, they can access the unix socket. Use the following command to add a user: # usermod -a -G photon-mgmt exampleusername

15.4 - photon-mgmtd API

Use photon-mgmtd REST-APIs to manage, control, configure, and monitor services remotely.

You can use photon-mgmtd to manage the following:

  • Services
  • System
  • Network
  • User, Group, Host

15.4.1 - Service Management

POST Method

To manage the available services and take actions on the services, execute a POST request in the following format:

curl --unix-socket  /run/photon-mgmt/mgmt.sock  --request POST --data '{"action":"{command}”,”unit”:”{unit}"}' http://localhost/api/v1/service/systemd

The following table lists the parameters:

ParameterDescription
UnitThe name of the service you want to manage.
Action CommandsThe action you want to take on the service. Start, stop, restart, try-restart, reload-or-restart, reload, enable, disable, mask, unnmask, kill

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request POST --data '{"action":"start","unit":"nginx.service"}' http://localhost/api/v1/service/systemd

Response:

{
   "success":true,
   "message":"",
   "errors":""
}

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request POST --data '{"action":"stop","unit":"nginx.service"}' http://localhost/api/v1/service/systemd

Response:

{
   "success":true,
   "message":"",
   "errors":""
}

GET Method:

Status of all the services:

The systemctl list-unit-files command lists all the services available in the system. To fetch the list of services listed in the list-unit files, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/units

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/units

Status of a Specific Service:

To receive the status details of a specific service, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/{unit}/status

The following table lists the parameter:

ParameterDescription
UnitThe name of the service for which you want to get the status.

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost:5208/api/v1/service/systemd/nginx.service/status | jq	% Total % Received % Xferd Average Speed Time Time Time Current	Dload Upload Total Spent Left Speed	100 514 100 514 0 0 38298 0 --:--:-- --:--:-- --:--:-- 39538

Response:

{
   "success":true,
   "message":{
      "Property":"inactive",
      "Unit":"nginx.service",
      "Name":"nginx.service",
      "Description":"Nginx High-performance HTTP server and reverse proxy",
      "MainPid":0,
      "LoadState":"loaded",
      "ActiveState":"inactive",
      "SubState":"dead",
      "Followed":"",
      "Path":"/org/freedesktop/systemd1/unit/nginx_2eservice",
      "JobId":0,
      "JobType":"",
      "JobPath":"/",
      "UnitFileState":"disabled",
      "StateChangeTimestamp":0,
      "InactiveExitTimestamp":0,
      "ActiveEnterTimestamp":0,
      "ActiveExitTimestamp":0,
      "InactiveEnterTimestamp":0
   },
   "errors":""
}

Value of a Specific Property

To fetch the value of a specific property, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/manager/property/Version

The following table lists the parameter:

ParameterDescription
PropertyVersion, Features, Virtualization, Architecture, Tainted.

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://127.0.0.1/api/v1/service/systemd/manager/property/Virtualization

Response:

{
   "success":true,
   "message":{
      "property":"Virtualization",
      "value":"vmware"
   },
   "errors":""
}

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://127.0.0.1/api/v1/service/systemd/manager/property/Architecture

Response:

{
   "success":true,
   "message":{
      "property":"Architecture",
      "value":"x86-64"
   },
   "errors":""
}

Properties of a Specific Service

To fetch the property of a specific service, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/{unit}/property

The following table lists the parameter:

ParameterDescription
UnitThe name of the service for which you want to get the properties.

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/nginx.service/property

Properties of All Services

To fetch all the properties of a service, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/{unit}/propertyall

The following table lists the parameter:

ParameterDescription
UnitThe name of the service for which you want to fetch the properties.

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/nginx.service/propertyall | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 9652 0 9652 0 0 1058k 0 --:--:-- --:--:-- --:--:-- 1178k

Configuration Details

To receive the configuration details, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/conf

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/conf

Response:

{
   "success":true,
   "message":{
      "CPUAffinity":"",
      "CapabilityBoundingSe":"",
      "CrashChangeVT":"",
      "CrashReboot":"",
      "CrashShell":"",
      "CtrlAltDelBurstAction":"",
      "DefaultBlockIOAccounting":"",
      "DefaultCPUAccounting":"",
      "DefaultEnvironment":"",
      "DefaultIOAccounting":"",
      "DefaultIPAccounting":"",
      "DefaultLimitAS":"",
      "DefaultLimitCORE":"",
      "DefaultLimitCPU":"",
      "DefaultLimitDATA":"",
      "DefaultLimitFSIZE":"",
      "DefaultLimitLOCKS":"",
      "DefaultLimitMEMLOCK":"",
      "DefaultLimitMSGQUEUE":"",
      "DefaultLimitNICE":"",
      "DefaultLimitNOFILE":"",
      "DefaultLimitNPROC":"",
      "DefaultLimitRSS":"",
      "DefaultLimitRTPRIO":"",
      "DefaultLimitRTTIME":"",
      "DefaultLimitSIGPENDING":"",
      "DefaultLimitSTACK":"",
      "DefaultMemoryAccounting":"",
      "DefaultRestartSec":"",
      "DefaultStandardError":"",
      "DefaultStandardOutput":"",
      "DefaultStartLimitBurst":"",
      "DefaultStartLimitIntervalSec":"",
      "DefaultTasksAccounting":"",
      "DefaultTasksMax":"",
      "DefaultTimeoutStartSec":"",
      "DefaultTimeoutStopSec":"",
      "DefaultTimerAccuracySec":"",
      "DumpCore":"",
      "IPAddressAllow":"",
      "IPAddressDeny":"",
      "JoinControllers":"",
      "LogColor":"",
      "LogLevel":"",
      "LogLocation":"",
      "LogTarget":"",
      "RuntimeWatchdogSec":"",
      "ShowStatus":"",
      "ShutdownWatchdogSec":"",
      "SystemCallArchitectures":"",
      "TimerSlackNSec":""
   },
   "errors":""
}

Configuration Update Details

To fetch the details about the configuration updates, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/conf/update

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/service/systemd/conf/update

Response:

{
   "success":true,
   "message":{
      "CPUAffinity":"",
      "CapabilityBoundingSe":"",
      "CrashChangeVT":"",
      "CrashReboot":"",
      "CrashShell":"",
      "CtrlAltDelBurstAction":"",
      "DefaultBlockIOAccounting":"",
      "DefaultCPUAccounting":"",
      "DefaultEnvironment":"",
      "DefaultIOAccounting":"",
      "DefaultIPAccounting":"",
      "DefaultLimitAS":"",
      "DefaultLimitCORE":"",
      "DefaultLimitCPU":"",
      "DefaultLimitDATA":"",
      "DefaultLimitFSIZE":"",
      "DefaultLimitLOCKS":"",
      "DefaultLimitMEMLOCK":"",
      "DefaultLimitMSGQUEUE":"",
      "DefaultLimitNICE":"",
      "DefaultLimitNOFILE":"",
      "DefaultLimitNPROC":"",
      "DefaultLimitRSS":"",
      "DefaultLimitRTPRIO":"",
      "DefaultLimitRTTIME":"",
      "DefaultLimitSIGPENDING":"",
      "DefaultLimitSTACK":"",
      "DefaultMemoryAccounting":"",
      "DefaultRestartSec":"",
      "DefaultStandardError":"",
      "DefaultStandardOutput":"",
      "DefaultStartLimitBurst":"",
      "DefaultStartLimitIntervalSec":"",
      "DefaultTasksAccounting":"",
      "DefaultTasksMax":"",
      "DefaultTimeoutStartSec":"",
      "DefaultTimeoutStopSec":"",
      "DefaultTimerAccuracySec":"",
      "DumpCore":"",
      "IPAddressAllow":"",
      "IPAddressDeny":"",
      "JoinControllers":"",
      "LogColor":"",
      "LogLevel":"",
      "LogLocation":"",
      "LogTarget":"",
      "RuntimeWatchdogSec":"",
      "ShowStatus":"",
      "ShutdownWatchdogSec":"",
      "SystemCallArchitectures":"",
      "TimerSlackNSec":""
   },
   "errors":""
}

15.4.2 - System Management

GET Method

System Information

To fetch the complete system information, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET http://localhost/api/v1/system/describe

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET http://localhost/api/v1/system/describe | jq	% Total % Received % Xferd Average Speed Time Time Time Current	Dload Upload Total Spent Left Speed	100 5588 0 5588 0 0 42133 0 --:--:-- --:--:-- --:--:-- 42015

CPU Information

To fetch information related to CPU, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/cpuinfo

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/cpuinfo

Disk Usage Details

To fetch the usage details of the disk, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/diskusage

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/diskusage

Response:

{
   "success":true,
   "message":{
      "path":"/",
      "fstype":"ext2/ext3",
      "total":269474643968,
      "free":241944858624,
      "used":13769904128,
      "usedPercent":5.3848686637440935,
      "inodesTotal":16777216,
      "inodesUsed":101362,
      "inodesFree":16675854,
      "inodesUsedPercent":0.6041646003723145
   },
   "errors":""
}

Platform & kernel version details

To fetch the details about the platform and kernel versions on which the system is installed:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/version

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/version

Response:

{
   "success":true,
   "message":{
      "hostname":"photon-4",
      "uptime":10168492,
      "bootTime":1627041016,
      "procs":475,
      "os":"linux",
      "platform":"photon",
      "platformFamily":"",
      "platformVersion":"4.0",
      "kernelVersion":"5.10.46-2.ph4",
      "kernelArch":"x86_64",
      "virtualizationSystem":"",
      "virtualizationRole":"",
      "hostId":"25a54d56-2249-524d-1355-e97b24e3415a"
   },
   "errors":""
}

Miscellaneous Hardware Details

To fetch miscellaneous harware details, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/misc

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/misc

Response:

{
   "success":true,
   "message":{
      "175":"agpgart",
      "183":"hw_random",
      "228":"hpet",
      "229":"fuse",
      "231":"snapshot",
      "235":"autofs",
      "237":"loop-control",
      "60":"vsock",
      "61":"vmci",
      "62":"cpu_dma_latency",
      "63":"vga_arbiter"
   },
   "errors":""
}

User Details

To fetch the user details, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/userstat

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/userstat

Virtual Memory Details

To fetch the details of the virtual memory, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/virtualmemory

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/virtualmemory

Response:

{
   "success":true,
   "message":{
      "total":16810287104,
      "available":15859195904,
      "used":519139328,
      "usedPercent":3.0882240427438687,
      "free":9925554176,
      "active":4017090560,
      "inactive":2234974208,
      "wired":0,
      "laundry":0,
      "buffers":171372544,
      "cached":6194221056,
      "writeBack":0,
      "dirty":0,
      "writeBackTmp":0,
      "shared":9539584,
      "slab":440422400,
      "sreclaimable":370315264,
      "sunreclaim":70107136,
      "pageTables":6144000,
      "swapCached":0,
      "commitLimit":8405143552,
      "committedAS":1310273536,
      "highTotal":0,
      "highFree":0,
      "lowTotal":0,
      "lowFree":0,
      "swapTotal":0,
      "swapFree":0,
      "mapped":126369792,
      "vmallocTotal":35184372087808,
      "vmallocUsed":46546944,
      "vmallocChunk":0,
      "hugePagesTotal":0,
      "hugePagesFree":0,
      "hugePageSize":2097152
   },
   "errors":""
}

Kernel Module Details

To fetch the details about the kernel module, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/modules

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/modules

Network ARP Details

To fetch the network ARP details, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/net/arp

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/net/arp

Response:

{
   "success":true,
   "message":[
      {
         "IPAddress":"",
         "HWType":"",
         "Flags":"",
         "HWAddress":"",
         "Mask":"",
         "Device":""
      },
      {
         "IPAddress":"10.197.103.253",
         "HWType":"0x1",
         "Flags":"0x2",
         "HWAddress":"00:00:0c:9f:f4:28",
         "Mask":"*",
         "Device":"eth0"
      },
      {
         "IPAddress":"10.197.103.162",
         "HWType":"0x1",
         "Flags":"0x2",
         "HWAddress":"00:0c:29:b1:e6:16",
         "Mask":"*",
         "Device":"eth0"
      },
      {
         "IPAddress":"10.197.103.251",
         "HWType":"0x1",
         "Flags":"0x2",
         "HWAddress":"00:35:1a:9d:b8:e3",
         "Mask":"*",
         "Device":"eth0"
      },
      {
         "IPAddress":"10.197.103.174",
         "HWType":"0x1",
         "Flags":"0x2",
         "HWAddress":"00:0c:29:d3:c7:00",
         "Mask":"*",
         "Device":"eth0"
      },
      {
         "IPAddress":"10.197.103.252",
         "HWType":"0x1",
         "Flags":"0x2",
         "HWAddress":"00:f2:8b:e1:b0:13",
         "Mask":"*",
         "Device":"eth0"
      },
      {
         "IPAddress":"10.197.103.91",
         "HWType":"0x1",
         "Flags":"0x2",
         "HWAddress":"00:0c:29:41:07:8b",
         "Mask":"*",
         "Device":"eth0"
      }
   ],
   "errors":""
}

Partition Details

To fetch the partition details, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/partitions

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/partitions

Platform Details

To fetch the details of the platform on which the system is installed, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/platform

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/platform

Respose:

{
   "success":true,
   "message":{
      "Platform":"photon",
      "Family":"",
      "Version":"4.0"
   },
   "errors":""
} 

Swap Memory Details

To fetch the swap memory details, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/swapmemory

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/swapmemory

Response:

{
   "success":true,
   "message":{
      "total":0,
      "used":0,
      "free":0,
      "usedPercent":0,
      "sin":0,
      "sout":0,
      "pgIn":0,
      "pgOut":0,
      "pgFault":0,
      "pgMajFault":0
   },
   "errors":""
}

Input/Output Details of all Disk Partitions

To fetch the input/output (read/write) details of all the disk partition, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/iocounters

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/proc/iocounters

Response:

{
   "success":true,
   "message":{
      "loop0":{
         "readCount":16407,
         "mergedReadCount":0,
         "writeCount":0,
         "mergedWriteCount":0,
         "readBytes":3999833088,
         "writeBytes":0,
         "readTime":6294,
         "writeTime":0,
         "iopsInProgress":0,
         "ioTime":9088,
         "weightedIO":6294,
         "name":"loop0",
         "serialNumber":"",
         "label":""
      },
      "sda":{
         "readCount":85357,
         "mergedReadCount":13672,
         "writeCount":212568,
         "mergedWriteCount":783168,
         "readBytes":5029398016,
         "writeBytes":44981511680,
         "readTime":54628,
         "writeTime":17939082,
         "iopsInProgress":0,
         "ioTime":301572,
         "weightedIO":17993710,
         "name":"sda",
         "serialNumber":"",
         "label":""
      },
      "sda1":{
         "readCount":351,
         "mergedReadCount":0,
         "writeCount":0,
         "mergedWriteCount":0,
         "readBytes":1437696,
         "writeBytes":0,
         "readTime":33,
         "writeTime":0,
         "iopsInProgress":0,
         "ioTime":152,
         "weightedIO":33,
         "name":"sda1",
         "serialNumber":"",
         "label":""
      },
      "sda2":{
         "readCount":128,
         "mergedReadCount":23,
         "writeCount":1,
         "mergedWriteCount":0,
         "readBytes":916480,
         "writeBytes":512,
         "readTime":38,
         "writeTime":0,
         "iopsInProgress":0,
         "ioTime":56,
         "weightedIO":38,
         "name":"sda2",
         "serialNumber":"",
         "label":""
      },
      "sda3":{
         "readCount":84806,
         "mergedReadCount":13649,
         "writeCount":212567,
         "mergedWriteCount":783168,
         "readBytes":5025352192,
         "writeBytes":44981511168,
         "readTime":54540,
         "writeTime":17939082,
         "iopsInProgress":0,
         "ioTime":301444,
         "weightedIO":17993623,
         "name":"sda3",
         "serialNumber":"",
         "label":""
      },
      "sr0":{
         "readCount":7,
         "mergedReadCount":0,
         "writeCount":0,
         "mergedWriteCount":0,
         "readBytes":1024,
         "writeBytes":0,
         "readTime":0,
         "writeTime":0,
         "iopsInProgress":0,
         "ioTime":12,
         "weightedIO":0,
         "name":"sr0",
         "serialNumber":"",
         "label":""
      }
   },
   "errors":""
}

sysctl Configuration Details Using pmctl Tool

You can use the pmctl tool to fetch the sysctl configuration details. The following section lists the commands related to various use cases of sysctl configuration.

sysctl Configuration Details

To fetch all the sysctl configuration details in the system, use the following command in the pmctl tool:

pmctl status sysctl

Specific Variable Configuration in sysctl

To fetch a specific variable configuration in the sysctl configuration, use the following command in the pmctl tool:

pmctl status sysctl k <InputKey>

or

pmctl status sysctl key <InputKey>

Example:

>pmctl status sysctl k fs.file-max
fs.file-max: 9223372036854775807

Variable Configuration in sysctl

To fetch all the variable configuration in the sysctl configuration based on the input pattern, use the following command in the pmctl tool:

pmctl status sysctl p <InputPatern>

or

pmctl status sysctl pattern <InputPatern>

Example:

pmctl status sysctl p net.ipv6.route.gc{
   "net.ipv6.route.gc_elasticity":"9",
   "net.ipv6.route.gc_interval":"30",
   "net.ipv6.route.gc_min_interval":"0",
   "net.ipv6.route.gc_min_interval_ms":"500",
   "net.ipv6.route.gc_thresh":"1024",
   "net.ipv6.route.gc_timeout":"60"
}

Add or Update Variable Configuration in sysctl

To add or Update a variable configuration in the sysctl configuration, use the following command in the pmctl tool.

pmctl sysctl u -k <InputKey> -v <InputValue> -f <InputFile>

or

pmctl sysctl update key <InputKey> value <InputValue> filename <InputFile>

Examples:

pmctl sysctl u -k fs.file-max -v 65566 -f 99-sysctl.conf

pmctl sysctl u -k fs.file-max -v 65566

Remove Variable Configuration in sysctl

To remove a variable configuration in the sysctl configuration, use the following command in the pmctl tool:

pmctl sysctl r -k <InputKey> -f <InputFile>

or

pmctl sysctl remove key <InputKey> filename <InputFile>

Examples:

pmctl sysctl r -k fs.file-max -f 99-sysctl.conf

pmctl sysctl r -k fs.file-max

Load sysctl Configuration Files

To Load sysctl configuration files, use the following command in the pmctl tool:

pmctl sysctl l -f <InputfileList>

or

pmctl sysctl load files <InputFileList>

Examples:

pmctl sysctl l -f 99-sysctl.conf,70-sysctl.conf

pmctl sysctl l -f

sysctl Configuration Details Using Curl Command

sysctl Configuration

To fetch the sysctl configuration, execute a GET request in the following JSON format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET http://localhost/api/v1/system/sysctl/statusall

Example:

>curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET http://localhost/api/v1/system/sysctl/statusall

Specific Variable Configuration in sysctl

To fetch a specific variable configuration from sysctl configuration, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET --data '{"key":"<keyName>"}' http://localhost/api/v1/system/sysctl/status

Example:

>curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET --data '{"key":"fs.file-max"}' http://localhost/api/v1/system/sysctl/status

Variable Configuration in sysctl

To fetch all the variable configuration in sysctl, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET --data '{"pattern":"<Pattern>"}' http://localhost/api/v1/system/sysctl/statuspattern


>curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET --data '{"pattern":"fs.file"}' http://localhost/api/v1/system/sysctl/statuspattern

Add or Update Variable Configuration in sysctl Confiiguration

To add or update a variable configuration in the sysctl configuration, execute a POST request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request POST --data '{"apply":true,"key":"<keyName>","value":"<Value>","filename":"<fileName>"}' http://localhost/api/v1/system/sysctl/update

Example:

>curl --unix-socket /run/photon-mgmt/mgmt.sock --request POST --data '{"apply":true,"key":"fs.file-max","value":"65409","filename":"99-sysctl.conf"}' http://localhost/api/v1/system/sysctl/update

Remove a Variable Configuration in sysctl Configuration

To remove a variable configuration from the sysctl configuration, execute a DELETE request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request DELETE --data '{"apply":true,"key":"<keyName>","filename":"<fileName>"}' http://localhost/api/v1/system/sysctl/remove

Example:

>curl --unix-socket /run/photon-mgmt/mgmt.sock --request DELETE --data '{"apply":true,"key":"fs.file-max","filename":"99-sysctl.conf"}' http://localhost/api/v1/system/sysctl/remove

Load sysctl Configuration Files

To load sysctl configuration files, execute a POST request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request POST --data '{"apply":true,"files":["<fileName>","<fileName>"]}' http://localhost/api/v1/system/sysctl/load

Example:

>curl --unix-socket /run/photon-mgmt/mgmt.sock --request POST --data '{"apply":true,"files":["99-sysctl.conf","75-sysctl.conf"]}' http://localhost/api/v1/system/sysctl/load

15.4.3 - Network Management

GET Method

Network Details

To fetch complete network details, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET http://localhost/api/v1/network/describe | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 5238 0 5238 0 0 88919 0 --:--:-- --:--:-- --:--:-- 90310

Response:

{
   "success":true,
   "message":{
      "NetworDescribe":{
         "AddressState":"routable",
         "CarrierState":"carrier",
         "OperationalState":"routable",
         "OnlineState":"",
         "IPv4AddressState":"",
         "IPv6AddressState":"",
         "DNS":[
            "10.142.7.1",
            "10.132.7.1",
            "10.166.17.90"
         ],
         "Domains":null,
         "RouteDomains":null,
         "NTP":[
            "10.128.152.81",
            "10.166.1.120",
            "10.188.26.119",
            "10.84.55.42"
         ]
      },
      "LinksDescribe":{
         "Interfaces":[
            {
               "AddressState":"off",
               "AlternativeNames":null,
               "CarrierState":"carrier",
               "Driver":"",
               "IPv4AddressState":"",
               "IPv6AddressState":"",
               "Index":1,
               "LinkFile":"",
               "Model":"",
               "Name":"lo",
               "OnlineState":"",
               "OperationalState":"carrier",
               "Path":"",
               "SetupState":"unmanaged",
               "Type":"loopback",
               "Vendor":"",
               "Manufacturer":""
            },
            {
               "AddressState":"routable",
               "AlternativeNames":null,
               "CarrierState":"carrier",
               "Driver":"vmxnet3",
               "IPv4AddressState":"",
               "IPv6AddressState":"",
               "Index":2,
               "LinkFile":"",
               "Model":"VMXNET3 Ethernet Controller",
               "Name":"eth0",
               "OnlineState":"",
               "OperationalState":"routable",
               "Path":"pci-0000:0b:00.0",
               "SetupState":"configured",
               "Type":"ether",
               "Vendor":"VMware",
               "Manufacturer":"",
               "NetworkFile":"/etc/systemd/network/99-dhcp-en.network"
            }
         ]
      },
      "links":[
         {
            "Index":1,
            "MTU":65536,
            "TxQLen":1000,
            "Name":"lo",
            "AlternativeNames":"",
            "HardwareAddr":"",
            "Flags":"up|loopback",
            "RawFlags":65609,
            "ParentIndex":0,
            "MasterIndex":0,
            "Namespace":"",
            "Alias":"",
            "Statistics":{
               "RxPackets":168,
               "TxPackets":168,
               "RxBytes":17146,
               "TxBytes":17146,
               "RxErrors":0,
               "TxErrors":0,
               "RxDropped":0,
               "TxDropped":0,
               "Multicast":0,
               "Collisions":0,
               "RxLengthErrors":0,
               "RxOverErrors":0,
               "RxCrcErrors":0,
               "RxFrameErrors":0,
               "RxFifoErrors":0,
               "RxMissedErrors":0,
               "TxAbortedErrors":0,
               "TxCarrierErrors":0,
               "TxFifoErrors":0,
               "TxHeartbeatErrors":0,
               "TxWindowErrors":0,
               "RxCompressed":0,
               "TxCompressed":0
            },
            "Promisc":0,
            "Xdp":{
               "Fd":0,
               "Attached":false,
               "Flags":0,
               "ProgId":0
            },
            "EncapType":"loopback",
            "Protinfo":"",
            "OperState":"unknown",
            "NetNsID":0,
            "NumTxQueues":1,
            "NumRxQueues":1,
            "GSOMaxSize":65536,
            "GSOMaxSegs":65535,
            "Group":0,
            "Slave":""
         },
         {
            "Index":2,
            "MTU":1500,
            "TxQLen":1000,
            "Name":"eth0",
            "AlternativeNames":"",
            "HardwareAddr":"00:0c:29:68:ed:d8",
            "Flags":"up|broadcast|multicast",
            "RawFlags":69699,
            "ParentIndex":0,
            "MasterIndex":0,
            "Namespace":"",
            "Alias":"",
            "Statistics":{
               "RxPackets":179491,
               "TxPackets":25306,
               "RxBytes":281174090,
               "TxBytes":2339627,
               "RxErrors":0,
               "TxErrors":0,
               "RxDropped":120,
               "TxDropped":0,
               "Multicast":0,
               "Collisions":0,
               "RxLengthErrors":0,
               "RxOverErrors":0,
               "RxCrcErrors":0,
               "RxFrameErrors":0,
               "RxFifoErrors":0,
               "RxMissedErrors":0,
               "TxAbortedErrors":0,
               "TxCarrierErrors":0,
               "TxFifoErrors":0,
               "TxHeartbeatErrors":0,
               "TxWindowErrors":0,
               "RxCompressed":0,
               "TxCompressed":0
            },
            "Promisc":0,
            "Xdp":{
               "Fd":0,
               "Attached":false,
               "Flags":0,
               "ProgId":0
            },
            "EncapType":"ether",
            "Protinfo":"",
            "OperState":"up",
            "NetNsID":0,
            "NumTxQueues":8,
            "NumRxQueues":8,
            "GSOMaxSize":65536,
            "GSOMaxSegs":65535,
            "Group":0,
            "Slave":""
         }
      ],
      "Addresses":[
         {
            "Name":"lo",
            "Ifindex":1,
            "OperState":"unknown",
            "Mac":"",
            "MTU":65536,
            "Addresses":[
               {
                  "IP":"127.0.0.1",
                  "Mask":8,
                  "Label":"lo",
                  "Flags":128,
                  "Scope":254,
                  "Peer":"",
                  "Broadcast":"",
                  "PreferedLft":4294967295,
                  "ValidLft":4294967295
               },
               {
                  "IP":"::1",
                  "Mask":128,
                  "Label":"",
                  "Flags":128,
                  "Scope":254,
                  "Peer":"",
                  "Broadcast":"",
                  "PreferedLft":4294967295,
                  "ValidLft":4294967295
               }
            ]
         },
         {
            "Name":"eth0",
            "Ifindex":2,
            "OperState":"up",
            "Mac":"00:0c:29:68:ed:d8",
            "MTU":1500,
            "Addresses":[
               {
                  "IP":"10.197.103.42",
                  "Mask":23,
                  "Label":"eth0",
                  "Flags":0,
                  "Scope":0,
                  "Peer":"",
                  "Broadcast":"10.197.103.255",
                  "PreferedLft":3927,
                  "ValidLft":3927
               },
               {
                  "IP":"fe80::20c:29ff:fe68:edd8",
                  "Mask":64,
                  "Label":"",
                  "Flags":128,
                  "Scope":253,
                  "Peer":"",
                  "Broadcast":"",
                  "PreferedLft":4294967295,
                  "ValidLft":4294967295
               }
            ]
         }
      ],
      "Routes":[
         {
            "LinkName":"eth0",
            "LinkIndex":2,
            "ILinkIndex":0,
            "Scope":0,
            "Dst":{
               "IP":"",
               "Mask":0
            },
            "Src":"10.197.103.42",
            "Gw":"10.197.103.253",
            "MultiPath":"",
            "Protocol":16,
            "Priority":1024,
            "Table":254,
            "Type":1,
            "Tos":0,
            "Flags":null,
            "MPLSDst":"",
            "NewDst":"",
            "Encap":"",
            "MTU":0,
            "AdvMSS":0,
            "Hoplimit":0
         },
         {
            "LinkName":"eth0",
            "LinkIndex":2,
            "ILinkIndex":0,
            "Scope":253,
            "Dst":{
               "IP":"10.197.102.0",
               "Mask":23
            },
            "Src":"10.197.103.42",
            "Gw":"",
            "MultiPath":"",
            "Protocol":2,
            "Priority":0,
            "Table":254,
            "Type":1,
            "Tos":0,
            "Flags":null,
            "MPLSDst":"",
            "NewDst":"",
            "Encap":"",
            "MTU":0,
            "AdvMSS":0,
            "Hoplimit":0
         },
         {
            "LinkName":"eth0",
            "LinkIndex":2,
            "ILinkIndex":0,
            "Scope":253,
            "Dst":{
               "IP":"10.197.103.253",
               "Mask":32
            },
            "Src":"10.197.103.42",
            "Gw":"",
            "MultiPath":"",
            "Protocol":16,
            "Priority":1024,
            "Table":254,
            "Type":1,
            "Tos":0,
            "Flags":null,
            "MPLSDst":"",
            "NewDst":"",
            "Encap":"",
            "MTU":0,
            "AdvMSS":0,
            "Hoplimit":0
         },
         {
            "LinkName":"lo",
            "LinkIndex":1,
            "ILinkIndex":0,
            "Scope":0,
            "Dst":{
               "IP":"::1",
               "Mask":128
            },
            "Src":"",
            "Gw":"",
            "MultiPath":"",
            "Protocol":2,
            "Priority":256,
            "Table":254,
            "Type":1,
            "Tos":0,
            "Flags":null,
            "MPLSDst":"",
            "NewDst":"",
            "Encap":"",
            "MTU":0,
            "AdvMSS":0,
            "Hoplimit":0
         },
         {
            "LinkName":"eth0",
            "LinkIndex":2,
            "ILinkIndex":0,
            "Scope":0,
            "Dst":{
               "IP":"fe80::",
               "Mask":64
            },
            "Src":"",
            "Gw":"",
            "MultiPath":"",
            "Protocol":2,
            "Priority":256,
            "Table":254,
            "Type":1,
            "Tos":0,
            "Flags":null,
            "MPLSDst":"",
            "NewDst":"",
            "Encap":"",
            "MTU":0,
            "AdvMSS":0,
            "Hoplimit":0
         }
      ],
      "Dns":[
         {
            "Link":"eth0",
            "Family":2,
            "Dns":"10.142.7.1"
         },
         {
            "Link":"eth0",
            "Family":2,
            "Dns":"10.132.7.1"
         },
         {
            "Link":"eth0",
            "Family":2,
            "Dns":"10.166.17.90"
         }
      ],
      "Domains":null,
      "NTP":{
         "ServerName":"",
         "Family":0,
         "ServerAddress":"",
         "SystemNTPServers":null,
         "LinkNTPServers":[
            "10.128.152.81",
            "10.166.1.120",
            "10.188.26.119",
            "10.84.55.42"
         ]
      }
   },
   "errors":""
}

Route Details

To fetch the route details, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/network/netlink/route

Example:

root@photon [ ~/4.0/photon ]# curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/network/netlink/route | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1407 100 1407 0 0 996k 0 --:--:-- --:--:-- --:--:-- 1374k

Response:

{
   "success":true,
   "message":[
      {
         "LinkName":"eth0",
         "LinkIndex":2,
         "ILinkIndex":0,
         "Scope":0,
         "Dst":{
            "IP":"",
            "Mask":0
         },
         "Src":"10.197.103.42",
         "Gw":"10.197.103.253",
         "MultiPath":"",
         "Protocol":16,
         "Priority":1024,
         "Table":254,
         "Type":1,
         "Tos":0,
         "Flags":null,
         "MPLSDst":"",
         "NewDst":"",
         "Encap":"",
         "MTU":0,
         "AdvMSS":0,
         "Hoplimit":0
      },
      {
         "LinkName":"eth0",
         "LinkIndex":2,
         "ILinkIndex":0,
         "Scope":253,
         "Dst":{
            "IP":"10.197.102.0",
            "Mask":23
         },
         "Src":"10.197.103.42",
         "Gw":"",
         "MultiPath":"",
         "Protocol":2,
         "Priority":0,
         "Table":254,
         "Type":1,
         "Tos":0,
         "Flags":null,
         "MPLSDst":"",
         "NewDst":"",
         "Encap":"",
         "MTU":0,
         "AdvMSS":0,
         "Hoplimit":0
      },
      {
         "LinkName":"eth0",
         "LinkIndex":2,
         "ILinkIndex":0,
         "Scope":253,
         "Dst":{
            "IP":"10.197.103.253",
            "Mask":32
         },
         "Src":"10.197.103.42",
         "Gw":"",
         "MultiPath":"",
         "Protocol":16,
         "Priority":1024,
         "Table":254,
         "Type":1,
         "Tos":0,
         "Flags":null,
         "MPLSDst":"",
         "NewDst":"",
         "Encap":"",
         "MTU":0,
         "AdvMSS":0,
         "Hoplimit":0
      },
      {
         "LinkName":"lo",
         "LinkIndex":1,
         "ILinkIndex":0,
         "Scope":0,
         "Dst":{
            "IP":"::1",
            "Mask":128
         },
         "Src":"",
         "Gw":"",
         "MultiPath":"",
         "Protocol":2,
         "Priority":256,
         "Table":254,
         "Type":1,
         "Tos":0,
         "Flags":null,
         "MPLSDst":"",
         "NewDst":"",
         "Encap":"",
         "MTU":0,
         "AdvMSS":0,
         "Hoplimit":0
      },
      {
         "LinkName":"eth0",
         "LinkIndex":2,
         "ILinkIndex":0,
         "Scope":0,
         "Dst":{
            "IP":"fe80::",
            "Mask":64
         },
         "Src":"",
         "Gw":"",
         "MultiPath":"",
         "Protocol":2,
         "Priority":256,
         "Table":254,
         "Type":1,
         "Tos":0,
         "Flags":null,
         "MPLSDst":"",
         "NewDst":"",
         "Encap":"",
         "MTU":0,
         "AdvMSS":0,
         "Hoplimit":0
      }
   ],
   "errors":""
}

To fetch all the interfaces links details (such as interface, mac address, and transaction), execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/network/netlink/link

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock http://localhost/api/v1/network/netlink/link

Response:

{
   "success":true,
   "message":[
      {
         "Index":1,
         "MTU":65536,
         "TxQLen":1000,
         "Name":"lo",
         "AlternativeNames":"",
         "HardwareAddr":"",
         "Flags":"up|loopback",
         "RawFlags":65609,
         "ParentIndex":0,
         "MasterIndex":0,
         "Namespace":"",
         "Alias":"",
         "Statistics":{
            "RxPackets":168,
            "TxPackets":168,
            "RxBytes":17146,
            "TxBytes":17146,
            "RxErrors":0,
            "TxErrors":0,
            "RxDropped":0,
            "TxDropped":0,
            "Multicast":0,
            "Collisions":0,
            "RxLengthErrors":0,
            "RxOverErrors":0,
            "RxCrcErrors":0,
            "RxFrameErrors":0,
            "RxFifoErrors":0,
            "RxMissedErrors":0,
            "TxAbortedErrors":0,
            "TxCarrierErrors":0,
            "TxFifoErrors":0,
            "TxHeartbeatErrors":0,
            "TxWindowErrors":0,
            "RxCompressed":0,
            "TxCompressed":0
         },
         "Promisc":0,
         "Xdp":{
            "Fd":0,
            "Attached":false,
            "Flags":0,
            "ProgId":0
         },
         "EncapType":"loopback",
         "Protinfo":"",
         "OperState":"unknown",
         "NetNsID":0,
         "NumTxQueues":1,
         "NumRxQueues":1,
         "GSOMaxSize":65536,
         "GSOMaxSegs":65535,
         "Group":0,
         "Slave":""
      },
      {
         "Index":2,
         "MTU":1500,
         "TxQLen":1000,
         "Name":"eth0",
         "AlternativeNames":"",
         "HardwareAddr":"00:0c:29:68:ed:d8",
         "Flags":"up|broadcast|multicast",
         "RawFlags":69699,
         "ParentIndex":0,
         "MasterIndex":0,
         "Namespace":"",
         "Alias":"",
         "Statistics":{
            "RxPackets":226492,
            "TxPackets":25740,
            "RxBytes":289546384,
            "TxBytes":2689948,
            "RxErrors":0,
            "TxErrors":0,
            "RxDropped":120,
            "TxDropped":0,
            "Multicast":0,
            "Collisions":0,
            "RxLengthErrors":0,
            "RxOverErrors":0,
            "RxCrcErrors":0,
            "RxFrameErrors":0,
            "RxFifoErrors":0,
            "RxMissedErrors":0,
            "TxAbortedErrors":0,
            "TxCarrierErrors":0,
            "TxFifoErrors":0,
            "TxHeartbeatErrors":0,
            "TxWindowErrors":0,
            "RxCompressed":0,
            "TxCompressed":0
         },
         "Promisc":0,
         "Xdp":{
            "Fd":0,
            "Attached":false,
            "Flags":0,
            "ProgId":0
         },
         "EncapType":"ether",
         "Protinfo":"",
         "OperState":"up",
         "NetNsID":0,
         "NumTxQueues":8,
         "NumRxQueues":8,
         "GSOMaxSize":65536,
         "GSOMaxSegs":65535,
         "Group":0,
         "Slave":""
      }
   ],
   "errors":""
}

Network DNS Status

To fetch the network DNS status, use the following command in pmctl:

>pmctl status network dns
Global

        DNS: 8.8.8.1 8.8.8.2 
DNS Domains: test3.com test4.com . localdomain . localdomain 
Link 2 (ens33)
Current DNS Server:  172.16.61.2
       DNS Servers:  172.16.61.2

Link 3 (ens37)
Current DNS Server:  172.16.61.2
       DNS Servers:  172.16.61.2

Network iostat Status

To fetch the network iostat status, use the following command in pmctl:

> pmctl status network iostat
            Name: lo
Packets received: 7510
  Bytes received: 7510
      Bytes sent: 7510
         Drop in: 7510
        Drop out: 0
        Error in: 0
       Error out: 0
         Fifo in: 0
        Fifo out: 0

            Name: ens33
Packets received: 46014
  Bytes received: 19072
      Bytes sent: 19072
         Drop in: 19072
        Drop out: 0
        Error in: 0
       Error out: 0
         Fifo in: 0
        Fifo out: 0

            Name: ens37
Packets received: 9682
  Bytes received: 10779
      Bytes sent: 10779
         Drop in: 10779
        Drop out: 0
        Error in: 0
       Error out: 0
         Fifo in: 0
        Fifo out: 0

Network interfaces status

To fetch the network status of the network interfaces, use the following command in pmctl:

> pmctl status network interfaces
            Name: lo
           Index: 1
             MTU: 65536
           Flags: up loopback
Hardware Address: 
       Addresses: 127.0.0.1/8 ::1/128

            Name: ens33
           Index: 2
             MTU: 1500
           Flags: up broadcast multicast
Hardware Address: 00:0c:29:7c:6f:84
       Addresses: 172.16.61.128/24 fe80::c099:2598:cc4c:14d1/64

            Name: ens37
           Index: 3
             MTU: 1500
           Flags: up broadcast multicast
Hardware Address: 00:0c:29:7c:6f:8e
       Addresses: 172.16.61.134/24 fe80::be9:7746:7729:3e2/64

You can configure the network links using pmctl command. The following section lists the commands you can use to configure network links.

Configure Network dhcp

pmctl network set-dhcp <deviceName> <DHCPMode>

Example:

>pmctl network set-dhcp ens37 ipv4

Configure network linkLocalAddressing

pmctl network set-link-local-addr <deviceName> <linkLocalAddressingMode>

Example:

>pmctl network set-link-local-addr ens37 ipv4

Configure network multicastDNS

pmctl network set-multicast-dns <deviceName> <MulticastDNSMode>

Example:

>pmctl network set-multicast-dns ens37 resolve

Configure network address

pmctl network add-link-address <deviceName> address <Address> peer <Address> label <labelValue> scope <scopeValue>

Example:

>pmctl network add-link-address ens37 address 192.168.0.15/24 peer 192.168.10.10/24 label ipv4 scope link

Configure network route

pmctl network add-route dev <deviceName> gw <Gateway> gwonlink <GatewayOnlink> src <Source> dest <Destination> prefsrc <preferredSource> table <Table> scope <Scope>

Example:

>pmctl network add-route dev ens33 gw 192.168.1.0 gwonlink no src 192.168.1.15/24 dest 192.168.10.10/24 prefsrc 192.168.8.9 table 1234 scope link

Configure network dns

pmctl network add-dns dev <deviceName> dns <dnslist>

Example:

>pmctl network add-dns dev ens37 dns 8.8.8.8,8.8.4.4,8.8.8.1,8.8.8.2

Configure network domains

pmctl network add-domain dev <deviceName> domains <domainlist>

Example:

>pmctl network add-domain dev ens37 domains test1.com,test2.com,test3.com,test4.com

Configure network ntp

pmctl network add-ntp dev <deviceName> ntp <ntplist>

Example:

>pmctl network add-ntp dev ens37 ntp 198.162.1.15,test3.com

Configure network ipv6AcceptRA

pmctl network set-ipv6-accept-ra <deviceName> <IPv6AcceptRA>

Example:

>pmctl network set-ipv6-accept-ra ens37 false
pmctl network set-link-mode dev <device> mode <unmanagedValue> arp <arpValue> mc <multicastValue> amc <allmulticastValue> pcs <PromiscuousValue> rfo <RequiredForOnline>

Example:

>pmctl network set-link-mode dev ens37 arp 1 mc no amc true pcs yes rfo on
pmctl network set-mtu <deviceName> <mtubytesValue>

Example:

>pmctl network set-mtu ens37 2048
pmctl network set-mac <deviceName> <MACAddress>

Example:

>pmctl network set-gmac ens37 00:a0:de:63:7a:e6
pmctl network set-group <deviceName> <groupValue>

Example:

>pmctl network set-group ens37 2147483647
pmctl network set-rf-online <deviceName> <familyValue>

Example:

>pmctl network set-rf-online ens37 ipv4
pmctl network set-active-policy <deviceName> <policyValue>

Example:

>pmctl network set-active-policy ens37 always-up

Configure network routingPolicyRule

pmctl network add-rule dev <deviceName> tos <TypeOfService> from <Address> to <Address> fwmark <FirewallMark> table <Table> prio <Priority> iif <IncomingInterface> oif <OutgoingInterface> srcport <SourcePort> destport <DestinationPort> ipproto <IPProtocol> invertrule <InvertRule> family <Family> usr <User> suppressprefixlen <SuppressPrefixLength> suppressifgrp <SuppressInterfaceGroup> type <Type>

Example:

>pmctl network add-rule dev ens37 tos 12 from 192.168.1.10/24 to 192.168.2.20/24 fwmark 7/255 table 8 prio 3 iif ens37 oif ens37 srcport 8000-8080 destport 9876 ipproto 17 invertrule yes family ipv4 usr 1001 suppressprefixlen 128 suppressifgrp 2098 type prohibit

Remove network routingPolicyRule

pmctl network delete-rule dev <deviceName> tos <TypeOfService> from <Address> to <Address> fwmark <FirewallMark> table <Table> prio <Priority> iif <IncomingInterface> oif <OutgoingInterface> srcport <SourcePort> destport <DestinationPort> ipproto <IPProtocol> invertrule <InvertRule> family <Family> usr <User> suppressprefixlen <SuppressPrefixLength> suppressifgrp <SuppressInterfaceGroup> type <Type>

Example:

>pmctl network delete-rule dev ens37 tos 12 from 192.168.1.10/24 to 192.168.2.20/24 fwmark 7/255 table 8 prio 3 iif ens37 oif ens37 srcport 8000-8080 destport 9876 ipproto 17 invertrule yes family ipv4 usr 1001 suppressprefixlen 128 suppressifgrp 2098 type prohibit

Configure network DHCPv4 id’s

pmctl network set-dhcpv4-id dev <deviceName> clientid <ClientIdentifier> vendorclassid <VendorClassIdentifier> iaid <IAID>

Example:

>pmctl network set-dhcpv4-id dev ens37 clientid duid vendorclassid 101 iaid 201

Configure network DHCPv4 duid

pmctl network set-dhcpv4-duid dev <deviceName> duidtype <DUIDType> duidrawdata <DUIDRawData>

Example:

>pmctl network set-dhcpv4-duid dev ens37 duidtype vendor duidrawdata af:03:ff:87

Configure network DHCPv4 use options

pmctl network set-dhcpv4-use dev <deviceName> usedns <UseDNS> usentp <UseNTP> usesip <UseSIP> usemtu <UseMTU> usehostname <UseHostname> usedomains <UseDomains> useroutes <UseRoutes> usegateway <UseGateway> usetimezone <UseTimezone>

Example:

>pmctl network set-dhcpv4-use dev ens37 usedns false usentp false usesip false usemtu yes usehostname true usedomains yes useroutes no usegateway yes usetimezone no

Configure network DHCPv6

pmctl network set-dhcpv6 dev <deviceName> mudurl <MUDURL> userclass <UserClass> vendorclass <VendorClass> prefixhint <IPV6ADDRESS> withoutra <WithoutRA>

Example:

>pmctl network set-dhcpv6 dev ens37 mudurl https://example.com/devB userclass usrcls1,usrcls2 vendorclass vdrcls1 prefixhint 2001:db1:fff::/64 withoutra solicit

Configure network DHCPv6 id’s

pmctl network set-dhcpv6-id dev <deviceName> iaid <IAID> duidtype <DUIDType> duidrawdata <DUIDRawData>

Example:

>pmctl network set-dhcpv6-id dev ens37 iaid 201 duidtype vendor duidrawdata af:03:ff:87

Configure network DHCPv6 Use

pmctl network set-dhcpv6-use dev <deviceName> useaddr <UseAddress> useprefix <UsePrefix> usedns <UseDNS> usentp <UseNTP> usehostname <UseHostname> usedomains <UseDomains>

Example:

>pmctl network set-dhcpv6-use dev ens37 useaddr yes useprefix no usedns false usentp false usehostname true usedomains yes

Configure network DHCPv6 Options

pmctl network set-dhcpv6-option dev <deviceName> reqopt <RequestOptions> sendopt <SendOption> sendvendoropt <SendVendorOption>

Example:

>pmctl network set-dhcpv6-option dev ens37 reqopt 10,198,34 sendopt 34563 sendvendoropt 1987653,65,ipv6address,af:03:ff:87

Configure network DHCPServer

pmctl network add-dhcpv4-server dev <Devicename> pool-offset <poolOffset> pool-size <PoolSize> default-lease-time-sec <DefaultLeaseTimeSec> max-lease-time-sec <MaxLeaseTimeSec> dns <DNS> emit-dns <EmitDNS> emit-ntp <EmitNTP> emit-router <EmitRouter>

Example:

>pmctl network add-dhcpv4-server dev ens37 pool-offset 100 pool-size 200 default-lease-time-sec 10 max-lease-time-sec 30 dns 192.168.1.2,192.168.10.10,192.168.20.30 emit-dns yes emit-ntp no emit-router yes

Remove network DHCPServer

pmctl network remove-dhcpv4-server <Devicename>

Example:

>pmctl network remove-dhcpv4-server ens37

Configure network IPv6SendRA

pmctl network add-ipv6ra dev <deviceName> rt-pref <RouterPreference> emit-dns <EmitDNS> dns <DNS> emit-domains <EmitDomains> domains <Domains> dns-lifetime-sec <DNSLifetimeSec> prefix <Prefix> pref-lifetime-sec <PreferredLifetimeSec> valid-lifetime-sec <ValidLifetimeSec> assign <Assign> route <Route> lifetime-sec <LifetimeSec>

Example:

>pmctl network add-ipv6ra dev ens37 rt-pref medium emit-dns yes dns 2002:da8:1::1,2002:da8:2::1 emit-domains yes domains test1.com,test2.com dns-lifetime-sec 100 prefix 2002:da8:1::/64 pref-lifetime-sec 100 valid-lifetime-sec 200 assign yes route 2001:db1:fff::/64 lifetime-sec 1000

Remove network IPv6SendRA

pmctl network remove-ipv6ra <Devicename>

Example:

>pmctl network remove-ipv6ra ens37

Configure Network Device using pmctl

You can configure the network devices using pmctl command. Use the following commands to configure network devices.

Configure VLan

pmctl network create-vlan <vlanName> dev <device> id <vlanId>

Example:

>pmctl network create-vlan vlan1 dev ens37 id 101

Configure Bond

pmctl network create-bond <bondName> dev <device> mode <modeType> thp <TransmitHashPolicyType> ltr <LACPTransmitRateType> mms <MIIMonitorSecTime>

Example:

>pmctl network create-bond bond1 dev ens37,ens38 mode 802.3ad thp layer2+3 ltr slow mms 1s

Configure Bond with default

Example:

>pmctl network create-bond bond1 dev ens37,ens38

Configure Bridge with default

pmctl network create-bridge <bridgeName> dev <device list>

Example:

>pmctl network create-bridge br0 dev ens37,ens38

Configure MacVLan

pmctl network create-macvlan <macvlanName> dev <device> mode <modeName>

Example:

>pmctl network create-macvlan macvlan1 dev ens37 mode private 

Configure IpVLan

pmctl network create-ipvlan <ipvlanName> dev <device> mode <modeName> flags <flagsName>

Example:

>pmctl network create-ipvlan ipvlan1 dev ens37 mode l2 flags vepa

Configure IpVLan with default

Example:

>pmctl network create-ipvlan ipvlan1 dev ens38

Configure VxLan

pmctl network create-vxlan <vxlanName> dev <device> remote <RemoteAddress> local <LocalAddress> group <GroupAddress> destport <DestinationPort> independent <IndependentFlag>

Example:

>pmctl network create-vxlan vxlan1 dev ens37 vni 16777215 remote 192.168.1.3 local 192.168.1.2 group 192.168.0.0 destport 4789 independent no 

Configure WireGuard

pmctl network create-wg <wireguardName> dev <device> skey <privateKey> pkey<publicKey> endpoint <address:Port> port <listenport> ips <allowedIPs>

Example:

>pmctl network create-wg wg1 dev ens37 skey wCmc/74PQpRoxTgqGircVFtdArZFUFIiOoyQY8kVgmI= pkey dSanSzExlryduCwNnAFt+rzpI5fKeHuJx1xx2zxEG2Q= endpoint 10.217.69.88:51820 port 51822 ips fd31:bf08:57cb::/48,192.168.26.0/24

Configure WireGuard with default

Example:

>pmctl network create-wg wg1 dev ens37 skey wCmc/74PQpRoxTgqGircVFtdArZFUFIiOoyQY8kVgmI= pkey dSanSzExlryduCwNnAFt+rzpI5fKeHuJx1xx2zxEG2Q= endpoint 10.217.69.88:51820

Remove Network Device Using pmctl

To remove a network device, use the following command in pmctl:

pmctl network remove-netdev <kindDeviceName> kind <kindType>

Example:

>pmctl network remove-netdev ipvlan1 dev ens37 kind ipvlan

Use the following commands to configure links using the pmctl command.

pmctl link set-mac dev <deviceName> macpolicy <MACAddressPolicy> macaddr <MACAddress>

Example:

>pmctl link set-mac dev eth0 macpolicy none macaddr 00:a0:de:63:7a:e6
pmctl link set-name dev <deviceName> namepolicy <NamePolicy> name <Name>

Example:

>pmctl link set-name dev ens37 namepolicy mac,kernel,database,onboard,keep,slot,path
pmctl link set-name dev <deviceName> altnamespolicy <AlternativeNamesPolicy> altname <AlternativeName>

Example:

>pmctl link set-alt-name dev ens37 altnamespolicy mac,database,onboard,slot,path
pmctl link set-csum-offload dev <deviceName> rco <ReceiveCheksumOffload> tco <TransmitChecksumOffload>

Example:

>pmctl link set-csum-offload dev ens37 rxco true txco true
pmctl link set-tcp-offload dev <deviceName> tcpso <TCPSegmentationOffload> tcp6so <TCP6SegmentationOffload>

Example:

>pmctl link set-tcp-offload dev ens37 tcpso true tcp6so true
pmctl link set-generic-offload dev <deviceName> gso <GenericSegmentationOffload> gro <GenericReceiveOffload> grohw <GenericReceiveOffloadHardware> gsomaxbytes <GenericSegmentOffloadMaxBytes> gsomaxseg <GenericSegementOffloadMaxSegments>

Example:

>pmctl link set-generic-offload dev ens37 gso true gro true grohw false gsomaxbytes 65536 gsomaxseg 65535
pmctl link set-vlan-tags dev <deviceName> rxvlanctaghwacl <ReceiveVLANCTAGHardwareAcceleration> txvlanctaghwacl <TransmitVLANCTAGHardwareAcceleration> rxvlanctagfilter <ReceiveVLANCTAGFilter> txvlanstaghwacl <TransmitVLANSTAGHardwareAcceleration>

Example:

>pmctl link set-vlan-tags dev ens37 rxvlanctaghwacl true txvlanctaghwacl false rxvlanctagfilter true txvlanstaghwacl true

Configure Link Channels

pmctl link set-channel dev <deviceName> rxch <RxChannels> txch <TxChannels> oth <OtherChannels> coch <CombinedChannels>

Example:

>pmctl link set-channel dev ens37 rxch 1024 txch 2045 och 45678 coch 32456
pmctl link set-buffer dev <deviceName> rxbufsz <RxBufferSize> rxmbufsz <RxMiniBufferSize> rxjbufsz <RxJumboBufferSize> txbufsz <TxBufferSize>

Example:

>pmctl link set-buffer dev ens37 rxbufsz 100009 rxmbufsz 1998 rxjbufsz 10999888 txbufsz 83724
pmctl link set-queue dev <deviceName> rxq <ReceiveQueues> txq <TransmitQueues> txqlen <TransmitQueueLength>

Example:

>pmctl link set-queue dev ens37 rxq 4096 txq 4096 txqlen 4294967294
pmctl link set-flow-ctrl dev <deviceName> rxfctrl <RxFlowControl> txfctrl <TxFlowControl> anfctrl <AutoNegotiationFlowControl>

Example:

>pmctl link set-flow-ctrl dev ens37 rxfctrl true txfctrl true anfctrl true
pmctl link set-adpt-coalesce dev <deviceName> uarxc <UseAdaptiveRxCoalesce> uatxc <UseAdaptiveTxCoalesce>

Example:

>pmctl link set-adpt-coalesce dev ens37 uarxc true uatxc true
pmctl link set-rx-coalesce dev <deviceName> rxcs <RxCoalesceSec> rxcsirq <RxCoalesceIrqSec> rxcslow <RxCoalesceLowSec> rxcshigh <RxCoalesceHighSec>

Example:

>pmctl link set-rx-coalesce dev ens37 rxcs 23 rxcsirq 56 rxcslow 5 rxcshigh 76788
pmctl link set-tx-coalesce dev <deviceName> txcs <TxCoalesceSec> txcsirq <TxCoalesceIrqSec> txcslow <TxCoalesceLowSec> txcshigh <TxCoalesceHighSec>

Example:

>pmctl link set-tx-coalesce dev ens37 txcs 23 txcsirq 56 txcslow 5 txcshigh 76788
pmctl link set-rx-coald-frames dev <deviceName> rxcmf <RxMaxCoalescedFrames> rxcmfirq <RxMaxCoalescedIrqFrames> rxcmflow <RxMaxCoalescedLowFrames> rxcmfhigh <RxMaxCoalescedHighFrames>

Example:

>pmctl link set-rx-coald-frames dev ens37 rxmcf 23 rxmcfirq 56 rxmcflow 5 rxmcfhigh 76788
pmctl link set-tx-coald-frames dev <deviceName> txcmf <TxMaxCoalescedFrames> txcmfirq <TxMaxCoalescedIrqFrames> txcmflow <TxMaxCoalescedLowFrames> txcmfhigh <TxMaxCoalescedHighFrames>

Example:

>pmctl link set-tx-coald-frames dev ens37 txmcf 23 txmcfirq 56 txmcflow 5 txmcfhigh 76788
pmctl link set-coalesce-pkt dev <deviceName> cprlow <CoalescePacketRateLow> cprhigh <CoalescePacketRateHigh> cprsis <CoalescePacketRateSampleIntervalSec>

Example:

>pmctl link set-coalesce-pkt dev ens37 cprlow 1000 cprhigh 32456 cprsis 102

You can configure links for Alias, Description, port, duplex, and so on.

pmctl link set-link dev ens37 alias <Alias> desc <Description> mtub <MTUBytes> bits <BitsPerSecond> duplex <Duplex> auton <AutoNegotiation> wol <WakeOnLan> wolpassd <WakeOnLanPassword> port <Port> advertise <Advertise> lrxo <LargeReceiveOffload> ntf <NTupleFilter> ssbcs <StatisticsBlockCoalesceSec>

Example:

>pmctl link set-link dev ens37 alias ifalias desc configdevice mtub 10M bits 5G duplex full auton no wol phy,unicast,broadcast,multicast,arp,magic,secureon wolpassd cb:a9:87:65:43:21  port mii advertise 10baset-half,10baset-full,20000basemld2-full lrxo true ntf true ssbcs 1024

Ethtool status

To fetch the Ethtool Status, use the following command:


\#Get Ethtool all status 

	pmctl status ethtool <LINK>

Example: 

	>pmctl status ethtool ens37

\#Get Ethtool status based on action

	pmctl status ethtool <LINK> <ACTION>

Example:

	>pmctl status ethtool ens37 bus

15.4.4 - User, Group, and Host Management

POST Method

Add a Group

To add a group, execute a POST request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request POST --data '{"Name":"photon","Gid":"1125"}' http://localhost/api/v1/system/group/add

The following table lists the parameter:

ParameterDescription
GidID of the group that you want to add.
NameName of the group that you want to add.

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request POST --data '{"Name":"photon","Gid":"1125"}' http://localhost/api/v1/system/group/add

Response:

{
   "success":true,
   "message":"group added",
   "errors":""
}

Add a User

To add a user, execute a POST request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request POST --data '{"Name":"photon1"}' http://localhost/api/v1/system/user/add

The following table lists the parameter:

ParameterDescription
NameName of the user you want to add.

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request POST --data '{"Name":"photon1"}' http://localhost/api/v1/system/user/add

DELETE Method

Remove a Group

To remove a group, execute a DELETE request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request DELETE --data '{"Name":"photon","Gid":"1125"}' http://localhost/api/v1/system/group/remove

The following table lists the parameters:

ParameterDescription
NameName of the group you want to delete.
GidID of the group that you want to delete.

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request DELETE --data '{"Name":"photon22"}' http://localhost/api/v1/system/group/remove

Response:

{
   "success":true,
   "message":"group removed",
   "errors":""
}

Remove a User

To remove a user, execute a DELETE request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request DELETE --data '{"Name":"photon1"}' http://localhost/api/v1/system/user/remove

Response

{
   "success":true,
   "message":"user removed",
   "errors":""
}

PUT Method

Modify Group

To modify the name of a group, execute a PUT request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request PUT --data '{"Name":"photon6","NewName":"photon33"}' http://localhost/api/v1/system/group/modify

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request PUT --data '{"Name":"photon6","NewName":"photon33"}' http://localhost/api/v1/system/group/modify

GET Method

Host Details

To fetch the details of the host, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET http://localhost/api/v1/system/hostname/describe

Example:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET http://localhost/api/v1/system/hostname/describe | jq % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 585 100 585 0 0 8374 0 --:--:-- --:--:-- --:--:-- 8478

Login Status

You can use the pmctl tool to get login details of users. The following section lists the commands you can use to get the user details.

List Users

To list all the logged in users, use the following command in the pmctl tool:

>pmctl status login user

List Sessions

To list all the logged in sessions, use the following command in the pmctl tool:

>pmctl status login session

Get User based on UID

To get the status of users based on user ID, use pmctl command in the following format:

pmctl status login user <UID>

Example:

>pmctl status login user 2

Get Session based on ID

To get the status of logged in sessions based on the users ID, use the pmctl command in the following format:

pmctl status login session <ID>

Example:

>pmctl status login session 1000

Group Details Using pmctl tool

You can get the group details using commands in pmctl tools. The following section lists the commands you can use in the pmctl tool to get various group details.

Get all Group Details

To fetch all the group details, use the following command in the the pmctl tool.

>pmctl status group
             Gid: 0
            Name: root

             Gid: 1
            Name: daemon

             Gid: 2
            Name: bin

             Gid: 3
            Name: sys

             Gid: 4
            Name: adm
		    .
            .
            .
             Gid: 1001
            Name: photon-mgmt

Get specific Group Details

To fetch specific group details, use the following commands in the pmctl tool:

pmctl status group <GroupName>

or

pmctl status group <GroupName>

Example:

>pmctl status group photon-mgmt
             Gid: 1001
            Name: photon-mgmt

Add a new Group

To add a new group, use the following command in the pmctl tool:

pmctl group add <GroupName> <Gid>

or

pmctl group add <GroupName>

Remove a Group

To remove a group, us the followong command in the omctl tool:

pmctl group remove <GroupName> <Gid>

or

pmctl group remove <GroupName>

Group Details Using cURL command

The following section list the cURL commands that you can use to fetch the groups details.

Get all Group information

To fetch the group details, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET http://localhost/api/v1/system/group/view

Get particuller Group information.

To fetch a specific group details, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET http://localhost/api/v1/system/group/view/<GroupName>

User Details Using pmctl Tool

You can use the pmctl tool to get the user details. The following section lists the commands to get the user details.

Get all User Details

To get all the user details, use the following command in the pmctl tool:

>pmctl status user
          User Name: root
                Uid: 0
                Gid: 0
              GECOS: root
     Home Directory: /root

          User Name: daemon
                Uid: 1
                Gid: 1
              GECOS: daemon
     Home Directory: /usr/sbin

          User Name: bin
                Uid: 2
                Gid: 2
              GECOS: bin
     Home Directory: /bin

          User Name: sys
                Uid: 3
                Gid: 3
              GECOS: sys
     Home Directory: /dev

          User Name: photon-mgmt
                Uid: 1001
                Gid: 1001
     Home Directory: /home/photon-mgmt

Add a New User

To add a new user, use the following command in the pmctl tool:

pmctl user add <UserName> home-dir <HomeDir> groups <groupsList> uid <Uid> gid <Gid> shell <Shell> password <xxxxxxx>

or

pmctl user a <UserName> -d <HomeDir> -grp <groupsList> -u <Uid> -g <Gid> -s <Shell> -p <xxxxxxx>

Remove a User

To remove a user, use the following command in the pmctl tool:

pmctl user remove <UserName>

or

pmctl user r <UserName>

GET User Details

To fetch user details, execute a GET request in the following format:

curl --unix-socket /run/photon-mgmt/mgmt.sock --request GET http://localhost/api/v1/system/user/view

15.4.5 - Package Management

You can use the pmctl commands to manage the available packages and perform various actions on the packages. The following section lists the pmctl commands for various services related to package management.

List all packages

To list all the packages, use the following command in pmctl:

pmctl pkg list

Example:

>pmctl pkg list

List specific packages

To list a specific package, use the following command in pmctl:

pmctl pkg list <pkg>

Example:

>pmctl pkg list lsof

Package Details

To get the details of a specific package, use the following command in pmctl:

pmctl pkg info <pkg>

Example:

pmctl pkg info lsof

Download metadata

To download the package metadata, use the following command in pmctl:

pmctl pkg makecache

Example:

>pmctl pkg makecache

Clean cache

To clean the package cache, use the following command in pmctl:

pmctl pkg clean

Example:

>pmctl pkg clean

List repositories

To list the repositories, use the following command in pmctl:

pmctl pkg repolist

Example:

pmctl pkg repolist

Search packages

To search a specific package, use the following command in pmctl:

pmctl pkg search <pattern>

Example:

pmctl pkg search lsof

Get update info

To get the update details of the packages, use the following commands in pmctl:

> pmctl pkg updateinfo
> pmctl pkg updateinfo --list
> pmctl pkg updateinfo --info

Install a package

To install a specific package, use the following command in pmctl:

pmctl pkg install <pkg>

Example:

>pmctl install lsof

Update a package

To update a specific package, use the following command in pmctl:

pmctl pkg update <pkg>

Example:

pmctl pkg update lsof

Remove a package

To remove a specific package, use the following command in pmctl:

pmctl pkg remove <pkg>

Example:

pmctl pkg remove lsof

Update all

To update all the packages, use th following command in pmctl:

pmctl pkg update

Example:

pmctl pkg update

Common options

In pmctl, run commands in the following format to use other common options:

> pmctl pkg [--allowerasing][--best][--cacheonly][--config=<file>][--disablerepo=<pattern>[,..]]
	[--disableexcludes][--downloaddir=<dir>][--downloadonly][--enablerepo=<pattern>[,..]]
	[--exclude=<pkg>][--installroot=<dir>][--noautoremove][--nogpgcheck][--noplugins]
	[--rebootrequired][--refresh][--releaserver=<release>][--repoid=<repo>]
	[--repofrompath=<repo>,<dir>][--security][--secseverity=<sev>][--setopt=<key=value>[,..]]
	[--skipconflicts][--skipdigest][--skipobsletes][--skipsignature]
pmctl pkg --repoid=photon-debuginfo list lsof*

15.4.6 - Firewall nftables Management

Use pmctl command to manage the firewall nftables. The following section lists the command that you can use to manage the nftables.

Add nftable

To add an nftable, use the following command in pmctl:

pmctl network add-nft-table name <TABLE> family <FAMILY>

Example:

>pmctl network add-nft-table name test99 family inet

Delete nftable

To delete an nftable, use the following command in pmctl:

pmctl network delete-nft-table name <TABLE> family <FAMILY>

Example:

>pmctl network delete-nft-table name test99 family inet

Show nftable

To show an nftable, use the following command in pmctl:

pmctl network show-nft-table name <TABLE> family <FAMILY>

Example:

>pmctl network show-nft-table name test99 family inet

Show all nftables

To show all the nftables, use the following command in pmctl:

>pmctl network show-nft-table

Add nftable chain

To add an nftable chain, use the following command in pmctl:

pmctl network add-nft-chain name <CHAIN> table <TABLE> family <FAMILY> hook <HOOK> priority <PRIORITY> type <TYPE> policy <POLICY>

Example:

>pmctl network add-nft-chain name chain1 table test99 family inet hook input priority 300 type filter policy drop

Delete nft chain

To delete an nftable chain, use the following command in pmctl:

pmctl network delete-nft-chain name <CHAIN> table <TABLE> family <FAMILY>

Example:

>pmctl network delete-nft-chain name chain1 table test99 family inet

Show nft chain

To show an nftable chain, use the following command in pmctl:

pmctl network show-nft-chain name <CHAIN> table <TABLE> family <FAMILY>

Example:

>pmctl network show-nft-chain name chain1 table test99 family inet

Show all nft chain

To show all nftable chains, use the following command in pmctl:

>pmctl network show-nft-chain

Save all nftables

To save all nftables, use the following command in pmctl:

>pmctl network nft-save

Run nft commands

To run the nftables command, use the following command in pmctl:

pmctl network nft-run <COMMAND>

Examples:

>pmctl network nft-run nft add table inet test99


>pmctl network nft-run nft add chain inet test99 my_chain '{ type filter hook input priority 0; }'


>pmctl network nft-run nft add rule inet test99 my_chain tcp dport {telnet, http, https} accept


>pmctl network nft-run nft delete rule inet test99 my_chain handle 3


>pmctl network nft-run nft delete chain inet test99 my_chain


>pmctl network nft-run nft delete table inet test99

15.4.7 - Process Details and Configuration Management

Net device property status

To get the status of the network device property, use the following command in pmctl:

pmctl status proc net path <PATH> property <PROPERTY>

Example:

pmctl status proc net path ipv6 property calipso_cache_bucket_size

Response:

                 Path: ipv6
             Property: calipso_cache_bucket_size
                Value: 10

Net device property configuration

To get the network device property configuration details, use the following command in pmctl:

pmctl proc net path <PATH> property <PROPERTY> value <VALUE>

Example:

>pmctl proc net path ipv6 property calipso_cache_bucket_size value 12

To get the status of the network device link, use the following command in pmctl:

pmctl status proc net path <PATH> dev <LINK> property <PROPERTY>

Example:

>pmctl status proc net path ipv6 dev ens37 property mtu

Response:

                 Path: ipv6
                 Link: ens37
             Property: mtu
                Value: 1300

To get the configuration details of the network device link, use the following command in pmctl:

pmctl proc net path <PATH> dev <LINK> property <PROPERTY> value <VALUE>

Example:

>pmctl proc net path ipv6 dev ens37 property mtu value 1500

VM property status

To get the property status of the virtual machine, use the following command in pmctl:

pmctl status proc vm <PROPERTY>

Example:

>pmctl status proc vm page-cluster

Response:

             Property: page-cluster
                Value: 3

VM property configuration

To get the property configuration details, use the following command in pmctl:

pmctl proc vm <PROPERTY> <VALUE>

Example:

pmctl proc vm page-cluster 5

System property status

To get system property details, use the following command in pmctl:

pmctl status proc system <PROPERTY>

Example:

>pmctl status proc system cpuinfo

ARP status

To get the ARP status details, use the following command in pmctl:

pmctl status proc arp

Example:

>pmctl status proc arp

Response:

         IPAddress: 172.16.61.254
            HWType: 0x1
             Flags: 0x2
         HWAddress: 00:50:56:f3:5d:48
              Mask: *
            Device: ens37

         IPAddress: 172.16.61.254
            HWType: 0x1
             Flags: 0x2
         HWAddress: 00:50:56:f3:5d:48
              Mask: *
            Device: ens33

         IPAddress: 172.16.61.2
            HWType: 0x1
             Flags: 0x2
         HWAddress: 00:50:56:f4:e7:22
              Mask: *
            Device: ens33

         IPAddress: 172.16.61.2
            HWType: 0x1
             Flags: 0x2
         HWAddress: 00:50:56:f4:e7:22
              Mask: *
            Device: ens37

Netstat Details

To get the netstat details, use the following command in pmctl:

pmctl status proc netstat <PROTOCOL>

Example:

>pmctl status proc netstat tcp

Process status

To get the process status details, use the following command in pmctl:

pmctl status proc process <PID> <PROPERTY>

Example:

>pmctl status proc process 88157 pid-memory-percent

Protopidstat status

To get the protopidstat status details, use the following command in pmctl:

pmctl status proc protopidstat <PID> <PROTOCOL>

Example:

>pmctl status proc protopidstat 89502 tcp

15.5 - Writing a Plugin

photon-mgmtd is designed with a robust plugin-based architecture in mind. You can easily add and remove modules to photon-mgmtd. The plugins are separate modules with well-defined interfaces that make implementing application features easier. You can create custom versions of an application with minimal source code modifications.

You can perform the following steps to write a plugin:

  1. Choose a namespace under plugins directory (systemd, system, proc) where you want to put your module.
  2. Write the sub router. For example, plugins/systemd/
  3. Write your module: module.go and module_router.go
  4. Write RegisterRouterModule
  5. Register RegisterRouterModule with the parent router. For example, for login registered with RegisterRouterSystem under system namespace, write login.RegisterRouterLogin.

You can use the pmctl tool to view and configure system, network, and service status. The following example illustrates how to view the status:

Service status:

❯ pmctl service status nginx.service
                  Name: nginx.service 
           Description: The nginx HTTP and reverse proxy server 
               MainPid: 45732 
             LoadState: loaded 
           ActiveState: active 
              SubState: running 
         UnitFileState: disabled 
  StateChangeTimeStamp: Sun Oct 31 12:02:02 IST 2021 
  ActiveEnterTimestamp: Sun Oct 31 12:02:02 IST 2021 
 InactiveExitTimestamp: Sun Oct 31 12:02:02 IST 2021 
   ActiveExitTimestamp: 0 
 InactiveExitTimestamp: Sun Oct 31 12:02:02 IST 2021 
                Active: active (running) since Sun Oct 31 12:02:02 IST 2021

System status:

❯ pmctl status  system
              System Name: Zeus
                   Kernel: Linux (5.14.0-0.rc7.54.fc36.x86_64) #1 SMP Mon Aug 23 13:55:32 UTC 2021
                  Chassis: vm
           Hardware Model: VMware Virtual Platform
          Hardware Vendor: VMware, Inc.
             Product UUID: 979e4d56b63718b18534e112e64cb18
         Operating System: VMware Photon OS/Linux
Operating System Home URL: https://vmware.github.io/photon/
          Systemd Version: v247.10-3.ph4
             Architecture: x86-64
           Virtualization: vmware
            Network State: routable (carrier)
     Network Online State: online
                      DNS: 172.16.130.2
                  Address: 172.16.130.132/24 on link ens33
                           172.16.130.131/24 on link ens33
                           fe80::3279:c56d:55f9:aed7/64 on link ens33
                           172.16.130.138/24 on link ens37
                  Gateway: 172.16.130.2 on link ens37
                           172.16.130.2 on link ens33
                   Uptime: Running Since (2 days, 3 hours, 8 minutes) Booted (Wed Dec 22 15:57:24 IST 2021) Users (9) Proc (284)
                   Memory: Total (13564788736) Used (13564788736) Free (589791232) Available (9723891712)

Network status:

❯ pmctl status network -i ens33
             Name: ens33
Alternative Names: enp2s1
            Index: 2
        Link File: /usr/lib/systemd/network/99-default.link
     Network File: /etc/systemd/network/10-ens33.network
             Type: ether
            State: routable (configured)
           Driver: e1000
           Vendor: Intel Corporation
            Model: 82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Single Port Adapter)
             Path: pci-0000:02:01.0
    Carrier State: carrier
     Online State: online
IPv4Address State: routable
IPv6Address State: degraded
       HW Address: 00:0c:29:5f:d1:39
              MTU: 1500
        OperState: up
            Flags: up|broadcast|multicast
        Addresses: 172.16.130.132/24 172.16.130.131/24 fe80::3279:c56d:55f9:aed7/64
          Gateway: 172.16.130.2
              DNS: 172.16.130.2

16 - Photon OS Installer Overview

The Photon OS Installer is an initiative that aims to separate out installer source code from the Photon project and use it as a python library. You can use this Photon OS Installer project to create a photon-installer binary that can install Photon OS when invoked with the appropriate arguments.

Features

You can use the Photon OS Installer to perform the following tasks:

  • Generate Photon Installer executable
  • Create Photon Images (ISO, GCE, AMI, AZURE, OVA, and so on)
  • Make Photon Installer Source code installable through the pip interface and use it as a python library.

Dependencies

The Photon OS installer has the following dependencies:

Build Dependecies:

  • python3
  • python3-pyinstaller
  • python3-setuptools
  • python3-devel
  • python3-requests
  • python3-cracklib
  • python3-curses

Run time dependecies:

  • dosfstools
  • efibootmgr
  • glibc
  • gptfdisk
  • grub2
  • kpartx
  • lvm2
  • zlib
  • cdrkit
  • findutils

Note: If the architecture is x86, then we need to add grub2-pc also in runtime dependency.

Building from source

To build the Photon OS Installer executable on Photon OS, run the following commands:

➜  ~ tdnf install -y python3 python3-setuptools python3-pyinstaller
➜  ~ git clone https://github.com/vmware/photon-os-installer.git
➜  ~ cd photon-os-installer
➜  ~ pyinstaller --onefile photon-installer.spec

To build the Photon Installer executable on other distros, run the following commands:

➜  ~ pip3 install setuptools pyinstaller
➜  ~ git clone https://github.com/vmware/photon-os-installer.git
➜  ~ cd photon-os-installer
➜  ~ pyinstaller --onefile photon-installer.spec

You can find the generated executable in the dist directory created.

Presently, you can build the following images with the Photon OS Installer:

x86_64arm64
isoiso
ovaova
ova_uefiova_uefi
minimal-iso
rt-iso
ami
gce
azure
rpi3

To build Photon Cloud images using Photon OS Installer, run the following commands:

➜  ~ pip3 install git+https://github.com/vmware/photon-os-installer.git
➜  ~ git clone https://github.com/vmware/photon.git
➜  ~ cd photon
➜  ~ make image IMG_NAME=ami

To use Photon OS Installer as a python library, run the following commands:

import photon_installer
from photon_installer.installer import Installer
import json
with open('path_to_file/config.json') as f:
    install_config = json.load(f)
installer = Installer(working_directory='/root/photon/stage/ova', repo_paths='/root/photon/stage/RPMS', log_path='/root/photon/stage/LOGS')
installer.configure(install_config)
installer.execute()

You can refer to the sample installation configuration files on the following page: Sample Kickstart Files

Developers or contributors can refer to the Photon OS Installer project here: Photo OS Installer