👀

GoでgRPCを使ってIOS XRのshowコマンドを実行する

2020/09/21に公開

前回はCiscoのModel Driven TelemetryのDial outを紹介したが、今回はDial inを紹介する。

Dial inはこのファイルを参照する。元のprotoファイルを参照すると、コンフィグ操作とshowコマンド系を実行するserviceが定義されていることがわかる(コメント等省略)。

service gRPCConfigOper {
    rpc GetConfig(ConfigGetArgs) returns(stream ConfigGetReply) {};
    rpc MergeConfig(ConfigArgs) returns(ConfigReply) {};
    rpc DeleteConfig(ConfigArgs) returns(ConfigReply) {};
    rpc ReplaceConfig(ConfigArgs) returns(ConfigReply) {};
    rpc CliConfig(CliConfigArgs) returns(CliConfigReply) {};
    rpc CommitReplace(CommitReplaceArgs) returns (CommitReplaceReply) {};
    rpc CommitConfig(CommitArgs) returns(CommitReply) {};
    rpc ConfigDiscardChanges(DiscardChangesArgs) returns(DiscardChangesReply) {};
    rpc GetOper(GetOperArgs) returns(stream GetOperReply) {};
    rpc CreateSubs(CreateSubsArgs) returns(stream CreateSubsReply) {};
}

service gRPCExec {
    rpc ShowCmdTextOutput(ShowCmdArgs) returns(stream ShowCmdTextReply) {};
    rpc ShowCmdJSONOutput(ShowCmdArgs) returns(stream ShowCmdJSONReply) {};
}

今回はshow runを実行したいので、service gRPCExecの方を使うことにする。

IOS XR側に必要な設定は以下の通り(portは適当)。

grpc
 port 50051
 no-tls
!

まず、実行したいコマンドを構造体ShowCmdArgsとして作成する。

command := "show run"
cli := dialin.ShowCmdArgs{Cli: command}

次に、gRPCのクライアントを定義。

conn, _ := grpc.Dial("192.168.1.10:50051", grpc.WithInsecure())
client := dialin.NewGRPCExecClient(conn)

GRPCExecClientShowCmdTextOutputメソッドを実行するわけだが、ログイン認証という問題がある。

これはprotoファイルを眺めても全然やり方がわからないわけだが、pipelineのソースコードを眺めているとやり方がわかる。metadataを定義してコンテキストに埋め込んやればいい。

md := metadata.Pairs(
	"username", "root",
	"password", "password",
)

ctx := metadata.NewOutgoingContext(context.Background(), md)
reply, err := client.ShowCmdTextOutput(ctx, &cli)

というわけで全体像は以下のようになる。

package main

import (
	"context"
	"fmt"

	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"

	dialin "github.com/cisco/bigmuddy-network-telemetry-proto/proto_go/mdt_grpc_dialin"
)

func main() {

	md := metadata.Pairs(
		"username", "root",
		"password", "password",
	)

	command := "show run"
	cli := dialin.ShowCmdArgs{Cli: command}

	conn, _ := grpc.Dial("192.168.1.10:50051", grpc.WithInsecure())
	client := dialin.NewGRPCExecClient(conn)

	ctx := metadata.NewOutgoingContext(context.Background(), md)
	reply, err := client.ShowCmdTextOutput(ctx, &cli)

	if err != nil {
		fmt.Println(err)
	} else {
		msg, _ := reply.Recv()
		fmt.Println(msg.Output)
	}
}

ちなみに、この内容をpythonで書くと以下のようになる。

import grpc
from mdt_grpc_dialin_pb2 import *
from mdt_grpc_dialin_pb2_grpc import *

_metadata = [('username', 'root'), ('password', 'password')]

channel   = grpc.insecure_channel('192.168.1.10:50051')
exec_stub = gRPCExecStub(channel)

cli = ShowCmdArgs(cli="show run")
reply = exec_stub.ShowCmdTextOutput(cli, metadata=_metadata)

for r in reply:
    print(r.output)

余談だが、Dial outのpackage名はmdt_dialoutなのに、Dial inのpackage名はIOSXRExtensibleManagabilityServiceなのがなんかもやもやする...

次回はコンフィグ投入について書きます。

Discussion