Skip to content
This repository has been archived by the owner on Feb 9, 2024. It is now read-only.

[7.0.x] loosen same OS requirement #1530

Merged
merged 1 commit into from
May 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
60 changes: 45 additions & 15 deletions lib/checks/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -772,28 +772,58 @@ func checkRAM(info ServerInfo, ram schema.RAM) error {
return nil
}

// checkSameOS makes sure all servers have the same OS/version
// checkSameOS verifies the OS distribution requirement for the specified set of servers.
// The check will pass if all nodes in the cluster are based on the same OS distribution and major version.
// Variance in minor/patch versions is acceptable.
func checkSameOS(servers []Server) error {
osToNodes := make(map[string][]string)
// distros maps distribution name to list of versions
distros := make(map[string][]string)
for _, server := range servers {
os := systeminfo.OS(server.GetOS()).Name()
osToNodes[os] = append(osToNodes[os], fmt.Sprintf("%v (%v)",
server.ServerInfo.GetHostname(), server.AdvertiseAddr))
info := server.GetOS()
distros[info.ID] = append(distros[info.ID], info.Version)
}
if len(distros) != 1 {
return trace.BadParameter("servers have different OS distributions: %v", formatKeysAsList(distros))
}
// Version verification is purposely simply and will compare the prefixes
// up to to either the first '.' or end of line
for _, versions := range distros {
if !verifyCommonVersionPrefix(versions...) {
return trace.BadParameter("servers have different OS versions: %v", formatAsList(distros))
}
}
log.Infof("Servers passed check for same OS: %v.", formatAsList(distros))
return nil
}

if len(osToNodes) > 1 {
var formatted []string
for os, nodes := range osToNodes {
formatted = append(formatted, fmt.Sprintf(
"%v: %v", os, strings.Join(nodes, ", ")))
func verifyCommonVersionPrefix(versions ...string) bool {
if len(versions) <= 1 {
return true
}
for i := 0; i < len(versions)-1; i += 1 {
if !strings.EqualFold(
strings.Split(versions[i], ".")[0],
strings.Split(versions[i+1], ".")[0]) {
return false
}
return trace.BadParameter(
"servers have different OSes/versions:\n%v",
strings.Join(formatted, "\n"))
}
return true
}

func formatAsList(m map[string][]string) (result []string) {
result = make([]string, 0, len(m))
for k, v := range m {
result = append(result, fmt.Sprintf("%v (%v)", k, v))
}
return result
}

log.Infof("Servers passed check for the same OS: %v.", osToNodes)
return nil
func formatKeysAsList(m map[string][]string) (result []string) {
result = make([]string, 0, len(m))
for k := range m {
result = append(result, k)
}
return result
}

// checkTime checks if time it out of sync between servers
Expand Down
85 changes: 58 additions & 27 deletions lib/checks/checks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,41 +118,72 @@ func (s *ChecksSuite) TestTime(c *check.C) {
}

func (s *ChecksSuite) TestCheckSameOS(c *check.C) {
infos := []Server{
var testCases = []struct {
comment string
servers []Server
err string
}{
{
ServerInfo: ServerInfo{
System: storage.NewSystemInfo(storage.SystemSpecV2{
Hostname: "node-1",
OS: storage.OSInfo{
ID: "centos",
Version: "7.1",
},
}),
comment: "servers match on the major version",
servers: []Server{
newServer("node-1", "centos", "7.1"),
newServer("node-2", "centos", "7.2"),
newServer("node-3", "centos", "7.2"),
},
},
{
ServerInfo: ServerInfo{
System: storage.NewSystemInfo(storage.SystemSpecV2{
Hostname: "node-2",
OS: storage.OSInfo{
ID: "centos",
Version: "7.2",
},
}),
comment: "servers do not match on the major version",
servers: []Server{
newServer("node-1", "centos", "7.1"),
newServer("node-2", "centos", "6.2"),
newServer("node-3", "centos", "7.2"),
},
err: "servers have different OS versions.*",
},
{
ServerInfo: ServerInfo{
System: storage.NewSystemInfo(storage.SystemSpecV2{
Hostname: "node-3",
OS: storage.OSInfo{
ID: "centos",
Version: "7.2",
},
}),
comment: "match on the whole version",
servers: []Server{
newServer("node-1", "centos", "7"),
newServer("node-2", "centos", "7"),
},
},
{
comment: "no match on the whole version",
servers: []Server{
newServer("node-1", "centos", "7"),
newServer("node-2", "centos", "6"),
},
err: "servers have different OS versions.*",
},
{
comment: "no match on distribution",
servers: []Server{
newServer("node-1", "centos", "7"),
newServer("node-2", "rhel", "7"),
},
err: "servers have different OS distributions.*",
},
}
for _, tc := range testCases {
comment := check.Commentf(tc.comment)
if tc.err != "" {
c.Assert(checkSameOS(tc.servers), check.ErrorMatches, tc.err, comment)
} else {
c.Assert(checkSameOS(tc.servers), check.IsNil, comment)
}
}
}

func newServer(hostname, os, version string) Server {
return Server{
ServerInfo: ServerInfo{
System: storage.NewSystemInfo(storage.SystemSpecV2{
Hostname: hostname,
OS: storage.OSInfo{
ID: os,
Version: version,
},
}),
},
}
c.Assert(checkSameOS(infos[:2]), check.NotNil)
c.Assert(checkSameOS(infos[1:]), check.IsNil)
}