#L3PD: bsc#1246068
diff --git a/mgradm/cmd/distro/cp.go b/mgradm/cmd/distro/cp.go
index 56aaedec..811ff2b9 100644
--- a/mgradm/cmd/distro/cp.go
+++ b/mgradm/cmd/distro/cp.go
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: 2024 SUSE LLC
+// SPDX-FileCopyrightText: 2025 SUSE LLC
 //
 // SPDX-License-Identifier: Apache-2.0
 
@@ -7,6 +7,7 @@ package distro
 import (
 	"errors"
 	"fmt"
+	"os"
 	"strings"
 
 	"github.com/rs/zerolog"
@@ -21,13 +22,19 @@ import (
 	"github.com/uyuni-project/uyuni-tools/shared/utils"
 )
 
+func isRoot() bool {
+	return os.Geteuid() == 0
+}
+
 func umount(mountpoint string) {
-	umountCmd := []string{
-		"/usr/bin/umount",
-		mountpoint,
+	umountCmd := []string{}
+
+	if !isRoot() {
+		umountCmd = []string{"/usr/bin/sudo"}
 	}
+	umountCmd = append(umountCmd, "/usr/bin/umount", mountpoint)
 
-	if err := utils.RunCmd("/usr/bin/sudo", umountCmd...); err != nil {
+	if err := utils.RunCmd(umountCmd[0], umountCmd[1:]...); err != nil {
 		log.Error().Err(err).Msgf(L("Unable to unmount ISO image, leaving %s intact"), mountpoint)
 	}
 }
@@ -78,16 +85,18 @@ func prepareSource(source string) (string, func(), error) {
 		}
 		srcdir = tmpdir
 
-		mountCmd := []string{
-			"/usr/bin/mount",
-			"-o", "ro,loop",
-			source,
-			srcdir,
+		mountCmd := []string{}
+		if !isRoot() {
+			mountCmd = []string{"/usr/bin/sudo"}
 		}
-		if out, err := utils.RunCmdOutput(zerolog.DebugLevel, "/usr/bin/sudo", mountCmd...); err != nil {
+		mountCmd = append(mountCmd, "/usr/bin/mount", "-o", "ro,loop", source, srcdir)
+
+		if out, err := utils.RunCmdOutput(zerolog.DebugLevel, mountCmd[0], mountCmd[1:]...); err != nil {
 			log.Debug().Msgf("Error mounting ISO image: '%s'", out)
 			return "", cleaner, fmt.Errorf(L("unable to mount ISO image: %s"), out)
 		}
+		// Not sure why, but cleaner is not setup once we leave if statement :/
+		return srcdir, cleaner, nil
 	}
 	return srcdir, cleaner, nil
 }
@@ -146,15 +155,19 @@ func distroCp(
 	}
 
 	srcdir, cleaner, err := prepareSource(source)
-	if err != nil {
-		return err
-	}
+	// Non-nil cleaner means tmpdir was successful, but mount failed. We need to defer cleanup
 	if cleaner != nil {
 		defer func() {
-			umount(srcdir)
+			// If on top err is nill, all was successful, need umount
+			if err == nil {
+				umount(srcdir)
+			}
 			cleaner()
 		}()
 	}
+	if err != nil {
+		return err
+	}
 
 	distribution := types.Distribution{}
 	if err := detectDistro(srcdir, distroDetails, flags, &distribution); err != nil {
@@ -162,7 +175,7 @@ func distroCp(
 		if attemptRegistration {
 			return err
 		}
-		log.Debug().Msgf("Would not be able to auto register")
+		log.Debug().Msg("Would not be able to auto register")
 		if len(distroDetails.Name) == 0 {
 			// If there is no hint, just use ISO/dir name
 			distroDetails.Name = getNameFromSource(source)
diff --git a/mgradm/cmd/distro/detect.go b/mgradm/cmd/distro/detect.go
index 1d2cd90d..c0c342e7 100644
--- a/mgradm/cmd/distro/detect.go
+++ b/mgradm/cmd/distro/detect.go
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: 2024 SUSE LLC
+// SPDX-FileCopyrightText: 2025 SUSE LLC
 //
 // SPDX-License-Identifier: Apache-2.0
 
@@ -18,23 +18,24 @@ import (
 	"github.com/uyuni-project/uyuni-tools/shared/utils"
 )
 
-var productMap = map[string]map[string]map[types.Arch]types.Distribution{
-	"SUSE Linux Enterprise": {
-		"15 SP4": {
+// Viper unmarshal keys in lowercase, we need to keep our bundled product map lowerkey as well.
+var defaultProductMap = types.ProductMap{
+	"suse linux enterprise": {
+		"15 sp4": {
 			types.AMD64: {
 				TreeLabel:    "SLES15SP4",
 				InstallType:  "sles15generic",
 				ChannelLabel: "sle-product-sles15-sp4-pool-x86_64",
 			},
 		},
-		"15 SP5": {
+		"15 sp5": {
 			types.AMD64: {
 				TreeLabel:    "SLES15SP5",
 				InstallType:  "sles15generic",
 				ChannelLabel: "sle-product-sles15-sp5-pool-x86_64",
 			},
 		},
-		"15 SP6": {
+		"15 sp6": {
 			types.AMD64: {
 				TreeLabel:    "SLES15SP6",
 				InstallType:  "sles15generic",
@@ -46,7 +47,19 @@ var productMap = map[string]map[string]map[types.Arch]types.Distribution{
 				ChannelLabel: "sle-product-sles15-sp6-pool-aarch64",
 			},
 		},
-		"12 SP5": {
+		"15 sp7": {
+			types.AMD64: {
+				TreeLabel:    "SLES15SP7",
+				InstallType:  "sles15generic",
+				ChannelLabel: "sle-product-sles15-sp7-pool-x86_64",
+			},
+			types.AArch64: {
+				TreeLabel:    "SLES15SP7",
+				InstallType:  "sles15generic",
+				ChannelLabel: "sle-product-sles15-sp7-pool-aarch64",
+			},
+		},
+		"12 sp5": {
 			types.AMD64: {
 				TreeLabel:    "SLES12SP5",
 				InstallType:  "sles12generic",
@@ -55,7 +68,7 @@ var productMap = map[string]map[string]map[types.Arch]types.Distribution{
 		},
 	},
 
-	"Red Hat Enterprise Linux": {
+	"red hat enterprise linux": {
 		"7": {
 			types.AMD64: {
 				TreeLabel:    "RHEL7",
@@ -85,10 +98,14 @@ func getDistroFromDetails(distro string, version string, arch types.Arch, flags
 	var distribution types.Distribution
 	var ok bool
 
+	// product map is all lowercase, make sure we match case sensitive go lookup
+	distro = strings.ToLower(distro)
+	version = strings.ToLower(version)
+
 	if productFromConfig[distro] != nil {
 		distribution, ok = productFromConfig[distro][version][arch]
-	} else if productMap[distro] != nil {
-		distribution, ok = productMap[distro][version][arch]
+	} else if defaultProductMap[distro] != nil {
+		distribution, ok = defaultProductMap[distro][version][arch]
 	}
 
 	if !ok {
@@ -128,24 +145,24 @@ func detectDistro(
 ) error {
 	treeinfopath := filepath.Join(path, ".treeinfo")
 	channelLabel := flags.ChannelLabel
-	if !utils.FileExists(treeinfopath) {
-		log.Debug().Msgf(".treeinfo %s does not exists", treeinfopath)
-		if distroDetails.Name != "" {
-			if channelLabel != "" {
-				log.Debug().Msg("Using channel override")
-				*distro = types.Distribution{
-					InstallType:  "generic_rpm",
-					TreeLabel:    distroDetails.Name,
-					ChannelLabel: channelLabel,
-				}
-				return nil
-			} else if distroDetails.Version != "" && distroDetails.Arch != types.UnknownArch {
-				log.Debug().Msg("Using distro details override")
-				var err error
-				*distro, err = getDistroFromDetails(distroDetails.Name, distroDetails.Version, distroDetails.Arch, flags)
-				return err
+	if distroDetails.Name != "" {
+		if channelLabel != "" {
+			log.Debug().Msg("Using channel override")
+			*distro = types.Distribution{
+				InstallType:  "suse",
+				TreeLabel:    distroDetails.Name,
+				ChannelLabel: channelLabel,
 			}
+			return nil
+		} else if distroDetails.Version != "" && distroDetails.Arch != types.UnknownArch {
+			log.Debug().Msg("Using distro details override")
+			var err error
+			*distro, err = getDistroFromDetails(distroDetails.Name, distroDetails.Version, distroDetails.Arch, flags)
+			return err
 		}
+	} else if utils.FileExists(treeinfopath) {
+		log.Debug().Msgf("Using .treeinfo %s", treeinfopath)
+	} else {
 		return fmt.Errorf(
 			L("distribution treeinfo %s does not exists. Please provide distribution details and/or channel label"),
 			treeinfopath,
diff --git a/mgradm/cmd/distro/distro.go b/mgradm/cmd/distro/distro.go
index a0d527ab..ddcecfbd 100644
--- a/mgradm/cmd/distro/distro.go
+++ b/mgradm/cmd/distro/distro.go
@@ -19,13 +19,21 @@ import (
 
 type flagpole struct {
 	Backend           string
-	ChannelLabel      string `mapstructure:"channel"`
-	ProductMap        map[string]map[string]map[types.Arch]types.Distribution
+	ChannelLabel      string                `mapstructure:"channel"`
+	ProductMap        types.ProductMap      `mapstructure:"ProductMap"`
 	ConnectionDetails api.ConnectionDetails `mapstructure:"api"`
 }
 
 type productMapTemplateData struct {
-	DefaultProductMap string
+	DefaultProductMapRender string
+	ProductMapRender        string
+}
+
+func prettyPrint(productMap types.ProductMap) string {
+	if prettyPrintedProductMapBytes, err := yaml.Marshal(map[string]interface{}{"ProductMap": productMap}); err == nil {
+		return string(prettyPrintedProductMapBytes)
+	}
+	return ""
 }
 
 func getProductMapHelp() string {
@@ -46,7 +54,7 @@ ProductMap:
       <distribution architecture>:
         ChannelLabel: <channel label>
         InstallType: <one of rhel_7|rhel_8|rhel_9|sles12generic|sles15generic|generic_rpm>
-        TreeName: <custom distribution name>
+        TreeLabel: <custom distribution name>
 
 Where
 * <distribution name> is the name of the distribution, by default taken from '.treeinfo' file from the media.
@@ -58,14 +66,43 @@ Where
 * ChannelLabel is the channel label from Uyuni server and which is to be used for this distribution;
   can be overridden by command line flag.
 * InstallType is used when installer is known (for autoyast or kickstart) or use 'generic_rpm'.
-* TreeName is how the distribution will be presented in the Uyuni server UI. If not set <distribution name> is used.
+* TreeLabel is how the distribution will be presented in the Uyuni server UI. If not set <distribution name> is used.
 
 Build-in product map:
 
-{{ .DefaultProductMap }}
+{{ .DefaultProductMapRender }}
 `)
 }
 
+func showHelp(_ *types.GlobalFlags,
+	flags *flagpole,
+	_ *cobra.Command,
+	_ []string,
+) error {
+	mergedMaps := make(types.ProductMap, len(defaultProductMap))
+	for k, v := range defaultProductMap {
+		mergedMaps[k] = v
+	}
+	for distro, versions := range flags.ProductMap {
+		if _, ok := mergedMaps[distro]; ok {
+			for version, archs := range versions {
+				if _, ok := mergedMaps[distro][version]; ok {
+					for arch, distroDetail := range archs {
+						// product map from config file has prio, overwrite
+						mergedMaps[distro][version][arch] = distroDetail
+					}
+				} else {
+					mergedMaps[distro][version] = archs
+				}
+			}
+		} else {
+			mergedMaps[distro] = versions
+		}
+	}
+	print(prettyPrint(mergedMaps))
+	return nil
+}
+
 func newCmd(globalFlags *types.GlobalFlags, run utils.CommandFunc[flagpole]) (*cobra.Command, error) {
 	var flags flagpole
 
@@ -98,17 +135,17 @@ Note: API details are required for auto registration.`),
 
 	cpCmdHelp := &cobra.Command{
 		Use:   "productmap",
-		Short: L("Help on using custom distribution product map"),
-	}
-	prettyPrintedProductMap := ""
-	if prettyPrintedProductMapBytes, err := yaml.Marshal(map[string]interface{}{"ProductMap": productMap}); err == nil {
-		prettyPrintedProductMap = string(prettyPrintedProductMapBytes)
+		Short: L("Show distribution product map"),
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return utils.CommandHelper(globalFlags, cmd, args, &flags, nil, showHelp)
+		},
 	}
 
 	t := template.Must(template.New("help").Parse(getProductMapHelp()))
 	var helpBuilder strings.Builder
 	if err := t.Execute(&helpBuilder, productMapTemplateData{
-		DefaultProductMap: prettyPrintedProductMap,
+		DefaultProductMapRender: prettyPrint(defaultProductMap),
+		ProductMapRender:        prettyPrint(flags.ProductMap),
 	}); err != nil {
 		log.Fatal().Err(err).Msg(L("failed to compute config help command"))
 	}
diff --git a/shared/types/distro.go b/shared/types/distro.go
index 02ab79a5..cc253554 100644
--- a/shared/types/distro.go
+++ b/shared/types/distro.go
@@ -19,6 +19,9 @@ type DistributionDetails struct {
 	Arch    Arch
 }
 
+// ProductMap contains mapping of distro, version arch to the Distribution.
+type ProductMap map[string]map[string]map[Arch]Distribution
+
 // Arch type to store architecture.
 type Arch string
 
