package se.kth.karamel.backend.launcher.nova; import com.google.common.base.Optional; import com.google.common.base.Predicates; import com.google.common.collect.FluentIterable; import org.jclouds.ContextBuilder; import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.RunNodesException; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.options.TemplateOptions; import org.jclouds.domain.LoginCredentials; import org.jclouds.net.domain.IpProtocol; import org.jclouds.openstack.nova.v2_0.NovaApi; import org.jclouds.openstack.nova.v2_0.compute.NovaComputeService; import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions; import org.jclouds.openstack.nova.v2_0.domain.Ingress; import org.jclouds.openstack.nova.v2_0.domain.KeyPair; import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup; import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule; import org.jclouds.openstack.nova.v2_0.extensions.KeyPairApi; import org.jclouds.openstack.nova.v2_0.extensions.SecurityGroupApi; import org.jclouds.rest.AuthorizationException; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.mockito.Matchers; import se.kth.karamel.backend.running.model.ClusterRuntime; import se.kth.karamel.backend.running.model.GroupRuntime; import se.kth.karamel.backend.running.model.MachineRuntime; import se.kth.karamel.common.clusterdef.Nova; import se.kth.karamel.common.clusterdef.json.JsonCluster; import se.kth.karamel.common.clusterdef.json.JsonGroup; import se.kth.karamel.common.exception.InvalidNovaCredentialsException; import se.kth.karamel.common.exception.KaramelException; import se.kth.karamel.common.util.Confs; import se.kth.karamel.common.util.NovaCredentials; import se.kth.karamel.common.util.SshKeyPair; import se.kth.karamel.common.util.settings.NovaSetting; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import static org.junit.Assert.*; import static org.mockito.Mockito.*; public class NovaLauncherTest { private static final Set<String> ports = new HashSet<>(); static { for (int i = 100; i <= 250; i++) { ports.add(i + ""); } } private NovaContext novaContext; private SshKeyPair sshKeyPair; private NovaCredentials novaCredentials; private ContextBuilder builder; private ComputeServiceContext serviceContext; private ComputeService novaComputeService; private NovaApi novaApi; private SecurityGroupApi securityGroupApi; private KeyPairApi keyPairApi; private Optional securityGroupApiOptional; private Optional keyPairApiOptional; private SecurityGroup securityGroupCreated; private String clusterName; private String groupName; private Nova nova; @Before public void setup() { //initialize value objects novaCredentials = new NovaCredentials(); novaCredentials.setAccountName("pepe"); novaCredentials.setAccountPass("1234"); novaCredentials.setEndpoint("http://sics-nova.se:8080"); novaCredentials.setRegion("SICSRegion"); nova = new Nova(); nova.setImage("ubuntu14.04"); nova.setFlavor("1"); sshKeyPair = new SshKeyPair(); sshKeyPair.setPrivateKey("this is my private key"); sshKeyPair.setPublicKey("this is my public key"); sshKeyPair.setPassphrase("helloworld"); sshKeyPair.setPrivateKeyPath("/pathToPrivateKey"); sshKeyPair.setPublicKeyPath("/pathToPublicKey"); clusterName = "novaTest"; groupName = "dummyGroup"; //Mocking external dependencies builder = mock(ContextBuilder.class); serviceContext = mock(ComputeServiceContext.class); novaComputeService = mock(NovaComputeService.class); securityGroupApi = mock(SecurityGroupApi.class); novaApi = mock(NovaApi.class); keyPairApi = mock(KeyPairApi.class); securityGroupApiOptional = mock(Optional.class); keyPairApiOptional = mock(Optional.class); novaContext = mock(NovaContext.class); securityGroupCreated = mock(SecurityGroup.class); when(novaContext.getNovaCredentials()).thenReturn(novaCredentials); when(novaContext.getNovaApi()).thenReturn(novaApi); when(novaContext.getKeyPairApi()).thenReturn(keyPairApi); when(novaContext.getComputeService()).thenReturn(novaComputeService); when(builder.credentials(novaCredentials.getAccountName(),novaCredentials.getAccountPass())).thenReturn(builder); when(builder.endpoint(novaCredentials.getEndpoint())).thenReturn(builder); when(builder.buildView(ComputeServiceContext.class)).thenReturn(serviceContext); when(serviceContext.getComputeService()).thenReturn(novaComputeService); when(novaComputeService.getContext()).thenReturn(serviceContext); when(serviceContext.unwrapApi(NovaApi.class)).thenReturn(novaApi); when(novaApi.getSecurityGroupApi(novaCredentials.getRegion())).thenReturn(securityGroupApiOptional); when(securityGroupApiOptional.isPresent()).thenReturn(true); when(securityGroupApiOptional.get()).thenReturn(securityGroupApi); when(novaApi.getKeyPairApi(novaCredentials.getRegion())).thenReturn(keyPairApiOptional); when(keyPairApiOptional.get()).thenReturn(keyPairApi); } @Test public void validateNovaCredentialsTest() throws InvalidNovaCredentialsException { NovaContext context = NovaLauncher.validateCredentials(novaCredentials, builder); assertNotNull(context); assertNotNull(context.getSecurityGroupApi()); } @Test(expected = InvalidNovaCredentialsException.class) public void validateNovaCredentialsTestException() throws InvalidNovaCredentialsException { when(securityGroupApi.list()).thenThrow(AuthorizationException.class); NovaContext context = NovaLauncher.validateCredentials(novaCredentials, builder); } @Test public void readNovaCredentialsTest() { Confs confs = mock(Confs.class); when(confs.getProperty(NovaSetting.NOVA_ACCOUNT_ID_KEY.getParameter())).thenReturn(novaCredentials.getAccountName()); when(confs.getProperty(NovaSetting.NOVA_ACCESSKEY_KEY.getParameter())).thenReturn(novaCredentials.getAccountPass()); when(confs.getProperty(NovaSetting.NOVA_ACCOUNT_ENDPOINT.getParameter())).thenReturn(novaCredentials.getEndpoint()); when(confs.getProperty(NovaSetting.NOVA_REGION.getParameter())).thenReturn(novaCredentials.getRegion()); NovaCredentials credentials = NovaLauncher.readCredentials(confs); assertNotNull(credentials); } @Test(expected = KaramelException.class) public void createNovaLauncherTestNullContext() throws KaramelException { NovaLauncher launcher = new NovaLauncher(null, sshKeyPair); } @Test(expected = KaramelException.class) public void createNovaLauncherTestNullSSHKey() throws KaramelException { NovaLauncher launcher = new NovaLauncher(novaContext, null); } @Test public void createSecurityGroupTestWithTestingFlag() throws KaramelException { //Initializing and mocking need for method test SecurityGroupRule rule = mock(SecurityGroupRule.class); String uniqueGroup = NovaSetting.NOVA_UNIQUE_GROUP_NAME(clusterName, groupName); String uniqueDescription = NovaSetting.NOVA_UNIQUE_GROUP_DESCRIPTION(clusterName, groupName); Ingress ingress = Ingress.builder() .fromPort(0) .toPort(65535) .ipProtocol(IpProtocol.TCP) .build(); when(novaContext.getSecurityGroupApi()).thenReturn(securityGroupApi); when(securityGroupApi.createWithDescription(uniqueGroup, uniqueDescription)).thenReturn(securityGroupCreated); when(securityGroupCreated.getId()).thenReturn("10"); when(securityGroupApi.createRuleAllowingCidrBlock("10", ingress, "0.0.0.0/0")).thenReturn(rule); NovaLauncher novaLauncher = new NovaLauncher(novaContext, sshKeyPair); String groupId = novaLauncher.createSecurityGroup(clusterName, groupName, nova, ports); assertEquals("10", groupId); } @Test public void uploadSSHPublicKeyAndCreate() throws KaramelException { String keypairName = "pepeKeyPair"; KeyPair pair = mock(KeyPair.class); List<KeyPair> keyPairList = new ArrayList<>(); FluentIterable<KeyPair> keys = FluentIterable.from(keyPairList); when(keyPairApi.list()).thenReturn(keys); when(keyPairApi.createWithPublicKey(keypairName, sshKeyPair.getPublicKey())).thenReturn(pair); NovaLauncher novaLauncher = new NovaLauncher(novaContext, sshKeyPair); boolean uploadSuccessful = novaLauncher.uploadSshPublicKey(keypairName, nova, false); assertTrue(uploadSuccessful); } @Test public void uploadSSHPublicKeyAndRecreateOld() throws KaramelException { String keypairName = "pepeKeyPair"; KeyPair pair = mock(KeyPair.class); List<KeyPair> keyPairList = new ArrayList<>(); keyPairList.add(pair); FluentIterable<KeyPair> keys = FluentIterable.from(keyPairList); when(keyPairApi.list()).thenReturn(keys); when(keyPairApi.delete(keypairName)).thenReturn(true); when(keyPairApi.createWithPublicKey(keypairName, sshKeyPair.getPublicKey())).thenReturn(pair); NovaLauncher novaLauncher = new NovaLauncher(novaContext, sshKeyPair); boolean uploadSuccessful = novaLauncher.uploadSshPublicKey(keypairName, nova, true); assertTrue(uploadSuccessful); } @Test public void uploadSSHPublicKeyAndNotRecreateOldFail() throws KaramelException { String keypairName = "pepeKeyPair"; KeyPair pair = mock(KeyPair.class); List<KeyPair> keyPairList = new ArrayList<>(); keyPairList.add(pair); FluentIterable<KeyPair> keys = FluentIterable.from(keyPairList); when(keyPairApi.list()).thenReturn(keys); when(keyPairApi.delete(keypairName)).thenReturn(true); when(keyPairApi.createWithPublicKey(keypairName, sshKeyPair.getPublicKey())).thenReturn(pair); NovaLauncher novaLauncher = new NovaLauncher(novaContext, sshKeyPair); boolean uploadSuccessful = novaLauncher.uploadSshPublicKey(keypairName, nova, false); assertFalse(uploadSuccessful); } @Test public void cleanupFailedNodesEmpty() throws KaramelException { Map<NodeMetadata, Throwable> failedNodes = new HashMap<>(); NovaLauncher novaLauncher = new NovaLauncher(novaContext, sshKeyPair); boolean cleanupSuccessful = novaLauncher.cleanupFailedNodes(failedNodes); assertTrue(cleanupSuccessful); } @Test public void cleanupFailedNodesNotEmpty() throws KaramelException { Map<NodeMetadata, Throwable> failedNodes = new HashMap<>(); Throwable exception = mock(Throwable.class); NodeMetadata meta = mock(NodeMetadata.class); failedNodes.put(meta, exception); Set<NodeMetadata> destroyedNodes = new HashSet<>(); destroyedNodes.add(meta); when(meta.getId()).thenReturn("20"); doReturn(destroyedNodes).when(novaComputeService).destroyNodesMatching(Predicates.in(failedNodes.keySet())); NovaLauncher novaLauncher = new NovaLauncher(novaContext, sshKeyPair); boolean cleanupSuccessful = novaLauncher.cleanupFailedNodes(failedNodes); assertTrue(cleanupSuccessful); } @Test public void cleanupFailedNodesSomethingWentWrong() throws KaramelException { Map<NodeMetadata, Throwable> failedNodes = new HashMap<>(); Throwable exception = mock(Throwable.class); NodeMetadata meta = mock(NodeMetadata.class); failedNodes.put(meta, exception); Set<NodeMetadata> destroyedNodes = new HashSet<>(); when(meta.getId()).thenReturn("20"); doReturn(destroyedNodes).when(novaComputeService).destroyNodesMatching(Predicates.in(failedNodes.keySet())); NovaLauncher novaLauncher = new NovaLauncher(novaContext, sshKeyPair); boolean cleanupSuccessful = novaLauncher.cleanupFailedNodes(failedNodes); assertFalse(cleanupSuccessful); } @Test public void testForkGroup() throws KaramelException{ //Same test parameters as the securityGroup Test //Initializing and mocking need for method test SecurityGroupRule rule = mock(SecurityGroupRule.class); String uniqueGroup = NovaSetting.NOVA_UNIQUE_GROUP_NAME(clusterName, groupName); String uniqueDescription = NovaSetting.NOVA_UNIQUE_GROUP_DESCRIPTION(clusterName, groupName); Ingress ingress = Ingress.builder() .fromPort(0) .toPort(65535) .ipProtocol(IpProtocol.TCP) .build(); when(novaContext.getSecurityGroupApi()).thenReturn(securityGroupApi); when(securityGroupApi.createWithDescription(uniqueGroup, uniqueDescription)).thenReturn(securityGroupCreated); when(securityGroupCreated.getId()).thenReturn("10"); when(securityGroupApi.createRuleAllowingCidrBlock("10", ingress, "0.0.0.0/0")).thenReturn(rule); NovaLauncher novaLauncher = new NovaLauncher(novaContext, sshKeyPair); //String groupId = novaLauncher.createSecurityGroup(clusterName, groupName, nova, ports); JsonCluster cluster = mock(JsonCluster.class); ClusterRuntime clusterRuntime = mock(ClusterRuntime.class); List<JsonGroup> groups = new ArrayList<>(); JsonGroup group = mock(JsonGroup.class); groups.add(group); when(group.getName()).thenReturn(groupName); when(cluster.getGroups()).thenReturn(groups); when(group.getProvider()).thenReturn(nova); when(cluster.getProvider()).thenReturn(nova); when(cluster.getName()).thenReturn(clusterName); String groupId = novaLauncher.forkGroup(cluster,clusterRuntime,groupName); assertEquals("10", groupId); } @Ignore @Test public void testForkMachines() throws KaramelException, RunNodesException { NovaLauncher novaLauncher = new NovaLauncher(novaContext, sshKeyPair); //mocking uploadSSHPublicKey String keypairName = "pepeKeyPair"; KeyPair pair = mock(KeyPair.class); List<KeyPair> keyPairList = new ArrayList<>(); keyPairList.add(pair); FluentIterable<KeyPair> keys = FluentIterable.from(keyPairList); when(keyPairApi.list()).thenReturn(keys); when(keyPairApi.delete(keypairName)).thenReturn(true); when(keyPairApi.createWithPublicKey(keypairName, sshKeyPair.getPublicKey())).thenReturn(pair); //mocking JsonCluster cluster = mock(JsonCluster.class); ClusterRuntime clusterRuntime = mock(ClusterRuntime.class); when(clusterRuntime.getName()).thenReturn(clusterName); List<JsonGroup> groups = new ArrayList<>(); //mocking json group JsonGroup group = mock(JsonGroup.class); groups.add(group); when(group.getName()).thenReturn(groupName); when(group.getProvider()).thenReturn(nova); when(group.getSize()).thenReturn(1); //mocking json cluster when(cluster.getGroups()).thenReturn(groups); when(cluster.getProvider()).thenReturn(nova); when(cluster.getName()).thenReturn(clusterName); //mocking group runtime List<GroupRuntime> groupRuntimes = new ArrayList<>(); GroupRuntime groupRuntime = mock(GroupRuntime.class); when(groupRuntime.getName()).thenReturn(groupName); when(groupRuntime.getId()).thenReturn("10"); when(groupRuntime.getCluster()).thenReturn(clusterRuntime); groupRuntimes.add(groupRuntime); //mocking clusterRuntime when(clusterRuntime.getGroups()).thenReturn(groupRuntimes); //mocking templateOptions NovaTemplateOptions novaTemplateOptions = mock(NovaTemplateOptions.class); TemplateBuilder templateBuilder = mock(TemplateBuilder.class); TemplateOptions templateOptions = mock(TemplateOptions.class); when(novaContext.getComputeService()).thenReturn(novaComputeService); when(novaComputeService.templateOptions()).thenReturn(novaTemplateOptions); when(novaTemplateOptions.securityGroups(Matchers.anyCollection())).thenReturn(novaTemplateOptions); when(templateOptions.as(NovaTemplateOptions.class)).thenReturn(novaTemplateOptions); when(novaComputeService.templateBuilder()).thenReturn(templateBuilder); //mock builder when(novaTemplateOptions.keyPairName(keypairName)).thenReturn(novaTemplateOptions); when(novaTemplateOptions.autoAssignFloatingIp(true)).thenReturn(novaTemplateOptions); when(novaTemplateOptions.nodeNames(Matchers.anyCollection())).thenReturn(novaTemplateOptions); //mock success nodes Set<NodeMetadata> succeededNodes = new HashSet<>(); NodeMetadata succeededNode = mock(NodeMetadata.class); succeededNodes.add(succeededNode); doReturn(succeededNodes).when(novaComputeService) .createNodesInGroup(Matchers.anyString(), eq(1), Matchers.any(Template.class)); LoginCredentials loginCredentials = mock(LoginCredentials.class); Set<String> ipAddresses = new HashSet<>(); ipAddresses.add("127.0.0.1"); when(succeededNode.getPublicAddresses()).thenReturn(ipAddresses); when(succeededNode.getPrivateAddresses()).thenReturn(ipAddresses); when(succeededNode.getLoginPort()).thenReturn(22); when(succeededNode.getCredentials()).thenReturn(loginCredentials); when(loginCredentials.getUser()).thenReturn("ubuntu"); //testing method List<MachineRuntime> forkedMachines =novaLauncher.forkMachines(cluster,clusterRuntime,groupName); assertNotNull(forkedMachines); assertFalse(forkedMachines.isEmpty()); } @Test public void cleanup() throws KaramelException{ String uniqueGroup = NovaSetting.NOVA_UNIQUE_GROUP_NAME(clusterName, groupName); //mocking JsonCluster cluster = mock(JsonCluster.class); ClusterRuntime clusterRuntime = mock(ClusterRuntime.class); when(clusterRuntime.getName()).thenReturn(clusterName); List<JsonGroup> groups = new ArrayList<>(); JsonGroup group = mock(JsonGroup.class); groups.add(group); when(cluster.getGroups()).thenReturn(groups); when(cluster.getProvider()).thenReturn(nova); when(cluster.getName()).thenReturn(clusterName); //mocking json group when(group.getName()).thenReturn(groupName); when(group.getProvider()).thenReturn(nova); when(group.getSize()).thenReturn(1); //mocking group runtime List<GroupRuntime> groupRuntimes = new ArrayList<>(); GroupRuntime groupRuntime = mock(GroupRuntime.class); when(groupRuntime.getName()).thenReturn(groupName); when(groupRuntime.getId()).thenReturn("10"); when(groupRuntime.getCluster()).thenReturn(clusterRuntime); groupRuntimes.add(groupRuntime); //mocking clusterRuntime when(clusterRuntime.getGroups()).thenReturn(groupRuntimes); //mocking securityGroups SecurityGroup securityGroup = mock(SecurityGroup.class); List<SecurityGroup> securityGroupList = new ArrayList<>(); securityGroupList.add(securityGroup); FluentIterable<SecurityGroup> securityGroupFluentIterable = FluentIterable.from(securityGroupList); when(novaContext.getSecurityGroupApi()).thenReturn(securityGroupApi); when(securityGroupApi.list()).thenReturn(securityGroupFluentIterable); when(securityGroup.getName()).thenReturn(uniqueGroup); NovaLauncher novaLauncher = new NovaLauncher(novaContext, sshKeyPair); novaLauncher.cleanup(cluster, clusterRuntime); } }