## AtCoder Beginners Contest 081 [A to C]

Tasks

A. Placing Marbles … Count “1” in the input string

`print(input().count("1"))`

B. Shift Only … Add the result into the temporary list if the number modulo 2 is 0. In each iteration of the list, compare the length of the original list and temporary list.

```n = int(input())
a = list(map(int, input().split()))

result = 0

while True:
temp_a = []
for num in a:
if num%2 == 0:
temp_a.append(num//2)
if len(temp_a) != n:
break
a = temp_a
result += 1

print(result)```

C. Not So Diverse … In python, there is a Counter function which can create a dictionary from a list. In this case, take a list of numbers, and make a dictionary which has “number” as a key, and “times of the number appears in the list” as a value.

```n = int(input())
a = list(map(int, input().split()))

result = 0

while True:
temp_a = []
for num in a:
if num%2 == 0:
temp_a.append(num//2)
if len(temp_a) != n:
break
a = temp_a
result += 1

print(result)```

## AtCoder Beginners Contest 080 [A to C]

Tasks

A. Parking … Simple comparison with if

```n, a, b = list(map(int, input().split()))

print(a*n if b > a*n else b)```

B. Harshard Number … Given one number, and judge if the number is Harshard Number. use modulus.

```x = input()

fx = sum([int(num) for num in x])

print("Yes" if int(x)%fx == 0 else "No")```

C. Shopping Street … Given one number, and two lists. And calculate the highest profit we can earn.

```n = int(input())
f = []
for _ in range(n):
f.append(list(map(int, input().split())))
p = []
for _ in range(n):
p.append(list(map(int, input().split())))

result = -float("inf")

# opening schedule for my shop.
# start from 1(only open Mon.AM) to 1023(open all day)
for b in range(1, 1<<10):

profit = 0
# compare with other shops
for i in range(n):

common_opening = 0
# compare time
for j in range(10):

if 1&(b>>j) and f[i][j] == 1:

common_opening += 1
profit += p[i][common_opening]

result = max(result, profit)

print(result)```

## IOx on Cisco: Launch Python

It’s been a long time since Cisco announced Fog computing, and implemented somewhat of programmability on their network devices. However I had never really looked at those functionalities until very recently.

I’m working in telecom industry and there has been no single day I don’t see Cisco devices, but most (if not all) of deployment is legacy, which utilizes only network function of those devices. It’s good as it is what those devices are meant to do, but I took a look on these new capabilities and found it very useful, and fun!

As Cisco mentioned in their article, these function should be used for non-networking functions. But these will be new weapons for those who knows networking very well to add-on new features as they wish, and on the other hand these will also be a good entry point for those who didn’t take care network(i.e developer, application engineer) until now. One of the most reliable network vendor provides small app platform on their small routers and switches.

### Enable IOX service

It’s not enabled on boot, so you need to enable services on IOS-XE. As this test is done on CSR1000v on AWS, it uses LXC.

```usrt01#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
usrt01(config)#iox
usrt01(config)#do sh iox-service
Virtual Service Global State and Virtualization Limits:

Infrastructure version : 1.7
Total virtual services installed : 0
Total virtual services activated : 0

Machine types supported   : LXC
Machine types disabled    : KVM

Maximum VCPUs per virtual service : 0
Resource virtualization limits:
Name                         Quota     Committed     Available
--------------------------------------------------------------
system CPU (%)                  75             0            75
memory (MB)                   1024             0          1024
bootflash (MB)               20000             0          6751

IOx Infrastructure Summary:
---------------------------
IOx service (CAF)    : Running
IOx service (HA)     : Not Running
IOx service (IOxman) : Running
Libvirtd             : Running```

The environment is almost ready.

