ing
This commit is contained in:
parent
e067b2c21c
commit
4d83529943
|
@ -1,11 +1,15 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
configM "git.loafle.net/overflow/overflow_commons_go/modules/config/model"
|
||||
"git.loafle.net/overflow/overflow_probe_container_network/crawler"
|
||||
"git.loafle.net/overflow/overflow_probe_container_network/crawler/impl/ssh/client"
|
||||
"git.loafle.net/overflow/overflow_probe_container_network/crawler/impl/ssh/parser"
|
||||
"github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
type SSHCrawler struct {
|
||||
|
@ -17,65 +21,65 @@ func (c *SSHCrawler) Name() string {
|
|||
}
|
||||
|
||||
func (c *SSHCrawler) InternalGet(config *configM.Config) (map[string]string, error) {
|
||||
|
||||
return c.start(config)
|
||||
}
|
||||
|
||||
func (c *SSHCrawler) start(config *configM.Config) (map[string]string, error) {
|
||||
ip := config.Target.Connection.IP
|
||||
port := config.Target.Connection.Port
|
||||
user := config.Target.Auth["id"].(string)
|
||||
pw := config.Target.Auth["pw"].(string)
|
||||
keyFilePathObj := config.Target.Auth["keyFilePath"]
|
||||
keyFilePath := ""
|
||||
|
||||
if keyFilePathObj != nil {
|
||||
keyFilePath = keyFilePathObj.(string)
|
||||
sshClient, err := client.New(config.Target)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cr, err := crawler.New(ip, port, user, pw, keyFilePath)
|
||||
itemCount := len(config.Items)
|
||||
results := make(map[string]string, 0)
|
||||
boundary := uuid.NewV4().String()
|
||||
commands := ""
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
for i := 0; i < itemCount; i++ {
|
||||
if "" != commands {
|
||||
commands = fmt.Sprintf("%s;echo \"--%s\";", commands, boundary)
|
||||
}
|
||||
commands = fmt.Sprintf("%s;%s;", commands, config.Items[i].QueryInfo.Query)
|
||||
}
|
||||
commands = fmt.Sprintf("%s;echo \"--%s--\";", commands, boundary)
|
||||
|
||||
var inter crawler.SSHCrawlerModuler
|
||||
var resultMap map[string]string = make(map[string]string)
|
||||
var tempMap map[string]string = nil
|
||||
var temp interface{} = nil
|
||||
for _, item := range c.Items {
|
||||
buf, err := sshClient.RunCommand(commands)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
r := bytes.NewReader(buf)
|
||||
scanner := bufio.NewScanner(r)
|
||||
|
||||
ParseLoop:
|
||||
for i := 0; i < itemCount; i++ {
|
||||
item := config.Items[i]
|
||||
mode := item.QueryInfo.Extend["mode"].(string)
|
||||
|
||||
switch mode {
|
||||
case "cpu":
|
||||
inter = stat.CPUStat{}
|
||||
break
|
||||
case "mem":
|
||||
inter = stat.MemStat{}
|
||||
break
|
||||
default:
|
||||
continue
|
||||
p := parser.GetParser(mode)
|
||||
if nil == p {
|
||||
return nil, fmt.Errorf("Container: Parser[%s] is not exist", mode)
|
||||
}
|
||||
|
||||
ch := make(chan interface{})
|
||||
cr.Process(inter, ch, item)
|
||||
temp = <-ch
|
||||
rm, err := p.Parse(scanner)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reflect.TypeOf(temp).String() == "map[string]string" {
|
||||
tempMap = temp.(map[string]string)
|
||||
for k, v := range tempMap {
|
||||
resultMap[k] = v
|
||||
if nil != rm {
|
||||
for k, v := range rm {
|
||||
results[k] = v
|
||||
}
|
||||
} else {
|
||||
var errr error = temp.(error)
|
||||
}
|
||||
|
||||
return nil, errr
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if line == "--"+boundary+"--" {
|
||||
break ParseLoop
|
||||
}
|
||||
|
||||
if line == "--"+boundary {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return &resultMap, nil
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func NewCrawler() crawler.Crawler {
|
||||
|
|
125
crawler/impl/ssh/client/client.go
Normal file
125
crawler/impl/ssh/client/client.go
Normal file
|
@ -0,0 +1,125 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
cuej "git.loafle.net/commons_go/util/encoding/json"
|
||||
configM "git.loafle.net/overflow/overflow_commons_go/modules/config/model"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type SSHConfig struct {
|
||||
User string
|
||||
Auth []ssh.AuthMethod
|
||||
Host string
|
||||
Port int
|
||||
}
|
||||
|
||||
type SSHClient struct {
|
||||
conf *SSHConfig
|
||||
}
|
||||
|
||||
func (cli *SSHClient) Session() (*ssh.Session, error) {
|
||||
sshConfig := &ssh.ClientConfig{
|
||||
User: cli.conf.User,
|
||||
Auth: cli.conf.Auth,
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
Timeout: time.Second * 10,
|
||||
}
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", cli.conf.Host, cli.conf.Port)
|
||||
|
||||
connection, err := ssh.Dial("tcp", addr, sshConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
session, err := connection.NewSession()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
modes := ssh.TerminalModes{
|
||||
ssh.ECHO: 0, // disable echoing
|
||||
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
|
||||
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
|
||||
}
|
||||
|
||||
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
|
||||
session.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func (cli *SSHClient) RunCommand(command string) ([]byte, error) {
|
||||
|
||||
session, err := cli.Session()
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
session.Close()
|
||||
}()
|
||||
|
||||
var b bytes.Buffer
|
||||
session.Stdout = &b
|
||||
|
||||
if err := session.Run(command); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
func parsePrivateKey(keyPath, pw string) (ssh.Signer, error) {
|
||||
buff, err := ioutil.ReadFile(keyPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if pw == "" {
|
||||
return ssh.ParsePrivateKey(buff)
|
||||
}
|
||||
return ssh.ParsePrivateKeyWithPassphrase(buff, []byte(pw))
|
||||
}
|
||||
|
||||
func New(target *configM.Target) (*SSHClient, error) {
|
||||
connection := target.Connection
|
||||
auth := target.Auth
|
||||
|
||||
ip := connection.IP
|
||||
port, _ := cuej.NumberToInt(connection.Port)
|
||||
user := auth["id"].(string)
|
||||
pw := auth["pw"].(string)
|
||||
keyFilePathObj := auth["keyFilePath"]
|
||||
keyFilePath := ""
|
||||
|
||||
sshAuth := make([]ssh.AuthMethod, 0)
|
||||
|
||||
if keyFilePathObj != nil {
|
||||
keyFilePath = keyFilePathObj.(string)
|
||||
if "" != keyFilePath {
|
||||
key, err := parsePrivateKey(keyFilePath, pw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sshAuth = append(sshAuth, ssh.PublicKeys(key))
|
||||
|
||||
}
|
||||
}
|
||||
sshAuth = append(sshAuth, ssh.Password(pw))
|
||||
|
||||
sshConf := &SSHConfig{
|
||||
User: user,
|
||||
Auth: sshAuth,
|
||||
Host: ip,
|
||||
Port: port,
|
||||
}
|
||||
|
||||
return &SSHClient{
|
||||
conf: sshConf,
|
||||
}, nil
|
||||
}
|
100
crawler/impl/ssh/parser/cpu_parser.go
Normal file
100
crawler/impl/ssh/parser/cpu_parser.go
Normal file
|
@ -0,0 +1,100 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CPUParser struct {
|
||||
}
|
||||
|
||||
func (p *CPUParser) Name() string {
|
||||
return "cpu"
|
||||
}
|
||||
|
||||
func (p *CPUParser) Parse(scanner *bufio.Scanner) (map[string]string, error) {
|
||||
resMap := make(map[string]string, 0)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
parts := strings.Fields(line)
|
||||
|
||||
if !strings.HasPrefix(parts[0], "cpu") {
|
||||
continue
|
||||
}
|
||||
|
||||
//var steal, guest, guestNice int64
|
||||
//if len(parts) > 8 {
|
||||
// steal = util.StringToInt64(parts[8])
|
||||
//}
|
||||
//if len(parts) > 9 {
|
||||
// guest = util.StringToInt64(parts[9])
|
||||
//}
|
||||
if 10 >= len(parts) {
|
||||
//guestNice = util.StringToInt64(parts[10])
|
||||
continue
|
||||
}
|
||||
|
||||
//stats = append(stats, CPUStat{
|
||||
//Device := util.StringToInt64(parts[0])
|
||||
// User := util.StringToInt64(parts[1])
|
||||
// Nice := util.StringToInt64(parts[2])
|
||||
// System := util.StringToInt64(parts[3])
|
||||
// Idle := util.StringToInt64(parts[4])
|
||||
// Iowait := util.StringToInt64(parts[5])
|
||||
// Irq := util.StringToInt64(parts[6])
|
||||
// SoftIrq := util.StringToInt64(parts[7])
|
||||
// Steal := util.StringToInt64(parts[8])
|
||||
// Guest := util.StringToInt64(parts[9])
|
||||
// GuestNice := util.StringToInt64(parts[10])
|
||||
//})
|
||||
|
||||
// sum := User + Nice + System + Idle + Iowait + Irq + SoftIrq + Steal + Guest + GuestNice
|
||||
sum := sumFromStrings(parts, 1, 11, nil)
|
||||
|
||||
resMap["sum"] = strconv.FormatInt(sum, 10)
|
||||
resMap["user"] = parts[1]
|
||||
resMap["nice"] = parts[2]
|
||||
resMap["system"] = parts[3]
|
||||
resMap["idle"] = parts[4]
|
||||
resMap["iowait"] = parts[5]
|
||||
resMap["irq"] = parts[6]
|
||||
resMap["softIrq"] = parts[7]
|
||||
resMap["steal"] = parts[8]
|
||||
resMap["guest"] = parts[9]
|
||||
resMap["gnice"] = parts[10]
|
||||
|
||||
break // first line only --- cpu
|
||||
}
|
||||
|
||||
//res, err := cpu.parse(keys, stats)
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
|
||||
return resMap, scanner.Err()
|
||||
|
||||
}
|
||||
|
||||
func sumFromStrings(ss []string, startIndex, endIndex int, exclude []int) int64 {
|
||||
if nil == ss {
|
||||
return 0
|
||||
}
|
||||
|
||||
var result int64
|
||||
Loop:
|
||||
for i := startIndex; i < endIndex; i++ {
|
||||
if nil != exclude {
|
||||
for j := 0; j < len(exclude); j++ {
|
||||
if exclude[j] == i {
|
||||
continue Loop
|
||||
}
|
||||
}
|
||||
}
|
||||
i64, _ := strconv.ParseInt(ss[i], 10, 64)
|
||||
result += i64
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
34
crawler/impl/ssh/parser/memory_parser.go
Normal file
34
crawler/impl/ssh/parser/memory_parser.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type MemoryParser struct {
|
||||
}
|
||||
|
||||
func (p *MemoryParser) Name() string {
|
||||
return "mem"
|
||||
}
|
||||
|
||||
func (p *MemoryParser) Parse(scanner *bufio.Scanner) (map[string]string, error) {
|
||||
var (
|
||||
stats = map[string]string{}
|
||||
)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
parts := strings.Fields(line)
|
||||
key := parts[0][:len(parts[0])-1]
|
||||
|
||||
stats[key] = parts[1]
|
||||
}
|
||||
|
||||
//res, err := mem.parse(keys, stats)
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
|
||||
return stats, scanner.Err()
|
||||
}
|
29
crawler/impl/ssh/parser/parser.go
Normal file
29
crawler/impl/ssh/parser/parser.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package parser
|
||||
|
||||
import "bufio"
|
||||
|
||||
var parsers map[string]Parser
|
||||
|
||||
func init() {
|
||||
parsers = make(map[string]Parser, 0)
|
||||
|
||||
addParser(&CPUParser{})
|
||||
addParser(&MemoryParser{})
|
||||
}
|
||||
|
||||
func addParser(p Parser) {
|
||||
parsers[p.Name()] = p
|
||||
}
|
||||
|
||||
func GetParser(name string) Parser {
|
||||
p, ok := parsers[name]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
type Parser interface {
|
||||
Name() string
|
||||
Parse(scanner *bufio.Scanner) (map[string]string, error)
|
||||
}
|
Loading…
Reference in New Issue
Block a user