[PYTHON] Fortsetzung ・ Ich habe versucht, die Router-Steuerungs-API-Bibliothek NAPALM eines Anbieters zu berühren

Dies ist der Artikel am 24. Tag von NetOpsCoding Adventskalender 2016.

NAPALM ist eine Open-Source-Python-Bibliothek zum Einrichten von Netzwerkgeräten und zum Erfassen von Informationen und steuert Produkte mehrerer Anbieter mit einer einheitlichen Schnittstelle. Es ist für diesen Zweck entwickelt. Für diejenigen, die eine Automatisierung in einer Netzwerkbetriebsumgebung mit mehreren Anbietern planen, ist eine mit mehreren Anbietern kompatible Bibliothek wie NAPALM eine lang erwartete Existenz.

NAPALM wurde im Juni 2015 in dem Artikel "Ich habe versucht, die Router-Steuerungs-API-Bibliothek NAPALM zu berühren" eingeführt, aber es ist immer noch NANOG. Die Entwicklung wird auf Initiative der Community aktiv fortgesetzt, und die Anzahl der Funktionen und kompatiblen Modelle nimmt nacheinander zu. Ich hatte das Gefühl, dass es an der Zeit sein könnte, es in einer Umgebung mit mehreren Anbietern an einem tatsächlichen Betriebsstandort zu platzieren, und fasste die Informationen diesmal erneut zusammen.

Kompatible Modelle

NAPALM unterstützt das folgende Netzwerkbetriebssystem.

--Arista EOS: 4.15.0F oder höher

Im Hintergrund von NAPALM die offizielle API des Herstellers (Juniper PyEZ und Arista eAPI pyeapi) usw.) und inoffizielle Hersteller-APIs, die von Einzelpersonen oder Communities (pyIOSXR und netmiko entwickelt wurden. Usw.) werden zu Make-up kombiniert.

Da es sich um eine von der Community geleitete Entwicklung handelt, scheinen die Funktionen stetig erweitert zu werden, mit der Idee, dass "Sie die fehlenden Funktionen selbst erstellen können". Bis Juni 2015 gab es nur vier kompatible Modelle, IOS XR, JUNOS, EOS und FortiOS. Es ist also ersichtlich, dass die Entwicklung in den letzten anderthalb Jahren dramatisch vorangekommen ist.

Entsprechende Funktion

Zum Zeitpunkt dieses Artikels sind in NAPALM die folgenden Funktionen implementiert. Die vom Betriebssystem implementierten Funktionen variieren jedoch. Weitere Informationen finden Sie auf der offiziellen Seite Unterstützte Geräte.

--Load config (ersetzen / zusammenführen) / Compare / Commit / Dicard / Rollback --Erfassung von Geräteinformationen

Bei der Entwicklung automatisierter Software ist es sehr hilfreich, dass die Funktionen des Statusbestätigungssystems erheblich sind. Wie ich in meinem vorherigen Blog geschrieben habe "Ich habe versucht, PyEZ und JSNAPy zu verwenden", ist es sehr wichtig, die Normalität von Netzwerkgeräten in Software zu überprüfen. Es ist eine Arbeit, die bricht. Implementieren Sie "Implementierung des Befehls zur Informationserfassung-> Zielzeichenfolge mit regulärem Ausdruck erfassen-> Extrahierte Zeichenfolge als Information erfassen oder normal / abnormal beurteilen", was für Softwareentwickler normalerweise unvermeidlich ist Durch die Verwendung des Prozesses als Bibliothek ohne Kenntnis des Anbieters / Modells kann der Entwicklungsaufwand erheblich reduziert werden.

Zusammenarbeit mit dem Automatisierungsrahmen

NAPALM ist nicht nur in Software eingebettet, sondern wird voraussichtlich auch von einem automatisierten Framework aufgerufen, das in den Betrieb der Serverinfrastruktur eingeführt wird. Derzeit werden NAPALM-Module für die Zusammenarbeit mit Ansible und Salt entwickelt.

Ich werde in diesem Artikel nicht auf Details eingehen, aber wenn Sie interessiert sind, lesen Sie bitte die folgenden Materialien.

Ich habe versucht, NAPALM zu verwenden

Versuchen wir, einen Router zu verwenden, um zu sehen, was Sie mit NAPALM tatsächlich tun können.

Durch zufälliges Berühren der Funktion, die ich verwenden möchte, ist die Menge ziemlich groß geworden. Überprüfen Sie daher bitte den Artikel, an dem Sie interessiert sind.

Umgebung

In diesem Artikel habe ich in der folgenden Umgebung experimentiert. Alle außer Macbook können kostenlos vorbereitet werden.

--PC (Host-Maschine) - MacBookAir OSX El Capitan 10.11.6

Wenn Sie mehr über die Vagrant-Integration von Firefly und IOS XRv erfahren möchten, lesen Sie bitte den folgenden Blog.

Referenz

Dieses Mal fuhr ich mit der Implementierung fort, während ich mir die folgenden Artikel ansah.

Installation

Installieren Sie die neueste Version von NAPALM (Version 1.1.0 zum Zeitpunkt dieses Blogs). Hier wird pip verwendet, ein Python-Paketverwaltungssystem.

% pip install napalm
(snip)


% pip list
(snip)
napalm (1.1.0)
napalm-base (0.21.0)
napalm-eos (0.5.0)
napalm-fortios (0.3.0)
napalm-ibm (0.1.6)
napalm-ios (0.5.0)
napalm-iosxr (0.4.2)
napalm-junos (0.5.1)
napalm-nxos (0.5.0)
napalm-panos (0.2.2)
napalm-pluribus (0.4.2)
(snip)


