initial commit

master
q3k 2018-10-14 15:21:46 -07:00
commit 753d63f893
7 changed files with 874 additions and 0 deletions

189
Gopkg.lock generated Normal file
View File

@ -0,0 +1,189 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
branch = "master"
digest = "1:2af0bc306f77bef606f6f6033652f0de3cc80e77008f4da52197b4b0a6be5853"
name = "code.hackerspace.pl/q3k/hspki"
packages = ["."]
pruneopts = "UT"
revision = "624295da664fea57a1e3bd8cee639ae04f4c0ccf"
[[projects]]
branch = "master"
digest = "1:b2619fc3d4ced0542d16962c73812d2e70ed09eb29cdfc3d767a85b726dab150"
name = "code.hackerspace.pl/q3k/mirko"
packages = ["."]
pruneopts = "UT"
revision = "4f7ee51e9a73e05e5b2dbc6cfa178ace2f83b155"
[[projects]]
digest = "1:e92f5581902c345eb4ceffdcd4a854fb8f73cf436d47d837d1ec98ef1fe0a214"
name = "github.com/StackExchange/wmi"
packages = ["."]
pruneopts = "UT"
revision = "5d049714c4a64225c3c79a7cf7d02f7fb5b96338"
version = "1.0.0"
[[projects]]
digest = "1:64a5a67c69b70c2420e607a8545d674a23778ed9c3e80607bfd17b77c6c87f6a"
name = "github.com/go-ole/go-ole"
packages = [
".",
"oleutil",
]
pruneopts = "UT"
revision = "a41e3c4b706f6ae8dfbff342b06e40fa4d2d0506"
version = "v1.2.1"
[[projects]]
branch = "master"
digest = "1:1ba1d79f2810270045c328ae5d674321db34e3aae468eb4233883b473c5c0467"
name = "github.com/golang/glog"
packages = ["."]
pruneopts = "UT"
revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998"
[[projects]]
digest = "1:5d1b5a25486fc7d4e133646d834f6fca7ba1cef9903d40e7aa786c41b89e9e91"
name = "github.com/golang/protobuf"
packages = [
"proto",
"protoc-gen-go/descriptor",
"ptypes",
"ptypes/any",
"ptypes/duration",
"ptypes/timestamp",
]
pruneopts = "UT"
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
version = "v1.2.0"
[[projects]]
branch = "master"
digest = "1:a7cc4447e0c2432f217fd2bed937c100ec475272a7a9306477170c2934297357"
name = "github.com/q3k/statusz"
packages = ["."]
pruneopts = "UT"
revision = "924f04ea71149b75f5b10f426cc4c39d6d90f6f2"
[[projects]]
branch = "master"
digest = "1:8f042d4b4c48d38d7a1201096299bd26d044c97c032ab20ee171fe5b0d201d2e"
name = "github.com/shirou/gopsutil"
packages = [
"internal/common",
"load",
]
pruneopts = "UT"
revision = "a11c78ba2c13c5b1ee59c53296ba35f92f0ce658"
[[projects]]
branch = "master"
digest = "1:505dbee0833715a72a529bb57c354826ad42a4496fad787fa143699b4de1a6d0"
name = "golang.org/x/net"
packages = [
"context",
"http/httpguts",
"http2",
"http2/hpack",
"idna",
"internal/timeseries",
"trace",
]
pruneopts = "UT"
revision = "49bb7cea24b1df9410e1712aa6433dae904ff66a"
[[projects]]
branch = "master"
digest = "1:f5aa274a0377f85735edc7fedfb0811d3cbc20af91633797cb359e29c3272271"
name = "golang.org/x/sys"
packages = [
"unix",
"windows",
]
pruneopts = "UT"
revision = "fa43e7bc11baaae89f3f902b2b4d832b68234844"
[[projects]]
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
name = "golang.org/x/text"
packages = [
"collate",
"collate/build",
"internal/colltab",
"internal/gen",
"internal/tag",
"internal/triegen",
"internal/ucd",
"language",
"secure/bidirule",
"transform",
"unicode/bidi",
"unicode/cldr",
"unicode/norm",
"unicode/rangetable",
]
pruneopts = "UT"
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
branch = "master"
digest = "1:56b0bca90b7e5d1facf5fbdacba23e4e0ce069d25381b8e2f70ef1e7ebfb9c1a"
name = "google.golang.org/genproto"
packages = ["googleapis/rpc/status"]
pruneopts = "UT"
revision = "af9cb2a35e7f169ec875002c1829c9b315cddc04"
[[projects]]
digest = "1:dc0c170b110c22d9a4eccf08ab58490608053eac450bf456f3aaf9b30a668781"
name = "google.golang.org/grpc"
packages = [
".",
"balancer",
"balancer/base",
"balancer/roundrobin",
"codes",
"connectivity",
"credentials",
"encoding",
"encoding/proto",
"grpclog",
"internal",
"internal/backoff",
"internal/channelz",
"internal/envconfig",
"internal/grpcrand",
"internal/transport",
"keepalive",
"metadata",
"naming",
"peer",
"reflection",
"reflection/grpc_reflection_v1alpha",
"resolver",
"resolver/dns",
"resolver/passthrough",
"stats",
"status",
"tap",
]
pruneopts = "UT"
revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1"
version = "v1.15.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"code.hackerspace.pl/q3k/mirko",
"github.com/golang/glog",
"github.com/golang/protobuf/proto",
"golang.org/x/net/context",
"google.golang.org/grpc",
"google.golang.org/grpc/codes",
"google.golang.org/grpc/status",
]
solver-name = "gps-cdcl"
solver-version = 1

