diff --git a/samples/compute/v2/servers/start_server.php b/samples/compute/v2/servers/start_server.php new file mode 100644 index 00000000..f70402b0 --- /dev/null +++ b/samples/compute/v2/servers/start_server.php @@ -0,0 +1,21 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$compute = $openstack->computeV2(['region' => '{region}']); + +$server = $compute->getServer([ + 'id' => '{serverId}', +]); + +$server->start(); diff --git a/samples/compute/v2/servers/stop_server.php b/samples/compute/v2/servers/stop_server.php new file mode 100644 index 00000000..eba70bc6 --- /dev/null +++ b/samples/compute/v2/servers/stop_server.php @@ -0,0 +1,21 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$compute = $openstack->computeV2(['region' => '{region}']); + +$server = $compute->getServer([ + 'id' => '{serverId}', +]); + +$server->stop(); diff --git a/src/Compute/v2/Api.php b/src/Compute/v2/Api.php index 4ba7acfd..491977f2 100644 --- a/src/Compute/v2/Api.php +++ b/src/Compute/v2/Api.php @@ -289,6 +289,30 @@ public function rebootServer(): array ]; } + public function startServer() : array + { + return [ + 'method' => 'POST', + 'path' => 'servers/{id}/action', + 'params' => [ + 'id' => $this->params->urlId('server'), + 'os-start' => $this->params->nullAction() + ], + ]; + } + + public function stopServer() : array + { + return [ + 'method' => 'POST', + 'path' => 'servers/{id}/action', + 'params' => [ + 'id' => $this->params->urlId('server'), + 'os-stop' => $this->params->nullAction() + ], + ]; + } + public function rebuildServer(): array { return [ diff --git a/src/Compute/v2/Models/Server.php b/src/Compute/v2/Models/Server.php index 7ed02d8e..a37e7e25 100644 --- a/src/Compute/v2/Models/Server.php +++ b/src/Compute/v2/Models/Server.php @@ -162,6 +162,28 @@ public function reboot(string $type = Enum::REBOOT_SOFT) ]); } + /** + * Starts server + */ + public function start() + { + $this->execute($this->api->startServer(), [ + 'id' => $this->id, + 'os-start' => null + ]); + } + + /** + * Stops server + */ + public function stop() + { + $this->execute($this->api->stopServer(), [ + 'id' => $this->id, + 'os-stop' => null + ]); + } + /** * Rebuilds the server. * diff --git a/tests/integration/Compute/v2/CoreTest.php b/tests/integration/Compute/v2/CoreTest.php index 3f62b64f..3dfbd9d1 100644 --- a/tests/integration/Compute/v2/CoreTest.php +++ b/tests/integration/Compute/v2/CoreTest.php @@ -23,6 +23,8 @@ class CoreTest extends TestCase const SUBNET = 'phptest_subnet'; const VOLUME = 'phptest_volume'; + const IMAGE = 'cirros'; + /** @var NetworkService */ private $networkService; @@ -79,11 +81,13 @@ private function searchImages($name) foreach ($this->getService()->listImages() as $image) { if (strpos($image->name, $name) !== false) { $this->imageId = $image->id; - return; + break; } } - $this->logger->emergency('No image found'); + if (!$this->imageId) { + throw new \RuntimeException(sprintf('Unable to find image "%s". Make sure this image is available for integration test.', $name)); + } } protected function setUp() @@ -126,7 +130,7 @@ public function runTests() // Manually trigger setUp $this->setUp(); - $this->searchImages('cirros'); + $this->searchImages(self::IMAGE); // Servers $this->createServer(); @@ -138,6 +142,8 @@ public function runTests() // Server actions //$this->changeServerPassword(); + $this->stopServer(); + $this->startServer(); $this->resizeServer(); $this->confirmServerResize(); $this->rebuildServer(); @@ -188,10 +194,16 @@ public function runTests() private function createServer() { + $flavorId = getenv('OS_FLAVOR'); + + if (!$flavorId) { + throw new \RuntimeException('OS_FLAVOR env var must be set'); + } + $replacements = [ '{serverName}' => $this->randomStr(), '{imageId}' => $this->imageId, - '{flavorId}' => 1, + '{flavorId}' => $flavorId, '{networkId}' => $this->network->id ]; @@ -355,6 +367,30 @@ private function rebootServer() $this->logStep('Rebooted server {serverId}', $replacements); } + private function stopServer() + { + $replacements = ['{serverId}' => $this->serverId]; + + /** @var $server \OpenStack\Compute\v2\Models\Server */ + require_once $this->sampleFile($replacements, 'servers/stop_server.php'); + + $server->waitUntil('SHUTOFF', false); + + $this->logStep('Stopped server {serverId}', $replacements); + } + + private function startServer() + { + $replacements = ['{serverId}' => $this->serverId]; + + /** @var $server \OpenStack\Compute\v2\Models\Server */ + require_once $this->sampleFile($replacements, 'servers/start_server.php'); + + $server->waitUntilActive(false); + + $this->logStep('Started server {serverId}', $replacements); + } + private function createFlavor() { $replacements = [ diff --git a/tests/integration/TestCase.php b/tests/integration/TestCase.php index ea886337..cebb1953 100644 --- a/tests/integration/TestCase.php +++ b/tests/integration/TestCase.php @@ -7,7 +7,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase implements TestInterface { - private $logger; + protected $logger; private $startPoint; private $lastPoint; private $sampleManager; diff --git a/tests/integration/run.php b/tests/integration/run.php index 6b52ad52..959cb117 100644 --- a/tests/integration/run.php +++ b/tests/integration/run.php @@ -1,4 +1,6 @@ assertEquals($userOptions['name'], $this->server->name); } + public function test_it_starts() + { + $expectedJson = ['os-start' => null]; + + $this->setupMock('POST', 'servers/serverId/action', $expectedJson, [], new Response(202)); + + $this->assertNull($this->server->start()); + } + + public function test_it_stops() + { + $expectedJson = ['os-stop' => null]; + + $this->setupMock('POST', 'servers/serverId/action', $expectedJson, [], new Response(202)); + + $this->assertNull($this->server->stop()); + } + public function test_it_resizes() { $expectedJson = ['resize' => ['flavorRef' => 'flavorId']];