Request for clarification on Provisioning Ubuntu Autoinstall

Problem:
Using Foreman :: Provisioning Ubuntu Autoinstall as a guide, we’re attempting to provision bare-metal laptops with autoinstall of Ubuntu Desktop 23.10. This article states the following: " The Preseed default finish template installs subscription-manager and registers the host to Foreman." When I look at the Preseed Default Finish template I do not see any call to the “subscription-manager-setup” snippet. This snippet’s description states that it is being called from the “global_registration” template. The Global Registration template, given its type, cannot be associated to an Operating System.

As it stands at the moment, subscription-manager does not get setup as part of our Ubuntu desktop provisioning process. Is Foreman (in our case, our proxy server) expected to automatically run the Global Registration template at some point of the process or should we simple add the subscription-manager-setup snippet to a cloned version of the Preseed Default Finish template?

Any clarification on this particular aspect would be greatly appreciated.

Expected outcome:
Subscription-manager gets installed as part of the provisioning process.

Foreman and Proxy versions:
Foreman and proxy are at 3.10

Foreman and Proxy plugin versions:

Distribution and version:
Almalinux 8.9

Other relevant data:
Our Foreman server is configured with the following features: Logs, Pulpcore, Puppet, Puppet CA

Our Proxy server is configured with the following features: Container_Gateway, Discovery, Dynflow, HTTPBoot, Logs, Pulpcore, Registration, Script, Templates, TFTP.

We also have a Windows proxy server configured with the following features: DHCP, DNS, Logs.

Due to our network configuration, our hosts cannot communicate with our foreman server, thus the provisioning is done via our proxy server.

2 Likes

We did it via Ansible as Roles are always run after the successfull deployment and subscription-manager is not available from the default repositories. As it was a project to evaluate things we have not polished and published results yet, but here is the tasks list from what my colleague @cbreit created to solve it. Instead of the upstream URL we could already used the URL from Katello at registration stage.

---
# tasks file for foreman_register_host

- name: "Foreman Users"
  ansible.builtin.debug:
    var: foreman.foreman_users

- name: "Include GPG Key in Keyring"
  ansible.builtin.get_url:
    url: https://oss.atix.de/atix_gpg.pub
    dest: /etc/apt/keyrings/atix2.asc

- name: "Include Subscription-Manager Repository"
  ansible.builtin.apt_repository:
    repo: "deb [arch=amd64 signed-by=/etc/apt/keyrings/atix2.asc] https://oss.atix.de/Ubuntu22LTS/ stable main"
    update_cache: true

- name: "Generate registration command"
  theforeman.foreman.registration_command:
    username: "{{ foreman_username }}"
    password: "{{ foreman_password }}"
    server_url: "https://foreman.localdomain"
    validate_certs: false
    insecure: true
    force: true
    packages: "katello-host-tools-tracer"
    activation_keys: 
      - ubuntu-desktop
  register: command

- name: "Perform registration"
  ansible.builtin.shell:
    executable: /bin/bash
    cmd: "{{ command.registration_command }}"
  environment: 
    TERM: xterm

- name: "Add Symlink for Katello-Packet-Tracer"
  ansible.builtin.file:  
    src: /usr/sbin/katello-tracer-upload
    dest: /usr/bin/tracer-upload
    state: link
1 Like

Thank you very much for your quick response and recommendation to use Ansible but I still would like confirmation whether the use of the available “subscription-manager-setup” snippet is a viable option.

Yes, as registration does also use the snippet (foreman/app/views/unattended/provisioning_templates/registration/global_registration.erb at develop · theforeman/foreman · GitHub). You just need to ensure subscription-manager is available at the state then I do not see any problem.

1 Like

Hi lgaboury:
How did you solve it? I met the same issue. Thanks.

I’ve just come to the same conclusion. Ubuntu deployment works fine but the subscription manager seems to be a catch-22 between getting the subscription-manager installed for managing Katello repos and adding the repo to do so.

Thank you for your input on this. For those still new to Foreman. Please, could you share a hint as to which method would be best suited for deploying the Atix Subscription Manager repo to a host before registration?

I currently see two options:

  1. Job templates: create an ansible job to install the repo.
  2. Assign the ansible role when creating a host.

You mentioned the latter, but how does one set the order of things to ensure the role is executed before registration is attempted?

I’m still reading up on how to get started with writing Ansible roles, the importing seems easy enough.

1 Like

You could create a snippet with the same name and the suffix custom apt to make the repository available in the cloud init already (or copy and adjust the template if needed, but I typically recommend extending via the prepared snippte includes). As my colleague was not really happy about the documentation for cloud init / Autostart, he decided to use the other option mentioned, but not as a job template but a Ansible role (see above).

1 Like

