うさラボ

お勉強と備忘録

CML-PのUbuntuでSSHにつまづいた

CMLで構築してるいるときにあった小ネタvol.2

CMLで立てたUbuntuiosSSHできなかったときにごちゃごちゃやっていたことの備忘録

検証環境を作成時に、マネジメントアクセス用でUbuntuを作成しました。

SSHの設定を終えて、IOSvにSSHしようとしたとき下記のログが出てきてアクセスできませんでした

f:id:usage_automate:20210117202320p:plain

ログを見るにかきkeyがなかったことが原因だったようです。 diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1

/etc/ssh/ssh_configにKexAlgorithms diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1を追記したところSSHが可能になりました。

iosvの設定方法がよくなかったのかもしれませんが、解決できたので書き残しておきます。

/etc/ssh/ssh_config

# This is the ssh client system-wide configuration file.  See
# ssh_config(5) for more information.  This file provides defaults for
# users, and the values can be changed in per-user configuration files
# or on the command line.

# Configuration data is parsed as follows:
#  1. command line options
#  2. user-specific file
#  3. system-wide file
(~snip~)
    KexAlgorithms diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1

CML-P Breakout-toolの使い方

CMLで構築してるいるときにあった小ネタvol.1

Breakout-toolは、ラボ環境で動作しているデバイスのコンソールポートへの接続性を提供する機能です。

イメージ図 f:id:usage_automate:20210117201118p:plain

Breakout-toolの使い方の話

インストールはCMLGUI画面から移動するサイトで可能です。

Windows/Mac/Linuxとそれぞれで実行ファイルがダウンロード可能です

f:id:usage_automate:20210117195241p:plain

Macで利用する場合は信頼されていないアプリケーションの実行がデフォルトで許可されていないので、自分で信頼ずみにする必要があります。

ダウンロードページに移動するとドキュメントがあるので基本はそちらを読んでいけば大丈夫です。

f:id:usage_automate:20210117195451p:plain

自分でもtweetしてますが、実行権限がたりたくて実行できずに結構ハマりました。

実行時にオプションでuiをつけるとGUIで起動可能です

breakout-macos-x86_amd64 ui

起動後、ページアクセスし、Configの設定をします。

f:id:usage_automate:20210117200247p:plain

最後に、対象LabのStatusをOff->Onに変更します。

f:id:usage_automate:20210117200332p:plain

対象Labをクリックし、アクセスしたいデバイスLinkをクリックするとアクセス可能です。

f:id:usage_automate:20210117200557p:plain

Cisco Certified DevNet Associate 合格体験記

Cisco Certified DevNet Associate 取得しました

2020年中になんとかDevNetの資格が欲しい!と思っていたので年内ギリギリで取得して来ました!

参考になるかわかりませんが自分がやった準備を書き残したいと思います

ちなみに、825点合格で825点でした(ギリギリすぎ)

なんとか合格できたもののもうちょっと勉強しておけばよかったなぁって気持ちもあります。

出題範囲

まず、最初に出題範囲の確認をしました。

公式サイトからざっくりと出題範囲をまとめてみました

15% ソフトウェア開発と設計
20% API の理解と使用
15% シスコ プラットフォームと開発
15% アプリケーションの展開とセキュリティ
20% インフラストラクチャと自動化
15% ネットワークの基礎

www.cisco.com

自分の知識レベル

  • Pythonは少し知ってる(Python 3 エンジニア認定基礎試験は合格してます)
  • 業務で簡単なスクリプトを書いたりしている
  • NWエンジニア歴5年目

とまぁ、目立ったスキルはありませんが数年前に勉強したPythonで空きあらば自作スクリプトを作成し、ちょっとしたことを効率化したりしてます。

勉強方法

試験の予約をしてから、「さて、どうやって勉強しようか」と迷いまくってました。

有料のコンテンツは使わないでなんとかしたいなぁと考えていたのでDevNet Associate Fundamentals Course という公式の教材がありましたが利用しませんでした(おそらくこれを利用するのが一番良いっぽい、しかし英語)。

とりあえず、APIの理解とソフトウェア開発についてを重点的に勉強をしました。

次にシスコ プラットフォームと開発とインフラストラクチャと自動化を手を動かしながら学習、Devnetのサンドボックス最高

  • Meraki,DNA,USC ManagerのAPIの叩き方も勉強(認証方式などなど)
  • Ansibleの出ると買いてあったのでIOS,ASAの設定変更系のモジュール確認
  • NETCONF,RESTCONF,gNMI,YANGのキーワードは勉強(私はちょっと勉強が足りてませんでした...)

