1
|
|
|
<?php declare(strict_types=1); |
2
|
|
|
|
3
|
|
|
namespace OpenStack\Compute\v2\Models; |
4
|
|
|
|
5
|
|
|
use OpenStack\Common\Resource\HasWaiterTrait; |
6
|
|
|
use OpenStack\Common\Resource\Creatable; |
7
|
|
|
use OpenStack\Common\Resource\Deletable; |
8
|
|
|
use OpenStack\Common\Resource\Listable; |
9
|
|
|
use OpenStack\Common\Resource\Retrievable; |
10
|
|
|
use OpenStack\Common\Resource\Updateable; |
11
|
|
|
use OpenStack\Common\Resource\OperatorResource; |
12
|
|
|
use OpenStack\Common\Transport\Utils; |
13
|
|
|
use OpenStack\BlockStorage\v2\Models\VolumeAttachment; |
14
|
|
|
use OpenStack\Compute\v2\Enum; |
15
|
|
|
use OpenStack\Networking\v2\Extensions\SecurityGroups\Models\SecurityGroup; |
16
|
|
|
use Psr\Http\Message\ResponseInterface; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* @property \OpenStack\Compute\v2\Api $api |
20
|
|
|
*/ |
21
|
|
|
class Server extends OperatorResource implements |
22
|
|
|
Creatable, |
23
|
|
|
Updateable, |
24
|
|
|
Deletable, |
25
|
|
|
Retrievable, |
26
|
|
|
Listable |
27
|
|
|
{ |
28
|
|
|
use HasWaiterTrait; |
29
|
|
|
|
30
|
|
|
/** @var string */ |
31
|
|
|
public $id; |
32
|
|
|
|
33
|
|
|
/** @var string */ |
34
|
|
|
public $ipv4; |
35
|
|
|
|
36
|
|
|
/** @var string */ |
37
|
|
|
public $ipv6; |
38
|
|
|
|
39
|
|
|
/** @var array */ |
40
|
|
|
public $addresses; |
41
|
|
|
|
42
|
|
|
/** @var \DateTimeImmutable */ |
43
|
|
|
public $created; |
44
|
|
|
|
45
|
|
|
/** @var \DateTimeImmutable */ |
46
|
|
|
public $updated; |
47
|
|
|
|
48
|
|
|
/** @var Flavor */ |
49
|
|
|
public $flavor; |
50
|
|
|
|
51
|
|
|
/** @var string */ |
52
|
|
|
public $hostId; |
53
|
|
|
|
54
|
|
|
/** @var Image */ |
55
|
|
|
public $image; |
56
|
|
|
|
57
|
|
|
/** @var array */ |
58
|
|
|
public $links; |
59
|
|
|
|
60
|
|
|
/** @var array */ |
61
|
|
|
public $metadata; |
62
|
|
|
|
63
|
|
|
/** @var string */ |
64
|
|
|
public $name; |
65
|
|
|
|
66
|
|
|
/** @var string */ |
67
|
|
|
public $progress; |
68
|
|
|
|
69
|
|
|
/** @var string */ |
70
|
|
|
public $status; |
71
|
|
|
|
72
|
|
|
/** @var string */ |
73
|
|
|
public $tenantId; |
74
|
|
|
|
75
|
|
|
/** @var string */ |
76
|
|
|
public $userId; |
77
|
|
|
|
78
|
|
|
/** @var string */ |
79
|
|
|
public $adminPass; |
80
|
|
|
|
81
|
|
|
/** @var string */ |
82
|
|
|
public $taskState; |
83
|
|
|
|
84
|
|
|
protected $resourceKey = 'server'; |
85
|
|
|
protected $resourcesKey = 'servers'; |
86
|
|
|
protected $markerKey = 'id'; |
87
|
|
|
|
88
|
|
|
protected $aliases = [ |
89
|
|
|
'block_device_mapping_v2' => 'blockDeviceMapping', |
90
|
|
|
'accessIPv4' => 'ipv4', |
91
|
|
|
'accessIPv6' => 'ipv6', |
92
|
|
|
'tenant_id' => 'tenantId', |
93
|
|
|
'user_id' => 'userId', |
94
|
|
|
'security_groups' => 'securityGroups', |
95
|
|
|
'OS-EXT-STS:task_state' => 'taskState', |
96
|
|
|
]; |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* {@inheritDoc} |
100
|
|
|
* |
101
|
2 |
|
* @param array $userOptions {@see \OpenStack\Compute\v2\Api::postServer} |
102
|
|
|
*/ |
103
|
2 |
|
public function create(array $userOptions): Creatable |
104
|
2 |
|
{ |
105
|
|
|
$response = $this->execute($this->api->postServer(), $userOptions); |
106
|
|
|
return $this->populateFromResponse($response); |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
1 |
|
* {@inheritDoc} |
111
|
|
|
*/ |
112
|
1 |
|
public function update() |
113
|
|
|
{ |
114
|
1 |
|
$response = $this->execute($this->api->putServer(), $this->getAttrs(['id', 'name', 'ipv4', 'ipv6'])); |
115
|
|
|
$this->populateFromResponse($response); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* {@inheritDoc} |
120
|
1 |
|
*/ |
121
|
|
|
public function delete() |
122
|
1 |
|
{ |
123
|
1 |
|
$this->execute($this->api->deleteServer(), $this->getAttrs(['id'])); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* {@inheritDoc} |
128
|
1 |
|
*/ |
129
|
|
|
public function retrieve() |
130
|
1 |
|
{ |
131
|
|
|
$response = $this->execute($this->api->getServer(), $this->getAttrs(['id'])); |
132
|
1 |
|
$this->populateFromResponse($response); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Changes the root password for a server. |
137
|
|
|
* |
138
|
|
|
* @param string $newPassword The new root password |
139
|
|
|
*/ |
140
|
1 |
|
public function changePassword(string $newPassword) |
141
|
|
|
{ |
142
|
1 |
|
$this->execute($this->api->changeServerPassword(), [ |
143
|
1 |
|
'id' => $this->id, |
144
|
|
|
'password' => $newPassword, |
145
|
1 |
|
]); |
146
|
1 |
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* Reboots the server. |
150
|
|
|
* |
151
|
|
|
* @param string $type The type of reboot that will be performed. Either SOFT or HARD is supported. |
152
|
|
|
*/ |
153
|
2 |
|
public function reboot(string $type = Enum::REBOOT_SOFT) |
154
|
|
|
{ |
155
|
2 |
|
if (!in_array($type, ['SOFT', 'HARD'])) { |
156
|
1 |
|
throw new \RuntimeException('Reboot type must either be SOFT or HARD'); |
157
|
|
|
} |
158
|
|
|
|
159
|
1 |
|
$this->execute($this->api->rebootServer(), [ |
160
|
1 |
|
'id' => $this->id, |
161
|
1 |
|
'type' => $type, |
162
|
1 |
|
]); |
163
|
1 |
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Starts server |
167
|
|
|
*/ |
168
|
|
|
public function start() |
169
|
|
|
{ |
170
|
1 |
|
$this->execute($this->api->startServer(), [ |
171
|
|
|
'id' => $this->id, |
172
|
1 |
|
'os-start' => null |
173
|
1 |
|
]); |
174
|
|
|
} |
175
|
1 |
|
|
176
|
1 |
|
/** |
177
|
|
|
* Stops server |
178
|
|
|
*/ |
179
|
|
|
public function stop() |
180
|
|
|
{ |
181
|
|
|
$this->execute($this->api->stopServer(), [ |
182
|
|
|
'id' => $this->id, |
183
|
|
|
'os-stop' => null |
184
|
1 |
|
]); |
185
|
|
|
} |
186
|
1 |
|
|
187
|
1 |
|
/** |
188
|
1 |
|
* Rebuilds the server. |
189
|
1 |
|
* |
190
|
|
|
* @param array $options {@see \OpenStack\Compute\v2\Api::rebuildServer} |
191
|
1 |
|
*/ |
192
|
1 |
|
public function rebuild(array $options) |
193
|
|
|
{ |
194
|
|
|
$options['id'] = $this->id; |
195
|
|
|
$response = $this->execute($this->api->rebuildServer(), $options); |
196
|
|
|
|
197
|
1 |
|
$this->populateFromResponse($response); |
198
|
|
|
} |
199
|
1 |
|
|
200
|
1 |
|
/** |
201
|
|
|
* Resizes the server to a new flavor. Once this operation is complete and server has transitioned |
202
|
|
|
* to an active state, you will either need to call {@see confirmResize()} or {@see revertResize()}. |
203
|
|
|
* |
204
|
|
|
* @param string $flavorId The UUID of the new flavor your server will be based on. |
205
|
1 |
|
*/ |
206
|
|
|
public function resize(string $flavorId) |
207
|
1 |
|
{ |
208
|
1 |
|
$response = $this->execute($this->api->resizeServer(), [ |
209
|
|
|
'id' => $this->id, |
210
|
|
|
'flavorId' => $flavorId, |
211
|
|
|
]); |
212
|
|
|
|
213
|
|
|
$this->populateFromResponse($response); |
214
|
|
|
} |
215
|
1 |
|
|
216
|
|
|
/** |
217
|
1 |
|
* Confirms a previous resize operation. |
218
|
1 |
|
*/ |
219
|
1 |
|
public function confirmResize() |
220
|
|
|
{ |
221
|
|
|
$this->execute($this->api->confirmServerResize(), ['confirmResize' => null, 'id' => $this->id]); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Reverts a previous resize operation. |
226
|
|
|
*/ |
227
|
|
|
public function revertResize() |
228
|
2 |
|
{ |
229
|
|
|
$this->execute($this->api->revertServerResize(), ['revertResize' => null, 'id' => $this->id]); |
230
|
2 |
|
} |
231
|
|
|
|
232
|
2 |
|
/** |
233
|
2 |
|
* Gets a VNC console for a server. |
234
|
2 |
|
* |
235
|
|
|
* @param string $type The type of VNC console: novnc|xvpvnc. |
236
|
|
|
* Defaults to novnc. |
237
|
|
|
* |
238
|
|
|
* @return array |
239
|
|
|
*/ |
240
|
|
|
public function getVncConsole($type = Enum::CONSOLE_NOVNC): array |
241
|
|
|
{ |
242
|
1 |
|
$response = $this->execute($this->api->getVncConsole(), ['id' => $this->id, 'type' => $type]); |
243
|
|
|
return Utils::jsonDecode($response)['console']; |
244
|
1 |
|
} |
245
|
1 |
|
|
246
|
|
|
/** |
247
|
|
|
* Gets a RDP console for a server. |
248
|
|
|
* |
249
|
|
|
* @param string $type The type of VNC console: rdp-html5 (default). |
250
|
|
|
* |
251
|
|
|
* @return array |
252
|
|
|
*/ |
253
|
|
|
public function getRDPConsole($type = Enum::CONSOLE_RDP_HTML5): array |
254
|
|
|
{ |
255
|
|
|
$response = $this->execute($this->api->getRDPConsole(), ['id' => $this->id, 'type' => $type]); |
256
|
1 |
|
return Utils::jsonDecode($response)['console']; |
257
|
|
|
} |
258
|
1 |
|
|
259
|
1 |
|
/** |
260
|
|
|
* Gets a Spice console for a server. |
261
|
|
|
* |
262
|
|
|
* @param string $type The type of VNC console: spice-html5. |
263
|
|
|
* |
264
|
|
|
* @return array |
265
|
|
|
*/ |
266
|
|
|
public function getSpiceConsole($type = Enum::CONSOLE_SPICE_HTML5): array |
267
|
|
|
{ |
268
|
|
|
$response = $this->execute($this->api->getSpiceConsole(), ['id' => $this->id, 'type' => $type]); |
269
|
|
|
return Utils::jsonDecode($response)['console']; |
270
|
|
|
} |
271
|
1 |
|
|
272
|
|
|
/** |
273
|
1 |
|
* Gets a serial console for a server. |
274
|
1 |
|
* |
275
|
|
|
* @param string $type The type of VNC console: serial. |
276
|
|
|
* |
277
|
|
|
* @return array |
278
|
|
|
*/ |
279
|
|
|
public function getSerialConsole($type = Enum::CONSOLE_SERIAL): array |
280
|
|
|
{ |
281
|
|
|
$response = $this->execute($this->api->getSerialConsole(), ['id' => $this->id, 'type' => $type]); |
282
|
|
|
return Utils::jsonDecode($response)['console']; |
283
|
|
|
} |
284
|
1 |
|
|
285
|
|
|
/** |
286
|
1 |
|
* Creates an image for the current server. |
287
|
1 |
|
* |
288
|
|
|
* @param array $options {@see \OpenStack\Compute\v2\Api::createServerImage} |
289
|
|
|
*/ |
290
|
|
|
public function createImage(array $options) |
291
|
|
|
{ |
292
|
|
|
$options['id'] = $this->id; |
293
|
|
|
$this->execute($this->api->createServerImage(), $options); |
294
|
|
|
} |
295
|
1 |
|
|
296
|
|
|
/** |
297
|
1 |
|
* Iterates over all the IP addresses for this server. |
298
|
1 |
|
* |
299
|
|
|
* @param array $options {@see \OpenStack\Compute\v2\Api::getAddressesByNetwork} |
300
|
|
|
* |
301
|
|
|
* @return array An array containing to two keys: "public" and "private" |
302
|
|
|
*/ |
303
|
|
|
public function listAddresses(array $options = []): array |
304
|
|
|
{ |
305
|
|
|
$options['id'] = $this->id; |
306
|
|
|
|
307
|
|
|
$data = (isset($options['networkLabel'])) ? $this->api->getAddressesByNetwork() : $this->api->getAddresses(); |
308
|
|
|
$response = $this->execute($data, $options); |
309
|
|
|
return Utils::jsonDecode($response)['addresses']; |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
/** |
313
|
|
|
* Retrieves metadata from the API. |
314
|
|
|
* |
315
|
|
|
* @return array |
316
|
|
|
*/ |
317
|
|
|
public function getMetadata(): array |
318
|
|
|
{ |
319
|
|
|
$response = $this->execute($this->api->getServerMetadata(), ['id' => $this->id]); |
320
|
|
|
return $this->parseMetadata($response); |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* Resets all the metadata for this server with the values provided. All existing metadata keys |
325
|
|
|
* will either be replaced or removed. |
326
|
|
|
* |
327
|
|
|
* @param array $metadata {@see \OpenStack\Compute\v2\Api::putServerMetadata} |
328
|
|
|
*/ |
329
|
|
|
public function resetMetadata(array $metadata) |
330
|
|
|
{ |
331
|
|
|
$response = $this->execute($this->api->putServerMetadata(), ['id' => $this->id, 'metadata' => $metadata]); |
332
|
|
|
$this->metadata = $this->parseMetadata($response); |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* Merges the existing metadata for the server with the values provided. Any existing keys |
337
|
|
|
* referenced in the user options will be replaced with the user's new values. All other |
338
|
|
|
* existing keys will remain unaffected. |
339
|
|
|
* |
340
|
|
|
* @param array $metadata {@see \OpenStack\Compute\v2\Api::postServerMetadata} |
341
|
|
|
* |
342
|
|
|
* @return array |
343
|
|
|
*/ |
344
|
|
|
public function mergeMetadata(array $metadata) |
345
|
|
|
{ |
346
|
|
|
$response = $this->execute($this->api->postServerMetadata(), ['id' => $this->id, 'metadata' => $metadata]); |
347
|
|
|
$this->metadata = $this->parseMetadata($response); |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Retrieve the value for a specific metadata key. |
352
|
|
|
* |
353
|
|
|
* @param string $key {@see \OpenStack\Compute\v2\Api::getServerMetadataKey} |
354
|
|
|
* |
355
|
|
|
* @return mixed |
356
|
|
|
*/ |
357
|
|
View Code Duplication |
public function getMetadataItem(string $key) |
|
|
|
|
358
|
|
|
{ |
359
|
|
|
$response = $this->execute($this->api->getServerMetadataKey(), ['id' => $this->id, 'key' => $key]); |
360
|
|
|
$value = $this->parseMetadata($response)[$key]; |
361
|
|
|
$this->metadata[$key] = $value; |
362
|
|
|
return $value; |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
/** |
366
|
|
|
* Remove a specific metadata key. |
367
|
|
|
* |
368
|
|
|
* @param string $key {@see \OpenStack\Compute\v2\Api::deleteServerMetadataKey} |
369
|
|
|
*/ |
370
|
|
View Code Duplication |
public function deleteMetadataItem(string $key) |
|
|
|
|
371
|
|
|
{ |
372
|
|
|
if (isset($this->metadata[$key])) { |
373
|
|
|
unset($this->metadata[$key]); |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
$this->execute($this->api->deleteServerMetadataKey(), ['id' => $this->id, 'key' => $key]); |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
|
380
|
|
|
/** |
381
|
|
|
* Add security group to a server (addSecurityGroup action) |
382
|
|
|
* |
383
|
|
|
* @param array $options {@see \OpenStack\Compute\v2\Api::postSecurityGroup} |
384
|
|
|
* |
385
|
|
|
* @return SecurityGroup |
386
|
|
|
*/ |
387
|
|
|
public function addSecurityGroup(array $options) : SecurityGroup |
388
|
|
|
{ |
389
|
|
|
$options['id'] = $this->id; |
390
|
|
|
|
391
|
|
|
$response = $this->execute($this->api->postSecurityGroup(), $options); |
392
|
|
|
|
393
|
|
|
return $this->model(SecurityGroup::class)->populateFromResponse($response); |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* Add security group to a server (addSecurityGroup action) |
398
|
|
|
* |
399
|
|
|
* @param array $options {@see \OpenStack\Compute\v2\Api::deleteSecurityGroup} |
400
|
|
|
*/ |
401
|
|
|
public function removeSecurityGroup(array $options) |
402
|
|
|
{ |
403
|
|
|
$options['id'] = $this->id; |
404
|
|
|
$this->execute($this->api->deleteSecurityGroup(), $options); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
public function parseMetadata(ResponseInterface $response): array |
408
|
|
|
{ |
409
|
|
|
return Utils::jsonDecode($response)['metadata']; |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
/** |
413
|
|
|
* Returns Generator for SecurityGroups |
414
|
|
|
* |
415
|
|
|
* @return \Generator |
416
|
|
|
*/ |
417
|
|
|
public function listSecurityGroups(): \Generator |
418
|
|
|
{ |
419
|
|
|
return $this->model(SecurityGroup::class)->enumerate($this->api->getSecurityGroups(), ['id' => $this->id]); |
|
|
|
|
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
|
423
|
|
|
/** |
424
|
|
|
* Returns Generator for VolumeAttachment |
425
|
|
|
* |
426
|
|
|
* @return \Generator |
427
|
|
|
*/ |
428
|
|
|
public function listVolumeAttachments(): \Generator |
429
|
|
|
{ |
430
|
|
|
return $this->model(VolumeAttachment::class)->enumerate($this->api->getVolumeAttachments(), ['id' => $this->id]); |
|
|
|
|
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
/** |
434
|
|
|
* Attach a volume and returns volume that was attached |
435
|
|
|
* |
436
|
|
|
* @param $volumeId |
437
|
|
|
* |
438
|
|
|
* @return VolumeAttachment |
439
|
|
|
*/ |
440
|
|
|
public function attachVolume(string $volumeId): VolumeAttachment |
441
|
|
|
{ |
442
|
|
|
$response = $this->execute($this->api->postVolumeAttachments(), ['id' => $this->id, 'volumeId' => $volumeId]); |
443
|
|
|
|
444
|
|
|
return $this->model(VolumeAttachment::class)->populateFromResponse($response); |
445
|
|
|
} |
446
|
|
|
|
447
|
|
|
/** |
448
|
|
|
* Detach a volume |
449
|
|
|
* |
450
|
|
|
* @param $attachmentId |
451
|
|
|
* |
452
|
|
|
* @return void |
453
|
|
|
*/ |
454
|
|
|
public function detachVolume(string $attachmentId) |
455
|
|
|
{ |
456
|
|
|
$this->execute($this->api->deleteVolumeAttachments(), ['id' => $this->id, 'attachmentId' => $attachmentId]); |
457
|
|
|
} |
458
|
|
|
} |
459
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.