PyATSはじめの一歩（ファイル作成、機器接続、コマンド実行まで）

## ■はじめに
PyATSをつかってみたい！でもぐぐっても日本語の記事少なすぎる＆インストールまでしか書いてない記事ばっかり！…ということでスタートするまでに時間がかかったので、備忘録やだれかの手助けになればと思い投稿しました。

## ■対象読者
概要は他の記事で読んだから、PyATSを実際に試してみたい！という方

- あるといいもの
Pythonの基本的な記述知識（処理で何をやっているか,値の受け渡しなど想像がつくので有利です。）

## ■動作要件
⚠Windowsはサポートしていません⚠ 　UbuntuとかCentOSでやってね。
> 対応OS：Linux (tested with CentOS, RHEL, Ubuntu, Alpine),Mac OSX (10.13+)

## ■検証構成
![kensyoukousei.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533083/38bd4de5-bbe5-bebc-062a-2dddac7f726e.png)
PCとCatalystが1対1でつながったシンプルな構成です。
前提として、PCからCatalystにSSH接続が確認済みであることです。

## ■インストール方法
[インストール方法](https://pubhub.devnetcloud.com/media/pyats/docs/getting_started/index.html#installation
)
` pip install pyats[full] `
`[full]`以外に、必要なものだけインストールする方法がありますが…
よくわからない場合は`[full]`でインストールしましょう。10分ぐらいかかるので気長に待ちます。

## ■必要なもの（ファイル）ってなに？
①【準必須】テスト対象のIPやログイン情報を書く.yamlファイル 
 > 例）testbed.yml 任意でOK

②【必須】試験内容を記述する.pyファイル 
>例) test.py 任意でOK

上記の①②だけでもスタートできます。
①がなぜ準必須かというと、直接②の実行するファイルに書いてもOKなのです。ですが、①があったほうが情報整理しやすく、ログイン情報を隔離しておくため準必須としています。

また、pyatsインストール後に`pyats create project`コマンドを使うと②のテンプレートに加えて
③【任意】Jobファイル も自動生成してくれます。
<details><summary>②のテンプレート</summary><div>

    '''
    access_pyats.py

    '''
    # see https://pubhub.devnetcloud.com/media/pyats/docs/aetest/index.html
    # for documentation on pyATS test scripts

    # optional author information
    # (update below with your contact information if needed)
    __author__ = 'Cisco Systems Inc.'
    __copyright__ = 'Copyright (c) 2019, Cisco Systems Inc.'
    __contact__ = ['pyats-support-ext@cisco.com']
    __credits__ = ['list', 'of', 'credit']
    __version__ = 1.0

    import logging

    from pyats import aetest

    # create a logger for this module
    logger = logging.getLogger(__name__)

    class CommonSetup(aetest.CommonSetup):

        @aetest.subsection
        def connect(self, testbed):
            '''
            establishes connection to all your testbed devices.
            '''
            # make sure testbed is provided
            assert testbed, 'Testbed is not provided!'

            # connect to all testbed devices
            testbed.connect()


    class show_version(aetest.Testcase):
        '''show_version

        < docstring description of this testcase >

        '''

        # testcase groups (uncomment to use)
        # groups = []

        @aetest.setup
        def setup(self):
            pass

        # you may have N tests within each testcase
        # as long as each bears a unique method name
        # this is just an example
        @aetest.test
        def test(self):
            pass

        @aetest.cleanup
        def cleanup(self):
            pass
        


    class CommonCleanup(aetest.CommonCleanup):
        '''CommonCleanup Section

        < common cleanup docstring >

        '''

        # uncomment to add new subsections
        # @aetest.subsection
        # def subsection_cleanup_one(self):
        #     pass

    if __name__ == '__main__':
        # for stand-alone execution
        import argparse
        from pyats import topology

        parser = argparse.ArgumentParser(description = "standalone parser")
        parser.add_argument('--testbed', dest = 'testbed',
                            help = 'testbed YAML file',
                            type = topology.loader.load,
                            default = None)

        # do the parsing
        args = parser.parse_known_args()[0]

        aetest.main(testbed = args.testbed)



</div></details>

<details><summary>③Jobファイル</summary><div>

    '''
    access_pyats_job.py

    '''
    # see https://pubhub.devnetcloud.com/media/pyats/docs/easypy/jobfile.html
    # for how job files work

    # optional author information
    # (update below with your contact information if needed)
    __author__ = 'Cisco Systems Inc.'
    __copyright__ = 'Copyright (c) 2019, Cisco Systems Inc.'
    __contact__ = ['pyats-support-ext@cisco.com']
    __credits__ = ['list', 'of', 'credit']
    __version__ = 1.0

    import os
    from pyats.easypy import run

    # compute the script path from this location
    SCRIPT_PATH = os.path.dirname(__file__)

    def main(runtime):
        '''job file entrypoint'''
        
        # run script
        run(testscript= os.path.join(SCRIPT_PATH, 
                                    'access_pyats.py'),
            runtime = runtime)

