From 56353bcc112e0c1e720fa4ab273d005a846b097c Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Fri, 9 Sep 2022 13:12:35 +0300 Subject: [PATCH 01/46] feat: new methods --- src/Data/SoapData.php | 8 +- src/Traits/Rest/VcenterApis.php | 11 +-- src/Traits/Soap/SoapFileApis.php | 51 ++++++++++--- src/Traits/Soap/SoapVmApis.php | 125 ++++++++++++++++++++----------- 4 files changed, 134 insertions(+), 61 deletions(-) diff --git a/src/Data/SoapData.php b/src/Data/SoapData.php index 79e01b8..7f79428 100644 --- a/src/Data/SoapData.php +++ b/src/Data/SoapData.php @@ -4,7 +4,7 @@ class SoapData { - public function findVmBody(string $vmId, string $pathSet = ''): array + public function objectInfoBody(string $objectId, string $objectType, string $pathSet = ''): array { return [ '_this' => [ @@ -13,14 +13,14 @@ public function findVmBody(string $vmId, string $pathSet = ''): array ], 'specSet' => [ 'propSet' => [ - 'type' => 'VirtualMachine', + 'type' => $objectType, 'all' => !$pathSet, 'pathSet' => $pathSet ], 'objectSet' => [ 'obj' => [ - '_' => $vmId, - 'type' => 'VirtualMachine' + '_' => $objectId, + 'type' => $objectType ] ] ] diff --git a/src/Traits/Rest/VcenterApis.php b/src/Traits/Rest/VcenterApis.php index 1af6b2f..753ba62 100644 --- a/src/Traits/Rest/VcenterApis.php +++ b/src/Traits/Rest/VcenterApis.php @@ -13,9 +13,10 @@ public function createVm() // TODO: } - public function getVmList() + public function getVmList(array $requestBody) { - return $this->request('get', '/api/vcenter/vm'); + $query = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', http_build_query($requestBody, null, '&')); + return $this->request('get', '/api/vcenter/vm', ['query' => $query]); } public function getVmInfo(string $vmId) @@ -23,14 +24,14 @@ public function getVmInfo(string $vmId) return $this->request('get', "/api/vcenter/vm/$vmId"); } - public function deleteVm() + public function deleteVm(string $vmId) { - // TODO: + return $this->request('delete', "/api/vcenter/vm/$vmId"); } public function cloneVm(array $requestBody) { - return $this->request('post', '/api/vcenter/vm?action=clone', ['body' => $requestBody]); + return $this->request('post', '/api/vcenter/vm?action=clone', ['json' => $requestBody]); } public function registerVm() diff --git a/src/Traits/Soap/SoapFileApis.php b/src/Traits/Soap/SoapFileApis.php index 0b089a4..78035d8 100644 --- a/src/Traits/Soap/SoapFileApis.php +++ b/src/Traits/Soap/SoapFileApis.php @@ -16,19 +16,19 @@ public function initiateFileTransferToGuest( string $username, string $password, string $vmId, - ?string $scriptPath, + ?string $localFilePath, string $guestFilePath, array $params = [], - string $script = null + string $data = null ): void { - if ($scriptPath) { - $fullScriptPath = base_path($scriptPath); - $script = file_get_contents($fullScriptPath); + if ($localFilePath) { + $fullScriptPath = base_path($localFilePath); + $data = file_get_contents($fullScriptPath); } if (count($params) > 0) { foreach ($params as $key => $value) { - $script = str_replace('{'.$key.'}', $value, $script); + $data = str_replace('{'.$key.'}', $value, $data); } } @@ -43,13 +43,13 @@ public function initiateFileTransferToGuest( ], 'auth' => [ '@type' => 'NamePasswordAuthentication', - 'interactiveSession' => true, + 'interactiveSession' => false, 'username' => $username, 'password' => $password ], 'guestFilePath' => "{$guestFilePath}", 'fileAttributes' => new \stdClass(), - 'fileSize' => strlen($script), + 'fileSize' => strlen($data), 'overwrite' => true ]; @@ -61,7 +61,7 @@ public function initiateFileTransferToGuest( if (is_string($response->returnval) && substr($response->returnval, 0, 4) !== 'http') { throw new Exception('File transfer invalid response url'); } - $client->request('PUT', $response->returnval, ['body' => $script]); + $client->request('PUT', $response->returnval, ['body' => $data]); } catch (Exception $e) { throw new Exception($e->getMessage()); } @@ -156,4 +156,37 @@ public function startProgramInGuest( return $this->soapClient->StartProgramInGuest($this->arrayToSoapVar($body)); } + + public function createTaskCollectorForVm(string $vmId) + { + $body = [ + '_this' => [ + '_' => 'TaskManager', + 'type' => 'TaskManager' + ], + 'filter' => [ + 'entity' => [ + 'entity' => [ + 'type' => 'VirtualMachine', + '_' => $vmId + ], + 'recursion' => 'self' + ] + ] + ]; + + return $this->soapClient->CreateCollectorForTasks($body); + } + + public function destroyTaskCollector(string $taskCollectorId) + { + $body = [ + '_this' => [ + 'type' => 'HistoryCollector', + '_' => $taskCollectorId + ] + ]; + + return $this->soapClient->DestroyCollector($body); + } } diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index fbaaf0e..4d292be 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -10,27 +10,9 @@ trait SoapVmApis use SoapRequest; use SoapTransform; - public function getVmInfo(string $vmId, string $pathSet = '') + public function getObjectInfo(string $objectId, string $objectType, string $pathSet = '') { - $body = [ - '_this' => [ - '_' => 'propertyCollector', - 'type' => 'PropertyCollector' - ], - 'specSet' => [ - 'propSet' => [ - 'type' => 'VirtualMachine', - 'all' => !$pathSet, - 'pathSet' => $pathSet - ], - 'objectSet' => [ - 'obj' => [ - '_' => $vmId, - 'type' => 'VirtualMachine' - ] - ] - ] - ]; + $body = $this->data->objectInfoBody($objectId, $objectType, $pathSet); $result = $this->soapClient->RetrieveProperties($body); @@ -39,33 +21,34 @@ public function getVmInfo(string $vmId, string $pathSet = '') : $this->transformPropSet($result->returnval->propSet); } + public function getVmInfo(string $vmId, string $pathSet = '') + { + return $this->getObjectInfo($vmId, 'VirtualMachine', $pathSet); + } + public function getTaskInfo(string $taskId, string $pathSet = '') { - $body = [ - '_this' => [ - '_' => 'propertyCollector', - 'type' => 'PropertyCollector' - ], - 'specSet' => [ - 'propSet' => [ - 'type' => 'Task', - 'all' => !$pathSet, - 'pathSet' => $pathSet - ], - 'objectSet' => [ - 'obj' => [ - '_' => $taskId, - 'type' => 'Task' - ] - ] - ] - ]; + return $this->getObjectInfo($taskId, 'Task', $pathSet); + } - $result = $this->soapClient->RetrieveProperties($body); + public function getClusterComputeResourceInfo(string $clusterComputeResourceId, string $pathSet = '') + { + return $this->getObjectInfo($clusterComputeResourceId, 'ClusterComputeResource', $pathSet); + } - return $pathSet - ? ($result->returnval->propSet->val ?? null) - : $this->transformPropSet($result->returnval->propSet); + public function getDatastoreInfo(string $datastore, string $pathSet = '') + { + return $this->getObjectInfo($datastore, 'Datastore', $pathSet); + } + + public function getSnapshotInfo(string $taskId, string $pathSet = '') + { + return $this->getObjectInfo($taskId, 'VirtualMachineSnapshot', $pathSet); + } + + public function getTaskHistoryCollectorInfo(string $taskHistoryCollectorId) + { + return $this->getObjectInfo($taskHistoryCollectorId, 'TaskHistoryCollector'); } public function reconfigVmTask(string $vmId, array $requestBody) @@ -287,4 +270,60 @@ public function createSnapshot( return $this->vmRequest('CreateSnapshot_Task', $vmId, $body); } + + public function revertSnapshot(string $snapshopId) + { + $body = [ + '_this' => [ + '_' => $snapshopId, + 'type' => 'VirtualMachineSnapshot' + ], + ]; + + return $this->soapClient->RevertToSnapshot_Task($body); + } + + public function removeSnapshot(string $snapshopId, bool $removeChildren = true, bool $consolidate = true) + { + $body = [ + '_this' => [ + '_' => $snapshopId, + 'type' => 'VirtualMachineSnapshot' + ], + 'removeChildren' => $removeChildren, + '$consolidate' => $consolidate + ]; + + return $this->soapClient->RemoveSnapshot_Task($body); + } + + public function queryPerf( + string $vmId, + ?string $startTime = null, + ?string $endTime = null, + int $intervalId = 20, + ?int $maxSample = null, + array $metricIds = [] + ) { + $body = [ + '_this' => [ + '_' => 'PerfMgr', + 'type' => 'PerformanceManager' + ], + 'querySpec' => [ + 'entity' => [ + '_' => $vmId, + 'type' => 'VirtualMachine' + ], + 'startTime' => $startTime, + 'endTime' => $endTime, + 'maxSample' => $maxSample, + 'metricId' => array_map(fn(int $id): array => ['counterId' => $id, 'instance' => ''], $metricIds), + 'intervalId' => $intervalId, + 'format' => 'normal' + ] + ]; + + return $this->soapClient->QueryPerf($body); + } } From d9df1c043e9eceb72760c308ca4aa94a54a1abd4 Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Fri, 9 Sep 2022 10:20:48 +0000 Subject: [PATCH 02/46] Fix styling --- src/Data/SoapData.php | 8 ++++---- src/Traits/Rest/VcenterApis.php | 1 + src/Traits/Soap/SoapFileApis.php | 12 ++++++------ src/Traits/Soap/SoapVmApis.php | 16 ++++++++-------- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/Data/SoapData.php b/src/Data/SoapData.php index 9b65f43..19023d0 100644 --- a/src/Data/SoapData.php +++ b/src/Data/SoapData.php @@ -14,16 +14,16 @@ public function objectInfoBody(string $objectId, string $objectType, string $pat 'specSet' => [ 'propSet' => [ 'type' => $objectType, - 'all' => !$pathSet, + 'all' => ! $pathSet, 'pathSet' => $pathSet, ], 'objectSet' => [ 'obj' => [ '_' => $objectId, 'type' => $objectType, - ] - ] - ] + ], + ], + ], ]; } diff --git a/src/Traits/Rest/VcenterApis.php b/src/Traits/Rest/VcenterApis.php index 753ba62..d27cf4e 100644 --- a/src/Traits/Rest/VcenterApis.php +++ b/src/Traits/Rest/VcenterApis.php @@ -16,6 +16,7 @@ public function createVm() public function getVmList(array $requestBody) { $query = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', http_build_query($requestBody, null, '&')); + return $this->request('get', '/api/vcenter/vm', ['query' => $query]); } diff --git a/src/Traits/Soap/SoapFileApis.php b/src/Traits/Soap/SoapFileApis.php index 43ff4d7..9f8ebe1 100644 --- a/src/Traits/Soap/SoapFileApis.php +++ b/src/Traits/Soap/SoapFileApis.php @@ -171,8 +171,8 @@ public function createTaskCollectorForVm(string $vmId) '_' => $vmId, ], 'recursion' => 'self', - ] - ] + ], + ], ]; return $this->soapClient->CreateCollectorForTasks($body); @@ -181,10 +181,10 @@ public function createTaskCollectorForVm(string $vmId) public function destroyTaskCollector(string $taskCollectorId) { $body = [ - '_this' => [ - 'type' => 'HistoryCollector', - '_' => $taskCollectorId - ] + '_this' => [ + 'type' => 'HistoryCollector', + '_' => $taskCollectorId, + ], ]; return $this->soapClient->DestroyCollector($body); diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index df5e7f5..3d22198 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -276,7 +276,7 @@ public function revertSnapshot(string $snapshopId) $body = [ '_this' => [ '_' => $snapshopId, - 'type' => 'VirtualMachineSnapshot' + 'type' => 'VirtualMachineSnapshot', ], ]; @@ -288,10 +288,10 @@ public function removeSnapshot(string $snapshopId, bool $removeChildren = true, $body = [ '_this' => [ '_' => $snapshopId, - 'type' => 'VirtualMachineSnapshot' + 'type' => 'VirtualMachineSnapshot', ], 'removeChildren' => $removeChildren, - '$consolidate' => $consolidate + '$consolidate' => $consolidate, ]; return $this->soapClient->RemoveSnapshot_Task($body); @@ -308,20 +308,20 @@ public function queryPerf( $body = [ '_this' => [ '_' => 'PerfMgr', - 'type' => 'PerformanceManager' + 'type' => 'PerformanceManager', ], 'querySpec' => [ 'entity' => [ '_' => $vmId, - 'type' => 'VirtualMachine' + 'type' => 'VirtualMachine', ], 'startTime' => $startTime, 'endTime' => $endTime, 'maxSample' => $maxSample, - 'metricId' => array_map(fn(int $id): array => ['counterId' => $id, 'instance' => ''], $metricIds), + 'metricId' => array_map(fn (int $id): array => ['counterId' => $id, 'instance' => ''], $metricIds), 'intervalId' => $intervalId, - 'format' => 'normal' - ] + 'format' => 'normal', + ], ]; return $this->soapClient->QueryPerf($body); From 112decb66c3df1e44cc14ad657c691b719a75224 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Tue, 20 Sep 2022 11:40:44 +0300 Subject: [PATCH 03/46] feat: new methods --- src/Data/SoapData.php | 16 ++ .../{SoapFileApis.php => SoapGuestApis.php} | 103 +++++++++- src/Traits/Soap/SoapStorageApis.php | 94 +++++++++ src/Traits/Soap/SoapVmApis.php | 187 ++++++++++++++++-- src/Transform/SoapTransform.php | 4 +- src/VcenterSoapClient.php | 6 +- 6 files changed, 394 insertions(+), 16 deletions(-) rename src/Traits/Soap/{SoapFileApis.php => SoapGuestApis.php} (65%) create mode 100644 src/Traits/Soap/SoapStorageApis.php diff --git a/src/Data/SoapData.php b/src/Data/SoapData.php index 19023d0..3bfda94 100644 --- a/src/Data/SoapData.php +++ b/src/Data/SoapData.php @@ -82,6 +82,22 @@ public function editVirtualDiskSpec(array $params): array ]; } + public function addBlockStorageSpec(string $blockStoragePath, int $capacityInKB, int $controllerKey = 1000) + { + return [ + '@type' => 'VirtualDisk', + 'key' => -1, + 'backing' => [ + '@type' => 'VirtualDiskFlatVer2BackingInfo', + 'fileName' => $blockStoragePath, + 'diskMode' => 'independent_persistent', + ], + 'controllerKey' => $controllerKey, + 'unitNumber' => -1, + 'capacityInKB' => $capacityInKB, + ]; + } + public function addNetworkSpec( string $switchUuid, string $portgroupKey, diff --git a/src/Traits/Soap/SoapFileApis.php b/src/Traits/Soap/SoapGuestApis.php similarity index 65% rename from src/Traits/Soap/SoapFileApis.php rename to src/Traits/Soap/SoapGuestApis.php index 9f8ebe1..c2d4617 100644 --- a/src/Traits/Soap/SoapFileApis.php +++ b/src/Traits/Soap/SoapGuestApis.php @@ -7,7 +7,7 @@ use Xelon\VmWareClient\Requests\SoapRequest; use Xelon\VmWareClient\Transform\SoapTransform; -trait SoapFileApis +trait SoapGuestApis { use SoapRequest; use SoapTransform; @@ -126,6 +126,33 @@ public function deleteDirectoryInGuest( return $this->soapClient->DeleteDirectoryInGuest($this->arrayToSoapVar($body)); } + public function deleteFileInGuest( + string $username, + string $password, + string $vmId, + string $filePath + ) { + $body = [ + '_this' => [ + 'type' => 'GuestFileManager', + '_' => 'guestOperationsFileManager', + ], + 'vm' => [ + 'type' => 'VirtualMachine', + '_' => $vmId, + ], + 'auth' => [ + '@type' => 'NamePasswordAuthentication', + 'interactiveSession' => false, + 'username' => $username, + 'password' => $password, + ], + 'filePath' => $filePath, + ]; + + return $this->soapClient->DeleteFileInGuest($this->arrayToSoapVar($body)); + } + public function startProgramInGuest( string $username, string $password, @@ -189,4 +216,78 @@ public function destroyTaskCollector(string $taskCollectorId) return $this->soapClient->DestroyCollector($body); } + + public function getListFilesInGuest( + string $username, + string $password, + string $vmId, + string $filePath + ) { + $body = [ + '_this' => [ + 'type' => 'GuestFileManager', + '_' => 'guestOperationsFileManager', + ], + 'vm' => [ + 'type' => 'VirtualMachine', + '_' => $vmId, + ], + 'auth' => [ + '@type' => 'NamePasswordAuthentication', + 'interactiveSession' => false, + 'username' => $username, + 'password' => $password, + ], + 'filePath' => $filePath, + ]; + + return $this->soapClient->ListFilesInGuest($this->arrayToSoapVar($body)); + } + + public function getListProcessInGuest( + string $username, + string $password, + string $vmId + ) { + $body = [ + '_this' => [ + 'type' => 'GuestFileManager', + '_' => 'guestOperationsFileManager', + ], + 'vm' => [ + 'type' => 'VirtualMachine', + '_' => $vmId, + ], + 'auth' => [ + '@type' => 'NamePasswordAuthentication', + 'interactiveSession' => false, + 'username' => $username, + 'password' => $password, + ], + ]; + + return $this->soapClient->ListProcessesInGuest($this->arrayToSoapVar($body)); + } + + public function validateCredentialsInGuest(string $username, string $password, string $vmId) + { + $body = [ + '_this' => [ + 'type' => 'GuestAuthManager', + '_' => 'guestOperationsAuthManager', + ], + 'vm' => [ + 'type' => 'VirtualMachine', + '_' => $vmId, + ], + 'auth' => [ + '@type' => 'NamePasswordAuthentication', + 'interactiveSession' => false, + 'username' => $username, + 'password' => $password, + ], + ]; + + return $this->soapClient->ValidateCredentialsInGuest($this->arrayToSoapVar($body)); + } } diff --git a/src/Traits/Soap/SoapStorageApis.php b/src/Traits/Soap/SoapStorageApis.php new file mode 100644 index 0000000..0ee23df --- /dev/null +++ b/src/Traits/Soap/SoapStorageApis.php @@ -0,0 +1,94 @@ + [ + 'id' => $vstorageId, + ], + '_this' => [ + 'type' => 'VcenterVStorageObjectManager', + '_' => 'VStorageObjectManager', + ], + 'datastore' => [ + 'type' => 'Datastore', + '_' => $datastore + ], + ]; + + return $this->soapClient->RetrieveVStorageObject($this->arrayToSoapVar($body)); + } + + public function deleteVcenterVStorageInfo(string $vstorageId, string $datastore) + { + $body = [ + 'id' => [ + 'id' => $vstorageId, + ], + '_this' => [ + 'type' => 'VcenterVStorageObjectManager', + '_' => 'VStorageObjectManager', + ], + 'datastore' => [ + 'type' => 'Datastore', + '_' => $datastore + ], + ]; + + return $this->soapClient->DeleteVStorageObject_Task($this->arrayToSoapVar($body)); + } + + public function createVStorage(string $name, int $capacityInMB, string $datastore, bool $keepAfterDeleteVm = true) + { + $body = [ + '_this' => [ + 'type' => 'VcenterVStorageObjectManager', + '_' => 'VStorageObjectManager', + ], + 'spec' => [ + 'name' => $name, + 'keepAfterDeleteVm' => $keepAfterDeleteVm, + 'backingSpec' => [ + '@type' => 'VslmCreateSpecDiskFileBackingSpec', + 'datastore' => [ + 'type' => 'Datastore', + '_' => $datastore + ], + ], + 'capacityInMB' => $capacityInMB, + ] + ]; + + return $this->soapClient->CreateDisk_Task($this->arrayToSoapVar($body)); + } + + public function extendVStorage(string $vstorageId, string $datastore, int $newCapacityInMB) + { + $body = [ + '_this' => [ + 'type' => 'VcenterVStorageObjectManager', + '_' => 'VStorageObjectManager', + ], + 'id' => [ + 'id' => $vstorageId, + ], + 'datastore' => [ + 'type' => 'Datastore', + '_' => $datastore + ], + 'newCapacityInMB' => $newCapacityInMB, + ]; + + return $this->soapClient->ExtendDisk_Task($this->arrayToSoapVar($body)); + } +} diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index 3d22198..8863fab 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -51,6 +51,20 @@ public function getTaskHistoryCollectorInfo(string $taskHistoryCollectorId) return $this->getObjectInfo($taskHistoryCollectorId, 'TaskHistoryCollector'); } + public function getResourcePoolInfo(?string $resourcePoolId, string $pathSet = '') + { + if (!$resourcePoolId) { + return []; + } + + return $this->getObjectInfo($resourcePoolId, 'ResourcePool', $pathSet); + } + + public function getDistributedVirtualPortgroupInfo(string $distributedVirtualPortgroupId, string $pathSet = '') + { + return $this->getObjectInfo($distributedVirtualPortgroupId, 'DistributedVirtualPortgroup', $pathSet); + } + public function reconfigVmTask(string $vmId, array $requestBody) { return $this->vmRequest('ReconfigVM_Task', $vmId, $this->arrayToSoapVar($requestBody)); @@ -76,12 +90,14 @@ public function cloneVmTask(string $vmId, array $params) ], ], 'template' => $params['spec']['template'] ?? false, - 'config' => [ - 'numCPUs' => $params['spec']['config']['numCPUs'], - 'numCoresPerSocket' => $params['spec']['config']['numCoresPerSocket'], - 'memoryMB' => $params['spec']['config']['memoryMB'], - 'deviceChange' => $params['spec']['config']['deviceChange'] ?? null, - ], + 'config' => isset($params['spec']['config']) + ? [ + 'numCPUs' => $params['spec']['config']['numCPUs'], + 'numCoresPerSocket' => $params['spec']['config']['numCoresPerSocket'], + 'memoryMB' => $params['spec']['config']['memoryMB'], + 'deviceChange' => $params['spec']['config']['deviceChange'] ?? null, + ] + : null, 'customization' => $params['spec']['customization'] ?? null, 'powerOn' => $params['spec']['powerOn'] ?? true, /*'bootOptions' => [ @@ -135,6 +151,22 @@ public function editDisk(string $vmId, array $params) return $this->reconfigVmTask($vmId, $body); } + public function addPersistantDisk(string $vmId, string $blockStoragePath, int $capacityInKB, int $controllerKey = 1000) + { + $body = [ + 'spec' => [ + '@type' => 'VirtualMachineConfigSpec', + 'deviceChange' => [ + '@type' => 'VirtualDeviceConfigSpec', + 'operation' => 'add', + 'device' => $this->data->addBlockStorageSpec($blockStoragePath, $capacityInKB, $controllerKey), + ], + ], + ]; + + return $this->reconfigVmTask($vmId, $this->arrayToSoapVar($body)); + } + public function addNetwork(string $vmId, int $unitNumber, string $portgroupKey, string $switchUuid) { $body = [ @@ -188,6 +220,111 @@ public function addSasController(string $vmId) return $this->reconfigVmTask($vmId, $body); } + public function changeDVPortgroupSpeed( + string $distributedVirtualPortgroupId, + string $configVersion, + int $speed + ) { + $body = [ + '_this' => [ + '_' => $distributedVirtualPortgroupId, + 'type' => 'DistributedVirtualPortgroup', + ], + 'spec' => [ + '@type' => 'DVPortgroupConfigSpec', + 'configVersion' => $configVersion, + 'defaultPortConfig' => [ + '@type' => 'DVPortSetting', + 'inShapingPolicy' => [ + '@type' => 'DVSTrafficShapingPolicy', + 'inherited' => false, + 'enabled' => [ + 'inherited' => false, + 'value' => true, + ], + 'averageBandwidth' => [ + 'inherited' => false, + 'value' => $speed, + ], + 'peakBandwidth' => [ + 'inherited' => false, + 'value' => $speed, + ], + 'burstSize' => [ + 'inherited' => false, + 'value' => $speed, + ] + ], + 'outShapingPolicy' => [ + '@type' => 'DVSTrafficShapingPolicy', + 'inherited' => false, + 'enabled' => [ + 'inherited' => false, + 'value' => true, + ], + 'averageBandwidth' => [ + 'inherited' => false, + 'value' => $speed, + ], + 'peakBandwidth' => [ + 'inherited' => false, + 'value' => $speed, + ], + 'burstSize' => [ + 'inherited' => false, + 'value' => $speed, + ] + ] + ] + ] + ]; + + return $this->soapClient->ReconfigureDVPortgroup_Task($this->arrayToSoapVar($body)); + } + + public function reconfigureComputeResource( + string $clusterComputerResourceId, + string $name, + array $vmIds + ) { + $body = [ + '_this' => [ + '_' => $clusterComputerResourceId, + 'type' => 'ComputeResource' + ], + 'spec' => [ + '@type' => 'ClusterConfigSpecEx', + 'drsConfig' => [ + '@type' => 'ClusterDrsConfigInfo' + ], + 'rulesSpec' => [ + '@type' => 'ClusterRuleSpec', + 'operation' => 'add', + 'info' => [ + '@type' => 'ClusterAntiAffinityRuleSpec', + 'enabled' => true, + 'name' => $name, + 'userCreated' => true, + ] + ], + 'dpmConfig' => [ + '@type' => 'ClusterDpmConfigInfo' + ] + + ], + 'modify' => false + ]; + + foreach ($vmIds as $vmId) { + $body['spec']['rulesSpec']['info']['vm'][] = [ + '_' => $vmId, + 'type' => 'VirtualMachine' + ]; + } + + return $this->soapClient->ReconfigureComputeResource_Task($this->arrayToSoapVar($body)); + } + public function mountIso(string $vmId, string $fileName, int $key, int $controllerKey, string $datastore) { $body = [ @@ -254,6 +391,18 @@ public function createFolder(string $parentFolder, string $name) return $this->soapClient->CreateFolder($body); } + public function deleteFolder(string $folderId) + { + $body = [ + '_this' => [ + '_' => $folderId, + 'type' => 'Folder', + ], + ]; + + return $this->soapClient->Destroy_Task($body); + } + public function createSnapshot( string $vmId, string $name, @@ -298,12 +447,13 @@ public function removeSnapshot(string $snapshopId, bool $removeChildren = true, } public function queryPerf( - string $vmId, + string $objectId, ?string $startTime = null, ?string $endTime = null, int $intervalId = 20, ?int $maxSample = null, - array $metricIds = [] + array $metricIds = [], + string $entity = 'VirtualMachine' ) { $body = [ '_this' => [ @@ -312,8 +462,8 @@ public function queryPerf( ], 'querySpec' => [ 'entity' => [ - '_' => $vmId, - 'type' => 'VirtualMachine', + '_' => $objectId, + 'type' => $entity, ], 'startTime' => $startTime, 'endTime' => $endTime, @@ -321,9 +471,24 @@ public function queryPerf( 'metricId' => array_map(fn (int $id): array => ['counterId' => $id, 'instance' => ''], $metricIds), 'intervalId' => $intervalId, 'format' => 'normal', - ], + ] ]; return $this->soapClient->QueryPerf($body); } + + public function acquireTicket(string $vmId, string $ticketType = 'webmks') + { + return $this->vmRequest('AcquireTicket', $vmId, ['ticketType' => $ticketType]); + } + + public function mountToolsInstaller(string $vmId) + { + return $this->vmRequest('MountToolsInstaller', $vmId); + } + + public function unmountToolsInstaller(string $vmId) + { + return $this->vmRequest('UnmountToolsInstaller', $vmId); + } } diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index 4d7d9d1..cfeb43d 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -41,10 +41,10 @@ public function arrayToSoapVar(array $array): array $arrayData = []; foreach ($value as $item) { - $arrayData[] = new SoapVar($this->arrayToSoapVar($item), SOAP_ENC_OBJECT, $typeName, null, 'deviceChange', null); + $arrayData[] = new SoapVar($this->arrayToSoapVar($item), SOAP_ENC_OBJECT, null, 'vm', null);; } - $data[$key] = new SoapVar($arrayData, SOAP_ENC_OBJECT, null, 'deviceChange', null, null); + $data[$key] = $arrayData; continue; } diff --git a/src/VcenterSoapClient.php b/src/VcenterSoapClient.php index 066d9ec..6482b65 100755 --- a/src/VcenterSoapClient.php +++ b/src/VcenterSoapClient.php @@ -4,13 +4,15 @@ use SoapClient; use Xelon\VmWareClient\Data\SoapData; -use Xelon\VmWareClient\Traits\Soap\SoapFileApis; +use Xelon\VmWareClient\Traits\Soap\SoapGuestApis; +use Xelon\VmWareClient\Traits\Soap\SoapStorageApis; use Xelon\VmWareClient\Traits\Soap\SoapVmApis; class VcenterSoapClient { use SoapVmApis; - use SoapFileApis; + use SoapGuestApis; + use SoapStorageApis; public SoapClient $soapClient; From a959bc0a92d64396fea362b78d903f22461a8e1e Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Tue, 20 Sep 2022 08:41:12 +0000 Subject: [PATCH 04/46] Fix styling --- src/Traits/Soap/SoapStorageApis.php | 10 +++++----- src/Traits/Soap/SoapVmApis.php | 28 ++++++++++++++-------------- src/Transform/SoapTransform.php | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Traits/Soap/SoapStorageApis.php b/src/Traits/Soap/SoapStorageApis.php index 0ee23df..7374ec4 100644 --- a/src/Traits/Soap/SoapStorageApis.php +++ b/src/Traits/Soap/SoapStorageApis.php @@ -22,7 +22,7 @@ public function getVcenterVStorageInfo(string $vstorageId, string $datastore) ], 'datastore' => [ 'type' => 'Datastore', - '_' => $datastore + '_' => $datastore, ], ]; @@ -41,7 +41,7 @@ public function deleteVcenterVStorageInfo(string $vstorageId, string $datastore) ], 'datastore' => [ 'type' => 'Datastore', - '_' => $datastore + '_' => $datastore, ], ]; @@ -62,11 +62,11 @@ public function createVStorage(string $name, int $capacityInMB, string $datastor '@type' => 'VslmCreateSpecDiskFileBackingSpec', 'datastore' => [ 'type' => 'Datastore', - '_' => $datastore + '_' => $datastore, ], ], 'capacityInMB' => $capacityInMB, - ] + ], ]; return $this->soapClient->CreateDisk_Task($this->arrayToSoapVar($body)); @@ -84,7 +84,7 @@ public function extendVStorage(string $vstorageId, string $datastore, int $newCa ], 'datastore' => [ 'type' => 'Datastore', - '_' => $datastore + '_' => $datastore, ], 'newCapacityInMB' => $newCapacityInMB, ]; diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index 8863fab..549ee3c 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -53,7 +53,7 @@ public function getTaskHistoryCollectorInfo(string $taskHistoryCollectorId) public function getResourcePoolInfo(?string $resourcePoolId, string $pathSet = '') { - if (!$resourcePoolId) { + if (! $resourcePoolId) { return []; } @@ -253,7 +253,7 @@ public function changeDVPortgroupSpeed( 'burstSize' => [ 'inherited' => false, 'value' => $speed, - ] + ], ], 'outShapingPolicy' => [ '@type' => 'DVSTrafficShapingPolicy', @@ -273,10 +273,10 @@ public function changeDVPortgroupSpeed( 'burstSize' => [ 'inherited' => false, 'value' => $speed, - ] - ] - ] - ] + ], + ], + ], + ], ]; return $this->soapClient->ReconfigureDVPortgroup_Task($this->arrayToSoapVar($body)); @@ -290,12 +290,12 @@ public function reconfigureComputeResource( $body = [ '_this' => [ '_' => $clusterComputerResourceId, - 'type' => 'ComputeResource' + 'type' => 'ComputeResource', ], 'spec' => [ '@type' => 'ClusterConfigSpecEx', 'drsConfig' => [ - '@type' => 'ClusterDrsConfigInfo' + '@type' => 'ClusterDrsConfigInfo', ], 'rulesSpec' => [ '@type' => 'ClusterRuleSpec', @@ -305,20 +305,20 @@ public function reconfigureComputeResource( 'enabled' => true, 'name' => $name, 'userCreated' => true, - ] + ], ], 'dpmConfig' => [ - '@type' => 'ClusterDpmConfigInfo' - ] + '@type' => 'ClusterDpmConfigInfo', + ], ], - 'modify' => false + 'modify' => false, ]; foreach ($vmIds as $vmId) { $body['spec']['rulesSpec']['info']['vm'][] = [ '_' => $vmId, - 'type' => 'VirtualMachine' + 'type' => 'VirtualMachine', ]; } @@ -471,7 +471,7 @@ public function queryPerf( 'metricId' => array_map(fn (int $id): array => ['counterId' => $id, 'instance' => ''], $metricIds), 'intervalId' => $intervalId, 'format' => 'normal', - ] + ], ]; return $this->soapClient->QueryPerf($body); diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index cfeb43d..2479aa1 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -41,7 +41,7 @@ public function arrayToSoapVar(array $array): array $arrayData = []; foreach ($value as $item) { - $arrayData[] = new SoapVar($this->arrayToSoapVar($item), SOAP_ENC_OBJECT, null, 'vm', null);; + $arrayData[] = new SoapVar($this->arrayToSoapVar($item), SOAP_ENC_OBJECT, null, 'vm', null); } $data[$key] = $arrayData; From dad860adbebde5a0dc5b6afd8292ff4ab232d5fb Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Fri, 23 Sep 2022 12:17:15 +0300 Subject: [PATCH 05/46] feat: Cis + ovf apis --- config/vmware-php-client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/vmware-php-client.php b/config/vmware-php-client.php index 9b22dfe..9144775 100644 --- a/config/vmware-php-client.php +++ b/config/vmware-php-client.php @@ -2,5 +2,5 @@ return [ // session ttl in minutes - 'session_ttl' => env('VMWARE_SESSION_TTL', 120), + 'session_ttl' => env('VMWARE_SESSION_TTL', 10), ]; From b067aa93750c4ffdec53b2523706bd60041c6f99 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Fri, 23 Sep 2022 12:18:07 +0300 Subject: [PATCH 06/46] feat: Cis + ovf apis --- src/Data/SoapData.php | 1 + src/Traits/Rest/CisApis.php | 58 +++++++++++++++++++++++++++++++++ src/Traits/Rest/OfvApis.php | 58 +++++++++++++++++++++++++++++++++ src/Traits/Rest/VcenterApis.php | 9 ++++- src/Transform/SoapTransform.php | 36 ++++++++++---------- src/VcenterClient.php | 4 +++ 6 files changed, 147 insertions(+), 19 deletions(-) create mode 100644 src/Traits/Rest/CisApis.php create mode 100644 src/Traits/Rest/OfvApis.php diff --git a/src/Data/SoapData.php b/src/Data/SoapData.php index 3bfda94..ac82c70 100644 --- a/src/Data/SoapData.php +++ b/src/Data/SoapData.php @@ -22,6 +22,7 @@ public function objectInfoBody(string $objectId, string $objectType, string $pat '_' => $objectId, 'type' => $objectType, ], + 'skip' => false ], ], ]; diff --git a/src/Traits/Rest/CisApis.php b/src/Traits/Rest/CisApis.php new file mode 100644 index 0000000..5441726 --- /dev/null +++ b/src/Traits/Rest/CisApis.php @@ -0,0 +1,58 @@ +request( + 'post', + "/api/cis/tagging/tag-association?action=list-attached-tags", + [ + 'json' => [ + 'object_id'=> [ + 'type'=>'VirtualMachine', + 'id'=> $vmId + ] + ] + ] + ); + } + + public function atachTagAssociation(string $vmId, string $tagId) + { + return $this->request( + 'post', + "/api/cis/tagging/tag-association/$tagId?action=attach", + [ + 'json' => [ + 'object_id'=> [ + 'type'=>'VirtualMachine', + 'id'=> $vmId + ] + ] + ] + ); + } + + public function detachTagAssociation(string $vmId, string $tagId) + { + return $this->request( + 'post', + "/api/cis/tagging/tag-association/$tagId?action=detach", + [ + 'json' => [ + 'object_id'=> [ + 'type'=>'VirtualMachine', + 'id'=> $vmId + ] + ] + ] + ); + } +} diff --git a/src/Traits/Rest/OfvApis.php b/src/Traits/Rest/OfvApis.php new file mode 100644 index 0000000..7b7befd --- /dev/null +++ b/src/Traits/Rest/OfvApis.php @@ -0,0 +1,58 @@ + [ + 'name' => $data['name'], + 'accept_all_EULA' => false, + 'default_datastore_id' => $data['default_datastore_id'], + 'storage_provisioning' => 'thin', + 'additional_parameters' => [ + [ + '@class' => 'com.vmware.vcenter.ovf.property_params', + 'type' => 'PropertyParams', + 'properties' => [ + [ + 'instance_id' => '', + 'class_id' => '', + 'description' => 'In order to fit into a xml attribute, this value is base64 encoded . It will be decoded, and then processed normally as user-data.', + 'id' => 'user-data', + 'label' => 'Encoded user-data', + 'category' => '', + 'type' => 'string', + 'value' => $data['user_data'], + 'ui_optional' => false + ] + ] + ] + ], + 'network_mappings' => [ + 'value' => $data['network_port_group'], + 'key' => 'VM Network' + ], + ], + 'target' => [ + 'resource_pool_id' => $data['resource_pool_id'], + ], + ]; + + if (isset($data['folder_id'])) { + $body['target']['folder_id'] = $data['folder_id']; + } + + return $this->request( + 'post', + "/api/vcenter/ovf/library-item/$ovfLibraryItemId?action=deploy", + ['json' => $body] + ); + } +} diff --git a/src/Traits/Rest/VcenterApis.php b/src/Traits/Rest/VcenterApis.php index d27cf4e..774224f 100644 --- a/src/Traits/Rest/VcenterApis.php +++ b/src/Traits/Rest/VcenterApis.php @@ -13,7 +13,7 @@ public function createVm() // TODO: } - public function getVmList(array $requestBody) + public function getVmList(array $requestBody = []) { $query = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', http_build_query($requestBody, null, '&')); @@ -54,4 +54,11 @@ public function unregisterVm() { // TODO: } + + public function getNetworkList(array $requestBody = []) + { + $query = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', http_build_query($requestBody, null, '&')); + + return $this->request('get', '/api/vcenter/network', ['query' => $query]); + } } diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index 2479aa1..90a74bd 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -19,37 +19,37 @@ public function arrayToSoapVar(array $array): array } if (array_key_exists('type', $value)) { - $data[$key] = new SoapVar($value['_'], null, $value['type'], '', '', ''); + $data[$key] = new SoapVar($value['_'], null, $value['type'], '', $key, ''); continue; } - // TODO: Get rid of BOGUS and ENV:Struct tags - /*if (array_key_exists(0, $value)) { - $arrayData = []; + if (is_array($value) && array_key_exists(0, $value)) { + foreach ($value as $childItem) { - foreach ($value as $item) { - $arrayData[] = new SoapVar($this->arrayToSoapVar($item), SOAP_ENC_OBJECT, $typeName, 'VirtualDeviceConfigSpec', 'deviceChange', ''); - } - - $data[$key] = new SoapVar($arrayData, SOAP_ENC_OBJECT, '', '', 'deviceChanges', ''); + if (array_key_exists('@type', $childItem)) { + $typeName = $childItem['@type']; + unset($childItem['@type']); + } - continue; - }*/ + if (array_key_exists('type', $childItem)) { + $data[] = new SoapVar($childItem['_'], null, $childItem['type'], '', $key, ''); - if (array_key_exists(0, $value)) { - $arrayData = []; + continue; + } - foreach ($value as $item) { - $arrayData[] = new SoapVar($this->arrayToSoapVar($item), SOAP_ENC_OBJECT, null, 'vm', null); + $data[] = new SoapVar($this->arrayToSoapVar($childItem), SOAP_ENC_OBJECT, $typeName, null); } - $data[$key] = $arrayData; + unset($array[$key]); - continue; + $deepArraySet = true; + } + + if (!isset($deepArraySet)) { + $data[$key] = new SoapVar($this->arrayToSoapVar($value), SOAP_ENC_OBJECT, $typeName, null, $key); } - $data[$key] = new SoapVar($this->arrayToSoapVar($value), SOAP_ENC_OBJECT, $typeName, null, 'empty'); $typeName = null; } elseif (! is_null($value)) { $data[$key] = $value; diff --git a/src/VcenterClient.php b/src/VcenterClient.php index cb1370f..232a605 100755 --- a/src/VcenterClient.php +++ b/src/VcenterClient.php @@ -2,7 +2,9 @@ namespace Xelon\VmWareClient; +use Xelon\VmWareClient\Traits\Rest\CisApis; use Xelon\VmWareClient\Traits\Rest\IsoApis; +use Xelon\VmWareClient\Traits\Rest\OfvApis; use Xelon\VmWareClient\Traits\Rest\VcenterApis; use Xelon\VmWareClient\Traits\Rest\VmApis; @@ -11,6 +13,8 @@ class VcenterClient extends VmWareClientInit use VcenterApis; use VmApis; use IsoApis; + use CisApis; + use OfvApis; public ?VcenterSoapClient $soap; From 9b7d247b62383376c9f372de4df422e7270f9d7e Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Fri, 23 Sep 2022 09:18:36 +0000 Subject: [PATCH 07/46] Fix styling --- src/Data/SoapData.php | 2 +- src/Traits/Rest/CisApis.php | 32 ++++++++++++++++---------------- src/Traits/Rest/OfvApis.php | 10 +++++----- src/Transform/SoapTransform.php | 3 +-- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/Data/SoapData.php b/src/Data/SoapData.php index ac82c70..93757c2 100644 --- a/src/Data/SoapData.php +++ b/src/Data/SoapData.php @@ -22,7 +22,7 @@ public function objectInfoBody(string $objectId, string $objectType, string $pat '_' => $objectId, 'type' => $objectType, ], - 'skip' => false + 'skip' => false, ], ], ]; diff --git a/src/Traits/Rest/CisApis.php b/src/Traits/Rest/CisApis.php index 5441726..85870ff 100644 --- a/src/Traits/Rest/CisApis.php +++ b/src/Traits/Rest/CisApis.php @@ -12,14 +12,14 @@ public function listAttachedTagsTagAssociation(string $vmId) { return $this->request( 'post', - "/api/cis/tagging/tag-association?action=list-attached-tags", + '/api/cis/tagging/tag-association?action=list-attached-tags', [ 'json' => [ - 'object_id'=> [ - 'type'=>'VirtualMachine', - 'id'=> $vmId - ] - ] + 'object_id' => [ + 'type' => 'VirtualMachine', + 'id' => $vmId, + ], + ], ] ); } @@ -31,11 +31,11 @@ public function atachTagAssociation(string $vmId, string $tagId) "/api/cis/tagging/tag-association/$tagId?action=attach", [ 'json' => [ - 'object_id'=> [ - 'type'=>'VirtualMachine', - 'id'=> $vmId - ] - ] + 'object_id' => [ + 'type' => 'VirtualMachine', + 'id' => $vmId, + ], + ], ] ); } @@ -47,11 +47,11 @@ public function detachTagAssociation(string $vmId, string $tagId) "/api/cis/tagging/tag-association/$tagId?action=detach", [ 'json' => [ - 'object_id'=> [ - 'type'=>'VirtualMachine', - 'id'=> $vmId - ] - ] + 'object_id' => [ + 'type' => 'VirtualMachine', + 'id' => $vmId, + ], + ], ] ); } diff --git a/src/Traits/Rest/OfvApis.php b/src/Traits/Rest/OfvApis.php index 7b7befd..71e55fa 100644 --- a/src/Traits/Rest/OfvApis.php +++ b/src/Traits/Rest/OfvApis.php @@ -30,14 +30,14 @@ public function deployLibraryItem(string $ovfLibraryItemId, array $data) 'category' => '', 'type' => 'string', 'value' => $data['user_data'], - 'ui_optional' => false - ] - ] - ] + 'ui_optional' => false, + ], + ], + ], ], 'network_mappings' => [ 'value' => $data['network_port_group'], - 'key' => 'VM Network' + 'key' => 'VM Network', ], ], 'target' => [ diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index 90a74bd..326dd9e 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -26,7 +26,6 @@ public function arrayToSoapVar(array $array): array if (is_array($value) && array_key_exists(0, $value)) { foreach ($value as $childItem) { - if (array_key_exists('@type', $childItem)) { $typeName = $childItem['@type']; unset($childItem['@type']); @@ -46,7 +45,7 @@ public function arrayToSoapVar(array $array): array $deepArraySet = true; } - if (!isset($deepArraySet)) { + if (! isset($deepArraySet)) { $data[$key] = new SoapVar($this->arrayToSoapVar($value), SOAP_ENC_OBJECT, $typeName, null, $key); } From 117c54d743f3efb5598bbdc9075445bd4f0647d6 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Mon, 3 Oct 2022 16:58:48 +0300 Subject: [PATCH 08/46] feat: created method for array transform --- src/Traits/Soap/SoapVmApis.php | 2 +- src/Transform/SoapTransform.php | 81 ++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index 549ee3c..6dc1ddc 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -474,7 +474,7 @@ public function queryPerf( ], ]; - return $this->soapClient->QueryPerf($body); + return $this->transformToArrayValues($this->soapClient->QueryPerf($body)); } public function acquireTicket(string $vmId, string $ticketType = 'webmks') diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index 90a74bd..6d43896 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -67,6 +67,85 @@ public function transformPropSet(array $data): stdClass $newData->{$item->name} = $item->val; } - return $newData; + return $this->transformToArrayValues($newData); + } + + /** + * @param stdClass $object + * @return stdClass + * This function transform to array objects that should be array type + */ + public function transformToArrayValues(stdClass $object, int $startIndex = 0, ?int $onlyIndexPath = null) + { + $pathes = [ + ['latestPage', 'TaskInfo'], + ['returnval', 'sampleInfo'], + ['returnval', 'value', 'value'], + ['layoutEx', 'file'], + ['layoutEx', 'snapshot'], + ['layoutEx', 'snapshot', 'disk'], + ['layoutEx', 'snapshot', 'disk', 'chain'], + ['snapshot', 'rootSnapshotList'], + ['snapshot', 'rootSnapshotList', 'childSnapshotList'], + ]; + + $recursiveOblectNames = ['childSnapshotList']; + + foreach ($pathes as $indexPath => $path) { + if ($onlyIndexPath && $onlyIndexPath !== $indexPath) { + continue; + } + + $lastIndex = count($path) - 1; + $newObj = $object; + + foreach ($path as $index => $property) { + if ($index < $startIndex || !is_object($newObj) || empty((array)$newObj) || !property_exists($newObj, $property)) { + continue; + } + + $newObj = $newObj->{$property}; + + $varName = "el_$indexPath"; + + isset($$varName) ? $$varName = &$$varName->{$property} : $$varName = &$object->{$property}; + + if ($index === $lastIndex && !is_array($newObj)) { + $$varName = [$$varName]; + } + + if ($index !== $lastIndex && is_array($$varName)) { + foreach ($$varName as &$oblectItem) { + $oblectItem = $this->transformToArrayValues($oblectItem, $index + 1, $indexPath); + } + } + + foreach ($recursiveOblectNames as $recursiveOblectName) { + if ($recursiveOblectName === $property) { + $this->transformToArrayValuesRecursive($$varName, $property); + } + } + } + } + + return $object; + } + + private function transformToArrayValuesRecursive(&$object, string $propertyName) + { + if (is_array($object)) { + foreach ($object as &$nestedObject) { + $nestedObject = $this->transformToArrayValuesRecursive($nestedObject, $propertyName); + } + } else { + if (isset($object->{$propertyName})) { + $object->{$propertyName} = [$object->{$propertyName}]; + foreach ($object->{$propertyName} as &$nestedObject1) { + $nestedObject1 = $this->transformToArrayValuesRecursive($nestedObject1, $propertyName); + } + } + } + + return $object; } } From 1850959611107d4338fe620144ed03ecd02abcac Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Mon, 3 Oct 2022 13:59:33 +0000 Subject: [PATCH 09/46] Fix styling --- src/Transform/SoapTransform.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index 84ce11f..dfd0db9 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -70,7 +70,7 @@ public function transformPropSet(array $data): stdClass } /** - * @param stdClass $object + * @param stdClass $object * @return stdClass * This function transform to array objects that should be array type */ @@ -99,7 +99,7 @@ public function transformToArrayValues(stdClass $object, int $startIndex = 0, ?i $newObj = $object; foreach ($path as $index => $property) { - if ($index < $startIndex || !is_object($newObj) || empty((array)$newObj) || !property_exists($newObj, $property)) { + if ($index < $startIndex || ! is_object($newObj) || empty((array) $newObj) || ! property_exists($newObj, $property)) { continue; } @@ -109,7 +109,7 @@ public function transformToArrayValues(stdClass $object, int $startIndex = 0, ?i isset($$varName) ? $$varName = &$$varName->{$property} : $$varName = &$object->{$property}; - if ($index === $lastIndex && !is_array($newObj)) { + if ($index === $lastIndex && ! is_array($newObj)) { $$varName = [$$varName]; } From da997d4cc5d0842ad55cb58d5eb9c15c8287922b Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Tue, 4 Oct 2022 14:08:40 +0300 Subject: [PATCH 10/46] feat: added logs to all requests --- config/vmware-php-client.php | 1 + src/Requests/SoapRequest.php | 44 ++++++++++++++++++++++++++++- src/Traits/Soap/SoapGuestApis.php | 20 ++++++------- src/Traits/Soap/SoapStorageApis.php | 8 +++--- src/Traits/Soap/SoapVmApis.php | 32 +++++++++++++++------ 5 files changed, 81 insertions(+), 24 deletions(-) diff --git a/config/vmware-php-client.php b/config/vmware-php-client.php index 9144775..4a962ac 100644 --- a/config/vmware-php-client.php +++ b/config/vmware-php-client.php @@ -3,4 +3,5 @@ return [ // session ttl in minutes 'session_ttl' => env('VMWARE_SESSION_TTL', 10), + 'enable_logs' => env('VMWARE_ENABLE_LOGS', true), ]; diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index db5fa9f..b78833f 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -2,8 +2,50 @@ namespace Xelon\VmWareClient\Requests; +use Illuminate\Support\Facades\Log; +use Xelon\VmWareClient\Transform\SoapTransform; +use stdClass; + trait SoapRequest { + use SoapTransform; + + /** + * @param string $method + * @param array $requestBody + * @param bool $convertToSoap + * @return stdClass + */ + private function request(string $method, array $requestBody, bool $convertToSoap= true): stdClass + { + try { + $response = $this->soapClient->$method($convertToSoap ? $this->arrayToSoapVar($requestBody) : $requestBody); + + if (config('vmware-php-client.enable_logs')) { + Log::info( + "SOAP REQUEST SUCCESS:". + "\nSOAP method: ".$method. + "\nSOAP request: ".$this->soapClient->__last_request + ); + } + + return $response; + } catch (\Exception $exception) { + Log::error( + "SOAP REQUEST FAILED:\nMessage: ".$exception->getMessage(). + "\nSOAP method: ".$method. + "\nSOAP request: ".$this->soapClient->__last_request. + "\nSOAP response: ".$this->soapClient->__last_response + ); + } + } + + /** + * @param string $method + * @param string $vmId + * @param array $requestBody + * @return stdClass + */ private function vmRequest(string $method, string $vmId, array $requestBody = []) { $soapMessage = [ @@ -14,6 +56,6 @@ private function vmRequest(string $method, string $vmId, array $requestBody = [] ]; $soapMessage = array_merge($soapMessage, $requestBody); - return $this->soapClient->$method($soapMessage); + return $this->request($method, $soapMessage); } } diff --git a/src/Traits/Soap/SoapGuestApis.php b/src/Traits/Soap/SoapGuestApis.php index c2d4617..70679ef 100644 --- a/src/Traits/Soap/SoapGuestApis.php +++ b/src/Traits/Soap/SoapGuestApis.php @@ -53,7 +53,7 @@ public function initiateFileTransferToGuest( 'overwrite' => true, ]; - $response = $this->soapClient->InitiateFileTransferToGuest($this->arrayToSoapVar($body)); + $response = $this->request('InitiateFileTransferToGuest', $body); $client = new GuzzleClient(['verify' => false]); @@ -95,7 +95,7 @@ public function createTemporaryDirectoryInGuest( 'directoryPath' => $directoryPath, ]; - return $this->soapClient->CreateTemporaryDirectoryInGuest($this->arrayToSoapVar($body)); + return $this->request('CreateTemporaryDirectoryInGuest', $body); } public function deleteDirectoryInGuest( @@ -123,7 +123,7 @@ public function deleteDirectoryInGuest( 'recursive' => true, ]; - return $this->soapClient->DeleteDirectoryInGuest($this->arrayToSoapVar($body)); + return $this->request('DeleteDirectoryInGuest', $body); } public function deleteFileInGuest( @@ -150,7 +150,7 @@ public function deleteFileInGuest( 'filePath' => $filePath, ]; - return $this->soapClient->DeleteFileInGuest($this->arrayToSoapVar($body)); + return $this->request('DeleteFileInGuest', $body); } public function startProgramInGuest( @@ -181,7 +181,7 @@ public function startProgramInGuest( ], ]; - return $this->soapClient->StartProgramInGuest($this->arrayToSoapVar($body)); + return $this->request('StartProgramInGuest', $body); } public function createTaskCollectorForVm(string $vmId) @@ -202,7 +202,7 @@ public function createTaskCollectorForVm(string $vmId) ], ]; - return $this->soapClient->CreateCollectorForTasks($body); + return $this->request('CreateCollectorForTasks', $body); } public function destroyTaskCollector(string $taskCollectorId) @@ -214,7 +214,7 @@ public function destroyTaskCollector(string $taskCollectorId) ], ]; - return $this->soapClient->DestroyCollector($body); + return $this->request('DestroyCollector', $body); } public function getListFilesInGuest( @@ -241,7 +241,7 @@ public function getListFilesInGuest( 'filePath' => $filePath, ]; - return $this->soapClient->ListFilesInGuest($this->arrayToSoapVar($body)); + return $this->request('ListFilesInGuest', $body); } public function getListProcessInGuest( @@ -266,7 +266,7 @@ public function getListProcessInGuest( ], ]; - return $this->soapClient->ListProcessesInGuest($this->arrayToSoapVar($body)); + return $this->request('ListProcessesInGuest', $body); } public function validateCredentialsInGuest(string $username, string $password, string $vmId) @@ -288,6 +288,6 @@ public function validateCredentialsInGuest(string $username, string $password, s ], ]; - return $this->soapClient->ValidateCredentialsInGuest($this->arrayToSoapVar($body)); + return $this->request('ValidateCredentialsInGuest', $body); } } diff --git a/src/Traits/Soap/SoapStorageApis.php b/src/Traits/Soap/SoapStorageApis.php index 7374ec4..d4fc862 100644 --- a/src/Traits/Soap/SoapStorageApis.php +++ b/src/Traits/Soap/SoapStorageApis.php @@ -26,7 +26,7 @@ public function getVcenterVStorageInfo(string $vstorageId, string $datastore) ], ]; - return $this->soapClient->RetrieveVStorageObject($this->arrayToSoapVar($body)); + return $this->request('RetrieveVStorageObject', $body); } public function deleteVcenterVStorageInfo(string $vstorageId, string $datastore) @@ -45,7 +45,7 @@ public function deleteVcenterVStorageInfo(string $vstorageId, string $datastore) ], ]; - return $this->soapClient->DeleteVStorageObject_Task($this->arrayToSoapVar($body)); + return $this->request('DeleteVStorageObject_Task', $body); } public function createVStorage(string $name, int $capacityInMB, string $datastore, bool $keepAfterDeleteVm = true) @@ -69,7 +69,7 @@ public function createVStorage(string $name, int $capacityInMB, string $datastor ], ]; - return $this->soapClient->CreateDisk_Task($this->arrayToSoapVar($body)); + return $this->request('CreateDisk_Task', $body); } public function extendVStorage(string $vstorageId, string $datastore, int $newCapacityInMB) @@ -89,6 +89,6 @@ public function extendVStorage(string $vstorageId, string $datastore, int $newCa 'newCapacityInMB' => $newCapacityInMB, ]; - return $this->soapClient->ExtendDisk_Task($this->arrayToSoapVar($body)); + return $this->request('ExtendDisk_Task', $body); } } diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index 6dc1ddc..1c9f455 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -2,6 +2,7 @@ namespace Xelon\VmWareClient\Traits\Soap; +use Illuminate\Support\Facades\Log; use Xelon\VmWareClient\Requests\SoapRequest; use Xelon\VmWareClient\Transform\SoapTransform; @@ -14,7 +15,20 @@ public function getObjectInfo(string $objectId, string $objectType, string $path { $body = $this->data->objectInfoBody($objectId, $objectType, $pathSet); - $result = $this->soapClient->RetrieveProperties($body); + try { + $result = $this->soapClient->RetrieveProperties($body); + } catch (\Exception $exception) { + Log::error( + "SOAP REQUEST FAILED:\nMessage: ".$exception->getMessage(). + "\nSOAP request: ".$this->soapClient->__last_request. + "\nSOAP response: ".$this->soapClient->__last_response + ); + + if (array_keys(json_decode(json_encode($exception->detail), true))[0] === 'ManagedObjectNotFoundFault') { + Log::error("404 error, type: $objectType, object id: $objectId"); + return new \stdClass(); + } + } return $pathSet ? ($result->returnval->propSet->val ?? null) @@ -279,7 +293,7 @@ public function changeDVPortgroupSpeed( ], ]; - return $this->soapClient->ReconfigureDVPortgroup_Task($this->arrayToSoapVar($body)); + return $this->request('ReconfigureDVPortgroup_Task', $body); } public function reconfigureComputeResource( @@ -322,7 +336,7 @@ public function reconfigureComputeResource( ]; } - return $this->soapClient->ReconfigureComputeResource_Task($this->arrayToSoapVar($body)); + return $this->request('ReconfigureComputeResource_Task', $body); } public function mountIso(string $vmId, string $fileName, int $key, int $controllerKey, string $datastore) @@ -375,7 +389,7 @@ public function findRulesForVm(string $vmId, string $clusterComputerResource) ], ]; - return $this->soapClient->FindRulesForVm($body); + return $this->request('FindRulesForVm', $body); } public function createFolder(string $parentFolder, string $name) @@ -388,7 +402,7 @@ public function createFolder(string $parentFolder, string $name) 'name' => $name, ]; - return $this->soapClient->CreateFolder($body); + return $this->request('CreateFolder', $body); } public function deleteFolder(string $folderId) @@ -400,7 +414,7 @@ public function deleteFolder(string $folderId) ], ]; - return $this->soapClient->Destroy_Task($body); + return $this->request('Destroy_Task', $body); } public function createSnapshot( @@ -429,7 +443,7 @@ public function revertSnapshot(string $snapshopId) ], ]; - return $this->soapClient->RevertToSnapshot_Task($body); + return $this->request('RevertToSnapshot_Task', $body); } public function removeSnapshot(string $snapshopId, bool $removeChildren = true, bool $consolidate = true) @@ -443,7 +457,7 @@ public function removeSnapshot(string $snapshopId, bool $removeChildren = true, '$consolidate' => $consolidate, ]; - return $this->soapClient->RemoveSnapshot_Task($body); + return $this->request('RemoveSnapshot_Task', $body); } public function queryPerf( @@ -474,7 +488,7 @@ public function queryPerf( ], ]; - return $this->transformToArrayValues($this->soapClient->QueryPerf($body)); + return $this->transformToArrayValues($this->request('QueryPerf', $body, false)); } public function acquireTicket(string $vmId, string $ticketType = 'webmks') From e8341442dc9d732a8f62f53d8a5b218faa9fb3c8 Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Tue, 4 Oct 2022 11:09:20 +0000 Subject: [PATCH 11/46] Fix styling --- src/Requests/SoapRequest.php | 18 +++++++++--------- src/Traits/Soap/SoapVmApis.php | 1 + 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index b78833f..b753c56 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -3,27 +3,27 @@ namespace Xelon\VmWareClient\Requests; use Illuminate\Support\Facades\Log; -use Xelon\VmWareClient\Transform\SoapTransform; use stdClass; +use Xelon\VmWareClient\Transform\SoapTransform; trait SoapRequest { use SoapTransform; /** - * @param string $method - * @param array $requestBody - * @param bool $convertToSoap + * @param string $method + * @param array $requestBody + * @param bool $convertToSoap * @return stdClass */ - private function request(string $method, array $requestBody, bool $convertToSoap= true): stdClass + private function request(string $method, array $requestBody, bool $convertToSoap = true): stdClass { try { $response = $this->soapClient->$method($convertToSoap ? $this->arrayToSoapVar($requestBody) : $requestBody); if (config('vmware-php-client.enable_logs')) { Log::info( - "SOAP REQUEST SUCCESS:". + 'SOAP REQUEST SUCCESS:'. "\nSOAP method: ".$method. "\nSOAP request: ".$this->soapClient->__last_request ); @@ -41,9 +41,9 @@ private function request(string $method, array $requestBody, bool $convertToSoap } /** - * @param string $method - * @param string $vmId - * @param array $requestBody + * @param string $method + * @param string $vmId + * @param array $requestBody * @return stdClass */ private function vmRequest(string $method, string $vmId, array $requestBody = []) diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index 1c9f455..952a3b1 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -26,6 +26,7 @@ public function getObjectInfo(string $objectId, string $objectType, string $path if (array_keys(json_decode(json_encode($exception->detail), true))[0] === 'ManagedObjectNotFoundFault') { Log::error("404 error, type: $objectType, object id: $objectId"); + return new \stdClass(); } } From 13eac1f26d3f4b7998e5c759ee1c66207c12ffcc Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Thu, 6 Oct 2022 14:52:52 +0300 Subject: [PATCH 12/46] feat: updated README.md --- README.md | 160 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 114 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index c5aa4d8..d676ca2 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,138 @@ [](https://supportukrainenow.org) - -# PHP API Client for VmWare - +​ +# PHP API Client for VMWare +​ [![Latest Version on Packagist](https://img.shields.io/packagist/v/xelon-ag/vmware-php-client.svg?style=flat-square)](https://packagist.org/packages/xelon-ag/vmware-php-client) -[![GitHub Tests Action Status](https://img.shields.io/github/workflow/status/xelon-ag/vmware-php-client/run-tests?label=tests)](https://github.com/xelon-ag/vmware-php-client/actions?query=workflow%3Arun-tests+branch%3Amain) [![GitHub Code Style Action Status](https://img.shields.io/github/workflow/status/xelon-ag/vmware-php-client/Check%20&%20fix%20styling?label=code%20style)](https://github.com/xelon-ag/vmware-php-client/actions?query=workflow%3A"Check+%26+fix+styling"+branch%3Amain) [![Total Downloads](https://img.shields.io/packagist/dt/xelon-ag/vmware-php-client.svg?style=flat-square)](https://packagist.org/packages/xelon-ag/vmware-php-client) - -This is where your description should go. Limit it to a paragraph or two. Consider adding a small example. - -## Support us - -[](https://spatie.be/github-ad-click/vmware-php-client) - -We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us). - -We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards). - +​ ## Installation - +​ You can install the package via composer: - +​ ```bash composer require xelon-ag/vmware-php-client ``` - +​ You can publish the config file with: - +​ ```bash php artisan vendor:publish --tag="vmware-php-client-config" ``` - -This is the contents of the published config file: - +​ ```php return [ + 'session_ttl' => env('VMWARE_SESSION_TTL', 10), + 'enable_logs' => env('VMWARE_ENABLE_LOGS', true), ]; ``` - - -## Usage - +​ +​ +## Getting started +​ +Create a connection to your hypervisor so that you can call the methods: ```php -$vmWareClient = new Xelon\VmWareClient(); -echo $vmWareClient->echoPhrase('Hello, Xelon!'); +$vcenterClient = new Xelon\VmWareClient\VcenterClient( + 'https://10.20.30.40', + 'mylogin', + 'mypassword' +); +$vmInfo = $vcenterClient->getVmInfo('vm-123'); ``` - - -## Changelog - -Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. - -## Contributing - -Please see [CONTRIBUTING](https://github.com/gazhur94/.github/blob/main/CONTRIBUTING.md) for details. - -## Security Vulnerabilities - -Please review [our security policy](../../security/policy) on how to report security vulnerabilities. - +This lib can run in three modes: `rest`, `soap` and `both`. By default, it runs in `rest` mode, but you can set another mode in constructor: +```php +$vcenterClient = new Xelon\VmWareClient\VcenterClient( + 'https://10.20.30.40', + 'mylogin', + 'mypassword', + 'soap' +); +``` +Yet we recommend to use constants: +```php +$vcenterClient = new Xelon\VmWareClient\VcenterClient( + 'https://10.20.30.40', + 'mylogin', + 'mypassword', + Xelon\VmWareClient\VcenterClient::MODE_SOAP +); +``` +​ +### `rest` mode +​ +With `rest` mode you can use REST methods which you can find in the [VMWare API developer center](https://developer.vmware.com/apis/vsphere-automation/latest/). +For now, the lib has only some methods available. You can find full list of files in the `vendor/xelon-ag/vmware-php-client/src/Traits/Rest` folder. +​ +> We plan to add the full list of methods later. +​ +### `soap` mode +​ +Using `soap` mode allow you to use SOAP methods which you can find in [VMWare SOAP developer center](https://developer.vmware.com/apis/1192/vsphere). +For now, the lib has only some methods available. You can find full list of files in the `vendor/xelon-ag/vmware-php-client/src/Traits/SOAP` folder. +​ +> We plan to add the full list of methods later. +​ +Here's how to make your first SOAP call: +```php +$folder = $vcenterClient->soap->createFolder('group-v3', 'foldername'); +``` +​ +If you want to use both modes at one time you can set `both` mode (Xelon\VmWareClient\VcenterClient::MODE_BOTH). +​ +If you want to run custom `soap` method, which you do not find in lib, you can run this method directly: +```php +$vcenterClient = new Xelon\VmWareClient\VcenterClient( + 'https://10.20.30.40', + 'mylogin', + 'mypassword', + Xelon\VmWareClient\VcenterClient::MODE_SOAP +); +​ +$taskInfo = $vcenterClient->soap->request('ReconfigureComputeResource_Task', [ + '_this' => [ + '_' => 'domain-c33', + 'type' => 'ComputeResource', + ], + 'spec' => [ + '@type' => 'ClusterConfigSpecEx', + 'drsConfig' => [ + '@type' => 'ClusterDrsConfigInfo', + ], + 'rulesSpec' => [ + '@type' => 'ClusterRuleSpec', + 'operation' => 'add', + 'info' => [ + '@type' => 'ClusterAntiAffinityRuleSpec', + 'enabled' => true, + 'name' => 'VM-VM Affinity rule', + 'userCreated' => true, + 'vm' => [ + ['_' => 'vm-133', 'type' => 'VirtualMachine'], + ['_' => 'vm-134', 'type' => 'VirtualMachine'] + ] + ], + ], + 'dpmConfig' => [ + '@type' => 'ClusterDpmConfigInfo', + ], + + ], + 'modify' => false, +]) +``` +​ +> Order of parameters is very important. You can find the correct order in the [documentation]((https://developer.vmware.com/apis/1192/vsphere)), the `WSDL type definition` section for each object type. +​ ## Credits - +​ - [Andrii Hazhur](https://github.com/gazhur94) -- [All Contributors](../../contributors) - +- [All Contributors](https://github.com/Xelon-AG/vmware-php-client/graphs/contributors) + ​ +## Questions and feedback +​ +If you've got questions about setup or just want to chat with the developer, please feel free to reach out to a.hazhur@bitcat.agency. +​ ## License - +​ The MIT License (MIT). Please see [License File](LICENSE.md) for more information. From 887bb553503cc8676b33e08bd144cf426aca0f9a Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Wed, 12 Oct 2022 13:35:53 +0300 Subject: [PATCH 13/46] feat: created classes for object types --- src/Data/SoapData.php | 168 +++++++++--------- src/Requests/SoapRequest.php | 2 +- src/Traits/Soap/SoapGuestApis.php | 40 ++--- src/Traits/Soap/SoapStorageApis.php | 6 +- src/Traits/Soap/SoapVmApis.php | 140 +++++++-------- src/Transform/SoapTransform.php | 8 +- src/Types/ArrayUpdateSpec.php | 12 ++ src/Types/ClusterAntiAffinityRuleSpec.php | 8 + src/Types/ClusterConfigSpecEx.php | 38 ++++ src/Types/ClusterDpmConfigInfo.php | 16 ++ src/Types/ClusterDrsConfigInfo.php | 20 +++ src/Types/ClusterRuleInfo.php | 24 +++ src/Types/ClusterRuleSpec.php | 8 + src/Types/ComputeResourceConfigSpec.php | 17 ++ src/Types/Core/DynamicData.php | 28 +++ src/Types/CustomizationFixedIp.php | 8 + src/Types/CustomizationFixedName.php | 10 ++ src/Types/CustomizationGuiUnattended.php | 16 ++ src/Types/CustomizationIdentification.php | 16 ++ src/Types/CustomizationIpGenerator.php | 10 ++ src/Types/CustomizationPassword.php | 12 ++ src/Types/CustomizationUserData.php | 16 ++ src/Types/DVPortSetting.php | 22 +++ src/Types/DVPortgroupConfigSpec.php | 43 +++++ src/Types/DVSTrafficShapingPolicy.php | 14 ++ src/Types/Description.php | 12 ++ ...DistributedVirtualSwitchPortConnection.php | 16 ++ src/Types/GuestAuthentication.php | 10 ++ src/Types/InheritablePolicy.php | 10 ++ src/Types/NamePasswordAuthentication.php | 10 ++ src/Types/SharesInfo.php | 12 ++ src/Types/VirtualCdrom.php | 8 + src/Types/VirtualCdromIsoBackingInfo.php | 8 + .../VirtualCdromRemoteAtapiBackingInfo.php | 8 + src/Types/VirtualController.php | 10 ++ src/Types/VirtualDevice.php | 22 +++ src/Types/VirtualDeviceBackingInfo.php | 10 ++ src/Types/VirtualDeviceConfigSpec.php | 18 ++ src/Types/VirtualDeviceConnectInfo.php | 18 ++ src/Types/VirtualDeviceFileBackingInfo.php | 12 ++ .../VirtualDeviceRemoteDeviceBackingInfo.php | 10 ++ src/Types/VirtualDisk.php | 24 +++ src/Types/VirtualDiskFlatVer2BackingInfo.php | 36 ++++ src/Types/VirtualEthernetCard.php | 18 ++ ...tCardDistributedVirtualPortBackingInfo.php | 8 + src/Types/VirtualLsiLogicSASController.php | 8 + ...lMachineBootOptionsBootableCdromDevice.php | 8 + ...irtualMachineBootOptionsBootableDevice.php | 10 ++ src/Types/VirtualMachineConfigSpec.php | 134 ++++++++++++++ src/Types/VirtualSCSIController.php | 12 ++ src/Types/VirtualVmxnet.php | 10 ++ src/Types/VirtualVmxnet3.php | 8 + src/Types/VslmCreateSpecBackingSpec.php | 12 ++ .../VslmCreateSpecDiskFileBackingSpec.php | 8 + src/VcenterSoapClient.php | 2 + 55 files changed, 1003 insertions(+), 191 deletions(-) create mode 100644 src/Types/ArrayUpdateSpec.php create mode 100644 src/Types/ClusterAntiAffinityRuleSpec.php create mode 100644 src/Types/ClusterConfigSpecEx.php create mode 100644 src/Types/ClusterDpmConfigInfo.php create mode 100644 src/Types/ClusterDrsConfigInfo.php create mode 100644 src/Types/ClusterRuleInfo.php create mode 100644 src/Types/ClusterRuleSpec.php create mode 100644 src/Types/ComputeResourceConfigSpec.php create mode 100644 src/Types/Core/DynamicData.php create mode 100644 src/Types/CustomizationFixedIp.php create mode 100644 src/Types/CustomizationFixedName.php create mode 100644 src/Types/CustomizationGuiUnattended.php create mode 100644 src/Types/CustomizationIdentification.php create mode 100644 src/Types/CustomizationIpGenerator.php create mode 100644 src/Types/CustomizationPassword.php create mode 100644 src/Types/CustomizationUserData.php create mode 100644 src/Types/DVPortSetting.php create mode 100644 src/Types/DVPortgroupConfigSpec.php create mode 100644 src/Types/DVSTrafficShapingPolicy.php create mode 100644 src/Types/Description.php create mode 100644 src/Types/DistributedVirtualSwitchPortConnection.php create mode 100644 src/Types/GuestAuthentication.php create mode 100644 src/Types/InheritablePolicy.php create mode 100644 src/Types/NamePasswordAuthentication.php create mode 100644 src/Types/SharesInfo.php create mode 100644 src/Types/VirtualCdrom.php create mode 100644 src/Types/VirtualCdromIsoBackingInfo.php create mode 100644 src/Types/VirtualCdromRemoteAtapiBackingInfo.php create mode 100644 src/Types/VirtualController.php create mode 100644 src/Types/VirtualDevice.php create mode 100644 src/Types/VirtualDeviceBackingInfo.php create mode 100644 src/Types/VirtualDeviceConfigSpec.php create mode 100644 src/Types/VirtualDeviceConnectInfo.php create mode 100644 src/Types/VirtualDeviceFileBackingInfo.php create mode 100644 src/Types/VirtualDeviceRemoteDeviceBackingInfo.php create mode 100644 src/Types/VirtualDisk.php create mode 100644 src/Types/VirtualDiskFlatVer2BackingInfo.php create mode 100644 src/Types/VirtualEthernetCard.php create mode 100644 src/Types/VirtualEthernetCardDistributedVirtualPortBackingInfo.php create mode 100644 src/Types/VirtualLsiLogicSASController.php create mode 100644 src/Types/VirtualMachineBootOptionsBootableCdromDevice.php create mode 100644 src/Types/VirtualMachineBootOptionsBootableDevice.php create mode 100644 src/Types/VirtualMachineConfigSpec.php create mode 100644 src/Types/VirtualSCSIController.php create mode 100644 src/Types/VirtualVmxnet.php create mode 100644 src/Types/VirtualVmxnet3.php create mode 100644 src/Types/VslmCreateSpecBackingSpec.php create mode 100644 src/Types/VslmCreateSpecDiskFileBackingSpec.php diff --git a/src/Data/SoapData.php b/src/Data/SoapData.php index 93757c2..9fec6bc 100644 --- a/src/Data/SoapData.php +++ b/src/Data/SoapData.php @@ -2,6 +2,25 @@ namespace Xelon\VmWareClient\Data; +use Xelon\VmWareClient\Types\CustomizationFixedIp; +use Xelon\VmWareClient\Types\CustomizationFixedName; +use Xelon\VmWareClient\Types\CustomizationGuiUnattended; +use Xelon\VmWareClient\Types\CustomizationIdentification; +use Xelon\VmWareClient\Types\CustomizationPassword; +use Xelon\VmWareClient\Types\CustomizationUserData; +use Xelon\VmWareClient\Types\Description; +use Xelon\VmWareClient\Types\DistributedVirtualSwitchPortConnection; +use Xelon\VmWareClient\Types\SharesInfo; +use Xelon\VmWareClient\Types\VirtualCdrom; +use Xelon\VmWareClient\Types\VirtualCdromIsoBackingInfo; +use Xelon\VmWareClient\Types\VirtualCdromRemoteAtapiBackingInfo; +use Xelon\VmWareClient\Types\VirtualDeviceConnectInfo; +use Xelon\VmWareClient\Types\VirtualDisk; +use Xelon\VmWareClient\Types\VirtualDiskFlatVer2BackingInfo; +use Xelon\VmWareClient\Types\VirtualEthernetCardDistributedVirtualPortBackingInfo; +use Xelon\VmWareClient\Types\VirtualLsiLogicSASController; +use Xelon\VmWareClient\Types\VirtualVmxnet3; + class SoapData { public function objectInfoBody(string $objectId, string $objectType, string $pathSet = ''): array @@ -33,70 +52,62 @@ public function addVirtualDiskSpec( int $unitNumber, bool $isHdd = false, string $name = 'New Hard disk' - ): array { - return [ - '@type' => 'VirtualDisk', + ): VirtualDisk { + return new VirtualDisk([ 'key' => -101, - 'deviceInfo' => [ - '@type' => 'Description', + 'deviceInfo' => new Description([ 'label' => $name, 'summary' => $name, - ], - 'backing' => [ - '@type' => 'VirtualDiskFlatVer2BackingInfo', + ]), + 'backing' => new VirtualDiskFlatVer2BackingInfo([ 'fileName' => '', 'diskMode' => 'persistent', 'thinProvisioned' => false, 'eagerlyScrub' => false, - ], + ]), 'controllerKey' => 1000, 'unitNumber' => $unitNumber, 'capacityInKB' => $capacityInKB, 'capacityInBytes' => $capacityInKB * 1024, 'storageIOAllocation' => [ 'limit' => $isHdd ? 3200 : -1, - 'shares' => [ - '@type' => 'SharesInfo', + 'shares' => new SharesInfo([ 'shares' => 1000, 'level' => 'normal', - ], + ]), ], - ]; + ]); } - public function editVirtualDiskSpec(array $params): array + public function editVirtualDiskSpec(array $params): VirtualDisk { - return [ - '@type' => 'VirtualDisk', + return new VirtualDisk([ 'key' => $params['key'], - 'backing' => [ - '@type' => 'VirtualDiskFlatVer2BackingInfo', + 'backing' => new VirtualDiskFlatVer2BackingInfo([ 'fileName' => $params['backing']['fileName'], 'diskMode' => $params['backing']['diskMode'] ?? 'persistent', 'thinProvisioned' => $params['backing']['thinProvisioned'] ?? false, 'eagerlyScrub' => $params['backing']['eagerlyScrub'] ?? false, - ], + ]), 'controllerKey' => $params['controllerKey'], 'unitNumber' => $params['unitNumber'], 'capacityInKB' => $params['capacityInKB'], 'capacityInBytes' => $params['capacityInKB'] * 1024, - ]; + ]); } - public function addBlockStorageSpec(string $blockStoragePath, int $capacityInKB, int $controllerKey = 1000) + public function addBlockStorageSpec(string $blockStoragePath, int $capacityInKB, int $controllerKey = 1000): VirtualDisk { - return [ - '@type' => 'VirtualDisk', + return new VirtualDisk([ 'key' => -1, - 'backing' => [ - '@type' => 'VirtualDiskFlatVer2BackingInfo', + 'backing' => new VirtualDiskFlatVer2BackingInfo([ 'fileName' => $blockStoragePath, 'diskMode' => 'independent_persistent', - ], + ]), 'controllerKey' => $controllerKey, 'unitNumber' => -1, 'capacityInKB' => $capacityInKB, - ]; + ]); } public function addNetworkSpec( @@ -105,20 +116,18 @@ public function addNetworkSpec( int $unitNumber, int $controllerKey = 100, int $key = -1 - ): array { - return [ - '@type' => 'VirtualVmxnet3', + ): VirtualVmxnet3 { + return new VirtualVmxnet3([ 'key' => $key, - 'backing' => [ - '@type' => 'VirtualEthernetCardDistributedVirtualPortBackingInfo', - 'port' => [ + 'backing' => new VirtualEthernetCardDistributedVirtualPortBackingInfo([ + 'port' => new DistributedVirtualSwitchPortConnection([ 'switchUuid' => $switchUuid, 'portgroupKey' => $portgroupKey, - ], - ], + ]), + ]), 'controllerKey' => $controllerKey, 'unitNumber' => $unitNumber, - ]; + ]); } public function editNetworkSpec( @@ -126,85 +135,71 @@ public function editNetworkSpec( string $portgroupKey, int $key, ?string $macAddress = null - ): array { - $data = [ - '@type' => 'VirtualVmxnet3', + ): VirtualVmxnet3 { + return new VirtualVmxnet3([ 'key' => $key, - 'backing' => [ - '@type' => 'VirtualEthernetCardDistributedVirtualPortBackingInfo', - 'port' => [ + 'backing' => new VirtualEthernetCardDistributedVirtualPortBackingInfo([ + 'port' => new DistributedVirtualSwitchPortConnection([ 'switchUuid' => $switchUuid, 'portgroupKey' => $portgroupKey, - ], - ], + ]), + ]), 'addressType' => 'generated', 'macAddress' => $macAddress, - ]; - - if ($macAddress) { - $data['macAddress'] = $macAddress; - } - - return $data; + ]); } - public function addSasControllerSpec() + public function addSasControllerSpec(): VirtualLsiLogicSASController { - return [ - '@type' => 'VirtualLsiLogicSASController', + return new VirtualLsiLogicSASController([ 'busNumber' => 1, 'hotAddRemove' => true, 'sharedBus' => 'physicalSharing', - ]; + ]); } - public function mountVirtualCdRomSpec(string $fileName, int $key, int $controllerKey, string $datastore): array + public function mountVirtualCdRomSpec(string $fileName, int $key, int $controllerKey, string $datastore): VirtualCdrom { - return [ - '@type' => 'VirtualCdrom', + return new VirtualCdrom([ 'key' => $key, - 'backing' => [ - '@type' => 'VirtualCdromIsoBackingInfo', + 'backing' => new VirtualCdromIsoBackingInfo([ 'fileName' => $fileName, 'datastore' => [ 'type' => 'Datastore', '_' => $datastore, ], - ], - 'connectable' => [ + ]), + 'connectable' => new VirtualDeviceConnectInfo([ 'startConnected' => true, 'allowGuestControl' => true, 'connected' => true, - ], + ]), 'controllerKey' => $controllerKey, - ]; + ]); } - public function unmountVirtualCdRomSpec(int $key, int $controllerKey): array + public function unmountVirtualCdRomSpec(int $key, int $controllerKey): VirtualCdrom { - return [ - '@type' => 'VirtualCdrom', + return new VirtualCdrom([ 'key' => $key, - 'backing' => [ - '@type' => 'VirtualCdromRemoteAtapiBackingInfo', + 'backing' => new VirtualCdromRemoteAtapiBackingInfo([ 'deviceName' => 'CDRom', - ], - 'connectable' => [ + ]), + 'connectable' => new VirtualDeviceConnectInfo([ 'startConnected' => false, 'allowGuestControl' => false, 'connected' => false, - ], + ]), 'controllerKey' => $controllerKey, - ]; + ]); } public function fixedIpAdapterSpec(string $ip, string $subnetMask, array $dnsServerList, array $gateway): array { return [ - 'adapter' => [ - '@type' => 'CustomizationFixedIp', + 'adapter' => new CustomizationFixedIp([ 'ipAddress' => $ip, - ], + ]), 'subnetMask' => $subnetMask, 'dnsServerList' => $dnsServerList, 'gateway' => $gateway, @@ -216,28 +211,27 @@ public function customizationIdendity(string $hostname, string $license, string { return [ 'type' => 'CustomizationSysprep', - 'guiUnattended' => [ - 'password' => [ + 'guiUnattended' => new CustomizationGuiUnattended([ + 'password' => new CustomizationPassword([ 'plainText' => true, 'value' => $password, - ], + ]), 'timeZone' => 110, 'autoLogon' => true, 'autoLogonCount' => 1, - ], - 'userData' => [ + ]), + 'userData' => new CustomizationUserData([ 'fullName' => $name, 'orgName' => $name, - 'computerName' => [ - '@type' => 'CustomizationFixedName', + 'computerName' => new CustomizationFixedName([ 'name' => $hostname, - ], + ]), 'productId' => $license, - ], - 'identification' => [ + ]), + 'identification' => new CustomizationIdentification([ 'joinWorkgroup' => 'workgroup', - ], + ]), ]; } } diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index b753c56..b832137 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -16,7 +16,7 @@ trait SoapRequest * @param bool $convertToSoap * @return stdClass */ - private function request(string $method, array $requestBody, bool $convertToSoap = true): stdClass + public function request(string $method, array $requestBody, bool $convertToSoap = true): stdClass { try { $response = $this->soapClient->$method($convertToSoap ? $this->arrayToSoapVar($requestBody) : $requestBody); diff --git a/src/Traits/Soap/SoapGuestApis.php b/src/Traits/Soap/SoapGuestApis.php index 70679ef..646cae7 100644 --- a/src/Traits/Soap/SoapGuestApis.php +++ b/src/Traits/Soap/SoapGuestApis.php @@ -6,6 +6,7 @@ use GuzzleHttp\Client as GuzzleClient; use Xelon\VmWareClient\Requests\SoapRequest; use Xelon\VmWareClient\Transform\SoapTransform; +use Xelon\VmWareClient\Types\NamePasswordAuthentication; trait SoapGuestApis { @@ -41,12 +42,11 @@ public function initiateFileTransferToGuest( 'type' => 'VirtualMachine', '_' => $vmId, ], - 'auth' => [ - '@type' => 'NamePasswordAuthentication', + 'auth' => new NamePasswordAuthentication([ 'interactiveSession' => false, 'username' => $username, 'password' => $password, - ], + ]), 'guestFilePath' => "{$guestFilePath}", 'fileAttributes' => new \stdClass(), 'fileSize' => strlen($data), @@ -84,12 +84,11 @@ public function createTemporaryDirectoryInGuest( 'type' => 'VirtualMachine', '_' => $vmId, ], - 'auth' => [ - '@type' => 'NamePasswordAuthentication', + 'auth' => new NamePasswordAuthentication([ 'interactiveSession' => false, 'username' => $username, 'password' => $password, - ], + ]), 'prefix' => $prefix, 'suffix' => $sufix, 'directoryPath' => $directoryPath, @@ -113,12 +112,11 @@ public function deleteDirectoryInGuest( 'type' => 'VirtualMachine', '_' => $vmId, ], - 'auth' => [ - '@type' => 'NamePasswordAuthentication', + 'auth' => new NamePasswordAuthentication([ 'interactiveSession' => false, 'username' => $username, 'password' => $password, - ], + ]), 'directoryPath' => $directoryPath, 'recursive' => true, ]; @@ -141,12 +139,11 @@ public function deleteFileInGuest( 'type' => 'VirtualMachine', '_' => $vmId, ], - 'auth' => [ - '@type' => 'NamePasswordAuthentication', + 'auth' => new NamePasswordAuthentication([ 'interactiveSession' => false, 'username' => $username, 'password' => $password, - ], + ]), 'filePath' => $filePath, ]; @@ -169,12 +166,11 @@ public function startProgramInGuest( 'type' => 'VirtualMachine', '_' => $vmId, ], - 'auth' => [ - '@type' => 'NamePasswordAuthentication', + 'auth' => new NamePasswordAuthentication([ 'interactiveSession' => false, 'username' => $username, 'password' => $password, - ], + ]), 'spec' => [ 'programPath' => $program, 'arguments' => "{$filePath}", @@ -232,12 +228,11 @@ public function getListFilesInGuest( 'type' => 'VirtualMachine', '_' => $vmId, ], - 'auth' => [ - '@type' => 'NamePasswordAuthentication', + 'auth' => new NamePasswordAuthentication([ 'interactiveSession' => false, 'username' => $username, 'password' => $password, - ], + ]), 'filePath' => $filePath, ]; @@ -258,12 +253,12 @@ public function getListProcessInGuest( 'type' => 'VirtualMachine', '_' => $vmId, ], - 'auth' => [ + 'auth' => new NamePasswordAuthentication([ '@type' => 'NamePasswordAuthentication', 'interactiveSession' => false, 'username' => $username, 'password' => $password, - ], + ]), ]; return $this->request('ListProcessesInGuest', $body); @@ -280,12 +275,11 @@ public function validateCredentialsInGuest(string $username, string $password, s 'type' => 'VirtualMachine', '_' => $vmId, ], - 'auth' => [ - '@type' => 'NamePasswordAuthentication', + 'auth' => new NamePasswordAuthentication([ 'interactiveSession' => false, 'username' => $username, 'password' => $password, - ], + ]), ]; return $this->request('ValidateCredentialsInGuest', $body); diff --git a/src/Traits/Soap/SoapStorageApis.php b/src/Traits/Soap/SoapStorageApis.php index d4fc862..3b7bd1a 100644 --- a/src/Traits/Soap/SoapStorageApis.php +++ b/src/Traits/Soap/SoapStorageApis.php @@ -4,6 +4,7 @@ use Xelon\VmWareClient\Requests\SoapRequest; use Xelon\VmWareClient\Transform\SoapTransform; +use Xelon\VmWareClient\Types\VslmCreateSpecDiskFileBackingSpec; trait SoapStorageApis { @@ -58,13 +59,12 @@ public function createVStorage(string $name, int $capacityInMB, string $datastor 'spec' => [ 'name' => $name, 'keepAfterDeleteVm' => $keepAfterDeleteVm, - 'backingSpec' => [ - '@type' => 'VslmCreateSpecDiskFileBackingSpec', + 'backingSpec' => new VslmCreateSpecDiskFileBackingSpec([ 'datastore' => [ 'type' => 'Datastore', '_' => $datastore, ], - ], + ]), 'capacityInMB' => $capacityInMB, ], ]; diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index 952a3b1..e859ffe 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -5,6 +5,17 @@ use Illuminate\Support\Facades\Log; use Xelon\VmWareClient\Requests\SoapRequest; use Xelon\VmWareClient\Transform\SoapTransform; +use Xelon\VmWareClient\Types\ClusterAntiAffinityRuleSpec; +use Xelon\VmWareClient\Types\ClusterConfigSpecEx; +use Xelon\VmWareClient\Types\ClusterDpmConfigInfo; +use Xelon\VmWareClient\Types\ClusterDrsConfigInfo; +use Xelon\VmWareClient\Types\ClusterRuleSpec; +use Xelon\VmWareClient\Types\DVPortgroupConfigSpec; +use Xelon\VmWareClient\Types\DVPortSetting; +use Xelon\VmWareClient\Types\DVSTrafficShapingPolicy; +use Xelon\VmWareClient\Types\VirtualDeviceConfigSpec; +use Xelon\VmWareClient\Types\VirtualMachineBootOptionsBootableCdromDevice; +use Xelon\VmWareClient\Types\VirtualMachineConfigSpec; trait SoapVmApis { @@ -119,7 +130,7 @@ public function cloneVmTask(string $vmId, array $params) 'bootDelay' => $params['spec']['bootOptions']['bootDelay'] ?? 0, 'bootRetryEnabled' => $params['spec']['bootOptions']['bootRetryEnabled'] ?? true, 'bootOrder' => [ - '@type' => 'VirtualMachineBootOptionsBootableCdromDevice' + '@type' => new VirtualMachineBootOptionsBootableCdromDevice() ] ],*/ ], @@ -136,15 +147,13 @@ public function addDisk( string $name = 'New Hard disk' ) { $body = [ - 'spec' => [ - '@type' => 'VirtualMachineConfigSpec', - 'deviceChange' => [ - '@type' => 'VirtualDeviceConfigSpec', + 'spec' => new VirtualMachineConfigSpec([ + 'deviceChange' => new VirtualDeviceConfigSpec([ 'operation' => 'add', 'fileOperation' => 'create', 'device' => $this->data->addVirtualDiskSpec($capacityInKB, $unitNumber, $isHdd, $name), - ], - ], + ]), + ]), ]; return $this->reconfigVmTask($vmId, $body); @@ -153,14 +162,12 @@ public function addDisk( public function editDisk(string $vmId, array $params) { $body = [ - 'spec' => [ - '@type' => 'VirtualMachineConfigSpec', - 'deviceChange' => [ - '@type' => 'VirtualDeviceConfigSpec', + 'spec' => new VirtualMachineConfigSpec([ + 'deviceChange' => new VirtualDeviceConfigSpec([ 'operation' => 'edit', 'device' => $this->data->editVirtualDiskSpec($params), - ], - ], + ]), + ]), ]; return $this->reconfigVmTask($vmId, $body); @@ -169,14 +176,12 @@ public function editDisk(string $vmId, array $params) public function addPersistantDisk(string $vmId, string $blockStoragePath, int $capacityInKB, int $controllerKey = 1000) { $body = [ - 'spec' => [ - '@type' => 'VirtualMachineConfigSpec', - 'deviceChange' => [ - '@type' => 'VirtualDeviceConfigSpec', + 'spec' => new VirtualMachineConfigSpec([ + 'deviceChange' => new VirtualDeviceConfigSpec([ 'operation' => 'add', 'device' => $this->data->addBlockStorageSpec($blockStoragePath, $capacityInKB, $controllerKey), - ], - ], + ]), + ]), ]; return $this->reconfigVmTask($vmId, $this->arrayToSoapVar($body)); @@ -185,14 +190,12 @@ public function addPersistantDisk(string $vmId, string $blockStoragePath, int $c public function addNetwork(string $vmId, int $unitNumber, string $portgroupKey, string $switchUuid) { $body = [ - 'spec' => [ - '@type' => 'VirtualMachineConfigSpec', - 'deviceChange' => [ - '@type' => 'VirtualDeviceConfigSpec', + 'spec' => new VirtualMachineConfigSpec([ + 'deviceChange' => new VirtualDeviceConfigSpec([ 'operation' => 'add', 'device' => $this->data->addNetworkSpec($switchUuid, $portgroupKey, $unitNumber), - ], - ], + ]), + ]), ]; return $this->reconfigVmTask($vmId, $body); @@ -206,14 +209,12 @@ public function editNetwork( int $key ) { $body = [ - 'spec' => [ - '@type' => 'VirtualMachineConfigSpec', - 'deviceChange' => [ - '@type' => 'VirtualDeviceConfigSpec', + 'spec' => new VirtualMachineConfigSpec([ + 'deviceChange' => new VirtualDeviceConfigSpec([ 'operation' => 'edit', 'device' => $this->data->editNetworkSpec($switchUuid, $portgroupKey, $key, $macAddress), - ], - ], + ]), + ]), ]; return $this->reconfigVmTask($vmId, $body); @@ -222,14 +223,12 @@ public function editNetwork( public function addSasController(string $vmId) { $body = [ - 'spec' => [ - '@type' => 'VirtualMachineConfigSpec', - 'deviceChange' => [ - '@type' => 'VirtualLsiLogicSASController', + 'spec' => new VirtualMachineConfigSpec([ + 'deviceChange' => new VirtualDeviceConfigSpec([ 'operation' => 'add', 'device' => $this->data->addSasControllerSpec(), - ], - ], + ]), + ]), ]; return $this->reconfigVmTask($vmId, $body); @@ -245,13 +244,10 @@ public function changeDVPortgroupSpeed( '_' => $distributedVirtualPortgroupId, 'type' => 'DistributedVirtualPortgroup', ], - 'spec' => [ - '@type' => 'DVPortgroupConfigSpec', + 'spec' => new DVPortgroupConfigSpec([ 'configVersion' => $configVersion, - 'defaultPortConfig' => [ - '@type' => 'DVPortSetting', - 'inShapingPolicy' => [ - '@type' => 'DVSTrafficShapingPolicy', + 'defaultPortConfig' => new DVPortSetting([ + 'inShapingPolicy' => new DVSTrafficShapingPolicy([ 'inherited' => false, 'enabled' => [ 'inherited' => false, @@ -269,9 +265,8 @@ public function changeDVPortgroupSpeed( 'inherited' => false, 'value' => $speed, ], - ], - 'outShapingPolicy' => [ - '@type' => 'DVSTrafficShapingPolicy', + ]), + 'outShapingPolicy' => new DVSTrafficShapingPolicy([ 'inherited' => false, 'enabled' => [ 'inherited' => false, @@ -289,9 +284,9 @@ public function changeDVPortgroupSpeed( 'inherited' => false, 'value' => $speed, ], - ], - ], - ], + ]), + ]) + ]), ]; return $this->request('ReconfigureDVPortgroup_Task', $body); @@ -302,41 +297,36 @@ public function reconfigureComputeResource( string $name, array $vmIds ) { + $vm = []; + + foreach ($vmIds as $vmId) { + $vm[] = [ + '_' => $vmId, + 'type' => 'VirtualMachine', + ]; + } + $body = [ '_this' => [ '_' => $clusterComputerResourceId, 'type' => 'ComputeResource', ], - 'spec' => [ - '@type' => 'ClusterConfigSpecEx', - 'drsConfig' => [ - '@type' => 'ClusterDrsConfigInfo', - ], - 'rulesSpec' => [ - '@type' => 'ClusterRuleSpec', + 'spec' => new ClusterConfigSpecEx([ + 'drsConfig' => new ClusterDrsConfigInfo(), + 'rulesSpec' => new ClusterRuleSpec([ 'operation' => 'add', - 'info' => [ - '@type' => 'ClusterAntiAffinityRuleSpec', + 'info' => new ClusterAntiAffinityRuleSpec([ 'enabled' => true, 'name' => $name, 'userCreated' => true, - ], - ], - 'dpmConfig' => [ - '@type' => 'ClusterDpmConfigInfo', - ], - - ], + 'vm' => $vm + ]), + ]), + 'dpmConfig' => new ClusterDpmConfigInfo(), + ]), 'modify' => false, ]; - foreach ($vmIds as $vmId) { - $body['spec']['rulesSpec']['info']['vm'][] = [ - '_' => $vmId, - 'type' => 'VirtualMachine', - ]; - } - return $this->request('ReconfigureComputeResource_Task', $body); } @@ -350,9 +340,7 @@ public function mountIso(string $vmId, string $fileName, int $key, int $controll ], 'bootOptions' => [ 'bootDelay' => 5000, - 'bootOrder' => [ - '@type' => 'VirtualMachineBootOptionsBootableCdromDevice', - ], + 'bootOrder' => new VirtualMachineBootOptionsBootableCdromDevice(), ], ], ]; @@ -455,7 +443,7 @@ public function removeSnapshot(string $snapshopId, bool $removeChildren = true, 'type' => 'VirtualMachineSnapshot', ], 'removeChildren' => $removeChildren, - '$consolidate' => $consolidate, + 'consolidate' => $consolidate, ]; return $this->request('RemoveSnapshot_Task', $body); diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index dfd0db9..e59b0ff 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -4,6 +4,7 @@ use SoapVar; use stdClass; +use Xelon\VmWareClient\Types\Core\DynamicData; trait SoapTransform { @@ -12,7 +13,12 @@ public function arrayToSoapVar(array $array): array $typeName = null; $data = []; foreach ($array as $key => $value) { - if (is_array($value)) { + if (is_array($value) || $value instanceof DynamicData) { + if ($value instanceof DynamicData) { + $typeName = (new \ReflectionClass($value))->getShortName(); + $value = $value->toArray(); + } + if (array_key_exists('@type', $value)) { $typeName = $value['@type']; unset($value['@type']); diff --git a/src/Types/ArrayUpdateSpec.php b/src/Types/ArrayUpdateSpec.php new file mode 100644 index 0000000..933a4e4 --- /dev/null +++ b/src/Types/ArrayUpdateSpec.php @@ -0,0 +1,12 @@ + $value) { + if (property_exists(static::class, $property)) { + $this->{$property} = $value; + } + } + } + + public function toArray(): array + { + $data = []; + + foreach ($this as $property => $value) { + if ($value !== null) { + $data[$property] = $value; + } + } + + return $data; + } +} diff --git a/src/Types/CustomizationFixedIp.php b/src/Types/CustomizationFixedIp.php new file mode 100644 index 0000000..23304e1 --- /dev/null +++ b/src/Types/CustomizationFixedIp.php @@ -0,0 +1,8 @@ + Date: Wed, 12 Oct 2022 13:36:22 +0300 Subject: [PATCH 14/46] feat: created classes for object types --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d676ca2..84a2ba8 100644 --- a/README.md +++ b/README.md @@ -73,14 +73,15 @@ For now, the lib has only some methods available. You can find full list of file ​ > We plan to add the full list of methods later. ​ + Here's how to make your first SOAP call: ```php $folder = $vcenterClient->soap->createFolder('group-v3', 'foldername'); ``` ​ -If you want to use both modes at one time you can set `both` mode (Xelon\VmWareClient\VcenterClient::MODE_BOTH). +If you want to use both modes at one time you can set `both` mode (Xelon\VmWareClient\VcenterClient::MODE_BOTH). ​ -If you want to run custom `soap` method, which you do not find in lib, you can run this method directly: + If you want to run custom `soap` method, which you do not find in lib, you can run this method directly: ```php $vcenterClient = new Xelon\VmWareClient\VcenterClient( 'https://10.20.30.40', From 0206ad3c8849f082fac83694d2286aa71a41be13 Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Wed, 12 Oct 2022 10:36:59 +0000 Subject: [PATCH 15/46] Fix styling --- src/Traits/Soap/SoapVmApis.php | 4 ++-- src/Types/ComputeResourceConfigSpec.php | 1 - src/Types/CustomizationIpGenerator.php | 1 - src/Types/DVPortgroupConfigSpec.php | 1 - src/Types/VirtualCdrom.php | 1 - src/Types/VirtualCdromIsoBackingInfo.php | 1 - src/Types/VirtualCdromRemoteAtapiBackingInfo.php | 1 - src/Types/VirtualDeviceBackingInfo.php | 1 - src/Types/VirtualLsiLogicSASController.php | 1 - src/Types/VirtualMachineBootOptionsBootableCdromDevice.php | 1 - src/Types/VirtualMachineBootOptionsBootableDevice.php | 1 - src/Types/VirtualVmxnet.php | 1 - src/Types/VirtualVmxnet3.php | 1 - 13 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index e859ffe..403f779 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -285,7 +285,7 @@ public function changeDVPortgroupSpeed( 'value' => $speed, ], ]), - ]) + ]), ]), ]; @@ -319,7 +319,7 @@ public function reconfigureComputeResource( 'enabled' => true, 'name' => $name, 'userCreated' => true, - 'vm' => $vm + 'vm' => $vm, ]), ]), 'dpmConfig' => new ClusterDpmConfigInfo(), diff --git a/src/Types/ComputeResourceConfigSpec.php b/src/Types/ComputeResourceConfigSpec.php index 08429e9..7461bf0 100644 --- a/src/Types/ComputeResourceConfigSpec.php +++ b/src/Types/ComputeResourceConfigSpec.php @@ -13,5 +13,4 @@ class ComputeResourceConfigSpec extends DynamicData public $defaultHardwareVersionKey; public $desiredSoftwareSpec; - } diff --git a/src/Types/CustomizationIpGenerator.php b/src/Types/CustomizationIpGenerator.php index b3ff9d6..6437ea2 100644 --- a/src/Types/CustomizationIpGenerator.php +++ b/src/Types/CustomizationIpGenerator.php @@ -6,5 +6,4 @@ class CustomizationIpGenerator extends DynamicData { - } diff --git a/src/Types/DVPortgroupConfigSpec.php b/src/Types/DVPortgroupConfigSpec.php index 64b1f2a..c734b3f 100644 --- a/src/Types/DVPortgroupConfigSpec.php +++ b/src/Types/DVPortgroupConfigSpec.php @@ -39,5 +39,4 @@ class DVPortgroupConfigSpec extends DynamicData public $logicalSwitchUuid; public $segmentId; - } diff --git a/src/Types/VirtualCdrom.php b/src/Types/VirtualCdrom.php index fa0bb21..80322dd 100644 --- a/src/Types/VirtualCdrom.php +++ b/src/Types/VirtualCdrom.php @@ -4,5 +4,4 @@ class VirtualCdrom extends VirtualDevice { - } diff --git a/src/Types/VirtualCdromIsoBackingInfo.php b/src/Types/VirtualCdromIsoBackingInfo.php index ad7def7..95e291c 100644 --- a/src/Types/VirtualCdromIsoBackingInfo.php +++ b/src/Types/VirtualCdromIsoBackingInfo.php @@ -4,5 +4,4 @@ class VirtualCdromIsoBackingInfo extends VirtualDeviceFileBackingInfo { - } diff --git a/src/Types/VirtualCdromRemoteAtapiBackingInfo.php b/src/Types/VirtualCdromRemoteAtapiBackingInfo.php index e45dcea..a988f35 100644 --- a/src/Types/VirtualCdromRemoteAtapiBackingInfo.php +++ b/src/Types/VirtualCdromRemoteAtapiBackingInfo.php @@ -4,5 +4,4 @@ class VirtualCdromRemoteAtapiBackingInfo extends VirtualDeviceRemoteDeviceBackingInfo { - } diff --git a/src/Types/VirtualDeviceBackingInfo.php b/src/Types/VirtualDeviceBackingInfo.php index 2be0f85..bccec7c 100644 --- a/src/Types/VirtualDeviceBackingInfo.php +++ b/src/Types/VirtualDeviceBackingInfo.php @@ -6,5 +6,4 @@ class VirtualDeviceBackingInfo extends DynamicData { - } diff --git a/src/Types/VirtualLsiLogicSASController.php b/src/Types/VirtualLsiLogicSASController.php index 2ac4630..1a74f91 100644 --- a/src/Types/VirtualLsiLogicSASController.php +++ b/src/Types/VirtualLsiLogicSASController.php @@ -4,5 +4,4 @@ class VirtualLsiLogicSASController extends VirtualSCSIController { - } diff --git a/src/Types/VirtualMachineBootOptionsBootableCdromDevice.php b/src/Types/VirtualMachineBootOptionsBootableCdromDevice.php index da45e98..eb8fda3 100644 --- a/src/Types/VirtualMachineBootOptionsBootableCdromDevice.php +++ b/src/Types/VirtualMachineBootOptionsBootableCdromDevice.php @@ -4,5 +4,4 @@ class VirtualMachineBootOptionsBootableCdromDevice extends VirtualMachineBootOptionsBootableDevice { - } diff --git a/src/Types/VirtualMachineBootOptionsBootableDevice.php b/src/Types/VirtualMachineBootOptionsBootableDevice.php index 63e7771..8e8e175 100644 --- a/src/Types/VirtualMachineBootOptionsBootableDevice.php +++ b/src/Types/VirtualMachineBootOptionsBootableDevice.php @@ -6,5 +6,4 @@ class VirtualMachineBootOptionsBootableDevice extends DynamicData { - } diff --git a/src/Types/VirtualVmxnet.php b/src/Types/VirtualVmxnet.php index ca876ad..2ba09e3 100644 --- a/src/Types/VirtualVmxnet.php +++ b/src/Types/VirtualVmxnet.php @@ -6,5 +6,4 @@ class VirtualVmxnet extends DynamicData { - } diff --git a/src/Types/VirtualVmxnet3.php b/src/Types/VirtualVmxnet3.php index 17b0cee..893bd71 100644 --- a/src/Types/VirtualVmxnet3.php +++ b/src/Types/VirtualVmxnet3.php @@ -4,5 +4,4 @@ class VirtualVmxnet3 extends VirtualVmxnet { - } From 850f37e58c5008080aa1f7c5383c48ba193e0863 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Mon, 17 Oct 2022 11:30:29 +0300 Subject: [PATCH 16/46] feat: alternative way to get soap session token --- src/VmWareClientInit.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/VmWareClientInit.php b/src/VmWareClientInit.php index 9ebf13f..a0fc0b9 100755 --- a/src/VmWareClientInit.php +++ b/src/VmWareClientInit.php @@ -158,8 +158,19 @@ private function createSoapSession(): void ]; $this->soapClient->Login($loginMessage); + if (isset($this->soapClient->_cookies)) { + $sessionToken = $this->soapClient->_cookies['vmware_soap_session'][0]; + } else { + $responseHeaders = $this->soapClient->__last_response_headers; + + $string = strstr($responseHeaders, 'vmware_soap_session'); + $string = strstr($string, '"'); + $string = ltrim($string, '"'); + $sessionToken = substr($string, 0, strpos($string, '"')); + } + Cache::add("vcenter-soap-session-$this->ip", [ - 'vmware_soap_session' => $this->soapClient->_cookies['vmware_soap_session'][0], + 'vmware_soap_session' => $sessionToken, 'expired_at' => Carbon::now()->addSeconds(config('vmware-php-client.session_ttl') * 60 - 30), ]); } catch (\Exception $e) { From 132f6d4ccf70a561623021e3d6acf53c746581ce Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Mon, 17 Oct 2022 14:43:11 +0300 Subject: [PATCH 17/46] feat: alternative way to get soap session token --- src/VmWareClientInit.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/VmWareClientInit.php b/src/VmWareClientInit.php index a0fc0b9..e64f956 100755 --- a/src/VmWareClientInit.php +++ b/src/VmWareClientInit.php @@ -126,6 +126,7 @@ private function initSoapSession(): void if (! $sessionInfo) { $this->createSoapSession(); } elseif ($this->isSessionExpired($sessionInfo['expired_at'])) { + $this->deleteSoapSession(); $this->createSoapSession(); } else { $this->createSoapClientWithExistingSession($sessionInfo['vmware_soap_session']); @@ -175,6 +176,7 @@ private function createSoapSession(): void ]); } catch (\Exception $e) { Log::error('Soap api exception : '.$e->getMessage()); + throw new \Exception($e->getMessage()); } } @@ -197,12 +199,16 @@ private function createSoapClientWithExistingSession(string $soapSessionToken) private function deleteSoapSession() { - $sessionManager = new \stdClass(); - $sessionManager->_ = $sessionManager->type = 'SessionManager'; + try { + Cache::forget("vcenter-soap-session-$this->ip"); - $soaplogout['_this'] = $sessionManager; - $this->soapClient->Logout($soaplogout); + $sessionManager = new \stdClass(); + $sessionManager->_ = $sessionManager->type = 'SessionManager'; - Cache::forget("vcenter-soap-session-$this->ip"); + $soaplogout['_this'] = $sessionManager; + $this->soapClient->Logout($soaplogout); + } catch (\Exception $exception) { + Log::error('Can\'t delete soap session'); + } } } From a461c2d28699c8f10bbb79a119813f41a186c9d2 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Mon, 17 Oct 2022 17:58:08 +0300 Subject: [PATCH 18/46] feat: alternative way to get soap session token --- src/Requests/SoapRequest.php | 2 +- src/VmWareClientInit.php | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index b832137..d125a39 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -16,7 +16,7 @@ trait SoapRequest * @param bool $convertToSoap * @return stdClass */ - public function request(string $method, array $requestBody, bool $convertToSoap = true): stdClass + public function request(string $method, array $requestBody, bool $convertToSoap = true) { try { $response = $this->soapClient->$method($convertToSoap ? $this->arrayToSoapVar($requestBody) : $requestBody); diff --git a/src/VmWareClientInit.php b/src/VmWareClientInit.php index e64f956..1710921 100755 --- a/src/VmWareClientInit.php +++ b/src/VmWareClientInit.php @@ -160,18 +160,19 @@ private function createSoapSession(): void $this->soapClient->Login($loginMessage); if (isset($this->soapClient->_cookies)) { - $sessionToken = $this->soapClient->_cookies['vmware_soap_session'][0]; + $soapSessionToken = $this->soapClient->_cookies['vmware_soap_session'][0]; } else { $responseHeaders = $this->soapClient->__last_response_headers; $string = strstr($responseHeaders, 'vmware_soap_session'); $string = strstr($string, '"'); $string = ltrim($string, '"'); - $sessionToken = substr($string, 0, strpos($string, '"')); + $soapSessionToken = substr($string, 0, strpos($string, '"')); + $this->soapClient->__setCookie('vmware_soap_session', $soapSessionToken); } Cache::add("vcenter-soap-session-$this->ip", [ - 'vmware_soap_session' => $sessionToken, + 'vmware_soap_session' => $soapSessionToken, 'expired_at' => Carbon::now()->addSeconds(config('vmware-php-client.session_ttl') * 60 - 30), ]); } catch (\Exception $e) { From 92eeb1a60876e2cd8e18ab9bf966930a2d38944f Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Tue, 18 Oct 2022 14:19:25 +0300 Subject: [PATCH 19/46] feat: get array class properties in right order --- src/Types/Core/DynamicData.php | 30 +++++++++++++++++++++++++++--- src/VmWareClientInit.php | 1 - 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/Types/Core/DynamicData.php b/src/Types/Core/DynamicData.php index e57ab39..b893a68 100644 --- a/src/Types/Core/DynamicData.php +++ b/src/Types/Core/DynamicData.php @@ -13,13 +13,37 @@ public function __construct(array $data = []) } } + /** + * @return array + * Generate array of class properties in order from parent to child + */ public function toArray(): array { $data = []; + $classes = []; + $properties = []; - foreach ($this as $property => $value) { - if ($value !== null) { - $data[$property] = $value; + $currentClass = static::class; + while ($currentClass && $currentClass !== self::class) { + $classes[] = $currentClass; + $currentClass = get_parent_class($currentClass); + } + + $classes = array_reverse($classes); + + foreach ($classes as $class) { + $classInfo = new \ReflectionClass($class); + + foreach ($classInfo->getProperties() as $prop) { + if ($prop->class === $class) { + $properties[] = $prop->getName(); + } + } + } + + foreach ($properties as $property) { + if ($this->$property !== null) { + $data[$property] = $this->$property; } } diff --git a/src/VmWareClientInit.php b/src/VmWareClientInit.php index 1710921..087bee3 100755 --- a/src/VmWareClientInit.php +++ b/src/VmWareClientInit.php @@ -126,7 +126,6 @@ private function initSoapSession(): void if (! $sessionInfo) { $this->createSoapSession(); } elseif ($this->isSessionExpired($sessionInfo['expired_at'])) { - $this->deleteSoapSession(); $this->createSoapSession(); } else { $this->createSoapClientWithExistingSession($sessionInfo['vmware_soap_session']); From 13fdeda2cefe7ab9c010e1d92272db235309c677 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Tue, 18 Oct 2022 14:44:01 +0300 Subject: [PATCH 20/46] fix --- src/Types/VirtualVmxnet.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Types/VirtualVmxnet.php b/src/Types/VirtualVmxnet.php index 2ba09e3..d9db879 100644 --- a/src/Types/VirtualVmxnet.php +++ b/src/Types/VirtualVmxnet.php @@ -2,8 +2,6 @@ namespace Xelon\VmWareClient\Types; -use Xelon\VmWareClient\Types\Core\DynamicData; - -class VirtualVmxnet extends DynamicData +class VirtualVmxnet extends VirtualEthernetCard { } From 3d219af48c34fff8c757ff4d51cd5ba06c4a10a3 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Tue, 18 Oct 2022 16:25:26 +0300 Subject: [PATCH 21/46] fix --- src/Traits/Soap/SoapGuestApis.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Traits/Soap/SoapGuestApis.php b/src/Traits/Soap/SoapGuestApis.php index 646cae7..5ab432d 100644 --- a/src/Traits/Soap/SoapGuestApis.php +++ b/src/Traits/Soap/SoapGuestApis.php @@ -58,12 +58,12 @@ public function initiateFileTransferToGuest( $client = new GuzzleClient(['verify' => false]); try { - if (is_string($response->returnval) && substr($response->returnval, 0, 4) !== 'http') { + if (isset($response->returnval) && is_string($response->returnval) && substr($response->returnval, 0, 4) !== 'http') { throw new Exception('File transfer invalid response url'); } $client->request('PUT', $response->returnval, ['body' => $data]); } catch (Exception $e) { - throw new Exception($e->getMessage()); + throw new Exception("{$e->getMessage()}. Resonse: " . json_encode($response)); } } From 50336f191386e18acb3a571e20b100c92fa6996f Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Tue, 18 Oct 2022 16:25:40 +0300 Subject: [PATCH 22/46] fix --- src/Traits/Soap/SoapGuestApis.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Traits/Soap/SoapGuestApis.php b/src/Traits/Soap/SoapGuestApis.php index 5ab432d..da00e41 100644 --- a/src/Traits/Soap/SoapGuestApis.php +++ b/src/Traits/Soap/SoapGuestApis.php @@ -63,7 +63,7 @@ public function initiateFileTransferToGuest( } $client->request('PUT', $response->returnval, ['body' => $data]); } catch (Exception $e) { - throw new Exception("{$e->getMessage()}. Resonse: " . json_encode($response)); + throw new Exception("{$e->getMessage()}. Response: " . json_encode($response)); } } From 4bb5d6c00e0497f135b110c6e09ad36ceccdaed6 Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Tue, 18 Oct 2022 13:26:23 +0000 Subject: [PATCH 23/46] Fix styling --- src/Traits/Soap/SoapGuestApis.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Traits/Soap/SoapGuestApis.php b/src/Traits/Soap/SoapGuestApis.php index da00e41..61c1f96 100644 --- a/src/Traits/Soap/SoapGuestApis.php +++ b/src/Traits/Soap/SoapGuestApis.php @@ -63,7 +63,7 @@ public function initiateFileTransferToGuest( } $client->request('PUT', $response->returnval, ['body' => $data]); } catch (Exception $e) { - throw new Exception("{$e->getMessage()}. Response: " . json_encode($response)); + throw new Exception("{$e->getMessage()}. Response: ".json_encode($response)); } } From adfcc8b9eb83899770d2760a70d87b7f799380e3 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Thu, 20 Oct 2022 12:11:18 +0300 Subject: [PATCH 24/46] fix: added tag name to soap array object --- src/Requests/SoapRequest.php | 4 ++-- src/Traits/Soap/SoapVmApis.php | 2 +- src/Transform/SoapTransform.php | 15 ++++++++++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index d125a39..ab31b7e 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -34,8 +34,8 @@ public function request(string $method, array $requestBody, bool $convertToSoap Log::error( "SOAP REQUEST FAILED:\nMessage: ".$exception->getMessage(). "\nSOAP method: ".$method. - "\nSOAP request: ".$this->soapClient->__last_request. - "\nSOAP response: ".$this->soapClient->__last_response + "\nSOAP request: ".$this->soapClient->__last_request ?? ''. + "\nSOAP response: ".$this->soapClient->__last_response ?? '' ); } } diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index 403f779..1483f8b 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -136,7 +136,7 @@ public function cloneVmTask(string $vmId, array $params) ], ]; - return $this->vmRequest('CloneVM_Task', $vmId, $this->arrayToSoapVar($body)); + return $this->vmRequest('CloneVM_Task', $vmId, $body); } public function addDisk( diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index e59b0ff..8d5554a 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -8,6 +8,15 @@ trait SoapTransform { + private $soapTypes = [ + 'string' => XSD_STRING, + 'integer' => XSD_INT, + 'boolean' => XSD_BOOLEAN, + 'double' => XSD_FLOAT, + 'array' => SOAP_ENC_OBJECT, + 'object' => SOAP_ENC_OBJECT, + ]; + public function arrayToSoapVar(array $array): array { $typeName = null; @@ -43,7 +52,7 @@ public function arrayToSoapVar(array $array): array continue; } - $data[] = new SoapVar($this->arrayToSoapVar($childItem), SOAP_ENC_OBJECT, $typeName, null); + $data[] = new SoapVar($this->arrayToSoapVar($childItem), SOAP_ENC_OBJECT, $typeName, null, $key); } unset($array[$key]); @@ -52,12 +61,12 @@ public function arrayToSoapVar(array $array): array } if (! isset($deepArraySet)) { - $data[$key] = new SoapVar($this->arrayToSoapVar($value), SOAP_ENC_OBJECT, $typeName, null, $key); + $data[] = new SoapVar($this->arrayToSoapVar($value), SOAP_ENC_OBJECT, $typeName, null, $key); } $typeName = null; } elseif (! is_null($value)) { - $data[$key] = $value; + $data[] = new SoapVar($value, null, $this->soapTypes[gettype($value)] ?? null, null, $key); } } From e1abae53b9c4b4d8eaa8c5c21da78279c6969c6a Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Fri, 21 Oct 2022 12:41:03 +0300 Subject: [PATCH 25/46] fix --- src/Traits/Soap/SoapGuestApis.php | 2 +- src/Transform/SoapTransform.php | 6 +++--- src/Types/VirtualDiskFlatVer2BackingInfo.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Traits/Soap/SoapGuestApis.php b/src/Traits/Soap/SoapGuestApis.php index 61c1f96..d9b8721 100644 --- a/src/Traits/Soap/SoapGuestApis.php +++ b/src/Traits/Soap/SoapGuestApis.php @@ -58,7 +58,7 @@ public function initiateFileTransferToGuest( $client = new GuzzleClient(['verify' => false]); try { - if (isset($response->returnval) && is_string($response->returnval) && substr($response->returnval, 0, 4) !== 'http') { + if (!isset($response->returnval) || !is_string($response->returnval) || substr($response->returnval, 0, 4) !== 'http') { throw new Exception('File transfer invalid response url'); } $client->request('PUT', $response->returnval, ['body' => $data]); diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index 8d5554a..8d8f152 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -47,7 +47,7 @@ public function arrayToSoapVar(array $array): array } if (array_key_exists('type', $childItem)) { - $data[] = new SoapVar($childItem['_'], null, $childItem['type'], '', $key, ''); + $data[$key] = new SoapVar($childItem['_'], null, $childItem['type'], '', $key, ''); continue; } @@ -61,12 +61,12 @@ public function arrayToSoapVar(array $array): array } if (! isset($deepArraySet)) { - $data[] = new SoapVar($this->arrayToSoapVar($value), SOAP_ENC_OBJECT, $typeName, null, $key); + $data[$key] = new SoapVar($this->arrayToSoapVar($value), SOAP_ENC_OBJECT, $typeName, null, $key); } $typeName = null; } elseif (! is_null($value)) { - $data[] = new SoapVar($value, null, $this->soapTypes[gettype($value)] ?? null, null, $key); + $data[$key] = new SoapVar($value, null, null, null, $key); } } diff --git a/src/Types/VirtualDiskFlatVer2BackingInfo.php b/src/Types/VirtualDiskFlatVer2BackingInfo.php index f1bc98c..450bef3 100644 --- a/src/Types/VirtualDiskFlatVer2BackingInfo.php +++ b/src/Types/VirtualDiskFlatVer2BackingInfo.php @@ -2,7 +2,7 @@ namespace Xelon\VmWareClient\Types; -class VirtualDiskFlatVer2BackingInfo extends VirtualDeviceBackingInfo +class VirtualDiskFlatVer2BackingInfo extends VirtualDeviceFileBackingInfo { public $diskMode; From 32168c82b93716d0d9d83ad46c645a307e4e5169 Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Fri, 21 Oct 2022 09:41:31 +0000 Subject: [PATCH 26/46] Fix styling --- src/Traits/Soap/SoapGuestApis.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Traits/Soap/SoapGuestApis.php b/src/Traits/Soap/SoapGuestApis.php index d9b8721..0bd34e8 100644 --- a/src/Traits/Soap/SoapGuestApis.php +++ b/src/Traits/Soap/SoapGuestApis.php @@ -58,7 +58,7 @@ public function initiateFileTransferToGuest( $client = new GuzzleClient(['verify' => false]); try { - if (!isset($response->returnval) || !is_string($response->returnval) || substr($response->returnval, 0, 4) !== 'http') { + if (! isset($response->returnval) || ! is_string($response->returnval) || substr($response->returnval, 0, 4) !== 'http') { throw new Exception('File transfer invalid response url'); } $client->request('PUT', $response->returnval, ['body' => $data]); From f62e1299d3b038d28e45c8cd915d7afe5c9726eb Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Mon, 24 Oct 2022 12:27:51 +0300 Subject: [PATCH 27/46] feat: created classes for customization --- src/Data/SoapData.php | 31 +++++++++++---------- src/Requests/SoapRequest.php | 10 ++++--- src/Transform/SoapTransform.php | 23 +++++++++++---- src/Types/Core/DynamicData.php | 15 +++++++++- src/Types/CustomizationAdapterMapping.php | 12 ++++++++ src/Types/CustomizationGlobalIPSettings.php | 12 ++++++++ src/Types/CustomizationIPSettings.php | 26 +++++++++++++++++ src/Types/CustomizationIdentitySettings.php | 9 ++++++ src/Types/CustomizationSpec.php | 18 ++++++++++++ src/Types/CustomizationSysprep.php | 16 +++++++++++ 10 files changed, 147 insertions(+), 25 deletions(-) create mode 100644 src/Types/CustomizationAdapterMapping.php create mode 100644 src/Types/CustomizationGlobalIPSettings.php create mode 100644 src/Types/CustomizationIPSettings.php create mode 100644 src/Types/CustomizationIdentitySettings.php create mode 100644 src/Types/CustomizationSpec.php create mode 100644 src/Types/CustomizationSysprep.php diff --git a/src/Data/SoapData.php b/src/Data/SoapData.php index 9fec6bc..560df94 100644 --- a/src/Data/SoapData.php +++ b/src/Data/SoapData.php @@ -2,11 +2,14 @@ namespace Xelon\VmWareClient\Data; +use Xelon\VmWareClient\Types\CustomizationAdapterMapping; use Xelon\VmWareClient\Types\CustomizationFixedIp; use Xelon\VmWareClient\Types\CustomizationFixedName; use Xelon\VmWareClient\Types\CustomizationGuiUnattended; use Xelon\VmWareClient\Types\CustomizationIdentification; +use Xelon\VmWareClient\Types\CustomizationIPSettings; use Xelon\VmWareClient\Types\CustomizationPassword; +use Xelon\VmWareClient\Types\CustomizationSysprep; use Xelon\VmWareClient\Types\CustomizationUserData; use Xelon\VmWareClient\Types\Description; use Xelon\VmWareClient\Types\DistributedVirtualSwitchPortConnection; @@ -194,23 +197,23 @@ public function unmountVirtualCdRomSpec(int $key, int $controllerKey): VirtualCd ]); } - public function fixedIpAdapterSpec(string $ip, string $subnetMask, array $dnsServerList, array $gateway): array + public function fixedIpAdapterSpec(string $ip, string $subnetMask, array $dnsServerList, array $gateway): CustomizationAdapterMapping { - return [ - 'adapter' => new CustomizationFixedIp([ - 'ipAddress' => $ip, - ]), - 'subnetMask' => $subnetMask, - 'dnsServerList' => $dnsServerList, - 'gateway' => $gateway, - - ]; + return new CustomizationAdapterMapping([ + 'adapter' => new CustomizationIPSettings([ + 'ip' => new CustomizationFixedIp([ + 'ipAddress' => $ip, + ]), + 'subnetMask' => $subnetMask, + 'dnsServerList' => $dnsServerList, + 'gateway' => $gateway, + ]) + ]); } - public function customizationIdendity(string $hostname, string $license, string $password, string $name): array + public function customizationIdendity(string $hostname, string $license, string $password, string $name): CustomizationSysprep { - return [ - 'type' => 'CustomizationSysprep', + return new CustomizationSysprep([ 'guiUnattended' => new CustomizationGuiUnattended([ 'password' => new CustomizationPassword([ 'plainText' => true, @@ -232,6 +235,6 @@ public function customizationIdendity(string $hostname, string $license, string 'identification' => new CustomizationIdentification([ 'joinWorkgroup' => 'workgroup', ]), - ]; + ]); } } diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index ab31b7e..f27ffa8 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -31,12 +31,14 @@ public function request(string $method, array $requestBody, bool $convertToSoap return $response; } catch (\Exception $exception) { - Log::error( - "SOAP REQUEST FAILED:\nMessage: ".$exception->getMessage(). + $message = "SOAP REQUEST FAILED:\nMessage: ".$exception->getMessage(). "\nSOAP method: ".$method. "\nSOAP request: ".$this->soapClient->__last_request ?? ''. - "\nSOAP response: ".$this->soapClient->__last_response ?? '' - ); + "\nSOAP response: ".$this->soapClient->__last_response ?? ''. + "\nTrace: " . json_encode($exception->getTrace()); + + Log::error($message); + throw new \Exception($message); } } diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index 8d8f152..28f6a52 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -41,13 +41,24 @@ public function arrayToSoapVar(array $array): array if (is_array($value) && array_key_exists(0, $value)) { foreach ($value as $childItem) { - if (array_key_exists('@type', $childItem)) { - $typeName = $childItem['@type']; - unset($childItem['@type']); + if ($childItem instanceof DynamicData) { + $typeName = (new \ReflectionClass($childItem))->getShortName(); + $childItem = $childItem->toArray(); } - if (array_key_exists('type', $childItem)) { - $data[$key] = new SoapVar($childItem['_'], null, $childItem['type'], '', $key, ''); + if (is_array($childItem)) { + if (array_key_exists('@type', $childItem)) { + $typeName = $childItem['@type']; + unset($childItem['@type']); + } + + if (array_key_exists('type', $childItem)) { + $data[$key] = new SoapVar($childItem['_'], null, $childItem['type'], '', $key, ''); + + continue; + } + } else { + $data[$key] = new SoapVar($childItem, null, null, null, $key); continue; } @@ -55,7 +66,7 @@ public function arrayToSoapVar(array $array): array $data[] = new SoapVar($this->arrayToSoapVar($childItem), SOAP_ENC_OBJECT, $typeName, null, $key); } - unset($array[$key]); + // unset($array[$key]); $deepArraySet = true; } diff --git a/src/Types/Core/DynamicData.php b/src/Types/Core/DynamicData.php index b893a68..241f88b 100644 --- a/src/Types/Core/DynamicData.php +++ b/src/Types/Core/DynamicData.php @@ -2,7 +2,7 @@ namespace Xelon\VmWareClient\Types\Core; -class DynamicData +class DynamicData implements \Countable { public function __construct(array $data = []) { @@ -49,4 +49,17 @@ public function toArray(): array return $data; } + + public function count(): int + { + $count = 0; + + foreach ($this as $property) { + if ($property !== null) { + $count++; + } + } + + return $count; + } } diff --git a/src/Types/CustomizationAdapterMapping.php b/src/Types/CustomizationAdapterMapping.php new file mode 100644 index 0000000..4ff1452 --- /dev/null +++ b/src/Types/CustomizationAdapterMapping.php @@ -0,0 +1,12 @@ + Date: Mon, 24 Oct 2022 09:29:22 +0000 Subject: [PATCH 28/46] Fix styling --- src/Data/SoapData.php | 2 +- src/Requests/SoapRequest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Data/SoapData.php b/src/Data/SoapData.php index 560df94..5e9e736 100644 --- a/src/Data/SoapData.php +++ b/src/Data/SoapData.php @@ -207,7 +207,7 @@ public function fixedIpAdapterSpec(string $ip, string $subnetMask, array $dnsSer 'subnetMask' => $subnetMask, 'dnsServerList' => $dnsServerList, 'gateway' => $gateway, - ]) + ]), ]); } diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index f27ffa8..733fce4 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -35,7 +35,7 @@ public function request(string $method, array $requestBody, bool $convertToSoap "\nSOAP method: ".$method. "\nSOAP request: ".$this->soapClient->__last_request ?? ''. "\nSOAP response: ".$this->soapClient->__last_response ?? ''. - "\nTrace: " . json_encode($exception->getTrace()); + "\nTrace: ".json_encode($exception->getTrace()); Log::error($message); throw new \Exception($message); From 777a61a8cf522f2318bfcc001125007be71b6939 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Mon, 24 Oct 2022 13:49:34 +0300 Subject: [PATCH 29/46] feat: throw exeption if vm id format is incorrect --- src/Traits/Soap/SoapVmApis.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index 1483f8b..78cbb9f 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -49,6 +49,10 @@ public function getObjectInfo(string $objectId, string $objectType, string $path public function getVmInfo(string $vmId, string $pathSet = '') { + if (substr($vmId, 0, 2) !== 'vm') { + throw new \Exception('Wrong vm id format!'); + } + return $this->getObjectInfo($vmId, 'VirtualMachine', $pathSet); } From 90b1274311445ee681e2929e76e13744323d34a9 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Wed, 26 Oct 2022 16:03:34 +0300 Subject: [PATCH 30/46] feat: added listFilelInGuest and makeDirectoryInGuest methods --- src/Requests/SoapRequest.php | 17 ++++++--- src/Traits/Soap/SoapGuestApis.php | 60 +++++++++++++++++++++++++++++++ src/Types/Core/DynamicData.php | 7 +++- 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index 733fce4..d0eb9f3 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -31,11 +31,18 @@ public function request(string $method, array $requestBody, bool $convertToSoap return $response; } catch (\Exception $exception) { - $message = "SOAP REQUEST FAILED:\nMessage: ".$exception->getMessage(). - "\nSOAP method: ".$method. - "\nSOAP request: ".$this->soapClient->__last_request ?? ''. - "\nSOAP response: ".$this->soapClient->__last_response ?? ''. - "\nTrace: ".json_encode($exception->getTrace()); + $message = "SOAP REQUEST FAILED:\nMessage: " . $exception->getMessage() . + "\nSOAP method: " . $method . + ( + property_exists($this->soapClient, '__last_request') + ? "\nSOAP request: " . $this->soapClient->__last_request + : '' + ) . ( + property_exists($this->soapClient, '__last_request') + ? "\nSOAP response: " . $this->soapClient->__last_response + : '' + ) . + "\nTrace: " . json_encode($exception->getTrace()); Log::error($message); throw new \Exception($message); diff --git a/src/Traits/Soap/SoapGuestApis.php b/src/Traits/Soap/SoapGuestApis.php index 0bd34e8..8d28650 100644 --- a/src/Traits/Soap/SoapGuestApis.php +++ b/src/Traits/Soap/SoapGuestApis.php @@ -97,6 +97,66 @@ public function createTemporaryDirectoryInGuest( return $this->request('CreateTemporaryDirectoryInGuest', $body); } + public function makeDirectoryInGuest( + string $username, + string $password, + string $vmId, + string $directoryPath, + bool $createParentDirectories = false + ) { + $body = [ + '_this' => [ + 'type' => 'GuestFileManager', + '_' => 'guestOperationsFileManager', + ], + 'vm' => [ + 'type' => 'VirtualMachine', + '_' => $vmId, + ], + 'auth' => new NamePasswordAuthentication([ + 'interactiveSession' => false, + 'username' => $username, + 'password' => $password, + ]), + 'directoryPath' => $directoryPath, + 'createParentDirectories' => $createParentDirectories + ]; + + return $this->request('MakeDirectoryInGuest', $body); + } + + public function listFilesInGuest( + string $username, + string $password, + string $vmId, + string $filePath, + int $index = 0, + int $maxResults = 50, + ?string $matchPattern = null + ) { + $body = [ + '_this' => [ + 'type' => 'GuestFileManager', + '_' => 'guestOperationsFileManager', + ], + 'vm' => [ + 'type' => 'VirtualMachine', + '_' => $vmId, + ], + 'auth' => new NamePasswordAuthentication([ + 'interactiveSession' => false, + 'username' => $username, + 'password' => $password, + ]), + 'filePath' => $filePath, + 'index' => $index, + 'maxResults' => $maxResults, + 'matchPattern' => $matchPattern + ]; + + return $this->request('ListFilesInGuest', $body); + } + public function deleteDirectoryInGuest( string $username, string $password, diff --git a/src/Types/Core/DynamicData.php b/src/Types/Core/DynamicData.php index 241f88b..b126594 100644 --- a/src/Types/Core/DynamicData.php +++ b/src/Types/Core/DynamicData.php @@ -2,7 +2,7 @@ namespace Xelon\VmWareClient\Types\Core; -class DynamicData implements \Countable +class DynamicData implements \Countable, \JsonSerializable { public function __construct(array $data = []) { @@ -62,4 +62,9 @@ public function count(): int return $count; } + + public function jsonSerialize(): array + { + return $this->toArray(); + } } From ce2f35f42105885aae242e1fb7b992df1ec81d1e Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Wed, 26 Oct 2022 13:04:02 +0000 Subject: [PATCH 31/46] Fix styling --- src/Requests/SoapRequest.php | 14 +++++++------- src/Traits/Soap/SoapGuestApis.php | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index d0eb9f3..490e6ba 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -31,18 +31,18 @@ public function request(string $method, array $requestBody, bool $convertToSoap return $response; } catch (\Exception $exception) { - $message = "SOAP REQUEST FAILED:\nMessage: " . $exception->getMessage() . - "\nSOAP method: " . $method . + $message = "SOAP REQUEST FAILED:\nMessage: ".$exception->getMessage(). + "\nSOAP method: ".$method. ( property_exists($this->soapClient, '__last_request') - ? "\nSOAP request: " . $this->soapClient->__last_request + ? "\nSOAP request: ".$this->soapClient->__last_request : '' - ) . ( + ).( property_exists($this->soapClient, '__last_request') - ? "\nSOAP response: " . $this->soapClient->__last_response + ? "\nSOAP response: ".$this->soapClient->__last_response : '' - ) . - "\nTrace: " . json_encode($exception->getTrace()); + ). + "\nTrace: ".json_encode($exception->getTrace()); Log::error($message); throw new \Exception($message); diff --git a/src/Traits/Soap/SoapGuestApis.php b/src/Traits/Soap/SoapGuestApis.php index 8d28650..d7a978d 100644 --- a/src/Traits/Soap/SoapGuestApis.php +++ b/src/Traits/Soap/SoapGuestApis.php @@ -119,7 +119,7 @@ public function makeDirectoryInGuest( 'password' => $password, ]), 'directoryPath' => $directoryPath, - 'createParentDirectories' => $createParentDirectories + 'createParentDirectories' => $createParentDirectories, ]; return $this->request('MakeDirectoryInGuest', $body); @@ -151,7 +151,7 @@ public function listFilesInGuest( 'filePath' => $filePath, 'index' => $index, 'maxResults' => $maxResults, - 'matchPattern' => $matchPattern + 'matchPattern' => $matchPattern, ]; return $this->request('ListFilesInGuest', $body); From 67d30f7c1ff9dee3f994e1f1d9de7a67a35ee14f Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Mon, 31 Oct 2022 12:27:44 +0200 Subject: [PATCH 32/46] fix --- src/Traits/Soap/SoapGuestApis.php | 4 ++-- src/Traits/Soap/SoapVmApis.php | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Traits/Soap/SoapGuestApis.php b/src/Traits/Soap/SoapGuestApis.php index 8d28650..bf3172f 100644 --- a/src/Traits/Soap/SoapGuestApis.php +++ b/src/Traits/Soap/SoapGuestApis.php @@ -47,7 +47,7 @@ public function initiateFileTransferToGuest( 'username' => $username, 'password' => $password, ]), - 'guestFilePath' => "{$guestFilePath}", + 'guestFilePath' => $guestFilePath, 'fileAttributes' => new \stdClass(), 'fileSize' => strlen($data), 'overwrite' => true, @@ -233,7 +233,7 @@ public function startProgramInGuest( ]), 'spec' => [ 'programPath' => $program, - 'arguments' => "{$filePath}", + 'arguments' => $filePath, ], ]; diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index 78cbb9f..e007df8 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -50,7 +50,8 @@ public function getObjectInfo(string $objectId, string $objectType, string $path public function getVmInfo(string $vmId, string $pathSet = '') { if (substr($vmId, 0, 2) !== 'vm') { - throw new \Exception('Wrong vm id format!'); + Log::error("Wrong vm id format: $vmId"); + return new \stdClass(); } return $this->getObjectInfo($vmId, 'VirtualMachine', $pathSet); From 5fd76e032ba396f1dc7c9006ca85a79af88856c8 Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Mon, 31 Oct 2022 10:28:15 +0000 Subject: [PATCH 33/46] Fix styling --- src/Traits/Soap/SoapVmApis.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index e007df8..747a151 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -51,6 +51,7 @@ public function getVmInfo(string $vmId, string $pathSet = '') { if (substr($vmId, 0, 2) !== 'vm') { Log::error("Wrong vm id format: $vmId"); + return new \stdClass(); } From 3b349e7ff0da5f26acb18f3840d285c7e577ffef Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Mon, 31 Oct 2022 17:54:40 +0200 Subject: [PATCH 34/46] feat: change data format in logs and responses --- src/Requests/ApiRequest.php | 11 ++++++++++- src/Requests/SoapRequest.php | 8 +++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Requests/ApiRequest.php b/src/Requests/ApiRequest.php index 3582dfd..5f6c5f8 100644 --- a/src/Requests/ApiRequest.php +++ b/src/Requests/ApiRequest.php @@ -24,7 +24,7 @@ private function request(string $method, string $uri, array $options = []) return [ 'isError' => true, 'code' => $e->getCode(), - 'info' => json_decode($e->getResponse()->getBody()->getContents()), + 'info' => $this->transformErrorInfo(json_decode($e->getResponse()->getBody()->getContents(), true)), ]; } catch (ClientException $e) { // if 401, create new session and reply attempt @@ -32,4 +32,13 @@ private function request(string $method, string $uri, array $options = []) Log::error('Rest api exception : '.$e->getMessage()); } } + + private function transformErrorInfo(array $info) + { + if (count($info['messages']) === 0) { + $info['messages'][0]['default_message'] = $info['error_type']; + } + + return $info; + } } diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index 490e6ba..b0a319c 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -25,7 +25,9 @@ public function request(string $method, array $requestBody, bool $convertToSoap Log::info( 'SOAP REQUEST SUCCESS:'. "\nSOAP method: ".$method. - "\nSOAP request: ".$this->soapClient->__last_request + property_exists($this->soapClient, '__last_request') + ? "\nSOAP request start***".json_encode(simplexml_load_string($this->soapClient->__last_request))."***SOAP request end" + : '' ); } @@ -35,11 +37,11 @@ public function request(string $method, array $requestBody, bool $convertToSoap "\nSOAP method: ".$method. ( property_exists($this->soapClient, '__last_request') - ? "\nSOAP request: ".$this->soapClient->__last_request + ? "\nSOAP request start***".json_encode(simplexml_load_string($this->soapClient->__last_request))."***SOAP request end" : '' ).( property_exists($this->soapClient, '__last_request') - ? "\nSOAP response: ".$this->soapClient->__last_response + ? "\nSOAP response start***: ".json_encode(simplexml_load_string($this->soapClient->__last_response))."***SOAP response end" : '' ). "\nTrace: ".json_encode($exception->getTrace()); From e165e37b4aa704291a42e4aaf8ada68c9c99dfeb Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Mon, 31 Oct 2022 15:55:14 +0000 Subject: [PATCH 35/46] Fix styling --- src/Requests/SoapRequest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index b0a319c..bf5c44a 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -26,7 +26,7 @@ public function request(string $method, array $requestBody, bool $convertToSoap 'SOAP REQUEST SUCCESS:'. "\nSOAP method: ".$method. property_exists($this->soapClient, '__last_request') - ? "\nSOAP request start***".json_encode(simplexml_load_string($this->soapClient->__last_request))."***SOAP request end" + ? "\nSOAP request start***".json_encode(simplexml_load_string($this->soapClient->__last_request)).'***SOAP request end' : '' ); } @@ -37,11 +37,11 @@ public function request(string $method, array $requestBody, bool $convertToSoap "\nSOAP method: ".$method. ( property_exists($this->soapClient, '__last_request') - ? "\nSOAP request start***".json_encode(simplexml_load_string($this->soapClient->__last_request))."***SOAP request end" + ? "\nSOAP request start***".json_encode(simplexml_load_string($this->soapClient->__last_request)).'***SOAP request end' : '' ).( property_exists($this->soapClient, '__last_request') - ? "\nSOAP response start***: ".json_encode(simplexml_load_string($this->soapClient->__last_response))."***SOAP response end" + ? "\nSOAP response start***: ".json_encode(simplexml_load_string($this->soapClient->__last_response)).'***SOAP response end' : '' ). "\nTrace: ".json_encode($exception->getTrace()); From 8dd093a76edfd7547e6197dbe43f0d394214a430 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Wed, 2 Nov 2022 11:24:18 +0200 Subject: [PATCH 36/46] fix: fixed logs --- src/Requests/SoapRequest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index b0a319c..6237572 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -26,7 +26,7 @@ public function request(string $method, array $requestBody, bool $convertToSoap 'SOAP REQUEST SUCCESS:'. "\nSOAP method: ".$method. property_exists($this->soapClient, '__last_request') - ? "\nSOAP request start***".json_encode(simplexml_load_string($this->soapClient->__last_request))."***SOAP request end" + ? "\nSOAP request start***".$this->soapClient->__last_request."***SOAP request end" : '' ); } @@ -37,11 +37,11 @@ public function request(string $method, array $requestBody, bool $convertToSoap "\nSOAP method: ".$method. ( property_exists($this->soapClient, '__last_request') - ? "\nSOAP request start***".json_encode(simplexml_load_string($this->soapClient->__last_request))."***SOAP request end" + ? "\nSOAP request start***".$this->soapClient->__last_request."***SOAP request end" : '' ).( property_exists($this->soapClient, '__last_request') - ? "\nSOAP response start***: ".json_encode(simplexml_load_string($this->soapClient->__last_response))."***SOAP response end" + ? "\nSOAP response start***: ".$this->soapClient->__last_response."***SOAP response end" : '' ). "\nTrace: ".json_encode($exception->getTrace()); From 660e2dac238c61822ecbab2990dc6baf98f0b544 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Wed, 2 Nov 2022 12:13:11 +0200 Subject: [PATCH 37/46] fix: nullable snapshot description --- src/Traits/Soap/SoapVmApis.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Traits/Soap/SoapVmApis.php b/src/Traits/Soap/SoapVmApis.php index 747a151..f8bdffa 100644 --- a/src/Traits/Soap/SoapVmApis.php +++ b/src/Traits/Soap/SoapVmApis.php @@ -415,7 +415,7 @@ public function deleteFolder(string $folderId) public function createSnapshot( string $vmId, string $name, - string $description, + ?string $description, bool $memory = false, bool $quiesce = true ) { From 3b828f4bfc60f09c7ea44a16c4ab7378419d8437 Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Wed, 2 Nov 2022 10:13:59 +0000 Subject: [PATCH 38/46] Fix styling --- src/Requests/SoapRequest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Requests/SoapRequest.php b/src/Requests/SoapRequest.php index 6237572..5a7ba8d 100644 --- a/src/Requests/SoapRequest.php +++ b/src/Requests/SoapRequest.php @@ -26,7 +26,7 @@ public function request(string $method, array $requestBody, bool $convertToSoap 'SOAP REQUEST SUCCESS:'. "\nSOAP method: ".$method. property_exists($this->soapClient, '__last_request') - ? "\nSOAP request start***".$this->soapClient->__last_request."***SOAP request end" + ? "\nSOAP request start***".$this->soapClient->__last_request.'***SOAP request end' : '' ); } @@ -37,11 +37,11 @@ public function request(string $method, array $requestBody, bool $convertToSoap "\nSOAP method: ".$method. ( property_exists($this->soapClient, '__last_request') - ? "\nSOAP request start***".$this->soapClient->__last_request."***SOAP request end" + ? "\nSOAP request start***".$this->soapClient->__last_request.'***SOAP request end' : '' ).( property_exists($this->soapClient, '__last_request') - ? "\nSOAP response start***: ".$this->soapClient->__last_response."***SOAP response end" + ? "\nSOAP response start***: ".$this->soapClient->__last_response.'***SOAP response end' : '' ). "\nTrace: ".json_encode($exception->getTrace()); From 1fe7cfebfa03d8d21bf8aeed195e3073752f0cf3 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Mon, 7 Nov 2022 14:02:10 +0200 Subject: [PATCH 39/46] feat: backward compatibility for vSphere 6.7 --- src/Requests/ApiRequest.php | 12 +++++++++-- src/Traits/Rest/CisApis.php | 12 ++++++++--- src/Traits/Rest/IsoApis.php | 26 +++++++++++++++-------- src/Traits/Rest/OfvApis.php | 4 +++- src/Traits/Rest/VcenterApis.php | 10 ++++----- src/Traits/Rest/VmApis.php | 32 +++++++++++++++++++++-------- src/Traits/Soap/SoapStorageApis.php | 2 +- src/Transform/SoapTransform.php | 1 + src/VcenterClient.php | 15 +++++++++++--- src/VmWareClientInit.php | 28 ++++++++++++++++++------- 10 files changed, 103 insertions(+), 39 deletions(-) diff --git a/src/Requests/ApiRequest.php b/src/Requests/ApiRequest.php index 5f6c5f8..9de67ad 100644 --- a/src/Requests/ApiRequest.php +++ b/src/Requests/ApiRequest.php @@ -13,7 +13,13 @@ trait ApiRequest private function request(string $method, string $uri, array $options = []) { try { - return json_decode($this->guzzleClient->request($method, $uri, $options)->getBody()); + $result = json_decode($this->guzzleClient->request($method, $uri, $options)->getBody()); + + if ($this->version < 7 && isset($result->value)) { + return $result->value; + } + + return $result; } catch (ConnectException $e) { Log::error('Rest api Connect exception: '.$e->getMessage()); } catch (ServerException $e) { @@ -35,7 +41,9 @@ private function request(string $method, string $uri, array $options = []) private function transformErrorInfo(array $info) { - if (count($info['messages']) === 0) { + if ($this->version < 7) { + $info['messages'] = $info['value']['messages']; + } elseif (count($info['messages']) === 0) { $info['messages'][0]['default_message'] = $info['error_type']; } diff --git a/src/Traits/Rest/CisApis.php b/src/Traits/Rest/CisApis.php index 85870ff..abd315b 100644 --- a/src/Traits/Rest/CisApis.php +++ b/src/Traits/Rest/CisApis.php @@ -12,7 +12,9 @@ public function listAttachedTagsTagAssociation(string $vmId) { return $this->request( 'post', - '/api/cis/tagging/tag-association?action=list-attached-tags', + $this->version >= 7 + ? '/api/cis/tagging/tag-association?action=list-attached-tags' + : '/rest/com/vmware/cis/tagging/tag-association?~action=list-attached-tags', [ 'json' => [ 'object_id' => [ @@ -28,7 +30,9 @@ public function atachTagAssociation(string $vmId, string $tagId) { return $this->request( 'post', - "/api/cis/tagging/tag-association/$tagId?action=attach", + $this->version >= 7 + ? "/api/cis/tagging/tag-association/$tagId?action=attach" + : "/rest/com/vmware/cis/tagging/tag-association/id:$tagId?~action=attach", [ 'json' => [ 'object_id' => [ @@ -44,7 +48,9 @@ public function detachTagAssociation(string $vmId, string $tagId) { return $this->request( 'post', - "/api/cis/tagging/tag-association/$tagId?action=detach", + $this->version >= 7 + ? "/api/cis/tagging/tag-association/$tagId?action=detach" + : "/rest/com/vmware/cis/tagging/tag-association/id:$tagId?~action=detach", [ 'json' => [ 'object_id' => [ diff --git a/src/Traits/Rest/IsoApis.php b/src/Traits/Rest/IsoApis.php index f1262de..3c036e2 100644 --- a/src/Traits/Rest/IsoApis.php +++ b/src/Traits/Rest/IsoApis.php @@ -10,17 +10,27 @@ trait IsoApis public function mountImage(string $vmId, string $libraryItem) { - return $this->request('post', '/api/vcenter/iso/image?action=mount', ['form_params' => [ - 'library_item' => $libraryItem, - 'vm' => $vmId, - ]]); + if ($this->version >= 7) { + $url = '/api/vcenter/iso/image?action=mount'; + $params = ['library_item' => $libraryItem, 'vm' => $vmId]; + } else { + $url = "/rest/com/vmware/vcenter/iso/image/id:$libraryItem?~action=mount"; + $params = ['vm' => $vmId]; + } + + return $this->request('post', $url, ['form_params' => $params]); } public function unmountImage(string $vmId, string $cdRom) { - return $this->request('post', '/api/vcenter/iso/image?action=unmount', ['form_params' => [ - 'cdrom' => $cdRom, - 'vm' => $vmId, - ]]); + if ($this->version >= 7) { + $url = '/api/vcenter/iso/image?action=unmount'; + $params = ['cdrom' => $cdRom, 'vm' => $vmId]; + } else { + $url = "/rest/com/vmware/vcenter/iso/image/id:$vmId?~action=unmount"; + $params = ['cdrom' => $cdRom]; + } + + return $this->request('post', $url, ['form_params' => $params]); } } diff --git a/src/Traits/Rest/OfvApis.php b/src/Traits/Rest/OfvApis.php index 71e55fa..44120b9 100644 --- a/src/Traits/Rest/OfvApis.php +++ b/src/Traits/Rest/OfvApis.php @@ -51,7 +51,9 @@ public function deployLibraryItem(string $ovfLibraryItemId, array $data) return $this->request( 'post', - "/api/vcenter/ovf/library-item/$ovfLibraryItemId?action=deploy", + $this->version >= 7 + ? "/api/vcenter/ovf/library-item/$ovfLibraryItemId?action=deploy" + : "/rest/com/vmware/vcenter/ovf/library-item/id:$ovfLibraryItemId?~action=deploy", ['json' => $body] ); } diff --git a/src/Traits/Rest/VcenterApis.php b/src/Traits/Rest/VcenterApis.php index 774224f..53c3691 100644 --- a/src/Traits/Rest/VcenterApis.php +++ b/src/Traits/Rest/VcenterApis.php @@ -17,22 +17,22 @@ public function getVmList(array $requestBody = []) { $query = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', http_build_query($requestBody, null, '&')); - return $this->request('get', '/api/vcenter/vm', ['query' => $query]); + return $this->request('get', "$this->apiUrlPrefix/vcenter/vm", ['query' => $query]); } public function getVmInfo(string $vmId) { - return $this->request('get', "/api/vcenter/vm/$vmId"); + return $this->request('get', "$this->apiUrlPrefix/vcenter/vm/$vmId"); } public function deleteVm(string $vmId) { - return $this->request('delete', "/api/vcenter/vm/$vmId"); + return $this->request('delete', "$this->apiUrlPrefix/vcenter/vm/$vmId"); } public function cloneVm(array $requestBody) { - return $this->request('post', '/api/vcenter/vm?action=clone', ['json' => $requestBody]); + return $this->request('post', "$this->apiUrlPrefix/vcenter/vm?action=clone", ['json' => $requestBody]); } public function registerVm() @@ -59,6 +59,6 @@ public function getNetworkList(array $requestBody = []) { $query = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', http_build_query($requestBody, null, '&')); - return $this->request('get', '/api/vcenter/network', ['query' => $query]); + return $this->request('get', "$this->apiUrlPrefix/vcenter/network", ['query' => $query]); } } diff --git a/src/Traits/Rest/VmApis.php b/src/Traits/Rest/VmApis.php index e4f703d..77370aa 100644 --- a/src/Traits/Rest/VmApis.php +++ b/src/Traits/Rest/VmApis.php @@ -35,22 +35,36 @@ public function getPower() public function resetPower(string $vmId) { - return $this->request('post', "/api/vcenter/vm/$vmId/power?action=reset"); + return $this->request( + 'post', + $this->version >= 7 ? "/api/vcenter/vm/$vmId/power?action=reset" : "/rest/vcenter/vm/$vmId/power/reset" + ); } public function startPower(string $vmId) { - return $this->request('post', "/api/vcenter/vm/$vmId/power?action=start"); + return $this->request( + 'post', + $this->version >= 7 ? "/api/vcenter/vm/$vmId/power?action=start" : "/rest/vcenter/vm/$vmId/power/start" + ); } public function stopPower(string $vmId) { - return $this->request('post', "/api/vcenter/vm/$vmId/power?action=stop"); + $a = 5; + + return $this->request( + 'post', + $this->version >= 7 ? "/api/vcenter/vm/$vmId/power?action=stop" : "/rest/vcenter/vm/$vmId/power/stop" + ); } public function suspendPower(string $vmId) { - return $this->request('post', "/api/vcenter/vm/$vmId/power?action=suspend"); + return $this->request( + 'post', + $this->version >= 7 ? "/api/vcenter/vm/$vmId/power?action=suspend" : "/rest/vcenter/vm/$vmId/power/suspend" + ); } public function getTools() @@ -275,7 +289,7 @@ public function updateHardwareCpu( bool $hotAddEnabled = false, bool $hotRemoveEnabled = false ) { - return $this->request('patch', "/api/vcenter/vm/$vmId/hardware/cpu", [ + return $this->request('patch', "$this->apiUrlPrefix/vcenter/vm/$vmId/hardware/cpu", [ 'json' => [ 'cores_per_socket' => $coresPerSocket, 'count' => $count, @@ -292,7 +306,7 @@ public function listHardwareDisk() public function createHardwareDisk(string $vmId, array $body) { - return $this->request('post', "/api/vcenter/vm/$vmId/hardware/disk", ['json' => $body]); + return $this->request('post', "$this->apiUrlPrefix/vcenter/vm/$vmId/hardware/disk", ['json' => $body]); } public function getHardwareDisk() @@ -307,7 +321,7 @@ public function updateHardwareDisk() public function deleteHardwareDisk(string $vmId, int $diskKey) { - return $this->request('delete', "/api/vcenter/vm/$vmId/hardware/disk/$diskKey"); + return $this->request('delete', "$this->apiUrlPrefix/vcenter/vm/$vmId/hardware/disk/$diskKey"); } public function listHardwareEthernet() @@ -332,7 +346,7 @@ public function updateHardwareEthernet() public function deleteHardwareEthernet(string $vmId, int $nicKey) { - return $this->request('delete', "/api/vcenter/vm/$vmId/hardware/ethernet/$nicKey"); + return $this->request('delete', "$this->apiUrlPrefix/vcenter/vm/$vmId/hardware/ethernet/$nicKey"); } public function connectHardwareEthernet() @@ -387,7 +401,7 @@ public function getHardwareMemory() public function updateHardwareMemory(string $vmId, int $size, bool $hotAddEnabled = false) { - return $this->request('patch', "/api/vcenter/vm/$vmId/hardware/memory", [ + return $this->request('patch', "$this->apiUrlPrefix/vcenter/vm/$vmId/hardware/memory", [ 'json' => [ 'hot_add_enabled' => $hotAddEnabled, 'size_MiB' => $size, diff --git a/src/Traits/Soap/SoapStorageApis.php b/src/Traits/Soap/SoapStorageApis.php index 3b7bd1a..0e91a57 100644 --- a/src/Traits/Soap/SoapStorageApis.php +++ b/src/Traits/Soap/SoapStorageApis.php @@ -27,7 +27,7 @@ public function getVcenterVStorageInfo(string $vstorageId, string $datastore) ], ]; - return $this->request('RetrieveVStorageObject', $body); + return $this->transformToArrayValues($this->request('RetrieveVStorageObject', $body)); } public function deleteVcenterVStorageInfo(string $vstorageId, string $datastore) diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index 28f6a52..7a06bae 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -106,6 +106,7 @@ public function transformToArrayValues(stdClass $object, int $startIndex = 0, ?i ['latestPage', 'TaskInfo'], ['returnval', 'sampleInfo'], ['returnval', 'value', 'value'], + ['returnval', 'config', 'consumerId'], ['layoutEx', 'file'], ['layoutEx', 'snapshot'], ['layoutEx', 'snapshot', 'disk'], diff --git a/src/VcenterClient.php b/src/VcenterClient.php index 232a605..3e79f4c 100755 --- a/src/VcenterClient.php +++ b/src/VcenterClient.php @@ -16,14 +16,23 @@ class VcenterClient extends VmWareClientInit use CisApis; use OfvApis; + public string $apiUrlPrefix; + public ?VcenterSoapClient $soap; - public function __construct(string $ip, string $login, string $password, string $mode = self::MODE_REST) - { - parent::__construct($ip, $login, $password, $mode); + public function __construct( + string $ip, + string $login, + string $password, + string $mode = self::MODE_REST, + float $version = 7 + ) { + parent::__construct($ip, $login, $password, $mode, $version); if ($mode === self::MODE_SOAP || $mode === self::MODE_BOTH) { $this->soap = new VcenterSoapClient($this->soapClient); } + + $this->apiUrlPrefix = $this->version >= 7 ? '/api' : '/rest'; } } diff --git a/src/VmWareClientInit.php b/src/VmWareClientInit.php index 087bee3..0d45411 100755 --- a/src/VmWareClientInit.php +++ b/src/VmWareClientInit.php @@ -24,15 +24,23 @@ class VmWareClientInit private string $password; + protected float $version; + protected ?GuzzleClient $guzzleClient; protected ?\SoapClient $soapClient; - public function __construct(string $ip, string $login, string $password, string $mode = self::MODE_REST) - { + public function __construct( + string $ip, + string $login, + string $password, + string $mode = self::MODE_REST, + float $version = 7 + ) { $this->ip = $ip; $this->login = $login; $this->password = $password; + $this->version = $version; switch ($mode) { case self::MODE_REST: @@ -68,9 +76,16 @@ private function initRestSession(): void private function createRestSession(): void { try { - $authReponse = $this->guzzleClient->post('/api/session', ['auth' => [$this->login, $this->password]]); + $authReponse = $this->guzzleClient->post( + $this->version >= 7 ? '/api/session' : '/rest/com/vmware/cis/session', + ['auth' => [$this->login, $this->password]] + ); $apiSessionId = json_decode($authReponse->getBody()); + if ($this->version < 7) { + $apiSessionId = $apiSessionId->value; + } + Cache::add("vcenter-rest-session-$this->ip", [ 'api_session_id' => $apiSessionId, 'expired_at' => Carbon::now()->addSeconds(config('vmware-php-client.session_ttl') * 60 - 30), @@ -91,10 +106,9 @@ private function createRestSession(): void private function deleteRestSession(string $apiSessionId): void { try { - $this->guzzleClient->delete('api/session', [ - 'headers' => [ - 'vmware-api-session-id' => $apiSessionId, - ], + $this->guzzleClient->delete( + $this->version >= 7 ? 'api/session' : '/rest/com/vmware/cis/session', + ['headers' => ['vmware-api-session-id' => $apiSessionId,], ]); } catch (\Exception $exception) { } From 8cb4681439961589d39bce307a913443159fc434 Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Mon, 7 Nov 2022 12:02:52 +0000 Subject: [PATCH 40/46] Fix styling --- src/VmWareClientInit.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/VmWareClientInit.php b/src/VmWareClientInit.php index 0d45411..8cd6cbd 100755 --- a/src/VmWareClientInit.php +++ b/src/VmWareClientInit.php @@ -108,8 +108,8 @@ private function deleteRestSession(string $apiSessionId): void try { $this->guzzleClient->delete( $this->version >= 7 ? 'api/session' : '/rest/com/vmware/cis/session', - ['headers' => ['vmware-api-session-id' => $apiSessionId,], - ]); + ['headers' => ['vmware-api-session-id' => $apiSessionId], + ]); } catch (\Exception $exception) { } From 60980fdd93ff76fb79799c621c84e1f166d0a7cf Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Mon, 7 Nov 2022 14:43:18 +0200 Subject: [PATCH 41/46] feat: backward compatibility for vSphere 6.7 --- src/Requests/ApiRequest.php | 6 +++++- src/Traits/Rest/VcenterApis.php | 18 ++++++++++++------ src/Transform/SoapTransform.php | 12 ++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/Requests/ApiRequest.php b/src/Requests/ApiRequest.php index 9de67ad..d847629 100644 --- a/src/Requests/ApiRequest.php +++ b/src/Requests/ApiRequest.php @@ -42,7 +42,11 @@ private function request(string $method, string $uri, array $options = []) private function transformErrorInfo(array $info) { if ($this->version < 7) { - $info['messages'] = $info['value']['messages']; + if (isset($info['value']['messages'])) { + $info['messages'] = $info['value']['messages']; + } elseif (isset($info['localizableMessages'])) { + $info['messages'] = $info['localizableMessages']; + } } elseif (count($info['messages']) === 0) { $info['messages'][0]['default_message'] = $info['error_type']; } diff --git a/src/Traits/Rest/VcenterApis.php b/src/Traits/Rest/VcenterApis.php index 53c3691..9921b0a 100644 --- a/src/Traits/Rest/VcenterApis.php +++ b/src/Traits/Rest/VcenterApis.php @@ -3,10 +3,12 @@ namespace Xelon\VmWareClient\Traits\Rest; use Xelon\VmWareClient\Requests\ApiRequest; +use Xelon\VmWareClient\Transform\SoapTransform; trait VcenterApis { use ApiRequest; + use SoapTransform; public function createVm() { @@ -15,9 +17,11 @@ public function createVm() public function getVmList(array $requestBody = []) { - $query = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', http_build_query($requestBody, null, '&')); - - return $this->request('get', "$this->apiUrlPrefix/vcenter/vm", ['query' => $query]); + return $this->request( + 'get', + "$this->apiUrlPrefix/vcenter/vm", + ['query' => $this->getListFilterQuery($requestBody)] + ); } public function getVmInfo(string $vmId) @@ -57,8 +61,10 @@ public function unregisterVm() public function getNetworkList(array $requestBody = []) { - $query = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', http_build_query($requestBody, null, '&')); - - return $this->request('get', "$this->apiUrlPrefix/vcenter/network", ['query' => $query]); + return $this->request( + 'get', + "$this->apiUrlPrefix/vcenter/network", + ['query' => $this->getListFilterQuery($requestBody)] + ); } } diff --git a/src/Transform/SoapTransform.php b/src/Transform/SoapTransform.php index 7a06bae..28eb1d6 100644 --- a/src/Transform/SoapTransform.php +++ b/src/Transform/SoapTransform.php @@ -157,6 +157,18 @@ public function transformToArrayValues(stdClass $object, int $startIndex = 0, ?i return $object; } + public function getListFilterQuery(array $filter): string + { + if ($this->version < 7) { + foreach ($filter as $key => $value) { + $filter["filter.$key"] = $value; + unset($filter[$key]); + } + } + + return preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', http_build_query($filter, null, '&')); + } + private function transformToArrayValuesRecursive(&$object, string $propertyName) { if (is_array($object)) { From b2db01eb89643570ae2b17a822de56ca64a1f8c1 Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Tue, 8 Nov 2022 20:08:02 +0200 Subject: [PATCH 42/46] feat: change vm info response for vSphere 6.7 --- src/Traits/Rest/VcenterApis.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Traits/Rest/VcenterApis.php b/src/Traits/Rest/VcenterApis.php index 9921b0a..3c67d91 100644 --- a/src/Traits/Rest/VcenterApis.php +++ b/src/Traits/Rest/VcenterApis.php @@ -26,7 +26,17 @@ public function getVmList(array $requestBody = []) public function getVmInfo(string $vmId) { - return $this->request('get', "$this->apiUrlPrefix/vcenter/vm/$vmId"); + $result = $this->request('get', "$this->apiUrlPrefix/vcenter/vm/$vmId"); + + if ($this->version < 7) { + foreach ($result->disks as $disk) { + foreach ($disk->value as $key => $property) { + $disk->$key = $property; + } + } + } + + return $result; } public function deleteVm(string $vmId) From 2fdd2e945b60357033d77a8847dc020ea3073b7e Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Tue, 8 Nov 2022 21:02:28 +0200 Subject: [PATCH 43/46] feat: change update hardware memory and cpu request for vSphere 6.7 --- src/Traits/Rest/VmApis.php | 40 +++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/Traits/Rest/VmApis.php b/src/Traits/Rest/VmApis.php index 77370aa..b1b3884 100644 --- a/src/Traits/Rest/VmApis.php +++ b/src/Traits/Rest/VmApis.php @@ -289,14 +289,21 @@ public function updateHardwareCpu( bool $hotAddEnabled = false, bool $hotRemoveEnabled = false ) { - return $this->request('patch', "$this->apiUrlPrefix/vcenter/vm/$vmId/hardware/cpu", [ - 'json' => [ - 'cores_per_socket' => $coresPerSocket, - 'count' => $count, - 'hot_add_enabled' => $hotAddEnabled, - 'hot_remove_enabled' => $hotRemoveEnabled, - ], - ]); + $requestBody = [ + 'cores_per_socket' => $coresPerSocket, + 'count' => $count, + 'hot_add_enabled' => $hotAddEnabled, + 'hot_remove_enabled' => $hotRemoveEnabled, + ]; + + if ($this->version < 7) { + $requestBody = ['spec' => $requestBody]; + } + + return $this->request( + 'patch', + "$this->apiUrlPrefix/vcenter/vm/$vmId/hardware/cpu", + ['json' => $requestBody]); } public function listHardwareDisk() @@ -401,12 +408,17 @@ public function getHardwareMemory() public function updateHardwareMemory(string $vmId, int $size, bool $hotAddEnabled = false) { - return $this->request('patch', "$this->apiUrlPrefix/vcenter/vm/$vmId/hardware/memory", [ - 'json' => [ - 'hot_add_enabled' => $hotAddEnabled, - 'size_MiB' => $size, - ], - ]); + $requestBody = ['hot_add_enabled' => $hotAddEnabled, 'size_MiB' => $size]; + + if ($this->version < 7) { + $requestBody = ['spec' => $requestBody]; + } + + return $this->request( + 'patch', + "$this->apiUrlPrefix/vcenter/vm/$vmId/hardware/memory", + ['json' => $requestBody] + ); } public function listHardwareParallel() From 0fd4e6af10835aef5a4e03fa4b397e7a2a13a7fb Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Thu, 10 Nov 2022 14:43:49 +0200 Subject: [PATCH 44/46] feat: change ofv template request for vSphere 6.7 --- src/Traits/Rest/OfvApis.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Traits/Rest/OfvApis.php b/src/Traits/Rest/OfvApis.php index 44120b9..51fa03b 100644 --- a/src/Traits/Rest/OfvApis.php +++ b/src/Traits/Rest/OfvApis.php @@ -10,6 +10,16 @@ trait OfvApis public function deployLibraryItem(string $ovfLibraryItemId, array $data) { + $networkMappings = [ + 'value' => $data['network_port_group'], + 'key' => 'VM Network', + ]; + + if ($this->version < 7) { + $networkMappings = [$networkMappings]; + + } + $body = [ 'deployment_spec' => [ 'name' => $data['name'], @@ -35,10 +45,7 @@ public function deployLibraryItem(string $ovfLibraryItemId, array $data) ], ], ], - 'network_mappings' => [ - 'value' => $data['network_port_group'], - 'key' => 'VM Network', - ], + 'network_mappings' => $networkMappings, ], 'target' => [ 'resource_pool_id' => $data['resource_pool_id'], From 16367ecf060c635559a3e012f0d5d5fb374f96ca Mon Sep 17 00:00:00 2001 From: gazhur94 Date: Thu, 10 Nov 2022 12:44:26 +0000 Subject: [PATCH 45/46] Fix styling --- src/Traits/Rest/OfvApis.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Traits/Rest/OfvApis.php b/src/Traits/Rest/OfvApis.php index 51fa03b..e3ded32 100644 --- a/src/Traits/Rest/OfvApis.php +++ b/src/Traits/Rest/OfvApis.php @@ -17,7 +17,6 @@ public function deployLibraryItem(string $ovfLibraryItemId, array $data) if ($this->version < 7) { $networkMappings = [$networkMappings]; - } $body = [ From eead2f26e52a838e55065f4e2b1aaf23d63202ac Mon Sep 17 00:00:00 2001 From: Andrii Hazhur Date: Thu, 10 Nov 2022 15:26:38 +0200 Subject: [PATCH 46/46] fix: add key to VirtualLsiLogicSASController data --- src/Data/SoapData.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Data/SoapData.php b/src/Data/SoapData.php index 5e9e736..54dee9d 100644 --- a/src/Data/SoapData.php +++ b/src/Data/SoapData.php @@ -155,6 +155,7 @@ public function editNetworkSpec( public function addSasControllerSpec(): VirtualLsiLogicSASController { return new VirtualLsiLogicSASController([ + 'key' => 1000, 'busNumber' => 1, 'hotAddRemove' => true, 'sharedBus' => 'physicalSharing',