cli_tools/import_precheck/precheck/check_osversion.go (86 lines of code) (raw):
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package precheck
import (
"fmt"
"strings"
"github.com/GoogleCloudPlatform/osconfig/osinfo"
"github.com/GoogleCloudPlatform/compute-image-import/cli_tools/common/distro"
"github.com/GoogleCloudPlatform/compute-image-import/cli_tools/common/utils/daisyutils"
)
const (
docsURL = "https://cloud.google.com/sdk/gcloud/reference/compute/images/import"
)
// OSVersionCheck is a precheck.Check that verifies the disk's operating system is importable.
type OSVersionCheck struct {
OSInfo *osinfo.OSInfo
}
// GetName returns the name of the precheck step; this is shown to the user.
func (c *OSVersionCheck) GetName() string {
return "OS Version Check"
}
// Run executes the precheck step.
func (c *OSVersionCheck) Run() (*Report, error) {
r := &Report{name: c.GetName()}
// Find osID from OS config's detection results.
major, minor := splitOSVersion(c.OSInfo.Version)
osID := c.createOSID(major, minor, r)
if osID == "" {
r.Info("Unable to determine whether your system is supported for import. " +
"For supported versions, see " + docsURL)
r.result = Skipped
return r, nil
}
// Check whether the osID is supported for import.
// Some systems are only available as BYOL, so check for both osID variants.
var supported bool
for _, suffix := range []string{"", "-byol"} {
if daisyutils.ValidateOS(osID+suffix) == nil {
supported = true
break
}
}
if supported {
if c.OSInfo.ShortName == osinfo.Windows {
// Emit the NT version for Windows, since the same NT version is
// either Desktop or Server, and we don't want to emit a misleading message.
r.Info(fmt.Sprintf("Detected Windows version number: NT %s", c.OSInfo.Version))
} else {
r.Info(fmt.Sprintf("Detected system: %s", osID))
}
} else {
r.Fatal(osID + " is not supported for import. For supported versions, see " + docsURL)
}
return r, nil
}
// createOSID creates the osID, as used in the `--os` flag of the CLI tools. An empty string is
// return when unable to determine the osID.
func (c *OSVersionCheck) createOSID(originalMajor string, originalMinor string, r *Report) string {
major, minor := originalMajor, originalMinor
switch c.OSInfo.ShortName {
case "":
r.Info("Unable to determine OS.")
return ""
case osinfo.Linux:
// OS config returns "linux" as the distro when it can't find a more specific match.
r.Info("Detected generic Linux system.")
return ""
case osinfo.Windows:
r.Info("Detected Windows system.")
// OS config uses NT version numbers, while cli_tools/common/distro uses marketing verions.
windowsMajor, windowsMinor, err :=
distro.WindowsServerVersionforNTVersion(originalMajor, originalMinor)
if err == nil {
major, minor = windowsMajor, windowsMinor
}
}
release, err := distro.FromComponents(c.OSInfo.ShortName, major, minor, c.OSInfo.Architecture)
if err != nil {
r.Info(err.Error())
return ""
}
osID := release.AsGcloudArg()
if osID != "" {
return osID
}
// If the distro package can't determine the osID, attempt to create one using
// the format "os-version".
if c.OSInfo.ShortName != osinfo.Linux && c.OSInfo.ShortName != "" && c.OSInfo.Version != "" {
return fmt.Sprintf("%s-%s", c.OSInfo.ShortName, c.OSInfo.Version)
}
return ""
}
func splitOSVersion(version string) (major, minor string) {
if version == "" {
return "", ""
}
if !strings.Contains(version, ".") {
return version, ""
}
parts := strings.Split(version, ".")
return parts[0], parts[1]
}