Create Oracle OS Management Hub Custom Software Sources with the OCI CLI

Introduction

Creating your own customized Oracle OS Management Hub software sources is powerful. Using the OCI console, you can apply filters to limit the set of packages and modules to just those you want and create a custom software source or versioned custom software source. Sometimes, using the filters to generate a lengthy set of packages at just the patch level you want is impractical. There is a faster and more streamlined way to create custom and versioned custom software sources using the OCI CLI. OS Management Hub integrates fully with the OCI CLI and the OCI API/SDK, so you can programmatically interact with the service. In this tutorial, you’ll learn how to take a reference package list from an Oracle Linux instance and use the OCI CLI to create a custom or versioned custom software source in OS Management Hub.

Objectives

In this tutorial, you will learn how to:

Prerequisites

Confirm the OCI CLI Version

Once you have the OCI CLI installed, ensure you have at least OCI CLI v3.29.2 or later. You can check the version with:

oci --version

Create a JSON Input Template

Creating a custom software source requires several pieces of information, including:

  1. The name and description of the software source
  2. The auto-update setting or a version designator, depending on the type of custom source you’re making
  3. The vendor software sources to use as the base
  4. The filters to limit the packages included in the custom source

OCI CLI commands can take input as a JSON file and are the best input choice for complex inputs like these. Also, the OCI CLI can tell you the JSON format for each command. For this example, we will work with a custom software source. Use the OCI CLI to output a template of the JSON input needed for the create software source command:

oci os-management-hub software-source create-custom-swsrc --generate-full-command-json-input > my-css.json

The OCI CLI outputs a block of JSON-formatted text, storing the output in the my-css.json file. You can use this JSON template to create a custom software source. Distilled down to the essentials needed to create a custom software source from a reference package list, we have:

{
  "compartmentId": "string",
  "description": "string",
  "displayName": "string",
  "filter": {
    "packageFilters": [
      {
        "filterType": "string",
        "packageName": "string",
        "packageNamePattern": "string",
        "packageVersion": "string"
      },
      {
        "filterType": "string",
        "packageName": "string",
        "packageNamePattern": "string",
        "packageVersion": "string"
      }
    ]
  },
  "vendorSoftwareSources": [
    {
      "displayName": "string",
      "id": "string"
    },
    {
      "displayName": "string",
      "id": "string"
    }
  ],
  "isAutoUpdated": "true"
}

Notice that the JSON template trims away some of the options in the filter area. The goal is a custom software source generated from a list of packages, so only the packageFilters filter type is needed. Let’s explore the JSON template a little further:

All information about the inputs, their formats, and accepted values come from the Data Types in the OS Management Hub API documentation.

Get the Package List

For the packageFilter portion of the JSON, you need to a supply packageName and a packageVersion string. The package version is in the RPM standard e:v-r format (epoch:version-release), and the epoch is optional. Use your reference Oracle Linux system to gather the packages and versions for the filters.

Using an OS Management Hub Managed Instance as the Reference

If OS Management Hub already manages your reference system, use the OCI CLI to get the list of installed packages with their version. You’ll need the OCID of the managed instance, which you can copy from the Managed Instance details screen in the OCI Console. Once you have the instance OCID, fetch the installed packages with the OCI CLI:

oci os-management-hub managed-instance list-installed-packages --managed-instance-id <managed_instance_OCID> --all |grep -E "\"name\":|\"version\":"

For example:

$ oci os-management-hub managed-instance list-installed-packages --managed-instance-id <managed_instance_OCID> --all |grep -E "\"name\":|\"version\":"
        "name": "bind-utils",
        "version": "32:9.11.36-8.el8_8.1"
        "name": "systemd-libs",
        "version": "239-74.0.4.el8_8.2"
        "name": "perf",
        "version": "4.18.0-477.15.1.el8_8"
...

Using Another Oracle Linux System as the Reference

If OS Management Hub does not manage your reference system, use the rpm -qa command to get the packages. Log into the reference system and run:

