Skip to content

Commit

Permalink
Check if server container or volumes already exists
Browse files Browse the repository at this point in the history
If the volumes are already populated, try to reuse the existing user/org
if it is possible.
  • Loading branch information
aaannz authored and cbosdo committed Jul 18, 2024
1 parent 26f4d12 commit e4eee83
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 10 deletions.
15 changes: 10 additions & 5 deletions mgradm/cmd/install/podman/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package podman

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

Expand Down Expand Up @@ -43,11 +44,6 @@ func installForPodman(
cmd *cobra.Command,
args []string,
) error {
flags.CheckParameters(cmd, "podman")
if _, err := exec.LookPath("podman"); err != nil {
return errors.New(L("install podman before running this command"))
}

hostData, err := shared_podman.InspectHost()
if err != nil {
return err
Expand All @@ -59,6 +55,15 @@ func installForPodman(
}
defer cleaner()

if hostData.HasUyuniServer {
return fmt.Errorf(L("Server is already initialized! Uninstall before attempting new installation or use upgrade command"))
}

flags.CheckParameters(cmd, "podman")
if _, err := exec.LookPath("podman"); err != nil {
return errors.New(L("install podman before running this command"))
}

fqdn, err := utils.GetFqdn(args)
if err != nil {
return err
Expand Down
46 changes: 43 additions & 3 deletions mgradm/cmd/install/shared/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
package shared

import (
"errors"
"net/url"
"os"
"path/filepath"
"strconv"
Expand All @@ -24,6 +26,13 @@ const setup_name = "setup.sh"

// RunSetup execute the setup.
func RunSetup(cnx *shared.Connection, flags *InstallFlags, fqdn string, env map[string]string) error {
// Containers should be running now, check storage if it is using volume from already configured server
preconfigured := false
if isServerConfigured(cnx) {
log.Warn().Msg(L("Server appears to be already configured. Installation will continue, but installation options may be ignored."))
preconfigured = true
}

tmpFolder := generateSetupScript(flags, fqdn, env)
defer os.RemoveAll(tmpFolder)

Expand All @@ -46,10 +55,37 @@ func RunSetup(cnx *shared.Connection, flags *InstallFlags, fqdn string, env map[
apiCnx := api.ConnectionDetails{
Server: fqdn,
Insecure: false,
User: flags.Admin.Login,
Password: flags.Admin.Password,
}
_, err := org.CreateFirst(&apiCnx, flags.Organization, &flags.Admin)
if err != nil {
return err

// Check if there is already admin user with given password and organization with same name
if _, err := api.Init(&apiCnx); err == nil {
if _, err := org.GetOrganizationDetails(&apiCnx, flags.Organization); err == nil {
log.Info().Msgf(L("Server organization already exists, reusing"))
} else {
log.Debug().Err(err).Msg("Error returned by server")
log.Warn().Msgf(L("Administration user already exists, but organization %s could not be found"), flags.Organization)
}
} else {
var connError *url.Error
if errors.As(err, &connError) {
// We were not able to connect to the server at all
return err
}
// We do not have any user existing, do not try to login
apiCnx = api.ConnectionDetails{
Server: fqdn,
Insecure: false,
}
_, err := org.CreateFirst(&apiCnx, flags.Organization, &flags.Admin)
if err != nil {
if preconfigured {
log.Warn().Msgf(L("Administration user already exists, but provided credentials are not valid"))
} else {
return err
}
}
}
}

Expand Down Expand Up @@ -137,3 +173,7 @@ func boolToString(value bool) string {
}
return "N"
}

func isServerConfigured(cnx *shared.Connection) bool {
return cnx.TestExistenceInPod("/root/.MANAGER_SETUP_COMPLETE")
}
9 changes: 7 additions & 2 deletions shared/podman/hostinspector.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ func NewHostInspector(scriptDir string) HostInspector {
types.NewInspectData(
"scc_password",
"cat /etc/zypp/credentials.d/SCCcredentials 2>&1 /dev/null | grep password | cut -d= -f2 || true"),

types.NewInspectData(
"has_uyuni_server",
"systemctl list-unit-files uyuni-server.service >/dev/null && echo true || echo false"),
},
ScriptDir: scriptDir,
}
Expand All @@ -38,8 +42,9 @@ func NewHostInspector(scriptDir string) HostInspector {

// HostInspectData are the data returned by the host inspector.
type HostInspectData struct {
SccUsername string `mapstructure:"scc_username"`
SccPassword string `mapstructure:"scc_password"`
SccUsername string `mapstructure:"scc_username"`
SccPassword string `mapstructure:"scc_password"`
HasUyuniServer bool `mapstructure:"has_uyuni_server"`
}

// ReadInspectData parses the data generated by the host inspector.
Expand Down
3 changes: 3 additions & 0 deletions shared/podman/hostinspector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestHostInspectorGenerate(t *testing.T) {
# inspect.sh, generated by mgradm
echo "scc_username=$(cat /etc/zypp/credentials.d/SCCcredentials 2>&1 /dev/null | grep username | cut -d= -f2 || true)" >> ` + dataPath + `
echo "scc_password=$(cat /etc/zypp/credentials.d/SCCcredentials 2>&1 /dev/null | grep password | cut -d= -f2 || true)" >> ` + dataPath + `
echo "has_uyuni_server=$(systemctl list-unit-files uyuni-server.service >/dev/null && echo true || echo false)" >> ` + dataPath + `
exit 0
`

Expand All @@ -43,6 +44,7 @@ func TestHostInspectorParse(t *testing.T) {
content := `
scc_username=myuser
scc_password=mysecret
has_uyuni_server=true
`
test_utils.WriteFile(t, inspector.GetDataPath(), content)

Expand All @@ -53,4 +55,5 @@ scc_password=mysecret

test_utils.AssertEquals(t, "Invalid SCC username", "myuser", actual.SccUsername)
test_utils.AssertEquals(t, "Invalid SCC password", "mysecret", actual.SccPassword)
test_utils.AssertTrue(t, "HasUyuniServer should be true", actual.HasUyuniServer)
}
7 changes: 7 additions & 0 deletions shared/test_utils/asserts.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,10 @@ func AssertEquals[T comparable](t *testing.T, message string, expected T, actual
t.Errorf(message+": got '%v' expected '%v'", actual, expected)
}
}

// AssertTrue ensures a value is true and raises and error if not.
func AssertTrue(t *testing.T, message string, actual bool) {
if !actual {
t.Errorf(message)
}
}
1 change: 1 addition & 0 deletions uyuni-tools.changes.oholecek.mgradm_reinstall
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- allow server installation with prexexisting storage volumes

0 comments on commit e4eee83

Please sign in to comment.