You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP调用ESXi SOAP API登录成功后Logout失败求助

问题:PHP SOAP调用ESXi时Logout失败,提示对象已删除

我正在编写PHP脚本重置ESXi主机「myhost」的root密码,旧密码存储在$oldpass,新密码存储在$newpass,测试环境为全新部署的嵌套ESXi 8.0.2b。折腾数月,尝试多种方法甚至AI工具仍未解决问题。

据了解,实现该操作需通过SOAP调用直接连接ESXi,以root身份认证到SOAP代理。我基于SoapClient编写的代码如下:

class ESXI_SOAP extends SoapClient {
private $ServiceInstance;
private $session;
 
public function __construct( $url , $user , $pass ) {
  try {
   parent::__construct( $url . '/vimService.wsdl' ,
    [ 'trace'      => true
    , 'exceptions' => true
    , "location"   => $url
    , 'stream_context' => stream_context_create(
       [ 'ssl' => [ 'verify_peer' => false
       , 'verify_peer_name' => false , 'allow_self_signed' => true ]
       ]
      )
    ]
   ) ;

   $this->ServiceInstance =
    $this->RetrieveServiceContent(
     [ "_this" => new SoapVar( "ServiceInstance", XSD_STRING , "ServiceInstance" ) ]
    )->returnval ;

   $this->session =
    $this->Login(
     [ '_this'    => $this->ServiceInstance->sessionManager
     , 'userName' => $user
     , 'password' => $pass
     ]
    )->returnval ;
   echo "login successful\n\nServiceInstance:\n" ;
   var_dump($this->ServiceInstance);
   echo "\nSession:\n";
   var_dump( $this->session ) ;
  } catch( Exception $e ) {
   printf("%s\n",$e->__toString() ) ;
   return false ;
  }

  echo $this->__getLastResponseHeaders();

  /*** Logout ***/
  try{
   echo "attempting logout()\n";
   $result = $this->Logout(
    [ "_this" => $this->ServiceInstance
    ]
   ) ;
  } catch (Exception $e) {
   printf("%s\n",$e->__toString());
   return false;
  }
  echo "logout successful\n";
}

登录操作成功,但会话似乎立即超时,Session对象无法使用,甚至执行即时Logout也报错:

login successful

ServiceInstance:
object(stdClass)#4 (26) {
  (...)
  ["about"]=>
  object(stdClass)#8 (14) {
    ["name"]=>
    string(11) "VMware ESXi"
    ["fullName"]=>
    string(32) "VMware ESXi 7.0.3 build-20328353"
    ["vendor"]=>
    string(12) "VMware, Inc."
    ["version"]=>
    string(5) "7.0.3"
    ["patchLevel"]=>
    string(4) "0.55"
    ["build"]=>
    string(8) "20328353"
    ["localeVersion"]=>
    string(4) "INTL"
    ["localeBuild"]=>
    string(3) "000"
    ["osType"]=>
    string(9) "vmnix-x86"
    ["productLineId"]=>
    string(11) "embeddedEsx"
    ["apiType"]=>
    string(9) "HostAgent"
    ["apiVersion"]=>
    string(7) "7.0.3.0"
    ["licenseProductName"]=>
    string(17) "VMware ESX Server"
    ["licenseProductVersion"]=>
    string(3) "7.0"
  }
(...)
}
 
Session:
object(stdClass)#2 (11) {
  ["key"]=>string(36) "5223f016-7f92-c38c-0870-6fb25219ef71"
  ["userName"]=>string(4) "root"
  ["fullName"]=>string(13) "Administrator"
  ["loginTime"]=>string(27) "2024-07-11T19:26:13.116449Z"
  ["lastActiveTime"]=>string(27) "2024-07-11T19:26:13.116466Z"
  ["locale"]=>string(2) "en"
  ["messageLocale"]=>string(2) "en"
 ["extensionSession"]=>bool(false)
  ["ipAddress"]=>string(10) "(redacted)"
  ["userAgent"]=>string(26) "PHP-SOAP/7.4.3-4ubuntu2.23"
  ["callCount"]=>int(0)
}
HTTP/1.1 200 OK
Date: Thu, 11 Jul 2024 19:26:13 GMT
Set-Cookie: vmware_soap_session="4f71046b2b4285b476a11ca548f61a690bba1a89"; Path=/; HttpOnly; Secure;
Cache-Control: no-cache
Connection: Keep-Alive
Content-Type: text/xml; charset=utf-8
X-Frame-Options: DENY
Content-Length: 815

attempting logout()
SoapFault exception: [ServerFaultCode] The object 'vmodl.ManagedObject:' has already been deleted or has not been completely created in /var/www/html/interfaces/RootPasswordChange/SOAP.php:45
Stack trace:
#0 /var/www/html/interfaces/RootPasswordChange/SOAP.php(45): SoapClient->__call()
#1 /var/www/html/interfaces/RootPasswordChange/SOAP.php(73): ESXI_SOAP->__construct()
#2 /var/www/html/interfaces/RootPasswordChange/SOAP.php(90): ESXI_Test()

我怀疑是$ServiceInstance的存储或传递给Logout方法时出现问题,目前仅需实现可正常运行的$this->Logout()。


解决方案

问题出在Logout方法的调用参数错误:必须传入SessionManager的ManagedObject引用,而非整个ServiceInstance对象。

ESXi的SOAP API中,Logout是SessionManager对象的专属方法,你登录时已经正确使用了$this->ServiceInstance->sessionManager作为Login方法的_this参数,注销时需要保持一致。

修正后的Logout代码段:

/*** Logout ***/
try{
 echo "attempting logout()\n";
 $result = $this->Logout(
  [ "_this" => $this->ServiceInstance->sessionManager ]
 ) ;
} catch (Exception $e) {
 printf("%s\n",$e->__toString());
 return false;
}
echo "logout successful\n";

补充说明

  • 你看到的"会话立即超时"并非真的超时,只是因为调用Logout时传入了错误的对象引用,导致API无法识别有效会话
  • 修正参数后,即可正常注销已建立的SOAP会话,后续也能基于该会话执行密码重置等其他操作

内容的提问来源于stack exchange,提问作者догонят

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:54:53