rpm -qa --queryformat "%{NAME} %{EPOCH}:%{VERSION}-%{RELEASE}\n" | sed 's/(none)://' | grep -v gpg-pubkey

The sed portion of the command cleans up the output for packages that do not have an expressly designated epoch. Notice the command filters out the gpg-pubkey packages. These are auto-generated entries in RPM, not physical packages that reside in a software source. For example:

$ rpm -qa --queryformat "%{NAME} %{EPOCH}:%{VERSION}-%{RELEASE}\n" | sed 's/(none)://' | grep -v gpg-pubkey
libkcapi 1.2.0-2.0.1.el8
libkadm5 1.18.2-22.0.1.el8_7
iptables-libs 1.8.4-24.0.1.el8
libatasmart 0.19-14.el8
libcroco 0.6.12-4.el8_2.1
lmdb-libs 0.9.24-2.el8
...

Get the Vendor Software Sources

Next, gather the information for the vendorSoftwareSources part of the JSON template. You’ll need the displayName and id of each vendor software source required for your custom software source.

Using an OS Management Hub Managed Instance as the Reference

If OS Management Hub already manages your reference system, use the OCI CLI to get the list of attached software sources. You’ll need the OCID of the managed instance, which you can copy from the Managed Instance details screen in the OCI Console. Once you have the instance OCID, fetch the installed packages with the OCI CLI:

oci os-management-hub managed-instance get --managed-instance-id <managed_instance_OCID>

For example:

$ oci os-management-hub managed-instance get --managed-instance-id <managed_instance_OCID>
...
     "software-sources": [
      {
        "description": "Oracle Linux 8 Application Stream (x86_64)",
        "display-name": "ol8_appstream-x86_64",
        "id": "ocid1.osmhsoftwaresource.oc1.iad.ama...",
        "software-source-type": "VENDOR"
      },
      {
        "description": "Latest Unbreakable Enterprise Kernel Release 7 for Oracle Linux 8 (x86_64)",
        "display-name": "ol8_uekr7-x86_64",
        "id": "ocid1.osmhsoftwaresource.oc1.iad.ama...",
        "software-source-type": "VENDOR"
      },
       {
        "description": "Oracle Linux 8 BaseOS Latest (x86_64)",
        "display-name": "ol8_baseos_latest-x86_64",
        "id": "ocid1.osmhsoftwaresource.oc1.iad.ama...",
        "software-source-type": "VENDOR"
      }
    ],
...

Using Another Oracle Linux System as the Reference

If OS Management Hub does not manage your reference system, first use the yum repolist or dnf repolist command to list the enabled repositories on the system:

sudo dnf repolist

Then, use the OCI CLI to list the vendor software sources OS Management contains. Use your tenancy OCID for the compartment-id. You can get your tenancy OCID from the OCI Console. Click your user profile icon and choose Tenancy.

oci os-management-hub software-source list --software-source-type VENDOR --os-family ORACLE_LINUX_8 --availability SELECTED --compartment-id <tenancy_OCID> --all | grep -E "display-name|osmhsoftwaresource"

For example:

$ sudo dnf repolist
repo id                                                                   repo name
ol8_UEKR7                                                                 Latest Unbreakable Enterprise Kernel Release 7 for Oracle Linux 8 (x86_64)
ol8_appstream                                                             Oracle Linux 8 Application Stream (x86_64)
ol8_baseos_latest                                                         Oracle Linux 8 BaseOS Latest (x86_64)
 
$ oci os-management-hub software-source list --software-source-type VENDOR --os-family ORACLE_LINUX_8 --availability SELECTED --compartment-id <tenancy_OCID> --all | grep -E "display-name|osmhsoftwaresource"
        "display-name": "ol8_uekr7-x86_64",
        "id": "ocid1.osmhsoftwaresource.oc1.iad.ama...",
        "display-name": "ol8_x86_64_userspace_ksplice-x86_64",
        "id": "ocid1.osmhsoftwaresource.oc1.iad.ama...",
        "display-name": "ol8_kvm_appstream-x86_64",
        "id": "ocid1.osmhsoftwaresource.oc1.iad.ama...",
         "display-name": "ol8_ksplice-x86_64",
        "id": "ocid1.osmhsoftwaresource.oc1.iad.ama...",
        "display-name": "ol8_appstream-x86_64",
        "id": "ocid1.osmhsoftwaresource.oc1.iad.ama...",
        "display-name": "ol8_baseos_latest-x86_64",
        "id": "ocid1.osmhsoftwaresource.oc1.iad.ama...",

