epiecs/mikodo

基于 phpmiko 的并发 Unix 兼容库,具有库存管理功能

维护者

详细信息

github.com/epiecs/mikodo

源代码

问题

安装: 20

依赖项: 0

建议者: 0

安全: 0

星标: 2

关注者: 0

分支: 1

开放性问题: 0

类型:项目

v1.0.8 2020-10-01 09:40 UTC

This package is auto-updated.

Last update: 2024-09-29 05:20:54 UTC


README

基于 phpmiko 的并发库。加快发送命令的过程。包含库存管理库。支持的库包括但不限于:Nornir yaml 文件、PhpIpam、...

需求

  • Php >= 7.1

  • ext-sockets

  • ext-pcntl

  • A UNIX 或 BSD OS。目前不支持原生 Windows,但可以使用 WSL。

安装

composer require epiecs/mikodo

支持的库存

已实现
  • 基本
  • Nornir
  • PhpIpam
计划中
  • Netbox
  • ...

基本示例

初始化 Mikodo

require_once __DIR__ . '/vendor/autoload.php';

$mikodo = new \Epiecs\Mikodo\Mikodo();
缓冲区大小

每个工作进程与父进程通信可用的字节数。如果您需要发送大量文本(例如)完整的配置文件,请将此设置为更高的数字。您可以将此设置为较低的数字以减少内存使用,但您可能无法接收到所有输出。

$mikodo->bufferSize(65535); // Defaults to 65535

运行命令

Mikodo 使用与 Phpmiko 相同的 3 种方法向设备发送命令:cli、operation 和 configure。

在发送命令时,您可以通过字符串或命令的数组提供方法。两种方式都一样。当提供数组时,命令按顺序运行。

有关命令类型之间的区别,您可以参考 Phpmiko 文档

准备库存

Mikodo 使用库存来完成其魔法。最基本的方式是为 inventory() 方法提供一个由主机组成的数组

$mikodo->inventory([
    'Hostname_1' => [
        'device_type'    => "junos",
        'username'       => "username",
        'password'       => "password",
        'hostname'       => "hostname or ip"
    ],
    'Hostname_2' => [
        'device_type'    => "junos",
        'username'       => "username",
        'password'       => "password",
        'hostname'       => "hostname or ip"
    ]
]);

每个主机至少应包括 Phpmiko 最基本所需信息:device_typeusernamepasswordhostname

发送命令(s)

当库存已准备就绪时,您就可以开始发送命令了。

$results = $mikodo->cli([
    'date',
    'ping -c 2 8.8.8.8'
]);

如果一切顺利,您将看到如下输出。当然,在现实生活中,您将看到(漂亮的)颜色。

Starting mikodo,  2 queued jobs
[cli]
        date
        ping -c 2 8.8.8.8
=========================================================================> 100%
Retrieving output from Hostname_2
检索结果

Mikodo 将返回一个数组形式的值,您可以在其中为每个主机期望一个键,在该主机的键中,每个已运行的命令都还有一个键。

[
    'Hostname_1' => [
        'date' => "
            Wed Jul 24 15:48:36 CEST 2019
            "
        'ping -c 2 8.8.8' => "
            PING 8.8.8.8 (8.8.8.8): 56 data bytes
            64 bytes from 8.8.8.8: icmp_seq=0 ttl=64 time=10.706 ms
            64 bytes from 8.8.8.8: icmp_seq=1 ttl=64 time=11.214 ms
            --- 8.8.8.8 ping statistics ---
            2 packets transmitted, 2 packets received, 0% packet loss
            round-trip min/avg/max/stddev = 10.706/10.960/11.214/0.254 ms
            "
    ]
    'Hostname_2' => [
        'date' => "
            Wed Jul 24 15:48:36 CEST 2019
            "
        'ping -c 2 8.8.8.8' => "
            PING 8.8.8.8 (8.8.8.8): 56 data bytes
            64 bytes from 8.8.8.8: icmp_seq=0 ttl=64 time=54.188 ms
            64 bytes from 8.8.8.8: icmp_seq=1 ttl=64 time=11.252 ms
            --- 8.8.8.8 ping statistics ---
            2 packets transmitted, 2 packets received, 0% packet loss
            round-trip min/avg/max/stddev = 11.252/32.720/54.188/21.468 ms
            "
    ]
]
打印结果