1. Create connection … VirtualPortGroup, which is the connection point between the IOS and the guest system.
2. Allocate resource for application
3. Start application
```usrt01(config)#
usrt01(config)#int virtualportGroup 0
usrt01(config-if)#ip addre 10.0.0.254 255.255.255.0
usrt01(config-if)#exit
usrt01(config)#
usrt01(config)#app-hosting appid guestshell
usrt01(config-app-hosting)#vnic gateway1 virtualportgroup 0 guest-interface 0 guest-ipaddress 10.0.0.1 netmask 255.255.255.0 gateway 10.0.0.254 name-server 8.8.8.8 default
usrt01(config-app-hosting)#resource profile custom cpu 1500 memory 512
usrt01(config-app-hosting)#end
usrt01#guestshell enable
Interface will be selected if configured in app-hosting
Please wait for completion
guestshell installed successfully
Current state is: DEPLOYED
guestshell activated successfully
Current state is: ACTIVATED
guestshell started successfully
Current state is: RUNNING
Guestshell enabled successfully

usrt01#sh app-hosting list
App id                           State
------------------------------------------------------
guestshell                       RUNNING

usrt01#usrt01#guestshell

[guestshell@guestshell ~]\$
[guestshell@guestshell ~]\$ hostname -I
10.0.0.1

[guestshell@guestshell ~]\$ ping 10.0.0.254
PING 10.0.0.254 (10.0.0.254) 56(84) bytes of data.
64 bytes from 10.0.0.254: icmp_seq=2 ttl=255 time=0.525 ms
64 bytes from 10.0.0.254: icmp_seq=3 ttl=255 time=0.550 ms
64 bytes from 10.0.0.254: icmp_seq=4 ttl=255 time=0.580 ms
^C
--- 10.0.0.254 ping statistics ---
4 packets transmitted, 3 received, 25% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.525/0.551/0.580/0.035 ms

[guestshell@guestshell ~]\$
[guestshell@guestshell ~]\$ cat /flash/work/i_am_running.py
#!/bin/bash/python

import cli

# you can execute IOS command from guestshell
print "Hello, I\'m running on {}".format(cli.execute("show ver | inc Cisco IOS XE Software"))

[guestshell@guestshell ~]\$ python /flash/work/i_am_running.py
Hello, I'm running on Cisco IOS XE Software, Version 16.07.01a

[guestshell@guestshell ~]\$```

## API on Meraki: Meraki REST APIを使ってみる

このエントリーはMerakiでのREST APIの概要と、REST APIを使ってMerakiから情報を取得するところまで。

#### 製品概要

Merakiは他の製品と大きく異なるので、簡単に紹介。

Merakiの主力製品はCiscoと同じくネットワーク機器。Cisco製品との住み分けは下のイメージ（あくまで主観）

Ciscoは基本的には大きめの企業向け。SDNに対しては大企業が社内の統合環境を構築するのを推進している。レガシーな機能のみでももちろん使える。

Merakiの狙いは企業規模というよりは構築形態が分散型のネットワーク向け。SDN的な要素を使うためのハードルがCiscoに比べてとても低い。Ciscoが厳格な管理のもとで統合環境を適用するのに対して、Merakiはそこが抽象化されているので緩やか。

#### API概要

MerakiはSaaSで管理を提供しているので、それぞれの機器ではなく管理サービスがAPIを提供している。

API参照資料は以下の通り

Dashboard API: https://dashboard.meraki.com/api_docs

#### ラボ環境

Ciscoのオンラインラボ環境を使う。

CiscoDevNetにアクセスし、Merakiラボを選択

アクセスできるネットワークがいくつかあるが、今回はTokyo-Japanを選択

ここからは通常Merakiを管理するダッシュボードで操作ができる。

#### APIを使ってみる

Dashboard APIを使うには事前にAPIキーをダッシュボードから取得する。

Tokyoという名前がついたネットワークにある機器一覧を取得する。

```import requests
from collections import defaultdict
from pprint import pprint

# user specified variables
apikey = "************"
place = "Tokyo"

# static variable
headers = { "X-Cisco-Meraki-API-Key": apikey, }
baseurl = "https://dashboard.meraki.com/api/v0/"

# Retrieve organization list which I'm belonging to
url = baseurl + 'organizations'
my_orgs = requests.get(url, headers=headers).json()

# Set organization which I'm going to poll
my_orgid = my_orgs[0]['id']

# Retrieve network list which is defined in this organization
url = baseurl + 'organizations/' + str(my_orgid) + "/networks"
my_networks = requests.get(url, headers=headers).json()

# Set network which I'm going to poll
for network in my_networks:
if 'Japan' in network['name']:
network_id = network['id']

# get devices in the network
url = baseurl + 'networks/' + str(network_id) + '/devices'
my_devices = requests.get(url, headers=headers).json()

# list numbers of respective device models
devices_dict = defaultdict(int)
for device in my_devices:
devices_dict[device["model"]] += 1

pprint(devices_dict)```

これを実行するとこんな感じで情報が返ってくる

```defaultdict(<class 'int'>,
{'MC74': 1,
'MR30H': 1,
'MR53': 1,
'MR84': 1,
'MS220-8P': 1,
'MX65': 1})```

