Skip to content

Commit 8ff73c7

Browse files
committed
Add Nova server-groups API support
1 parent 09b8a10 commit 8ff73c7

File tree

16 files changed

+738
-13
lines changed

16 files changed

+738
-13
lines changed

doc/services/compute/v2/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ OpenStack Compute (Nova) API Version 2. Nova is the OpenStack project that provi
1111

1212
create
1313
servers
14+
server-groups
1415
volume-attachments
1516
flavors
1617
images
17-
states
18+
states
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
Server Groups
2+
=============
3+
4+
Server groups let you express affinity or anti-affinity placement rules for Nova servers.
5+
6+
.. osdoc:: https://docs.openstack.org/api-ref/compute/#server-groups-os-server-groups
7+
8+
.. |models| replace:: server groups
9+
10+
.. include:: /common/service.rst
11+
12+
List
13+
----
14+
15+
.. sample:: Compute/v2/server_groups/list.php
16+
17+
Each iteration will return a :php:class:`ServerGroup` instance <OpenStack/Compute/v2/Models/ServerGroup.html>.
18+
19+
.. include:: /common/generators.rst
20+
21+
Admin-only listing across all projects is also available:
22+
23+
.. code-block:: php
24+
25+
$serverGroups = $service->listServerGroups([
26+
'allProjects' => true,
27+
]);
28+
29+
Create
30+
------
31+
32+
Use ``name`` and ``policies`` for the baseline Compute API:
33+
34+
.. sample:: Compute/v2/server_groups/create.php
35+
36+
Microversion 2.64+
37+
~~~~~~~~~~~~~~~~~~
38+
39+
If the Compute service is created with microversion ``2.64`` or later, you can use the singular ``policy`` field and
40+
optional ``rules`` object instead:
41+
42+
.. code-block:: php
43+
44+
$compute = $openstack->computeV2([
45+
'microVersion' => '2.64',
46+
]);
47+
48+
$serverGroup = $compute->createServerGroup([
49+
'name' => 'db-group',
50+
'policy' => 'anti-affinity',
51+
'rules' => [
52+
'max_server_per_host' => 1,
53+
],
54+
]);
55+
56+
When Nova responds with the newer singular ``policy`` field, the SDK also exposes that value as the first item in
57+
``policies`` for compatibility with the older response shape.
58+
59+
Read
60+
----
61+
62+
.. sample:: Compute/v2/server_groups/read.php
63+
64+
Delete
65+
------
66+
67+
.. sample:: Compute/v2/server_groups/delete.php
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
require 'vendor/autoload.php';
4+
5+
$openstack = new OpenStack\OpenStack([
6+
'authUrl' => '{authUrl}',
7+
'region' => '{region}',
8+
'user' => [
9+
'id' => '{userId}',
10+
'password' => '{password}'
11+
],
12+
'scope' => ['project' => ['id' => '{projectId}']]
13+
]);
14+
15+
$compute = $openstack->computeV2(['region' => '{region}']);
16+
17+
$serverGroup = $compute->createServerGroup([
18+
'name' => '{serverGroupName}',
19+
'policies' => ['affinity'],
20+
]);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
require 'vendor/autoload.php';
4+
5+
$openstack = new OpenStack\OpenStack([
6+
'authUrl' => '{authUrl}',
7+
'region' => '{region}',
8+
'user' => [
9+
'id' => '{userId}',
10+
'password' => '{password}'
11+
],
12+
'scope' => ['project' => ['id' => '{projectId}']]
13+
]);
14+
15+
$compute = $openstack->computeV2(['region' => '{region}']);
16+
17+
$serverGroup = $compute->getServerGroup(['id' => '{serverGroupId}']);
18+
$serverGroup->delete();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
require 'vendor/autoload.php';
4+
5+
$openstack = new OpenStack\OpenStack([
6+
'authUrl' => '{authUrl}',
7+
'region' => '{region}',
8+
'user' => [
9+
'id' => '{userId}',
10+
'password' => '{password}'
11+
],
12+
'scope' => ['project' => ['id' => '{projectId}']]
13+
]);
14+
15+
$compute = $openstack->computeV2(['region' => '{region}']);
16+
17+
$serverGroups = $compute->listServerGroups();
18+
19+
foreach ($serverGroups as $serverGroup) {
20+
/** @var \OpenStack\Compute\v2\Models\ServerGroup $serverGroup */
21+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
require 'vendor/autoload.php';
4+
5+
$openstack = new OpenStack\OpenStack([
6+
'authUrl' => '{authUrl}',
7+
'region' => '{region}',
8+
'user' => [
9+
'id' => '{userId}',
10+
'password' => '{password}'
11+
],
12+
'scope' => ['project' => ['id' => '{projectId}']]
13+
]);
14+
15+
$compute = $openstack->computeV2(['region' => '{region}']);
16+
17+
$serverGroup = $compute->getServerGroup(['id' => '{serverGroupId}']);
18+
$serverGroup->retrieve();

src/Compute/v2/Api.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,68 @@ public function deleteKeypair(): array
708708
];
709709
}
710710