You will need to associate the repos from yum/dnf to the software sources enabled in OS Management Hub. The mapping is generally straightforward. In the above example, ol8_UEKR7 from DNF maps to ol8_uekr7-x86_64 from the OCI CLI.

Edit the JSON Input Template

Note: Automate the construction of the package filters using the scripts included in this tutorial. See Automating JSON Input File Creation.

Now that you have your vendor software sources, packages, and versions, you can fill in the JSON input template. Here is an example:

{
  "compartmentId": "MY_TENANCY_OCID",
  "description": "Custom source created with the OCI CLI",
  "displayName": "my-custom-source",
  "filter": {
    "packageFilters": [
      {
        "filterType": "INCLUDE",
        "packageName": "bind-utils",
        "packageVersion": "32:9.11.36-8.el8_8.1"
      },
      {
        "filterType": "INCLUDE",
        "packageName": "systemd-libs",
        "packageVersion": "239-74.0.4.el8_8.2"
      }
    ]
  },
  "vendorSoftwareSources": [
    {
      "displayName": "ol8_baseos_latest-x86_64",
      "id": "ocid1.osmhsoftwaresource.oc1.iad.ama..."
    },
    {
      "display-name": "ol8_uekr7-x86_64",
      "id": "ocid1.osmhsoftwaresource.oc1.iad.ama..."
    },
    {
      "displayName": "ol8_appstream-x86_64",
      "id": "ocid1.osmhsoftwaresource.oc1.iad.ama..."
    }
  ]
}

Notice that the packageNamePattern parameter in the filter is not used. The filters exactly match the packageVersion. Also, this custom software source omits the isAutoUpdated option, which OS Management Hub does not automatically update.

Create the Custom Software Source

Finally, pass the JSON input file to the OCI CLI to create the custom software source:

oci os-management-hub software-source create-custom-swsrc --from-json file:///<full-path-to-JSON>/my-css.json

The command will return a JSON block with the definition of the custom software source, and the OS Management Hub service assembles the packages you specified in the filters. The OCID of the newly created software source is one of the items returned by the OCI CLI. For example:

