Initial commit
This commit is contained in:
55
cmd/chkmqhealthy/main.go
Normal file
55
cmd/chkmqhealthy/main.go
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// chkmqhealthy checks that MQ is healthy, by checking the output of the "dspmq" command
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.ibm.com/mq-container/mq-container/pkg/name"
|
||||
)
|
||||
|
||||
func queueManagerHealthy() (bool, error) {
|
||||
name, err := name.GetQueueManagerName()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// Specify the queue manager name, just in case someone's created a second queue manager
|
||||
cmd := exec.Command("dspmq", "-n", "-m", name)
|
||||
// Run the command and wait for completion
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !strings.Contains(string(out), "(RUNNING)") {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
healthy, err := queueManagerHealthy()
|
||||
if err != nil {
|
||||
os.Exit(2)
|
||||
}
|
||||
if !healthy {
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
31
cmd/chkmqready/main.go
Normal file
31
cmd/chkmqready/main.go
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// chkmqready checks that MQ is ready for work, by checking if the MQ listener port is available
|
||||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn, err := net.Dial("tcp", "127.0.0.1:1414")
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
conn.Close()
|
||||
}
|
||||
87
cmd/runmqserver/crtmqvol.go
Normal file
87
cmd/runmqserver/crtmqvol.go
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017
|
||||
|
||||
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 main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
//const mainDir string := "/mnt/mqm"
|
||||
const mqmUID uint32 = 1000
|
||||
const mqmGID uint32 = 1000
|
||||
|
||||
func createVolume(path string) error {
|
||||
// fi, err := os.Stat(path)
|
||||
// if err != nil {
|
||||
// if os.IsNotExist(err) {
|
||||
// // TODO: Should this be fatal?
|
||||
// //log.Warnf("No volume found under %v", path)
|
||||
// return nil
|
||||
// } else {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
//log.Printf("%v details: %v", path, fi.Sys())
|
||||
dataPath := filepath.Join(path, "data")
|
||||
fi, err := os.Stat(dataPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = os.MkdirAll(dataPath, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fi, err = os.Stat(dataPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sys := fi.Sys()
|
||||
if sys != nil && runtime.GOOS == "linux" {
|
||||
// log.Printf("Checking UID/GID for %v", dataPath)
|
||||
//log.Debugf("Checking UID/GID for %v", dataPath)
|
||||
stat := sys.(*syscall.Stat_t)
|
||||
if stat.Uid != mqmUID || stat.Gid != mqmGID {
|
||||
err = os.Chown(dataPath, int(mqmUID), int(mqmGID))
|
||||
if err != nil {
|
||||
log.Printf("Error: Unable to change ownership of %v", dataPath)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// If /mnt/mqm exists
|
||||
// If /mnt/mqm contains a "data" directory AND data is owned by mqm:mqm AND data is writeable by mqm:mqm then
|
||||
// Create Symlink from /var/mqm to /mnt/mqm/data
|
||||
// Else
|
||||
// // Try to sort it out
|
||||
// Create directory /mnt/mqm/data
|
||||
// If directory not already owned by mqm:mqm
|
||||
// chown mqm:mqm
|
||||
// if error
|
||||
// delete directory again if empty
|
||||
// if directory not already 0755
|
||||
// chmod 0755
|
||||
// if error
|
||||
// delete directory again if empty
|
||||
331
cmd/runmqserver/main.go
Normal file
331
cmd/runmqserver/main.go
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// runmqserver initializes, creates and starts a queue manager, as PID 1 in a container
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/hpcloud/tail"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// resolveLicenseFile returns the file name of the MQ license file, taking into
|
||||
// account the language set by the LANG environment variable
|
||||
func resolveLicenseFile() string {
|
||||
lang, ok := os.LookupEnv("LANG")
|
||||
if !ok {
|
||||
return "English.txt"
|
||||
}
|
||||
switch {
|
||||
case strings.HasPrefix(lang, "zh_TW"):
|
||||
return "Chinese_TW.txt"
|
||||
case strings.HasPrefix(lang, "zh"):
|
||||
return "Chinese.txt"
|
||||
case strings.HasPrefix(lang, "cs"):
|
||||
return "Czech.txt"
|
||||
case strings.HasPrefix(lang, "fr"):
|
||||
return "French.txt"
|
||||
case strings.HasPrefix(lang, "de"):
|
||||
return "German.txt"
|
||||
case strings.HasPrefix(lang, "el"):
|
||||
return "Greek.txt"
|
||||
case strings.HasPrefix(lang, "id"):
|
||||
return "Indonesian.txt"
|
||||
case strings.HasPrefix(lang, "it"):
|
||||
return "Italian.txt"
|
||||
case strings.HasPrefix(lang, "ja"):
|
||||
return "Japanese.txt"
|
||||
case strings.HasPrefix(lang, "ko"):
|
||||
return "Korean.txt"
|
||||
case strings.HasPrefix(lang, "lt"):
|
||||
return "Lithuanian.txt"
|
||||
case strings.HasPrefix(lang, "pl"):
|
||||
return "Polish.txt"
|
||||
case strings.HasPrefix(lang, "pt"):
|
||||
return "Portugese.txt"
|
||||
case strings.HasPrefix(lang, "ru"):
|
||||
return "Russian.txt"
|
||||
case strings.HasPrefix(lang, "sl"):
|
||||
return "Slovenian.txt"
|
||||
case strings.HasPrefix(lang, "es"):
|
||||
return "Spanish.txt"
|
||||
case strings.HasPrefix(lang, "tr"):
|
||||
return "Turkish.txt"
|
||||
}
|
||||
return "English.txt"
|
||||
}
|
||||
|
||||
func checkLicense() {
|
||||
lic, ok := os.LookupEnv("LICENSE")
|
||||
switch {
|
||||
case ok && lic == "accept":
|
||||
return
|
||||
case ok && lic == "view":
|
||||
file := filepath.Join("/opt/mqm/licenses", resolveLicenseFile())
|
||||
buf, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(string(buf))
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("Error: Set environment variable LICENSE=accept to indicate acceptance of license terms and conditions.")
|
||||
fmt.Println("License agreements and information can be viewed by setting the environment variable LICENSE=view. You can also set the LANG environment variable to view the license in a different language.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// sanitizeQueueManagerName removes any invalid characters from a queue manager name
|
||||
func sanitizeQueueManagerName(name string) string {
|
||||
var re = regexp.MustCompile("[^a-zA-Z0-9._%/]")
|
||||
return re.ReplaceAllString(name, "")
|
||||
}
|
||||
|
||||
// GetQueueManagerName resolves the queue manager name to use. Resolved from
|
||||
// either an environment variable, or the hostname.
|
||||
func getQueueManagerName() (string, error) {
|
||||
var name string
|
||||
var err error
|
||||
name, ok := os.LookupEnv("MQ_QMGR_NAME")
|
||||
if !ok || name == "" {
|
||||
name, err = os.Hostname()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
name = sanitizeQueueManagerName(name)
|
||||
}
|
||||
// TODO: What if the specified env variable is an invalid name?
|
||||
return name, nil
|
||||
}
|
||||
|
||||
// runCommand runs an OS command. On Linux it waits for the command to
|
||||
// complete and returns the exit status (return code).
|
||||
func runCommand(name string, arg ...string) (string, int, error) {
|
||||
// log.Debugf("Running command %v %v", name, arg)
|
||||
cmd := exec.Command(name, arg...)
|
||||
// Run the command and wait for completion
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
var rc int
|
||||
// Only works on Linux
|
||||
if runtime.GOOS == "linux" {
|
||||
// func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error)
|
||||
var ws unix.WaitStatus
|
||||
//var rusage syscall.Rusage
|
||||
unix.Wait4(cmd.Process.Pid, &ws, 0, nil)
|
||||
//ee := err.(*os.SyscallError)
|
||||
//ws := ee.Sys().(syscall.WaitStatus)
|
||||
rc = ws.ExitStatus()
|
||||
} else {
|
||||
rc = -1
|
||||
}
|
||||
if rc == 0 {
|
||||
return string(out), rc, nil
|
||||
}
|
||||
return string(out), rc, err
|
||||
}
|
||||
return string(out), 0, nil
|
||||
}
|
||||
|
||||
// createDirStructure creates the default MQ directory structure under /var/mqm
|
||||
func createDirStructure() {
|
||||
out, _, err := runCommand("/opt/mqm/bin/crtmqdir", "-f", "-s")
|
||||
if err != nil {
|
||||
log.Fatalf("Error creating directory structure: %v\n", string(out))
|
||||
}
|
||||
log.Println("Created directory structure under /var/mqm")
|
||||
}
|
||||
|
||||
func createQueueManager(name string) {
|
||||
log.Printf("Creating queue manager %v", name)
|
||||
out, rc, err := runCommand("crtmqm", "-q", "-p", "1414", name)
|
||||
if err != nil {
|
||||
// 8=Queue manager exists, which is fine
|
||||
if rc != 8 {
|
||||
log.Printf("crtmqm returned %v", rc)
|
||||
log.Fatalln(string(out))
|
||||
} else {
|
||||
log.Printf("Detected existing queue manager %v", name)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateCommandLevel() {
|
||||
level, ok := os.LookupEnv("MQ_CMDLEVEL")
|
||||
if ok && level != "" {
|
||||
out, rc, err := runCommand("strmqm", "-e", "CMDLEVEL="+level)
|
||||
if err != nil {
|
||||
log.Fatalf("Error %v setting CMDLEVEL: %v", rc, string(out))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func startQueueManager() {
|
||||
out, rc, err := runCommand("strmqm")
|
||||
if err != nil {
|
||||
log.Fatalf("Error %v starting queue manager: %v", rc, string(out))
|
||||
}
|
||||
}
|
||||
|
||||
func configureQueueManager() {
|
||||
const configDir string = "/etc/mqm"
|
||||
files, err := ioutil.ReadDir(configDir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if strings.HasSuffix(file.Name(), ".mqsc") {
|
||||
abs := filepath.Join(configDir, file.Name())
|
||||
mqsc, err := ioutil.ReadFile(abs)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
cmd := exec.Command("runmqsc")
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
stdin.Write(mqsc)
|
||||
stdin.Close()
|
||||
// Run the command and wait for completion
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
// Print the runmqsc output, adding tab characters to make it more readable as part of the log
|
||||
log.Printf("Output for \"runmqsc\" with %v:\n\t%v", abs, strings.Replace(string(out), "\n", "\n\t", -1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func stopQueueManager() {
|
||||
log.Println("Stopping queue manager")
|
||||
out, _, err := runCommand("endmqm", "-w")
|
||||
if err != nil {
|
||||
log.Fatalf("Error stopping queue manager: %v", string(out))
|
||||
}
|
||||
log.Println("Stopped queue manager")
|
||||
}
|
||||
|
||||
// createTerminateChannel creates a channel which will be closed when SIGTERM
|
||||
// is received.
|
||||
func createTerminateChannel() chan struct{} {
|
||||
done := make(chan struct{})
|
||||
// Handle SIGTERM
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
|
||||
go func() {
|
||||
sig := <-c
|
||||
log.Printf("Signal received: %v", sig)
|
||||
stopQueueManager()
|
||||
close(done)
|
||||
}()
|
||||
return done
|
||||
}
|
||||
|
||||
// createReaperChannel creates a channel which will be used to reap zombie
|
||||
// (defunct) processes. This is a responsibility of processes running
|
||||
// as PID 1.
|
||||
func createReaper() {
|
||||
// Handle SIGCHLD
|
||||
c := make(chan os.Signal, 3)
|
||||
signal.Notify(c, syscall.SIGCHLD)
|
||||
go func() {
|
||||
for {
|
||||
<-c
|
||||
for {
|
||||
var ws unix.WaitStatus
|
||||
_, err := unix.Wait4(-1, &ws, 0, nil)
|
||||
// If err indicates "no child processes" left to reap, then
|
||||
// wait for next SIGCHLD signal
|
||||
if err == unix.ECHILD {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// mirrorLog tails the specified file, and logs each line.
|
||||
// This is useful for usability, as the container console log can show
|
||||
// messages from the MQ log.
|
||||
func mirrorLog(path string) error {
|
||||
tail, err := tail.TailFile(path, tail.Config{
|
||||
ReOpen: true,
|
||||
Follow: true,
|
||||
Poll: true,
|
||||
Location: &tail.SeekInfo{
|
||||
Offset: 0,
|
||||
// End of file
|
||||
Whence: 2,
|
||||
},
|
||||
Logger: tail.DiscardingLogger,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
for line := range tail.Lines {
|
||||
// TODO: Unless we parse the message, the timestamp will be (slightly) wrong
|
||||
if strings.HasPrefix(line.Text, "AMQ") {
|
||||
// TODO: Extended characters don't print correctly
|
||||
log.Println(line.Text)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
createReaper()
|
||||
checkLicense()
|
||||
|
||||
// Start SIGTERM handler channel
|
||||
done := createTerminateChannel()
|
||||
|
||||
name, err := getQueueManagerName()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
log.Printf("Using queue manager name: %v", name)
|
||||
logConfig()
|
||||
err = createVolume("/mnt/mqm")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
createDirStructure()
|
||||
mirrorLog("/var/mqm/qmgrs/" + name + "/errors/AMQERR01.LOG")
|
||||
createQueueManager(name)
|
||||
updateCommandLevel()
|
||||
startQueueManager()
|
||||
configureQueueManager()
|
||||
// Wait for terminate signal
|
||||
<-done
|
||||
}
|
||||
34
cmd/runmqserver/main_test.go
Normal file
34
cmd/runmqserver/main_test.go
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017
|
||||
|
||||
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 main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var test *bool
|
||||
|
||||
func init() {
|
||||
test = flag.Bool("test", false, "Set to true when running tests for coverage")
|
||||
}
|
||||
|
||||
// Test started when the test binary is started. Only calls main.
|
||||
func TestSystem(t *testing.T) {
|
||||
if *test {
|
||||
main()
|
||||
}
|
||||
}
|
||||
135
cmd/runmqserver/mqconfig.go
Normal file
135
cmd/runmqserver/mqconfig.go
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2017
|
||||
|
||||
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 main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// fsTypes contains file system identifier codes.
|
||||
// This code will not compile on some operating systems - Linux only.
|
||||
var fsTypes = map[int64]string{
|
||||
0x61756673: "aufs",
|
||||
0xef53: "ext",
|
||||
0x6969: "nfs",
|
||||
0x65735546: "fuse",
|
||||
0x9123683e: "btrfs",
|
||||
0x01021994: "tmpfs",
|
||||
0x794c7630: "overlayfs",
|
||||
}
|
||||
|
||||
func logBaseImage() error {
|
||||
buf, err := ioutil.ReadFile("/etc/os-release")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lines := strings.Split(string(buf), "\n")
|
||||
for _, l := range lines {
|
||||
if strings.HasPrefix(l, "PRETTY_NAME=") {
|
||||
words := strings.Split(l, "\"")
|
||||
if len(words) >= 2 {
|
||||
log.Printf("Base image detected: %v", words[1])
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readProc(filename string) (value string, err error) {
|
||||
buf, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(string(buf)), nil
|
||||
}
|
||||
|
||||
func readMounts() error {
|
||||
all, err := readProc("/proc/mounts")
|
||||
if err != nil {
|
||||
log.Println("Error: Couldn't read /proc/mounts")
|
||||
return err
|
||||
}
|
||||
lines := strings.Split(all, "\n")
|
||||
detected := false
|
||||
for i := range lines {
|
||||
parts := strings.Split(lines[i], " ")
|
||||
//dev := parts[0]
|
||||
mountPoint := parts[1]
|
||||
fsType := parts[2]
|
||||
if strings.Contains(mountPoint, "/mnt") {
|
||||
log.Printf("Detected '%v' volume mounted to %v", fsType, mountPoint)
|
||||
detected = true
|
||||
}
|
||||
}
|
||||
if !detected {
|
||||
log.Println("No volume detected. Persistent messages may be lost")
|
||||
} else {
|
||||
checkFS("/mnt/mqm")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkFS(path string) {
|
||||
statfs := &unix.Statfs_t{}
|
||||
err := unix.Statfs(path, statfs)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
t := fsTypes[statfs.Type]
|
||||
switch t {
|
||||
case "aufs", "overlayfs", "tmpfs":
|
||||
log.Fatalf("Error: %v uses unsupported filesystem type %v", path, t)
|
||||
default:
|
||||
log.Printf("Detected %v has filesystem type '%v'", path, t)
|
||||
}
|
||||
}
|
||||
|
||||
func logConfig() {
|
||||
log.Printf("CPU architecture: %v", runtime.GOARCH)
|
||||
// TODO: You can't use os.user if you're cross-compiling
|
||||
// u, err := user.Current()
|
||||
// if err != nil {
|
||||
// log.Println(err)
|
||||
// } else {
|
||||
// log.Printf("Running as user ID %v (%v) with primary group %v", u.Uid, u.Name, u.Gid)
|
||||
// }
|
||||
if runtime.GOOS == "linux" {
|
||||
var err error
|
||||
osr, err := readProc("/proc/sys/kernel/osrelease")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
} else {
|
||||
log.Printf("Linux kernel version: %v", osr)
|
||||
}
|
||||
logBaseImage()
|
||||
fileMax, err := readProc("/proc/sys/fs/file-max")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
} else {
|
||||
log.Printf("Maximum file handles: %v", fileMax)
|
||||
}
|
||||
readMounts()
|
||||
} else {
|
||||
log.Fatalf("Unsupported platform: %v", runtime.GOOS)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user