This commit is contained in:
crusader 2017-12-14 14:36:17 +09:00
parent e067b2c21c
commit 4d83529943
5 changed files with 337 additions and 45 deletions

View File

@ -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 {

View 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
}

View 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
}

View 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()
}

View 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)
}