Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Systemd free setup #507

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mgradm/cmd/inspect/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func kuberneteInspect(
}

// Get the SCC credentials secret if existing
pullSecret, err := kubernetes.GetSCCSecret(namespace, &types.SCCCredentials{}, kubernetes.ServerApp)
pullSecret, err := kubernetes.GetRegistrySecret(namespace, &types.SCCCredentials{}, kubernetes.ServerApp)
if err != nil {
return err
}
Expand Down
173 changes: 150 additions & 23 deletions mgradm/cmd/install/podman/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ package podman

import (
"errors"
"fmt"
"os/exec"
"strconv"
"strings"

"github.com/rs/zerolog"
Expand All @@ -16,6 +18,7 @@ import (
"github.com/uyuni-project/uyuni-tools/mgradm/shared/hub"
"github.com/uyuni-project/uyuni-tools/mgradm/shared/podman"
"github.com/uyuni-project/uyuni-tools/mgradm/shared/saline"
"github.com/uyuni-project/uyuni-tools/mgradm/shared/templates"
adm_utils "github.com/uyuni-project/uyuni-tools/mgradm/shared/utils"
"github.com/uyuni-project/uyuni-tools/shared"
. "github.com/uyuni-project/uyuni-tools/shared/l10n"
Expand Down Expand Up @@ -91,35 +94,23 @@ func installForPodman(
return err
}

cnx := shared.NewConnection("podman", shared_podman.ServerContainerName, "")
if err := waitForSystemStart(systemd, cnx, preparedImage, flags); err != nil {
return utils.Errorf(err, L("cannot wait for system start"))
if err := shared_podman.SetupNetwork(false); err != nil {
return utils.Errorf(err, L("cannot setup network"))
}

caPassword := flags.Installation.SSL.Password
if flags.Installation.SSL.UseExisting() {
// We need to have a password for the generated CA, even though it will be thrown away after install
caPassword = "dummy"
}
log.Info().Msg(L("Run setup command in the container"))

env := map[string]string{
"CERT_O": flags.Installation.SSL.Org,
"CERT_OU": flags.Installation.SSL.OU,
"CERT_CITY": flags.Installation.SSL.City,
"CERT_STATE": flags.Installation.SSL.State,
"CERT_COUNTRY": flags.Installation.SSL.Country,
"CERT_EMAIL": flags.Installation.SSL.Email,
"CERT_CNAMES": strings.Join(append([]string{fqdn}, flags.Installation.SSL.Cnames...), ","),
"CERT_PASS": caPassword,
if err := runSetup(preparedImage, &flags.ServerFlags, fqdn); err != nil {
return err
}

log.Info().Msg(L("Run setup command in the container"))
cnx := shared.NewConnection("podman", shared_podman.ServerContainerName, "")
if err := waitForSystemStart(systemd, cnx, preparedImage, flags); err != nil {
return utils.Errorf(err, L("cannot wait for system start"))
}

if err := adm_utils.RunSetup(cnx, &flags.ServerFlags, fqdn, env); err != nil {
if stopErr := systemd.StopService(shared_podman.ServerService); stopErr != nil {
log.Error().Msgf(L("Failed to stop service: %v"), stopErr)
}
return err
if err := cnx.CopyCaCertificate(fqdn); err != nil {
return utils.Errorf(err, L("failed to add SSL CA certificate to host trusted certificates"))
}

if path, err := exec.LookPath("uyuni-payg-extract-data"); err == nil {
Expand Down Expand Up @@ -173,3 +164,139 @@ func installForPodman(
}
return nil
}

// runSetup execute the setup.
func runSetup(image string, flags *adm_utils.ServerFlags, fqdn string) error {
localHostValues := []string{
"localhost",
"127.0.0.1",
"::1",
fqdn,
}

localDB := utils.Contains(localHostValues, flags.Installation.DB.Host)

dbHost := flags.Installation.DB.Host
reportdbHost := flags.Installation.ReportDB.Host

if localDB {
dbHost = "localhost"
if reportdbHost == "" {
reportdbHost = "localhost"
}
}

caPassword := flags.Installation.SSL.Password
if flags.Installation.SSL.UseExisting() {
// We need to have a password for the generated CA, even though it will be thrown away after install
caPassword = "dummy"
}

// TODO Share the env variables preparation with Kubernetes?
env := map[string]string{
"UYUNI_FQDN": fqdn,
"MANAGER_USER": flags.Installation.DB.User,
"MANAGER_PASS": flags.Installation.DB.Password,
"ADMIN_USER": flags.Installation.Admin.Login,
"ADMIN_PASS": flags.Installation.Admin.Password,
"MANAGER_ADMIN_EMAIL": flags.Installation.Email,
"MANAGER_MAIL_FROM": flags.Installation.EmailFrom,
"MANAGER_ENABLE_TFTP": boolToString(flags.Installation.Tftp),
"LOCAL_DB": boolToString(localDB),
"MANAGER_DB_NAME": flags.Installation.DB.Name,
"MANAGER_DB_HOST": dbHost,
"MANAGER_DB_PORT": strconv.Itoa(flags.Installation.DB.Port),
"MANAGER_DB_PROTOCOL": flags.Installation.DB.Protocol,
"REPORT_DB_NAME": flags.Installation.ReportDB.Name,
"REPORT_DB_HOST": reportdbHost,
"REPORT_DB_PORT": strconv.Itoa(flags.Installation.ReportDB.Port),
"REPORT_DB_USER": flags.Installation.ReportDB.User,
"REPORT_DB_PASS": flags.Installation.ReportDB.Password,
"EXTERNALDB_ADMIN_USER": flags.Installation.DB.Admin.User,
"EXTERNALDB_ADMIN_PASS": flags.Installation.DB.Admin.Password,
"EXTERNALDB_PROVIDER": flags.Installation.DB.Provider,
"ISS_PARENT": flags.Installation.IssParent,
"ACTIVATE_SLP": "N", // Deprecated, will be removed soon
"SCC_USER": flags.Installation.SCC.User,
"SCC_PASS": flags.Installation.SCC.Password,
"CERT_O": flags.Installation.SSL.Org,
"CERT_OU": flags.Installation.SSL.OU,
"CERT_CITY": flags.Installation.SSL.City,
"CERT_STATE": flags.Installation.SSL.State,
"CERT_COUNTRY": flags.Installation.SSL.Country,
"CERT_EMAIL": flags.Installation.SSL.Email,
"CERT_CNAMES": strings.Join(append([]string{fqdn}, flags.Installation.SSL.Cnames...), ","),
"CERT_PASS": caPassword,
}

if flags.Mirror != "" {
env["MIRROR_PATH"] = "/mirror"
}

envNames := []string{}
envValues := []string{}
for key, value := range env {
envNames = append(envNames, "-e", key)
envValues = append(envValues, fmt.Sprintf("%s=%s", key, value))
}

command := []string{
"run",
"--rm",
"--shm-size=0",
"--shm-size-systemd=0",
"--name", "uyuni-setup",
"--network", shared_podman.UyuniNetwork,
"-e", "TZ=" + flags.Installation.TZ,
}
for _, volume := range utils.ServerVolumeMounts {
command = append(command, "-v", fmt.Sprintf("%s:%s:z", volume.Name, volume.MountPath))
}
command = append(command, envNames...)
command = append(command, image)

script, err := generateSetupScript(&flags.Installation)
if err != nil {
return err
}
command = append(command, "/usr/bin/sh", "-c", script)

if _, err := newRunner("podman", command...).Env(envValues).StdMapping().Exec(); err != nil {
return utils.Errorf(err, L("server setup failed"))
}

log.Info().Msgf(L("Server set up, login on https://%[1]s with %[2]s user"), fqdn, flags.Installation.Admin.Login)
return nil
}

var newRunner = utils.NewRunner

// generateSetupScript creates a temporary folder with the setup script to execute in the container.
// The script exports all the needed environment variables and calls uyuni's mgr-setup.
func generateSetupScript(flags *adm_utils.InstallationFlags) (string, error) {
// TODO Share with kubernetes implementation
template := templates.MgrSetupScriptTemplateData{
DebugJava: flags.Debug.Java,
OrgName: flags.Organization,
AdminLogin: "$ADMIN_USER",
AdminPassword: "$ADMIN_PASS",
AdminFirstName: flags.Admin.FirstName,
AdminLastName: flags.Admin.LastName,
AdminEmail: flags.Admin.Email,
NoSSL: false,
}

// Prepare the script
scriptBuilder := new(strings.Builder)
if err := template.Render(scriptBuilder); err != nil {
return "", utils.Errorf(err, L("failed to render setup script"))
}
return scriptBuilder.String(), nil
}

func boolToString(value bool) string {
if value {
return "Y"
}
return "N"
}
2 changes: 1 addition & 1 deletion mgradm/cmd/migrate/kubernetes/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func migrateToKubernetes(
}

// Create a secret using SCC credentials if any are provided
pullSecret, err := shared_kubernetes.GetSCCSecret(
pullSecret, err := shared_kubernetes.GetRegistrySecret(
flags.Kubernetes.Uyuni.Namespace, &flags.Installation.SCC, shared_kubernetes.ServerApp,
)
if err != nil {
Expand Down
17 changes: 14 additions & 3 deletions mgradm/shared/kubernetes/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
package kubernetes

import (
"strings"

"github.com/rs/zerolog"
"github.com/uyuni-project/uyuni-tools/shared/kubernetes"
. "github.com/uyuni-project/uyuni-tools/shared/l10n"
core "k8s.io/api/core/v1"
Expand All @@ -19,12 +22,20 @@ const (
DBSecret = "db-credentials"
// ReportdbSecret is the name of the report database credentials secret.
ReportdbSecret = "reportdb-credentials"
SCCSecret = "scc-credentials"
secretUsername = "username"
secretPassword = "password"
)

// CreateDBSecret creates a secret containing the DB credentials.
func CreateDBSecret(namespace string, name string, user string, password string) error {
// CreateBasicAuthSecret creates a secret of type basic-auth.
func CreateBasicAuthSecret(namespace string, name string, user string, password string) error {
// Check if the secret is already existing
out, err := runCmdOutput(zerolog.DebugLevel, "kubectl", "get", "-n", namespace, "secret", name, "-o", "name")
if err == nil && strings.TrimSpace(string(out)) != "" {
return nil
}

// Create the secret
secret := core.Secret{
TypeMeta: meta.TypeMeta{APIVersion: "v1", Kind: "Secret"},
ObjectMeta: meta.ObjectMeta{
Expand All @@ -40,5 +51,5 @@ func CreateDBSecret(namespace string, name string, user string, password string)
Type: core.SecretTypeBasicAuth,
}

return kubernetes.Apply([]runtime.Object{&secret}, L("failed to create the database secret"))
return kubernetes.Apply([]runtime.Object{&secret}, L("failed to create the secret"))
}
Loading
Loading