要将结果输出到终端,只需将返回的结果提供给 Mikodo->print() 函数。

$mikodo->print($results);

此外,在现实生活中,您应该得到漂亮的颜色。

Hostname_1
date

Wed Jul 24 15:33:48 CEST 2019

ping -c 2 8.8.8.8

PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8 icmp_seq=0 ttl=64 time=10.798 ms
64 bytes from 8.8.8.8 icmp_seq=1 ttl=64 time=11.348 ms
--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 10.798/11.073/11.348/0.275 ms

Hostname_2
date

Wed Jul 24 15:33:48 CEST 2019

ping -c 2 8.8.8.8

PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8 icmp_seq=0 ttl=64 time=11.876 ms
64 bytes from 8.8.8.8 icmp_seq=1 ttl=64 time=11.193 ms
--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 11.193/11.534/11.876/0.341 ms

库存

为了使您的生活更轻松,Mikodo 包含了几个库存提供者。

库存允许您轻松选择库存中的特定主机和/或组。库存还允许您在全局和/或组级别设置默认值。

您甚至可以混合和匹配不同的库存。一个例子可以是加载 PhpIpam 中的所有主机,并通过简单库存提供默认的用户名/密码。

您必须注意的一个注意事项是设置的顺序。

优先顺序是主机 > 组 > 默认值。想象一下这种情况:您有一个库存,并在默认设置中设置了默认的用户名和密码。在您的库存中,还有一个主机,其中在主机配置中设置了密码。

主机中定义的密码将优先于默认设置中提供的密码。

编写自己的库存提供者

所有库存提供者都可以扩展基本库存类,并应实现DeviceInterface接口。

建议扩展基本Inventory类并使用sethosts/setgroups/setdefaults命令。这些命令将确保配置按预期正确合并。

InventoryInterface提供了一种很好的结构,说明包含主机、组和默认值的数组应该如何工作。

基本库存

基本库存可以通过三种方式初始化

  • 通过构造函数
  • 通过设置器
  • 两者的组合

示例

require_once __DIR__ . '/vendor/autoload.php';

use Epiecs\Mikodo\Mikodo;
use Epiecs\Mikodo\InventoryProviders\BaseInventory;

$baseInventory = new BaseInventory();

// Sethosts is used here but you can always use the constructor if you'd like

$baseInventory->setGroups([
    'core_switches' => [
        'device_type' => "cisco_ios",
    ],
    'lab_switches' => [
        'username'    => 'lab_username',
        'password'    => 'lab_password',
        'port'        => 2020
    ]
]);

$baseInventory->setDefaults([
     'port'     => 22,
     'username' => "defaultusername",
     'password' => "defaultpassword"
]);

$baseInventory->setHosts([
    'Hostname_1' => [
      'device_type' => 'junos',
      'port'        => 22,
      'username'    => 'my_default_username',
      'password'    => 'my_default_password',
      'hostname'    => '192.168.0.1',
      'groups'      => [
          'core_switches',
      ],
    ],
    'Hostname_2' => [
      'device_type' => 'junos',
      'port'        => 22,
      'username'    => 'my_default_username',
      'password'    => 'my_default_password',
      'hostname'    => '192.168.0.1',
      'groups'      => [
          'core_switches'
      ]
    ],
    'Hostname_3' => [
      'device_type' => 'cisco_ios',
      'port'        => 22,
      'hostname'    => '172.16.2.10',
      'groups'      => [
          'lab_switches',
          'core_switches'
      ]
    ],
]);

$mikodo = new Mikodo();

$mikodo->inventory($baseInventory->getGroups(['lab_swithches', 'core_switches']));

以下方法被支持

$baseInventory = new BaseInventory(array $hosts = array(), array $groups = array(), array $defaults = array());

// Setting the inventory
$baseInventory->setHosts(array $hosts);
$baseInventory->setGroups(array $groups);
$baseInventory->setDefaults(array $defaults);

// Get all hosts
$baseInventory->getHosts(array $hosts);

// Get all groups provided in the $groups array
$baseInventory->getGroups(array $groups);
// Get all groups provided in the $groups array and reduce with the groups within the $filterGroups array
$baseInventory->getGroups(array $groups, array $filterGroups);

// Get the full inventory. Usefull if you need to modify it yourself.
$baseInventory->getInventory();

getGroups方法

当使用getGroups方法时,有一个可选参数叫做$groups。

根据在$groups参数中提供的组名,从库存中获取所有主机。

当提供了一个包含filterGroups的数组时,库存将返回只包含$groups和$filterGroups数组中的组的二分搜索结果

$groups数组将结果集填充为所有提供的组,而$filterGroups有助于减少它

例如,如果您请求cisco和switches组中的所有设备,并且只想使用也是nexus和europe组成员的设备

$groups = ['cisco', 'switches'];
$filterGroups = ['nexus', 'eu'];

$baseInventory->getGroups(array $groups, array $filterGroups);

PhpIpam库存

Mikodo可以使用现有的PhpIpam实例。库存提供者将从phpipam获取所有设备,并将某些组自动应用于每个主机名,只要phpipam中对应的值存在且不为空。

之后,如果需要,您仍然可以通过提供的库存方法设置组和/或默认设置。

将为

  • 每种在phpipam中已知的设备类型应用一个组。
  • 该设备的机架(们)
  • 该设备所属的区(们)
  • 该设备的位置(们)
  • 如果为设备设置了自定义字段。

如果为用户名、密码、端口和/或设备类型提供了自定义字段,则不会将其作为组应用,而是直接应用于主机对象。这样就可以在PhpIpam中设置一些默认值

如果您愿意,也可以提供一个名为'groups'的自定义字段,其中包含逗号分隔的组。这些组将被添加到该设备的已知组中。

以下认证方法被支持

  • 用户令牌(未加密,需要用户名和密码)
  • 带有用户令牌的SSL(加密,需要用户名和密码),提供https api链接
  • 带有应用代码令牌的SSL(加密,需要应用代码),提供https链接
$ipamUrl  = 'https://phpipam.local/api'
$appId    = 'ipamappId'
$username = 'ipamuser';
$password = 'ipampassword';

$appCode  = 'ipamAppCode';

// When using username and password
$phpipamInventory = new \Epiecs\Mikodo\InventoryProviders\PhpipamInventory($ipamUrl, $appId, $username, $password);

// When using an app code token
$phpipamInventory = new \Epiecs\Mikodo\InventoryProviders\PhpipamInventory($ipamUrl, $appId, "", "", $appCode);

// Set the group and default settings if neccesary
$phpipamInventory->setGroups([
    'switch' => [
        'device_type' => "cisco_ios",
        'password'    => "password"
    ],
    'firewall' => [
        'device_type' => "junos",
        'port'        => 2020
    ]
]);

$phpipamInventory->setDefaults([
     'port'     => 22,
     'username' => "defaultusername",
     'password' => "defaultpassword"
]);

$mikodo = new \Epiecs\Mikodo\Mikodo();

$mikodo->inventory($phpipamInventory->getGroups(['Switch']));

Nornir库存

如果您喜欢Nornir,您很可能已经有了Nornir库存。在我的项目文件夹中,我有以下目录结构

└── inventory
    ├── defaults.yaml
    ├── groups.yaml
    └── hosts.yaml

您可以使用NornirInventory提供者加载此目录,并像使用基本库存一样查询它。所需文件仅为hosts.yaml文件

为了简化起见,我将使用以下库存作为参考。虽然简短,但足以作为一个示例,向您展示所有库存组件的优先级。

default.yaml

---
port: 22
username: my_default_username
password: my_default_password

groups.yaml

---
core_switches:
    device_type: junos

lab_switches:
    device_type: cisco_ios
    port: 2000

hosts.yaml

---
Hostname_1:
    hostname: 192.168.0.1
    groups:
        - core_switches
Hostname_2:
    hostname: 192.168.0.1
    groups:
        - core_switches
Hostname_3:
    hostname: 172.16.2.10
    groups:
        - lab_switches
Hostname_4:
    hostname: 172.16.2.20
    groups:
        - lab_switches
Hostname_5:
    hostname: 172.16.2.30
    groups:
        - lab_switches
Hostname_6:
    hostname: 172.16.2.50
    groups:
        - lab_switches
        - core_switches
$nornirInventory = new \Epiecs\Mikodo\InventoryProviders\NornirInventory(__DIR__ . DIRECTORY_SEPARATOR . 'inventory');

$mikodo = new \Epiecs\Mikodo\Mikodo();

$mikodo->inventory($nornirInventory->getGroups(['lab_switches', 'core_switches']));