## API on FortiNet: FortiOS REST APIを使ってみる

* There is a new entry for FortiOS Rest API at ‘Fortigate RestAPI Config Backup – FortiOS 6.0.4’. Fortinet calls session based cookie –which is explained here, as legacy. If you are using FortiOS 5.6.1 or newer you can use API Token authentication as shown in the link above.

* このポストではセッションベースでの認証を紹介しています。ただし、この方法は将来的には廃止される予定なので、トークンベースでの認証をおすすめします。‘Fortigate RestAPI Config Backup – FortiOS 6.0.4’

このエントリーはFortiOSでのREST APIの概要と、REST APIを使ってFortigateから情報を取得するところまで。

#### API概要

FortiOSのREST APIは以下のように大きく二部構成になっている

CMDB API

• Retrieve object meta data (default, schema)
• Retrieve object/table (with filter, format, start, count, other flags)
• Create object
• Modify object l Delete object
• Clone object
• Move object

Monitor API

• Retrieve/Reset endpoint stats (with filter, start, count)
• Perform endpoint operations
• Upload/Download file
• Restore/Backup config
• Upgrade/Downgrade firmware
• Restart/Shutdown FGT

REST API関連のドキュメントは一般公開サイトでは見当たらず（特にFortiOS）、パートナーポータルにもない。

CiscoのASAやJuniperのSRXと違って、CLIで設定している人が少ないくAPIを使う人が少ない（＝需要が少ない）という発想から基本非公開にしているのか、それとも単純に何もしていないのかは疑問。FWの中ではかなりメジャーな部類に入ると思うのだが。

#### ラボ環境を作る

AWSでFortigateVMを立ち上げる。

1. FWを立ち上げる
2. sshでFWにアクセス
3. 起動時の設定で既にREST APIは使えるが、API用のユーザーを作成

#### APIを使ってみる

FortiOSのAPI認証は二種類あり、ユーザー名とパスワードを使用して認証用Cookieを取得する方法と、事前にTOKENを発行しておく二種類の方法がある。今回は前者を使う。

```import requests
import pprint

user = "api-user"
password = "******"
source = 'https://<fortigate_ip_address>'

s = requests.Session()

# Authenticate and obtain cookies, especially APSCOOKIE_ is important for subsequent GET request
s.post(source + "/logincheck", data={"username":user, "secretkey":password, "ajax":1}, verify=False)

# Using obtained cookies, request for information
url = source + '/api/v2/monitor/system/interface/select/'

r = s.get(url, verify=False)

pprint.pprint(r.json())```

これを実行するとこんな感じで情報が返ってくる

```{'action': 'select',
'build': 3176,
'http_method': 'GET',
'name': 'interface',
'path': 'system',
'results': {'port1': {'alias': '',
'duplex': 1,
'id': 'port1',
'ip': '10.10.145.176',
'link': True,
'mac': '00:00:00:00:00:00',
'mask': 24,
'name': 'port1',
'rx_bytes': 17599288,
'rx_errors': 0,
'rx_packets': 20990,
'speed': 1000.0,
'tx_bytes': 7903627,
'tx_errors': 0,
'tx_packets': 14461}},
'serial': 'FGTAWS0007D92F2A',
'status': 'success',
'vdom': 'root',
'version': 'v5.4.5'}```

## Install NAPALM

Using vendor proprietary API is usually a good option if you have only a few vendor to deal with. But It’s very time consuming, and some vendors don’t have those in-built API.

I have numbers of customers to take care, and there are their own demands. There is no one-fit-all network devices, hence I need to take care several vendors. Definitely I cannot be the master of all the network devices, but it’s a key how I can decrease the time taken by routine tasks(e.g monitoring interface stats) so that I can use other time to concentrate customer specific requirement.

#### Install NAPALM

NAPALM is registered in PyPI, so all you need to do is just use pip to install along with all the dependencies.

