You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@trafficcontrol.apache.org by GitBox <gi...@apache.org> on 2020/07/15 16:48:41 UTC

[GitHub] [trafficcontrol] jrushford commented on a change in pull request #4872: traffic_ops_ort.pl transliteration to go

jrushford commented on a change in pull request #4872:
URL: https://github.com/apache/trafficcontrol/pull/4872#discussion_r455189915



##########
File path: traffic_ops_ort/traffic_ops_t3c/util/util.go
##########
@@ -0,0 +1,383 @@
+package util
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"github.com/apache/trafficcontrol/lib/go-log"
+	"github.com/apache/trafficcontrol/traffic_ops_ort/traffic_ops_t3c/config"
+	"github.com/gofrs/flock"
+	"io/ioutil"
+	"math/rand"
+	"os"
+	"os/exec"
+	"os/user"
+	"path/filepath"
+	"strings"
+	"time"
+)
+
+const OneWeek = 604800
+
+type FileLock struct {
+	f_lock    *flock.Flock
+	is_locked bool
+}
+
+// Try to get a file lock, non-blocking.
+func (f *FileLock) GetLock(lockFile string) bool {
+	f.f_lock = flock.New(lockFile)
+	is_locked, err := f.f_lock.TryLock()
+	f.is_locked = is_locked
+
+	if err != nil { // some OS error attempting to obtain a file lock
+		log.Errorf("unable to obtain a lock on %s\n", lockFile)
+		return false
+	}
+	if !f.is_locked { // another process is running.
+		log.Errorf("Another traffic_ops_t3c process is already running, try again later\n")
+		return false
+	}
+
+	return f.is_locked
+}
+
+// Releases a file lock and exits with the given status code.
+func (f *FileLock) UnlockAndExit(code int) {
+	if f.is_locked {
+		f.f_lock.Unlock()
+	}
+	os.Exit(code)
+}
+
+func DirectoryExists(dir string) (bool, os.FileInfo) {
+	info, err := os.Stat(dir)
+	if os.IsNotExist(err) {
+		return false, nil
+	}
+	return info.IsDir(), info
+}
+
+func ExecCommand(fullCommand string, arg ...string) ([]byte, int, error) {
+	var output bytes.Buffer
+	cmd := exec.Command(fullCommand, arg...)
+	cmd.Stdout = &output
+	err := cmd.Run()
+	return output.Bytes(), cmd.ProcessState.ExitCode(), err
+}
+
+func FileExists(fn string) (bool, os.FileInfo) {
+	info, err := os.Stat(fn)
+	if os.IsNotExist(err) {
+		return false, nil
+	}
+	return !info.IsDir(), info
+}
+
+func ReadFile(fn string) ([]byte, error) {
+	var data []byte
+	info, err := os.Stat(fn)
+	if err != nil {
+		return nil, err
+	}
+	size := info.Size()
+
+	fd, err := os.Open(fn)
+	if err != nil {
+		return nil, err
+	}
+	data = make([]byte, size)
+	c, err := fd.Read(data)
+	if err != nil || int64(c) != size {
+		return nil, errors.New("unable to completely read from '" + fn + "': " + err.Error())
+	}
+	fd.Close()
+
+	return data, nil
+}
+
+func serviceStatus(name string) (int, error) {
+	var pid int = -1
+	var result bool
+
+	// the service command returns an error and return code of '3'
+	// if a service is loaded and not running.  So if rc == 3, ignore
+	// the error
+	output, rc, err := ExecCommand("/usr/sbin/service", name, "status")
+	if err != nil && rc != 3 {
+		return pid, errors.New("could not get status for service '" + name + "'\n")
+	}
+	lines := strings.Split(string(output), "\n")
+	for ii := range lines {
+		line := strings.TrimSpace(lines[ii])
+		if strings.Contains(line, "Active: active") {
+			result = true
+		}
+		if result && strings.Contains(line, "Main PID: ") {
+			fmt.Sscanf(line, "Main PID: %d", &pid)
+		}
+	}
+
+	return pid, nil
+}
+
+// start or restart the service 'service'. cmd is 'start | restart'
+func ServiceStart(service string, cmd string) (bool, error) {
+	log.Infof("ServiceStart called for '%s'\n", service)
+	pid, err := serviceStatus(service)
+	if err != nil {
+		return false, errors.New("Could not get status for '" + service + "' : " + err.Error())
+	} else if pid > 0 && cmd == "start" {
+		log.Infof("service '%s' is already running, pid: %d\n", service, pid)
+	} else {
+		_, rc, err := ExecCommand("/usr/sbin/service", service, cmd)
+		if err != nil {
+			return false, errors.New("Could not " + cmd + " the '" + service + "' service: " + err.Error())
+		} else if rc == 0 {
+			// service was sucessfully started
+			return true, nil
+		}
+	}
+	// not started, service is already running
+	return false, nil
+}
+
+func WriteFile(fn string, data []byte, perm os.FileMode) (int, error) {
+	return WriteFileWithOwner(fn, data, -1, -1, perm)
+}
+
+func WriteFileWithOwner(fn string, data []byte, uid int, gid int, perm os.FileMode) (int, error) {
+	fd, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+	if err != nil {
+		return 0, errors.New("unable to open '" + fn + "' for writing: " + err.Error())
+	}
+
+	c, err := fd.Write(data)
+	if err != nil {
+		return 0, errors.New("error writing to '" + fn + "': " + err.Error())
+	}
+	fd.Close()
+
+	if uid > -1 && gid > -1 {
+		err = os.Chown(fn, uid, gid)
+		if err != nil {
+			return 0, errors.New("error changing ownership on '" + fn + "': " + err.Error())
+		}
+	}
+	return c, nil
+}
+
+func PackageAction(cmdstr string, name string) (bool, error) {
+	var rc int = -1
+	var err error = nil
+	var result bool = false
+
+	switch cmdstr {
+	case "info":
+		_, rc, err = ExecCommand("/usr/bin/yum", "info", name)
+	case "install":
+		_, rc, err = ExecCommand("/usr/bin/yum", "install", "-y", name)
+	case "remove":
+		_, rc, err = ExecCommand("/usr/bin/yum", "remove", "-y", name)
+	}
+
+	if rc == 0 {
+		result = true
+		err = nil
+	}
+	return result, err
+}
+
+// runs the rpm command.
+// if the return code from rpm == 0, then a valid package list is returned.
+//
+// if the return code is 1, the the 'name' queried for is not part of a
+//   package or is not installed.
+//
+// otherwise, if the return code is not 0 or 1 and error is set, a general
+// rpm command execution error is assumed and the error is returned.
+func PackageInfo(cmdstr string, name string) ([]string, error) {
+	var result []string
+	switch cmdstr {
+	case "cfg-files": // returns a list of the package configuration files.
+		output, rc, err := ExecCommand("/bin/rpm", "-q", "-c", name)
+		if rc == 1 { // rpm package for 'name' was not found.
+			return nil, nil
+		} else if rc == 0 { // add the package name the file belongs to.
+			log.Debugf("output from cfg-files query: %s\n", string(output))
+			files := strings.Split(string(output), "\n")
+			for ii := range files {
+				result = append(result, strings.TrimSpace(files[ii]))
+			}
+			log.Debugf("result length: %d, result: %s\n", len(result), string(output))
+		} else if err != nil {
+			return nil, err
+		}
+	case "file-query": // returns the rpm name that owns the file 'name'
+		output, rc, err := ExecCommand("/bin/rpm", "-q", "-f", name)
+		if rc == 1 { // file is not part of any package.
+			return nil, nil
+		} else if rc == 0 { // add the package name the file belongs to.
+			log.Debugf("output from file-query: %s\n", string(output))
+			result = append(result, string(strings.TrimSpace(string(output))))
+			log.Debugf("result length: %d, result: %s\n", len(result), string(output))
+		} else if err != nil {
+			return nil, err
+		}
+	case "pkg-provides": // returns the package name that provides 'name'
+		output, rc, err := ExecCommand("/bin/rpm", "-q", "--whatprovides", name)
+		log.Debugf("pkg-provides - name: %s, output: %s\n", name, output)
+		if rc == 1 { // no package provides 'name'
+			return nil, nil
+		} else if rc == 0 {
+			pkgs := strings.Split(string(output), "\n")
+			for ii := range pkgs {
+				result = append(result, strings.TrimSpace(pkgs[ii]))
+			}
+		} else if err != nil {
+			return nil, err
+		}
+	case "pkg-query": // returns the package name for 'name'.
+		output, rc, err := ExecCommand("/bin/rpm", "-q", name)
+		if rc == 1 { // the package is not installed.
+			return nil, nil
+		} else if rc == 0 { // add the rpm name
+			result = append(result, string(strings.TrimSpace(string(output))))
+		} else if err != nil {
+			return nil, err
+		}
+	case "pkg-requires": // returns a list of packages that requires package 'name'
+		output, rc, err := ExecCommand("/bin/rpm", "-q", "--whatrequires", name)
+		if rc == 1 { // no package reuires package 'name'
+			return nil, nil
+		} else if rc == 0 {
+			pkgs := strings.Split(string(output), "\n")
+			for ii := range pkgs {
+				result = append(result, strings.TrimSpace(pkgs[ii]))
+			}
+		} else if err != nil {
+			return nil, err
+		}
+	}
+	return result, nil
+}
+
+func RandomDuration(max time.Duration) time.Duration {
+	rand.Seed(time.Now().UnixNano())
+	return time.Duration(rand.Int63n(int64(max)))

Review comment:
       I've fixed this.  Had a math issue




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org