% pip show napalm                                                                                           (git)-[master]
Name: napalm
Version: 1.1.0
Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
Home-page: https://github.com/napalm-automation/napalm
Author: David Barroso
Author-email: [email protected]
License: UNKNOWN
Location: /usr/local/lib/python2.7/site-packages
Requires: napalm-pluribus, napalm-base, napalm-ios, napalm-iosxr, napalm-ibm, napalm-junos, napalm-eos, napalm-nxos, napalm-fortios, napalm-panos

Vorbereitung des Routers

Glühwürmcheneinstellungen

Um Firefly zu verwenden, wird es wie folgt eingestellt.

Informationen zum Erstellen von Firefly Vagrant finden Sie unter Die Geschichte des Fortschritts der automatisierten Entwicklung, als Firefly auf Vagrant ausgeführt wurde.

Vagrantfile


# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
    config.vm.box = "juniper/ffp-12.1X47-D20.7"
    config.vm.define :firefly1 do | firefly1 |
        firefly1.vm.hostname = 'firefly1'
        firefly1.vm.network "private_network",ip: "192.168.34.16",netmask: "255.255.255.0"
    end
end

Glühwürmchen zusätzliche Einstellungen


set system root-authentication plain-text-password
set system login user user1 class super-user
set system login user user1 authentication plain-text-password

#Die Standardeinstellung ist ge-0/0/Die Kommunikation mit dem Host-Computer ist nicht möglich, da 1 in der nicht vertrauenswürdigen Zone festgelegt ist.
#Hier die Hostmaschine(MacbookAir)Ich möchte das Automatisierungstool bedienen und mit ge kommunizieren-0/0/Ich ändere 1 in Vertrauenszone.
set security zones security-zone trust interfaces ge-0/0/1
set security zones security-zone trust interfaces ge-0/0/1.0 host-inbound-traffic system-services all
set system time-zone Asia/Tokyo


#Die Standardeinstellung ist Flow-basierter Übertragungsmodus(Modus zum Betreiben der Firewall-Funktion)Ist aktiviert und
#Routing-Protokolle wie BGP und OSPF funktionieren derzeit nicht.
#Hier, um das Routing-Protokoll zu betreiben, Paket-Die Einstellung zum Wechseln in den basierten Übertragungsmodus ist implementiert.
#Um den Modus zu wechseln, müssen Sie nach dem Einstellen neu starten.
delete security policies
set security forwarding-options family mpls mode packet-based
set security forwarding-options family inet6 mode packet-based

#BGP-bezogene Einstellungen für Dummy
set routing-options autonomous-system 65001
set protocols bgp family inet unicast
set protocols bgp group ge-0/0/2 type external
set protocols bgp group ge-0/0/2 neighbor 192.168.35.2 peer-as 65002
set protocols bgp group ge-0/0/2 export advertised_for_firefly2
set routing-options rib inet.0 static route 10.10.10.0/24 discard
set routing-options rib inet.0 static route 10.10.20.0/24 discard
set policy-options policy-statement advertised_for_firefly2 term 10 from route-filter 10.10.10.0/24 exact
set policy-options policy-statement advertised_for_firefly2 term 10 then accept
set policy-options policy-statement advertised_for_firefly2 term 999 then reject


#Außerdem konnte ich NAPALM verwenden, ohne das folgende NETCONF einzustellen.
# (Nicht festgelegt) set system services netconf ssh

Überprüfen Sie die Einstellungen mit Firefly



root@firefly1> show configuration
## Last commit: 2016-12-24 18:32:08 JST by root
version 12.1X47-D20.7;
system {
    host-name firefly1;
    time-zone Asia/Tokyo;
    root-authentication {
        encrypted-password "$1$EUe8ffbf$HT20ATkJCGIyslemV9hTf1"; ## SECRET-DATA
        ssh-rsa "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqs9vHYiqhpS5/5QWI2EskcTz1nMdv+1NlxrCaDyO8+03rzyHiOjXILcYx5MHExvw4JRlMMxiO0D3dHW+i4EtIVTSstyzEyd2coxLtgBp4VfaINBLInQKQNxOPioPUtu7rJynR9cHPk7DQw7QjCCUawYgQHWzCiiYSnmKWZrJAgVQZzfP2LEj1+Cqrg1ro8VQ4CpLeplOT4qXmlTE/dvQFPHabhAmGdP7JZv4IDPwZtkJ7gRv/PfYdTpn96IiG4Y09yIMPXaq40A82bczptazcOdScVyjUrFe8NbzQfnkVpe2C6ieDc7lU7PQhqqBGPpb1eEbQo1vq2Lo9b88dT7EH vagrant"; ## SECRET-DATA
    }
    login {
        user user1 {
            uid 2001;
            class super-user;
            authentication {
                encrypted-password "$1$P9L/Y/Ca$dzv5waDzJeYa5VdKGDm340"; ## SECRET-DATA
            }
        }
        user vagrant {
            uid 2000;
            class super-user;
            authentication {
                ssh-rsa "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key"; ## SECRET-DATA
            }
        }
    }
    services {
        ssh {
            root-login allow;
        }
        web-management {
            http {
                interface ge-0/0/0.0;
            }
        }
    }
    syslog {
        user * {
            any emergency;
        }
        file messages {
            any any;
            authorization info;
        }
        file interactive-commands {
            interactive-commands any;
        }
    }
    license {
        autoupdate {
            url https://ae1.juniper.net/junos/key_retrieval;
        }
    }
}
interfaces {
    ge-0/0/0 {
        unit 0 {
            family inet {
                dhcp;
            }
        }
    }
    ge-0/0/1 {
        unit 0 {
            family inet {
                address 192.168.34.16/24;
            }
        }
    }
    ge-0/0/2 {
        unit 0 {
            family inet {
                address 192.168.35.1/30;
            }
        }
    }
}
routing-options {
    rib inet.0 {
        static {
            route 10.10.10.0/24 discard;
            route 10.10.20.0/24 discard;
        }
    }
    autonomous-system 65001;
}
protocols {
    bgp {
        family inet {
            unicast;
        }
        group ge-0/0/2 {
            type external;
            export advertised_for_firefly2;
            neighbor 192.168.35.2 {
                peer-as 65002;
            }
        }
    }
}
policy-options {
    policy-statement advertised_for_firefly2 {
        term 10 {
            from {
                route-filter 10.10.10.0/24 exact;
            }
            then accept;
        }
        term 999 {
            then reject;
        }
    }
}
security {
    forwarding-options {
        family {
            inet6 {
                mode packet-based;
            }
            mpls {
                mode packet-based;
            }
        }
    }
    screen {
        ids-option untrust-screen {
            icmp {
                ping-death;
            }
            ip {
                source-route-option;
                tear-drop;
            }
            tcp {
                syn-flood {
                    alarm-threshold 1024;
                    attack-threshold 200;
                    source-threshold 1024;
                    destination-threshold 2048;
                    queue-size 2000; ## Warning: 'queue-size' is deprecated
                    timeout 20;
                }
                land;
            }
        }
    }
    zones {
        functional-zone management {
            interfaces {
                ge-0/0/0.0 {
                    host-inbound-traffic {
                        system-services {
                            all;
                        }
                        protocols {
                            all;
                        }
                    }
                }
            }
        }
        security-zone trust {
            tcp-rst;
            interfaces {
                ge-0/0/1.0 {
                    host-inbound-traffic {
                        system-services {
                            all;
                        }
                    }
                }
                ge-0/0/2.0 {
                    host-inbound-traffic {
                        system-services {
                            all;
                        }
                    }
                }
            }
        }
        security-zone untrust {
            screen untrust-screen;
        }
    }
}

