diff --git a/build.gradle b/build.gradle index 257ed71..2cd6148 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ buildscript { } plugins { id 'net.researchgate.release' version '2.1.2' - id "nebula.os-package" version "2.2.6" + id "nebula.ospackage" version "4.5.1" id 'com.github.sherter.google-java-format' version '0.5' } @@ -64,7 +64,7 @@ project.ext { * gradle Related Vars */ mainClass = 'org.openbaton.drivers.amazon.AmazonDriver' - obVersion = '5.0.0-RC3-SNAPSHOT' + obVersion = '5.1.3-SNAPSHOT' //------------------------------------------------// } @@ -87,10 +87,12 @@ dependencies { compile group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.11.218' - compile 'org.slf4j:slf4j-api:1.7.12' - compile 'org.slf4j:slf4j-simple:1.7.12' + compile 'org.slf4j:slf4j-api:1.7.25' + compile 'org.slf4j:slf4j-simple:1.7.25' testCompile("junit:junit:4.12") + + } apply from: 'gradle/gradle/packaging.plugin-vimdriver-amazon.debian.gradle' diff --git a/src/main/java/org/openbaton/drivers/amazon/AmazonDriver.java b/src/main/java/org/openbaton/drivers/amazon/AmazonDriver.java index 54b62a1..6cb6988 100644 --- a/src/main/java/org/openbaton/drivers/amazon/AmazonDriver.java +++ b/src/main/java/org/openbaton/drivers/amazon/AmazonDriver.java @@ -16,6 +16,7 @@ package org.openbaton.drivers.amazon; +import com.amazonaws.AmazonClientException; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.regions.Regions; @@ -30,6 +31,7 @@ import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -37,6 +39,12 @@ import org.openbaton.catalogue.mano.common.DeploymentFlavour; import org.openbaton.catalogue.mano.descriptor.VNFDConnectionPoint; import org.openbaton.catalogue.nfvo.*; +import org.openbaton.catalogue.nfvo.images.AWSImage; +import org.openbaton.catalogue.nfvo.images.BaseNfvImage; +import org.openbaton.catalogue.nfvo.networks.AWSNetwork; +import org.openbaton.catalogue.nfvo.networks.BaseNetwork; +import org.openbaton.catalogue.nfvo.viminstances.AmazonVimInstance; +import org.openbaton.catalogue.nfvo.viminstances.BaseVimInstance; import org.openbaton.catalogue.security.Key; import org.openbaton.exceptions.VimDriverException; import org.openbaton.exceptions.VimException; @@ -104,13 +112,13 @@ private String changeHostname(String userdata, String hostname) { * @return amazonEc2 client ready to handle requests * @throws VimDriverException if one of the arguments is not correctly set */ - private AmazonEC2 createClient(VimInstance vimInstance) throws VimDriverException { + private AmazonEC2 createClient(AmazonVimInstance vimInstance) throws VimDriverException { BasicAWSCredentials awsCreds = - new BasicAWSCredentials(vimInstance.getUsername(), vimInstance.getPassword()); + new BasicAWSCredentials(vimInstance.getAccessKey(), vimInstance.getSecretKey()); Regions regions; AmazonEC2 client; try { - regions = Regions.fromName(vimInstance.getLocation().getName()); + regions = Regions.fromName(vimInstance.getRegion()); client = AmazonEC2ClientBuilder.standard() .withRegion(regions) @@ -125,7 +133,7 @@ private AmazonEC2 createClient(VimInstance vimInstance) throws VimDriverExceptio @java.lang.Override public Server launchInstance( - VimInstance vimInstance, + BaseVimInstance vimInstanceBase, String name, String image, String flavor, @@ -138,33 +146,37 @@ public Server launchInstance( log.info("Launching instance " + name); Server server = null; try { + AmazonVimInstance vimInstance = (AmazonVimInstance) vimInstanceBase; String changeUserData = changeHostname(userData, name); - log.info(changeUserData); AmazonEC2 client = createClient(vimInstance); Gson gson = new Gson(); String oldVNFDCP = gson.toJson(networks); Set newNetworks = gson.fromJson(oldVNFDCP, new TypeToken>() {}.getType()); RunInstancesRequest runInstancesRequest = new RunInstancesRequest(); - String vpcId = getVpcsMap(vimInstance).get(vimInstance.getTenant()); + String vpcId = getVpcsMap(vimInstance).get(vimInstance.getVpcName()); if (vpcId == null) { - throw new VimDriverException("No such VPC " + vimInstance.getTenant() + " exists"); + throw new VimDriverException("No such VPC " + vimInstance.getVpcName() + " exists"); } log.info("Found the VPC ID: " + vpcId); byte[] encodedData = Base64.encodeBase64(changeUserData.getBytes()); - DescribeVpcsRequest describeVpcsRequest = new DescribeVpcsRequest(); - DescribeVpcsResult describeVpcsResult = client.describeVpcs(describeVpcsRequest); List flavours = listFlavors(vimInstance); log.info("Listed flavours"); - List presentSubnets = listNetworks(vimInstance); + List presentSubnets = listNetworks(vimInstance); log.info("Listed subents"); Collection inters = new ArrayList<>(); Set groupIds = getSecurityIdFromName(secGroup, client, vimInstance); log.info("Retrieved security ids"); int deviceIndex = 0; - for (Network net : searchForRelevantSubnets(presentSubnets, newNetworks)) { - inters.add(createInterface(net, deviceIndex, newNetworks)); - deviceIndex++; + List relevantSubnets = searchForRelevantSubnets(presentSubnets, newNetworks); + if (relevantSubnets.size() < 2) { + inters.add(createInterfaceWithPublicIp(relevantSubnets.get(0), 0, groupIds)); + } else { + for (BaseNetwork net : relevantSubnets) { + inters.add(createInterface(net, deviceIndex, groupIds)); + deviceIndex++; + log.info("Interface " + deviceIndex); + } } log.info("Created interfaces"); String amiID = imageExistsOnAWS(image, client); @@ -202,29 +214,174 @@ public Server launchInstance( tags.add(tag); CreateTagsRequest tagsRequest = new CreateTagsRequest().withTags(tags).withResources(id); client.createTags(tagsRequest); - ModifyInstanceAttributeRequest groupsReq = - new ModifyInstanceAttributeRequest().withGroups(groupIds).withInstanceId(id); - log.info("Assigning security groups to instance " + id); - ModifyInstanceAttributeResult groupRes = client.modifyInstanceAttribute(groupsReq); + log.info("Instance is up, handling networking"); + if (networks.size() > 1) { + server = waitForInstance(name, vimInstance); + setupInstanceNetwork(client, server); + } List servers = listServer(vimInstance); for (Server ser : servers) { - if (ser.getHostName().equals(name)) { + if (ser != null && ser.getHostName().equals(name)) { server = ser; } } - } catch (VimException e) { log.error(e.getMessage(), e); - VimDriverException vimDriverException = new VimDriverException(e.getMessage()); - throw vimDriverException; + throw new VimDriverException(e.getMessage()); } catch (UnsupportedEncodingException e) { - VimDriverException vimDriverException = new VimDriverException(e.getMessage()); - throw vimDriverException; + throw new VimDriverException(e.getMessage()); + } catch (AmazonClientException e) { + log.info("Amazon has thrown an exception: " + e.getMessage()); + throw new VimDriverException(e.getMessage()); + } catch (InterruptedException e) { + throw new VimDriverException(e.getMessage()); } log.info("Instance " + name + " launched"); return server; } + @Override + public BaseVimInstance refresh(BaseVimInstance vimInstance) throws VimDriverException { + AmazonVimInstance amazon = (AmazonVimInstance) vimInstance; + List newImages = listImages(vimInstance); + if (amazon.getImages() == null) { + amazon.setImages(new HashSet<>()); + } + amazon.removeAllImages(); + amazon.addAllImages(newImages); + + List newNetworks = listNetworks(vimInstance); + + if (amazon.getNetworks() == null) { + amazon.setNetworks(new HashSet<>()); + } + amazon.removeAllNetworks(); + amazon.addAllNetworks(newNetworks); + amazon.setVpcId(getVpcsMap(amazon).get(amazon.getVpcName())); + + List newFlavors = listFlavors(vimInstance); + if (amazon.getFlavours() == null) { + amazon.setFlavours(new HashSet<>()); + } + amazon.removeAllFlavours(); + amazon.addAllFlavours(newFlavors); + return (BaseVimInstance) amazon; + } + + private Server waitForInstance(String name, BaseVimInstance vimInstance) + throws VimDriverException, InterruptedException { + int timeOut = Integer.parseInt(properties.getProperty("launchTimeout")); + log.info("Waiting for instance. LaunchTimeout is " + timeOut); + int waitTime = 4; + while (waitTime < timeOut) { + List servers = listServer(vimInstance); + for (Server ser : servers) { + if (ser != null && ser.getHostName().equals(name) && ser.getStatus().equals("running")) { + return ser; + } + try { + TimeUnit.SECONDS.sleep(waitTime); + waitTime = waitTime * 2; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + throw new VimDriverException( + "Launch Timeout reached, seems that the instance never went into running status"); + } + + private void setupInstanceNetwork(AmazonEC2 client, Server server) { + List
freeAddresses = getUnallocatedAddresses(client); + List instanceInterfaces = + listInterfaceByAttachment(client, server.getExtId()); + + if (freeAddresses.size() < instanceInterfaces.size()) { + allocateElasticIps(client, instanceInterfaces.size() - freeAddresses.size()); + } + freeAddresses = getUnallocatedAddresses(client); + int i = 0; + for (NetworkInterface inter : instanceInterfaces) { + AssociateAddressRequest addrReq = + new AssociateAddressRequest() + .withNetworkInterfaceId(inter.getNetworkInterfaceId()) + .withAllocationId(freeAddresses.get(i).getAllocationId()) + .withAllowReassociation(false); + client.associateAddress(addrReq); + i++; + } + } + + private void allocateElasticIps(AmazonEC2 client, int number) { + log.info("Allocating " + number + " elastic ips"); + AllocateAddressRequest req = new AllocateAddressRequest(); + for (int i = 0; i < number; i++) { + client.allocateAddress(req); + } + } + + private List
getUnallocatedAddresses(AmazonEC2 client) { + DescribeAddressesRequest addReq = new DescribeAddressesRequest(); + DescribeAddressesResult re = client.describeAddresses(addReq); + List
unAllockAddrs = new ArrayList<>(); + for (Address addr : re.getAddresses()) { + if (addr.getAssociationId() == null) { + unAllockAddrs.add(addr); + } + } + return unAllockAddrs; + } + + /** + * Get the interfaces attached to a certain VM + * @param client amazonec2 client + * @param instanceId id of the vm + * @return list of interfaces + */ + private List listInterfaceByAttachment(AmazonEC2 client, String instanceId) { + Filter filter = new Filter(); + filter.setName("attachment.instance-id"); + filter.setValues(Collections.singletonList(instanceId)); + Filter filter1 = new Filter(); + // filter1.setName("attachment.device-index"); + // filter1.setValues(Collections.singletonList("0")); + // + // DescribeNetworkInterfacesRequest req = new DescribeNetworkInterfacesRequest().withFilters(Arrays.asList(filter, filter1)); + DescribeNetworkInterfacesRequest req = + new DescribeNetworkInterfacesRequest().withFilters(Collections.singletonList(filter)); + DescribeNetworkInterfacesResult res = client.describeNetworkInterfaces(req); + return res.getNetworkInterfaces(); + } + + private List getInternetGatewaysByVPC(AmazonEC2 client, String vpcId) { + Filter filter = new Filter(); + filter.setName("attachment.vpc-id"); + filter.setValues(Collections.singletonList(vpcId)); + DescribeInternetGatewaysRequest request = new DescribeInternetGatewaysRequest(); + request.setFilters(Collections.singletonList(filter)); + DescribeInternetGatewaysResult result = client.describeInternetGateways(request); + return result.getInternetGateways(); + } + + /** + * Creates the internet gateway in a particular vpc + * + * @param client amazon client to make calls to api + * @param vpcId the id of the VPC where gateway should be attached + * @return createdgateway data + */ + private InternetGateway createAndAttachInternetGateway(AmazonEC2 client, String vpcId) { + CreateInternetGatewayRequest request = new CreateInternetGatewayRequest(); + CreateInternetGatewayResult result = client.createInternetGateway(request); + InternetGateway gateway = result.getInternetGateway(); + AttachInternetGatewayRequest attach = + new AttachInternetGatewayRequest() + .withVpcId(vpcId) + .withInternetGatewayId(gateway.getInternetGatewayId()); + client.attachInternetGateway(attach); + return gateway; + } + /** * Checks if the image exists inside AWS and returns its ID * @@ -232,7 +389,7 @@ public Server launchInstance( * @param client AmazonEC2 client to make a request * @return id of the image or null if no image is there */ - private String imageExistsOnAWS(String nameId, AmazonEC2 client) { + private String imageExistsOnAWS(String nameId, AmazonEC2 client) throws AmazonClientException { Filter filter = new Filter(); filter.setName("name"); filter.setValues(Arrays.asList(nameId)); @@ -254,31 +411,61 @@ private String imageExistsOnAWS(String nameId, AmazonEC2 client) { } /** - * Creates an interface for the instance in order to connect to subnet. Cross checks for floating - * ips and enables it if necessary. Currently supports only random floating ips. - * + * Creates an interface for the instance in order to connect to subnet. Does not assign floating ip, + * this method is used in case multiple interfaces are supposed to be created for on instance. Elastic ips + * are then assgined after creation. * @param net subnet inside AWS represented through NFVO network * @param deviceIndex device index for the interface is required by AWS - * @param cps VNFD connection points + * @param secIDs security group ID * @return the list of interfaces */ private InstanceNetworkInterfaceSpecification createInterface( - Network net, int deviceIndex, Set cps) { + BaseNetwork net, int deviceIndex, Set secIDs) { InstanceNetworkInterfaceSpecification interSpec = new InstanceNetworkInterfaceSpecification() .withDeleteOnTermination(true) .withSubnetId(net.getExtId()) + .withGroups(secIDs) .withDeviceIndex(deviceIndex); - String floatingIp = ""; + log.info("Device index" + deviceIndex); + return interSpec; + + /*String floatingIp = ""; for (VNFDConnectionPoint cp : cps) { if (net.getName().equals(cp.getVirtual_link_reference())) { floatingIp = cp.getFloatingIp(); } - } - if (floatingIp != null) { - interSpec.setAssociatePublicIpAddress(true); - } + }*/ + + } + + /** + * Creates an interface for the instance in order to connect to subnet and assigns public ip to it connecting + * the instance to internet. Used only if the instance has no more than one network interface. It is made in order + * to conserve the limited amount of elastic ips on AWS (5 only generally) and not use them if not necessary. + * @param net subnet inside AWS represented through NFVO network + * @param deviceIndex device index for the interface is required by AWS + * @param secIDs security group ID + * @return + */ + private InstanceNetworkInterfaceSpecification createInterfaceWithPublicIp( + BaseNetwork net, int deviceIndex, Set secIDs) { + InstanceNetworkInterfaceSpecification interSpec = + new InstanceNetworkInterfaceSpecification() + .withDeleteOnTermination(true) + .withSubnetId(net.getExtId()) + .withGroups(secIDs) + .withDeviceIndex(deviceIndex).withAssociatePublicIpAddress(true); + log.info("Device index" + deviceIndex); return interSpec; + + /*String floatingIp = ""; + for (VNFDConnectionPoint cp : cps) { + if (net.getName().equals(cp.getVirtual_link_reference())) { + floatingIp = cp.getFloatingIp(); + } + }*/ + } /** @@ -288,15 +475,33 @@ private InstanceNetworkInterfaceSpecification createInterface( * @param cps All connection points * @return subnets the instance is connected to */ - private List searchForRelevantSubnets(List nets, Set cps) { - List relevantSubnets = new ArrayList<>(); - for (VNFDConnectionPoint cp : cps) { - for (Network net : nets) { + private List searchForRelevantSubnets( + List nets, Set cps) { + ArrayList cpList = new ArrayList<>(cps); + Collections.sort( + cpList, + new Comparator() { + @Override + public int compare(VNFDConnectionPoint t, VNFDConnectionPoint t1) { + if (t.getInterfaceId() > t1.getInterfaceId()) { + return -1; + } + if (t.getInterfaceId() == t1.getInterfaceId()) { + return 0; + } else { + return 1; + } + } + }); + List relevantSubnets = new ArrayList<>(); + for (VNFDConnectionPoint cp : cpList) { + for (BaseNetwork net : nets) { if (net.getName().equals(cp.getVirtual_link_reference())) { - relevantSubnets.add(net); + relevantSubnets.add((AWSNetwork) net); } } } + return relevantSubnets; } @@ -305,16 +510,19 @@ private List searchForRelevantSubnets(List nets, Set getSecurityIdFromName( - Set groupNames, AmazonEC2 client, VimInstance vimInstance) throws VimDriverException { - String vpcId = getVpcsMap(vimInstance).get(vimInstance.getTenant()); + Set groupNames, AmazonEC2 client, BaseVimInstance vimInstanceBase) + throws VimDriverException, AmazonClientException { + AmazonVimInstance vimInstance = (AmazonVimInstance) vimInstanceBase; + String vpcId = getVpcsMap(vimInstance).get(vimInstance.getVpcName()); if (vpcId == null) { - throw new VimDriverException("No such VPC " + vimInstance.getTenant() + " exists"); + throw new VimDriverException( + "No such VPC " + ((AmazonVimInstance) vimInstance).getVpcName() + " exists"); } Filter filter = new Filter(); filter.setName("vpc-id"); @@ -334,7 +542,7 @@ private Set getSecurityIdFromName( groupIds.add(id); } else { throw new VimDriverException( - "No group " + name + "exists on VPC " + vimInstance.getTenant()); + "No group " + name + "exists on VPC " + ((AmazonVimInstance) vimInstance).getVpcName()); } } @@ -342,72 +550,92 @@ private Set getSecurityIdFromName( } @java.lang.Override - public java.util.List listImages(VimInstance vimInstance) throws VimDriverException { - AmazonEC2 client = createClient(vimInstance); - String keyWord = properties.getProperty("image-key-word", "*"); - String keyWords[] = keyWord.split(","); - for (int i = 0; i < keyWords.length; i++) { - keyWords[i] = "*" + keyWords[i] + "*"; - } - Filter filter = new Filter(); - filter.setName("name"); - filter.setValues(Arrays.asList(keyWords)); - DescribeImagesRequest describeImagesRequest = new DescribeImagesRequest(); - describeImagesRequest.setFilters(Arrays.asList(filter)); - DescribeImagesResult describeImagesResult = client.describeImages(describeImagesRequest); - List images = new ArrayList<>(); - for (Image image : describeImagesResult.getImages()) { - images.add(Utils.getImage(image)); - } - filter.setName("image-id"); - filter.setValues(Arrays.asList(keyWords)); - describeImagesRequest = new DescribeImagesRequest(); - describeImagesRequest.setFilters(Arrays.asList(filter)); - describeImagesResult = client.describeImages(describeImagesRequest); - for (Image image : describeImagesResult.getImages()) { - images.add(Utils.getImage(image)); - } + public java.util.List listImages(BaseVimInstance vimInstance) + throws VimDriverException { + try { + AmazonEC2 client = createClient((AmazonVimInstance) vimInstance); + String keyWord = properties.getProperty("image-key-word", "*"); + String keyWords[] = keyWord.split(","); + for (int i = 0; i < keyWords.length; i++) { + keyWords[i] = "*" + keyWords[i] + "*"; + } + Filter filter = new Filter(); + filter.setName("name"); + filter.setValues(Arrays.asList(keyWords)); + DescribeImagesRequest describeImagesRequest = new DescribeImagesRequest(); + describeImagesRequest.setFilters(Arrays.asList(filter)); + DescribeImagesResult describeImagesResult = client.describeImages(describeImagesRequest); + List images = new ArrayList<>(); + for (Image image : describeImagesResult.getImages()) { + images.add(Utils.getImage(image)); + } + filter.setName("image-id"); + filter.setValues(Arrays.asList(keyWords)); + describeImagesRequest = new DescribeImagesRequest(); + describeImagesRequest.setFilters(Arrays.asList(filter)); + describeImagesResult = client.describeImages(describeImagesRequest); + for (Image image : describeImagesResult.getImages()) { + images.add(Utils.getImage(image)); + } - return images; + return images; + } catch (AmazonClientException e) { + VimDriverException vimDriverException = new VimDriverException(e.getMessage()); + throw vimDriverException; + } } @java.lang.Override - public java.util.List listServer(VimInstance vimInstance) throws VimDriverException { - List servers = new ArrayList<>(); - AmazonEC2 client = createClient(vimInstance); - String vpcId = getVpcsMap(vimInstance).get(vimInstance.getTenant()); - if (vpcId == null) { - throw new VimDriverException("No such VPC " + vimInstance.getTenant() + " exists"); - } - Filter filter = new Filter(); - filter.setName("vpc-id"); - filter.setValues(Arrays.asList(vpcId)); - boolean done = false; - List nets = listNetworks(vimInstance); - while (!done) { - DescribeInstancesRequest request = new DescribeInstancesRequest(); - request.setFilters(Arrays.asList(filter)); - DescribeInstancesResult response = client.describeInstances(request); - for (Reservation reservation : response.getReservations()) { - for (Instance instance : reservation.getInstances()) { - servers.add(Utils.getServer(instance, nets)); - } + public java.util.List listServer(BaseVimInstance vimInstanceBase) + throws VimDriverException { + AmazonVimInstance vimInstance = (AmazonVimInstance) vimInstanceBase; + try { + List servers = new ArrayList<>(); + AmazonEC2 client = createClient(vimInstance); + String vpcId = getVpcsMap(vimInstance).get(vimInstance.getVpcName()); + if (vpcId == null) { + throw new VimDriverException("No such VPC " + vimInstance.getVpcName() + " exists"); } - request.setNextToken(response.getNextToken()); - if (response.getNextToken() == null) { - done = true; + Filter filter = new Filter(); + filter.setName("vpc-id"); + filter.setValues(Arrays.asList(vpcId)); + boolean done = false; + List nets = listNetworks(vimInstance); + while (!done) { + DescribeInstancesRequest request = new DescribeInstancesRequest(); + request.setFilters(Arrays.asList(filter)); + DescribeInstancesResult response = client.describeInstances(request); + for (Reservation reservation : response.getReservations()) { + for (Instance instance : reservation.getInstances()) { + servers.add(Utils.getServer(instance, nets)); + } + } + request.setNextToken(response.getNextToken()); + if (response.getNextToken() == null) { + done = true; + } } + return servers; + } catch (AmazonClientException e) { + VimDriverException vimDriverException = new VimDriverException(e.getMessage()); + throw vimDriverException; } - return servers; + } + + @Override + public Server rebuildServer(BaseVimInstance vimInstance, String serverId, String imageId) throws VimDriverException { + return null; } @java.lang.Override - public java.util.List listNetworks(VimInstance vimInstance) throws VimDriverException { - List nfvoNetworks = new ArrayList<>(); + public List listNetworks(BaseVimInstance vimInstanceBase) throws VimDriverException { + log.info("Listing networks"); + AmazonVimInstance vimInstance = (AmazonVimInstance) vimInstanceBase; + List nfvoNetworks = new ArrayList<>(); AmazonEC2 client = createClient(vimInstance); - String vpcId = getVpcsMap(vimInstance).get(vimInstance.getTenant()); + String vpcId = getVpcsMap(vimInstance).get(vimInstance.getVpcName()); if (vpcId == null) { - throw new VimDriverException("No such VPC " + vimInstance.getTenant() + " exists"); + throw new VimDriverException("No such VPC " + vimInstance.getVpcName() + " exists"); } Filter filter = new Filter(); filter.setName("vpc-id"); @@ -417,15 +645,14 @@ public java.util.List listNetworks(VimInstance vimInstance) throws VimD DescribeSubnetsResult subnetsResult = client.describeSubnets(describeSubnetsRequest); List subnets = subnetsResult.getSubnets(); for (Subnet subnet : subnets) { - nfvoNetworks.add(Utils.getNetworkFromSubnet(subnet)); + nfvoNetworks.add((BaseNetwork) Utils.getNetworkFromSubnet(subnet)); } return nfvoNetworks; } @java.lang.Override - public java.util.List listFlavors(VimInstance vimInstance) + public java.util.List listFlavors(BaseVimInstance vimInstanceBase) throws VimDriverException { - AmazonEC2 client = createClient(vimInstance); List flavours = new ArrayList<>(); for (InstanceType type : InstanceType.values()) { DeploymentFlavour flavour = new DeploymentFlavour(); @@ -438,7 +665,7 @@ public java.util.List listFlavors(VimInstance vimInstance) @java.lang.Override public Server launchInstanceAndWait( - VimInstance vimInstance, + BaseVimInstance vimInstance, String hostname, String image, String flavorExtId, @@ -449,7 +676,6 @@ public Server launchInstanceAndWait( java.util.Map floatingIps, java.util.Set keys) throws VimDriverException { - AmazonEC2 client = createClient(vimInstance); Server server = launchInstance( @@ -460,7 +686,7 @@ public Server launchInstanceAndWait( @Override public Server launchInstanceAndWait( - VimInstance vimInstance, + BaseVimInstance vimInstance, String hostname, String image, String extId, @@ -483,30 +709,30 @@ public Server launchInstanceAndWait( } @java.lang.Override - public void deleteServerByIdAndWait(VimInstance vimInstance, String id) + public void deleteServerByIdAndWait(BaseVimInstance vimInstance, String id) throws VimDriverException { - AmazonEC2 client = createClient(vimInstance); - TerminateInstancesRequest req = new TerminateInstancesRequest().withInstanceIds(id); - TerminateInstancesResult res = client.terminateInstances(req); + try { + AmazonEC2 client = createClient((AmazonVimInstance) vimInstance); + TerminateInstancesRequest req = new TerminateInstancesRequest().withInstanceIds(id); + TerminateInstancesResult res = client.terminateInstances(req); + } catch (AmazonClientException e) { + VimDriverException vimDriverException = new VimDriverException(e.getMessage()); + throw vimDriverException; + } } @java.lang.Override - public Network createNetwork(VimInstance vimInstance, Network network) throws VimDriverException { + public BaseNetwork createNetwork(BaseVimInstance vimInstanceBase, BaseNetwork network) + throws VimDriverException { + AmazonVimInstance vimInstance = (AmazonVimInstance) vimInstanceBase; AmazonEC2 client = createClient(vimInstance); - - String vpcId = getVpcsMap(vimInstance).get(vimInstance.getTenant()); - if (vpcId == null) { - throw new VimDriverException("No such VPC " + vimInstance.getTenant() + " exists"); - } - CreateSubnetResult res; try { - CreateSubnetRequest req = - new CreateSubnetRequest() - .withVpcId(vpcId) - .withCidrBlock(network.getSubnets().iterator().next().getCidr()); - res = client.createSubnet(req); - } catch (Exception e) { - log.debug("Provided CIDR is invalid, generating different one"); + String vpcId = getVpcsMap(vimInstance).get(vimInstance.getVpcName()); + if (vpcId == null) { + throw new VimDriverException("No such VPC " + vimInstance.getVpcName() + " exists"); + } + CreateSubnetResult res; + log.debug("Generating CIDR"); DescribeVpcsRequest req = new DescribeVpcsRequest(); DescribeVpcsResult resVpc = client.describeVpcs(req); Vpc vpc = null; @@ -528,56 +754,73 @@ public Network createNetwork(VimInstance vimInstance, Network network) throws Vi CreateSubnetRequest newReq = new CreateSubnetRequest().withVpcId(vpcId).withCidrBlock(subnetCidr); res = client.createSubnet(newReq); - } - String id = res.getSubnet().getSubnetId(); - List tags = new ArrayList<>(); - Tag tag = new Tag(); - tag.setKey("Name"); - tag.setValue(network.getName()); - tags.add(tag); - CreateTagsRequest tagsRequest = new CreateTagsRequest().withTags(tags).withResources(id); - client.createTags(tagsRequest); - List nets = listNetworks(vimInstance); - Network returnNetwork = null; - for (Network net : nets) { - if (net.getExtId().equals(res.getSubnet().getSubnetId())) { - returnNetwork = net; + String id = res.getSubnet().getSubnetId(); + List tags = new ArrayList<>(); + Tag tag = new Tag(); + tag.setKey("Name"); + tag.setValue(network.getName()); + tags.add(tag); + CreateTagsRequest tagsRequest = new CreateTagsRequest().withTags(tags).withResources(id); + client.createTags(tagsRequest); + List nets = listNetworks(vimInstanceBase); + BaseNetwork returnNetwork = null; + for (BaseNetwork net : nets) { + if (net.getExtId().equals(res.getSubnet().getSubnetId())) { + returnNetwork = net; + } } - } - return returnNetwork; + return returnNetwork; + } catch (AmazonClientException e) { + VimDriverException vimDriverException = new VimDriverException(e.getMessage()); + throw vimDriverException; + } } - private HashMap getVpcsMap(VimInstance vimInstance) throws VimDriverException { + /** + * Get the table of VPCs name to id by name + * @param vimInstance + * @return + * @throws VimDriverException + */ + private HashMap getVpcsMap(AmazonVimInstance vimInstance) + throws VimDriverException { AmazonEC2 client = createClient(vimInstance); - DescribeVpcsRequest describeVpcsRequest = new DescribeVpcsRequest(); - DescribeVpcsResult describeVpcsResult = client.describeVpcs(describeVpcsRequest); - HashMap vpcNameId = new HashMap<>(); - for (Vpc vpc : describeVpcsResult.getVpcs()) { - String id = vpc.getVpcId(); - String name = ""; - for (Tag tag : vpc.getTags()) { - if (tag.getKey().equals("Name")) { - name = tag.getValue(); + try { + DescribeVpcsRequest describeVpcsRequest = new DescribeVpcsRequest(); + DescribeVpcsResult describeVpcsResult = client.describeVpcs(describeVpcsRequest); + HashMap vpcNameId = new HashMap<>(); + for (Vpc vpc : describeVpcsResult.getVpcs()) { + String id = vpc.getVpcId(); + String name = ""; + for (Tag tag : vpc.getTags()) { + if (tag.getKey().equals("Name")) { + name = tag.getValue(); + } } + vpcNameId.put(name, id); } - vpcNameId.put(name, id); + return vpcNameId; + } catch (AmazonClientException e) { + VimDriverException vimDriverException = new VimDriverException(e.getMessage()); + throw vimDriverException; } - return vpcNameId; } @java.lang.Override - public DeploymentFlavour addFlavor(VimInstance vimInstance, DeploymentFlavour deploymentFlavour) - throws VimDriverException { - AmazonEC2 client = createClient(vimInstance); + public DeploymentFlavour addFlavor( + BaseVimInstance vimInstance, DeploymentFlavour deploymentFlavour) throws VimDriverException { return null; } @java.lang.Override - public NFVImage addImage(VimInstance vimInstance, NFVImage image, byte[] imageFile) + public BaseNfvImage addImage( + BaseVimInstance vimInstanceBase, BaseNfvImage imageBase, byte[] imageFile) throws VimDriverException { + AmazonVimInstance vimInstance = (AmazonVimInstance) vimInstanceBase; + AWSImage image = (AWSImage) imageBase; AmazonEC2 client = createClient(vimInstance); - NFVImage newImage; + AWSImage newImage; Filter filter = new Filter(); filter.setName("image-id"); filter.setValues(Arrays.asList(image.getName())); @@ -608,63 +851,48 @@ public NFVImage addImage(VimInstance vimInstance, NFVImage image, byte[] imageFi } @java.lang.Override - public NFVImage addImage(VimInstance vimInstance, NFVImage image, String image_url) + public BaseNfvImage addImage(BaseVimInstance vimInstance, BaseNfvImage image, String image_url) throws VimDriverException { return addImage(vimInstance, image, "".getBytes()); } @java.lang.Override - public NFVImage updateImage(VimInstance vimInstance, NFVImage image) throws VimDriverException { + public BaseNfvImage updateImage(BaseVimInstance vimInstance, BaseNfvImage image) + throws VimDriverException { return addImage(vimInstance, image, "".getBytes()); } @java.lang.Override - public NFVImage copyImage(VimInstance vimInstance, NFVImage image, byte[] imageFile) + public BaseNfvImage copyImage(BaseVimInstance vimInstance, BaseNfvImage image, byte[] imageFile) throws VimDriverException { - AmazonEC2 client = createClient(vimInstance); return null; } @java.lang.Override - public boolean deleteImage(VimInstance vimInstance, NFVImage image) throws VimDriverException { - AmazonEC2 client = createClient(vimInstance); + public boolean deleteImage(BaseVimInstance vimInstance, BaseNfvImage image) + throws VimDriverException { return false; } @java.lang.Override public DeploymentFlavour updateFlavor( - VimInstance vimInstance, DeploymentFlavour deploymentFlavour) throws VimDriverException { - AmazonEC2 client = createClient(vimInstance); + BaseVimInstance vimInstance, DeploymentFlavour deploymentFlavour) throws VimDriverException { + return null; } @java.lang.Override - public boolean deleteFlavor(VimInstance vimInstance, String extId) throws VimDriverException { - AmazonEC2 client = createClient(vimInstance); + public boolean deleteFlavor(BaseVimInstance vimInstance, String extId) throws VimDriverException { return false; } - /** - * This - * - * @param vimInstance - * @param createdNetwork - * @param subnet - * @return - * @throws VimDriverException - */ - @java.lang.Override - public org.openbaton.catalogue.nfvo.Subnet createSubnet( - VimInstance vimInstance, Network createdNetwork, org.openbaton.catalogue.nfvo.Subnet subnet) + @Override + public org.openbaton.catalogue.nfvo.networks.Subnet createSubnet( + BaseVimInstance vimInstance, + BaseNetwork createdNetwork, + org.openbaton.catalogue.nfvo.networks.Subnet subnet) throws VimDriverException { - log.info("Creating subnet " + subnet.getName() + " on by return the subnet:"); - log.info(createdNetwork.toString()); - org.openbaton.catalogue.nfvo.Subnet sub = new org.openbaton.catalogue.nfvo.Subnet(); - sub.setName(createdNetwork.getName() + "_subnet"); - sub.setExtId(createdNetwork.getExtId()); - sub.setCidr(createdNetwork.getSubnets().iterator().next().getCidr()); - sub.setNetworkId(createdNetwork.getExtId()); - return sub; + return null; } /** @@ -675,77 +903,81 @@ public org.openbaton.catalogue.nfvo.Subnet createSubnet( * @return same network */ @java.lang.Override - public Network updateNetwork(VimInstance vimInstance, Network network) { + public BaseNetwork updateNetwork(BaseVimInstance vimInstance, BaseNetwork network) { log.info("Called the update network method which is not implemented"); return network; } - /** - * This is a stub that simply return the same network to avoid null pointer exceptions - * - * @param vimInstance vim - * @param subnet network data - * @return same network - */ - @java.lang.Override - public org.openbaton.catalogue.nfvo.Subnet updateSubnet( - VimInstance vimInstance, Network updatedNetwork, org.openbaton.catalogue.nfvo.Subnet subnet) { - log.info("Called the update subnet method which is not implemented"); - return subnet; + @Override + public org.openbaton.catalogue.nfvo.networks.Subnet updateSubnet( + BaseVimInstance vimInstance, + BaseNetwork updatedNetwork, + org.openbaton.catalogue.nfvo.networks.Subnet subnet) + throws VimDriverException { + return null; } - @java.lang.Override - public java.util.List getSubnetsExtIds(VimInstance vimInstance, String network_extId) + @Override + public List getSubnetsExtIds(BaseVimInstance vimInstance, String network_extId) throws VimDriverException { - List nets = listNetworks(vimInstance); - List ids = new ArrayList<>(); - for (Network net : nets) { - ids.add(net.getExtId()); - } - return ids; + return null; } - @java.lang.Override - public boolean deleteSubnet(VimInstance vimInstance, String existingSubnetExtId) + @Override + public boolean deleteSubnet(BaseVimInstance vimInstance, String existingSubnetExtId) throws VimDriverException { - return true; + return false; } @java.lang.Override - public boolean deleteNetwork(VimInstance vimInstance, String extId) throws VimDriverException { - AmazonEC2 client = createClient(vimInstance); - DeleteSubnetRequest req = new DeleteSubnetRequest().withSubnetId(extId); - DeleteSubnetResult res = client.deleteSubnet(req); - return true; + public boolean deleteNetwork(BaseVimInstance vimInstanceBase, String extId) + throws VimDriverException { + try { + AmazonVimInstance vimInstance = (AmazonVimInstance) vimInstanceBase; + AmazonEC2 client = createClient(vimInstance); + DeleteSubnetRequest req = new DeleteSubnetRequest().withSubnetId(extId); + DeleteSubnetResult res = client.deleteSubnet(req); + return true; + } catch (AmazonClientException e) { + VimDriverException vimDriverException = new VimDriverException(e.getMessage()); + throw vimDriverException; + } } @java.lang.Override - public Network getNetworkById(VimInstance vimInstance, String id) throws VimDriverException { + public BaseNetwork getNetworkById(BaseVimInstance vimInstanceBase, String id) + throws VimDriverException { + AmazonVimInstance vimInstance = (AmazonVimInstance) vimInstanceBase; AmazonEC2 client = createClient(vimInstance); - Filter filter = new Filter(); - filter.setName("subnet-id"); - filter.setValues(Arrays.asList(id)); - DescribeSubnetsRequest req = new DescribeSubnetsRequest().withFilters(filter); - DescribeSubnetsResult res = client.describeSubnets(req); - if (res.getSubnets().size() < 1) { - throw new VimDriverException("Network with id " + id + " does not exist"); + try { + Filter filter = new Filter(); + filter.setName("subnet-id"); + filter.setValues(Arrays.asList(id)); + DescribeSubnetsRequest req = new DescribeSubnetsRequest().withFilters(filter); + DescribeSubnetsResult res = client.describeSubnets(req); + if (res.getSubnets().size() < 1) { + throw new VimDriverException("Network with id " + id + " does not exist"); + } + return Utils.getNetworkFromSubnet(res.getSubnets().get(0)); + } catch (AmazonClientException e) { + VimDriverException vimDriverException = new VimDriverException(e.getMessage()); + throw vimDriverException; } - return Utils.getNetworkFromSubnet(res.getSubnets().get(0)); } @java.lang.Override - public Quota getQuota(VimInstance vimInstance) throws VimDriverException { + public Quota getQuota(BaseVimInstance vimInstance) throws VimDriverException { log.info("Returning fake quota"); Quota quota = new Quota(); quota.setCores(99999); quota.setFloatingIps(444); - quota.setInstances(20 - listServer(vimInstance).size()); + quota.setInstances(20); quota.setRam(9999); return quota; } @java.lang.Override - public String getType(VimInstance vimInstance) throws VimDriverException { + public String getType(BaseVimInstance vimInstance) throws VimDriverException { return "amazon"; } } diff --git a/src/main/java/org/openbaton/drivers/amazon/Utils.java b/src/main/java/org/openbaton/drivers/amazon/Utils.java index 632fd0a..8fd0d2e 100644 --- a/src/main/java/org/openbaton/drivers/amazon/Utils.java +++ b/src/main/java/org/openbaton/drivers/amazon/Utils.java @@ -2,22 +2,23 @@ import com.amazonaws.services.ec2.model.*; import java.util.*; -import org.openbaton.catalogue.nfvo.NFVImage; -import org.openbaton.catalogue.nfvo.Network; import org.openbaton.catalogue.nfvo.Server; -import org.openbaton.catalogue.nfvo.Subnet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.openbaton.catalogue.nfvo.images.AWSImage; +import org.openbaton.catalogue.nfvo.images.NFVImage; +import org.openbaton.catalogue.nfvo.networks.AWSNetwork; +import org.openbaton.catalogue.nfvo.networks.BaseNetwork; class Utils { - private static Logger log = LoggerFactory.getLogger(Utils.class); - static org.openbaton.catalogue.nfvo.Server getServer(Instance instance, List nets) { + static org.openbaton.catalogue.nfvo.Server getServer(Instance instance, List nets) { Server server = new Server(); server.setExtId(instance.getInstanceId()); server.setStatus(instance.getState().getName()); server.setHypervisorHostName(instance.getHypervisor()); server.setCreated(instance.getLaunchTime()); + NFVImage image = new NFVImage(); + image.setExtId(instance.getImageId()); + server.setImage(image); if (instance.getTags() != null) { for (Tag tag : instance.getTags()) { if (tag.getKey().equals("Name")) { @@ -28,12 +29,12 @@ static org.openbaton.catalogue.nfvo.Server getServer(Instance instance, List netNameId = new HashMap<>(); - for (Network net : nets) { + for (BaseNetwork net : nets) { netNameId.put(net.getExtId(), net.getName()); } String primarySubnetId = instance.getSubnetId(); String primarySubnetName = ""; - for (Network net : nets) { + for (BaseNetwork net : nets) { if (net.getExtId().equals(primarySubnetId)) { primarySubnetName = net.getName(); } @@ -76,37 +77,42 @@ static org.openbaton.catalogue.nfvo.Server getServer(Instance instance, ListAWS EC2 VPCs do not have internal networks. Subnet is converted to network with one subnet - * in order to map the resource as precisely as possible + * in order to map the resource as precisely as possible Is the subnet has not name tag, which is allowed + * in AWS the id will be assigned to name to ensure consistency * * @param subnet aws subnet * @return created nfvo network */ - static org.openbaton.catalogue.nfvo.Network getNetworkFromSubnet( + static org.openbaton.catalogue.nfvo.networks.AWSNetwork getNetworkFromSubnet( com.amazonaws.services.ec2.model.Subnet subnet) { - Network nfvoNetwork = new Network(); + AWSNetwork nfvoNetwork = new AWSNetwork(); nfvoNetwork.setExtId(subnet.getSubnetId()); for (Tag tag : subnet.getTags()) { if (tag.getKey().equals("Name")) { nfvoNetwork.setName(tag.getValue()); } } - Set subs = new HashSet<>(); - Subnet sub = new Subnet(); - sub.setExtId(subnet.getSubnetId()); - sub.setCidr(subnet.getCidrBlock()); - sub.setNetworkId(subnet.getSubnetId()); - subs.add(sub); - nfvoNetwork.setSubnets(subs); + if (nfvoNetwork.getName() == null || nfvoNetwork.getName().isEmpty() || nfvoNetwork.equals("")) { + nfvoNetwork.setName(subnet.getSubnetId()); + } + nfvoNetwork.setIpv4cidr(subnet.getCidrBlock()); + nfvoNetwork.setAvZone(subnet.getAvailabilityZone()); + nfvoNetwork.setExtId(subnet.getSubnetId()); + nfvoNetwork.setVpcId(subnet.getVpcId()); + nfvoNetwork.setState(subnet.getState()); + nfvoNetwork.setDef(subnet.getDefaultForAz()); return nfvoNetwork; } - static org.openbaton.catalogue.nfvo.NFVImage getImage( + static org.openbaton.catalogue.nfvo.images.AWSImage getImage( com.amazonaws.services.ec2.model.Image image) { - NFVImage nfvoImage = new NFVImage(); + AWSImage nfvoImage = new AWSImage(); nfvoImage.setName(image.getName()); nfvoImage.setExtId(image.getImageId()); - nfvoImage.setDiskFormat(image.getImageType()); - nfvoImage.setStatus("ACTIVE"); + nfvoImage.setHypervisor(image.getHypervisor()); + nfvoImage.setDescription(image.getDescription()); + nfvoImage.setImageOwner(image.getImageOwnerAlias()); + nfvoImage.setPublic(image.getPublic()); return nfvoImage; } } diff --git a/src/main/resources/plugin.conf.properties b/src/main/resources/plugin.conf.properties index f033e83..b0c7010 100644 --- a/src/main/resources/plugin.conf.properties +++ b/src/main/resources/plugin.conf.properties @@ -18,3 +18,4 @@ type = amazon external-properties-file = /etc/openbaton/plugin/amazon/driver.properties image-key-word = ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-20170727,ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-20170721,CentOS Linux 7 x86_64 HVM EBS 1708_01-b7ee8a69-ee97-4a49-9e68-afaee216db2e-ami-0d8f9576.4 +launchTimeout = 128 \ No newline at end of file