ラボ環境の自動化に pyATS Clean を活用しよう！

この記事はシスコの有志による Cisco Systems Japan Advent Calendar 2021 1枚目の 11 日目として投稿しています。

2022年版: https://qiita.com/advent-calendar/2022/cisco (<<<)
2021年版: https://qiita.com/advent-calendar/2021/cisco
2021年版(2枚目): https://https://qiita.com/advent-calendar/2021/cisco2
2020年版: https://qiita.com/advent-calendar/2020/cisco
2020年版(2枚目): https://qiita.com/advent-calendar/2020/cisco2
2019年版: https://qiita.com/advent-calendar/2019/cisco
2018年版: https://qiita.com/advent-calendar/2018/cisco
2017年版: https://qiita.com/advent-calendar/2017/cisco

# はじめに

pyATS 開発チームに**所属していた**東村(@tahigash3)です。シスコジャパンではなく、シスコカナダで働いております。最近自分の希望で pyATS チームから異動し、今は開発チームと連携して SRv6 の新機能に対する内容や実装の確認、テストプラン作成やそのテストケースの実装など、社内テストの自動化をメインで行っております(もちろん pyATS を使ってます)。

今回は [Cisco](https://cisco.com) が開発しているネットワーク自動化ツール [pyATS](https://developer.cisco.com/pyats/)が提供している `pyATS Clean` という機能を紹介したいと思います。

過去の記事でも [pyATS](https://developer.cisco.com/pyats/) について書いているので、こちらも合わせて参照ください。

- [今からでも遅くない pyATS でネットワーク自動化入門 2021版](https://qiita.com/tahigash/items/05a2cad4365ec1a47f55)
- [DevNet Sandbox を使って pyATS/XPRESSO を CML2 と始めよう](https://qiita.com/tahigash/items/753cffdbf6380afa823f)
- [pyATS と Python辞書/JSON が楽しくなる Dq(Data Query) を極める!!](https://qiita.com/tahigash/private/2776b00e97a416b98e3d)
- [pyATS|Genieの隠れ必殺技Blitzを用いて高速自動化テスト作成](https://qiita.com/tahigash/items/fa00872a1ced946da23b)
- [pyATS/GenieとRobot Framework で簡単にマルチベンダーネットワークをチェックする](https://qiita.com/tahigash/items/ceb0809a4a9464c521b3)

また Cisco Japan の有志が今年のアドベントカレンダーで pyATS について書いてくれている記事もあるので、こちらも是非！

- [pyATSでConfigを残すけど残しすぎない？ツール](https://qiita.com/kykanno/items/8a7d4aae66767b7159a0)

# pyATS Clean とは?

pyATS Clean とは名前の通り、クリーニングを行ってくれます。と言っても何かよく分からないと思いますが。。皆さんががラボでテスト環境を作成してテスト行っている時に、どのような悩みがあるでしょうか？テスト自体は pyATS、Ansible、TeraTermのマクロ等で自動化しているかもしれません。
が、下記のような事は手動でやっていたりしませんか？

- イメージの入れ替え
- ROMMON に落ちている機器の復旧
- コンソールが誰かに掴まれており、コンソールサーバに入りセッションを切る

pyATS Clean とは上記のようなことすらも自動化でき、一言で言うと **テスト行う前の期待される状況にラボ環境をセットアップしてくれます**。

# pyATS Clean の動作フロー

下記が pyATS Clean の動作フローになります。

![61059657-2C02-44CF-AB9B-A20EC010106F.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/496c8e82-b5ee-f61e-bf59-caedbcad4a8f.png)

簡単に書くと下記のようになります。

1.pyATS Clean の開始
2.Cleanステージの実行
3.デバイスへの接続性のチェック。
4.接続できない場合はコンソールサーバ経由でセッション切断
5.それでも接続できない場合はパワーサイクラーで電源のOFF/ON
6.ROMMON から TFTP サーバ経由でイメージの起動
7.接続に問題がない、接続問題が解消されたら2.へ戻る

`Cleanステージ`とは詳細は後述しますが、`接続(connect)`や`再起動(reload)`など pyATS Clean の機能毎のステージとなります。

要はクリーニングのステップ（各ステージ）を実行し、接続性の確認を実行、問題があれば復旧し、クリーニングを続行するということになります。

# testbed.yaml へサーバやパワーサイクラー等の情報の追加

pyATS Clean ではコンソールサーバでのコンソールセッションの切断やデバイしの再起動などができると書きましたが、残念ながらマジックはありません。その機能を使うためにはラボ環境にコンソールサーバやパワーサイクラーが必要になります。

### tftp サーバの追記

`testbed.yaml` の `testbed` セクションの中に `servers` セクションを追加し、下記のようにtftpサーバ情報を追加します。

```yaml:testbed.yaml
testbed:
  name: pyATS-testbed
  servers:
    tftp:
      server: pyats-tftp   # tftpサーバー名
      address: 192.168.1.1 # tftpサーバーアドレス
      path: /auto/path/images/
```

### コンソールサーバ及びパワーサイクラーの追記

次にコンソールサーバ及びパワーサイクラーを testbed.yaml へ追記します。
この2つはデバイス毎に異なる情報となるため、`devices` セクションのデバイスの配下に `peripherals` というセクションで追加します。

```yaml:testbed.yaml
devices:
  asr1000:
    os: iosxe
    (snip)
    peripherals:
      terminal_server:
        pyats-ts-1: [41] # ターミナルサーバ名 `pyats-ts-1`。ポート番号 41
      power_cycler:
        type: dualcomm           # パワーサイクラーのタイプ
        connection_type: snmp    # SNMP 経由での電源OFF/ON
        host: 10.1.1.1           # パワーサイクラーのIPアドレス
        read_community: public   # SNMP コミュニティ for Read-Only
        write_community: public  # SNMP コミュニティ for Read-Write
        outlets: [1, 2]          # デバイスが接続されているOutlet番号  
```

:::note
パワーサイクラーやコンソールサーバ情報が無くても pyATS Clean を実行することはできますが、電源OFF/ONやコンソールセッションの切断などの機能が使えなくなります。
:::

# clean.yaml の作成

`testbed.yaml` の更新が終わったら、次はメインの clean.yaml を作成します。
ただ、最初は難しいと思うので、pyATS チームが作成したサンプルファイルを活用しましょう。

pyATS Clean のサンプルファイルは下記の GitHub にあります。

https://github.com/CiscoTestAutomation/examples/tree/master/clean

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/08f8614d-b184-a928-b4a3-2fc38ba51647.png">

上記のように色々なプラットフォームの例が用意されています。

今回は ASR1K の例を見ていきたいと思います。

https://github.com/CiscoTestAutomation/examples/blob/master/clean/full_clean_asr1k_iosxe/clean.yaml

各項目の説明を下記 yaml ファイルの中に記載しています。

```yaml:clean.yaml
cleaners:                    # devices 以外はお決まりとお覚えください
  DeviceClean:
    module: genie.libs.clean
    devices: [asr1000]       # pyATS Clean の対象デバイスを指定

devices:
  asr1000:
    images:                            # 起動したいイメージの場所を指定
      - /auto/release/path/vmlinux.bin

    device_recovery:                           # デバイスの復旧
      break_count: 5                           # ()
      console_activity_pattern: "\\.\\.\\.\\." # ROMMON に落とすタイミングとなる表示パターンを指定。機種によって調整が必要な場合あり
      timeout: 600                             # デバイス復旧のタイムアウト値
      recovery_password: "%ENC{w5zDmsOD}"      # ()
      golden_image:
        - bootflash:/golden_image.bin          # デバイス上のイメージ指定

    connect:  # デバイスへの接続

    ping_server:               # ping で tftp サーバーへの接続確認
      server: pyats-tftp       # tftp サーバー名
      vrf: Mgmt-intf           # tftp サーバへの接続に VRF 指定が必要な場合

    copy_to_linux:                    # イメージをtftpサーバへコピー
      destination:
        directory: /auto/path/images/ # tftp サーバがアクセスできる場所
      overwrite: True                 # イメージの上書きを許可するか
      copy_attempts: 3                # 試行回数
      append_hostname: True           # イメージ名にホスト名を追加するか

    copy_to_device:               # イメージをデバイスへコピー
      origin:
        hostname: pyats-tftp      # TFTPサーバ名
      destination:
        directory: 'harddisk:/'   # デバイス上のコピー先
      protocol: tftp              # コピーに使用するプロトコル    
      overwrite: True             # 上書きを許可するか
      verify_num_images: False    # イメージ数をチェックするか
      check_file_stability: True  # ファイルが安定しているかのチェック
      min_free_space_percent: 50  # 空きスペースの閾値

    change_boot_variable:         # boot variable の設定

    write_erase:                  # コンフィグの削除

    reload:                       # デバイスのリロード

    apply_configuration:          # 初期設定の追加
      configuration: |            # 初期設定のコンフィグを記述
        hostname asr1000
        enable password banana
        interface GigabitEthernet0
          ip address X.X.X.X 255.255.255.0
          no shut
        line console 0
          exec-timeout 0 0
          logging synchronous
        line vty 0 4
          password lab
      config_timeout: 30          # 設定時のタイムアウト値 
      config_stable_time: 120     # 設定後の待ち時間

    verify_running_image:         # イメージの確認

    order:                        # Clean ステージの実行順序
      - 'connect'
      - 'ping_server'
      - 'copy_to_linux'
      - 'copy_to_device'
      - 'change_boot_variable'
      - 'write_erase'
      - 'reload'
      - 'apply_configuration'
      - 'verify_running_image'
```

それでは各ステージを簡単に説明していきます。

### `images`

```yaml:clean.yamlの抜粋
    images:                            # 起動したいイメージの場所を指定
      - /auto/release/path/vmlinux.bin
```

デバイスを起動させるイメージを指定します。**YAML 内では同じレベルにありますが、`images` は Clean ステージではありません。**

### `device_recovery`

```yaml:clean.yamlの抜粋
    device_recovery:                           # デバイスの復旧
      break_count: 5                           # ()
      console_activity_pattern: "\\.\\.\\.\\." # ROMMON に落とすタイミングとなる表示パターンを指定。機種によって調整が必要な場合あり
      timeout: 600                             # デバイス復旧のタイムアウト値
      recovery_password: "%ENC{w5zDmsOD}"      # ()
      golden_image:
        - bootflash:/golden_image.bin          # デバイス上のイメージ指定
```

**`device_recovery` も同じく Clean ステージではありません。** `device_discovery` はデバイスにアクセスできない、電源OFF/ONによる復旧が必要な場合に実行される**救済機能**となります。
通常は実行されませんが、Clean ステージ実行後にデバイスに接続できないような状況になった場合に実行されます。

### `connect` ステージ

```yaml:clean.yamlの抜粋
    connect:  # デバイスへの接続
```

デバイスへ接続します。ただそれだけです。w
通常特にパラメーターは渡さないため、Cleanステージ名のみになります。

:::note warn
デバイスに接続しないと何もできないため、`connect` ステージは必ず必要になります。
:::

### `ping_server` ステージ

```yaml:clean.yamlの抜粋
    ping_server:               # ping で tftp サーバーへの接続確認
      server: pyats-tftp       # tftp サーバー名
      vrf: Mgmt-intf           # tftp サーバへの接続に VRF 指定が必要な場合
```

指定した `server` へ ping を行い、疎通があることを確認します。これは デバイス <-> TFTP サーバ間の確認となります。TFTP サーバーへの接続に使う Mgmt インタフェースに VRF を設定している場合は、その VRF も指定します。

:::note
通常、イメージをコピーするTFTPサーバへの疎通性確認を行いますが、server の指定を変更することでTFTPサーバ以外の疎通確認にも使えます。
:::

### `copy_to_linux` ステージ

```yaml:clean.yamlの抜粋
    copy_to_linux:                    # イメージをtftpサーバへコピー
      destination:
        directory: /auto/path/images/ # tftp サーバがアクセスできる場所
      overwrite: True                 # イメージの上書きを許可するか
      copy_attempts: 3                # 試行回数
      append_hostname: True           # イメージ名にホスト名を追加するか
```

**イメージファイルが TFTP サーバー上にない場合に使用します。**
イメージファイルを `destination` で指定した TFTP サーバ上のフォルダにコピーします。
`overwrite` は上書きの有無の指定、`copy_attempts` はコピーが失敗した場合に何回トライするか、`append_hostname` はデバイス毎にイメージをユニークに保存しておきたい場合に使います。

:::note
イメージファイルが TFTP サーバー上にある、またマウント経由でアクセスできる状況の場合は、このステージは不要です。
:::

### `copy_to_device` ステージ

```yaml:clean.yamlの抜粋
    copy_to_device:               # イメージをデバイスへコピー
      origin:
        hostname: pyats-tftp      # TFTPサーバ名
      destination:
        directory: 'harddisk:/'   # デバイス上のコピー先
      protocol: tftp              # コピーに使用するプロトコル    
      overwrite: True             # 上書きを許可するか
      verify_num_images: False    # イメージ数をチェックするか
      check_file_stability: True  # ファイルが安定しているかのチェック
      min_free_space_percent: 50  # 空きスペースの閾値
```

TFTPサーバからデバイスへイメージファイルをコピーします。重要なパラメータは `origin` と `destination` になり、送信元の TFTP サーバを指定、送信先のデバイス上の場所を指定します。

他には `protocol` は今回の場合は `tftp` としていますが、FTP/SCPなども使えます。
`check_file_stability` はファイルサイズが変動していないか(コピー中じゃないか)を定期的にサイズを確認してチェックします。`min_free_space_percent` はディスクスペースの空きスペースの閾値を指定します。50% としているので、harddisk: に 50% 以上の空きがない場合はファイルを削除して、サイズを50%以上確保しようとします。


### `change_boot_variable` ステージ

```yaml:clean.yamlの抜粋
    change_boot_variable:         # boot variable の設定
```

起動するイメージにて boot statment を変更して次回起動時に指定したイメージで起動する設定を行います。

### `write_erase` ステージ

```yaml:clean.yamlの抜粋
    write_erase:                  # コンフィグの削除
```

`write erase` コマンドで設定を初期化します。pyATS Clean ではデバイスを初期化するのが目的なため、一般的に設定の削除を行います。

### `reload` ステージ

```yaml:clean.yamlの抜粋
    reload:                       # デバイスのリロード
```

デバイスを再起動します。設定を初期化するため、新しいイメージで起動するために再起動を行います。

### `apply_configuration` ステージ

```yaml:clean.yamlの抜粋
    apply_configuration:          # 初期設定の追加
      configuration: |            # 初期設定のコンフィグを記述
        hostname asr1000
        enable password banana
        interface GigabitEthernet0
          ip address X.X.X.X 255.255.255.0
          no shut
        line console 0
          exec-timeout 0 0
          logging synchronous
        line vty 0 4
          password lab
      config_timeout: 30          # 設定時のタイムアウト値 
      config_stable_time: 120     # 設定後の待ち時間
```

`apply_configuration` は再起動後に管理インタフェース(Management Interface)を設定するために使用されます。上記のように、ホスト名、Mgmt Interface の設定などを行います。

:::note
pyATS Clean の apply_configuration では前述のように Mgmt Interface など管理系の設定のみを行うのが一般的ではありますが、pyATS Clean 後にある程度のコンフィグを持っておきたい場合などにはここに他の設定(OSPFやBGP等)を追加してももちろん OK です。
:::


### `verify_running_image` ステージ

```yaml:clean.yamlの抜粋
    verify_running_image:         # イメージの確認
```

`verify_running_image` では指定したイメージで起動していることを確認します。

### `order` 

```yaml:clean.yamlの抜粋
    order:                        # Clean ステージの実行順序
      - 'connect'
      - 'ping_server'
      - 'copy_to_linux'
      - 'copy_to_device'
      - 'change_boot_variable'
      - 'write_erase'
      - 'reload'
      - 'apply_configuration'
      - 'verify_running_image'
```

**`order` も Clean ステージではございません。** 非常に重要な項目となり、前述した Clean ステージの実行順序を指定します。そのため、上記までの記載の順番は関係なく、ここで記載された順番で実行されます。
**`order` は省略できない必須項目でもあります。また、Cleanステージを記載しつつ、`order` に入れなかった場合は実行されません。**

### その他の Clean ステージ

上記は ASR1K のクリーンにおける場合について紹介しましたが、機種やOSの違いによりクリーンアップの手順が異なっている場合があります。そのためにここでは紹介していない Clean ステージもあり、下記の Web ページから Clean ステージを見つけることができます。また各パラメータの詳細も確認できます。

https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/#/clean

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/830dacf1-98b2-c4dc-a950-c4743e28d04e.png"><img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/37457064-d021-93ea-7922-6880bdd77085.png">

# pyATS Clean の実行

実行方法は主に2通りになります。

### pyATS Job と一緒に実行

pyATS Job を実行する `pyats run job` コマンドに `--clean-file`、`--invoke-clean` というオプションを実行することで pyATS Clean が実行されデバイスが初期化された後に、pyATS Job が実行されます。

```shell
$ pyats run job job.py --testbed-file testbed.yaml --clean-file clean.yaml --invoke-clean
```

上記を実行後に `pyats logs view` コマンドを実行するとログビューワーが開きログが確認できます。

下記が実行画面になります。色枠にしているところがタブになり、`緑枠が pyATS Clean の実行結果` となり、`白枠が pyATS Job の実行結果`となります。

<img width="75%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/0758addd-9d7a-e474-69c2-3d25cdfdd8ea.png">

:::note
pyATS Clean を行うことで毎回デバイスが初期化されるため、pyATS Job の実行が **同じ状態のデバイス** に対して実行されるということになり、結果の一貫性が保つことができるようになります。
例えば、ラボ機器ですと、知らない間に誰かがイメージを入れ替えていた、設定が微妙に変更されていたというようなことが起こりえるかもしれませんが、pyATS Clean で毎回テスト環境をクリーニングすることで同じ状況でテストを走らせることが可能になります。
:::

### pyATS Clean 単体(スタンドアローン)で実行

次は pyATS Clean のみを実行する方法となり、`pyats clean` コマンドを使います。*この場合は `--invoke-clean` は必要ありません。*

```shell
$ pyats clean --testbed-file testbed.yaml --clean-file clean.yaml
```

上記を実行後に `pyats logs view` コマンドを実行すると `pyATS Job` と同じような形で pyATS Clean の事項結果を確認できます。但し、タブのところが一つしかなく pyATS Clean の実行結果のみとなります。

<img width="75%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/54026eeb-cda8-fdda-832d-dadb07fbbe66.png">

:::note
例えば、テスト環境をクリーニングアップしたいが、クリーニング後はマニュアルでの検証を行いたいという場合に主に使用されます。
:::

# pyATS Clean の便利な使い方

ここまでで `pyATS Clean` の使い方について説明してきましたが、こういう場合にも使えるよというユースケースを紹介しておきたいと思います。

## ライセンスモードを切り替えてリロードしたい

ラボ機材は手配できたが、あれ？設定したい設定が入らない。。というライセンスモードによる問題も pyATS Clean を使えばマニュアル作業を軽減できます! 

```yaml:clean.yaml
cleaners:
  DeviceClean:
    module: genie.libs.clean
    devices: [asr1000]

devices:
  asr1000:
    connect:

    apply_configuration:
      configuration: |
        license boot level network-advantage addon dna-advantage

    reload:

    order:
      - 'connect'
      - 'apply_configuration'
      - 'reload'
```

`clean.yaml` は上記のようになり、簡素なのがお分かりかと思います。
`connect`、`apply_configuration`、`reload` しか使っていません。また自動化したいシナリオに応じて、`order` で順序を変えて実行しています。

:::note
`order` のところの説明でお気づきの方も多いと思いますが、clean ステージは作業ステップ毎になっており、その組み合わせで色々なシナリオでのクリーンアップが可能になっております。必要でなければ、そのステージを持つ必要はなく、必要なものだけを使用し、また順番も必要に応じて変更可能です。
:::

## testbed.yaml の全ての機器に接続できるか確認したい

pyATS Clean を使ってデバイスへの接続性を確認する clean.yaml の例です。
この場合は、全てのデバイスに対して同じステージと、パラメータ（今回パラメータはありませんが)となる場合は、`devices` の代わりに `groups` でグルーピングして YAML 内も簡素化できます。

```yaml:clean.yaml
cleaners:
  DeviceClean:
    module: genie.libs.clean
    groups: [my_group]

groups:
  my_group:
    devices:
      - asr1000-1
      - asr1000-2
      - asr1000-3

    connect:

    order:
      - 'connect'
```

:::note warn
ステージ１つでも `order` は必要になりますので、ご注意ください。
:::

あくまで一例であり、同じ事をするなら実際には pyATS Shell から testbed.connect() する方が早いです。w
```
$ pyats shell --testbed-file testbed.yaml
>>> testbed.connect()
```

## 全ての機器へ同じ設定を投入したい

```yaml:clean.yaml
cleaners:
  DeviceClean:
    module: genie.libs.clean
    groups: [my_group]

groups:
  my_group:
    devices:
      - asr1000-1
      - asr1000-2
      - asr1000-3

    connect:

    apply_configuration:
      configuration: |
        ntp server 10.1.1.1
        no ip domain-lookup
        ip tftp source-interface GigabitEthernet1
        ip tftp block-size 8192

    ping_server:
      server: 10.1.1.1

    order:
      - 'connect'
      - 'apply_configuration'
      - 'ping_server'
```

NTP サーバや TFTP 関連の設定など、全デバイスで共通しているようなコンフィグを一括で設定したい場合にも pyATS Clean を使うことができます。念のため、NTPサーバへの接続性があるかを `ping_server` ステージを使って確認しています。

## 全ての機器の設定を削除したい

```yaml:clean.yaml
cleaners:
  DeviceClean:
    module: genie.libs.clean
    groups: [my_group]

groups:
  my_group:
    devices:
      - asr1000-1
      - asr1000-2
      - asr1000-3

    connect:

    write_erase:

    reload:

    order:
      - 'connect'
      - 'write_erase'
      - 'reload'
```

設定のみを指定したデバイスから削除したい場合には上記のように pyATS Clean を実行できます。`write_erase` 及び `reload` ステージを使って実現できます。

# pyATS 関連の問い合わせ

pyATS の問い合わせ先は下記のメールアドレスまたは Cisco Webex Teams Space(下記のリンクから参加) になります。

- メール: pyats-support-ext(at)cisco.com
- pyATS community : https://eurl.io/#r18UzrQVr

また、特定のコンポーネント(pyATS, Genie, Genie Parser, Genie Libs, Unicon)が把握できている場合は、GitHub の Issue を該当のレポジトリでオープンしてもらう形でも問題ありません。

https://github.com/CiscoTestAutomation

:::note
問い合わせは現状では英語のみとなっております。
:::

:::note
サポートはコミュニティでというのが前提ですがpyATSチームは積極的に直接サポートを行なっています。ただし、無料ツールとなっているため、SLA などは無いことにご注意ください。
:::

:::note
日本語のサポートは現時点では用意されていませんが、Twitter で呟いていただくと、私のアカウント @tahigash3 が反応するかもしれません。
:::


# まとめ

今回は pyATS Clean を使ったテスト環境の準備や簡単な作業を自動化することを紹介してみました。pyATS では設定の投入や機能試験などのテスト自体の自動化に話されることが多いですが、pyATS Clean のようにさりげなく、他の自動化ツールが持っていないユニークな機能も持っています。

またイメージしやすいように pyATS Clean が使えるケースも clean.yaml を使って紹介してみました。なんとか使うイメージが分かったり、pyATS Clean の使い方を理解する手助けができたなら幸いです。

pyATS には他にも色々な機能があるので、ぜひ興味がある方は試して使ってみてくださいね!

# 参考リンク
今回の記事 pyATS Clean に関連したリンク
- [pyATS Clean](https://pubhub.devnetcloud.com/media/genie-docs/docs/clean/index.html)
- [pyATS Clean Developer Guide](https://pubhub.devnetcloud.com/media/genie-docs/docs/clean/developer_guide/index.html)
- [pyATS Clean Stages Browser](https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/#/clean)

下記は pyATS の参考になるリンク
- [pyATS Document](https://developer.cisco.com/docs/pyats/api/)
- [Genie Document](https://developer.cisco.com/docs/genie-docs/)
  - [Genie CLI - Genie Run](https://pubhub.devnetcloud.com/media/genie-docs/docs/cli/genie_run.html)
  - [Genie API Browser](https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/#/)
  - [Genie Useful Libraries](https://pubhub.devnetcloud.com/media/genie-docs/docs/userguide/utils/index.html#)
    - [Dq](https://pubhub.devnetcloud.com/media/genie-docs/docs/userguide/utils/index.html#dq)
  - [Genie Parser GitHub](https://github.com/CiscoTestAutomation/genieparser)
  - [Genie Libs GitHub](https://github.com/CiscoTestAutomation/genielibs)
- [XPRESSO Document](https://developer.cisco.com/docs/xpresso/)
    - [XPRESSO GitHub](https://github.com/CiscoTestAutomation/xpresso)
- [pyATS community on Webex teams](https://eurl.io/#r18UzrQVr)

# 免責事項

本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。