50
Gopkg.toml Normal file
View File

@ -0,0 +1,50 @@
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true
[[constraint]]
branch = "master"
name = "code.hackerspace.pl/q3k/mirko"
[[constraint]]
branch = "master"
name = "github.com/golang/glog"
[[constraint]]
name = "github.com/golang/protobuf"
version = "1.2.0"
[[constraint]]
branch = "master"
name = "golang.org/x/net"
[[constraint]]
name = "google.golang.org/grpc"
version = "1.15.0"
[prune]
go-tests = true
unused-packages = true

348
client.go Normal file
View File

@ -0,0 +1,348 @@
package main
import (
"context"
"crypto/tls"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"regexp"
"strings"
"code.hackerspace.pl/q3k/mirko"
"github.com/cenkalti/backoff"
"github.com/golang/glog"
)
var (
reSessionCookie = regexp.MustCompile("'SESSION_COOKIE' : '([^']*)'")
reIpmiPriv = regexp.MustCompile("'IPMI_PRIV' : ([^,]*)")
reExtPriv = regexp.MustCompile("'EXT_PRIV' : ([^,]*)")
reSystemModel = regexp.MustCompile("'SYSTEM_MODEL' : '([^']*)'")
reArgument = regexp.MustCompile("<argument>([^<]*)</argument>")
)
var (
ErrorNoFreeSlot = fmt.Errorf("iDRAC reports no free slot")
)
type cmcRequestType int
const (
cmcRequestKVMDetails cmcRequestType = iota
)
type cmcResponse struct {
data interface{}
err error
}
type cmcRequest struct {
t cmcRequestType
req interface{}
res chan cmcResponse
canceled bool
}
type KVMDetails struct {
arguments []string
}
type cmcClient struct {
session string
req chan *cmcRequest
}
func (c *cmcClient) RequestKVMDetails(ctx context.Context, slot int) (*KVMDetails, error) {
r := &cmcRequest{
t: cmcRequestKVMDetails,
req: slot,
res: make(chan cmcResponse, 1),
}
mirko.Trace(ctx, "cmcRequestKVMDetails: requesting...")
c.req <- r
mirko.Trace(ctx, "cmcRequestKVMDetails: requested.")
select {
case <-ctx.Done():
r.canceled = true
return nil, context.Canceled
case res := <-r.res:
mirko.Trace(ctx, "cmcRequestKVMDetails: got response")
if res.err != nil {
return nil, res.err
}
return res.data.(*KVMDetails), nil
}
}
func NewCMCClient() *cmcClient {
return &cmcClient{
req: make(chan *cmcRequest, 4),
}
}
func (c *cmcClient) Run(ctx context.Context) {
for {
select {
case <-ctx.Done():
c.logout()
return
case msg := <-c.req:
c.handle(msg)
}
}
}
func (c *cmcClient) handle(r *cmcRequest) {
switch {
case r.t == cmcRequestKVMDetails:
var details *KVMDetails
slot := r.req.(int)
err := backoff.Retry(func() error {
if err := c.login(); err != nil {
return err
}
url, err := c.getiDRACURL(slot)
if err != nil {
return err
}
details, err = c.getiDRACJNLP(url)
return err
}, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), 2))
if err != nil {
r.res <- cmcResponse{err: err}
}
r.res <- cmcResponse{data: details}
default:
panic("invalid cmcRequestType")
}
}
func makeUrl(path string) string {
if strings.HasSuffix(flagCMCAddress, "/") {
return flagCMCAddress + path
}
return flagCMCAddress + "/" + path
}
func (c *cmcClient) transport() *http.Transport {
return &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
}
func (c *cmcClient) addCookies(req *http.Request) {
req.AddCookie(&http.Cookie{Name: "custom_domain", Value: ""})
req.AddCookie(&http.Cookie{Name: "domain_selected", Value: "This Chassis"})
if c.session != "" {
glog.Infof("Adding session: %v", c.session)
req.AddCookie(&http.Cookie{Name: "sid", Value: c.session})
}
}
func (c *cmcClient) getiDRACURL(slot int) (string, error) {
if c.session == "" {
return "", fmt.Errorf("not logged in")
}
url := makeUrl(pathiDRACURL) + fmt.Sprintf("?vKVM=1&serverSlot=%d", slot)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return "", fmt.Errorf("GET prepare to %s failed: %v", pathLogin, err)
}
c.addCookies(req)
cl := &http.Client{
Transport: c.transport(),
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
resp, err := cl.Do(req)
if err != nil {
return "", fmt.Errorf("GET to %s failed: %v", pathLogin, err)
}
if resp.StatusCode != 302 {
return "", fmt.Errorf("expected 302 on iDRAC URL redirect, got %v instead", resp.Status)
}
loc, _ := resp.Location()
if !strings.Contains(loc.String(), "cmc_sess_id") {
c.session = ""
return "", fmt.Errorf("redirect URL contains no session ID - session timed out?")
}
return loc.String(), nil
}
func (c *cmcClient) getiDRACJNLP(loginUrl string) (*KVMDetails, error) {
lurl, err := url.Parse(loginUrl)
if err != nil {
return nil, err
}
sessid := lurl.Query().Get("cmc_sess_id")
if sessid == "" {
return nil, fmt.Errorf("no cmc_sess_id in iDRAC login URL")
}
createURL := *lurl
createURL.Path = "/Applications/dellUI/RPC/WEBSES/create.asp"
createURL.RawQuery = ""
values := url.Values{}
values.Set("WEBVAR_USERNAME", "cmc")
values.Set("WEBVAR_PASSWORD", sessid)
values.Set("WEBVAR_ISCMCLOGIN", "1")
valuesString := values.Encode()
req, err := http.NewRequest("POST", createURL.String(), strings.NewReader(valuesString))
cl := &http.Client{
Transport: c.transport(),
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
resp, err := cl.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, _ := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
first := func(v [][]byte) string {
if len(v) < 1 {
return ""
}
return string(v[1])
}
sessionCookie := first(reSessionCookie.FindSubmatch(data))
ipmiPriv := first(reIpmiPriv.FindSubmatch(data))
extPriv := first(reExtPriv.FindSubmatch(data))
systemModel := first(reSystemModel.FindSubmatch(data))
if sessionCookie == "Failure_No_Free_Slot" {
return nil, ErrorNoFreeSlot
}
jnlpURL := *lurl
jnlpURL.Path = "/Applications/dellUI/Java/jviewer.jnlp"
jnlpURL.RawQuery = ""
req, err = http.NewRequest("GET", jnlpURL.String(), nil)
for _, cookie := range resp.Cookies() {
glog.Infof("%+v", cookie)
req.AddCookie(cookie)
}
req.AddCookie(&http.Cookie{Name: "SessionCookie", Value: sessionCookie})
req.AddCookie(&http.Cookie{Name: "SessionCookieUser", Value: "cmc"})
req.AddCookie(&http.Cookie{Name: "IPMIPriv", Value: ipmiPriv})
req.AddCookie(&http.Cookie{Name: "ExtPriv", Value: extPriv})
req.AddCookie(&http.Cookie{Name: "SystemModel", Value: systemModel})
resp, err = cl.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, err = ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
// yes we do parse xml with regex why are you asking
matches := reArgument.FindAllSubmatch(data, -1)
res := &KVMDetails{
arguments: []string{},
}
for _, match := range matches {
res.arguments = append(res.arguments, string(match[1]))
}
return res, nil
}
func (c *cmcClient) login() error {
if c.session != "" {
return nil
}
values := url.Values{}
values.Set("ST2", "NOTSET")
values.Set("user", flagCMCUsername)
values.Set("user_id", flagCMCUsername)
values.Set("password", flagCMCPassword)
values.Set("WEBSERVER_timeout", "1800")
values.Set("WEBSERVER_timeout_select", "1800")
valuesString := values.Encode()
glog.Info(valuesString)
req, err := http.NewRequest("POST", makeUrl(pathLogin), strings.NewReader(valuesString))
if err != nil {
return fmt.Errorf("POST prepare to %s failed: %v", pathLogin, err)
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
c.addCookies(req)
cl := &http.Client{
Transport: c.transport(),
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
resp, err := cl.Do(req)
if err != nil {
return fmt.Errorf("POST to %s failed: %v", pathLogin, err)
}
glog.Infof("Login response: %s", resp.Status)
defer resp.Body.Close()
for _, cookie := range resp.Cookies() {
if cookie.Name == "sid" {
c.session = cookie.Value
break
}
}
if c.session == "" {
return fmt.Errorf("login unsuccesful")
}
return nil
}
func (c *cmcClient) logout() {
glog.Infof("Killing session..")
if c.session == "" {
return
}
req, err := http.NewRequest("GET", makeUrl(pathLogout), nil)
if err != nil {
glog.Errorf("GET prepare to %s failed: %v", pathLogin, err)
}
c.addCookies(req)
cl := &http.Client{
Transport: c.transport(),
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
resp, err := cl.Do(req)
if err != nil {
glog.Errorf("GET to %s failed: %v", pathLogin, err)
}
glog.Infof("Logout response: %s", resp.Status)
return
}

75
main.go Normal file
View File

@ -0,0 +1,75 @@
package main
import (
"context"
"flag"
"code.hackerspace.pl/q3k/mirko"
"github.com/golang/glog"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "code.hackerspace.pl/q3k/cmc-proxy/proto"
)
var (
flagCMCAddress string
flagCMCUsername string
flagCMCPassword string
)
const (
pathLogin = "cgi-bin/webcgi/login"
pathLogout = "cgi-bin/webcgi/logout"
pathiDRACURL = "cgi-bin/webcgi/blade_iDRAC_url"
)
func init() {
flag.Set("logtostderr", "true")
}
type service struct {
cmc *cmcClient
}
func (s *service) GetKVMData(ctx context.Context, req *pb.GetKVMDataRequest) (*pb.GetKVMDataResponse, error) {
if req.BladeNum < 1 || req.BladeNum > 16 {
return nil, status.Error(codes.InvalidArgument, "blade_num must be [1,16]")
}
details, err := s.cmc.RequestKVMDetails(ctx, int(req.BladeNum))
if err != nil {
glog.Errorf("RequestKVMDetails(_, %d): %v", req.BladeNum, err)
return nil, status.Error(codes.Unavailable, "CMC unavailable")
}
return &pb.GetKVMDataResponse{
Arguments: details.arguments,
}, nil
}
func main() {
flag.StringVar(&flagCMCAddress, "cmc_address", "https://10.10.10.10", "URL of Dell M1000e CMC")
flag.StringVar(&flagCMCUsername, "cmc_username", "root", "Login username for CMC")
flag.StringVar(&flagCMCPassword, "cmc_password", "", "Login password for CMC")
flag.Parse()
m := mirko.New()
if err := m.Listen(); err != nil {
glog.Exitf("Could not listen: %v", err)
}
s := &service{
cmc: NewCMCClient(),
}
pb.RegisterCMCProxyServer(m.GRPC(), s)
if err := m.Serve(); err != nil {
glog.Exitf("Could not run: %v", err)
}
go s.cmc.Run(m.Context())
glog.Info("Running.")
<-m.Done()
}

3
proto/generate.go Normal file
View File

@ -0,0 +1,3 @@
//go:generate protoc -I.. ../proxy.proto --go_out=plugins=grpc:.
package proto

194
proto/proxy.pb.go Normal file
View File

@ -0,0 +1,194 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: proxy.proto
package proto
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type GetKVMDataRequest struct {
BladeNum int64 `protobuf:"varint,1,opt,name=blade_num,json=bladeNum,proto3" json:"blade_num,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetKVMDataRequest) Reset() { *m = GetKVMDataRequest{} }
func (m *GetKVMDataRequest) String() string { return proto.CompactTextString(m) }
func (*GetKVMDataRequest) ProtoMessage() {}
func (*GetKVMDataRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_700b50b08ed8dbaf, []int{0}
}
func (m *GetKVMDataRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetKVMDataRequest.Unmarshal(m, b)
}
func (m *GetKVMDataRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetKVMDataRequest.Marshal(b, m, deterministic)
}
func (m *GetKVMDataRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetKVMDataRequest.Merge(m, src)
}
func (m *GetKVMDataRequest) XXX_Size() int {
return xxx_messageInfo_GetKVMDataRequest.Size(m)
}
func (m *GetKVMDataRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetKVMDataRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetKVMDataRequest proto.InternalMessageInfo
func (m *GetKVMDataRequest) GetBladeNum() int64 {
if m != nil {
return m.BladeNum
}
return 0
}
type GetKVMDataResponse struct {
Arguments []string `protobuf:"bytes,1,rep,name=arguments,proto3" json:"arguments,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetKVMDataResponse) Reset() { *m = GetKVMDataResponse{} }
func (m *GetKVMDataResponse) String() string { return proto.CompactTextString(m) }
func (*GetKVMDataResponse) ProtoMessage() {}
func (*GetKVMDataResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_700b50b08ed8dbaf, []int{1}
}
func (m *GetKVMDataResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetKVMDataResponse.Unmarshal(m, b)
}
func (m *GetKVMDataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetKVMDataResponse.Marshal(b, m, deterministic)
}
func (m *GetKVMDataResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetKVMDataResponse.Merge(m, src)
}
func (m *GetKVMDataResponse) XXX_Size() int {
return xxx_messageInfo_GetKVMDataResponse.Size(m)
}
func (m *GetKVMDataResponse) XXX_DiscardUnknown() {
xxx_messageInfo_GetKVMDataResponse.DiscardUnknown(m)
}
var xxx_messageInfo_GetKVMDataResponse proto.InternalMessageInfo
func (m *GetKVMDataResponse) GetArguments() []string {
if m != nil {
return m.Arguments
}
return nil
}
func init() {
proto.RegisterType((*GetKVMDataRequest)(nil), "proto.GetKVMDataRequest")
proto.RegisterType((*GetKVMDataResponse)(nil), "proto.GetKVMDataResponse")
}
func init() { proto.RegisterFile("proxy.proto", fileDescriptor_700b50b08ed8dbaf) }
var fileDescriptor_700b50b08ed8dbaf = []byte{
// 156 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2e, 0x28, 0xca, 0xaf,
0xa8, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x53, 0x4a, 0x06, 0x5c, 0x82, 0xee,
0xa9, 0x25, 0xde, 0x61, 0xbe, 0x2e, 0x89, 0x25, 0x89, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25,
0x42, 0xd2, 0x5c, 0x9c, 0x49, 0x39, 0x89, 0x29, 0xa9, 0xf1, 0x79, 0xa5, 0xb9, 0x12, 0x8c, 0x0a,
0x8c, 0x1a, 0xcc, 0x41, 0x1c, 0x60, 0x01, 0xbf, 0xd2, 0x5c, 0x25, 0x23, 0x2e, 0x21, 0x64, 0x1d,
0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x32, 0x5c, 0x9c, 0x89, 0x45, 0xe9, 0xa5, 0xb9, 0xa9,
0x79, 0x25, 0xc5, 0x12, 0x8c, 0x0a, 0xcc, 0x1a, 0x9c, 0x41, 0x08, 0x01, 0x23, 0x5f, 0x2e, 0x0e,
0x67, 0x5f, 0xe7, 0x00, 0x90, 0xf5, 0x42, 0x8e, 0x5c, 0x5c, 0x08, 0xfd, 0x42, 0x12, 0x10, 0xe7,
0xe8, 0x61, 0x38, 0x42, 0x4a, 0x12, 0x8b, 0x0c, 0xc4, 0xb2, 0x24, 0x36, 0xb0, 0x8c, 0x31, 0x20,
0x00, 0x00, 0xff, 0xff, 0x09, 0x00, 0x2b, 0x54, 0xd1, 0x00, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// CMCProxyClient is the client API for CMCProxy service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type CMCProxyClient interface {
GetKVMData(ctx context.Context, in *GetKVMDataRequest, opts ...grpc.CallOption) (*GetKVMDataResponse, error)
}
type cMCProxyClient struct {
cc *grpc.ClientConn
}
func NewCMCProxyClient(cc *grpc.ClientConn) CMCProxyClient {
return &cMCProxyClient{cc}
}
func (c *cMCProxyClient) GetKVMData(ctx context.Context, in *GetKVMDataRequest, opts ...grpc.CallOption) (*GetKVMDataResponse, error) {
out := new(GetKVMDataResponse)
err := c.cc.Invoke(ctx, "/proto.CMCProxy/GetKVMData", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// CMCProxyServer is the server API for CMCProxy service.
type CMCProxyServer interface {
GetKVMData(context.Context, *GetKVMDataRequest) (*GetKVMDataResponse, error)
}
func RegisterCMCProxyServer(s *grpc.Server, srv CMCProxyServer) {
s.RegisterService(&_CMCProxy_serviceDesc, srv)
}
func _CMCProxy_GetKVMData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetKVMDataRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CMCProxyServer).GetKVMData(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/proto.CMCProxy/GetKVMData",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CMCProxyServer).GetKVMData(ctx, req.(*GetKVMDataRequest))
}
return interceptor(ctx, in, info, handler)
}
var _CMCProxy_serviceDesc = grpc.ServiceDesc{
ServiceName: "proto.CMCProxy",
HandlerType: (*CMCProxyServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetKVMData",
Handler: _CMCProxy_GetKVMData_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proxy.proto",
}

15
proxy.proto Normal file
View File

@ -0,0 +1,15 @@
syntax = "proto3";
package proto;
message GetKVMDataRequest {
int64 blade_num = 1;
}
message GetKVMDataResponse {
repeated string arguments = 1;
}
service CMCProxy {
rpc GetKVMData(GetKVMDataRequest) returns (GetKVMDataResponse);
}