Cisco IMC(CIMC)1 のEmulatorをインストールしてpythonからログイン・ログアウトのAPIを実行してみたのですが、XMLや構造体(メソッド)などの勉強としてGoでも同じことをやってみたので備忘録として書いておきます。
CIMC Emulatorインストールについて
CIMCやインストール方法については以下を参照ください。
CIMC API Document
CIMCのAPIを使いたかったきっかけ
CIMC経由でサーバの監視や管理を自動化したかった
GoでCIMCにログイン・ログアウト
ソース
package main
import (
"crypto/tls"
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"
"github.com/urfave/cli"
)
// ログインのXML構造体
type aaaLogin struct {
InName string `xml:"inName,attr"`
InPassword string `xml:"inPassword,attr"`
}
// ログアウトのXML構造体
type aaaLogout struct {
Cookie string `xml:"cookie,attr"`
InCookie string `xml:"inCookie,attr"`
}
// Login CIMCへログインしてCookieを取得するメソッド
func (data *aaaLogin) Login(url string) (cookie string, err error) {
// ログインレスポンスのBodyで得られるXMLの構造体
type aaaLogin struct {
Cookie string `xml:"cookie,attr"`
Response string `xml:"response,attr"`
OutCookie string `xml:"outCookie,attr"`
OutRefreshPeriod int32 `xml:"outRefreshPreiod,attr"`
OutPriv string `xml:"outPriv,attr"`
OutSessionID int32 `xml:"outSessionId,attr"`
OutVersion string `xml:"outVersion,attr"`
}
// ログイン用XMLに変換
reqXML, err := xml.Marshal(data)
if err != nil {
return "", err
}
// Bodyを取得
body, err := PostRequest(url, reqXML)
if err != nil {
return "", err
}
// Cookieを戻す
resData := new(aaaLogin)
if err := xml.Unmarshal(body, resData); err != nil {
return "", err
}
return resData.OutCookie, nil
}
// Logout CIMCからログアウトするメソッド
func (data *aaaLogout) Logout(url string) (status string, err error) {
// ログアウトレスポンスのBodyで得られるXMLの構造体
type aaaLogout struct {
Cookie string `xml:"cookie,attr"`
Response string `xml:"response,attr"`
OutStatus string `xml:"outStatus,attr"`
}
// ログアウト用XMLに変換
reqXML, err := xml.Marshal(data)
if err != nil {
return "", err
}
// Bodyを取得
body, err := PostRequest(url, reqXML)
if err != nil {
return "", err
}
// OutStatusを戻す
resData := new(aaaLogout)
if err := xml.Unmarshal(body, resData); err != nil {
return "", err
}
return resData.OutStatus, nil
}
// PostRequest CIMCにPostリクエストを実行する関数
func PostRequest(url string, reqXML []byte) (body []byte, err error) {
// HTTPクライアントを作成、SSL証明書の検証はスキップ
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true},
},
}
// リクエストを作成
req, err := http.NewRequest("POST", url, strings.NewReader(string(reqXML)))
if err != nil {
return nil, err
}
// ヘッダ追加
req.Header.Add("content-type", "application/x-www-form-urlencoded")
// リクエストを実行
res, err := client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
// 取得したBodyを戻す
body, err = ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
return body, nil
}
func doMain(c *cli.Context) {
// CIMCへログイン
login := new(aaaLogin)
login.InName = c.String("user")
login.InPassword = c.String("password")
cookie, _ := login.Login(c.String("url"))
fmt.Println("cookie: " + cookie)
// CIMCからログアウト
logout := new(aaaLogout)
logout.Cookie = cookie
logout.InCookie = cookie
status, _ := logout.Logout(c.String("url"))
fmt.Println("Logout: " + status)
}
func main() {
app := cli.NewApp()
app.Name = "cimc_login_logout"
app.Usage = "CIMCログイン,ログアウトツール"
app.UsageText = "cimc_login_logout [--url CIMC URL] [--user CIMC USER] [--password CIMC USER PASSWORD]"
app.Version = "0.1"
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "url",
Value: "https://127.0.0.1/nuova",
Usage: "CIMC URL",
},
cli.StringFlag{
Name: "user, u",
Value: "admin",
Usage: "CIMC Login User.",
},
cli.StringFlag{
Name: "password, p",
Value: "password",
Usage: "CIMC Login User Password.",
},
}
app.Action = doMain
app.Run(os.Args)
}
実行
[root@localhost ~]# go build -o cimc_login_logout main.go
[root@localhost ~]# ./cimc_login_logout --url https://192.168.1.54/nuova
cookie: 1507529279/7cd516ac-5b17-1b17-800d-ee768522e470
Logout: success
できた :-)
CIMCの管理構造について
CIMCの管理モデルはツリー構造化されています。
Emulatorで起動したUCS C220 M4の全ツリー構造については参考までに以下に保存してあります。
XMLだと見にくいのでJSONに変換してみました。
-
Cisco UCS Cシリーズの管理コントローラー、HPだとiLo ↩