#初めに
DevNet Sandboxを使って簡単にpyATS/Genieを試すことができる非常に良い記事があるので、その記事を参考にしながらGenieのHarnessをCML2で稼働させているネットワーク機器で試してみました。
(参考記事)
- DevNet Sandboxを使ってpyATS/XPRESSOをCML2と始めよう
#Genieとは
Genieとは、pyATSフレームワークのモジュラーアーキテクチャにバンドルされているネットワークテスト自動化に必要なすべてのツールを含むpyATS用のPythonライブラリ。
#Genie Harness
Genie Harnessは、Common Setup、Triggers and Verifications、Common Cleanupの3つのセクションでテストシナリオを構成します。コアとなるのはTriggers and Verificationsです。
interfaceのshutdown
、no shutdown
やBPGのunconfig
、restore
などの__アクション__がTriggersで処理され、Modelsのlearn object(Ops Object)
やParsers object
を駆使した__検証__がVerificationsで処理されます。VerificationsはTriggers前後に実行され、その取得した検証結果を比較し期待通りであるか判断します。
Genie Harnessは多くのモジュールが積み重ねられ、デバイスが更新されても対応できる将来性のある自動化ソリューションを作成することができます。
こちらにOS毎にサポートされているTriggers、こちらにVerificationsが掲載されています。
#testbed.yamlファイル
DevNet Sandboxの「Cisco pyATS XPRESSO」の環境でデモを実行します。
GenieのParsers、Models、Apisなどの各ライブラリを使用するためには、testbedというネットワーク構成を記載したyamlファイルが必要です。参考記事にもあるようにSandbox内にtestbed.yamlは準備されています。
また、前回記事にも掲載しています。
- Genie Parsersで実現するDevices’ outputsの構造化
#データファイル
Genie Harnessは、7つのdatafileを使用します。
①testbed.yaml Datafile (Mandatory)
testbed.yaml Datafileには、デバイス情報や、それらへの接続方法、サーバー、インターフェースなど、テスト対象のネットワーク構成が記述されています。
②Mapping Datafile (Optional)
Mapping Datafileは、ユーザーがtestbed.yaml上のどのデバイスのどの接続タイプを制御したいかなどをGenieに橋渡します。 Mapping Datafileが指定されない場合、Genieは全てのデバイスに接続します。
③Verification Datafile (Optional)
Verification Datafileには、検証に関するすべての情報が含まれています。 Verification Datafileが指定されない場合は、デフォルトのデータファイル$ VIRTUAL_ENV / genie_yamls / any os /verification_datafile.yamlが使用されます。
デフォルトのファイルを変更する場合にのみ、新しいVerification Datafileを指定する必要があります。
④Trigger Datafile (Optional)
Trigger Datafileには、トリガーに関するすべての情報が含まれています。 Trigger Datafileが指定されない場合は、デフォルトのデータファイル$ VIRTUAL_ENV / genie_yamls / any os /trigger_datafile.yamlが使用されます。
デフォルトのファイルを変更する場合にのみ、新しいTrigger Datafileを指定する必要があります。
⑤Subsection Datafile (Optional)
Subsection Datafileには、サブセクションに関するすべての情報が含まれています。 Subsection Datafileが指定されていない場合は、デフォルトのデータファイル$ VIRTUAL_ENV / genie_yamls /subsection_datafile.yamlが使用されます。
デフォルトのファイルを変更する場合にのみ、新しいSubsection Datafileを指定する必要があります。 それ以外の場合、必要なのはデフォルトのものだけです。
Subsectionは、Common SetupとCommon Cleanupで実行され、トリガー間では実行されません。 そのため、Genieは、実行に影響を与えることなく、デバイスに設定されたすべてのFeaturesの完全なスナップショットの作成、クラウドへの設定のバックアップやレストアなど、様々なタスクを実行できます。
⑥Configuration Datafile (Optional)
Configuration Datafileには、デバイスのコンフィグ設定に関するすべての情報が含まれています。Configuration Datafileが提供されていない場合、デバイスにコンフィグを設定することはありません。
⑦PTS Datafile (Optional)
PTS(Profile The System) Datafileには、Common SetupとCommon Cleanupで実行されるOps objectを使用したFeature statusの情報収集に関するすべての情報が含まれています。 PTS Datafileが提供されていない場合は、デフォルトのデータファイル$ VIRTUAL_ENV / genie_yamls /pts_datafile.yamlが使用されます。
デフォルトのファイルを変更する場合にのみ、新しいPTS Datafileを指定する必要があります。
PTSはOps objectを使用しFeature statusの情報収集をします。その点でVerificationに似ていますが、PTSはCommon SetupとCommon Cleanupでのみ実行されます。トリガー間では実行されません。PTSは2回しか実行されないため、Genie Harnessは、実行時間に影響を与えることなく、デバイスに構成されているすべての機能の完全なスナップショットを取得できます。PTSはOps objectを使用しFeature statusの情報を収集し比較することを目的としているので、Common SetupとCommon Cleanupで同じ処理をします。SubsectionのようにCommon SetupとCommon Cleanup時に異なる処理を実行しません。
PTSのもう1つの利点は、pts_golden_config機能です。 この機能により、Genieはデバイスに適用された構成の動作状態が、以前に作成された検証済みスナップショットと正確に一致することを検証できます。 これにより、同じ構成でのすべての実行で同じ動作状態が保証されます。
#Jobファイル
Genie Harnessを実行させるために必要なpythonファイルです。
実行するTriggers、Verificationsの選択や、参照するDatafilesの指定、PTSでSnapshotをとるFeatureの指定など、Argumentsでオプションを指定しながら実行するテストシナリオをgRun()
で構成、実行します。
# Import Genie run
from genie.harness.main import gRun
def main():
# Set job file path to current directory
test_path = os.path.dirname(os.path.abspath(__file__))
gRun(mapping_datafile=os.path.join(test_path, 'mapping.yaml'),
runtime=runtime, config_datafile=os.path.join('configs.yaml'),
pts_features=['ospf', 'hsrp'],
pts_datafile=os.path.join(test_path, 'pts_datafile'),
pts_golden_config='<path>/pts',
verification_datafile=os.path.join(test_path, 'verification_datafile'),
trigger_datafile=os.path.join(test_path, 'trigger_datafile'),
trigger_uids=['TriggerShutNoShutOspf', 'TriggerClearOspf'])
#JobファイルのArguments
Genieは高度にカスタマイズ可能であり、テストの仕様と要件を満たすように調整できます。 すべての引数は、gRunの引数としてジョブファイルに指定できます。
すべての引数はオプションなので、オプションを指定せずgRun()のみで実行することも可能です。
オプションを指定せずgRun()を実行すれば、Common SetupとCommon CleanupをデフォルトのSubsection Datafileに従って処理します。VerificationsやTriggersは実行されません。
- __
pts_features
:__スナップショットをとるFeatureを指定します。
gRun(pts_features=['ospf', 'bgp'])`
- __
pts_golden_config
:__PTS golden configuration fileの格納場所を指定します。
gRun(pts_golden_config='/path/pts')`
- __
verification_uids
:__実行するverification uidのリストを指定します。
gRun(verification_uids=['Verify_IpOspfNeighborDetail_vrf_all', 'Verify_IpRoute_protocol_bgp'])`
verification名は、Verification Datafileに定義しているものを指定します。
- __
verification_groups
:__実行するverificationsのグループを指定します。
# aetest.main() example using datastructure logic
from pyats.datastructures.logic import Or, And
gRun(verification_groups=And(Or('group1','group2'), 'group3'))
- __
trigger_uids
:__実行するverification uidのリストを指定します。
gRun(trigger_uids=['TriggerUnconfigConfigBgp', 'TriggerShutNoShutEthernetInterface'])
- __
trigger_groups
:__実行するtriggersのグループを指定します。
# aetest.main() example using datastructure logic
from pyats.datastructures.logic import Or, And
gRun(trigger_groups=And(Or('group1','group2'), 'group3'))
trigger名は、Trigger Datafileに定義しているものを指定します。
- __
mapping_datafile
:__Mapping Datafileの格納場所を指定します。
gRun(mapping_datafile='/path/mapping.pts')
- __
verification_datafile
:__Verification Datafileの格納場所を指定します。
gRun(verification_datafile='/path/verificationdatafile.yaml')
- __
trigger_datafile
:__Trigger Datafileの格納場所を指定します。
gRun(trigger_datafile='/path/triggerdatafile.yaml')
- __
config_datafile
:__Configuration Datafileの格納場所を指定します。
gRun(config_datafile='/path/config_datafile.yaml')
- __
subsection_datafile
:__Subsection Datafileの格納場所を指定します。
gRun(subsection_datafile='/path/subsection_datafile.yaml')
- __
pts_datafile
:__PTS Datafileの格納場所を指定します。
gRun(pts_datafile='/path/pts_datafile.yaml')
- __
debug_plugin
:__debug-pluginの格納場所を指定します。
# Inside a job file
# In case of single debug plugin in the run
gRun(debug_plugin='/path/debug_plugin')
# Inside a job file
# In case of multiple debug plugins in the run (differnet device types)
gRun(debug_plugin='/path/')
複数のdebug pluginを指定する場合は、下記のようにtestbed.yamlファイルの対応するdeviceのcustom sectionでそのdebug pluginを記載する必要があります。
custom:
debug_plugin: n7700-s2-debug-sh.8.4.1.gbin
- __
devices
:__Mapping Datafileを指定せず、ユーザーが複数のデバイスに接続したい場合に指定するデバイスのリスト。
devices
を指定せず、かつ、Mapping Datafileを指定していない場合、Genieはtestbed.yamlファイル内のすべてのデバイスを接続します。
gRun(devices=['N95_1', 'N95_2'])
- __
random
:__トリガーのランダム化を有効にすると、スクリプトのテストケースの順序をランダムにシャッフルできます。
gRun(pts_features=['platform', 'bgp', 'interface'],
verification_uids=['Verify_IpInterfaceBrief', 'Verify_IpRoute_vrf_all'],
trigger_uids=['TriggerUnconfigConfigBgp.uut', 'TriggerShutNoShutBgpNeighbors', 'TriggerModifyLoopbackInterfaceIp.uut', 'TriggerShutNoShutEthernetInterface'],
random=True)
#デモの概要
Sandbox - Cisco DevNetの環境を使って、
Genie Harnessを試してみます。TriggersとVerificationsはいろんなテストの組み合わせをplug and playのテストケースとして実現することができます。このデモでは、そのTriggersとVerificationsを簡単に試してみます。処理は以下のように進みます。
- testbed.yaml Datafile、Mapping Datafileで定義されているデバイスに接続します。
- 最初のVerificationsラウンドを実行します。 Verificationsで実行されるコマンドのアウトプットからステータスのスナップショットを取ります。 後に同じように実行されるVerificationsラウンドが、この最初のスナップショットと比較されます。
- 最初のTriggerである
TriggerUnconfigConfigBgp
を実行します。 - 2回目のVerificationsラウンドを実行します。この結果は最初のラウンドと比較されます。
- 2番目のTriggerである
TriggerModifyLoopbackInterfaceIp
を実行します。 - すべてのTriggersが実行されるまで繰り返します。
- 実行を終了します。
他にもGenie Harness ExamplesがGit Hubで公開されており、下記からcloneすることができます。
Genie Harness Examplesリポジトリ
#デモの手順
① CML2のルータへの追加設定
Sandbox - Cisco DevNetの「dist-rtr01」と「dist-rtr02」にBGPの設定を追加します。
両ルータ間でMP-BGPとSR-MPLSでのL3VPNを構成するようにします。
② データファイルの準備
__testbed.yaml__と同じディレクトリに、map.yaml(Mapping Datafile)、
verify.yaml(Verification Datafile)、trigger.yaml(Trigger Datafile)、pts.yaml(PTS Datafile)をtouch
やvim
でコピーします。Subsection DatafileはDefault Datafileを使用します。今回は追加コンフィグは直接手動で設定するので、Configuration Datafileは作成しません。
③Jobファイルの準備
__testbed.yaml__と同じディレクトリに、Jobファイルである__job.py__をコピーします。
④Jobの実行
pyats run job
コマンドで、__job.py__を実行します。
⑤ログ参照
pyats logs view
コマンドで、ブラウザからGUIでログを参照することができます。
#デモの実行
① CML2のルータへの追加設定
「dist-rtr01」へ__xe01.cfg__を、「dist-rtr02」へ__xe02.cfg__をcliで追加設定します。
vrf definition A
rd 65432:1
address-family ipv4
route-target both 65432:1
exit-address-family
vrf definition B
rd 65432:2
address-family ipv4
route-target both 65432:2
exit-address-family
interface loopback 0
ip address 172.16.252.101 255.255.255.255
no shutdown
interface loopback 1000
vrf forwarding A
ip address 10.0.0.101 255.255.255.255
no shutdown
interface loopback 1001
vrf forwarding B
ip address 10.0.1.101 255.255.255.255
no shutdown
segment-routing mpls
!
connected-prefix-sid-map
address-family ipv4
172.16.252.101/32 index 1 range 1
exit-address-family
router ospf 1
segment-routing area 0 mpls
segment-routing mpls
router bgp 65432
no bgp default ipv4-unicast
neighbor 172.16.252.102 remote-as 65432
neighbor 172.16.252.102 update-source Loopback0
!
address-family vpnv4
neighbor 172.16.252.102 activate
neighbor 172.16.252.102 send-community both
exit-address-family
!
address-family ipv4 vrf A
redistribute connected
exit-address-family
!
address-family ipv4 vrf B
redistribute connected
exit-address-family
vrf definition A
rd 65432:1
address-family ipv4
route-target both 65432:1
exit-address-family
vrf definition B
rd 65432:2
address-family ipv4
route-target both 65432:2
exit-address-family
interface loopback 0
ip address 172.16.252.102 255.255.255.255
no shutdown
interface loopback 1000
vrf forwarding A
ip address 10.0.0.102 255.255.255.255
no shutdown
interface loopback 1001
vrf forwarding B
ip address 10.0.1.102 255.255.255.255
no shutdown
segment-routing mpls
!
connected-prefix-sid-map
address-family ipv4
172.16.252.102/32 index 2 range 1
exit-address-family
router ospf 1
segment-routing area 0 mpls
segment-routing mpls
router bgp 65432
no bgp default ipv4-unicast
neighbor 172.16.252.101 remote-as 65432
neighbor 172.16.252.101 update-source Loopback0
!
address-family vpnv4
neighbor 172.16.252.101 activate
neighbor 172.16.252.101 send-community both
exit-address-family
!
address-family ipv4 vrf A
redistribute connected
exit-address-family
!
address-family ipv4 vrf B
redistribute connected
exit-address-family
② データファイルの準備
__testbed.yaml__と同じディレクトリに、map.yaml(Mapping Datafile)、
verify.yaml(Verification Datafile)、trigger.yaml(Trigger Datafile)、pts.yaml(PTS Datafile)をコピーします。
devices:
xe01:
context: cli
pool_size: 2
mapping:
cli: cli
xe02:
context: cli
pool_size: 2
mapping:
cli: cli
__testbed.yaml__の中から、検証対象のデバイスと、デバイスへの接続方式を__map.yaml__で指定してGenieに渡します。
extends: "%CALLABLE{genie.libs.sdk.genie_yamls.datafile(verification)}"
Verify_BgpAll:
devices: ['xe01', 'xe02']
exclude: []
Verify_BgpAllSummary:
devices: ['xe01', 'xe02']
exclude: []
iteration:
attempt: 10
interval: 10
Verify_IpInterfaceBrief:
devices: ['xe01', 'xe02']
exclude: []
Verification Datafileは、実行するVerificationsとその場所を示すYAMLファイルで、次の項目を記載します。
- Verification名
- Verification source — Verificationクラスとそのパス
- テストを実行するデバイス(
-- device
で指定する。) - その他のVerificationに引数として渡すパラメーター
extends: "%CALLABLE{genie.libs.sdk.genie_yamls.datafile(trigger)}"
TriggerUnconfigConfigBgp:
groups: ['unconfig-config', 'bgp', 'L3']
method: 'checkpoint'
timeout:
max_time: 400
interval: 10
tgn_timeout: 300
tgn_delay: 10
devices: ['xe01', 'xe02']
TriggerModifyLoopbackInterfaceIp:
groups: ['modify', 'interface', 'L3']
method: 'checkpoint'
timeout:
max_time: 180
interval: 10
tgn_timeout: 300
tgn_delay: 10
devices: ['xe01', 'xe02']
Trigger Datafileは、実行するテストケースとその場所を示すYAMLファイルで、次の項目を記載します。
- Trigger名
- Trigger source — triggerクラスとそのパス
- テストを実行するデバイス(
-- device
で指定する。) - その他のTriggerに引数として渡すパラメーター
platform:
source:
pkg: genie.libs.ops
class: platform.platform.Platform
devices: ['xe01', 'xe02']
exclude: []
bgp:
source:
pkg: genie.libs.ops
class: bgp.bgp.Bgp
devices: ['xe01', 'xe02']
exclude: []
interface:
source:
pkg: genie.libs.ops
class: interface.interface.Interface
devices: ['xe01', 'xe02']
exclude: []
③__Jobファイルの準備__
testbed.yamlと同じディレクトリに、Jobファイルであるdemo2_harness_triggers_job.pyをコピーします。
import os
from genie.harness.main import gRun
def main():
test_path = os.path.dirname(os.path.abspath(__file__))
gRun(mapping_datafile=os.path.join(test_path, 'map.yaml'),
pts_datafile=os.path.join(test_path, 'pts.yaml'),
trigger_datafile=os.path.join(test_path, 'trigger.yaml'),
verification_datafile=os.path.join(test_path, 'verify.yaml'),
pts_features=['platform', 'bgp', 'interface'],
verification_uids=['Verify_IpInterfaceBrief', 'Verify_BgpAllSummary'],
trigger_uids=['TriggerUnconfigConfigBgp', 'TriggerModifyLoopbackInterfaceIp'])
④__Jobの実行__
pyats run job
コマンドで、__job.py__を実行します。
pyats run job job.py --testbed-file testbed.yaml
⑤__ログ参照__
ログはリアルタイムにコンソールに表示され、最終的に下記のようなサマリーレポートが表示されます。ログは~/.pyats/archive
に保存されます。
+------------------------------------------------------------------------------+
| Easypy Report |
+------------------------------------------------------------------------------+
pyATS Instance : /home/developer/py3venv
Python Version : cpython-3.6.8 (64bit)
CLI Arguments : /home/developer/py3venv/bin/pyats run job job.py --testbed-file testbed.yaml
User : developer
Host Server : devbox
Host OS Version : CentOS Linux 7 Core (x86_64)
Job Information
Name : job
Start time : 2021-09-19 06:08:24.292997
Stop time : 2021-09-19 06:10:29.827424
Elapsed time : 125.534427
Archive : /home/developer/.pyats/archive/21-Sep/job.2021Sep19_06:08:21.772769.zip
Total Tasks : 1
Overall Stats
Passed : 26
Passx : 0
Failed : 0
Aborted : 0
Blocked : 0
Skipped : 0
Errored : 0
TOTAL : 26
Success Rate : 100.00 %
+------------------------------------------------------------------------------+
| Task Result Summary |
+------------------------------------------------------------------------------+
Task-1: genie_testscript.common_setup PASSED
Task-1: genie_testscript.Verify_IpInterfaceBrief.xe01.1 PASSED
Task-1: genie_testscript.Verify_IpInterfaceBrief.xe02.1 PASSED
Task-1: genie_testscript.Verify_BgpAllSummary.xe01.1 PASSED
Task-1: genie_testscript.Verify_BgpAllSummary.xe02.1 PASSED
Task-1: genie_testscript.TriggerUnconfigConfigBgp.xe01 PASSED
Task-1: genie_testscript.Verify_IpInterfaceBrief.xe01.2 PASSED
Task-1: genie_testscript.Verify_IpInterfaceBrief.xe02.2 PASSED
Task-1: genie_testscript.Verify_BgpAllSummary.xe01.2 PASSED
Task-1: genie_testscript.Verify_BgpAllSummary.xe02.2 PASSED
Task-1: genie_testscript.TriggerUnconfigConfigBgp.xe02 PASSED
Task-1: genie_testscript.Verify_IpInterfaceBrief.xe01.3 PASSED
Task-1: genie_testscript.Verify_IpInterfaceBrief.xe02.3 PASSED
Task-1: genie_testscript.Verify_BgpAllSummary.xe01.3 PASSED
Task-1: genie_testscript.Verify_BgpAllSummary.xe02.3 PASSED
Task-1: genie_testscript.TriggerModifyLoopbackInterfaceIp.xe01 PASSED
Task-1: genie_testscript.Verify_IpInterfaceBrief.xe01.4 PASSED
Task-1: genie_testscript.Verify_IpInterfaceBrief.xe02.4 PASSED
Task-1: genie_testscript.Verify_BgpAllSummary.xe01.4 PASSED
Task-1: genie_testscript.Verify_BgpAllSummary.xe02.4 PASSED
Task-1: genie_testscript.TriggerModifyLoopbackInterfaceIp.xe02 PASSED
Task-1: genie_testscript.Verify_IpInterfaceBrief.xe01.5 PASSED
Task-1: genie_testscript.Verify_IpInterfaceBrief.xe02.5 PASSED
Task-1: genie_testscript.Verify_BgpAllSummary.xe01.5 PASSED
Task-1: genie_testscript.Verify_BgpAllSummary.xe02.5 PASSED
Task-1: genie_testscript.common_cleanup PASSED
+------------------------------------------------------------------------------+
| Task Result Details |
+------------------------------------------------------------------------------+
Task-1: genie_testscript
|-- common_setup PASSED
| |-- connect PASSED
| |-- configure SKIPPED
| |-- configuration_snapshot PASSED
| |-- save_bootvar PASSED
| |-- learn_system_defaults PASSED
| |-- initialize_traffic SKIPPED
| |-- profile_platform_pre PASSED
| |-- profile_bgp_pre PASSED
| |-- profile_interface_pre PASSED
| `-- PostProcessor-1 PASSED
|-- Verify_IpInterfaceBrief.xe01.1 PASSED
| `-- verify PASSED
|-- Verify_IpInterfaceBrief.xe02.1 PASSED
| `-- verify PASSED
|-- Verify_BgpAllSummary.xe01.1 PASSED
| `-- verify PASSED
|-- Verify_BgpAllSummary.xe02.1 PASSED
| `-- verify PASSED
|-- TriggerUnconfigConfigBgp.xe01 PASSED
| |-- verify_prerequisite PASSED
| | |-- STEP 1: Learning 'Bgp' Ops PASSED
| | |-- STEP 2: Verifying requirements PASSED
| | `-- STEP 3: Merge requirements PASSED
| |-- save_configuration PASSED
| |-- unconfigure PASSED
| | `-- STEP 1: Unconfiguring 'Bgp' PASSED
| |-- verify_unconfigure PASSED
| | `-- STEP 1: Verifying 'Bgp' state with ops.bgp.bgp.Bgp PASSED
| |-- restore_configuration PASSED
| `-- verify_initial_state PASSED
| `-- STEP 1: Verifying ops 'Bgp' is back to original state PASSED
|-- Verify_IpInterfaceBrief.xe01.2 PASSED
| `-- verify PASSED
|-- Verify_IpInterfaceBrief.xe02.2 PASSED
| `-- verify PASSED
|-- Verify_BgpAllSummary.xe01.2 PASSED
| `-- verify PASSED
|-- Verify_BgpAllSummary.xe02.2 PASSED
| `-- verify PASSED
|-- TriggerUnconfigConfigBgp.xe02 PASSED
| |-- verify_prerequisite PASSED
| | |-- STEP 1: Learning 'Bgp' Ops PASSED
| | |-- STEP 2: Verifying requirements PASSED
| | `-- STEP 3: Merge requirements PASSED
| |-- save_configuration PASSED
| |-- unconfigure PASSED
| | `-- STEP 1: Unconfiguring 'Bgp' PASSED
| |-- verify_unconfigure PASSED
| | `-- STEP 1: Verifying 'Bgp' state with ops.bgp.bgp.Bgp PASSED
| |-- restore_configuration PASSED
| `-- verify_initial_state PASSED
| `-- STEP 1: Verifying ops 'Bgp' is back to original state PASSED
|-- Verify_IpInterfaceBrief.xe01.3 PASSED
| `-- verify PASSED
|-- Verify_IpInterfaceBrief.xe02.3 PASSED
| `-- verify PASSED
|-- Verify_BgpAllSummary.xe01.3 PASSED
| `-- verify PASSED
|-- Verify_BgpAllSummary.xe02.3 PASSED
| `-- verify PASSED
|-- TriggerModifyLoopbackInterfaceIp.xe01 PASSED
| |-- verify_prerequisite PASSED
| | |-- STEP 1: Learning 'Interface' Ops PASSED
| | |-- STEP 2: Verifying requirements PASSED
| | `-- STEP 3: Merge requirements PASSED
| |-- save_configuration PASSED
| |-- modify_configuration PASSED
| | `-- STEP 1: Configuring 'Interface' PASSED
| |-- verify_modification PASSED
| | `-- STEP 1: Verifying 'Interface' state with ops.interface.... PASSED
| |-- restore_configuration PASSED
| `-- verify_initial_state PASSED
| `-- STEP 1: Verifying ops 'Interface' is back to original s... PASSED
|-- Verify_IpInterfaceBrief.xe01.4 PASSED
| `-- verify PASSED
|-- Verify_IpInterfaceBrief.xe02.4 PASSED
| `-- verify PASSED
|-- Verify_BgpAllSummary.xe01.4 PASSED
| `-- verify PASSED
|-- Verify_BgpAllSummary.xe02.4 PASSED
| `-- verify PASSED
|-- TriggerModifyLoopbackInterfaceIp.xe02 PASSED
| |-- verify_prerequisite PASSED
| | |-- STEP 1: Learning 'Interface' Ops PASSED
| | |-- STEP 2: Verifying requirements PASSED
| | `-- STEP 3: Merge requirements PASSED
| |-- save_configuration PASSED
| |-- modify_configuration PASSED
| | `-- STEP 1: Configuring 'Interface' PASSED
| |-- verify_modification PASSED
| | `-- STEP 1: Verifying 'Interface' state with ops.interface.... PASSED
| |-- restore_configuration PASSED
| `-- verify_initial_state PASSED
| `-- STEP 1: Verifying ops 'Interface' is back to original s... PASSED
|-- Verify_IpInterfaceBrief.xe01.5 PASSED
| `-- verify PASSED
|-- Verify_IpInterfaceBrief.xe02.5 PASSED
| `-- verify PASSED
|-- Verify_BgpAllSummary.xe01.5 PASSED
| `-- verify PASSED
|-- Verify_BgpAllSummary.xe02.5 PASSED
| `-- verify PASSED
`-- common_cleanup PASSED
|-- verify_configuration_snapshot PASSED
|-- stop_traffic SKIPPED
|-- profile_platform_post PASSED
|-- profile_bgp_post PASSED
|-- profile_interface_post PASSED
また、pyats logs view
コマンドでブラウザ経由でログを参照することができます。
下記コマンドを投入しブラウザでhttp://10.10.20.50:8181にアクセスすればログがとても分かりやすく可視化されています。
pyats logs view --host 10.10.20.50 --port 8181
DockerコンテナなどでpyATS/Genieの環境を作成している場合は、ブリッジネットワーク上で割り当てられたコンテナのアドレスと、内部ポート番号を指定します。
#まとめ
Genie Harnessを使えば多くのモジュールが積み重ねらた自動化ソリューションを、Verificationsや Triggers、PTSを組み合わせるだけで簡単に作成することができます。また、Common Setup、Testcases、Common CleanupなどpyATSのテストスクリプトの構造を理解するのにも適しています。
#参考リンク
- DevNet Sandboxを使ってpyATS/XPRESSOをCML2と始めよう
- Genie Parsersで実現するDevices’ outputsの構造化
- Genie Documentation
- genie-feature-browser