Bestätigen Sie, dass Sie sich vom Host-Computer aus ssh bei Firefly anmelden können


% ssh [email protected]
Password:
--- JUNOS 12.1X47-D20.7 built 2015-03-03 21:53:50 UTC
user1@firefly1>
user1@firefly1> show version
Hostname: firefly1
Model: firefly-perimeter
JUNOS Software Release [12.1X47-D20.7]

IOSXRv-Konfiguration

Um IOSXRv verwenden zu können, wird Folgendes festgelegt. --Hostname: ios (Standard)

Informationen zum Erstellen von IOSXRv finden Sie unter Ich habe IOS-XRv Vagrant ausprobiert.

Vagrantfile


# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "IOS-XRv"
end

IOSXRv zusätzliche Einstellungen


#Erforderlich bei Verwendung von NAPALM
xml agent tty iteration off

#BGP-Einstellung für Dummy
router bgp 65001
 timers bgp 30 90
 address-family ipv4 unicast
  network 0.0.0.0/0
 !
 neighbor 192.168.0.1
  remote-as 65002
  description test_AS65002
  address-family ipv4 unicast
   send-community-ebgp
   next-hop-self
   soft-reconfiguration inbound always
  !
 !
!
end

Überprüfen Sie die Einstellungen mit IOS XRv


RP/0/RP0/CPU0:ios#show running-config
Fri Dec 23 13:16:25.273 UTC
Building configuration...
!! IOS XR Configuration version = 6.2.1.23I
!! Last configuration change at Fri Dec 23 13:08:29 2016 by vagrant
!
telnet vrf default ipv4 server max-servers 10
username vagrant
 group root-lr
 group cisco-support
 secret 5 $1$RQve$C1P.pH/koIKYsybRgxtSZ0
!
tpa
 address-family ipv4
  update-source MgmtEth0/RP0/CPU0/0
 !
!
interface MgmtEth0/RP0/CPU0/0
 ipv4 address dhcp
!
router static
 address-family ipv4 unicast
  0.0.0.0/0 MgmtEth0/RP0/CPU0/0 10.0.2.2
 !
!
router bgp 65001
 timers bgp 30 90
 address-family ipv4 unicast
  network 0.0.0.0/0
 !
 neighbor 192.168.0.1
  remote-as 65002
  description test_AS65002
  address-family ipv4 unicast
   send-community-ebgp
   next-hop-self
   soft-reconfiguration inbound always
  !
 !
!
grpc
 port 57777
!
xml agent tty
 iteration off
!
ssh server v2
ssh server vrf default
end

Anwendungsbeispiel für NAPALM: Erfassung von Geräteinformationen

Lassen Sie uns zuerst die Geräteinformationen abrufen. Informationen können mithilfe von get_facts () als Variable vom Typ Wörterbuch abgerufen werden. ..

Für JUNOS

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1' )

print 'Open session: ',
device.open()
print 'OK'

pprint(device.get_facts())

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python get_info.py 

Open session:  OK
get facts:
{u'fqdn': u'firefly1',
 u'hostname': u'firefly1',
 u'interface_list': ['ge-0/0/0',
                     'gr-0/0/0',
                     'ip-0/0/0',
                     'lsq-0/0/0',
                     'lt-0/0/0',
                     'mt-0/0/0',
                     'sp-0/0/0',
                     'ge-0/0/1',
                     'ge-0/0/2',
                     '.local.',
                     'dsc',
                     'gre',
                     'ipip',
                     'irb',
                     'lo0',
                     'lsi',
                     'mtun',
                     'pimd',
                     'pime',
                     'pp0',
                     'ppd0',
                     'ppe0',
                     'st0',
                     'tap',
                     'vlan'],
 u'model': u'FIREFLY-PERIMETER',
 u'os_version': u'12.1X47-D20.7',
 u'serial_number': u'f0016079634f',
 u'uptime': 1740,
 u'vendor': u'Juniper'}
Close session:  OK

Überprüfen des Status auf dem tatsächlichen Router


root@firefly1> show version
Hostname: firefly1
Model: firefly-perimeter
JUNOS Software Release [12.1X47-D20.7]