```(venv) shogokobayashi napalm \$ pip install napalm
Collecting napalm
Downloading napalm-2.3.0.tar.gz (147kB)
100% |████████████████████████████████| 153kB 964kB/s
Collecting future (from napalm)
Downloading future-0.16.0.tar.gz (824kB)
100% |████████████████████████████████| 829kB 1.3MB/s
Collecting jtextfsm (from napalm)
Downloading jtextfsm-0.3.1-py3-none-any.whl
Collecting jinja2 (from napalm)
Downloading Jinja2-2.10-py2.py3-none-any.whl (126kB)
100% |████████████████████████████████| 133kB 1.4MB/s
Collecting netaddr (from napalm)
Downloading netaddr-0.7.19-py2.py3-none-any.whl (1.6MB)
100% |████████████████████████████████| 1.6MB 1.7MB/s
Collecting pyYAML (from napalm)
Downloading PyYAML-3.12.tar.gz (253kB)
100% |████████████████████████████████| 256kB 2.1MB/s
Collecting pyeapi (from napalm)
Downloading pyeapi-0.8.2.tar.gz (133kB)
100% |████████████████████████████████| 143kB 1.5MB/s
Collecting netmiko>=1.4.3 (from napalm)
Downloading netmiko-2.1.0.tar.gz (70kB)
100% |████████████████████████████████| 71kB 2.1MB/s
Collecting pyIOSXR>=0.51 (from napalm)
Downloading pyIOSXR-0.52.tar.gz
Collecting junos-eznc>=2.1.5 (from napalm)
Downloading junos_eznc-2.1.7-py2.py3-none-any.whl (150kB)
100% |████████████████████████████████| 153kB 2.9MB/s
Collecting pynxos (from napalm)
Downloading pynxos-0.0.3.tar.gz
Collecting scp (from napalm)
Downloading scp-0.10.2-py2.py3-none-any.whl
Collecting MarkupSafe>=0.23 (from jinja2->napalm)
Downloading MarkupSafe-1.0.tar.gz
Collecting paramiko>=2.0.0 (from netmiko>=1.4.3->napalm)
Downloading paramiko-2.4.1-py2.py3-none-any.whl (194kB)
100% |████████████████████████████████| 194kB 2.5MB/s
Collecting pyserial (from netmiko>=1.4.3->napalm)
Downloading pyserial-3.4-py2.py3-none-any.whl (193kB)
100% |████████████████████████████████| 194kB 2.4MB/s
Collecting textfsm (from netmiko>=1.4.3->napalm)
Downloading textfsm-0.3.2.tar.gz
Collecting lxml>=3.2.4 (from pyIOSXR>=0.51->napalm)
Downloading lxml-4.2.0-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl (8.7MB)
100% |████████████████████████████████| 8.7MB 3.4MB/s
Collecting six (from junos-eznc>=2.1.5->napalm)
Downloading six-1.11.0-py2.py3-none-any.whl
Collecting ncclient>=0.5.3 (from junos-eznc>=2.1.5->napalm)
Downloading ncclient-0.5.3.tar.gz (63kB)
100% |████████████████████████████████| 71kB 3.3MB/s
Collecting requests>=2.7.0 (from pynxos->napalm)
Downloading requests-2.18.4-py2.py3-none-any.whl (88kB)
100% |████████████████████████████████| 92kB 2.2MB/s
Collecting pyasn1>=0.1.7 (from paramiko>=2.0.0->netmiko>=1.4.3->napalm)
Downloading pyasn1-0.4.2-py2.py3-none-any.whl (71kB)
100% |████████████████████████████████| 71kB 2.5MB/s
Collecting cryptography>=1.5 (from paramiko>=2.0.0->netmiko>=1.4.3->napalm)
Downloading cryptography-2.2-cp34-abi3-macosx_10_6_intel.whl (1.5MB)
100% |████████████████████████████████| 1.5MB 3.7MB/s
Collecting pynacl>=1.0.1 (from paramiko>=2.0.0->netmiko>=1.4.3->napalm)
Downloading PyNaCl-1.2.1-cp36-cp36m-macosx_10_6_intel.whl (243kB)
100% |████████████████████████████████| 245kB 2.4MB/s
Collecting bcrypt>=3.1.3 (from paramiko>=2.0.0->netmiko>=1.4.3->napalm)
Downloading bcrypt-3.1.4-cp36-cp36m-macosx_10_6_intel.whl (51kB)
100% |████████████████████████████████| 61kB 7.0MB/s
Requirement already satisfied: setuptools>0.6 in ./venv/lib/python3.6/site-packages (from ncclient>=0.5.3->junos-eznc>=2.1.5->napalm)
Collecting certifi>=2017.4.17 (from requests>=2.7.0->pynxos->napalm)
Downloading certifi-2018.1.18-py2.py3-none-any.whl (151kB)
100% |████████████████████████████████| 153kB 4.3MB/s
Collecting urllib3<1.23,>=1.21.1 (from requests>=2.7.0->pynxos->napalm)
Downloading urllib3-1.22-py2.py3-none-any.whl (132kB)
100% |████████████████████████████████| 133kB 2.7MB/s
Collecting idna<2.7,>=2.5 (from requests>=2.7.0->pynxos->napalm)
Downloading idna-2.6-py2.py3-none-any.whl (56kB)
100% |████████████████████████████████| 61kB 3.7MB/s
Collecting chardet<3.1.0,>=3.0.2 (from requests>=2.7.0->pynxos->napalm)
Downloading chardet-3.0.4-py2.py3-none-any.whl (133kB)
100% |████████████████████████████████| 143kB 3.7MB/s
Collecting cffi>=1.7; platform_python_implementation != "PyPy" (from cryptography>=1.5->paramiko>=2.0.0->netmiko>=1.4.3->napalm)
Downloading cffi-1.11.5-cp36-cp36m-macosx_10_6_intel.whl (241kB)
100% |████████████████████████████████| 245kB 2.8MB/s
Collecting asn1crypto>=0.21.0 (from cryptography>=1.5->paramiko>=2.0.0->netmiko>=1.4.3->napalm)
Downloading asn1crypto-0.24.0-py2.py3-none-any.whl (101kB)
100% |████████████████████████████████| 102kB 4.1MB/s
Collecting pycparser (from cffi>=1.7; platform_python_implementation != "PyPy"->cryptography>=1.5->paramiko>=2.0.0->netmiko>=1.4.3->napalm)
Downloading pycparser-2.18.tar.gz (245kB)
100% |████████████████████████████████| 256kB 3.0MB/s
Installing collected packages: future, jtextfsm, MarkupSafe, jinja2, netaddr, pyYAML, pyeapi, pyasn1, pycparser, cffi, asn1crypto, idna, six, cryptography, pynacl, bcrypt, paramiko, scp, pyserial, textfsm, netmiko, lxml, pyIOSXR, ncclient, junos-eznc, certifi, urllib3, chardet, requests, pynxos, napalm
Running setup.py install for future ... done
Running setup.py install for MarkupSafe ... done
Running setup.py install for pyYAML ... done
Running setup.py install for pyeapi ... done
Running setup.py install for pycparser ... done
Running setup.py install for textfsm ... done
Running setup.py install for netmiko ... done
Running setup.py install for pyIOSXR ... done
Running setup.py install for ncclient ... done
Running setup.py install for pynxos ... done
Running setup.py install for napalm ... done
Successfully installed MarkupSafe-1.0 asn1crypto-0.24.0 bcrypt-3.1.4 certifi-2018.1.18 cffi-1.11.5 chardet-3.0.4 cryptography-2.2 future-0.16.0 idna-2.6 jinja2-2.10 jtextfsm-0.3.1 junos-eznc-2.1.7 lxml-4.2.0 napalm-2.3.0 ncclient-0.5.3 netaddr-0.7.19 netmiko-2.1.0 paramiko-2.4.1 pyIOSXR-0.52 pyYAML-3.12 pyasn1-0.4.2 pycparser-2.18 pyeapi-0.8.2 pynacl-1.2.1 pynxos-0.0.3 pyserial-3.4 requests-2.18.4 scp-0.10.2 six-1.11.0 textfsm-0.3.2 urllib3-1.22
You are using pip version 9.0.1, however version 9.0.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
(venv) shogokobayashi napalm \$
```