711+
public function getServerGroups(): array
712+
{
713+
return [
714+
'method' => 'GET',
715+
'path' => 'os-server-groups',
716+
'params' => [
717+
'allProjects' => $this->params->allProjects(),
718+
'limit' => $this->params->limit(),
719+
'offset' => $this->params->offset(),
720+
],
721+
];
722+
}
723+
724+
public function getServerGroup(): array
725+
{
726+
return [
727+
'method' => 'GET',
728+
'path' => 'os-server-groups/{id}',
729+
'params' => [
730+
'id' => $this->params->urlId('server group'),
731+
],
732+
];
733+
}
734+
735+
public function postServerGroup(): array
736+
{
737+
return [
738+
'method' => 'POST',
739+
'path' => 'os-server-groups',
740+
'jsonKey' => 'server_group',
741+
'params' => [
742+
'name' => $this->isRequired($this->params->name('server group')),
743+
'policies' => $this->isRequired($this->params->serverGroupPolicies()),
744+
],
745+
];
746+
}
747+
748+
public function postServerGroupWithPolicy(): array
749+
{
750+
return [
751+
'method' => 'POST',
752+
'path' => 'os-server-groups',
753+
'jsonKey' => 'server_group',
754+
'params' => [
755+
'name' => $this->isRequired($this->params->name('server group')),
756+
'policy' => $this->isRequired($this->params->serverGroupPolicy()),
757+
'rules' => $this->notRequired($this->params->serverGroupRules()),
758+
],
759+
];
760+
}
761+
762+
public function deleteServerGroup(): array
763+
{
764+
return [
765+
'method' => 'DELETE',
766+
'path' => 'os-server-groups/{id}',
767+
'params' => [
768+
'id' => $this->params->urlId('server group'),
769+
],
770+
];
771+
}
772+
711773
public function postSecurityGroup(): array
712774
{
713775
return [
@@ -914,3 +976,8 @@ public function putQuotaSet(): array
914976
];
915977
}
916978
}
979+
980+
981+
982+
983+
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenStack\Compute\v2\Models;
6+
7+
use OpenStack\Common\Resource\Creatable;
8+
use OpenStack\Common\Resource\Deletable;
9+
use OpenStack\Common\Resource\Listable;
10+
use OpenStack\Common\Resource\OperatorResource;
11+
use OpenStack\Common\Resource\Retrievable;
12+
use OpenStack\Common\Transport\Utils;
13+
14+
/**
15+
* Represents a Compute v2 Server Group.
16+
*
17+
* @property \OpenStack\Compute\v2\Api $api
18+
*/
19+
class ServerGroup extends OperatorResource implements Listable, Retrievable, Creatable, Deletable
20+
{
21+
/** @var string */
22+
public $id;
23+
24+
/** @var array */
25+
public $members = [];
26+
27+
/** @var array */
28+
public $metadata = [];
29+
30+
/** @var string */
31+
public $name;
32+
33+
/** @var string */
34+
public $policy;
35+
36+
/** @var array */
37+
public $policies = [];
38+
39+
/** @var string */
40+
public $projectId;
41+
42+
/** @var array */
43+
public $rules = [];
44+
45+
/** @var string */
46+
public $userId;
47+
48+
protected $aliases = [
49+
'project_id' => 'projectId',
50+
'user_id' => 'userId',
51+
];
52+
53+
protected $resourceKey = 'server_group';
54+
protected $resourcesKey = 'server_groups';
55+
56+
public function retrieve()
57+
{
58+
$response = $this->execute($this->api->getServerGroup(), ['id' => (string) $this->id]);
59+
$this->populateFromResponse($response);
60+
}
61+
62+
public function create(array $userOptions): Creatable
63+
{
64+
if (isset($userOptions['policy'], $userOptions['policies'])) {
65+
throw new \RuntimeException('Provide either "policy" or "policies", not both.');
66+
}
67+
68+
if (isset($userOptions['rules']) && !isset($userOptions['policy'])) {
69+
throw new \RuntimeException('"rules" requires "policy".');
70+
}
71+
72+
if (!isset($userOptions['policy']) && !isset($userOptions['policies'])) {
73+
throw new \RuntimeException('"policy" or "policies" must be set.');
74+
}
75+
76+
$definition = isset($userOptions['policy'])
77+
? $this->api->postServerGroupWithPolicy()
78+
: $this->api->postServerGroup();
79+
80+
$response = $this->execute($definition, $userOptions);
81+
82+
return $this->populateFromResponse($response);
83+
}
84+
85+
public function delete()
86+
{
87+
$this->execute($this->api->deleteServerGroup(), ['id' => (string) $this->id]);
88+
}
89+
90+
public function populateFromArray(array $array): self
91+
{
92+
$array = Utils::flattenJson($array, $this->resourceKey);
93+
94+
if (isset($array['policy']) && !isset($array['policies'])) {
95+
$array['policies'] = [$array['policy']];
96+
}
97+
98+
if (isset($array['policies']) && is_array($array['policies']) && !isset($array['policy']) && count($array['policies']) > 0) {
99+
$array['policy'] = reset($array['policies']);
100+
}
101+
102+
$array += [
103+
'members' => [],
104+
'metadata' => [],
105+
'policies' => [],
106+
'rules' => [],
107+
];
108+
109+
return parent::populateFromArray($array);
110+
}
111+
}

0 commit comments

Comments
 (0)