Loading modules/cloud_service_providers/openstack/src/Service/Rest/OpenStackService.php +51 −33 Original line number Diff line number Diff line Loading @@ -299,7 +299,10 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter $instances = $response['body']['servers'] ?? []; foreach ($instances ?: [] as $key => $instance) { $instance_tags = $this->getInstanceTags(['InstanceId' => $instance['id']]); $instance_tags = !empty($instance['OS-EXT-STS:vm_state']) && $instance['OS-EXT-STS:vm_state'] !== 'building' ? $this->getInstanceTags(['InstanceId' => $instance['id']]) : []; foreach ($instance['security_groups'] ?? [] as $key_group => $group) { $security_groups[$key_group] = [ Loading @@ -321,13 +324,17 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter } // Get flavor Response. $flavor_id = $instance['flavor']['id'] ?? NULL; $flavor_data = $this->describeFlavorById([], $flavor_id); $flavor_data = !empty($instance['flavor']['id']) ? $this->describeFlavorById([], $instance['flavor']['id']) : []; // Get port response. $port_result = $this->instancePortInterface([ $port_result = !empty($instance['OS-EXT-STS:vm_state']) && $instance['OS-EXT-STS:vm_state'] !== 'building' ? $this->instancePortInterface([ 'InstanceId' => $instance['id'], ]); ]) : []; $port_ids = []; if (!empty($port_result)) { Loading Loading @@ -442,13 +449,17 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter } // Get flavor Response. $flavor_id = $instance['flavor']['id'] ?? NULL; $flavor_data = $this->describeFlavorById([], $flavor_id); $flavor_data = !empty($instance['flavor']['id']) ? $this->describeFlavorById([], $instance['flavor']['id']) : []; // Get port response. $port_result = $this->instancePortInterface([ $port_result = !empty($instance['OS-EXT-STS:vm_state']) && $instance['OS-EXT-STS:vm_state'] !== 'building' ? $this->instancePortInterface([ 'InstanceId' => $instance['id'], ]); ]) : []; $port_ids = []; if (!empty($port_result)) { Loading Loading @@ -678,36 +689,40 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter $server_id = !empty($response['body']['server']) ? $response['body']['server']['id'] : ''; $promise = new Promise(function () use (&$promise, $server_id) { $body = [ 'status' => 'ACTIVE', ]; $credentials = [ 'http_method' => 'get', 'endpoint' => $this->getEndpoint(OpenStackServiceInterface::COMPUTE_ENDPOINT, '/servers'), 'params' => $body, 'endpoint' => $this->getEndpoint(OpenStackServiceInterface::COMPUTE_ENDPOINT, '/servers') . "/$server_id", ]; for ($i = 0; $i < OpenStackServiceInterface::WAIT_SECOUNDS_FOR_OPENSTACK_INSTANCE_ACTIVE; $i++) { // Get servers whose status is active. $response = $this->getClient($credentials); $get_response = $this->getClient($credentials); // If the server_id of the created server exists in response, // exit from the loop. if (array_search($server_id, array_column($response['body']['servers'], 'id')) !== FALSE) { // Exit from the loop when vm_state becomes active. if (!empty($get_response['body']['server']['OS-EXT-STS:vm_state']) && $get_response['body']['server']['OS-EXT-STS:vm_state'] === 'active') { break; } sleep(OpenStackServiceInterface::OPENSTACK_INSTANCE_STATUS_CHECK_INTERVAL); } $promise->resolve($response['body']['server']['id']); $promise->resolve(!empty($get_response['body']['server']['id']) ? $get_response['body']['server']['id'] : 0 ); }); $promise->wait(); $server_id = $promise->wait(); // Create instance tags. $this->createTags([ 'Resources' => [$response['body']['server']['id']], !empty($server_id) ? $this->createTags([ 'Resources' => [$server_id], 'Tags' => $tags, 'EntityType' => 'openstack_instance', ]); ]) : $this->messenger->addError($this->t('Failed to create tag because the @name instance did not start within @wait_secound seconds.', [ '@name' => $params['Name'], '@wait_secound' => OpenStackServiceInterface::WAIT_SECOUNDS_FOR_OPENSTACK_INSTANCE_ACTIVE, ])); return $response['status_code'] === 202 ? ['Success' => TRUE] : NULL; } Loading Loading @@ -987,7 +1002,10 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter return $tags; } $uid = $tag_result[0]; $uid = 0; if (preg_match('/[^__]+$/', $tag_result[0], $matches)) { $uid = $matches[0]; } $uid_key_name = $this->getTagKeyCreatedByUid( 'openstack', $this->cloudContext, Loading Loading @@ -1821,7 +1839,7 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter * @return array * The Flavor list API response. */ public function describeFlavorById(array $params = [], $flavor_id = '') { public function describeFlavorById(array $params = [], $flavor_id = ''): array { $this->loadCredentials(); $credentials = [ Loading @@ -1832,7 +1850,7 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter $response = $this->getClient($credentials); return $response['body']['flavor']; return !empty($response['body']['flavor']) ? $response['body']['flavor'] : []; } /** Loading Loading @@ -2704,7 +2722,7 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter * @return array * The Instance Port Interface list API response. */ public function instancePortInterface(array $params = []) { public function instancePortInterface(array $params = []): array { $this->loadCredentials(); $credentials = [ Loading Loading @@ -3681,7 +3699,7 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter * @return array * Array interpretation of the response body. */ private function request($http_method, $endpoint, array $params = []) { private function request($http_method, $endpoint, array $params = []): array { $output = []; try { Loading modules/cloud_service_providers/openstack/tests/src/Behat/features/templates/OpenStack-ATDD-00-02-CreateDrupalResources.feature +2 −3 Original line number Diff line number Diff line Loading @@ -49,9 +49,8 @@ Feature: Create a Drupal role for OpenStack and a user as "Administrator" And I check the box "View any OpenStack image" And I check the box "Edit any OpenStack image" # Allow to view an instance And I check the box "View any OpenStack instance" And I check the box "Edit any OpenStack instance" And I check the box "Delete / Terminate any OpenStack instance" # Temporarily add the following permission until the default permission includes this. And I check the box "Delete / Terminate own OpenStack instance" # Allow to launch an instance. And I check the box "Launch approved cloud launch template" And I check the box "Delete own cloud launch templates" Loading modules/cloud_service_providers/openstack/tests/src/Behat/features/templates/OpenStack-ATDD-02-03-LaunchInstances.feature +1 −3 Original line number Diff line number Diff line Loading @@ -13,9 +13,7 @@ Feature: Launch an instance for OpenStack as "Authenticated User" And I wait for AJAX to finish Then the url should match "/clouds/openstack/{{ cloud_context }}/instance" And I should see the success message "has been launched" # Temporarily comment out the error check until "instance not found" error # is addressed. # And I should see neither error nor warning messages And I should see neither error nor warning messages And I wait {{ wait }} milliseconds And I click "Refresh" And I should see "{{ instance_flavor }}" in the "{{ instance_name }}" row Loading modules/cloud_service_providers/openstack/tests/src/Behat/features/templates/OpenStack-ATDD-03-06-OperateInstances.feature +2 −5 Original line number Diff line number Diff line Loading @@ -33,9 +33,7 @@ Feature: Launch, stop, and terminate an instance for OpenStack as "Authenticated And I wait for AJAX to finish Then the url should match "/clouds/openstack/{{ cloud_context }}/instance" And I should see the success message "has been launched" # Temporarily comment out the error check until "instance not found" error # is addressed. # And I should see neither error nor warning messages And I should see neither error nor warning messages And I wait {{ wait }} milliseconds And I click "Refresh" And I should see "{{ instance_flavor }}" in the "{{ instance_name_operate }}" row Loading @@ -57,8 +55,7 @@ Feature: Launch, stop, and terminate an instance for OpenStack as "Authenticated And I should see "{{ security_group_name }}" in the "Security groups" And I should see "{{ key_name }}" in the "Key pair name" And I press "Others" # Temporarily commenting out until the authored_by issue is addressed. # And I should see "{{ drupal_user_name }}" in the "Authored by" And I should see "{{ drupal_user_name }}" in the "Authored by" @api Scenario: Stop the running instance Loading src/Service/CloudServiceInterface.php +0 −42 Original line number Diff line number Diff line Loading @@ -319,46 +319,4 @@ interface CloudServiceInterface { */ public function buildOwnerQueryCondition(AlterableInterface $query): void; /** * Get the key name of the UID tag. * * @param string $bundle * The bundle the entity type, such as aws_cloud. * @param string $cloud_context * The cloud context. * @param string $tag * The tag. * @param int $uid * The uid. * * @throws \Drupal\cloud\Service\CloudServiceException * Throws CloudServiceException. * * @return string * The string of tag. */ public function getTagKeyCreatedByUid($bundle, $cloud_context, $tag = '', $uid = 0): string; /** * Get the key name of the UID tag. * * @param string $bundle * The bundle the entity type, such as aws_cloud. * @param string $cloud_context * The cloud context. * @param int $uid * The uid. * @param string $tag * The tag. * * @return string * The string of tag. */ public function getTagValueCreatedByUid( string $bundle, string $cloud_context, int $uid, string $tag = '' ): string; } Loading
modules/cloud_service_providers/openstack/src/Service/Rest/OpenStackService.php +51 −33 Original line number Diff line number Diff line Loading @@ -299,7 +299,10 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter $instances = $response['body']['servers'] ?? []; foreach ($instances ?: [] as $key => $instance) { $instance_tags = $this->getInstanceTags(['InstanceId' => $instance['id']]); $instance_tags = !empty($instance['OS-EXT-STS:vm_state']) && $instance['OS-EXT-STS:vm_state'] !== 'building' ? $this->getInstanceTags(['InstanceId' => $instance['id']]) : []; foreach ($instance['security_groups'] ?? [] as $key_group => $group) { $security_groups[$key_group] = [ Loading @@ -321,13 +324,17 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter } // Get flavor Response. $flavor_id = $instance['flavor']['id'] ?? NULL; $flavor_data = $this->describeFlavorById([], $flavor_id); $flavor_data = !empty($instance['flavor']['id']) ? $this->describeFlavorById([], $instance['flavor']['id']) : []; // Get port response. $port_result = $this->instancePortInterface([ $port_result = !empty($instance['OS-EXT-STS:vm_state']) && $instance['OS-EXT-STS:vm_state'] !== 'building' ? $this->instancePortInterface([ 'InstanceId' => $instance['id'], ]); ]) : []; $port_ids = []; if (!empty($port_result)) { Loading Loading @@ -442,13 +449,17 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter } // Get flavor Response. $flavor_id = $instance['flavor']['id'] ?? NULL; $flavor_data = $this->describeFlavorById([], $flavor_id); $flavor_data = !empty($instance['flavor']['id']) ? $this->describeFlavorById([], $instance['flavor']['id']) : []; // Get port response. $port_result = $this->instancePortInterface([ $port_result = !empty($instance['OS-EXT-STS:vm_state']) && $instance['OS-EXT-STS:vm_state'] !== 'building' ? $this->instancePortInterface([ 'InstanceId' => $instance['id'], ]); ]) : []; $port_ids = []; if (!empty($port_result)) { Loading Loading @@ -678,36 +689,40 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter $server_id = !empty($response['body']['server']) ? $response['body']['server']['id'] : ''; $promise = new Promise(function () use (&$promise, $server_id) { $body = [ 'status' => 'ACTIVE', ]; $credentials = [ 'http_method' => 'get', 'endpoint' => $this->getEndpoint(OpenStackServiceInterface::COMPUTE_ENDPOINT, '/servers'), 'params' => $body, 'endpoint' => $this->getEndpoint(OpenStackServiceInterface::COMPUTE_ENDPOINT, '/servers') . "/$server_id", ]; for ($i = 0; $i < OpenStackServiceInterface::WAIT_SECOUNDS_FOR_OPENSTACK_INSTANCE_ACTIVE; $i++) { // Get servers whose status is active. $response = $this->getClient($credentials); $get_response = $this->getClient($credentials); // If the server_id of the created server exists in response, // exit from the loop. if (array_search($server_id, array_column($response['body']['servers'], 'id')) !== FALSE) { // Exit from the loop when vm_state becomes active. if (!empty($get_response['body']['server']['OS-EXT-STS:vm_state']) && $get_response['body']['server']['OS-EXT-STS:vm_state'] === 'active') { break; } sleep(OpenStackServiceInterface::OPENSTACK_INSTANCE_STATUS_CHECK_INTERVAL); } $promise->resolve($response['body']['server']['id']); $promise->resolve(!empty($get_response['body']['server']['id']) ? $get_response['body']['server']['id'] : 0 ); }); $promise->wait(); $server_id = $promise->wait(); // Create instance tags. $this->createTags([ 'Resources' => [$response['body']['server']['id']], !empty($server_id) ? $this->createTags([ 'Resources' => [$server_id], 'Tags' => $tags, 'EntityType' => 'openstack_instance', ]); ]) : $this->messenger->addError($this->t('Failed to create tag because the @name instance did not start within @wait_secound seconds.', [ '@name' => $params['Name'], '@wait_secound' => OpenStackServiceInterface::WAIT_SECOUNDS_FOR_OPENSTACK_INSTANCE_ACTIVE, ])); return $response['status_code'] === 202 ? ['Success' => TRUE] : NULL; } Loading Loading @@ -987,7 +1002,10 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter return $tags; } $uid = $tag_result[0]; $uid = 0; if (preg_match('/[^__]+$/', $tag_result[0], $matches)) { $uid = $matches[0]; } $uid_key_name = $this->getTagKeyCreatedByUid( 'openstack', $this->cloudContext, Loading Loading @@ -1821,7 +1839,7 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter * @return array * The Flavor list API response. */ public function describeFlavorById(array $params = [], $flavor_id = '') { public function describeFlavorById(array $params = [], $flavor_id = ''): array { $this->loadCredentials(); $credentials = [ Loading @@ -1832,7 +1850,7 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter $response = $this->getClient($credentials); return $response['body']['flavor']; return !empty($response['body']['flavor']) ? $response['body']['flavor'] : []; } /** Loading Loading @@ -2704,7 +2722,7 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter * @return array * The Instance Port Interface list API response. */ public function instancePortInterface(array $params = []) { public function instancePortInterface(array $params = []): array { $this->loadCredentials(); $credentials = [ Loading Loading @@ -3681,7 +3699,7 @@ class OpenStackService extends CloudServiceBase implements OpenStackServiceInter * @return array * Array interpretation of the response body. */ private function request($http_method, $endpoint, array $params = []) { private function request($http_method, $endpoint, array $params = []): array { $output = []; try { Loading
modules/cloud_service_providers/openstack/tests/src/Behat/features/templates/OpenStack-ATDD-00-02-CreateDrupalResources.feature +2 −3 Original line number Diff line number Diff line Loading @@ -49,9 +49,8 @@ Feature: Create a Drupal role for OpenStack and a user as "Administrator" And I check the box "View any OpenStack image" And I check the box "Edit any OpenStack image" # Allow to view an instance And I check the box "View any OpenStack instance" And I check the box "Edit any OpenStack instance" And I check the box "Delete / Terminate any OpenStack instance" # Temporarily add the following permission until the default permission includes this. And I check the box "Delete / Terminate own OpenStack instance" # Allow to launch an instance. And I check the box "Launch approved cloud launch template" And I check the box "Delete own cloud launch templates" Loading
modules/cloud_service_providers/openstack/tests/src/Behat/features/templates/OpenStack-ATDD-02-03-LaunchInstances.feature +1 −3 Original line number Diff line number Diff line Loading @@ -13,9 +13,7 @@ Feature: Launch an instance for OpenStack as "Authenticated User" And I wait for AJAX to finish Then the url should match "/clouds/openstack/{{ cloud_context }}/instance" And I should see the success message "has been launched" # Temporarily comment out the error check until "instance not found" error # is addressed. # And I should see neither error nor warning messages And I should see neither error nor warning messages And I wait {{ wait }} milliseconds And I click "Refresh" And I should see "{{ instance_flavor }}" in the "{{ instance_name }}" row Loading
modules/cloud_service_providers/openstack/tests/src/Behat/features/templates/OpenStack-ATDD-03-06-OperateInstances.feature +2 −5 Original line number Diff line number Diff line Loading @@ -33,9 +33,7 @@ Feature: Launch, stop, and terminate an instance for OpenStack as "Authenticated And I wait for AJAX to finish Then the url should match "/clouds/openstack/{{ cloud_context }}/instance" And I should see the success message "has been launched" # Temporarily comment out the error check until "instance not found" error # is addressed. # And I should see neither error nor warning messages And I should see neither error nor warning messages And I wait {{ wait }} milliseconds And I click "Refresh" And I should see "{{ instance_flavor }}" in the "{{ instance_name_operate }}" row Loading @@ -57,8 +55,7 @@ Feature: Launch, stop, and terminate an instance for OpenStack as "Authenticated And I should see "{{ security_group_name }}" in the "Security groups" And I should see "{{ key_name }}" in the "Key pair name" And I press "Others" # Temporarily commenting out until the authored_by issue is addressed. # And I should see "{{ drupal_user_name }}" in the "Authored by" And I should see "{{ drupal_user_name }}" in the "Authored by" @api Scenario: Stop the running instance Loading
src/Service/CloudServiceInterface.php +0 −42 Original line number Diff line number Diff line Loading @@ -319,46 +319,4 @@ interface CloudServiceInterface { */ public function buildOwnerQueryCondition(AlterableInterface $query): void; /** * Get the key name of the UID tag. * * @param string $bundle * The bundle the entity type, such as aws_cloud. * @param string $cloud_context * The cloud context. * @param string $tag * The tag. * @param int $uid * The uid. * * @throws \Drupal\cloud\Service\CloudServiceException * Throws CloudServiceException. * * @return string * The string of tag. */ public function getTagKeyCreatedByUid($bundle, $cloud_context, $tag = '', $uid = 0): string; /** * Get the key name of the UID tag. * * @param string $bundle * The bundle the entity type, such as aws_cloud. * @param string $cloud_context * The cloud context. * @param int $uid * The uid. * @param string $tag * The tag. * * @return string * The string of tag. */ public function getTagValueCreatedByUid( string $bundle, string $cloud_context, int $uid, string $tag = '' ): string; }