Documentation can be found here.

And you can get the interfaces’ ip address with small script as follows:

```from pprint import pprint

def get_interfaces_ip(ip):

import napalm

driver = napalm.get_network_driver('ios')
device = driver(hostname=ip, username='api-user', password='*******' )

device.open()
interfaces = device.get_interfaces_ip()
device.close()

return interfaces

if __name__ == "__main__":
pprint(get_interfaces_ip("<ip_address or hostname>"))```

And output is as follows:

```{'GigabitEthernet1': {'ipv4': {'10.1.145.191': {'prefix_length': 24}}},
'GigabitEthernet2': {'ipv4': {'10.1.17.32': {'prefix_length': 24}}},
'VirtualPortGroup0': {'ipv4': {'10.0.0.254': {'prefix_length': 24}}}}```

The beauty of this script is:

• It doesn’t require IOS device to be configured with restconf nor netconf, just needs to be accessible via ssh.
• It can retrieve other vendors device information if you change ‘ios’ to other platform, such as ‘fortios’.

## API on Sophos: Sophos UTMを使ってみる (REST)

このエントリーはSophos UTMでのRESTの概要と、REST APIを使ってSophos UTMから情報を取得するところまで。

#### ラボ環境を作る

AWSでSophos UTMを立ち上げる。