@Dirk I spotted the reference to ‘custom apt’ this morning. I’m hesitant about using this as editing a cloned template to add a custom apt repo has only resulted in 100% CPU during deployment and a hang at a later point, preventing the installation from completing successfully. So adding a sources section after the primary section breaks things completely. As the install hangs, troubleshooting this is proving to be hard.

I want to use Ansible to build the services on the created hosts so it would make sense to go this route. I was hoping there might be an example of how to get started with an Ansible script for this. The importing is well documented, but I need to get to where I have something to import.

@Bernhard_Suttner do you know of a set paradigm for provisioning Ubuntu/Deb systems while using the subscription-manager setup snippet? The snippet seems to rely on subscription-manager being available out of the box, which is true at least for EL distributions.

1 Like

The “Repository” field in the global registration command generator form is supposed to address that. You can add a repository to install sub-man, before registering. (But, yes, it does need to be accessible to the host.)

1 Like

Oh, where can I find the documentation for this?

The sub-man for debian/ubuntu are available here:

https://apt.atix.de/

But they require to have access to base repositories to install dependencies.

But is there a similar method for provisioning? My take from this thread was that the sub-man registration was running completely from the Preseed default finish template.

1 Like

Oh right. I’m not aware of a corresponding feature for provisioning. I could be wrong…

I’m aware of that, but what I am looking for; is to add this repo to the installed host before /tmp/finish.sh tries to install/use subscription-manager. Once I can do that with the public repo I can decide if I there’s a benefit to mirror it locally, but that’s secondary.

What isn’t fully clear to me yet is how to parse parameter repo_data[repo] to ‘Global Registration’ and whether this is early enough as both ‘Preseed default finish’ and ‘Linux host_init_config default’ test for the presence of subscription-manager.

My findings so far

The template snippet “subscription_manager_setup” is meant to install the subscription manager, but doesn’t add the Atix repository. This snippet is called by “global_registration”, before registration is attempted. I haven’t tried Ansible yet, but my concern is that the Ansible role won’t run until after Global Registration has completed and I’d like to keep customisation to a minimum.

The only way I’ve been able to get the subscription manager repo deployed at host build time has been by using the following late-commands:

  - echo "deb https://oss.atix.de/Ubuntu24LTS/ stable main" >> /target/etc/apt/sources.list.d/client.list
  - curl --silent --show-error --output /target/etc/apt/trusted.gpg.d/client.asc https://oss.atix.de/atix_gpg.pub
  #- echo "deb [trusted=yes] https://foreman.local/pulp/content/Org/Library/custom/Ubuntu_Sub_Client/Ubuntu24/ default all" >> /target/etc/apt/sources.list.d/client.list
  - curtin in-target -- apt update

Using the public (subscription-manager) Atix repo works for adding the repo (I’m primarily focused on Ubuntu 24.04). But for some reason, Global Registration doesn’t then install the subscription-manager. I have a hunch that Global Registration happens before the late-commands are executed, but don’t know this for sure, nor do I know how to troubleshoot the Global Registration template.

Using a local repo fails because curtin won’t accept the [trusted=yes] option; GPG keys may need to be added to pulp to get that working.

Do the rendered template previews that you can see on your hosts help at all with showing the order of operations at provisioning time?

@iballou They do. I’ve now found that the source for finish.sh is template Preseed default finish. Which has a hook for calling Preseed default finish custom post if it exists. So I created this snippet and now a host gets subscribed during an unattended installation.

In case this may help someone else looking to do the same thing, here are the templates I created for adding subscription-manager during an unattended installation:

<%#
kind: snippet
name: Preseed default finish custom post
model: ProvisioningTemplate
snippet: true
description: |
  This snippet adds the subscription client repo to Debian/Ubuntu systems.
  It then calls snippet debian_register to register the host.

  Note that if the registration fails, unattended installation may also fail.
-%>
<%
#rhel_compatible = @host.operatingsystem.family == 'Redhat' && @host.operatingsystem.name != 'Fedora'
#is_fedora = @host.operatingsystem.name == 'Fedora'
os_major = @host.operatingsystem.major.to_i
-%>

##
## Subscription manager
##
<% if plugin_present?('katello') -%>
echo "Adding Subscription manager repo"
if [ -f /etc/debian_version ]; then
  # Add subscription-manager repo if package is unavailable
  if ! [[ $(apt-cache search --names-only '^subscription-managr') ]] ; then
    curl --silent --show-error --output /etc/apt/trusted.gpg.d/client.asc https://oss.atix.de/atix_gpg.pub
    echo "deb https://oss.atix.de/Ubuntu<%= os_major %>LTS/ stable main" > /etc/apt/sources.list.d/client.list
    apt-get update
  fi
  apt-get install subscription-manager -y
fi
<%= snippet_if_exists('debian_register') %>
<% end -%>