root@firefly1> show chassis hardware
Hardware inventory:
Item             Version  Part number  Serial number     Description
Chassis                                f0016079634f      FIREFLY-PERIMETER
Midplane
System IO
Routing Engine                                           FIREFLY-PERIMETER RE
FPC 0                                                    Virtual FPC
  PIC 0                                                  Virtual VTNET GE
Power Supply 0

Für IOS XR

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

print 'get facts: '
pprint(device.get_facts())

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python get_info.py                                                                                                                                                                         (git)-[master]
Open session:  OK
get facts:
{u'fqdn': u'ios',
 u'hostname': u'ios',
 u'interface_list': [u'Null0', u'MgmtEth0/RP0/CPU0/0'],
 u'model': u'XRV-P-L--CH',
 u'os_version': u'6.2.1.23I',
 u'serial_number': u'XRV-SN---CH',
 u'uptime': 1585,
 u'vendor': u'Cisco'}

Überprüfen des Status auf dem tatsächlichen Router


RP/0/RP0/CPU0:ios#show version
Fri Dec 23 12:38:05.156 UTC

Cisco IOS XR Software, Version 6.2.1.23I
Copyright (c) 2013-2016 by Cisco Systems, Inc.

Build Information:
 Built By     : jwu
 Built On     : Mon Nov 21 00:33:58 PST 2016
 Build Host   : iox-ucs-005
 Workspace    : /auto/iox-ucs-005-san1/nightly/xr-dev_16.11.20C/iosxrv-x64
 Version      : 6.2.1.23I
 Location     : /opt/cisco/XR/packages/

cisco IOS XRv x64 () processor
System uptime is 34 minutes


RP/0/RP0/CPU0:ios#show inventory
Fri Dec 23 12:39:25.870 UTC
NAME: "0/RP0", DESCR: "FLEX_PH"
PID: XRV-P-L--RP       , VID: FLEX_PH, SN: XRV-SN---RP

NAME: "Rack 0", DESCR: "FLEX_PH"
PID: XRV-P-L--CH       , VID: FLEX_PH, SN: XRV-SN---CH

Anwendungsbeispiel für NAPALM: Erfassung von Schnittstellenadressinformationen

Verwenden Sie die Funktion get_interfaces_ip (), um die Adressinformationen der Schnittstelle abzurufen.