1. FWを立ち上げる
2. sshでFWにアクセス
3. RESTでアクセスできるように設定。

```\$ssh -i aws_eu-ce1.pem loginuser@*******

Using username "loginuser".

Sophos UTM
(C) Copyright 2000-2017 Sophos Limited and others. All rights reserved.
Sophos is a registered trademark of Sophos Limited and Sophos Group.
All other product and company names mentioned are trademarks or registered
trademarks of their respective owners.

For more copyright information look at /doc/astaro-license.txt
or http://www.astaro.com/doc/astaro-license.txt

NOTE: If not explicitly approved by Sophos support, any modifications
done by root will void your support.

loginuser@sophons9_eu-central-1:/home/login > su -
Password:
sophons9_eu-central-1:/root #
sophons9_eu-central-1:/root # cc set webadmin rest_api 1
1
sophons9_eu-central-1:/root #

```

#### APIを使ってみる

APIの構成は、”https://<FWのIPアドレス>:<ポート番号（デフォルトは4444）>/api/definitions”からたどることが出来る。下の例ではethernetのインタフェース情報は”/objects/interface/ethernet/”で取得できることがわかる

Sophos UTMのAPI認証は、ユーザー名とパスワードをリクエストと一緒に送る（BASIC認証）と、事前にTOKENを発行しておく二種類の方法がある。今回はBASIC認証を使う。

```import requests
from pprint import pprint

def main():

source = "https://******.eu-central-1.compute.amazonaws.com:4444/api"
path = "/objects/interface/ethernet/"

url = source + path

headers = {"content-Type":"application/json", "Accept":"application/json", }

r = requests.get(url, headers=headers, verify=False, auth=('api-user', '******'))

return r.json()

if __name__ == '__main__':
pprint(main())```

これを実行するとこんな感じで情報が返ってくる

```ec2-user:~/environment/sophos_api \$ python3 get-interface.py
[{'_locked': '',
'_ref': 'REF_DefaultInternal',
'_type': 'interface/ethernet',
'additional_addresses': [],
'bandwidth': 100000000,
'comment': 'Auto-created on installation',
'inbandwidth': 0,
'itfhw': 'REF_ItfHwDefaultInternal',
'link': True,
'mtu': 9001,
'mtu_auto_discovery': True,
'name': 'Internal',
'outbandwidth': 0,
'primary_address': 'REF_ItfParamsDefaultInternal',
'proxyarp': False,
'proxyndp': False,
'status': True}]
ec2-user:~/environment/sophos_api \$```

## API on PaloAlto: PANOS 使ってみる (REST)

このエントリーはPANOSでのRESTの概要と、REST APIを使ってPaloAltoファイアウォールから情報を読むところまで。

#### ラボ環境を作る

AWSでVM Series PaloAlto FWを立ち上げる。

1. FWを立ち上げる
2. sshでFWにアクセス
3. RESTでアクセスできる設定は特に必要なし

#### APIを使ってみる

コマンドに対応した情報は、CLIから実行したいコマンドを打ってXPATHを確認するのが楽。下の例では”show interface logical”のXPATHは”<operations><show><interface>logical</interface></show></operations>”とわかる

```admin@PA-VM> debug cli on
admin@PA-VM> show interface logical
(leaf-tag: interface value: logical)
((eol-matched: . #t) (context-inserted-at-end-p: . #f))

<request cmd="op" cookie="8212554970679817" uid="500"><operations><show><interface>logical</interface></show></operations></reques
t>

<response status="success"><result><![CDATA[total configured logical interfaces: 1

name                id    vsys zone             forwarding               tag    address
------------------- ----- ---- ---------------- ------------------------ ------ ------------------
ethernet1/1         16    1                     N/A                      0      10.1.1.254/32
]]></result></response>

total configured logical interfaces: 1

name                id    vsys zone             forwarding               tag    address
------------------- ----- ---- ---------------- ------------------------ ------ ------------------
ethernet1/1         16    1                     N/A                      0      10.1.1.254/32

admin@PA-VM>```