他にもDevnetのLearning?のの日本語化されているトラックも参考にしました。

Cisco DevNet: APIs, SDKs, Sandbox, and Community for Cisco Developers

あまり参考にならないと思いますが読んだ本(さらっと読みしかしてないっす)

AmazonKidleunlimitede最高

アジャイル/ウォーターフールの説明を読んだ

APIのところだけ読みました

体系的に学ぶには何がいいのだろうか。。といまだに思う

試験中

試験が始まって、見直しができないことに気づきました。

Microsoftの試験を受けたときは見直しができたので、軽い気持ちで問題を解いてから「後で見直そ〜」と思ってませんでしたがそんなこともできずに ドキドキしながら問題を解いていきました。

日本語翻訳は若干苦しかったです。(私の読解力が足りない可能性は大)

感想

感想としては「なんとか取れた。」でした、正直試験中は「あー、これは来年再挑戦かもなぁ」と思うくらいの自信でした。

結果的に取れたから良いものの勉強不足を痛感したので、継続して勉強を続けようと思える試験になりました。

考えるのが嫌なのでIPアドレス計算ツール作ってみました

192.168.99.43/28のネットワークアドレスってなんだっけ

IPアドレスをパッとみたときにネットワークアドレスとか利用IPなどを頭の中で計算することってありませんか?

私はよくやっていて、その度に念のためググって確認しようってなっていました。

そこでPythonのipaddressモジュールを使いIPアドレスの計算をしてくれるCLIツールを作ってみました。

f:id:usage_automate:20201225183812p:plain

f:id:usage_automate:20201225183821p:plain

簡単なものですが紹介します。

構成

(ipcal) usalab!:ipcal-1.0 $ tree
.
├── ipcal
│   ├── __init__.py
│   ├── main.py
│   └── util.py
└── setup.py

main.pyはutil.pyを呼び出しのとclickで--ipのオプションで実行時にもIPセグメントの入力ができます。

from . import util
import click

@click.command()
@click.option('--ip',default='', type=str, help='ipaddress')
def main(ip):
  ipnetwork = util.input_value_cast_to_ipv4network(ip)
  util.ipnetwork_information(ipnetwork)

if __name__ == '__main__':
  main()

util.py(名前つけるセンスがない)ではipaddressモジュールを利用して、入力値をIPv4Networkオブジェクトにして返すinput_valueと計算結果を表示するipnetwork_informationの2つのメソッドを作成してます。

import ipaddress
import sys

def input_value_cast_to_ipv4network(input_ip):
  '''
  入力値をipaddressオブジェクトにキャストして戻す
  '''
  if input_ip:
    try:
      ipnetwork = ipaddress.ip_network(input_ip,strict=False)
      return ipnetwork
    except ValueError:
      print(f"Error: Value Error")
      sys.exit(1)
    except Exception as e:
      print(f"Error: {e}")
      sys.exit(1)
  else:
    value = input('IPアドレス入力[X.X.X.X/X]>> ')
    try:
      ipnetwork = ipaddress.ip_network(value,strict=False)
      return ipnetwork
    except ValueError:
      print(f"Error: Value Error")
      sys.exit(1)
    except Exception as e:
      print(f"Error: {e}")
      sys.exit(1)

def ipnetwork_information(ipnetwork):
  print(f'Prefix          : {ipnetwork.with_prefixlen}')
  print(f'SubnetMask      : {ipnetwork.netmask}')
  print(f'WildCardMask    : {ipnetwork.with_hostmask}')
  print(f'NetworkAddress  : {ipnetwork.network_address}')
  print(f'BroadCastAddress: {ipnetwork.broadcast_address}')

ipaddressモジュールのメソッドを呼び出すだけで簡単にネットワークアドレスやブロードキャストアドレスを表示することができます。

どうやって公開するのがいいのかよくわからない。。

python setup sdistを実施してpip install dist/ipcal-1.0.tar.gzすることでipcalコマンドで実行することができます。

ググる時間が減ったのでヨシ!!

参考にさせていただいたサイト

qiita.com

blog.amedama.jp

buildersbox.corp-sansan.com

docs.python.org

Microsoft Azure AZ-104取得しました

AZ-104合格できました

私がした勉強方法を紹介したいと思います。