</div></details>
①、②のテンプレート、③があると、画像のように、失敗箇所やテストがうまくいっているかをいい感じにビジュアライズしてくれるようになります。
<details><summary>実行例</summary><div>

    user@user:~/workspace/pyats/access_pyats$ pyats run job access_pyats_job.py  
    /usr/lib/python3/dist-packages/paramiko/transport.py:236: CryptographyDeprecationWarning: Blowfish has been deprecated
      "class": algorithms.Blowfish,
    2023-05-05T18:03:54: %EASYPY-INFO: Starting job run: access_pyats_job
    2023-05-05T18:03:54: %EASYPY-INFO: Runinfo directory: /home/user/.pyats/runinfo/access_pyats_job.2023May05_18:03:53.226951
    2023-05-05T18:03:54: %EASYPY-INFO: --------------------------------------------------------------------------------
    2023-05-05T18:03:55: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:55: %EASYPY-INFO: |                              Clean Information                               |
    2023-05-05T18:03:55: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:55: %EASYPY-INFO: {'bringup': {}, 'cleaners': {}, 'devices': {}}

    2023-05-05T18:03:55: %ATS-INFO: Checking all devices are up and ready is disabled, '--check-all-devices-up' must be set to True in case of pyats runs or '-check_all_devices_up' set to True in case of legacy easypy runs
    2023-05-05T18:03:55: %EASYPY-INFO: Starting task execution: Task-1
    2023-05-05T18:03:55: %EASYPY-INFO:     test harness = pyats.aetest
    2023-05-05T18:03:55: %EASYPY-INFO:     testscript   = /home/user/workspace/pyats/access_pyats/access_pyats.py
    2023-05-05T18:03:55: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:55: %AETEST-INFO: |                            Starting common setup                             |
    2023-05-05T18:03:55: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:55: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:55: %AETEST-INFO: |                         Starting subsection connect                          |
    2023-05-05T18:03:55: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:55: %AETEST-WARNING: Caught an assertion failure while executing subsection connect:
    2023-05-05T18:03:55: %AETEST-WARNING: Traceback (most recent call last):
    2023-05-05T18:03:55: %AETEST-WARNING:   File "/home/user/workspace/pyats/access_pyats/access_pyats.py", line 31, in connect
    2023-05-05T18:03:55: %AETEST-WARNING:     assert testbed, 'Testbed is not provided!'
    2023-05-05T18:03:55: %AETEST-WARNING: AssertionError: Testbed is not provided!
    2023-05-05T18:03:55: %AETEST-INFO: The result of subsection connect is => FAILED
    2023-05-05T18:03:55: %AETEST-INFO: The result of common setup is => FAILED
    2023-05-05T18:03:55: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:55: %AETEST-INFO: |                        Starting testcase show_version                        |
    2023-05-05T18:03:55: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:55: %AETEST-INFO: Blocking show_version because common_setup did not pass.
    2023-05-05T18:03:55: %AETEST-INFO: The result of testcase show_version is => BLOCKED
    2023-05-05T18:03:55: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:55: %AETEST-INFO: |                           Starting common cleanup                            |
    2023-05-05T18:03:55: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:55: %AETEST-INFO: The result of common cleanup is => PASSED
    2023-05-05T18:03:55: %CONTRIB-INFO: WebEx Token not given as argument or in config. No WebEx notification will be sent
    2023-05-05T18:03:55: %EASYPY-INFO: --------------------------------------------------------------------------------
    2023-05-05T18:03:55: %EASYPY-INFO: Job finished. Wrapping up...
    2023-05-05T18:03:56: %EASYPY-INFO: Creating archive file: /home/user/.pyats/archive/23-05/access_pyats_job.2023May05_18:03:53.226951.zip
    2023-05-05T18:03:56: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:56: %EASYPY-INFO: |                                Easypy Report                                 |
    2023-05-05T18:03:56: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:56: %EASYPY-INFO: pyATS Instance   : /usr
    2023-05-05T18:03:56: %EASYPY-INFO: Python Version   : cpython-3.10.6 (64bit)
    2023-05-05T18:03:56: %EASYPY-INFO: CLI Arguments    : /usr/local/bin/pyats run job access_pyats_job.py
    2023-05-05T18:03:56: %EASYPY-INFO: User             : user
    2023-05-05T18:03:56: %EASYPY-INFO: Host Server      : user
    2023-05-05T18:03:56: %EASYPY-INFO: Host OS Version  : Ubuntu 22.04 jammy (x86_64)
    2023-05-05T18:03:56: %EASYPY-INFO: 
    2023-05-05T18:03:56: %EASYPY-INFO: Job Information
    2023-05-05T18:03:56: %EASYPY-INFO:     Name         : access_pyats_job
    2023-05-05T18:03:56: %EASYPY-INFO:     Start time   : 2023-05-05 18:03:55.794935+09:00
    2023-05-05T18:03:56: %EASYPY-INFO:     Stop time    : 2023-05-05 18:03:55.874762+09:00
    2023-05-05T18:03:56: %EASYPY-INFO:     Elapsed time : 0.079827
    2023-05-05T18:03:56: %EASYPY-INFO:     Archive      : /home/user/.pyats/archive/23-05/access_pyats_job.2023May05_18:03:53.226951.zip
    2023-05-05T18:03:56: %EASYPY-INFO: 
    2023-05-05T18:03:56: %EASYPY-INFO: Total Tasks    : 1 
    2023-05-05T18:03:56: %EASYPY-INFO: 
    2023-05-05T18:03:56: %EASYPY-INFO: Overall Stats
    2023-05-05T18:03:56: %EASYPY-INFO:     Passed     : 1
    2023-05-05T18:03:56: %EASYPY-INFO:     Passx      : 0
    2023-05-05T18:03:56: %EASYPY-INFO:     Failed     : 1
    2023-05-05T18:03:56: %EASYPY-INFO:     Aborted    : 0
    2023-05-05T18:03:56: %EASYPY-INFO:     Blocked    : 1
    2023-05-05T18:03:56: %EASYPY-INFO:     Skipped    : 0
    2023-05-05T18:03:56: %EASYPY-INFO:     Errored    : 0
    2023-05-05T18:03:56: %EASYPY-INFO: 
    2023-05-05T18:03:56: %EASYPY-INFO:     TOTAL      : 3
    2023-05-05T18:03:56: %EASYPY-INFO: 
    2023-05-05T18:03:56: %EASYPY-INFO: Success Rate   : 33.33 %
    2023-05-05T18:03:56: %EASYPY-INFO: 
    2023-05-05T18:03:56: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:56: %EASYPY-INFO: |                             Task Result Summary                              |
    2023-05-05T18:03:56: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:56: %EASYPY-INFO: Task-1: access_pyats.common_setup                                         FAILED
    2023-05-05T18:03:56: %EASYPY-INFO: Task-1: access_pyats.show_version                                        BLOCKED
    2023-05-05T18:03:56: %EASYPY-INFO: Task-1: access_pyats.common_cleanup                                       PASSED
    2023-05-05T18:03:56: %EASYPY-INFO: 
    2023-05-05T18:03:56: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:56: %EASYPY-INFO: |                             Task Result Details                              |
    2023-05-05T18:03:56: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:03:56: %EASYPY-INFO: Task-1: access_pyats
    2023-05-05T18:03:56: %EASYPY-INFO: |-- common_setup                                                          FAILED
    2023-05-05T18:03:56: %EASYPY-INFO: |   `-- connect                                                           FAILED
    2023-05-05T18:03:56: %EASYPY-INFO: |-- show_version                                                         BLOCKED
    2023-05-05T18:03:56: %EASYPY-INFO: `-- common_cleanup                                                        PASSED
    2023-05-05T18:03:56: %EASYPY-INFO: Sending report email...
    2023-05-05T18:03:56: %EASYPY-INFO: Missing SMTP server configuration, or failed to reach/authenticate/send mail. Result notification email failed to send.
    2023-05-05T18:03:56: %EASYPY-INFO: Done!

    Pro Tip
    -------
      Try the following command to view your logs:
          pyats logs view

    user@user:~/workspace/pyats/access_pyats$ pyats run job access_pyats_job.py  -t testbed.yml 
    /usr/lib/python3/dist-packages/paramiko/transport.py:236: CryptographyDeprecationWarning: Blowfish has been deprecated
      "class": algorithms.Blowfish,
    2023-05-05T18:04:55: %EASYPY-INFO: Starting job run: access_pyats_job
    2023-05-05T18:04:55: %EASYPY-INFO: Runinfo directory: /home/user/.pyats/runinfo/access_pyats_job.2023May05_18:04:54.185732
    2023-05-05T18:04:55: %EASYPY-INFO: --------------------------------------------------------------------------------
    2023-05-05T18:04:56: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:04:56: %EASYPY-INFO: |                              Clean Information                               |
    2023-05-05T18:04:56: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:04:56: %EASYPY-INFO: {'bringup': {}, 'cleaners': {}, 'devices': {}}

    2023-05-05T18:04:56: %ATS-INFO: Checking all devices are up and ready is disabled, '--check-all-devices-up' must be set to True in case of pyats runs or '-check_all_devices_up' set to True in case of legacy easypy runs
    2023-05-05T18:04:56: %EASYPY-INFO: Starting task execution: Task-1
    2023-05-05T18:04:56: %EASYPY-INFO:     test harness = pyats.aetest
    2023-05-05T18:04:56: %EASYPY-INFO:     testscript   = /home/user/workspace/pyats/access_pyats/access_pyats.py
    2023-05-05T18:04:56: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:04:56: %AETEST-INFO: |                            Starting common setup                             |
    2023-05-05T18:04:56: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:04:56: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:04:56: %AETEST-INFO: |                         Starting subsection connect                          |
    2023-05-05T18:04:56: %AETEST-INFO: +------------------------------------------------------------------------------+

    2023-05-05 18:04:56,877: %UNICON-INFO: +++ Test-Switch logfile /home/user/.pyats/runinfo/access_pyats_job.2023May05_18:04:54.185732/Test-Switch-cli-1683277496.log +++

    2023-05-05 18:04:56,951: %UNICON-INFO: +++ Unicon plugin ios (unicon.plugins.ios) +++
    (admin@192.168.1.1) Password: 

    2023-05-05 18:04:58,382: %UNICON-INFO: +++ connection to spawn: ssh -l admin 192.168.1.1, id: 140542433662896 +++

    2023-05-05 18:04:58,390: %UNICON-INFO: connection to Test-Switch


    Test-Switch>

    2023-05-05 18:04:58,456: %UNICON-INFO: +++ initializing handle +++
    enable
    Password: 
    Test-Switch#

    2023-05-05 18:04:58,547: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'term length 0' +++
    term length 0
    Test-Switch#

    2023-05-05 18:04:58,716: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'term width 0' +++
    term width 0
    Test-Switch#

    2023-05-05 18:04:58,876: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'show version' +++
    show version
    Cisco IOS Software, C3560C Software (C3560c405ex-UNIVERSALK9-M), Version 15.0(2)SE5, RELEASE SOFTWARE (fc1)
    Technical Support: http://www.cisco.com/techsupport
    Copyright (c) 1986-2013 by Cisco Systems, Inc.
    Compiled Fri 25-Oct-13 14:53 by prod_rel_team

    ROM: Bootstrap program is C3560C boot loader
    BOOTLDR: C3560C Boot Loader (C3560C-HBOOT-M) Version 12.2(55r)EX11, RELEASE SOFTWARE (fc1)

    Test-Switch uptime is 1 hour, 14 minutes
    System returned to ROM by power-on
    System restarted at 10:27:20 JST Wed Mar 30 2011
    System image file is "flash:/c3560c405ex-universalk9-mz.150-2.SE5/c3560c405ex-universalk9-mz.150-2.SE5.bin"


    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: ipbase
    License Type: Permanent
    Next reload license Level: ipbase

    cisco WS-C3560CG-8PC-S (PowerPC) processor (revision G0) with 131072K bytes of memory.
    Processor board ID FOC1913Y010
    Last reset from power-on
    2 Virtual Ethernet interfaces
    10 Gigabit Ethernet interfaces
    The password-recovery mechanism is enabled.

    512K bytes of flash-simulated non-volatile configuration memory.
    Base ethernet MAC Address       : 88:90:8D:05:E1:00
    Motherboard assembly number     : 73-13272-08
    Power supply part number        : 341-0407-01
    Motherboard serial number       : FOC19113Q1E
    Power supply serial number      : DCB190921U4
    Model revision number           : G0
    Motherboard revision number     : A0
    Model number                    : WS-C3560CG-8PC-S
    System serial number            : FOC1913Y010
    Top Assembly Part Number        : 800-33676-03
    Top Assembly Revision Number    : E0
    Version ID                      : V03
    CLEI Code Number                : CMMD900ARC
    Hardware Board Revision Number  : 0x00


    Switch Ports Model              SW Version            SW Image                 
    ------ ----- -----              ----------            ----------               
    *    1 10    WS-C3560CG-8PC-S   15.0(2)SE5            C3560c405ex-UNIVERSALK9-M


    Configuration register is 0xF

    Test-Switch#

    2023-05-05 18:04:59,051: %UNICON-INFO: +++ Test-Switch with via 'console': configure +++
    config term
    Enter configuration commands, one per line.  End with CNTL/Z.
    Test-Switch(config)#no logging console
    Test-Switch(config)#line console 0
    Test-Switch(config-line)#exec-timeout 0
    Test-Switch(config-line)#line vty 0 4
    Test-Switch(config-line)#exec-timeout 0
    Test-Switch(config-line)#end
    Test-Switch#
    2023-05-05T18:04:59: %LOG-INFO: >>>> Begin child log /home/user/.pyats/runinfo/access_pyats_job.2023May05_18:04:54.185732/TaskLog.Task-1:pid-33975

    2023-05-05 18:04:59,861: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'show version' +++
    show version
    Cisco IOS Software, C3560C Software (C3560c405ex-UNIVERSALK9-M), Version 15.0(2)SE5, RELEASE SOFTWARE (fc1)
    Technical Support: http://www.cisco.com/techsupport
    Copyright (c) 1986-2013 by Cisco Systems, Inc.
    Compiled Fri 25-Oct-13 14:53 by prod_rel_team

    ROM: Bootstrap program is C3560C boot loader
    BOOTLDR: C3560C Boot Loader (C3560C-HBOOT-M) Version 12.2(55r)EX11, RELEASE SOFTWARE (fc1)

    Test-Switch uptime is 1 hour, 14 minutes
    System returned to ROM by power-on
    System restarted at 10:27:20 JST Wed Mar 30 2011
    System image file is "flash:/c3560c405ex-universalk9-mz.150-2.SE5/c3560c405ex-universalk9-mz.150-2.SE5.bin"


    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: ipbase
    License Type: Permanent
    Next reload license Level: ipbase

    cisco WS-C3560CG-8PC-S (PowerPC) processor (revision G0) with 131072K bytes of memory.
    Processor board ID FOC1913Y010
    Last reset from power-on
    2 Virtual Ethernet interfaces
    10 Gigabit Ethernet interfaces
    The password-recovery mechanism is enabled.

    512K bytes of flash-simulated non-volatile configuration memory.
    Base ethernet MAC Address       : 88:90:8D:05:E1:00
    Motherboard assembly number     : 73-13272-08
    Power supply part number        : 341-0407-01
    Motherboard serial number       : FOC19113Q1E
    Power supply serial number      : DCB190921U4
    Model revision number           : G0
    Motherboard revision number     : A0
    Model number                    : WS-C3560CG-8PC-S
    System serial number            : FOC1913Y010
    Top Assembly Part Number        : 800-33676-03
    Top Assembly Revision Number    : E0
    Version ID                      : V03
    CLEI Code Number                : CMMD900ARC
    Hardware Board Revision Number  : 0x00


    Switch Ports Model              SW Version            SW Image                 
    ------ ----- -----              ----------            ----------               
    *    1 10    WS-C3560CG-8PC-S   15.0(2)SE5            C3560c405ex-UNIVERSALK9-M


    Configuration register is 0xF

    Test-Switch#
    2023-05-05T18:05:00: %LOG-INFO: <<<< End child log /home/user/.pyats/runinfo/access_pyats_job.2023May05_18:04:54.185732/TaskLog.Task-1:pid-33975
    2023-05-05T18:05:00: %AETEST-INFO: The result of subsection connect is => PASSED
    2023-05-05T18:05:00: %AETEST-INFO: The result of common setup is => PASSED
    2023-05-05T18:05:00: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:00: %AETEST-INFO: |                        Starting testcase show_version                        |
    2023-05-05T18:05:00: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:00: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:00: %AETEST-INFO: |                            Starting section setup                            |
    2023-05-05T18:05:00: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:00: %AETEST-INFO: The result of section setup is => PASSED
    2023-05-05T18:05:00: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:00: %AETEST-INFO: |                            Starting section test                             |
    2023-05-05T18:05:00: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:00: %AETEST-INFO: The result of section test is => PASSED
    2023-05-05T18:05:00: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:00: %AETEST-INFO: |                           Starting section cleanup                           |
    2023-05-05T18:05:00: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:00: %AETEST-INFO: The result of section cleanup is => PASSED
    2023-05-05T18:05:00: %AETEST-INFO: The result of testcase show_version is => PASSED
    2023-05-05T18:05:00: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:00: %AETEST-INFO: |                           Starting common cleanup                            |
    2023-05-05T18:05:00: %AETEST-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:00: %AETEST-INFO: The result of common cleanup is => PASSED
    2023-05-05T18:05:00: %CONTRIB-INFO: WebEx Token not given as argument or in config. No WebEx notification will be sent
    2023-05-05T18:05:00: %EASYPY-INFO: --------------------------------------------------------------------------------
    2023-05-05T18:05:00: %EASYPY-INFO: Job finished. Wrapping up...
    2023-05-05T18:05:01: %EASYPY-INFO: Creating archive file: /home/user/.pyats/archive/23-05/access_pyats_job.2023May05_18:04:54.185732.zip
    2023-05-05T18:05:01: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:01: %EASYPY-INFO: |                                Easypy Report                                 |
    2023-05-05T18:05:01: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:01: %EASYPY-INFO: pyATS Instance   : /usr
    2023-05-05T18:05:01: %EASYPY-INFO: Python Version   : cpython-3.10.6 (64bit)
    2023-05-05T18:05:01: %EASYPY-INFO: CLI Arguments    : /usr/local/bin/pyats run job access_pyats_job.py -t testbed.yml
    2023-05-05T18:05:01: %EASYPY-INFO: User             : user
    2023-05-05T18:05:01: %EASYPY-INFO: Host Server      : user
    2023-05-05T18:05:01: %EASYPY-INFO: Host OS Version  : Ubuntu 22.04 jammy (x86_64)
    2023-05-05T18:05:01: %EASYPY-INFO: 
    2023-05-05T18:05:01: %EASYPY-INFO: Job Information
    2023-05-05T18:05:01: %EASYPY-INFO:     Name         : access_pyats_job
    2023-05-05T18:05:01: %EASYPY-INFO:     Start time   : 2023-05-05 18:04:56.816770+09:00
    2023-05-05T18:05:01: %EASYPY-INFO:     Stop time    : 2023-05-05 18:05:00.210687+09:00
    2023-05-05T18:05:01: %EASYPY-INFO:     Elapsed time : 3.393917
    2023-05-05T18:05:01: %EASYPY-INFO:     Archive      : /home/user/.pyats/archive/23-05/access_pyats_job.2023May05_18:04:54.185732.zip
    2023-05-05T18:05:01: %EASYPY-INFO: 
    2023-05-05T18:05:01: %EASYPY-INFO: Total Tasks    : 1 
    2023-05-05T18:05:01: %EASYPY-INFO: 
    2023-05-05T18:05:01: %EASYPY-INFO: Overall Stats
    2023-05-05T18:05:01: %EASYPY-INFO:     Passed     : 3
    2023-05-05T18:05:01: %EASYPY-INFO:     Passx      : 0
    2023-05-05T18:05:01: %EASYPY-INFO:     Failed     : 0
    2023-05-05T18:05:01: %EASYPY-INFO:     Aborted    : 0
    2023-05-05T18:05:01: %EASYPY-INFO:     Blocked    : 0
    2023-05-05T18:05:01: %EASYPY-INFO:     Skipped    : 0
    2023-05-05T18:05:01: %EASYPY-INFO:     Errored    : 0
    2023-05-05T18:05:01: %EASYPY-INFO: 
    2023-05-05T18:05:01: %EASYPY-INFO:     TOTAL      : 3
    2023-05-05T18:05:01: %EASYPY-INFO: 
    2023-05-05T18:05:01: %EASYPY-INFO: Success Rate   : 100.00 %
    2023-05-05T18:05:01: %EASYPY-INFO: 
    2023-05-05T18:05:01: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:01: %EASYPY-INFO: |                             Task Result Summary                              |
    2023-05-05T18:05:01: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:01: %EASYPY-INFO: Task-1: access_pyats.common_setup                                         PASSED
    2023-05-05T18:05:01: %EASYPY-INFO: Task-1: access_pyats.show_version                                         PASSED
    2023-05-05T18:05:01: %EASYPY-INFO: Task-1: access_pyats.common_cleanup                                       PASSED
    2023-05-05T18:05:01: %EASYPY-INFO: 
    2023-05-05T18:05:01: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:01: %EASYPY-INFO: |                             Task Result Details                              |
    2023-05-05T18:05:01: %EASYPY-INFO: +------------------------------------------------------------------------------+
    2023-05-05T18:05:01: %EASYPY-INFO: Task-1: access_pyats
    2023-05-05T18:05:01: %EASYPY-INFO: |-- common_setup                                                          PASSED
    2023-05-05T18:05:01: %EASYPY-INFO: |   `-- connect                                                           PASSED
    2023-05-05T18:05:01: %EASYPY-INFO: |-- show_version                                                          PASSED
    2023-05-05T18:05:01: %EASYPY-INFO: |   |-- setup                                                             PASSED
    2023-05-05T18:05:01: %EASYPY-INFO: |   |-- test                                                              PASSED
    2023-05-05T18:05:01: %EASYPY-INFO: |   `-- cleanup                                                           PASSED
    2023-05-05T18:05:01: %EASYPY-INFO: `-- common_cleanup                                                        PASSED
    2023-05-05T18:05:01: %EASYPY-INFO: Sending report email...
    2023-05-05T18:05:01: %EASYPY-INFO: Missing SMTP server configuration, or failed to reach/authenticate/send mail. Result notification email failed to send.
    2023-05-05T18:05:01: %EASYPY-INFO: Done!

    Pro Tip
    -------
      Try the following command to view your logs:
          pyats logs view


</div></details>

> `pyats create project`コマンドで生成した②のテンプレートはちょっと勉強中。
だれか書き方教えてください。。




## ■①の書き方
YAML形式と呼ばれる記述方法になります。YAMLはインデントに非常にうるさいのでVscodeの拡張機能とかでアシストしてもらいましょう

以下のコードは最小減の内容です（多分）。ググると日本語記事もいくつかありますが
微妙に記事ごとに違ったりして初学者は混乱してしまいます。

    ---
    testbed:
        name: IOS_testbed

    devices:
        Test-Switch:
            os: 'ios'
            type: 'ios'
            credentials:
                default:
                    username: admin
                    password: admin
                enable:
                    password: admin
            connections:
                console:
                    protocol: ssh
                    ip: 192.168.1.1

`testbed`と`devices`の２つの括りがありますね。
`testbed`では`name`に任意の名前を入れています。出力結果のどこにでも使われてないっぽいからなんでもいいです。多分。


`devices`では対象機器のos種別やログイン情報、IPアドレス、接続プロトコルが書いてありますね

公式を読んでみます。[Deviceオブジェクト](https://pubhub.devnetcloud.com/media/pyats/docs/topology/concept.html#device-objects)
`os`や`type`,`credentials`などの指定できる属性はこの通りです。全部使ったことないからわからないのがまだあります。

ひとつ前の`testbed`のほうも観てみましょう [Testbedオブジェクト](https://pubhub.devnetcloud.com/media/pyats/docs/topology/concept.html#testbed-object
)
あれ、こっちにも`credentials`がありますね。なんでかなと思ったんですが、多分複数台機器があるとき用に一括で定義できるように…かな？要検証

ほかにも
[インターフェースオブジェクト](https://pubhub.devnetcloud.com/media/pyats/docs/topology/concept.html#interface-objects
)
[リンクオブジェクト](https://pubhub.devnetcloud.com/media/pyats/docs/topology/concept.html#link-objects)
があります。リンクは機器同士どこがつながってるとか書けるらしい。要検証

コードの説明に戻ります。

    ---
    testbed:
        name: IOS_testbed

    devices:
        Test-Switch:　　　←ココ
            os: 'ios'
            ...


矢印の箇所ですが、**テスト対象のホスト名にしてください（重要）**。
わたしは適当に`catalyst_1`にしていたのですが実行すると
`Failed while bringing device to "enable" state pyats`
とenableするところで詰まってエラーがでました。
> 正確に言うと、見かけ上はenableできてて#マークでてくるが、コマンド入れるところでフリーズしてるように見える。


    devices:
        Test-Switch:
            os: 'ios'
            type: 'ios'
            credentials:
                default:　←ココ
                    username: admin
                    password: admin
                enable:　←ココ
                    password: admin
            connections:　
                console:　←ココ
                    protocol: ssh
                    ip: 192.168.1.1


`default`とか`enable`のところ、見よう見まねで書いたのだがなんでこれで行けるのかよくわかってないです。公式にも指定がない当たり、ただの辞書キーの一つに過ぎないか、あまり意識してない？要検証



以下は公式の例。testbedファイルを使わずに普通にPythonを書くように記述する場合の方法
`os`,`connections`,`protocol`,`ip`は引数名として受け取ってるっぽいから重要そう。

    # creating a device with connection parameters
    device_b = Device('deviceThatCanBeConnected', 
                      os='iosxe',
                      connections={
                          'mgmt': {
                              'protocol': 'telnet',
                              'ip': '1.1.1.1'
                         },
                      })

## ■②の書き方
    from genie.testbed import load

    testbed = load("testbed.yml")
    testbed.devices
    cat = testbed.devices["Test-Switch"]

    cat.connect()
    cat.execute("ter len 0")
    cat.execute("show version")
    cat.configure("""
        interface GigabitEthernet0/3
        shutdown
    """)
    cat.execute("wr")
   
１行目`from genie.testbed import load`
多分、testbedを読み込む際はloadモジュールが必要なためこれが必要
`from pyats.topology import Testbed, Device…`のように書いてある記事もあるが、
これは前述の公式の例のようにtestbed.yml1ファイルを使わずに直書きする場合のものだと思う。

2行目 testbedファイルをロードします。
4行目 `.devices`で取り出します
5行目 さらに機器ホスト名を指定して情報を取り出しインスタント化します
7行目 `インスタント名.connect()`で接続します。
ログイン情報が正しければ正常にプロンプトが帰ってきて処理が進みます。
8行目 `.execute`でようやくコマンド入力ができます。ここでは`ter len 0`で出力制限を解除して
 > ter len 0 なしでも自動で設定してくれるようです

9行目で`show version`をしています。
10行目 `.configure`でいきなり設定を入れていますね。決して`.execute('conf t')`のような設定モードに移動する手順を踏む必要なんかありません。
最後に`wr`(設定を保存するコマンド)をいれて終わりです。処理が終わったら自動でログアウトされます。

実行は`python3 main.py`で動きます。


## ■実行結果はこんな感じ（一部抜粋）
    user@user:~/workspace/pyats/access_pyats$ python3 main.py 
    2023-05-05 17:02:18,817: %UNICON-INFO: +++ Test-Switch logfile /tmp/Test-Switch-cli-20230505T170218816.log +++
    2023-05-05 17:02:18,817: %UNICON-INFO: +++ Unicon plugin ios (unicon.plugins.ios) +++
    (admin@192.168.1.1) Password: 
    2023-05-05 17:02:20,219: %UNICON-INFO: +++ connection to spawn: ssh -l admin 192.168.1.1, id: 140110085111968 +++
    2023-05-05 17:02:20,220: %UNICON-INFO: connection to Test-Switch

    Test-Switch>　##ログイン成功

    2023-05-05 17:02:21,513: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'ter len 0' +++
    ter len 0
    Test-Switch#  ##enableモードに昇格

    2023-05-05 17:02:21,677: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'show version' +++
    show version　##show versionコマンド実行
    Cisco IOS Software, C3560C Software (C3560c405ex-UNIVERSALK9-M), Version 15.0(2)SE5, RELEASE SOFTWARE (fc1)
    Technical Support: http://www.cisco.com/techsupport
    Copyright (c) 1986-2013 by Cisco Systems, Inc.
    Compiled Fri 25-Oct-13 14:53 by prod_rel_team

    2023-05-05 17:02:21,922: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'show running-config' +++
    show running-config  ##show runコマンド実行
    Building configuration...

    Current configuration : 3074 bytes
    !
    ! Last configuration change at 10:39:18 JST Wed Mar 30 2011 by admin
    ! NVRAM config last updated at 10:28:54 JST Wed Mar 30 2011
    !

    << 省略 >> 

    2023-05-05 17:02:22,491: %UNICON-INFO: +++ Test-Switch with via 'console': configure +++
    config term
    Enter configuration commands, one per line.  End with CNTL/Z.
    Test-Switch(config)#
    Test-Switch(config)#    interface GigabitEthernet0/3
    Test-Switch(config-if)#    shutdown
    Test-Switch(config-if)#end
    Test-Switch#

    2023-05-05 17:02:22,975: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'wr' +++
    wr
    Building configuration...
    [OK]
    Test-Switch#



<details><summary>全部見たい方はこちら</summary><div>

    user@user:~/workspace/pyats/access_pyats$ python3 main.py 

    2023-05-05 17:02:18,817: %UNICON-INFO: +++ Test-Switch logfile /tmp/Test-Switch-cli-20230505T170218816.log +++

    2023-05-05 17:02:18,817: %UNICON-INFO: +++ Unicon plugin ios (unicon.plugins.ios) +++
    (admin@192.168.1.1) Password: 

    2023-05-05 17:02:20,219: %UNICON-INFO: +++ connection to spawn: ssh -l admin 192.168.1.1, id: 140110085111968 +++

    2023-05-05 17:02:20,220: %UNICON-INFO: connection to Test-Switch


    Test-Switch>

    2023-05-05 17:02:20,300: %UNICON-INFO: +++ initializing handle +++
    enable
    Password: 
    Test-Switch#

    2023-05-05 17:02:20,412: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'term length 0' +++
    term length 0
    Test-Switch#

    2023-05-05 17:02:20,579: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'term width 0' +++
    term width 0
    Test-Switch#

    2023-05-05 17:02:20,741: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'show version' +++
    show version
    Cisco IOS Software, C3560C Software (C3560c405ex-UNIVERSALK9-M), Version 15.0(2)SE5, RELEASE SOFTWARE (fc1)
    Technical Support: http://www.cisco.com/techsupport
    Copyright (c) 1986-2013 by Cisco Systems, Inc.
    Compiled Fri 25-Oct-13 14:53 by prod_rel_team

    ROM: Bootstrap program is C3560C boot loader
    BOOTLDR: C3560C Boot Loader (C3560C-HBOOT-M) Version 12.2(55r)EX11, RELEASE SOFTWARE (fc1)

    Test-Switch uptime is 11 minutes
    System returned to ROM by power-on
    System restarted at 10:27:20 JST Wed Mar 30 2011
    System image file is "flash:/c3560c405ex-universalk9-mz.150-2.SE5/c3560c405ex-universalk9-mz.150-2.SE5.bin"


    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: ipbase
    License Type: Permanent
    Next reload license Level: ipbase

    cisco WS-C3560CG-8PC-S (PowerPC) processor (revision G0) with 131072K bytes of memory.
    Processor board ID FOC1913Y010
    Last reset from power-on
    2 Virtual Ethernet interfaces
    10 Gigabit Ethernet interfaces
    The password-recovery mechanism is enabled.

    512K bytes of flash-simulated non-volatile configuration memory.
    Base ethernet MAC Address       : 88:90:8D:05:E1:00
    Motherboard assembly number     : 73-13272-08
    Power supply part number        : 341-0407-01
    Motherboard serial number       : FOC19113Q1E
    Power supply serial number      : DCB190921U4
    Model revision number           : G0
    Motherboard revision number     : A0
    Model number                    : WS-C3560CG-8PC-S
    System serial number            : FOC1913Y010
    Top Assembly Part Number        : 800-33676-03
    Top Assembly Revision Number    : E0
    Version ID                      : V03
    CLEI Code Number                : CMMD900ARC
    Hardware Board Revision Number  : 0x00


    Switch Ports Model              SW Version            SW Image                 
    ------ ----- -----              ----------            ----------               
    *    1 10    WS-C3560CG-8PC-S   15.0(2)SE5            C3560c405ex-UNIVERSALK9-M


    Configuration register is 0xF

    Test-Switch#

    2023-05-05 17:02:20,919: %UNICON-INFO: +++ Test-Switch with via 'console': configure +++
    config term
    Enter configuration commands, one per line.  End with CNTL/Z.
    Test-Switch(config)#no logging console
    Test-Switch(config)#line console 0
    Test-Switch(config-line)#exec-timeout 0
    Test-Switch(config-line)#line vty 0 4
    Test-Switch(config-line)#exec-timeout 0
    Test-Switch(config-line)#end
    Test-Switch#

    2023-05-05 17:02:21,513: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'ter len 0' +++
    ter len 0
    Test-Switch#

    2023-05-05 17:02:21,677: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'show version' +++
    show version
    Cisco IOS Software, C3560C Software (C3560c405ex-UNIVERSALK9-M), Version 15.0(2)SE5, RELEASE SOFTWARE (fc1)
    Technical Support: http://www.cisco.com/techsupport
    Copyright (c) 1986-2013 by Cisco Systems, Inc.
    Compiled Fri 25-Oct-13 14:53 by prod_rel_team

    ROM: Bootstrap program is C3560C boot loader
    BOOTLDR: C3560C Boot Loader (C3560C-HBOOT-M) Version 12.2(55r)EX11, RELEASE SOFTWARE (fc1)

    Test-Switch uptime is 11 minutes
    System returned to ROM by power-on
    System restarted at 10:27:20 JST Wed Mar 30 2011
    System image file is "flash:/c3560c405ex-universalk9-mz.150-2.SE5/c3560c405ex-universalk9-mz.150-2.SE5.bin"


    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: ipbase
    License Type: Permanent
    Next reload license Level: ipbase

    cisco WS-C3560CG-8PC-S (PowerPC) processor (revision G0) with 131072K bytes of memory.
    Processor board ID FOC1913Y010
    Last reset from power-on
    2 Virtual Ethernet interfaces
    10 Gigabit Ethernet interfaces
    The password-recovery mechanism is enabled.

    512K bytes of flash-simulated non-volatile configuration memory.
    Base ethernet MAC Address       : 88:90:8D:05:E1:00
    Motherboard assembly number     : 73-13272-08
    Power supply part number        : 341-0407-01
    Motherboard serial number       : FOC19113Q1E
    Power supply serial number      : DCB190921U4
    Model revision number           : G0
    Motherboard revision number     : A0
    Model number                    : WS-C3560CG-8PC-S
    System serial number            : FOC1913Y010
    Top Assembly Part Number        : 800-33676-03
    Top Assembly Revision Number    : E0
    Version ID                      : V03
    CLEI Code Number                : CMMD900ARC
    Hardware Board Revision Number  : 0x00


    Switch Ports Model              SW Version            SW Image                 
    ------ ----- -----              ----------            ----------               
    *    1 10    WS-C3560CG-8PC-S   15.0(2)SE5            C3560c405ex-UNIVERSALK9-M


    Configuration register is 0xF

    Test-Switch#

    2023-05-05 17:02:21,922: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'show running-config' +++
    show running-config
    Building configuration...

    Current configuration : 3074 bytes
    !
    ! Last configuration change at 10:39:18 JST Wed Mar 30 2011 by admin
    ! NVRAM config last updated at 10:28:54 JST Wed Mar 30 2011
    !
    version 15.0
    no service pad
    service timestamps debug datetime msec
    service timestamps log datetime msec
    no service password-encryption
    !
    hostname Test-Switch
    !
    boot-start-marker
    boot-end-marker
    !
    no logging console
    enable password admin
    !
    username admin password 0 admin
    no aaa new-model
    clock timezone JST 9 0
    system mtu routing 1500
    ip routing
    !
    !
    no ip domain-lookup
    ip domain-name example.co.jp
    vtp mode transparent
    !
    !
    crypto pki trustpoint TP-self-signed-2365972736
    enrollment selfsigned
    subject-name cn=IOS-Self-Signed-Certificate-2365972736
    revocation-check none
    rsakeypair TP-self-signed-2365972736
    !
    !
    crypto pki certificate chain TP-self-signed-2365972736
    certificate self-signed 01
    3082022B 30820194 A0030201 02020101 300D0609 2A864886 F70D0101 05050030 
    31312F30 2D060355 04031326 494F532D 53656C66 2D536967 6E65642D 43657274 
    69666963 6174652D 32333635 39373237 3336301E 170D3131 30333330 30313238 
    35335A17 0D323030 31303130 30303030 305A3031 312F302D 06035504 03132649 
    4F532D53 656C662D 5369676E 65642D43 65727469 66696361 74652D32 33363539 
    37323733 3630819F 300D0609 2A864886 F70D0101 01050003 818D0030 81890281 
    81009CDA F41E9123 27AFD567 D165212F 4B9F04E5 4C930582 03284829 45105559 
    518C7730 3CF65301 B45E6832 3B7BB7C3 D2A33D1C 62755DC0 11FA48F9 4B4CE05F 
    4590BC27 17C09000 B1A3A0B2 BFB25542 FF415E2E 76F3D92A 9A08341C 47CD1FF7 
    9F729AE8 21414D70 8CA8D5D8 8FDB8EE9 639B3DC5 F28F85A8 393E0E2C 74868CFC 
    FFB90203 010001A3 53305130 0F060355 1D130101 FF040530 030101FF 301F0603 
    551D2304 18301680 14EC3371 FBDACDA6 4135EEDF 7693A11F 74D37878 CF301D06 
    03551D0E 04160414 EC3371FB DACDA641 35EEDF76 93A11F74 D37878CF 300D0609 
    2A864886 F70D0101 05050003 81810059 DA9FBE68 B422679E 2CA6E0C2 4DC9EBF1 
    1ECDB09F B1EF548D B86C4F37 35DE8C66 B546D91F 4DADE40C 1D6BC5A5 06FE538E 
    2D3A0CC5 DABA9514 BE288E7B 8FABA1B9 AA29B658 FA88B84A BB5879AF 908EDD66 
    26AD12A2 EFD84ED9 A7BD1A69 BF687558 0EAFF4F0 E98F2FEB 77B198EC 15510A5A 
    17A3AD33 424CFF16 CDBED520 588FF8
        quit
    spanning-tree mode pvst
    spanning-tree extend system-id
    !
    !
    !
    !
    !
    !
    !
    !
    !
    vlan internal allocation policy ascending
    !
    vlan 2,10,20,30,40,100,172 
    !
    ip ssh version 2
    !
    ! 
    !
    !
    !
    !
    !
    !
    !
    !
    interface GigabitEthernet0/1
    switchport access vlan 172
    switchport mode access
    !
    interface GigabitEthernet0/2
    switchport access vlan 172
    switchport mode access
    !
    interface GigabitEthernet0/3
    shutdown
    !
    interface GigabitEthernet0/4
    !
    interface GigabitEthernet0/5
    !
    interface GigabitEthernet0/6
    !
    interface GigabitEthernet0/7
    !
    interface GigabitEthernet0/8
    !
    interface GigabitEthernet0/9
    !
    interface GigabitEthernet0/10
    !
    interface Vlan1
    no ip address
    !
    interface Vlan172
    ip address 192.168.1.1 255.255.255.0
    !
    ip http server
    ip http secure-server
    !
    !
    !
    !
    !
    line con 0
    exec-timeout 0 0
    login local
    line vty 0 4
    exec-timeout 0 0
    login local
    transport input telnet ssh
    line vty 5 15
    login local
    transport input telnet ssh
    !
    end

    Test-Switch#

    2023-05-05 17:02:22,491: %UNICON-INFO: +++ Test-Switch with via 'console': configure +++
    config term
    Enter configuration commands, one per line.  End with CNTL/Z.
    Test-Switch(config)#
    Test-Switch(config)#    interface GigabitEthernet0/3
    Test-Switch(config-if)#    shutdown
    Test-Switch(config-if)#end
    Test-Switch#

    2023-05-05 17:02:22,975: %UNICON-INFO: +++ Test-Switch with via 'console': executing command 'wr' +++
    wr
    Building configuration...
    [OK]
    Test-Switch#


</div></details>

これでPyATS経由で機器にログインしてコマンドを実行までできました。お疲れ様でした。

実際は、例えばポート1と2でＬＡＧを組んだ機器に対して、片方shutdownしても通信できるか？インターフェースが正常にリンクアップしてるか？などケースバイケースだとおもいます。
ここからはifやtryで処理分岐させて思い通りのテストを記述していくことになります。皆さんの腕の見せ所です。

<details><summary>ホスト名とPingのテストサンプル</summary><div>

    import sys
    from genie.testbed import load
    testbed = load("testbed.yml")

    testbed.devices
    cat = testbed.devices["Test-Switch"]

    try:
        cat.connect()

        hostname = cat.execute("show running-config | include hostname")
        if ("Test-Switch" in hostname):
            print("【テスト結果】 >> ホスト名はポリシーを満たしています\n")
        else:
            print("【テスト結果】 >> ホスト名が誤っています\n")

        ping_result = cat.execute("ping 192.168.144.100") ##PC向けにping
        if ("!" in ping_result):
            print("【テスト結果】 >> コネクション確認OK\n")
        else:
            print("【テスト結果】 >> コネクション確認失敗\n")
    except:
        print(sys.exc_info()[0])

うーん、スイッチ1台だとあんまできることがないな～…
もしくは公式読んで関数の勉強しなきゃ
</div></details>

## ■雑談
機器の構築とかの社内検証段階では使えると思うんだけど、お客さん先に導入する機器の場合、セキュリティ的に自分のパソコンをつなげない場合が多いですよね。
作業用ＰＣとか貸してもらえると思うけどさすがにPythonいれたりするわけにはいかないし、作業直前にそんな時間ないよね。（入れてもらうにしても手間だし）
ネットワーク自動化って似たような構築テスト、もしくは運用や監視なら強いと思うんだけど、本番導入作業では難しそう。さすがに導入作業では人の目で見なきゃダメかな？
それに作ったコードの動作確認も事前にやっとかないといけないし、コード作成と動作検証にかける時間を考えたら手動でやったがいい場合もあるし、結構難しいライン引きだなあと思います。


## ■トラブルシューティング（自分が詰まった箇所のみですが）
- pyATSがインストールできないんだけど！
 →windowsでやってませんか？　
もしくは、`[full]`などのオプションを付けずに`pip install pyats`を実行。
そこから必要なモジュールをインストールしてみてください。

- `.connect()`しても接続できないんだけど！
 →そもそもターミナルなどからSSHできるか確認ください。 **■①の書き方** で書いたように、testbed内でホスト名が正確に書かれていますか？もしくはホストのSSHの設定に問題があるかもしれません。testbedファイルのIPやログイン情報が間違っていないかも確認してください。

## ■最後に
PyATSを最初からスタートラインに立つまでを書いてみました。
誰かのお役に立ったらうれしいです。