PAN-OSの場合はCiscoやJuniperと異なり、実際のAPIリクエストをする前にキーを取得する必要がある。

```import requests
import xmltodict
import pprint

source = 'https://*****.eu-central-1.compute.amazonaws.com/api'

def get_key():

url = source + '/?type=keygen&user=api-user&password=******'
r = requests.get(url, verify=False)
r_dict = xmltodict.parse(r.text)

return r_dict['response']['result']['key']

def get_logical_interface(key):

# cmd=""を取得したいXPATHに変更する
param = '?type=op&cmd=<show><interface>logical</interface></show>'
url = source + param + '&key=' + key
r = requests.get(url, verify=False)

return r.text

key = get_key()

pprint.pprint(get_logical_interface(key))```

こんな感じで情報が返ってくる

```('<response status="success"><result>\n'
'  <ifnet>\n'
'    <entry>\n'
'      <name>ethernet1/1</name>\n'
'      <zone/>\n'
'      <fwd>N/A</fwd>\n'
'      <vsys>1</vsys>\n'
'      <dyn-addr/>\n'
'      <addr6/>\n'
'      <tag>0</tag>\n'
'      <ip>10.1.1.254/32</ip>\n'
'      <id>16</id>\n'
'      <addr/>\n'
'    </entry>\n'
'  </ifnet>\n'
'</result></response>')```

## API on Juniper: JUNOS 使ってみる (REST)

このエントリーはJUNOSでのRESTの概要と、SRXファイアウォールから情報を引きだせるところまで。

#### API概要

• Retrieve configuration information in XML, ASCII (plain text), or JSON.
• Retrieve operational data in XML, ASCII, or JSON.

#### ラボ環境を作る

AWSでvSRXを立ち上げる。

1. vSRXを立ち上げる
2. sshでvSRXにアクセス
3. RESTでアクセスできる設定
```root@%
root@% cli
root> configure
Entering configuration mode
Users currently editing the configuration:
root terminal p1 (pid 9176) on since 2018-03-15 00:24:19 UTC, idle 00:13:19

root# run show interfaces terse | match 172
fxp0.0                  up    up   inet     172.31.12.74/20

root# set system services rest http port 8080

root# show | compare
[edit system]
+   services {
+       rest {
+           http {
+               port 8080;
+           }
+       }
+   }

root# commit
commit complete

root#```

#### RESTを使ってみる

JUNOSでのXMLデザインはJunos XML API Operational Developer Reference dが参考になる。ただし16,000ページ以上の大長編。JUNOSコマンドに対応した情報は、CLIからメソッドを確認するのが楽。

```root> show interfaces fxp0.0 | display xml rpc
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/15.1X49/junos">
<rpc>
<get-interface-information>
<interface-name>fxp0.0</interface-name>
</get-interface-information>
</rpc>
<cli>
<banner></banner>
</cli>
</rpc-reply>

root>```

この例では、http://”vSRXのIPアドレス”:”ポート”/rpc/get-interface-information/interface-name=fxp0.0 にリクエストを送ればいい。

このようなスクリプトを実行すると

```import requests
import pprint

def get_json(interface):

source = 'http://****.eu-central-*.compute.amazonaws.com:8080/rpc'
method = '/get-interface-information'
param = '/interface-name=' + interface
options = ''

url = source + method + param + options
headers = {'Content-type': 'application/json', 'Accept': 'application/json'}

r = requests.get(url, auth=('api-user', '*****'), headers=headers)

return r.json()

pprint.pprint(get_json('fxp0.0'))```

こんな感じで情報が返ってくる

```{'interface-information': [{'attributes': {'junos:style': 'normal',
'xmlns': 'http://xml.juniper.net/junos/15.1X49/junos-interface'},
'logical-interface': [{'address-family': [{'address-family-flags': [{'ifff-is-primary': [{'data': None}],
'ifff-sendbcast-pkt-to-re': [{'data': None}]}],
'address-family-name': [{'data': 'inet'}],
'interface-address': [{'ifa-broadcast': [{'data': '172.31.15.255'}],
'ifa-destination': [{'data': '172.31.0/20'}],
'ifa-flags': [{'ifaf-current-default': [{'data': None}],
'ifaf-current-preferred': [{'data': None}],
'ifaf-current-primary': [{'data': None}]}],
'ifa-local': [{'data': '172.31.12.74'}]}],
'mtu': [{'data': '1500'}]}],
'encapsulation': [{'data': 'ENET2'}],
'filter-information': [{}],
'if-config-flags': [{'iff-snmp-traps': [{'data': None}],
'iff-up': [{'data': None}],
'internal-flags': [{'data': '0x4000000'}]}],
'local-index': [{'data': '4'}],
'name': [{'data': 'fxp0.0'}],
'snmp-index': [{'data': '13'}],
'traffic-statistics': [{'attributes': {'junos:style': 'brief'},
'input-packets': [{'data': '4062'}],
'output-packets': [{'data': '2683'}]}]}]}]}```