少しでも参考になるとこがあれば幸いです

自分の知識レベル

  • AZ-900は合格
  • 業務でAzureはいっさい触ってない

やったこと

速習Azure Administratorを一気読みしました。

試験の内容がまとまっていて非常に参考になりました

しかし、これを読めばOKといった本ではなかったです。

Azureをちょびっと触る、、

無料枠を無駄に使い切っていたのでほんとに少しだけ、、

vNETの作成やピアリングなどをちょびっと試した程度です

MS LearnとDocを読む

特に苦手なストレージ/AADは追加でMS Learnを読みました

Azure Storage アカウントをセキュリティで保護する - Learn | Microsoft Docs

VPN Gateway を使用して、ご利用のオンプレミス ネットワークを Azure に接続する - Learn | Microsoft Docs

Azure DNS のドキュメント | Microsoft Docs

などなど

模擬試験をやってみる

試験前々日くらいか流石に焦りだし、情報を漁ってると模擬試験があることを知りました。

下記のQiitaを参考にさせていただき模擬試験をやってみました。

Azure Administrator Associate模擬試験問題サイトまとめ - Qiita

いろいろとあるようですが、私はJPN試験 (日本語)のみやりました。

受験してみての感想

受験中に、「こりゃダメかな。。」と思うくらい手応えはなかったですw

結果的には723点(700点が合格ライン)とギリギリでしたが合格できました。

模擬試験で試験の雰囲気をなんとなく理解できていたのが良かったのかもしれません。

NSG/AAD/WebApp/DNS/VPNなど試験範囲は結構広かったので大変でしたが取得できてよかったです。

pyATS/genieを組み込んだスクリプト作成してみた

本記事はエーピーコミュニケーションズ Advent Calendar 2020の11日目の記事です。

qiita.com

pyATSについて

pyATSはCisco社製のテスト自動化ソリューションです。

pythonで書かれたOSSです。

細い情報は以下も参考にしていただければと思います。

インストール編 usage-automate.hatenablog.com

Testbed編 usage-automate.hatenablog.com

pyATS/genieを組み込んだスクリプトを作成してみました

勉強のために、作ったスクリプトを2つほどお見せいたします。(スクリプト部分が多いです)

pyATS利用イメージの助けになれば幸いです(あまりスクリプトに組み込むことはないかもですが)

Testbedファイルは以下を作成し利用しました(CiscoのSnadboxで常時解放されているIOS-XE,IOS-XR)

---
devices:
  csr1000v-1:
      alias: xe1
      credentials:
        default:
          username: developer
          password: C1sco12345
      connections:
        vty:
          protocol: ssh
          ip: ios-xe-mgmt-latest.cisco.com
      os: iosxe
      type: iosxe
  TEST-CONV:
    credentials:
      default:
        username: admin
        password: C1sco12345
    connections:
      vty:
        protocol: ssh
        ip: sbx-iosxr-mgmt.cisco.com
        port: 8181
    os: iosxr
    type: iosxr

[1] Routing取得(Leanの利用)

Testbedファイルに定義したデバイスのRoutingを取得し表示させます。

え?普通に機器入ってコマンド打てば良いじゃんって?それは言わないお約束

実行結果 f:id:usage_automate:20201211002202p:plain

作成した、Scriptの解説をしていきます。

内容としてはpyATS/genieのLeanメソッドを利用して、Routing情報を取得と整形、表示をやっているだけになります。

まずpyATS/genieを利用するためにgenie.conf.Genieスクリプト内にimportします。

#Genie import
from genie.conf import Genie

まず最初にGenie.initを呼び出しTestbedをLoadします。

  try:
    #####テストベッドを初期化####
    testbed = Genie.init(testbed)
    print(">>> Load Testbed >>>")
  except TypeError:
    print('Testbed Load Error[001]')
    sys.exit(1)

testbed.connectでDeviceに接続します。

接続にはUniconライラブリを利用しています。

  #####接続#####
  try:
    testbed.connect(log_stdout=False)
    for device in testbed.devices.keys():
      if testbed.devices[device].is_connected():
        print(f">>> {device} Connected >>>")
  except unicon.core.errors.ConnectionError:
    print('Connection Error[002]')
    sys.exit(1)

pyATS/genieのleanメソッドを利用して、Routing情報を取得します。 f:id:usage_automate:20201211123320p:plain Cisco DevNet: APIs, SDKs, Sandbox, and Community for Cisco Developers

