mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-12 14:18:32 +00:00
Fixes for PT-66
This commit is contained in:
@@ -2,6 +2,8 @@ package util
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -18,3 +20,36 @@ func Pretty(value interface{}) string {
|
|||||||
bytes, _ := json.MarshalIndent(value, "", " ")
|
bytes, _ := json.MarshalIndent(value, "", " ")
|
||||||
return string(bytes)
|
return string(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoadJson(filename string, destination interface{}) error {
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(buf, &destination)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteJson(filename string, data interface{}) error {
|
||||||
|
|
||||||
|
buf, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(filename, buf, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
205
src/go/mongolib/util/main_test.go
Normal file
205
src/go/mongolib/util/main_test.go
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
mgo "gopkg.in/mgo.v2"
|
||||||
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
lutil "github.com/percona/percona-toolkit/src/go/lib/util"
|
||||||
|
"github.com/percona/percona-toolkit/src/go/mongolib/proto"
|
||||||
|
"github.com/percona/pmgo/pmgomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OK
|
||||||
|
func TestGetReplicasetMembers(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
dialer := pmgomock.NewMockDialer(ctrl)
|
||||||
|
|
||||||
|
session := pmgomock.NewMockSessionManager(ctrl)
|
||||||
|
|
||||||
|
mockrss := proto.ReplicaSetStatus{
|
||||||
|
Date: "",
|
||||||
|
MyState: 1,
|
||||||
|
Term: 0,
|
||||||
|
HeartbeatIntervalMillis: 0,
|
||||||
|
Members: []proto.Members{
|
||||||
|
proto.Members{
|
||||||
|
Optime: nil,
|
||||||
|
OptimeDate: "",
|
||||||
|
InfoMessage: "",
|
||||||
|
ID: 0,
|
||||||
|
Name: "localhost:17001",
|
||||||
|
Health: 1,
|
||||||
|
StateStr: "PRIMARY",
|
||||||
|
Uptime: 113287,
|
||||||
|
ConfigVersion: 1,
|
||||||
|
Self: true,
|
||||||
|
State: 1,
|
||||||
|
ElectionTime: 6340960613392449537,
|
||||||
|
ElectionDate: "",
|
||||||
|
Set: ""},
|
||||||
|
proto.Members{
|
||||||
|
Optime: nil,
|
||||||
|
OptimeDate: "",
|
||||||
|
InfoMessage: "",
|
||||||
|
ID: 1,
|
||||||
|
Name: "localhost:17002",
|
||||||
|
Health: 1,
|
||||||
|
StateStr: "SECONDARY",
|
||||||
|
Uptime: 113031,
|
||||||
|
ConfigVersion: 1,
|
||||||
|
Self: false,
|
||||||
|
State: 2,
|
||||||
|
ElectionTime: 0,
|
||||||
|
ElectionDate: "",
|
||||||
|
Set: ""},
|
||||||
|
proto.Members{
|
||||||
|
Optime: nil,
|
||||||
|
OptimeDate: "",
|
||||||
|
InfoMessage: "",
|
||||||
|
ID: 2,
|
||||||
|
Name: "localhost:17003",
|
||||||
|
Health: 1,
|
||||||
|
StateStr: "SECONDARY",
|
||||||
|
Uptime: 113031,
|
||||||
|
ConfigVersion: 1,
|
||||||
|
Self: false,
|
||||||
|
State: 2,
|
||||||
|
ElectionTime: 0,
|
||||||
|
ElectionDate: "",
|
||||||
|
Set: ""}},
|
||||||
|
Ok: 1,
|
||||||
|
Set: "r1",
|
||||||
|
}
|
||||||
|
expect := []proto.Members{
|
||||||
|
proto.Members{
|
||||||
|
Optime: nil,
|
||||||
|
OptimeDate: "",
|
||||||
|
InfoMessage: "",
|
||||||
|
ID: 0,
|
||||||
|
Name: "localhost:17001",
|
||||||
|
Health: 1,
|
||||||
|
StateStr: "PRIMARY",
|
||||||
|
Uptime: 113287,
|
||||||
|
ConfigVersion: 1,
|
||||||
|
Self: true,
|
||||||
|
State: 1,
|
||||||
|
ElectionTime: 6340960613392449537,
|
||||||
|
ElectionDate: "",
|
||||||
|
Set: "r1"},
|
||||||
|
proto.Members{Optime: (*proto.Optime)(nil),
|
||||||
|
OptimeDate: "",
|
||||||
|
InfoMessage: "",
|
||||||
|
ID: 1,
|
||||||
|
Name: "localhost:17002",
|
||||||
|
Health: 1,
|
||||||
|
StateStr: "SECONDARY",
|
||||||
|
Uptime: 113031,
|
||||||
|
ConfigVersion: 1,
|
||||||
|
Self: false,
|
||||||
|
State: 2,
|
||||||
|
ElectionTime: 0,
|
||||||
|
ElectionDate: "",
|
||||||
|
Set: "r1"},
|
||||||
|
proto.Members{Optime: (*proto.Optime)(nil),
|
||||||
|
OptimeDate: "",
|
||||||
|
InfoMessage: "",
|
||||||
|
ID: 2,
|
||||||
|
Name: "localhost:17003",
|
||||||
|
Health: 1,
|
||||||
|
StateStr: "SECONDARY",
|
||||||
|
Uptime: 113031,
|
||||||
|
ConfigVersion: 1,
|
||||||
|
Self: false,
|
||||||
|
State: 2,
|
||||||
|
ElectionTime: 0,
|
||||||
|
ElectionDate: "",
|
||||||
|
Set: "r1",
|
||||||
|
}}
|
||||||
|
|
||||||
|
database := pmgomock.NewMockDatabaseManager(ctrl)
|
||||||
|
ss := proto.ServerStatus{}
|
||||||
|
lutil.LoadJson("test/sample/serverstatus.json", &ss)
|
||||||
|
|
||||||
|
dialer.EXPECT().DialWithInfo(gomock.Any()).Return(session, nil)
|
||||||
|
session.EXPECT().Run(bson.M{"replSetGetStatus": 1}, gomock.Any()).SetArg(1, mockrss)
|
||||||
|
|
||||||
|
dialer.EXPECT().DialWithInfo(gomock.Any()).Return(session, nil)
|
||||||
|
session.EXPECT().DB("admin").Return(database)
|
||||||
|
database.EXPECT().Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, gomock.Any()).SetArg(1, ss)
|
||||||
|
session.EXPECT().Close()
|
||||||
|
|
||||||
|
dialer.EXPECT().DialWithInfo(gomock.Any()).Return(session, nil)
|
||||||
|
session.EXPECT().DB("admin").Return(database)
|
||||||
|
database.EXPECT().Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, gomock.Any()).SetArg(1, ss)
|
||||||
|
session.EXPECT().Close()
|
||||||
|
|
||||||
|
dialer.EXPECT().DialWithInfo(gomock.Any()).Return(session, nil)
|
||||||
|
session.EXPECT().DB("admin").Return(database)
|
||||||
|
database.EXPECT().Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, gomock.Any()).SetArg(1, ss)
|
||||||
|
session.EXPECT().Close()
|
||||||
|
|
||||||
|
session.EXPECT().Close()
|
||||||
|
|
||||||
|
di := &mgo.DialInfo{Addrs: []string{"localhost"}}
|
||||||
|
rss, err := GetReplicasetMembers(dialer, di)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("getReplicasetMembers: %v", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(rss, expect) {
|
||||||
|
t.Errorf("getReplicasetMembers:\ngot %#v\nwant: %#v\n", rss, expect)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//OK
|
||||||
|
func TestGetHostnames(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
dialer := pmgomock.NewMockDialer(ctrl)
|
||||||
|
session := pmgomock.NewMockSessionManager(ctrl)
|
||||||
|
|
||||||
|
mockShardsInfo := proto.ShardsInfo{
|
||||||
|
Shards: []proto.Shard{
|
||||||
|
proto.Shard{
|
||||||
|
ID: "r1",
|
||||||
|
Host: "r1/localhost:17001,localhost:17002,localhost:17003",
|
||||||
|
},
|
||||||
|
proto.Shard{
|
||||||
|
ID: "r2",
|
||||||
|
Host: "r2/localhost:18001,localhost:18002,localhost:18003",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
OK: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
dialer.EXPECT().DialWithInfo(gomock.Any()).Return(session, nil)
|
||||||
|
session.EXPECT().Run("getShardMap", gomock.Any()).SetArg(1, mockShardsInfo)
|
||||||
|
session.EXPECT().Close()
|
||||||
|
|
||||||
|
expect := []string{"localhost", "localhost:17001", "localhost:18001"}
|
||||||
|
di := &mgo.DialInfo{Addrs: []string{"localhost"}}
|
||||||
|
rss, err := GetHostnames(dialer, di)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("getHostnames: %v", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(rss, expect) {
|
||||||
|
t.Errorf("getHostnames: got %+v, expected: %+v\n", rss, expect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addToCounters(ss proto.ServerStatus, increment int64) proto.ServerStatus {
|
||||||
|
ss.Opcounters.Command += increment
|
||||||
|
ss.Opcounters.Delete += increment
|
||||||
|
ss.Opcounters.GetMore += increment
|
||||||
|
ss.Opcounters.Insert += increment
|
||||||
|
ss.Opcounters.Query += increment
|
||||||
|
ss.Opcounters.Update += increment
|
||||||
|
return ss
|
||||||
|
}
|
@@ -3,6 +3,7 @@ package util
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/bradfitz/slice"
|
"github.com/bradfitz/slice"
|
||||||
"github.com/percona/percona-toolkit/src/go/mongolib/proto"
|
"github.com/percona/percona-toolkit/src/go/mongolib/proto"
|
||||||
@@ -12,50 +13,22 @@ import (
|
|||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetReplicasetMembersNew(dialer pmgo.Dialer, di *mgo.DialInfo) ([]proto.Members, error) {
|
|
||||||
hostnames, err := GetHostnames(dialer, di)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
replicaMembers := []proto.Members{}
|
|
||||||
for _, hostname := range hostnames {
|
|
||||||
if serverStatus, err := GetServerStatus(dialer, di, hostname); err == nil {
|
|
||||||
|
|
||||||
m := proto.Members{
|
|
||||||
ID: serverStatus.Pid,
|
|
||||||
Name: hostname,
|
|
||||||
StorageEngine: serverStatus.StorageEngine,
|
|
||||||
Set: serverStatus.Repl.SetName,
|
|
||||||
}
|
|
||||||
if serverStatus.Repl.IsMaster != nil && serverStatus.Repl.IsMaster.(bool) {
|
|
||||||
m.StateStr = "PRIMARY"
|
|
||||||
}
|
|
||||||
if serverStatus.Repl.Secondary != nil && serverStatus.Repl.Secondary.(bool) {
|
|
||||||
m.StateStr = "SECONDARY"
|
|
||||||
}
|
|
||||||
replicaMembers = append(replicaMembers, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return replicaMembers, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetReplicasetMembers(dialer pmgo.Dialer, di *mgo.DialInfo) ([]proto.Members, error) {
|
func GetReplicasetMembers(dialer pmgo.Dialer, di *mgo.DialInfo) ([]proto.Members, error) {
|
||||||
hostnames, err := GetHostnames(dialer, di)
|
hostnames, err := GetHostnames(dialer, di)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
membersMap := make(map[string]proto.Members)
|
membersMap := make(map[string]proto.Members)
|
||||||
members := []proto.Members{}
|
members := []proto.Members{}
|
||||||
|
|
||||||
for _, hostname := range hostnames {
|
for _, hostname := range hostnames {
|
||||||
tmpdi := *di
|
session, err := dialer.DialWithInfo(getTmpDI(di, hostname))
|
||||||
tmpdi.Addrs = []string{hostname}
|
|
||||||
session, err := dialer.DialWithInfo(&tmpdi)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "getReplicasetMembers. cannot connect to %s", hostname)
|
continue
|
||||||
}
|
}
|
||||||
|
defer session.Close()
|
||||||
|
session.SetMode(mgo.Monotonic, true)
|
||||||
|
|
||||||
cmdOpts := proto.CommandLineOptions{}
|
cmdOpts := proto.CommandLineOptions{}
|
||||||
session.DB("admin").Run(bson.D{{"getCmdLineOpts", 1}, {"recordStats", 1}}, &cmdOpts)
|
session.DB("admin").Run(bson.D{{"getCmdLineOpts", 1}, {"recordStats", 1}}, &cmdOpts)
|
||||||
@@ -101,18 +74,65 @@ func GetReplicasetMembers(dialer pmgo.Dialer, di *mgo.DialInfo) ([]proto.Members
|
|||||||
|
|
||||||
func GetHostnames(dialer pmgo.Dialer, di *mgo.DialInfo) ([]string, error) {
|
func GetHostnames(dialer pmgo.Dialer, di *mgo.DialInfo) ([]string, error) {
|
||||||
hostnames := []string{di.Addrs[0]}
|
hostnames := []string{di.Addrs[0]}
|
||||||
|
di.Direct = true
|
||||||
|
di.Timeout = 2 * time.Second
|
||||||
|
|
||||||
session, err := dialer.DialWithInfo(di)
|
session, err := dialer.DialWithInfo(di)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return hostnames, err
|
return hostnames, err
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
session.SetMode(mgo.Monotonic, true)
|
||||||
|
|
||||||
|
// Try getShardMap first. If we are connected to a mongos it will return
|
||||||
|
// all hosts, including config hosts
|
||||||
var shardsMap proto.ShardsMap
|
var shardsMap proto.ShardsMap
|
||||||
err = session.Run("getShardMap", &shardsMap)
|
err = session.Run("getShardMap", &shardsMap)
|
||||||
if err != nil {
|
if err == nil && len(shardsMap.Map) > 0 {
|
||||||
return hostnames, errors.Wrap(err, "cannot list shards")
|
// if the only element getShardMap returns is the list of config servers,
|
||||||
|
// it means we are connected to a replicaSet member and getShardMap is not
|
||||||
|
// the answer we want.
|
||||||
|
_, ok := shardsMap.Map["config"]
|
||||||
|
if ok && len(shardsMap.Map) > 1 {
|
||||||
|
return buildHostsListFromShardMap(shardsMap), nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Probably we are connected to an individual member of a replica set
|
||||||
|
rss := proto.ReplicaSetStatus{}
|
||||||
|
if err := session.Run(bson.M{"replSetGetStatus": 1}, &rss); err == nil {
|
||||||
|
return buildHostsListFromReplStatus(rss), nil
|
||||||
|
}
|
||||||
|
return hostnames, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildHostsListFromReplStatus(replStatus proto.ReplicaSetStatus) []string {
|
||||||
|
/*
|
||||||
|
"members" : [
|
||||||
|
{
|
||||||
|
"_id" : 0,
|
||||||
|
"name" : "localhost:17001",
|
||||||
|
"health" : 1,
|
||||||
|
"state" : 1,
|
||||||
|
"stateStr" : "PRIMARY",
|
||||||
|
"uptime" : 4700,
|
||||||
|
"optime" : Timestamp(1486554836, 1),
|
||||||
|
"optimeDate" : ISODate("2017-02-08T11:53:56Z"),
|
||||||
|
"electionTime" : Timestamp(1486651810, 1),
|
||||||
|
"electionDate" : ISODate("2017-02-09T14:50:10Z"),
|
||||||
|
"configVersion" : 1,
|
||||||
|
"self" : true
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
hostnames := []string{}
|
||||||
|
for _, member := range replStatus.Members {
|
||||||
|
hostnames = append(hostnames, member.Name)
|
||||||
|
}
|
||||||
|
return hostnames
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildHostsListFromShardMap(shardsMap proto.ShardsMap) []string {
|
||||||
/* Example
|
/* Example
|
||||||
mongos> db.getSiblingDB('admin').runCommand('getShardMap')
|
mongos> db.getSiblingDB('admin').runCommand('getShardMap')
|
||||||
{
|
{
|
||||||
@@ -126,7 +146,12 @@ func GetHostnames(dialer pmgo.Dialer, di *mgo.DialInfo) ([]string, error) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
hostnames := []string{}
|
||||||
hm := make(map[string]bool)
|
hm := make(map[string]bool)
|
||||||
|
|
||||||
|
// Since shardMap can return repeated hosts in different rows, we need a Set
|
||||||
|
// but there is no Set in Go so, we are going to create a map and the loop
|
||||||
|
// through the keys to get a list of unique host names
|
||||||
if shardsMap.Map != nil {
|
if shardsMap.Map != nil {
|
||||||
for _, val := range shardsMap.Map {
|
for _, val := range shardsMap.Map {
|
||||||
m := strings.Split(val, "/")
|
m := strings.Split(val, "/")
|
||||||
@@ -143,17 +168,16 @@ func GetHostnames(dialer pmgo.Dialer, di *mgo.DialInfo) ([]string, error) {
|
|||||||
hm[host] = false
|
hm[host] = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hostnames = []string{} // re-init because it has di.Addr[0]
|
|
||||||
for host := range hm {
|
for host := range hm {
|
||||||
hostnames = append(hostnames, host)
|
hostnames = append(hostnames, host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hostnames, nil
|
return hostnames
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is like GetHostnames but it uses listShards instead of getShardMap
|
// This function is like GetHostnames but it uses listShards instead of getShardMap
|
||||||
// so it won't include config servers in the returned list
|
// so it won't include config servers in the returned list
|
||||||
func GetShardsHosts(dialer pmgo.Dialer, di *mgo.DialInfo) ([]string, error) {
|
func GetShardedHosts(dialer pmgo.Dialer, di *mgo.DialInfo) ([]string, error) {
|
||||||
hostnames := []string{di.Addrs[0]}
|
hostnames := []string{di.Addrs[0]}
|
||||||
session, err := dialer.DialWithInfo(di)
|
session, err := dialer.DialWithInfo(di)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -177,24 +201,27 @@ func GetShardsHosts(dialer pmgo.Dialer, di *mgo.DialInfo) ([]string, error) {
|
|||||||
return hostnames, nil
|
return hostnames, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTmpDI(di *mgo.DialInfo, hostname string) *mgo.DialInfo {
|
||||||
|
tmpdi := *di
|
||||||
|
tmpdi.Addrs = []string{hostname}
|
||||||
|
tmpdi.Direct = true
|
||||||
|
tmpdi.Timeout = 2 * time.Second
|
||||||
|
|
||||||
|
return &tmpdi
|
||||||
|
}
|
||||||
|
|
||||||
func GetServerStatus(dialer pmgo.Dialer, di *mgo.DialInfo, hostname string) (proto.ServerStatus, error) {
|
func GetServerStatus(dialer pmgo.Dialer, di *mgo.DialInfo, hostname string) (proto.ServerStatus, error) {
|
||||||
ss := proto.ServerStatus{}
|
ss := proto.ServerStatus{}
|
||||||
|
|
||||||
tmpdi := *di
|
tmpdi := getTmpDI(di, hostname)
|
||||||
tmpdi.Addrs = []string{hostname}
|
session, err := dialer.DialWithInfo(tmpdi)
|
||||||
// tmpdi.Direct = true
|
|
||||||
// tmpdi.Timeout = 5 * time.Second
|
|
||||||
// tmpdi.FailFast = false
|
|
||||||
|
|
||||||
session, err := dialer.DialWithInfo(&tmpdi)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error %s\n", err.Error())
|
|
||||||
return ss, errors.Wrapf(err, "getReplicasetMembers. cannot connect to %s", hostname)
|
return ss, errors.Wrapf(err, "getReplicasetMembers. cannot connect to %s", hostname)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
session.SetMode(mgo.Monotonic, true)
|
||||||
|
|
||||||
if err := session.DB("admin").Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, &ss); err != nil {
|
if err := session.DB("admin").Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, &ss); err != nil {
|
||||||
fmt.Printf("error 2%s\n", err.Error())
|
|
||||||
return ss, errors.Wrap(err, "GetHostInfo.serverStatus")
|
return ss, errors.Wrap(err, "GetHostInfo.serverStatus")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,7 +52,6 @@ type opCounters struct {
|
|||||||
SampleRate time.Duration
|
SampleRate time.Duration
|
||||||
}
|
}
|
||||||
type hostInfo struct {
|
type hostInfo struct {
|
||||||
ThisHostID int
|
|
||||||
Hostname string
|
Hostname string
|
||||||
HostOsType string
|
HostOsType string
|
||||||
HostSystemCPUArch string
|
HostSystemCPUArch string
|
||||||
@@ -115,6 +114,7 @@ type clusterwideInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type options struct {
|
type options struct {
|
||||||
|
Help bool
|
||||||
Host string
|
Host string
|
||||||
User string
|
User string
|
||||||
Password string
|
Password string
|
||||||
@@ -129,32 +129,9 @@ type options struct {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
opts := options{
|
opts := parseFlags()
|
||||||
Host: "localhost:27017",
|
|
||||||
LogLevel: "error",
|
|
||||||
RunningOpsSamples: 5,
|
|
||||||
RunningOpsInterval: 1000, // milliseconds
|
|
||||||
}
|
|
||||||
help := getopt.BoolLong("help", '?', "Show help")
|
|
||||||
getopt.BoolVarLong(&opts.Version, "version", 'v', "", "Show version & exit")
|
|
||||||
getopt.BoolVarLong(&opts.NoVersionCheck, "no-version-check", 'c', "", "Don't check for updates")
|
|
||||||
|
|
||||||
getopt.StringVarLong(&opts.User, "user", 'u', "", "User name")
|
if opts.Help {
|
||||||
getopt.StringVarLong(&opts.Password, "password", 'p', "", "Password").SetOptional()
|
|
||||||
getopt.StringVarLong(&opts.AuthDB, "authenticationDatabase", 'a', "admin",
|
|
||||||
"Database used to establish credentials and privileges with a MongoDB server")
|
|
||||||
getopt.StringVarLong(&opts.LogLevel, "log-level", 'l', "error", "Log level:, panic, fatal, error, warn, info, debug")
|
|
||||||
|
|
||||||
getopt.IntVarLong(&opts.RunningOpsSamples, "running-ops-samples", 's',
|
|
||||||
fmt.Sprintf("Number of samples to collect for running ops. Default: %d", opts.RunningOpsSamples))
|
|
||||||
|
|
||||||
getopt.IntVarLong(&opts.RunningOpsInterval, "running-ops-interval", 'i',
|
|
||||||
fmt.Sprintf("Interval to wait betwwen running ops samples in milliseconds. Default %d milliseconds", opts.RunningOpsInterval))
|
|
||||||
|
|
||||||
getopt.SetParameters("host[:port]")
|
|
||||||
|
|
||||||
getopt.Parse()
|
|
||||||
if *help {
|
|
||||||
getopt.Usage()
|
getopt.Usage()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -166,11 +143,6 @@ func main() {
|
|||||||
|
|
||||||
log.SetLevel(logLevel)
|
log.SetLevel(logLevel)
|
||||||
|
|
||||||
args := getopt.Args() // positional arg
|
|
||||||
if len(args) > 0 {
|
|
||||||
opts.Host = args[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Version {
|
if opts.Version {
|
||||||
fmt.Println(TOOLNAME)
|
fmt.Println(TOOLNAME)
|
||||||
fmt.Printf("Version %s\n", Version)
|
fmt.Printf("Version %s\n", Version)
|
||||||
@@ -216,26 +188,29 @@ func main() {
|
|||||||
|
|
||||||
session, err := dialer.DialWithInfo(di)
|
session, err := dialer.DialWithInfo(di)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("cannot connect to the db: %s", err)
|
message := fmt.Sprintf("Cannot connect to %q", di.Addrs[0])
|
||||||
|
if di.Username != "" || di.Password != "" {
|
||||||
|
message += fmt.Sprintf(" using user: %q, password: %q", di.Username, di.Password)
|
||||||
|
}
|
||||||
|
message += fmt.Sprintf(". %s", err.Error())
|
||||||
|
log.Errorf(message)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
||||||
if replicaMembers, err := util.GetReplicasetMembers(dialer, di); err != nil {
|
if replicaMembers, err := util.GetReplicasetMembers(dialer, di); err != nil {
|
||||||
log.Printf("[Error] cannot get replicaset members: %v\n", err)
|
log.Warnf("[Error] cannot get replicaset members: %v\n", err)
|
||||||
|
os.Exit(2)
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("replicaMembers:\n%+v\n", replicaMembers)
|
log.Debugf("replicaMembers:\n%+v\n", replicaMembers)
|
||||||
t := template.Must(template.New("replicas").Parse(templates.Replicas))
|
t := template.Must(template.New("replicas").Parse(templates.Replicas))
|
||||||
t.Execute(os.Stdout, replicaMembers)
|
t.Execute(os.Stdout, replicaMembers)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
hostInfo, err := GetHostinfo(session)
|
hostInfo, err := GetHostinfo(session)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[Error] cannot get host info: %v\n", err)
|
log.Warnf("[Error] cannot get host info: %v\n", err)
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("hostInfo:\n%+v\n", hostInfo)
|
|
||||||
t := template.Must(template.New("hosttemplateData").Parse(templates.HostInfo))
|
t := template.Must(template.New("hosttemplateData").Parse(templates.HostInfo))
|
||||||
t.Execute(os.Stdout, hostInfo)
|
t.Execute(os.Stdout, hostInfo)
|
||||||
}
|
}
|
||||||
@@ -249,19 +224,26 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hostInfo != nil {
|
||||||
if security, err := GetSecuritySettings(session, hostInfo.Version); err != nil {
|
if security, err := GetSecuritySettings(session, hostInfo.Version); err != nil {
|
||||||
log.Printf("[Error] cannot get security settings: %v\n", err)
|
log.Printf("[Error] cannot get security settings: %v\n", err)
|
||||||
} else {
|
} else {
|
||||||
t := template.Must(template.New("ssl").Parse(templates.Security))
|
t := template.Must(template.New("ssl").Parse(templates.Security))
|
||||||
t.Execute(os.Stdout, security)
|
t.Execute(os.Stdout, security)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.Warn("Cannot check security settings since host info is not available (permissions?)")
|
||||||
|
}
|
||||||
|
|
||||||
if oplogInfo, err := oplog.GetOplogInfo(hostnames, di); err != nil {
|
if oplogInfo, err := oplog.GetOplogInfo(hostnames, di); err != nil {
|
||||||
log.Printf("[Error] cannot get Oplog info: %v\n", err)
|
log.Info("Cannot get Oplog info: %v\n", err)
|
||||||
} else {
|
} else {
|
||||||
if len(oplogInfo) > 0 {
|
if len(oplogInfo) > 0 {
|
||||||
t := template.Must(template.New("oplogInfo").Parse(templates.Oplog))
|
t := template.Must(template.New("oplogInfo").Parse(templates.Oplog))
|
||||||
t.Execute(os.Stdout, oplogInfo[0])
|
t.Execute(os.Stdout, oplogInfo[0])
|
||||||
|
} else {
|
||||||
|
|
||||||
|
log.Info("oplog info is empty. Skipping")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,6 +267,7 @@ func GetHostinfo(session pmgo.SessionManager) (*hostInfo, error) {
|
|||||||
|
|
||||||
hi := proto.HostInfo{}
|
hi := proto.HostInfo{}
|
||||||
if err := session.Run(bson.M{"hostInfo": 1}, &hi); err != nil {
|
if err := session.Run(bson.M{"hostInfo": 1}, &hi); err != nil {
|
||||||
|
log.Debugf("run('hostInfo') error: %s", err.Error())
|
||||||
return nil, errors.Wrap(err, "GetHostInfo.hostInfo")
|
return nil, errors.Wrap(err, "GetHostInfo.hostInfo")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,3 +763,38 @@ func externalIP() (string, error) {
|
|||||||
}
|
}
|
||||||
return "", errors.New("are you connected to the network?")
|
return "", errors.New("are you connected to the network?")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseFlags() options {
|
||||||
|
opts := options{
|
||||||
|
Host: "localhost:27017",
|
||||||
|
LogLevel: "warn",
|
||||||
|
RunningOpsSamples: 5,
|
||||||
|
RunningOpsInterval: 1000, // milliseconds
|
||||||
|
}
|
||||||
|
|
||||||
|
getopt.BoolVarLong(&opts.Help, "help", 'h', "Show help")
|
||||||
|
getopt.BoolVarLong(&opts.Version, "version", 'v', "", "Show version & exit")
|
||||||
|
getopt.BoolVarLong(&opts.NoVersionCheck, "no-version-check", 'c', "", "Don't check for updates")
|
||||||
|
|
||||||
|
getopt.StringVarLong(&opts.User, "user", 'u', "", "User name")
|
||||||
|
getopt.StringVarLong(&opts.Password, "password", 'p', "", "Password").SetOptional()
|
||||||
|
getopt.StringVarLong(&opts.AuthDB, "authenticationDatabase", 'a', "admin",
|
||||||
|
"Database used to establish credentials and privileges with a MongoDB server")
|
||||||
|
getopt.StringVarLong(&opts.LogLevel, "log-level", 'l', "error", "Log level:, panic, fatal, error, warn, info, debug")
|
||||||
|
|
||||||
|
getopt.IntVarLong(&opts.RunningOpsSamples, "running-ops-samples", 's',
|
||||||
|
fmt.Sprintf("Number of samples to collect for running ops. Default: %d", opts.RunningOpsSamples))
|
||||||
|
|
||||||
|
getopt.IntVarLong(&opts.RunningOpsInterval, "running-ops-interval", 'i',
|
||||||
|
fmt.Sprintf("Interval to wait betwwen running ops samples in milliseconds. Default %d milliseconds", opts.RunningOpsInterval))
|
||||||
|
|
||||||
|
getopt.SetParameters("host[:port]")
|
||||||
|
|
||||||
|
var gop = getopt.CommandLine
|
||||||
|
gop.Parse(os.Args)
|
||||||
|
if gop.NArgs() > 0 {
|
||||||
|
opts.Host = gop.Arg(0)
|
||||||
|
gop.Parse(gop.Args())
|
||||||
|
}
|
||||||
|
return opts
|
||||||
|
}
|
||||||
|
@@ -6,13 +6,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mgo "gopkg.in/mgo.v2"
|
|
||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
|
lutil "github.com/percona/percona-toolkit/src/go/lib/util"
|
||||||
"github.com/percona/percona-toolkit/src/go/mongolib/proto"
|
"github.com/percona/percona-toolkit/src/go/mongolib/proto"
|
||||||
"github.com/percona/pmgo/pmgomock"
|
"github.com/percona/pmgo/pmgomock"
|
||||||
"github.com/percona/toolkit-go-old/pt-mongodb-summary/test"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetOpCounterStats(t *testing.T) {
|
func TestGetOpCounterStats(t *testing.T) {
|
||||||
@@ -24,7 +23,7 @@ func TestGetOpCounterStats(t *testing.T) {
|
|||||||
database := pmgomock.NewMockDatabaseManager(ctrl)
|
database := pmgomock.NewMockDatabaseManager(ctrl)
|
||||||
|
|
||||||
ss := proto.ServerStatus{}
|
ss := proto.ServerStatus{}
|
||||||
test.LoadJson("test/sample/serverstatus.json", &ss)
|
lutil.LoadJson("test/sample/serverstatus.json", &ss)
|
||||||
|
|
||||||
session.EXPECT().DB("admin").Return(database)
|
session.EXPECT().DB("admin").Return(database)
|
||||||
database.EXPECT().Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, gomock.Any()).SetArg(1, ss)
|
database.EXPECT().Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, gomock.Any()).SetArg(1, ss)
|
||||||
@@ -45,7 +44,7 @@ func TestGetOpCounterStats(t *testing.T) {
|
|||||||
session.EXPECT().DB("admin").Return(database)
|
session.EXPECT().DB("admin").Return(database)
|
||||||
database.EXPECT().Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, gomock.Any()).SetArg(1, ss)
|
database.EXPECT().Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, gomock.Any()).SetArg(1, ss)
|
||||||
|
|
||||||
var sampleCount int64 = 5
|
var sampleCount int = 5
|
||||||
var sampleRate time.Duration = 10 * time.Millisecond // in seconds
|
var sampleRate time.Duration = 10 * time.Millisecond // in seconds
|
||||||
expect := TimedStats{Min: 0, Max: 0, Total: 0, Avg: 0}
|
expect := TimedStats{Min: 0, Max: 0, Total: 0, Avg: 0}
|
||||||
|
|
||||||
@@ -255,185 +254,6 @@ func TestGetNodeType(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetReplicasetMembers(t *testing.T) {
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
dialer := pmgomock.NewMockDialer(ctrl)
|
|
||||||
|
|
||||||
session := pmgomock.NewMockSessionManager(ctrl)
|
|
||||||
|
|
||||||
mockrss := proto.ReplicaSetStatus{
|
|
||||||
Date: "",
|
|
||||||
MyState: 1,
|
|
||||||
Term: 0,
|
|
||||||
HeartbeatIntervalMillis: 0,
|
|
||||||
Members: []proto.Members{
|
|
||||||
proto.Members{
|
|
||||||
Optime: nil,
|
|
||||||
OptimeDate: "",
|
|
||||||
InfoMessage: "",
|
|
||||||
Id: 0,
|
|
||||||
Name: "localhost:17001",
|
|
||||||
Health: 1,
|
|
||||||
StateStr: "PRIMARY",
|
|
||||||
Uptime: 113287,
|
|
||||||
ConfigVersion: 1,
|
|
||||||
Self: true,
|
|
||||||
State: 1,
|
|
||||||
ElectionTime: 6340960613392449537,
|
|
||||||
ElectionDate: "",
|
|
||||||
Set: ""},
|
|
||||||
proto.Members{
|
|
||||||
Optime: nil,
|
|
||||||
OptimeDate: "",
|
|
||||||
InfoMessage: "",
|
|
||||||
Id: 1,
|
|
||||||
Name: "localhost:17002",
|
|
||||||
Health: 1,
|
|
||||||
StateStr: "SECONDARY",
|
|
||||||
Uptime: 113031,
|
|
||||||
ConfigVersion: 1,
|
|
||||||
Self: false,
|
|
||||||
State: 2,
|
|
||||||
ElectionTime: 0,
|
|
||||||
ElectionDate: "",
|
|
||||||
Set: ""},
|
|
||||||
proto.Members{
|
|
||||||
Optime: nil,
|
|
||||||
OptimeDate: "",
|
|
||||||
InfoMessage: "",
|
|
||||||
Id: 2,
|
|
||||||
Name: "localhost:17003",
|
|
||||||
Health: 1,
|
|
||||||
StateStr: "SECONDARY",
|
|
||||||
Uptime: 113031,
|
|
||||||
ConfigVersion: 1,
|
|
||||||
Self: false,
|
|
||||||
State: 2,
|
|
||||||
ElectionTime: 0,
|
|
||||||
ElectionDate: "",
|
|
||||||
Set: ""}},
|
|
||||||
Ok: 1,
|
|
||||||
Set: "r1",
|
|
||||||
}
|
|
||||||
expect := []proto.Members{
|
|
||||||
proto.Members{
|
|
||||||
Optime: nil,
|
|
||||||
OptimeDate: "",
|
|
||||||
InfoMessage: "",
|
|
||||||
Id: 0,
|
|
||||||
Name: "localhost:17001",
|
|
||||||
Health: 1,
|
|
||||||
StateStr: "PRIMARY",
|
|
||||||
Uptime: 113287,
|
|
||||||
ConfigVersion: 1,
|
|
||||||
Self: true,
|
|
||||||
State: 1,
|
|
||||||
ElectionTime: 6340960613392449537,
|
|
||||||
ElectionDate: "",
|
|
||||||
Set: "r1"},
|
|
||||||
proto.Members{Optime: (*proto.Optime)(nil),
|
|
||||||
OptimeDate: "",
|
|
||||||
InfoMessage: "",
|
|
||||||
Id: 1,
|
|
||||||
Name: "localhost:17002",
|
|
||||||
Health: 1,
|
|
||||||
StateStr: "SECONDARY",
|
|
||||||
Uptime: 113031,
|
|
||||||
ConfigVersion: 1,
|
|
||||||
Self: false,
|
|
||||||
State: 2,
|
|
||||||
ElectionTime: 0,
|
|
||||||
ElectionDate: "",
|
|
||||||
Set: "r1"},
|
|
||||||
proto.Members{Optime: (*proto.Optime)(nil),
|
|
||||||
OptimeDate: "",
|
|
||||||
InfoMessage: "",
|
|
||||||
Id: 2,
|
|
||||||
Name: "localhost:17003",
|
|
||||||
Health: 1,
|
|
||||||
StateStr: "SECONDARY",
|
|
||||||
Uptime: 113031,
|
|
||||||
ConfigVersion: 1,
|
|
||||||
Self: false,
|
|
||||||
State: 2,
|
|
||||||
ElectionTime: 0,
|
|
||||||
ElectionDate: "",
|
|
||||||
Set: "r1",
|
|
||||||
}}
|
|
||||||
|
|
||||||
database := pmgomock.NewMockDatabaseManager(ctrl)
|
|
||||||
ss := proto.ServerStatus{}
|
|
||||||
test.LoadJson("test/sample/serverstatus.json", &ss)
|
|
||||||
|
|
||||||
dialer.EXPECT().DialWithInfo(gomock.Any()).Return(session, nil)
|
|
||||||
session.EXPECT().Run(bson.M{"replSetGetStatus": 1}, gomock.Any()).SetArg(1, mockrss)
|
|
||||||
|
|
||||||
dialer.EXPECT().DialWithInfo(gomock.Any()).Return(session, nil)
|
|
||||||
session.EXPECT().DB("admin").Return(database)
|
|
||||||
database.EXPECT().Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, gomock.Any()).SetArg(1, ss)
|
|
||||||
session.EXPECT().Close()
|
|
||||||
|
|
||||||
dialer.EXPECT().DialWithInfo(gomock.Any()).Return(session, nil)
|
|
||||||
session.EXPECT().DB("admin").Return(database)
|
|
||||||
database.EXPECT().Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, gomock.Any()).SetArg(1, ss)
|
|
||||||
session.EXPECT().Close()
|
|
||||||
|
|
||||||
dialer.EXPECT().DialWithInfo(gomock.Any()).Return(session, nil)
|
|
||||||
session.EXPECT().DB("admin").Return(database)
|
|
||||||
database.EXPECT().Run(bson.D{{"serverStatus", 1}, {"recordStats", 1}}, gomock.Any()).SetArg(1, ss)
|
|
||||||
session.EXPECT().Close()
|
|
||||||
|
|
||||||
session.EXPECT().Close()
|
|
||||||
|
|
||||||
di := &mgo.DialInfo{Addrs: []string{"localhost"}}
|
|
||||||
rss, err := GetReplicasetMembers(dialer, []string{"localhost"}, di)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("getReplicasetMembers: %v", err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(rss, expect) {
|
|
||||||
t.Errorf("getReplicasetMembers:\ngot %#v\nwant: %#v\n", rss, expect)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetHostnames(t *testing.T) {
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
dialer := pmgomock.NewMockDialer(ctrl)
|
|
||||||
session := pmgomock.NewMockSessionManager(ctrl)
|
|
||||||
|
|
||||||
mockShardsInfo := proto.ShardsInfo{
|
|
||||||
Shards: []proto.Shard{
|
|
||||||
proto.Shard{
|
|
||||||
ID: "r1",
|
|
||||||
Host: "r1/localhost:17001,localhost:17002,localhost:17003",
|
|
||||||
},
|
|
||||||
proto.Shard{
|
|
||||||
ID: "r2",
|
|
||||||
Host: "r2/localhost:18001,localhost:18002,localhost:18003",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
OK: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
dialer.EXPECT().DialWithInfo(gomock.Any()).Return(session, nil)
|
|
||||||
session.EXPECT().Run("listShards", gomock.Any()).SetArg(1, mockShardsInfo)
|
|
||||||
session.EXPECT().Close()
|
|
||||||
|
|
||||||
expect := []string{"localhost", "localhost:17001", "localhost:18001"}
|
|
||||||
di := &mgo.DialInfo{Addrs: []string{"localhost"}}
|
|
||||||
rss, err := getHostnames(dialer, di)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("getHostnames: %v", err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(rss, expect) {
|
|
||||||
t.Errorf("getHostnames: got %+v, expected: %+v\n", rss, expect)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsPrivateNetwork(t *testing.T) {
|
func TestIsPrivateNetwork(t *testing.T) {
|
||||||
//privateCIDRs := []string{"10.0.0.0/24", "172.16.0.0/20", "192.168.0.0/16"}
|
//privateCIDRs := []string{"10.0.0.0/24", "172.16.0.0/20", "192.168.0.0/16"}
|
||||||
testdata :=
|
testdata :=
|
||||||
|
@@ -22,7 +22,7 @@ func GetOplogInfo(hostnames []string, di *mgo.DialInfo) ([]proto.OplogInfo, erro
|
|||||||
di.Addrs = []string{hostname}
|
di.Addrs = []string{hostname}
|
||||||
session, err := mgo.DialWithInfo(di)
|
session, err := mgo.DialWithInfo(di)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "cannot connect to %s", hostname)
|
continue
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ func GetOplogInfo(hostnames []string, di *mgo.DialInfo) ([]proto.OplogInfo, erro
|
|||||||
replSetStatus := proto.ReplicaSetStatus{}
|
replSetStatus := proto.ReplicaSetStatus{}
|
||||||
err = session.Run(bson.M{"replSetGetStatus": 1}, &replSetStatus)
|
err = session.Run(bson.M{"replSetGetStatus": 1}, &replSetStatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "cannot get ReplicaSetStatus")
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, member := range replSetStatus.Members {
|
for _, member := range replSetStatus.Members {
|
||||||
|
@@ -1,10 +1,14 @@
|
|||||||
package templates
|
package templates
|
||||||
|
|
||||||
const HostInfo = `# This host
|
const HostInfo = `# This host
|
||||||
|
{{ if .ProcPath -}}
|
||||||
# Mongo Executable #######################################################################################
|
# Mongo Executable #######################################################################################
|
||||||
Path to executable | {{.ProcPath }}
|
Path to executable | {{.ProcPath }}
|
||||||
# Report On {{.ThisHostID}} ########################################
|
{{ end -}}
|
||||||
|
# Report On {{.Hostname}} ########################################
|
||||||
|
{{- if .ProcUserName }}
|
||||||
User | {{.ProcUserName }}
|
User | {{.ProcUserName }}
|
||||||
|
{{- end }}
|
||||||
PID Owner | {{.ProcessName}}
|
PID Owner | {{.ProcessName}}
|
||||||
Hostname | {{.Hostname}}
|
Hostname | {{.Hostname}}
|
||||||
Version | {{.Version}}
|
Version | {{.Version}}
|
||||||
|
@@ -5,7 +5,7 @@ const Replicas = `
|
|||||||
PID Host Type ReplSet Engine
|
PID Host Type ReplSet Engine
|
||||||
{{- if . -}}
|
{{- if . -}}
|
||||||
{{- range . }}
|
{{- range . }}
|
||||||
{{printf "% 3d" .ID}} {{printf "%-30s" .Name}} {{printf "%-30s" .StateStr}} {{ if .Set }}{{printf "%-10s" .Set }}{{else}}- {{end}} {{printf "%20s" .StorageEngine.Name -}}
|
{{printf "% 6d" .ID}} {{printf "%-30s" .Name}} {{printf "%-25s" .StateStr}} {{ if .Set }}{{printf "%-10s" .Set }}{{else}}- {{end}} {{printf "%20s" .StorageEngine.Name -}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
no replica sets found
|
no replica sets found
|
||||||
|
Reference in New Issue
Block a user