## API on Cisco: IOS-XE 使ってみる (RESTCONF)

NETCONFに続き、RESTCONFのエントリー

このエントリーはRESTCONFの概要と、ルータから情報を引きだせるところまで。

#### ビデオで概要を知る

1. Learn to CRUD with GET, POST and DELETE using RESTCONF … RESTCONFの使い方概要

#### ラボ環境を作る

AWSに立てたCSR1000Vでテストを行う

1. CSR1000Vを立ち上げる
2. sshでCSR1000Vにアクセス
3. RESTCONFでアクセスできる設定
```ip-172-31-2-170#
ip-172-31-2-170#sh ver | inc Cisco IOS
Cisco IOS XE Software, Version 16.07.01a
Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.7.1a, RELEASE SOFTWARE (fc4)
Cisco IOS-XE software, Copyright (c) 2005-2017 by cisco Systems, Inc.
All rights reserved.  Certain components of Cisco IOS-XE software are
ip-172-31-2-170#
ip-172-31-2-170#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
ip-172-31-2-170(config)#restconf
ip-172-31-2-170(config)#
ip-172-31-2-170(config)#ip http secure-server
ip-172-31-2-170(config)#exit
ip-172-31-2-170#```

#### RESTCONFを使ってみる

GigabitEthernet1の状態を確認するスクリプト

```import requests
import pprint

def get_json(interface):

source = 'https://xxxxxx.compute-x.amazonaws.com/restconf/data/'
module = 'ietf-interfaces:'
container = 'interfaces'
leaf = '/interface=' + interface
options = ''

url = source + module + container + leaf + options
headers = {'Content-type': 'application/yang-data+json', 'Accept': 'application/yang-data+json'}

r = requests.get(url, auth=('api-user', 'xxxxxx'), headers=headers, verify=False)

return r.json()

if __name__ == '__main__':

interface = 'GigabitEthernet1'

pprint.pprint(get_json(interface))```

CSR1000Vに対して実行したところ。インタフェースの情報が取得できた。

```\$ python3 get_one_interface.py
{'ietf-interfaces:interface': {'enabled': True,
'ietf-ip:ipv4': {'address': [{'ip': '172.31.2.170',
'netmask': '255.255.255.0'}]},
'ietf-ip:ipv6': {},
'name': 'GigabitEthernet1',
'type': 'iana-if-type:ethernetCsmacd'}}
\$```

GigabitEthernet1の設定を変更するスクリプト

```import requests
import json

import get_one_interface

def put_json(interface, data):

source = 'https://xxxxxx.compute-x.amazonaws.com/restconf/data/'
module = 'ietf-interfaces:'
container = 'interfaces'
leaf = '/interface=' + interface
options = ''

url = source + module + container + leaf + options
headers = {'Content-type': 'application/yang-data+json', 'Accept': 'application/yang-data+json'}

r = requests.put(url, data=data, auth=('api-user', 'xxxxxx'), headers=headers, verify=False)

return r.status_code

if __name__ == '__main__':
# retrieve current config of the interface
interface = 'GigabitEthernet1'
interface_config = get_one_interface.get_json(interface)

# add 'description' into the interface
interface_config['ietf-interfaces:interface']['description'] = 'Configured By RESTCONF'

print(put_json(interface, json.dumps(interface_config)))```

```\$ python3 put_one_interface.py
204
\$```

もう一度インターフェース情報を取得すると、descriptionが追加されているのが確認できる

```\$ python3 get_one_interface.py
{'ietf-interfaces:interface': {'description': 'Configured By RESTCONF',
'enabled': True,
'ietf-ip:ipv4': {'address': [{'ip': '172.31.2.170',
'netmask': '255.255.255.0'}]},
'ietf-ip:ipv6': {},
'name': 'GigabitEthernet1',
'type': 'iana-if-type:ethernetCsmacd'}}
\$```