Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding the pause, hibernate and resume features between the AWS and F… #759

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/main/java/cloud/fogbow/ras/constants/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ public static class Exception {
public static final String ERROR_WHILE_CREATING_RESOURCE_S = Log.ERROR_WHILE_CREATING_RESOURCE_S;
public static final String ERROR_WHILE_GETTING_RESOURCE_S_FROM_CLOUD = Log.ERROR_WHILE_GETTING_RESOURCE_S_FROM_CLOUD;
public static final String ERROR_WHILE_GETTING_VOLUME_INSTANCE = Log.ERROR_WHILE_GETTING_VOLUME_INSTANCE;
public static final String ERROR_WHILE_HIBERNATING_S = Log.ERROR_WHILE_HIBERNATING_S;
public static final String ERROR_WHILE_PAUSING_S = Log.ERROR_WHILE_PAUSING_S;
public static final String ERROR_WHILE_PROCESSING_VOLUME_REQUIREMENTS = Log.ERROR_WHILE_PROCESSING_VOLUME_REQUIREMENTS;
public static final String ERROR_WHILE_REMOVING_RESOURCE_S_S = Log.ERROR_WHILE_REMOVING_RESOURCE_S_S;
public static final String ERROR_WHILE_REMOVING_VM_S_S = "Error while removing virtual machine: %s, with response: %s.";
public static final String ERROR_WHILE_REMOVING_VOLUME_IMAGE_S_S = Log.ERROR_WHILE_REMOVING_VOLUME_IMAGE_S_S;
public static final String ERROR_WHILE_RESUMING_S = Log.ERROR_WHILE_RESUMING_S;
public static final String EXTERNAL_NETWORK_NOT_FOUND = "External network not found.";
public static final String FAILED_TO_GET_QUOTA = "Failed to get quota.";
public static final String GENERIC_EXCEPTION_S = Log.GENERIC_EXCEPTION_S;
Expand Down Expand Up @@ -156,12 +159,15 @@ public static class Log {
public static final String ERROR_WHILE_GETTING_USER_S_S = "Error while getting info about user %s: %s.";
public static final String ERROR_WHILE_GETTING_USERS_S = "Error while getting info about users: %s.";
public static final String ERROR_WHILE_GETTING_VOLUME_INSTANCE = "Error while getting volume instance.";
public static final String ERROR_WHILE_HIBERNATING_S = "Error while hibernating the following image: %s";
public static final String ERROR_WHILE_INSTANTIATING_FROM_TEMPLATE_S = "Error while instantiating an instance from template: %s.";
public static final String ERROR_WHILE_LOADING_IMAGE_S = "Error while loading the following image: %s";
public static final String ERROR_WHILE_PAUSING_S = "Error while pausing the following image: %s";
public static final String ERROR_WHILE_PROCESSING_ASYNCHRONOUS_REQUEST_INSTANCE_STEP = "Error while It was trying to pass to the next step in the asynchronous request instance.";
public static final String ERROR_WHILE_PROCESSING_VOLUME_REQUIREMENTS = "Error while processing volume requirements";
public static final String ERROR_WHILE_REMOVING_RESOURCE_S_S = "An error occurred while removing %s: %s.";
public static final String ERROR_WHILE_REMOVING_VOLUME_IMAGE_S_S = "Error while removing volume image: %s, with response: %s.";
public static final String ERROR_WHILE_RESUMING_S = "Error while resuming the following image: %s.";
public static final String ERROR_WHILE_UPDATING_NETWORK_S = "Error while updating a network from template: %s.";
public static final String ERROR_WHILE_UPDATING_SECURITY_GROUPS_S = "Error while updating a security groups from template: %s.";
public static final String FIRST_STEP_CREATE_PUBLIC_IP_ASYNC_BEHAVIOUR = "First step: Public IP Address created and associated with the virtual machine.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,23 +130,32 @@ public void deleteInstance(ComputeOrder computeOrder, AwsV2User cloudUser) throw
}

@Override
public void takeSnapshot(ComputeOrder order, String name, AwsV2User cloudUser) throws FogbowException {
public void takeSnapshot(ComputeOrder computeOrder, String name, AwsV2User cloudUser) throws FogbowException {
// ToDo: implement
}

@Override
public void pauseInstance(ComputeOrder order, AwsV2User cloudUser) throws FogbowException {
// ToDo: implement
public void pauseInstance(ComputeOrder computeOrder, AwsV2User cloudUser) throws FogbowException {
String instanceId = computeOrder.getInstanceId();
LOGGER.info(String.format(Messages.Log.PAUSING_INSTANCE_S, instanceId));
Ec2Client client = AwsV2ClientUtil.createEc2Client(cloudUser.getToken(), this.region);
doPauseInstance(instanceId, client);
}

@Override
public void hibernateInstance(ComputeOrder order, AwsV2User cloudUser) throws FogbowException {
// ToDo: implement
public void hibernateInstance(ComputeOrder computeOrder, AwsV2User cloudUser) throws FogbowException {
String instanceId = computeOrder.getInstanceId();
LOGGER.info(String.format(Messages.Log.HIBERNATING_INSTANCE_S, instanceId));
Ec2Client client = AwsV2ClientUtil.createEc2Client(cloudUser.getToken(), this.region);
doHibernateInstance(instanceId, client);
}

@Override
public void resumeInstance(ComputeOrder order, AwsV2User cloudUser) throws FogbowException {
// ToDo: implement
public void resumeInstance(ComputeOrder computeOrder, AwsV2User cloudUser) throws FogbowException {
String instanceId = computeOrder.getInstanceId();
LOGGER.info(String.format(Messages.Log.RESUMING_INSTANCE_S, instanceId));
Ec2Client client = AwsV2ClientUtil.createEc2Client(cloudUser.getToken(), this.region);
doResumeInstance(instanceId, client);
}

@Override
Expand Down Expand Up @@ -181,7 +190,50 @@ void doDeleteInstance(String instanceId, Ec2Client client) throws InternalServer
throw new InternalServerErrorException(String.format(Messages.Exception.ERROR_WHILE_REMOVING_RESOURCE_S_S, RESOURCE_NAME, instanceId));
}
}


@VisibleForTesting
void doPauseInstance(String instanceId, Ec2Client client) throws InternalServerErrorException {
StopInstancesRequest request = StopInstancesRequest.builder()
.instanceIds(instanceId)
.build();

try{
client.stopInstances(request);
} catch (SdkException e) {
LOGGER.error(String.format(Messages.Log.ERROR_WHILE_PAUSING_S, RESOURCE_NAME, instanceId), e);
throw new InternalServerErrorException(String.format(Messages.Exception.ERROR_WHILE_PAUSING_S, RESOURCE_NAME, instanceId));
}
}

@VisibleForTesting
void doHibernateInstance(String instanceId, Ec2Client client) throws InternalServerErrorException {
StopInstancesRequest request = StopInstancesRequest.builder()
.hibernate(true)
.instanceIds(instanceId)
.build();

try{
client.stopInstances(request);
} catch (SdkException e) {
LOGGER.error(String.format(Messages.Log.ERROR_WHILE_HIBERNATING_S, RESOURCE_NAME, instanceId), e);
throw new InternalServerErrorException(String.format(Messages.Exception.ERROR_WHILE_HIBERNATING_S, RESOURCE_NAME, instanceId));
}
}

@VisibleForTesting
void doResumeInstance(String instanceId, Ec2Client client) throws InternalServerErrorException {
StartInstancesRequest request = StartInstancesRequest.builder()
.instanceIds(instanceId)
.build();

try {
client.startInstances(request);
} catch (SdkException e) {
LOGGER.error(String.format(Messages.Log.ERROR_WHILE_RESUMING_S, RESOURCE_NAME, instanceId), e);
throw new InternalServerErrorException(String.format(Messages.Exception.ERROR_WHILE_RESUMING_S, RESOURCE_NAME, instanceId));
}
}

@VisibleForTesting
ComputeInstance doGetInstance(String instanceId, Ec2Client client) throws FogbowException {
DescribeInstancesResponse response = AwsV2CloudUtil.doDescribeInstanceById(instanceId, client);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,71 @@ public void testDeleteInstance() throws FogbowException {
Mockito.verify(this.plugin, Mockito.times(TestUtils.RUN_ONCE))
.doDeleteInstance(Mockito.eq(order.getInstanceId()), Mockito.eq(this.client));
}

// test case: When calling the pauseInstance method, with a compute order and
// cloud user valid, the instance in the cloud must be paused (stopped).
@Test
public void testPauseInstance() throws FogbowException {
// set up
ComputeOrder order = this.testUtils.createLocalComputeOrder();
AwsV2User cloudUser = Mockito.mock(AwsV2User.class);

Mockito.doNothing().when(this.plugin).doPauseInstance(Mockito.eq(order.getInstanceId()), Mockito.eq(this.client));

// exercise
this.plugin.pauseInstance(order, cloudUser);

// verify
PowerMockito.verifyStatic(AwsV2ClientUtil.class, VerificationModeFactory.times(TestUtils.RUN_ONCE));
AwsV2ClientUtil.createEc2Client(Mockito.eq(cloudUser.getToken()), Mockito.anyString());

Mockito.verify(this.plugin, Mockito.times(TestUtils.RUN_ONCE))
.doPauseInstance(Mockito.eq(order.getInstanceId()), Mockito.eq(this.client));
}


// test case: When calling the hibernateInstance method, with a compute order and
// cloud user valid, the instance in the cloud must be hibernated.
@Test
public void testHibernateInstance() throws FogbowException {
// set up
ComputeOrder order = this.testUtils.createLocalComputeOrder();
AwsV2User cloudUser = Mockito.mock(AwsV2User.class);

Mockito.doNothing().when(this.plugin).doHibernateInstance(Mockito.eq(order.getInstanceId()), Mockito.eq(this.client));

// exercise
this.plugin.hibernateInstance(order, cloudUser);

// verify
PowerMockito.verifyStatic(AwsV2ClientUtil.class, VerificationModeFactory.times(TestUtils.RUN_ONCE));
AwsV2ClientUtil.createEc2Client(Mockito.eq(cloudUser.getToken()), Mockito.anyString());

Mockito.verify(this.plugin, Mockito.times(TestUtils.RUN_ONCE))
.doHibernateInstance(Mockito.eq(order.getInstanceId()), Mockito.eq(this.client));
}


// test case: When calling the resumeInstance method, with a compute order and
// cloud user valid, the instance in the cloud must be resumed (started).
@Test
public void testResumeInstance() throws FogbowException {
// set up
ComputeOrder order = this.testUtils.createLocalComputeOrder();
AwsV2User cloudUser = Mockito.mock(AwsV2User.class);

Mockito.doNothing().when(this.plugin).doResumeInstance(Mockito.eq(order.getInstanceId()), Mockito.eq(this.client));

// exercise
this.plugin.resumeInstance(order, cloudUser);

// verify
PowerMockito.verifyStatic(AwsV2ClientUtil.class, VerificationModeFactory.times(TestUtils.RUN_ONCE));
AwsV2ClientUtil.createEc2Client(Mockito.eq(cloudUser.getToken()), Mockito.anyString());

Mockito.verify(this.plugin, Mockito.times(TestUtils.RUN_ONCE))
.doResumeInstance(Mockito.eq(order.getInstanceId()), Mockito.eq(this.client));
}

// test case: When calling the isReady method with the cloud state RUNNING,
// this means that the state of compute is READY and it must return true.
Expand Down Expand Up @@ -273,7 +338,141 @@ public void testDoDeleteInstanceFail() {
Assert.assertEquals(expected, e.getMessage());
}
}


// test case: When calling the doPauseInstance method, it must verify
// that is call was successful.
@Test
public void testDoPauseInstance() throws FogbowException {
// set up
String instanceId = TestUtils.FAKE_INSTANCE_ID;

StopInstancesRequest request = StopInstancesRequest.builder()
.instanceIds(instanceId)
.build();

Mockito.when(this.client.stopInstances(Mockito.eq(request)))
.thenReturn(StopInstancesResponse.builder().build());

// exercise
this.plugin.doPauseInstance(instanceId, client);

// verify
Mockito.verify(this.client, Mockito.times(TestUtils.RUN_ONCE)).stopInstances(Mockito.eq(request));
}

// test case: When calling the doPauseInstance method, and an unexpected error
// occurs, it must verify if an InternalServerErrorException has been thrown.
@Test
public void testDoPauseInstanceFail() {
// set up
String instanceId = TestUtils.FAKE_INSTANCE_ID;

Mockito.when(this.client.stopInstances(Mockito.any(StopInstancesRequest.class)))
.thenThrow(SdkClientException.builder().build());

String expected = String.format(Messages.Log.ERROR_WHILE_PAUSING_S, AwsComputePlugin.RESOURCE_NAME,
instanceId);

try {
// exercise
this.plugin.doPauseInstance(instanceId, this.client);
Assert.fail();
} catch (InternalServerErrorException e) {
// verify
Assert.assertEquals(expected, e.getMessage());
}
}


// test case: When calling the doHibernateInstance method, it must verify
// that is call was successful.
@Test
public void testDoHibernateInstance() throws FogbowException {
// set up
String instanceId = TestUtils.FAKE_INSTANCE_ID;

StopInstancesRequest request = StopInstancesRequest.builder()
.hibernate(true)
.instanceIds(instanceId)
.build();

Mockito.when(this.client.stopInstances(Mockito.eq(request)))
.thenReturn(StopInstancesResponse.builder().build());

// exercise
this.plugin.doHibernateInstance(instanceId, client);

// verify
Mockito.verify(this.client, Mockito.times(TestUtils.RUN_ONCE)).stopInstances(Mockito.eq(request));
}

// test case: When calling the doHibernateInstance method, and an unexpected error
// occurs, it must verify if an InternalServerErrorException has been thrown.
@Test
public void testDoHibernateInstanceFail() {
// set up
String instanceId = TestUtils.FAKE_INSTANCE_ID;

Mockito.when(this.client.stopInstances(Mockito.any(StopInstancesRequest.class)))
.thenThrow(SdkClientException.builder().build());

String expected = String.format(Messages.Log.ERROR_WHILE_HIBERNATING_S, AwsComputePlugin.RESOURCE_NAME,
instanceId);

try {
// exercise
this.plugin.doHibernateInstance(instanceId, this.client);
Assert.fail();
} catch (InternalServerErrorException e) {
// verify
Assert.assertEquals(expected, e.getMessage());
}
}

// test case: When calling the doResumeInstance method, it must verify
// that is call was successful.
@Test
public void testDoResumeInstance() throws FogbowException {
// set up
String instanceId = TestUtils.FAKE_INSTANCE_ID;

StartInstancesRequest request = StartInstancesRequest.builder()
.instanceIds(instanceId)
.build();

Mockito.when(this.client.startInstances(Mockito.eq(request)))
.thenReturn(StartInstancesResponse.builder().build());

// exercise
this.plugin.doResumeInstance(instanceId, client);

// verify
Mockito.verify(this.client, Mockito.times(TestUtils.RUN_ONCE)).startInstances(Mockito.eq(request));
}

// test case: When calling the doResumeInstance method, and an unexpected error
// occurs, it must verify if an InternalServerErrorException has been thrown.
@Test
public void testDoResumeInstanceFail() {
// set up
String instanceId = TestUtils.FAKE_INSTANCE_ID;

Mockito.when(this.client.startInstances(Mockito.any(StartInstancesRequest.class)))
.thenThrow(SdkClientException.builder().build());

String expected = String.format(Messages.Log.ERROR_WHILE_RESUMING_S, AwsComputePlugin.RESOURCE_NAME,
instanceId);

try {
// exercise
this.plugin.doResumeInstance(instanceId, this.client);
Assert.fail();
} catch (InternalServerErrorException e) {
// verify
Assert.assertEquals(expected, e.getMessage());
}
}

// test case: When calling the doGetInstance method, it must verify
// that is call was successful.
@Test
Expand Down