Diesmal nicht implementiert, aber wenn Sie Schnittstellen-Up / Down- und MAC-Informationen erhalten möchten, [get_interfaces () -Funktion](https://napalm.readthedocs.io/en/latest/base.html#napalm_base.base.NetworkDriver .get_interfaces), get_interfaces_counters () -Funktion, wenn Sie Schnittstellenfehlerzähler und Informationen zur Lichtintensität erhalten möchten Wenn Sie es erhalten möchten, können Sie die Informationen mithilfe der Funktion [get_optics ()] abrufen (https://napalm.readthedocs.io/en/latest/base.html#napalm_base.base.NetworkDriver.get_optics). ..

Für JUNOS

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1')

print 'Open session: ',
device.open()
print 'OK'

print 'get interface IP: '
pprint(device.get_interfaces_ip())

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python get_info.py 

Open session:  OK
get interface IP:
{u'ge-0/0/0.0': {u'ipv4': {u'10.0.2.15': {u'prefix_length': 24}}},
 u'ge-0/0/1.0': {u'ipv4': {u'192.168.34.16': {u'prefix_length': 24}}},
 u'ge-0/0/2.0': {u'ipv4': {u'192.168.35.1': {u'prefix_length': 30}}},
 u'lo0.16384': {u'ipv4': {u'127.0.0.1': {u'prefix_length': 0}}},
 u'lo0.16385': {u'ipv4': {u'10.0.0.1': {u'prefix_length': 0},
                          u'10.0.0.16': {u'prefix_length': 0},
                          u'128.0.0.1': {u'prefix_length': 0},
                          u'128.0.0.4': {u'prefix_length': 0},
                          u'128.0.1.16': {u'prefix_length': 0}}},
 u'sp-0/0/0.16383': {u'ipv4': {u'10.0.0.1': {u'prefix_length': 0},
                               u'10.0.0.6': {u'prefix_length': 0},
                               u'128.0.0.1': {u'prefix_length': 0},
                               u'128.0.0.6': {u'prefix_length': 0}}}}
Close session:  OK

Überprüfen des Status auf dem tatsächlichen Router


root@firefly1> show interfaces terse
Interface               Admin Link Proto    Local                 Remote
ge-0/0/0                up    up
ge-0/0/0.0              up    up   inet     10.0.2.15/24
gr-0/0/0                up    up
ip-0/0/0                up    up
lsq-0/0/0               up    up
lt-0/0/0                up    up
mt-0/0/0                up    up
sp-0/0/0                up    up
sp-0/0/0.0              up    up   inet
                                   inet6
sp-0/0/0.16383          up    up   inet     10.0.0.1            --> 10.0.0.16
                                            10.0.0.6            --> 0/0
                                            128.0.0.1           --> 128.0.1.16
                                            128.0.0.6           --> 0/0
ge-0/0/1                up    up
ge-0/0/1.0              up    up   inet     192.168.34.16/24
ge-0/0/2                up    up
ge-0/0/2.0              up    up   inet     192.168.35.1/30
dsc                     up    up
gre                     up    up
ipip                    up    up
irb                     up    up
lo0                     up    up
lo0.16384               up    up   inet     127.0.0.1           --> 0/0
lo0.16385               up    up   inet     10.0.0.1            --> 0/0
                                            10.0.0.16           --> 0/0
                                            128.0.0.1           --> 0/0
                                            128.0.0.4           --> 0/0
                                            128.0.1.16          --> 0/0
lo0.32768               up    up
lsi                     up    up
mtun                    up    up
pimd                    up    up
pime                    up    up
pp0                     up    up
ppd0                    up    up
ppe0                    up    up
st0                     up    up
tap                     up    up
vlan                    up    down

Für IOS XR

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

print 'get interface IP: '
pprint(device.get_interfaces_ip())

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python get_info.py                                                                                                                                                                         (git)-[master]
Open session:  OK

get interface IP:
{u'MgmtEth0/RP0/CPU0/0': {u'ipv4': {u'10.0.2.15': {u'prefix_length': 24}}}}

Close session:  OK

Überprüfen des Status auf dem tatsächlichen Router


RP/0/RP0/CPU0:ios#show ipv4 interface brief
Fri Dec 23 12:44:59.827 UTC

Interface                      IP-Address      Status          Protocol Vrf-Name
MgmtEth0/RP0/CPU0/0            10.0.2.15       Up              Up       default

Anwendungsbeispiel für NAPALM: Erfassung von ARP-Tabelleninformationen

Verwenden Sie die Funktion get_arp_table (), um die ARP-Tabelleninformationen abzurufen.

Für JUNOS

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1')

print 'Open session: ',
device.open()
print 'OK'

print 'get ARP table'
pprint(device.get_arp_table())

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python get_info.py

Open session:  OK
get ARP table
[{'age': 530.0,
  'interface': u'ge-0/0/0.0',
  'ip': u'10.0.2.2',
  'mac': u'52:54:00:12:35:02'},
 {'age': 505.0,
  'interface': u'ge-0/0/0.0',
  'ip': u'10.0.2.3',
  'mac': u'52:54:00:12:35:03'},
 {'age': 1415.0,
  'interface': u'ge-0/0/1.0',
  'ip': u'192.168.34.1',
  'mac': u'0A:00:27:00:00:04'}]
Close session:  OK

Überprüfen des Status auf dem tatsächlichen Router


root@firefly1> show arp
MAC Address       Address         Name                      Interface           Flags
52:54:00:12:35:02 10.0.2.2        10.0.2.2                  ge-0/0/0.0          none
52:54:00:12:35:03 10.0.2.3        10.0.2.3                  ge-0/0/0.0          none
0a:00:27:00:00:04 192.168.34.1    192.168.34.1              ge-0/0/1.0          none
Total entries: 3

Für IOS XR

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

print 'get ARP table'
pprint(device.get_arp_table())

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python get_info.py

Open session:  OK
get ARP table
[{u'age': 1228.0,
  u'interface': u'MgmtEth0/RP0/CPU0/0',
  u'ip': u'10.0.2.2',
  u'mac': u'52:54:00:12:35:02'},
 {u'age': 0.0,
  u'interface': u'MgmtEth0/RP0/CPU0/0',
  u'ip': u'10.0.2.15',
  u'mac': u'08:00:27:0D:1E:94'}]

Close session:  OK

Überprüfen des Status auf dem tatsächlichen Router


RP/0/RP0/CPU0:ios#show arp
Fri Dec 23 12:46:58.918 UTC

-------------------------------------------------------------------------------
0/RP0/CPU0
-------------------------------------------------------------------------------
Address         Age        Hardware Addr   State      Type  Interface
10.0.2.2        00:37:45   5254.0012.3502  Dynamic    ARPA  MgmtEth0/RP0/CPU0/0
10.0.2.15       -          0800.270d.1e94  Interface  ARPA  MgmtEth0/RP0/CPU0/0

Anwendungsbeispiel für NAPALM: Erfassung von Routing-Informationen für eine bestimmte Route

Sie können die Routing-Informationen der angegebenen Route mithilfe der Funktion [get_route_to ()] abrufen (https://napalm.readthedocs.io/en/latest/base.html#napalm_base.base.NetworkDriver.get_route_to).

Für JUNOS

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1')

print 'Open session: ',
device.open()
print 'OK'

print 'get route to 192.168.35.0'
pprint(device.get_route_to(destination=u'192.168.35.0'))

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python get_info.py 

Open session:  OK
get route to 192.168.35.0
{u'192.168.35.0/30': [{'age': 3444,
                       'current_active': True,
                       'inactive_reason': u'',
                       'last_active': True,
                       'next_hop': None,
                       'outgoing_interface': u'ge-0/0/2.0',
                       'preference': 0,
                       'protocol': u'Direct',
                       u'protocol_attributes': {},
                       'routing_table': u'inet.0',
                       'selected_next_hop': True}]}
Close session:  OK

Überprüfen des Status auf dem tatsächlichen Router


root@firefly1> show route 192.168.35.2 detail

inet.0: 7 destinations, 7 routes (7 active, 0 holddown, 0 hidden)
192.168.35.0/30 (1 entry, 1 announced)
        *Direct Preference: 0
                Next hop type: Interface
                Address: 0x9350448
                Next-hop reference count: 2
                Next hop: via ge-0/0/2.0, selected
                State: <Active Int>
                Age: 58:00
                Task: IF
                Announcement bits (1): 1-Resolve tree 1
                AS path: I

Für IOSXR (Fehler)

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

pprint 'get route to 10.0.2.2'
pprint(device.get_route_to(destination=u'10.0.2.2'))

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python get_info.py                                                                                                                                                                         

Open session:  OK
get route to 10.0.2.2
Traceback (most recent call last):
  File "get_info.py", line 38, in <module>
    pprint(device.get_route_to(destination=u'10.0.2.2'))
  File "/usr/local/lib/python2.7/site-packages/napalm_iosxr/iosxr.py", line 1218, in get_route_to
    protocol=protocol
TypeError: Protocol not supported: .

Ich kann Folgendes auf dem Router sehen, aber es ist auf NAPALM fehlgeschlagen.

Überprüfen des Status auf dem tatsächlichen Router


RP/0/RP0/CPU0:ios#show route 10.0.2.15
Fri Dec 23 12:49:19.184 UTC

Routing entry for 10.0.2.15/32
  Known via "local", distance 0, metric 0 (connected)
  Installed Dec 23 12:09:11.148 for 00:40:08
  Routing Descriptor Blocks
    directly connected, via MgmtEth0/RP0/CPU0/0
      Route metric is 0
  No advertising protos.

Ich frage mich, ob es falsch war, das optionale Argumentprotokoll nicht in der Funktion [get_route_to ()] anzugeben (https://napalm.readthedocs.io/en/latest/base.html#napalm_base.base.NetworkDriver.get_route_to). Ich dachte, ich habe die folgenden Muster ausprobiert, aber es hat nicht funktioniert.

pprint(device.get_route_to(destination=u'10.0.2.2', protocol=u'bgp'))

Ausführungsergebnis


% python get_info.py                                                                                                                                                                         

Open session:  OK
get route to 10.0.2.2
Traceback (most recent call last):
  File "get_info.py", line 38, in <module>
    pprint(device.get_route_to(destination=u'10.0.2.2', protocol=u'bgp'))
  File "/usr/local/lib/python2.7/site-packages/napalm_iosxr/iosxr.py", line 1239, in get_route_to
    routes_tree = ETREE.fromstring(self.device.make_rpc_call(route_info_rpc_command))
  File "/usr/local/lib/python2.7/site-packages/pyIOSXR/iosxr.py", line 148, in make_rpc_call
    result = self._execute_rpc(rpc_command)
  File "/usr/local/lib/python2.7/site-packages/pyIOSXR/iosxr.py", line 412, in _execute_rpc
    raise XMLCLIError(error_msg, self)
pyIOSXR.exceptions.XMLCLIError:
Original call was: <?xml version="1.0" encoding="UTF-8"?><Request MajorVersion="1" MinorVersion="0"><Get><Operational><RIB><VRFTable><VRF><Naming><VRFName>default        </VRFName></Naming><AFTable><AF><Naming><AFName>IPv4</AFName></Naming><SAFTable><SAF>        <Naming><SAFName>Unicast</SAFName></Naming><IP_RIBRouteTable><IP_RIBRoute><Naming>        <RouteTableName>default</RouteTableName></Naming><RouteTable><Route><Naming><Address>        10.0.2.2</Address></Naming></Route></RouteTable></IP_RIBRoute></IP_RIBRouteTable>        </SAF></SAFTable></AF></AFTable></VRF></VRFTable></RIB></Operational></Get></Request>

Es kann ein Fehler in pyIOSXR sein, also werde ich versuchen, mehr herauszufinden, wenn ich Zeit habe.

Anwendungsbeispiel für NAPALM: Erfassung von BGP-Nachbarinformationen

Sie können BGP-Nachbarinformationen mithilfe der Funktion [get_bgp_neighbors ()] abrufen (https://napalm.readthedocs.io/en/latest/base.html#napalm_base.base.NetworkDriver.get_bgp_neighbors).

Für JUNOS

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1')

print 'Open session: ',
device.open()
print 'OK'

print 'get BGP neighbors'
pprint(device.get_bgp_neighbors())

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python get_info.py

Open session:  OK
get BGP neighbors
{u'global': {u'peers': {u'192.168.35.2': {u'address_family': {},
                                          'description': u'',
                                          'is_enabled': True,
                                          'is_up': False,
                                          'local_as': 65001,
                                          'remote_as': 65002,
                                          'remote_id': u'',
                                          u'uptime': 291}},
             u'router_id': u'None'}}
Close session:  OK

Überprüfen des Status auf dem tatsächlichen Router


root@firefly1> show bgp neighbor
Peer: 192.168.35.2+179 AS 65002 Local: 192.168.35.1 AS 65001
  Type: External    State: Connect        Flags: <ImportEval>
  Last State: Connect       Last Event: ConnectRetry
  Last Error: None
  Export: [ advertised_for_firefly2 ]
  Options: <Preference AddressFamily PeerAS Refresh>
  Address families configured: inet-unicast
  Holdtime: 90 Preference: 170
  Number of flaps: 0

Für IOS XR

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

print 'get BGP neighbors'
pprint(device.get_bgp_neighbors())

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python get_info.py

Open session:  OK
get BGP neighbors
{u'global': {u'peers': {u'192.168.0.1': {u'address_family': {u'ipv4': {u'accepted_prefixes': 0,
                                                                       u'received_prefixes': 0,
                                                                       u'sent_prefixes': 0}},
                                         u'description': u'test_AS65002',
                                         u'is_enabled': False,
                                         u'is_up': False,
                                         u'local_as': 65001,
                                         u'remote_as': 65002,
                                         u'remote_id': u'0.0.0.0',
                                         u'uptime': -1}},
             u'router_id': u'0.0.0.0'}}
Close session:  OK

Überprüfen des Status auf dem tatsächlichen Router


RP/0/RP0/CPU0:ios#show bgp neighbor
Fri Dec 23 13:14:16.879 UTC

BGP neighbor is 192.168.0.1
 Remote AS 65002, local AS 65001, external link
 Description: test_AS65002
 Remote router ID 0.0.0.0
  BGP state = Idle (eBGP neighbor not directly connected)
  NSR State: None
  Last read 00:00:00, Last read before reset 00:00:00
  Hold time is 180, keepalive interval is 60 seconds
  Configured hold time: 90, keepalive: 30, min acceptable hold time: 3
(snip)

Anwendungsbeispiel für NAPALM: Router-Konfigurationseinstellungen

Sie können die Konfigurationseinstellungen auf die gleiche Weise ändern, wie im vorherigen Blog beschrieben Ich habe versucht, die Router-Steuerungs-API-Bibliothek NAPALM zu berühren.

Für JUNOS (Fehler)

change_hostname_JUNOS.conf


system {
    host-name firefly1_changed_by_NAPALM;
}

set_hostname.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm

# For JUNOS firefly1
driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1')

print 'Open session: ',
device.open()
print 'OK'

print 'get hostname : ', 
print device.get_facts()[u'hostname']

print 'Config load (merge mode): ',
device.load_merge_candidate(filename='./change_hostname_JUNOS.conf')
print 'OK'

print 'Compare config: '
print device.compare_config()

print 'Do you commit? y/n'
choice = raw_input().lower()
if choice == 'y':
    print 'Commit config:',
    device.commit_config()
    print 'OK'
else:
    print 'Discard config:',
    device.discard_config()
    print 'OK'

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python set_hostname.py                                                                                                                                                                     (git)-[master]
Open session:  OK
get hostname :  firefly1
Config load (merge mode):  OK
Compare config:
[edit system]
-  host-name firefly1;
+  host-name firefly1_changed_by_NAPALM;
Do you commit? y/n
y
Commit config: OK
get hostname :
Traceback (most recent call last):
  File "set_hostname.py", line 41, in <module>
    print device.get_facts()[u'hostname']
  File "/usr/local/lib/python2.7/site-packages/napalm_junos/junos.py", line 182, in get_facts
    interfaces.get()
  File "/Library/Python/2.7/site-packages/jnpr/junos/factory/optable.py", line 64, in get
    self.xml = getattr(self.RPC, self.GET_RPC)(**rpc_args)
  File "/Library/Python/2.7/site-packages/jnpr/junos/rpcmeta.py", line 156, in _exec_rpc
    return self._junos.execute(rpc, **dec_args)
  File "/Library/Python/2.7/site-packages/jnpr/junos/decorators.py", line 58, in wrapper
    result = function(*args, **kwargs)
  File "/Library/Python/2.7/site-packages/jnpr/junos/decorators.py", line 26, in wrapper
    return function(*args, **kwargs)
  File "/Library/Python/2.7/site-packages/jnpr/junos/device.py", line 520, in execute
    raise EzErrors.RpcTimeoutError(self, rpc_cmd_e.tag, self.timeout)
jnpr.junos.exception.RpcTimeoutError: RpcTimeoutError(host: 192.168.34.16, cmd: get-interface-information, timeout: 60)

Ich habe einen Fehler bekommen. .. Auf dem eigentlichen Router scheinen sich die Änderungen jedoch ohne Probleme geändert zu haben.

Überprüfen des Status auf dem tatsächlichen Router


root@firefly1
(Programmausführung)

root@firefly1_changed_by_NAPALM>

root@firefly1_changed_by_NAPALM> show version
Hostname: firefly1_changed_by_NAPALM
Model: firefly-perimeter
JUNOS Software Release [12.1X47-D20.7]

[edit]
root@firefly1_changed_by_NAPALM# rollback ?
Possible completions:
  <[Enter]>            Execute this command
  0                    2016-12-24 18:55:57 JST by user1 via netconf
  1                    2016-12-24 18:32:08 JST by root via cli
  2                    2016-12-24 15:20:22 JST by root via cli

Als ich die Bedingungen änderte und sofort nach dem Festschreiben ohne "device.get_facts () [u'hostname ']" versuchte, wurde ein weiterer Fehler angezeigt.

Ausführungsergebnis


% python set_hostname.py                                                                                                                                                                     (git)-[master]
Open session:  OK
get hostname :  firefly1
Config load (merge mode):  OK
Compare config:
[edit system]
-  host-name firefly1;
+  host-name firefly1_changed_by_NAPALM;
Do you commit? y/n
y
Commit config: OK
Close session:
Traceback (most recent call last):
  File "set_hostname.py", line 44, in <module>
    device.close()
  File "/usr/local/lib/python2.7/site-packages/napalm_junos/junos.py", line 94, in close
    self._unlock()
  File "/usr/local/lib/python2.7/site-packages/napalm_junos/junos.py", line 106, in _unlock
    self.device.cu.unlock()
  File "/Library/Python/2.7/site-packages/jnpr/junos/utils/config.py", line 489, in unlock
    raise UnlockError(rsp=err.rsp)
jnpr.junos.exception.UnlockError: <exception str() failed>

Ich hatte nicht genug Zeit, um Fehler zu beheben, aber es kann sein, dass etwas mit JUNOS 'Unlock nicht stimmt. Ich werde es hinzufügen, sobald die Ursache bekannt ist.

Für IOS XR

change_hostname_IOSXR.conf


hostname iosxrv1_changed_by_NAPALM

set_hostname.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm

# For Cisco IOSXRv
driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

print 'get hostname : ', 
print device.get_facts()[u'hostname']

print 'Config load (merge mode): ',
device.load_merge_candidate(filename='./change_hostname_IOSXR.conf')
print 'OK'

print 'Compare config: '
print device.compare_config()

print 'Do you commit? y/n'
choice = raw_input().lower()
if choice == 'y':
    print 'Commit config:',
    device.commit_config()
    print 'OK'
else:
    print 'Discard config:',
    device.discard_config()
    print 'OK'

print 'get hostname : ', 
print device.get_facts()[u'hostname']

print 'Close session: ',
device.close()
print 'OK'

Ausführungsergebnis


% python set_hostname.py                                                                                                                                                                     (git)-[master]
Open session:  OK
get hostname :  ios
Config load (merge mode):  OK
Compare config:
---
+++
@@ -1,5 +1,6 @@
 !! Last configuration change at Fri Dec 23 13:20:24 2016 by vagrant
 !
+hostname iosxrv1_changed_by_NAPALM
 telnet vrf default ipv4 server max-servers 10
 username vagrant
  group root-lr
Do you commit? y/n
y
Commit config: OK
get hostname :  iosxrv1_changed_by_NAPALM
Close session:  OK

Überprüfen des Status auf dem tatsächlichen Router


RP/0/RP0/CPU0:ios#
(Programmausführung)

RP/0/RP0/CPU0:iosxrv1_changed_by_NAPALM#

RP/0/RP0/CPU0:iosxrv1_changed_by_NAPALM#sh running-config hostname
Fri Dec 23 13:21:32.129 UTC
hostname iosxrv1_changed_by_NAPALM

IOSXR konnte die Einstellungen erfolgreich ändern!

Zusammenfassung

Dieses Mal wurde bestätigt, dass mithilfe von NAPALM Informationen erfasst und Router-Einstellungen in der Umgebung von JUNOS-Router und IOS XR-Router vorgenommen werden können. Es gab einige Dinge, die nicht gut liefen, aber es könnte in Zukunft verbessert werden. Ich werde es hinzufügen, wenn ich die Ursache des Problems verstehe.

NAPALM hat bereits eine Vielzahl von Funktionen implementiert, und es scheint, dass NAPALM den Aufwand für die Entwicklung von Automatisierungssoftware in einer Umgebung mit mehreren Anbietern erheblich reduzieren kann.

Da die Entwicklung durch die NAPALM-Community sehr aktiv ist, können wir außerdem in Zukunft mit einer weiteren Erweiterung der Funktionen und einer Zunahme kompatibler Modelle rechnen.

Derzeit scheinen nur Brocade-Produkte, OSPF-bezogene und MPLS-bezogene Funktionen zu fehlen. Wenn Sie es etwas mehr berühren, werden Sie möglicherweise verschiedene Aspekte bemerken, die fehlen.

Das Programm, das ich dieses Mal ausprobiert habe, ist auf Github veröffentlicht. Wenn Sie möchten, lesen Sie es bitte. (Entschuldigung für den schmutzigen Code ...) https://github.com/taijiji/sample_nalapm

Schließlich

Dieses Mal habe ich gerade die Funktionen von NAPALM vorgestellt, aber wenn ich in Zukunft Zeit habe, habe ich versucht, den vorherigen Blog "[PyEZ und JSNAPy. Teil 4: Automatisieren der ISP-Einstellungsarbeit mit PyEZ und JSNAPy]( Ich werde auch versuchen, eine herstellerkompatible Version (vorerst JUNOS und IOSXR) des Automatisierungstools zu entwickeln, das mit "http://qiita.com/taijijiji/items/983189f9bdebaa53e499)" erstellt wurde.

Wenn jemand versucht hat, ein Automatisierungstool mit NAPALM zu entwickeln, stellen Sie es bitte in Zukunft vor NetOps Coding. Ich bin froh.

Schöne Weihnachten.

Recommended Posts

Fortsetzung ・ Ich habe versucht, die Router-Steuerungs-API-Bibliothek NAPALM eines Anbieters zu berühren
Ich habe versucht, die API-Bibliothek NAPALM für Router-Steuerungen mehrerer Hersteller zu berühren
Ich habe die Changefinder-Bibliothek ausprobiert!
Ich habe die Naro-Roman-API 2 ausprobiert
Ich habe die neuartige API von Naruro ausprobiert
Ich habe versucht, die checkio-API zu verwenden
Ich habe versucht, die COTOHA-API zu berühren
Ich habe versucht, die BigQuery-Speicher-API zu verwenden
Ich habe in der Bibliothek nach der Verwendung der Gracenote-API gesucht
Ich habe versucht, die Qiita-API von Anfang an zu aktivieren
Ich habe versucht, die Google Cloud Vision-API zu verwenden
Ich habe versucht, die funktionale Programmierbibliothek toolz zu verwenden
Ich habe versucht, die API von Sakenowa Data Project zu verwenden
Ich habe versucht, die API mit dem Python-Client von echonest zu erreichen
[Erste COTOHA-API] Ich habe versucht, die alte Geschichte zusammenzufassen
Ich habe versucht, die Python-Bibliothek von Ruby mit PyCall zu verwenden
Ich habe versucht, den DRF-API-Anforderungsverlauf mit django-request zu speichern
[Python] Ich habe versucht, Daten mit der API von Wikipedia zu sammeln
Ich habe die Google Cloud Vision-API zum ersten Mal ausprobiert
Ich habe versucht, verschiedene Informationen von der Codeforces-API abzurufen
[Für Anfänger] Ich habe versucht, die Tensorflow-Objekterkennungs-API zu verwenden
Ich habe versucht, die Qiita-API zu berühren
Ich habe eine Python-Bibliothek erstellt, um die API von LINE WORKS aufzurufen
Ich habe versucht, die COTOHA-API zu verwenden (es gibt auch Code auf GitHub).
Fortsetzung: Ich habe versucht, das Blockdiagramm-Generierungswerkzeug blockdiag einzuführen
Ich habe das TensorFlow-Tutorial als erstes ausprobiert
Ich habe versucht, eine Quip-API zu erstellen
Ich habe das 2. TensorFlow-Tutorial ausprobiert
Ich habe Teslas API berührt
Ich habe versucht, den Ball zu bewegen
Ich habe versucht, den Abschnitt zu schätzen.
Ich habe versucht, die Vorhersage-API des maschinellen Lernmodells von WordPress aus aufzurufen
Ich habe versucht, mehrere Servomotoren MG996R mit dem Servotreiber PCA9685 zu steuern.
Ich habe versucht, verschiedene Sätze mit der automatischen Zusammenfassungs-API "summpy" zusammenzufassen.
Ich habe versucht, das Modell mit der Low-Code-Bibliothek für maschinelles Lernen "PyCaret" zu visualisieren.
Ich habe versucht, die Filminformationen der TMDb-API mit Python abzurufen
Ich habe versucht, berührungsbezogene Methoden im Szenenmodul von Pythonista zu berühren
Ich habe versucht, die Netzwerkbandbreite und -verzögerung mit dem Befehl tc zu steuern