今回対象のIOS-XEでは下記コマンド

  • show ip route
  • show ip route vrf
  • show ipv6 route updated
  • show ipv6 route vrf updated

IOS-XRでは下記コマンドを実行し、実行結果が.infoに格納されます。

  • show route ipv4
  • show route vrf all ipv4 show route ipv6
  • show route vrf all ipv6

XEとXRで微妙にRoutingを確認するコマンドが違いますが、learn('routing')をすると、.infoには同様の構成の辞書(dict)で情報が格納されます。

    #####Routing取得####
    print(f">>> {device} Learn Routing >>>")
    lean_routing = testbed.devices[device].learn('routing')
    routes = lean_routing.info['vrf']['default']['address_family']['ipv4']['routes']

learn('routing')の実行結果から、Route/NextHop/Interfaceの情報のみ抜き出し、tabulateを利用し表として出力させます。

NexthopがないRouteなど、実行結果によって微妙に値に引っ張りかたが変わったのがつまづきポイントでした。

    #####整形#####
    for route in routes.keys():
      if 'next_hop_list' in list(routes[route]['next_hop'].keys()):
        routes_list.append(routes[route]['route'])
        next_hops_list.append(routes[route]['next_hop']['next_hop_list'][1]['next_hop'])
        if 'outgoing_interface' in list(routes[route]['next_hop']['next_hop_list'][1].keys()):
          outgoing_interface_list.append(routes[route]['next_hop']['next_hop_list'][1]['outgoing_interface'])
        else:
          outgoing_interface_list.append('-')
      else:
        for interface in list(routes[route]['next_hop']['outgoing_interface'].keys()):
          routes_list.append(routes[route]['route'])
          next_hops_list.append('-')
          outgoing_interface_list.append(routes[route]['next_hop']['outgoing_interface'][interface]['outgoing_interface'])

    headers = ["route", "next_hops","outgoing_interface"]
    table = [routes_list, next_hops_list, outgoing_interface_list]
    result = tabulate.tabulate(np.array(table).transpose(), headers,tablefmt="grid")
    print(result)

最後にDeviceからログアウトして処理を終了させています。

    ####切断####
    print(f"<<< {device} Disconnected <<<")
    testbed.devices[device].disconnect()

作成したpythonスクリプト(全行)

#Genie import
from genie.conf import Genie

import unicon
import tabulate
import click
import sys
import numpy as np

@click.command()
@click.option('-t','--testbed',type=str,required=True)
def main(testbed):
  #####事前処理#####
  print(">>>>> Start >>>>>>")

  try:
    #####テストベッドを初期化####
    testbed = Genie.init(testbed)
    print(">>> Load Testbed >>>")
  except TypeError:
    print('Testbed Load Error[001]')
    sys.exit(1)

  #####接続#####
  try:
    testbed.connect(log_stdout=False)
    for device in testbed.devices.keys():
      if testbed.devices[device].is_connected():
        print(f">>> {device} Connected >>>")
  except unicon.core.errors.ConnectionError:
    print('Connection Error[002]')
    sys.exit(1)

  for device in testbed.devices.keys():
    ####List初期化####
    routes_list = list()
    next_hops_list = list()
    outgoing_interface_list = list()

    #####Routing取得####
    print(f">>> {device} Learn Routing >>>")
    lean_routing = testbed.devices[device].learn('routing')
    routes = lean_routing.info['vrf']['default']['address_family']['ipv4']['routes']

    #####整形#####
    for route in routes.keys():
      if 'next_hop_list' in list(routes[route]['next_hop'].keys()):
        routes_list.append(routes[route]['route'])
        next_hops_list.append(routes[route]['next_hop']['next_hop_list'][1]['next_hop'])
        if 'outgoing_interface' in list(routes[route]['next_hop']['next_hop_list'][1].keys()):
          outgoing_interface_list.append(routes[route]['next_hop']['next_hop_list'][1]['outgoing_interface'])
        else:
          outgoing_interface_list.append('-')
      else:
        for interface in list(routes[route]['next_hop']['outgoing_interface'].keys()):
          routes_list.append(routes[route]['route'])
          next_hops_list.append('-')
          outgoing_interface_list.append(routes[route]['next_hop']['outgoing_interface'][interface]['outgoing_interface'])

    headers = ["route", "next_hops","outgoing_interface"]
    table = [routes_list, next_hops_list, outgoing_interface_list]
    result = tabulate.tabulate(np.array(table).transpose(), headers,tablefmt="grid")
    print(result)

    ####切断####
    print(f"<<< {device} Disconnected <<<")
    testbed.devices[device].disconnect()
  print("<<<<<<< End <<<<<<<")

