Skip to content
Snippets Groups Projects
Commit d1df0b25 authored by xiaohua guan's avatar xiaohua guan Committed by Yas Naoi
Browse files

Issue #3017114 by Xiaohua Guan, yas, baldwinlouie: Make it possible to change...

Issue #3017114 by Xiaohua Guan, yas, baldwinlouie: Make it possible to change the instance type of my instance
parent 632dd409
No related branches found
No related tags found
No related merge requests found
......@@ -99,6 +99,13 @@ class Instance extends CloudContentEntityBase implements InstanceInterface {
return $this->get('instance_type')->value;
}
/**
* {@inheritdoc}
*/
public function setInstanceType($instance_type) {
return $this->set('instance_type', $instance_type);
}
/**
* {@inheritdoc}
*/
......
......@@ -106,16 +106,21 @@ class InstanceEditForm extends AwsCloudContentForm {
];
$form['instance_type'] = [
'#type' => 'textfield',
'#type' => 'select',
'#title' => $this->t('Instance Type'),
'#size' => 60,
'#default_value' => $entity->instance_type(),
'#weight' => -5,
'#required' => FALSE,
'#attributes' => ['readonly' => 'readonly'],
'#disabled' => TRUE,
'#options' => $this->getInstanceTypeOptions(),
];
if ($entity->instance_state() !== 'stopped') {
$form['instance_type'] += [
'#attributes' => ['readonly' => 'readonly'],
'#disabled' => TRUE,
];
}
$form['kernel_id'] = [
'#type' => 'textfield',
'#title' => $this->t('Kernel Image'),
......@@ -185,11 +190,11 @@ class InstanceEditForm extends AwsCloudContentForm {
public function save(array $form, FormStateInterface $form_state) {
/* @var \Drupal\Core\Datetime\DrupalDateTime $termination_timestamp */
$termination_timestamp = $form_state->getValue('termination_timestamp')[0]['value'];
if ($termination_timestamp == NULL) {
// Unset the termination timestamp.
$this->entity->set('termination_timestamp', NULL);
}
parent::save($form, $form_state);
// update the instance name - it is a tag.
......@@ -215,9 +220,33 @@ class InstanceEditForm extends AwsCloudContentForm {
$this->awsEc2Service->setCloudContext($this->entity->get('cloud_context')->value);
$this->awsEc2Service->createTags($params);
// Update the instance type.
if ($this->entity->instance_state() == 'stopped'
&& $this->entity->instance_type() != $form['instance_type']['#default_value']) {
$response = $this->awsEc2Service->modifyInstanceAttribute([
'InstanceId' => $this->entity->get('instance_id')->value,
'InstanceType' => ['Value' => $this->entity->instance_type()],
]);
if ($response['Return']) {
$this->messenger->addMessage($this->t('Instance type was updated.'), 'status');
}
else {
$this->messenger->addMessage($this->t('Instance type couldn\'t be updated.'), 'error');
}
}
// Set the redirect url to the listing page.
$form_state->setRedirect('view.aws_instances.page_1', ['cloud_context' => $this->entity->cloud_context()]);
}
private function getInstanceTypeOptions() {
$types = \Drupal::config('aws_cloud.settings')->get('aws_cloud_instance_types');
$instance_array = explode("\r\n", $types);
foreach ($instance_array as $type) {
$instance_types[$type] = $type;
}
return $instance_types;
}
}
......@@ -572,6 +572,15 @@ class AwsEc2Service implements AwsEc2ServiceInterface {
return $results;
}
/**
* {@inheritdoc}
*/
public function modifyInstanceAttribute($params = []) {
$params += $this->getDefaultParameters();
$results = $this->execute('ModifyInstanceAttribute', $params);
return $results;
}
/**
* {@inheritdoc}
*/
......@@ -654,6 +663,7 @@ class AwsEc2Service implements AwsEc2ServiceInterface {
}
$entity->setSecurityGroups(implode(', ', $security_groups));
$entity->setInstanceType($instance['InstanceType']);
$entity->setRefreshed($timestamp);
$entity->set_launch_time($instance['LaunchTime']->__toString());
$entity->setTerminationTimestamp($termination_timestamp);
......
......@@ -416,6 +416,13 @@ interface AwsEc2ServiceInterface {
*/
public function startInstances($params = []);
/**
* Modifies the specified attribute of a instance
* @param array $params
* @return mixed
*/
public function modifyInstanceAttribute($params = []);
/**
* Attaches an EBS volume to a running or stopped
* instance and exposes it to the instance with the
......
......@@ -19,3 +19,5 @@ DescribeSnapshots:
Snapshots: []
DescribeVolumes:
Volumes: []
ModifyInstanceAttribute:
Return: true
......@@ -16,7 +16,7 @@ SecurityGroups:
GroupName: {{security_group_name}}
State:
Code: 16
Name: running
Name: {{state}}
PublicDnsName: {{public_dns_name}}
PublicIpAddress: {{public_ip_address}}
PrivateDnsName: {{private_dns_name}}
......
......@@ -71,6 +71,7 @@ class InstanceTest extends AwsCloudTestCase {
'image_id' => 'ami-' . $this->random->name(8, TRUE),
'reason' => $this->random->string(16, TRUE),
'instance_id' => 'i-' . $this->random->name(17, TRUE),
'state' => 'running',
];
}
......@@ -143,18 +144,6 @@ class InstanceTest extends AwsCloudTestCase {
'@name' => $edit[$i]['name'],
]));
$this->assertResponse(200, t('Edit | HTTP 200: A New Cloud Instance #@num', ['@num' => $num]));
$this->assertNoText(t('Notice'), t('Edit | Make sure w/o Notice'));
$this->assertNoText(t('warning'), t('Edit | Make sure w/o Warnings'));
$this->assertText($edit[$i]['name'], t('Name: @name ', ['@name' => $edit[$i]['name']]));
$this->assertText(t('The AWS Cloud Instance "@name" has been saved.', [
'@name' => $edit[$i]['name'],
]),
t('Confirm Message') . ': '
. t('Edit | The AWS Cloud Instance "@name" has been saved.', [
'@name' => $edit[$i]['name'],
]));
// Make sure listing.
$this->drupalGet("/clouds/aws_cloud/$cloud_context/instance");
$this->assertResponse(200, t('Edit | List | HTTP 200: Instance #@num', ['@num' => $num]));
......@@ -232,6 +221,10 @@ class InstanceTest extends AwsCloudTestCase {
$security_group_name2 = $this->random->name(8, TRUE);
$this->updateSecurityGroupsInMockData($security_group_name1, $security_group_name2);
// Change instance type.
$instance_type = $this->random->name(6, TRUE);
$this->updateInstanceTypeInMockData($instance_type);
// Run cron job to update instances.
$key = \Drupal::state()->get('system.cron_key');
$this->drupalGet('/cron/' . $key);
......@@ -243,6 +236,83 @@ class InstanceTest extends AwsCloudTestCase {
$this->assertNoText(t('Notice'), t('View | Make sure w/o Notice'));
$this->assertNoText(t('warning'), t('View | Make sure w/o Warnings'));
$this->assertText("$security_group_name1, $security_group_name2", t('Security Group'));
$this->assertText($instance_type, t('Instance Type'));
}
/**
* Tests updating instance type.
*/
function testUpdateInstanceType() {
$this->_testUpdateInstanceTypeRepeat(AWS_CLOUD_INSTANCE_REPEAT_COUNT);
}
private function _testUpdateInstanceTypeRepeat($max_test_repeat_count = 1) {
$cloud_context = $this->cloud_context;
for ($i = 0; $i < $max_test_repeat_count; $i++) {
$num = $i + 1;
$this->createServerTemplate();
// Launch a stopped Instance.
$add = $this->createInstanceTestData();
$this->addInstanceMockData($add[$i]['name'], $add[$i]['key_pair_name'], 'stopped');
$this->drupalPostForm("/clouds/design/server_template/$cloud_context/$num/launch",
[],
t('Launch'));
$this->assertResponse(200, t('HTTP 200: Launch | A New Cloud Instance @num', [
'@num' => $num
]));
$this->assertNoText(t('Notice'), t('Launch | Make sure w/o Notice'));
$this->assertNoText(t('warning'), t('Launch | Make sure w/o Warnings'));
$this->assertText('stopped', t('Instance Type: stopped'));
// Edit instance.
$edit = $this->createInstanceTestData();
unset($edit[$i]['cloud_type']);
unset($edit[$i]['image_id']);
unset($edit[$i]['min_count']);
unset($edit[$i]['max_count']);
unset($edit[$i]['key_pair_name']);
unset($edit[$i]['is_monitoring']);
unset($edit[$i]['availability_zone']);
unset($edit[$i]['security_groups']);
unset($edit[$i]['kernel_id']);
unset($edit[$i]['ramdisk_id']);
unset($edit[$i]['user_data']);
$instance_type = 'm1.small';
$edit[$i]['instance_type'] = $instance_type;
$this->drupalPostForm("/clouds/aws_cloud/$cloud_context/instance/$num/edit",
$edit[$i],
t('Save'));
$this->updateInstanceInMockData($i, $edit[$i]['name']);
$this->assertResponse(200, t('Edit | HTTP 200: A New Instance #@num', [
'@num' => $num
]));
$this->assertNoText(t('Notice'), t('Edit | Make sure w/o Notice'));
$this->assertNoText(t('warning'), t('Edit | Make sure w/o Warnings'));
$this->assertText(t('The AWS Cloud Instance "@name" has been saved.', [
'@name' => $edit[$i]['name'],
]),
t('Confirm Message') . ': '
. t('Edit | The AWS Cloud Instance "@name" has been saved.', [
'@name' => $edit[$i]['name'],
]));
$this->assertText('Instance type was updated.');
// Verify instance type.
$this->drupalGet("/clouds/aws_cloud/$cloud_context/instance/$num");
$this->assertResponse(200, t('View | HTTP 200: The Cloud Instance @num', [
'@num' => $num
]));
$this->assertNoText(t('Notice'), t('View | Make sure w/o Notice'));
$this->assertNoText(t('warning'), t('View | Make sure w/o Warnings'));
$this->assertText($instance_type, t('Instance Type') . ': ' . $instance_type);
}
}
private function createInstanceTestData() {
......@@ -262,7 +332,7 @@ class InstanceTest extends AwsCloudTestCase {
'is_monitoring' => 0,
'availability_zone' => "us-west-$num",
'security_groups' => "security_group-$num-" . $this->random->name(8, TRUE),
'instance_type' => "t$num.small",
'instance_type' => "t$num.micro",
'kernel_id' => 'aki-' . $this->random->name(8, TRUE),
'ramdisk_id' => 'ari-' . $this->random->name(8, TRUE),
'user_data' => "User Data #$num: " . $this->random->string(64, TRUE),
......@@ -298,11 +368,12 @@ class InstanceTest extends AwsCloudTestCase {
$template->save();
}
private function addInstanceMockData($name, $key_pair_name) {
private function addInstanceMockData($name, $key_pair_name, $state = 'running') {
$mock_data = $this->getMockDataFromConfig();
$vars = $this->getMockDataTemplateVars();
$vars['name'] = $name;
$vars['key_name'] = $key_pair_name;
$vars['state'] = $state;
$instance_mock_data_content = $this->getMockDataFileContent(get_class($this), $vars, '_instance');
$instance_mock_data = Yaml::decode($instance_mock_data_content);
......@@ -325,6 +396,13 @@ class InstanceTest extends AwsCloudTestCase {
$this->updateMockDataToConfig($mock_data);
}
private function updateInstanceTypeInMockData($instance_type) {
$mock_data = $this->getMockDataFromConfig();
$mock_data['DescribeInstances']['Reservations'][0]['Instances'][0]['InstanceType']
= $instance_type;
$this->updateMockDataToConfig($mock_data);
}
private function updateInstanceInMockData($instance_index, $name) {
$mock_data = $this->getMockDataFromConfig();
$mock_data['DescribeInstances']['Reservations'][0]['Instances'][$instance_index]['Tags'][0]['Value'] = $name;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment