VMWare vSphere List VM's with PHP using webservices

感謝 Vmware 大方提供免費的 ESXi 供大家使用,目前幾乎所有的伺服器都轉成 VM 了。

隨著 ESXi 和 VM 的數量增多,常常不曉得那個 VM 在那個 host 上,要一個一個 host 連進去找。其實, 可透過 ESXi 的開放的 SOAP 界面取得資訊。在網路上找到使用 PHP + SoapClient 來取得 VM 訊息的程式,經稍作修改,列表如下,謹供大家參考。

<?php
define('DEBUG', false);  // set to true is you want raw results to be displayed
$serverIP = "10.1.1.139"; // Your VC IP address or dns name
$username = "myid";
$password = "mypasswd";
class soapclientd extends SoapClient
{
    public $action = false;
    public function __construct($wsdl, $options = [])
    {
        try{
            parent::__construct($wsdl, $options);
        } catch (Exception $e) {
            echo '<pre>'.$e.'</pre>';
            exit;
        }
    }
    public function __doRequest($request, $location, $action, $version, $one_way = 0)
    {
        if (DEBUG){
           echo '<pre>' . htmlspecialchars(
                    str_replace(
                        ['<ns', '></'],
                        [PHP_EOL . '<ns', '>'.PHP_EOL.'</'],
                        $request)
                    ) . '</pre>';
        }
        $resp = parent::__doRequest($request, $location, $action, $version, $one_way);
        if (DEBUG) {
            echo 'res: <pre>' . htmlspecialchars(
                    str_replace(
                        ['<ns', '></'],
                        [PHP_EOL . '<ns', '>'.PHP_EOL.'</'],
                        $resp)
                    ) . '</pre>';
        }
        return $resp;
    }
}
$client = new soapclientd (
                    "https://{$serverIP}/sdk/vimService.wsdl",
                    ['location' => "https://{$serverIP}/sdk",
                     'trace' => 1
                    ]
             );
try
{
    $request = [
        '_this' => [ '_' => 'ServiceInstance',
                     'type' => 'ServiceInstance'
                   ]
        ];
    $response = $client->__soapCall(
                            'RetrieveServiceContent',
                            [$request]
                        );
} catch (Exception $e)
{
    echo $e->getMessage();
    exit;
}
$ret = $response->returnval;
if (DEBUG) {
  echo '<pre>'.print_r($ret, true).'</pre>';
}
$sm = $ret->sessionManager;
// 內容等同如下
// $sm = ['_' => 'ha-sessionmgr',
//        'type' => 'SessionManager'];
try
{
    $request = [
        '_this' => $sm, // $ret->sessionManager;
        'userName' => $username,
        'password' => $password,
    ];
    $response = $client->__soapCall('Login', [$request]);
} catch (Exception $e)
{
    echo $e->getMessage();
    exit;
}
if (DEBUG) {
  echo 'response: <pre>'.print_r($response, true).'</pre>';
}
$ss1 = new soapvar(['name' => 'FolderTraversalSpec'],
            SOAP_ENC_OBJECT, null, null, 'selectSet', null
        );
$ss2 = new soapvar(['name' => 'DataCenterVMTraversalSpec'],
            SOAP_ENC_OBJECT, null, null, 'selectSet', null
        );
$a = ['name' => 'FolderTraversalSpec',
      'type' => 'Folder',
      'path' => 'childEntity',
      'skip' => false,
      $ss1, $ss2
     ];
$ss = new soapvar(['name' => 'FolderTraversalSpec'],
            SOAP_ENC_OBJECT, null, null, 'selectSet', null);
$b = ['name' => 'DataCenterVMTraversalSpec',
      'type' => 'Datacenter',
      'path' => 'vmFolder',
      'skip' => false,
      $ss
     ];
$res = null;
//
// 'config' : 取回 config 之下所有的 information
// 'config.hardware.numCPU' : 則只取回 CPU 的 information
//
$pathSet = [
         'name', 'guest.ipAddress',
         'guest.guestState', 'runtime.powerState',
         'config', 'config.annotation',
         'config.hardware.numCPU',
         'config.hardware.memoryMB'
      ];
try
{
    $request = [
        '_this' => $ret->propertyCollector,
        'specSet' => [
            'propSet' => [
                ['type' => 'VirtualMachine',
                 'all' => 0,
                 'pathSet' => $pathSet,
                ],
            ],
            'objectSet' => [
                'obj' => $ret->rootFolder,
                'skip' => false,
                'selectSet' => [
                    new soapvar($a, SOAP_ENC_OBJECT, 'TraversalSpec'),
                    new soapvar($b, SOAP_ENC_OBJECT, 'TraversalSpec'),
                ],
            ]
        ]
    ];
    $res = $client->__soapCall('RetrieveProperties', [$request]);
} catch (Exception $e)
{
    echo 'Error: '.$e->getMessage();
}
echo 'VMs: <pre>'.print_r($res, true).'</pre>';