if __name__ == '__main__':
  main()

[2] ACL確認用Script

続いて、SourceIPとDestination IPを入力すると該当のACLがHitするScriptを作成しました。

こちらはlearn('acl')を利用しています。

learn('acl')は現状はXEのみ対応しています。

実行結果① f:id:usage_automate:20201211121354p:plain

実行結果② f:id:usage_automate:20201211121359p:plain

pythonの標準モジュールのipaddressを利用して、検索対象が含まれるIPを抽出しHitしたACLのみを表として表示させました。

leanメソッドで辞書になっているため、値の取り出し方を覚えれば応用は簡単にできます。

今回はlearnを利用しましたが、parseを利用する場合は特定の値を抜き出すためにDqと呼ばれるメソッドも用意されているようです。

ACLが適当すぎたので、少し反省しつつも想定どおりに動いてくれました。

#Genieモジュールをインポート
from genie.conf import Genie

import re
import unicon
import tabulate
import click
import sys
import numpy as np
import ipaddress

def format_ipaddress(ipv4_net):
  if ipv4_net == 'any':
    ipv4_net = ipaddress.ip_network('0.0.0.0/0')
  elif re.search('host', str(ipv4_net)) is not None:
    ipv4_net = ipaddress.ip_network(ipv4_net.replace('host ',''))
  else:
    ipv4_net = ipaddress.ip_network(ipv4_net.replace(' ','/'))
  return ipv4_net

@click.command()
@click.option('-t','--testbed',type=str,required=True)
@click.option('-sip','--source_ip_address',type=str,prompt='Source IP>>')
@click.option('-dip','--destination_ip_address',type=str,prompt='Destination IP>>')
def main(testbed,source_ip_address,destination_ip_address):
  #####事前処理#####
  #メッセージ
  print(">>>>> Start >>>>>>")
  try:
    if source_ip_address == 'any':
      search_source_ipaddress = ipaddress.ip_network('0.0.0.0/0')
    else:
      search_source_ipaddress = ipaddress.ip_network(source_ip_address,strict=False)
    if destination_ip_address == 'any':
      search_destination_ipaddress = ipaddress.ip_network('0.0.0.0/0')
    else:
      search_destination_ipaddress = ipaddress.ip_network(destination_ip_address,strict=False)
  except TypeError or ValueError:
    print('IPaddress Load Error[001]')
    sys.exit(1)
  try:
    #テストベッドを初期化
    testbed = Genie.init(testbed)
    print(">>> Load Testbed >>>")
  except TypeError:
    print('Testbed Load Error[002]')
    sys.exit(1)
  
  try:
    for device in testbed.devices.keys():
      if testbed.devices[device].os == 'iosxe':
        testbed.connect(log_stdout=False)
        if testbed.devices[device].is_connected():
          print(f">>> {device} Connected >>>")
      else:
        print(f"<< {device} skkiped {testbed.devices[device].os} is not support <<")
  except unicon.core.errors.ConnectionError:
    print('Connection Error[003]')
    sys.exit(1)

  for device in testbed.devices.keys():
    # List初期化
    acl_list = list()
    source_list = list()
    destination_list = list()
    src_port_list = list()
    dst_port_list =list()
    action_list =list()

    if testbed.devices[device].os == 'iosxe':
    #ACL取得
      print(f">>> {device} Learn ACL >>>")
      lean_acls = testbed.devices[device].learn('acl')
      acl_name_list = list(lean_acls.info['acls'].keys())
      for acl in acl_name_list:
        if 'aces' in lean_acls.info['acls'][acl].keys():
          aces = lean_acls.info['acls'][acl]['aces']
          for ace in aces.keys():
            destination_ipv4_network = aces[ace]['matches']['l3']['ipv4']['destination_ipv4_network']
            source_ipv4_network = aces[ace]['matches']['l3']['ipv4']['source_ipv4_network']
            for dst_ipv4_net,src_ipv4_net in zip(destination_ipv4_network.keys(),source_ipv4_network.keys()):
              dst_ipv4_net = format_ipaddress(dst_ipv4_net)
              src_ipv4_net = format_ipaddress(src_ipv4_net)

              if search_destination_ipaddress.subnet_of(dst_ipv4_net) or search_source_ipaddress.subnet_of(src_ipv4_net):
                acl_list.append(lean_acls.info['acls'][acl]['name'])
                source_list.append(src_ipv4_net)
                src_port_list.append('-')
                destination_list.append(dst_ipv4_net)
                dst_port_list.append('-')
                action_list.append(aces[ace]['actions']['forwarding'])
      headers = ["acl", "src_ip","src_port","dst_ip","dst_port","action"]
      table = [acl_list, source_list, src_port_list,destination_list,dst_port_list,action_list]
      result = tabulate.tabulate(np.array(table).transpose(), headers,tablefmt="grid")
      print(f">>> {device} Hit ACL >>>")
      print(result)

      print(f"<<< {device} Disconnected <<<")
      testbed.devices[device].disconnect()
  print("<<<<<<< End <<<<<<<")