$ oci os-management-hub software-source create-custom-swsrc --from-json file:///<full-path-to-JSON>/my-css.json
{
  "data": {
    "arch-type": "X86_64",
    "availability": "SELECTED",
    "checksum-type": "SHA256",
...
    "id": "ocid1.osmhsoftwaresource.oc1.iad.ama...",

Confirm the Custom Software Source Creation

You can check the status of the newly created software source using the OCI CLI:

oci os-management-hub software-source get --software-source-id <custom_swsrc_OCID> | grep -E "display-name|lifecycle-state"

A lifecycle-state of ACTIVE means that OS Management Hub has finished assembling the custom software source and is ready for use by your managed instances and groups. For example:

$ oci os-management-hub software-source get --software-source-id <custom_swsrc_OCID> | grep -E "display-name|lifecycle-state"
    "display-name": "my-custom-source",
    "lifecycle-state": "ACTIVE",
        "display-name": "ol8_baseos_latest-x86_64",
        "display-name": "ol8_uekr7-x86_64",
        "display-name": "ol8_appstream-x86_64",

Automating JSON Input File Creation

The “heavy lifting” is the assembly of the package filters in the JSON input file. Let’s automate the generation of the JSON input file with some basic scripting.

Using an OS Management Hub Managed Instance as the Reference

If OS Management Hub already manages your reference system, use the css-json-from-mi script to build a JSON input file. You can run this script from any system set up to use the OCI CLI. You’ll also need the OCID of the managed instance, which you can copy from the Managed Instance details screen in the OCI Console. Once you have the instance OCID, fetch the installed packages with the OCI CLI:

css-json-from-mi <managed-instance-OCID> [vcss] > my-css.json

This script uses the OCI CLI to get the installed packages and versions from a reference managed instance and outputs a JSON input file. All of the package filters are pre-populated.

Edit the JSON and supply the compartment ID, name, description, software source version (if VCSS), and vendor software sources. Then, pass the JSON to the OCI CLI with the --from-json option to create the custom or versioned custom software source.

Using Another Oracle Linux System as the Reference

If OS Management Hub does not manage your reference system, log into the reference system and run the css-json-from-rpm-qa script to build a JSON input file.

css-json-from-rpm-qa [vcss] > my-css.json

This script gathers the packages installed on the system and outputs a JSON input file. All of the package filters are pre-populated.

Edit the JSON and supply the compartment ID, name, description, software source version (if VCSS), and vendor software sources. Then, pass the JSON to the OCI CLI with the --from-json option to create the custom or versioned custom software source.

Conclusion

OS Management Hub custom and versioned custom software sources give you more control over the content available to your managed instances. The OCI CLI facilitates the creation of those software sources by enabling programmatic interaction with OS Management Hub.

This tutorial’s steps showed you how to create a custom software source in OS Management Hub. The procedure is very similar to creating a versioned custom software source. You will use the OCI CLI subcommand os-management-hub software-source create-versioned-custom-swsrc to generate the JSON template and create the versioned custom software source. The JSON template for a versioned custom software source has slight differences compared to a custom software source. A versioned custom software source needs a softwareSourceVersion string and won’t have the isAutoUpdated option (versioned software sources are immutable). The remainder of the JSON template is the same. The sample scripts in this tutorial accept an optional vcss parameter to help automate building the JSON input template for a versioned custom software source.

Appendix

css-json-from-mi

#!/bin/sh
 
MAKE_CSS=0
MAKE_VCSS=0
if [ "X$1" == "X" ]; then
    echo "Usage: $0 <managed_instance_ocid> [vcss]"
    exit 1
fi
MANAGED_INSTANCE=$1
TMPFILE=/tmp/output.$$
if [ "X$2" == "XVCSS" ]; then
    MAKE_VCSS=1
elif [ "X$2" == "Xvcss" ]; then
    MAKE_VCSS=1
else
    MAKE_CSS=1
fi
 
# Heading
echo "{"
echo "\"compartmentId\": \"MY_TENANCY_OCID\","
echo "\"displayName\": \"MY_CSS_NAME\","
echo "\"description\": \"MY_CSS_DESCRIPTION\","
 
# Version
if [ $MAKE_VCSS == 1 ]; then
    echo "\"softwareSourceVersion\": \"MY_VERSION_STRING\","
fi
 
# Vendor SSs
echo "\"vendorSoftwareSources\": ["
echo "    {"
echo "        \"id\": \"OCID_FOR_VENDOR_SWSRC1\","
echo "        \"displayName\": \"DISPLAY_NAME_FOR_VENDOR_SWSRC1\""
echo "    },"
echo "    {"
echo "        \"id\": \"OCID_FOR_VENDOR_SWSRC2\","
echo "        \"displayName\": \"DISPLAY_NAME_FOR_VENDOR_SWSRC2\""
echo "    }"
echo "],"
 
# Filters
echo "\"filter\": {"
echo "\"packageFilters\": ["
 
# Get all installed pacakges from the MI
oci os-management-hub managed-instance list-installed-packages --managed-instance-id $MANAGED_INSTANCE --all | grep -E "\"name\":|\"version\":" | awk -F"\": " '{print $2}' | sed 's/\",//' | sed 's/\"//g' > $TMPFILE
INSTALLED_PACKAGES=`awk '{getline b;printf("%s %s\n",$0,b)}' $TMPFILE`
INSTALLED_PACKAGE_COUNT=`echo $INSTALLED_PACKAGES | wc -w | awk '{print $1}'`
COUNTER=1
for PKG in $INSTALLED_PACKAGES; do
    PACKAGE=`echo $PKG | awk -F":::" '{print $1}'`
    VERSION=`echo $PKG | awk -F":::" '{print $2}'`
    # Use 'packageName' for an _EXACT_ package match
    echo "    {"
    echo "        \"filterType\": \"INCLUDE\","
    echo "        \"packageName\": \"$PACKAGE\","
    echo "        \"packageVersion\": \"$VERSION\""
 
    if [ $COUNTER -lt $INSTALLED_PACKAGE_COUNT ]; then 
        echo "    },"
    else
        echo "    }"
    fi
    COUNTER=`expr $COUNTER + 1`
done
 
echo "]"
if [ $MAKE_CSS == 1 ]; then
    echo "},"
    echo "\"isAutoUpdated\": \"false\""
else
    echo "}"
fi
echo "}"
rm $TMPFILE

css-json-from-rpm-qa

#!/bin/sh
 
MAKE_CSS=0
MAKE_VCSS=0
if [ "X$1" == "XVCSS" ]; then
    MAKE_VCSS=1
elif [ "X$1" == "Xvcss" ]; then
    MAKE_VCSS=1
else
    MAKE_CSS=1
fi
 
# Heading
echo "{"
echo "\"compartmentId\": \"MY_TENANCY_OCID\","
echo "\"displayName\": \"MY_CSS_NAME\","
echo "\"description\": \"MY_CSS_DESCRIPTION\","
 
# Version
if [ $MAKE_VCSS == 1 ]; then
    echo "\"softwareSourceVersion\": \"MY_VERSION_STRING\","
fi
 
# Vendor SSs
echo "\"vendorSoftwareSources\": ["
echo "    {"
echo "        \"id\": \"OCID_FOR_VENDOR_SWSRC1\","
echo "        \"displayName\": \"DISPLAY_NAME_FOR_VENDOR_SWSRC1\""
echo "    },"
echo "    {"
echo "        \"id\": \"OCID_FOR_VENDOR_SWSRC2\","
echo "        \"displayName\": \"DISPLAY_NAME_FOR_VENDOR_SWSRC2\""
echo "    }"
echo "],"
 
# Filters
echo "\"filter\": {"
echo "\"packageFilters\": ["
 
 
# Get all installed packages, filter out pseudo gpg-pubkey package
INSTALLED_PACKAGES=`rpm -qa --queryformat "%{NAME}:::%{EPOCH}:%{VERSION}-%{RELEASE}\n" | sed "s/(none)://" | grep -v gpg-pubkey | sort`
INSTALLED_PACKAGE_COUNT=`echo $INSTALLED_PACKAGES | wc -w | awk '{print $1}'`
COUNTER=1
for PKG in $INSTALLED_PACKAGES; do
    PACKAGE=`echo $PKG | awk -F":::" '{print $1}'`
    VERSION=`echo $PKG | awk -F":::" '{print $2}'`
    # Use 'packageName' for an _EXACT_ package match
    echo "    {"
    echo "        \"filterType\": \"INCLUDE\","
    echo "        \"packageName\": \"$PACKAGE\","
    echo "        \"packageVersion\": \"$VERSION\""
 
    if [ $COUNTER -lt $INSTALLED_PACKAGE_COUNT ]; then 
        echo "    },"
    else
        echo "    }"
    fi
    COUNTER=`expr $COUNTER + 1`
done
 
echo "]"
if [ $MAKE_CSS == 1 ]; then
    echo "},"
    echo "\"isAutoUpdated\": \"false\""
else
    echo "}"
fi
echo "}"

For More Information

See other related resources:

More Learning Resources

Explore other labs on docs.oracle.com/learn or access more free learning content on the Oracle Learning YouTube channel. Additionally, visit education.oracle.com/learning-explorer to become an Oracle Learning Explorer.

For product documentation, visit Oracle Help Center.