And the template snippet debian_register, which is cloned from redhat_register:

<%#
kind: snippet
name: debian_register
model: ProvisioningTemplate
snippet: true
description: |
  Debian Derivatives Registration Snippet

  General parameters:

    debian_install_host_tools = [true|false]    Install the katello-host-tools apt plugins.

    debian_install_host_tracer_tools = [true|false]  Install the katello-host-tools Tracer apt plugin.

    activation_key = <key>                      Activation key string #, not needed if using
                                                #subscription-manager with username/password

  Parameters for use with subscription-manager (Satellite, or Katello)

    subscription_manager = 'true'               You're going to use subscription-manager

    subscription_manager_auto_attach = 'false'  Run attach --auto after registering.

    subscription_manager_username = <username>  Username for subscription-manager

    subscription_manager_password = <password>  Password for subscription-manager

    subscription_manager_certpkg_url = <url>    Custom certificate package URL

    subscription_manager_org = <org name>       Organization name, if required

    subscription_manager_repos = <repos>        Additional repositories to enable
                                                after registration.
                                                Separate multiple repositories with commas.

    #subscription_manager_override_repos_cost = <cost>  Override repository cost

    subscription_manager_pool = <pool>          Specific subscription pool to use

    http-proxy = <host>                         Proxy hostname to be used for registration

    http-proxy-port = <port>                    Proxy port to be used for registration

    http-proxy-user = <user>                    Proxy user to be used for registration

    http-proxy-password = <password>            Proxy password to be used for registration
#'
-%>
<%
  # Katello or subscription-manager:
  if host_param_true?('subscription_manager') || host_param('kt_activation_keys')
    registration_type = 'subscription_manager'
  else
    registration_type = nil
  end
-%>
# registration_type = '<%= registration_type %>'
<% if registration_type == 'subscription_manager' -%>
  <%
    if host_param('kt_activation_keys')
      subscription_manager_certpkg_url = subscription_manager_configuration_url(@host)
      subscription_manager_org = @host.rhsm_organization_label
      activation_key = host_param('kt_activation_keys')
      debian_install_host_tools = host_param_true?('debian_install_host_tools', true)
      debian_install_host_tracer_tools = host_param_true?('debian_install_host_tracer_tools')
    else
      subscription_manager_certpkg_url = host_param('subscription_manager_certpkg_url')
      subscription_manager_org = host_param('subscription_manager_org')
      activation_key = host_param('activation_key')
      debian_install_host_tools = host_param_true?('debian_install_host_tools')
      debian_install_host_tracer_tools = host_param_true?('debian_install_host_tracer_tools')
    end
  -%>

  echo "##############################################################"
  echo "################# SUBSCRIPTION MANAGER #######################"
  echo "##############################################################"
  echo
  echo "Starting the subscription-manager registration process"

  # Set up subscription-manager
  <%= snippet("subscription_manager_setup", variables: { subman_setup_scenario: 'provisioning' }).strip -%>

  <% if host_param('http-proxy') -%>
    subscription-manager config --server.proxy_hostname='<%= host_param("http-proxy") %>'
    <% if host_param('http-proxy-user') -%>
      subscription-manager config --server.proxy_user='<%= host_param("http-proxy-user") %>'
    <% end -%>
    <% if host_param('http-proxy-password') -%>
      subscription-manager config --server.proxy_password='<%= host_param("http-proxy-password") %>'
    <% end -%>
    <% if host_param('http-proxy-port') -%>
      subscription-manager config --server.proxy_port='<%= host_param("http-proxy-port") %>'
    <% end -%>
  <% end -%>
  
  <% if host_param('subscription_manager_username') && host_param('subscription_manager_password') -%>
    <% if host_param('subscription_manager_pool') -%>
      subscription-manager register --name="<%= @host.name %>" --username='<%= host_param("subscription_manager_username") %>' --password='<%= host_param("subscription_manager_password") %>'
      subscription-manager attach --pool='<%= host_param('subscription_manager_pool') %>'
    <% else -%>
      subscription-manager register --name="<%= @host.name %>" --username='<%= host_param("subscription_manager_username") %>' --password='<%= host_param("subscription_manager_password") %>' --auto-attach
    <% end -%>

  <% elsif activation_key -%>
    subscription-manager register --name="<%= @host.name %>" --org='<%= subscription_manager_org %>' --activationkey='<%= activation_key %>'
  <% else -%>
    echo "No activation key found: Not registering to subscription manager"
  <% end -%>

  <% if debian_install_host_tools -%>
    $PKG_MANAGER_INSTALL katello-host-tools
  <% end -%>

  <% if debian_install_host_tracer_tools -%>
    $PKG_MANAGER_INSTALL katello-host-tools-tracer
  <% end -%>
<% end -%>