if __name__ == '__main__':
  main()

ACLプロトコルを全部IPにしてしまったので、source_portやdestination_portの情報が取れずなかったため、、 プロトコルTCP/UDPに設定しているACLで検索する場合は改修が必要です(いつかやります)

振り返りと次回

今回、自作ScriptにpyATS/genieを組み込んでみました。

欲しい値をピンポイントで取得するには多少時間がかかってしまいましたが、半日も掛からずScriptができました。

物凄い簡単!とは言えませんでしたが、pythonを嗜んでいる方ならばそこまで時間がかからずにキャッチアップできると思います。

今度こそ、次回でJob書きます!

pyATS shellの実行

pyATS shell

これまでpyATSのインストールとTestbedファイルの作成を実施してきました

pyATS インストール編 - うさラボ

pyATS Testbed作成 - うさラボ

shellコマンドを実行することでpythonの対話型インタプリンタが起動しpyATSの機能を利用することができます。

今回はshellコマンドを利用して簡単に、pyATSの機能を確認しましょう。

起動

さっそくpyats shellを実行します。

--testbedオプションで前回作成したTestbedを指定します。

(pyats-core) usalab!:nw_lab $ pyats shell --testbed vars/sample.yml 
Welcome to pyATS Interactive Shell
==================================
Python 3.7.5 (default, Nov 27 2019, 18:39:20) 
[Clang 11.0.0 (clang-1100.0.33.8)]

>>> from pyats.topology import loader
>>> testbed = loader.load('vars/sample.yml')
-------------------------------------------------------------------------------
>>>

pyats shellでインタプリンタが起動したら、TestbedファイルのDeviceに接続してみましょう。

接続

接続にはUniconと呼ばれる、接続用のライブラリを利用しています(pip install pyatsで同時にインストールされる)

テストベットに登録している全てのデバイスに接続するには下記コマンドを利用します

testbed.connect()

テストベット内の対象デバイスに接続する場合は下記コマンドを実施

testbed.devices['csr-1000v*ホスト名'].connect()

さっそく接続しましょう

>>> testbed.connect()

2020-12-06 22:01:14,198: %UNICON-INFO: +++ csr1000v logfile /tmp/csr1000v-default-20201206T220114198.log +++

2020-12-06 22:01:14,199: %UNICON-INFO: +++ Unicon plugin iosxe +++

Welcome to the DevNet Sandbox for CSR1000v and IOS XE

The following programmability features are already enabled:
   - NETCONF
   - RESTCONF

Thanks for stopping by.


2020-12-06 22:01:16,685: %UNICON-INFO: +++ connection to spawn: ssh -l developer 64.103.37.51 -p 8181, id: 4611986512 +++

2020-12-06 22:01:16,686: %UNICON-INFO: connection to csr1000v
Password: 

Welcome to the DevNet Sandbox for CSR1000v and IOS XE

The following programmability features are already enabled:
  - NETCONF
  - RESTCONF

Thanks for stopping by.


csr1000v#

2020-12-06 22:01:20,983: %UNICON-INFO: +++ initializing handle +++

2020-12-06 22:01:20,985: %UNICON-INFO: +++ csr1000v: executing command 'term length 0' +++
term length 0
csr1000v#

(~snip~)

2020-12-06 22:01:25,206: %UNICON-INFO: +++ csr1000v: configure +++
config term
Enter configuration commands, one per line.  End with CNTL/Z.
csr1000v(config)#no logging console
csr1000v(config)#line console 0
csr1000v(config-line)#exec-timeout 0
csr1000v(config-line)#end
csr1000v#
['\r\r\nWelcome to the DevNet Sandbox for CSR1000v and IOS XE\r\r\n\r\r\nThe following programmability features are already enabled:\r\r\n   - NETCONF\r\r\n   - RESTCONF\r\r\n\r\r\nThanks for stopping by.\r\r\n\rPassword: \r\n\r\nWelcome to the DevNet Sandbox for CSR1000v and IOS XE\r\n\r\nThe following programmability features are already enabled:\r\n  - NETCONF\r\n  - RESTCONF\r\n\r\nThanks for stopping by.\r\n\r\n\r\ncsr1000v#']
>>> 

確認(接続状態/showコマンド)

接続の確認にはis_connected()のメソッドを利用します。

>>> testbed.devices['csr1000v'].is_connected()
True

今回はpyATSのみしかインストールしていませんので、genieのメソッドは利用できません(parse/learnなど)。

続いて、deviceにコマンド送ることのできるexecuteメソッドを利用してshow versionを実施してみます。

>>> testbed.devices['csr1000v'].execute('show version')

2020-12-06 22:43:52,130: %UNICON-INFO: +++ csr1000v: executing command 'show version' +++
show version
Cisco IOS XE Software, Version 16.09.03
Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.9.3, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2019 by Cisco Systems, Inc.
Compiled Wed 20-Mar-19 07:56 by mcpre


Cisco IOS-XE software, Copyright (c) 2005-2019 by cisco Systems, Inc.
All rights reserved.  Certain components of Cisco IOS-XE software are
licensed under the GNU General Public License ("GPL") Version 2.0.  The
software code licensed under GPL Version 2.0 is free software that comes
with ABSOLUTELY NO WARRANTY.  You can redistribute and/or modify such
GPL code under the terms of GPL Version 2.0.  For more details, see the
documentation or "License Notice" file accompanying the IOS-XE software,
or the applicable URL provided on the flyer accompanying the IOS-XE
software.


ROM: IOS-XE ROMMON

csr1000v uptime is 20 hours, 31 minutes
Uptime for this control processor is 20 hours, 32 minutes
System returned to ROM by reload
System image file is "bootflash:packages.conf"
Last reload reason: reload



This product contains cryptographic features and is subject to United
States and local country laws governing import, export, transfer and
use. Delivery of Cisco cryptographic products does not imply
third-party authority to import, export, distribute or use encryption.
Importers, exporters, distributors and users are responsible for
compliance with U.S. and local country laws. By using this product you
agree to comply with applicable laws and regulations. If you are unable
to comply with U.S. and local laws, return this product immediately.

A summary of U.S. laws governing Cisco cryptographic products may be found at:
http://www.cisco.com/wwl/export/crypto/tool/stqrg.html

If you require further assistance please contact us by sending email to
export@cisco.com.

License Level: ax
License Type: Default. No valid license found.
Next reload license Level: ax


Smart Licensing Status: Smart Licensing is DISABLED

cisco CSR1000V (VXE) processor (revision VXE) with 2392579K/3075K bytes of memory.
Processor board ID 939QG0VY6CG
3 Gigabit Ethernet interfaces
32768K bytes of non-volatile configuration memory.
8113280K bytes of physical memory.
7774207K bytes of virtual hard disk at bootflash:.
0K bytes of WebUI ODM Files at webui:.

Configuration register is 0x2102

csr1000v#
'Cisco IOS XE Software, Version 16.09.03\r\nCisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.9.3, RELEASE SOFTWARE (fc2)\r\nTechnical Support: http://www.cisco.com/techsupport\r\nCopyright (c) 1986-2019 by Cisco Systems, Inc.\r\nCompiled Wed 20-Mar-19 07:56 by mcpre\r\n\r\n\r\nCisco IOS-XE software, Copyright (c) 2005-2019 by cisco Systems, Inc.\r\nAll rights reserved.  Certain components of Cisco IOS-XE software are\r\nlicensed under the GNU General Public License ("GPL") Version 2.0.  The\r\nsoftware code licensed under GPL Version 2.0 is free software that comes\r\nwith ABSOLUTELY NO WARRANTY.  You can redistribute and/or modify such\r\nGPL code under the terms of GPL Version 2.0.  For more details, see the\r\ndocumentation or "License Notice" file accompanying the IOS-XE software,\r\nor the applicable URL provided on the flyer accompanying the IOS-XE\r\nsoftware.\r\n\r\n\r\nROM: IOS-XE ROMMON\r\n\r\ncsr1000v uptime is 20 hours, 31 minutes\r\nUptime for this control processor is 20 hours, 32 minutes\r\nSystem returned to ROM by reload\r\nSystem image file is "bootflash:packages.conf"\r\nLast reload reason: reload\r\n\r\n\r\n\r\nThis product contains cryptographic features and is subject to United\r\nStates and local country laws governing import, export, transfer and\r\nuse. Delivery of Cisco cryptographic products does not imply\r\nthird-party authority to import, export, distribute or use encryption.\r\nImporters, exporters, distributors and users are responsible for\r\ncompliance with U.S. and local country laws. By using this product you\r\nagree to comply with applicable laws and regulations. If you are unable\r\nto comply with U.S. and local laws, return this product immediately.\r\n\r\nA summary of U.S. laws governing Cisco cryptographic products may be found at:\r\nhttp://www.cisco.com/wwl/export/crypto/tool/stqrg.html\r\n\r\nIf you require further assistance please contact us by sending email to\r\nexport@cisco.com.\r\n\r\nLicense Level: ax\r\nLicense Type: Default. No valid license found.\r\nNext reload license Level: ax\r\n\r\n\r\nSmart Licensing Status: Smart Licensing is DISABLED\r\n\r\ncisco CSR1000V (VXE) processor (revision VXE) with 2392579K/3075K bytes of memory.\r\nProcessor board ID 939QG0VY6CG\r\n3 Gigabit Ethernet interfaces\r\n32768K bytes of non-volatile configuration memory.\r\n8113280K bytes of physical memory.\r\n7774207K bytes of virtual hard disk at bootflash:.\r\n0K bytes of WebUI ODM Files at webui:.\r\n\r\nConfiguration register is 0x2102'
>>> 

このようにexecuteメソッドを利用することで任意のをコマンドを送信することが可能です。

設定変更

設定変更はconfigureメソッドを利用することで可能です。

static routeの追加作業を実現してみましょう

executeで事前事後の確認も合わせて実施します。

// 設定確認
>>> testbed.devices['csr1000v'].execute('show run | inc route')

2020-12-06 23:03:02,226: %UNICON-INFO: +++ csr1000v: executing command 'show run | inc route' +++
show run | inc route
ip route 0.0.0.0 0.0.0.0 GigabitEthernet1 10.10.20.254
ip route 8.8.8.8 255.255.255.255 Null0
csr1000v#
'ip route 0.0.0.0 0.0.0.0 GigabitEthernet1 10.10.20.254\r\nip route 8.8.8.8 255.255.255.255 Null0'
>>> 

// 設定追加
>>> testbed.devices['csr1000v'].configure('ip route 1.1.1.1 255.255.255.255 10.10.20.254')

2020-12-06 23:06:42,714: %UNICON-INFO: +++ csr1000v: configure +++
config term
Enter configuration commands, one per line.  End with CNTL/Z.
csr1000v(config)#ip route 1.1.1.1 255.255.255.255 10.10.20.254
csr1000v(config)#end
csr1000v#
'ip route 1.1.1.1 255.255.255.255 10.10.20.254\r\n'
>>> 

// 設定確認
>>> testbed.devices['csr1000v'].execute('show run | inc route')

2020-12-06 23:07:14,288: %UNICON-INFO: +++ csr1000v: executing command 'show run | inc route' +++
show run | inc route
ip route 0.0.0.0 0.0.0.0 GigabitEthernet1 10.10.20.254
ip route 1.1.1.1 255.255.255.255 10.10.20.254
ip route 8.8.8.8 255.255.255.255 Null0
csr1000v#
'ip route 0.0.0.0 0.0.0.0 GigabitEthernet1 10.10.20.254\r\nip route 1.1.1.1 255.255.255.255 10.10.20.254\r\nip route 8.8.8.8 255.255.255.255 Null0'
>>> 

追加後の確認からも想定通り追加されたことが確認できました。

下記コマンドは自動で入力してくれます。 * configure termina * end

他にも、設定追加で複数行送信したい場合はリストで定義すれば可能です。

今回、pyatsコアモジュールでshellコマンドで実施し、簡単な接続/設定確認/設定変更を実施してみました。

genieがあるとさらにparse/learn/api/triggerなど強力な機能も利用できるようになります。

次回は、pyatsで簡単なJobを作成してみます。