Adding floating ip association with instances
Project: http://git-wip-us.apache.org/repos/asf/airavata/repo Commit: http://git-wip-us.apache.org/repos/asf/airavata/commit/8b9f5c89 Tree: http://git-wip-us.apache.org/repos/asf/airavata/tree/8b9f5c89 Diff: http://git-wip-us.apache.org/repos/asf/airavata/diff/8b9f5c89 Branch: refs/heads/master Commit: 8b9f5c89cbff522c8f913532cd7ad8ff5abaf412 Parents: cf575fe Author: Mangirish Wagle <[email protected]> Authored: Sat Apr 16 00:24:34 2016 -0400 Committer: Mangirish Wagle <[email protected]> Committed: Sat Apr 16 00:24:34 2016 -0400 ---------------------------------------------------------------------- modules/cloud/cloud-provisioning/README | 2 +- .../airavata/cloud/intf/CloudInterface.java | 8 +- .../cloud/intf/impl/OpenstackIntfImpl.java | 132 +++++++++++++++++-- .../apache/airavata/cloud/util/Constants.java | 2 + .../org/apache/airavata/cloud/util/IPType.java | 39 ++++++ .../main/resources/jetstream_openrc.properties | 4 + .../airavata/cloud/test/CloudIntfTest.java | 19 ++- .../src/test/resources/test_data.properties | 1 - 8 files changed, 187 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/airavata/blob/8b9f5c89/modules/cloud/cloud-provisioning/README ---------------------------------------------------------------------- diff --git a/modules/cloud/cloud-provisioning/README b/modules/cloud/cloud-provisioning/README index 1b161a0..dc4a7a6 100644 --- a/modules/cloud/cloud-provisioning/README +++ b/modules/cloud/cloud-provisioning/README @@ -3,5 +3,5 @@ Currently supporting, Openstack on Jetstream using Openstack4j. To Test Run:- 1) Replace the credentials in src/main/resources/jetstream_openrc.properties with the Jetstream credentials. -2) Update the publicKeyFile, jetstream_imageId, jetstream_flavorId and jetstream_networkId to the local path in src/test/resources/test_data.properties. This are the parameters used by the unit tests. +2) Update the publicKeyFile, jetstream_imageId, jetstream_flavorId to the local path in src/test/resources/test_data.properties. This are the parameters used by the unit tests. 3) Run JUnit Test org.apache.airavata.cloud.test.CloudIntfTest. http://git-wip-us.apache.org/repos/asf/airavata/blob/8b9f5c89/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/intf/CloudInterface.java ---------------------------------------------------------------------- diff --git a/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/intf/CloudInterface.java b/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/intf/CloudInterface.java index f9d9520..f64e11a 100644 --- a/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/intf/CloudInterface.java +++ b/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/intf/CloudInterface.java @@ -35,7 +35,7 @@ public interface CloudInterface { * @param keyPairName * @return Server object. */ - public Server createServer(String serverName, String imageId, String flavorId, String networkId, String keyPairName); + public Server createServer(String serverName, String imageId, String flavorId, String keyPairName); /** * Returns the Server object pertaining to the serverId. @@ -69,4 +69,10 @@ public interface CloudInterface { * @param publicKey */ public void deleteKeyPair(String keyPairName); + + /** + * Associates a floating ip to the instance indicated by serverId. + * @param serverId + */ + public void addFloatingIP(String serverId); } http://git-wip-us.apache.org/repos/asf/airavata/blob/8b9f5c89/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/intf/impl/OpenstackIntfImpl.java ---------------------------------------------------------------------- diff --git a/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/intf/impl/OpenstackIntfImpl.java b/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/intf/impl/OpenstackIntfImpl.java index cb202c4..a4c4ed6 100644 --- a/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/intf/impl/OpenstackIntfImpl.java +++ b/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/intf/impl/OpenstackIntfImpl.java @@ -29,11 +29,20 @@ import java.util.Properties; import org.apache.airavata.cloud.intf.CloudInterface; import org.apache.airavata.cloud.openstack.OS4JClientProvider; +import org.apache.airavata.cloud.util.Constants; +import org.apache.airavata.cloud.util.IPType; import org.openstack4j.api.Builders; import org.openstack4j.api.OSClient; +import org.openstack4j.model.compute.ActionResponse; +import org.openstack4j.model.compute.Address; +import org.openstack4j.model.compute.FloatingIP; import org.openstack4j.model.compute.Keypair; import org.openstack4j.model.compute.Server; import org.openstack4j.model.compute.ServerCreate; +import org.openstack4j.model.network.Subnet; +import org.openstack4j.openstack.compute.domain.NovaAddresses.NovaAddress; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class OpenstackIntfImpl implements CloudInterface { @@ -41,6 +50,9 @@ public class OpenstackIntfImpl implements CloudInterface { private String propertiesFile; private Properties properties; + // Initializing Logger + private Logger logger = LoggerFactory.getLogger(OpenstackIntfImpl.class); + OSClient os = null; /** @@ -72,30 +84,51 @@ public class OpenstackIntfImpl implements CloudInterface { } @Override - public Server createServer(String serverName, String imageId, String flavorId, String networkId, String keyPairName) { + public Server createServer(String serverName, String imageId, String flavorId, String keyPairName) { try { + Server newServer = null; + String networkId = null; + + // Adhering to openstack format of subnet names 'subnet-<name>'. + String networkName = "subnet-" + properties.getProperty(Constants.OS_SUBNET_NAME); + + for( Subnet net : os.networking().subnet().list() ) { + if(net.getName().equals(networkName)) { + networkId = net.getNetworkId(); + logger.info("Using network " + networkName + " with ID: " + networkId); + break; + } + } + + if(networkId != null) { - List<String> srvNet = new LinkedList<String>(); - srvNet.add(networkId); + List<String> srvNet = new LinkedList<String>(); + srvNet.add(networkId); - ServerCreate sc = Builders.server() - .name(serverName) - .flavor(flavorId) - .image(imageId) - .networks(srvNet) - .keypairName(keyPairName) - .addPersonality("/etc/motd", "Welcome to the new VM! Restricted access only") - .build(); + ServerCreate sc = Builders.server() + .name(serverName) + .flavor(flavorId) + .image(imageId) + .networks(srvNet) + .keypairName(keyPairName) + .build(); - //Boot the Server - Server newServer = os.compute().servers().boot(sc); + //Boot the Server + newServer = os.compute().servers().boot(sc); + logger.info("New server created with ID: " + newServer.getId()); + + } + else { + logger.error("Network with name " + networkName + " not found."); + } return newServer; } catch( Exception ex ) { ex.printStackTrace(); // TODO: Check with the team on how to handle exceptions. + logger.error("Failed to create server."); return null; } } @@ -106,11 +139,14 @@ public class OpenstackIntfImpl implements CloudInterface { Server server = os.compute().servers().get(serverId); + logger.info("Server retrieved successfully for ID: " + serverId); + return server; } catch( Exception ex ) { ex.printStackTrace(); // TODO: Check with the team on how to handle exceptions. + logger.error("Failed to retrieve server for ID: " + serverId); return null; } } @@ -119,11 +155,38 @@ public class OpenstackIntfImpl implements CloudInterface { public void deleteServer(String serverId) { try { - os.compute().servers().delete(serverId); + Server server = this.getServer(serverId); + + // Get Floating IP if there is one associated. + String floatingIpAddr = null; + for(Address novaAddress : server.getAddresses().getAddresses().get(properties.getProperty(Constants.OS_SUBNET_NAME))) { + novaAddress = (NovaAddress) novaAddress; + if(novaAddress.getType().equals(IPType.FLOATING.toString())) { + floatingIpAddr = novaAddress.getAddr(); + break; + } + } + + if(server != null) { + os.compute().servers().delete(serverId); + + // Deallocating Floating IP. + if(floatingIpAddr != null) { + for(FloatingIP floatIp : os.compute().floatingIps().list()) { + if(floatIp.getFloatingIpAddress().equals(floatingIpAddr)) { + os.compute().floatingIps().deallocateIP(floatIp.getId()); + } + } + } + + logger.info("Server deleted successfully for ID: " + serverId); + } + } catch( Exception ex ) { ex.printStackTrace(); // TODO: Check with the team on how to handle exceptions. + logger.error("Failed to delete server with ID: " + serverId); } } @@ -133,11 +196,14 @@ public class OpenstackIntfImpl implements CloudInterface { Keypair keyp = os.compute().keypairs().create(keyPairName, publicKey); + logger.info("Keypair created successfully: " + keyp.getName()); + return keyp; } catch( Exception ex ) { ex.printStackTrace(); // TODO: Check with the team on how to handle exceptions. + logger.error("Failed to create keypair: " + keyPairName); return null; } } @@ -148,11 +214,16 @@ public class OpenstackIntfImpl implements CloudInterface { Keypair keyp = os.compute().keypairs().get(keyPairName); + if(keyp != null){ + logger.info("Keypair retrieved successfully: " + keyp.getName()); + } + return keyp; } catch( Exception ex ) { ex.printStackTrace(); // TODO: Check with the team on how to handle exceptions. + logger.error("Failed to retrieve keypair: " + keyPairName); return null; } } @@ -162,11 +233,44 @@ public class OpenstackIntfImpl implements CloudInterface { try { os.compute().keypairs().delete(keyPairName); + + logger.info("Keypair deleted successfully: " + keyPairName); } catch( Exception ex ) { ex.printStackTrace(); // TODO: Check with the team on how to handle exceptions. + logger.error("Failed to delete keypair: " + keyPairName); } } + @Override + public void addFloatingIP(String serverId) { + + try { + Server server = this.getServer(serverId); + + if(server != null) { + FloatingIP floatIp = os.compute().floatingIps().allocateIP(properties.getProperty(Constants.OS_FLOATING_IP_POOL)); + + if(floatIp != null) { + String ipAddr = floatIp.getFloatingIpAddress(); + + if(ipAddr != null) { + ActionResponse response = os.compute().floatingIps().addFloatingIP(server, ipAddr); + logger.info(response.isSuccess() + ":" + response.getCode() + ":" + response.getFault() + ":" + response.toString()); + + logger.info("Floating IP "+ ipAddr + " assigned successfully to server with ID: " + serverId); + } + } + else { + logger.error("Failed to associate Floating IP."); + } + } + } + catch( Exception ex ) { + ex.printStackTrace(); + // TODO: Check with the team on how to handle exceptions. + logger.error("Failed to associate floating IP to server with ID: " + serverId); + } + } } http://git-wip-us.apache.org/repos/asf/airavata/blob/8b9f5c89/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/util/Constants.java ---------------------------------------------------------------------- diff --git a/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/util/Constants.java b/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/util/Constants.java index 275a0e7..e2b9ad1 100644 --- a/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/util/Constants.java +++ b/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/util/Constants.java @@ -30,5 +30,7 @@ public class Constants { public static final String OS_PASSWORD = "OS_PASSWORD"; public static final String OS_USER_DOMAIN_NAME = "OS_USER_DOMAIN_NAME"; public static final String OS_PROJECT_DOMAIN_NAME = "OS_PROJECT_DOMAIN_NAME"; + public static final String OS_FLOATING_IP_POOL = "OS_FLOATING_IP_POOL"; + public static final String OS_SUBNET_NAME = "OS_SUBNET_NAME"; } http://git-wip-us.apache.org/repos/asf/airavata/blob/8b9f5c89/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/util/IPType.java ---------------------------------------------------------------------- diff --git a/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/util/IPType.java b/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/util/IPType.java new file mode 100644 index 0000000..36b5598 --- /dev/null +++ b/modules/cloud/cloud-provisioning/src/main/java/org/apache/airavata/cloud/util/IPType.java @@ -0,0 +1,39 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.airavata.cloud.util; + +public enum IPType { + + FLOATING("floating"), + STATIC("static"); + + String ipType; + + private IPType(String type) { + this.ipType = type; + } + + @Override + public String toString() { + return this.ipType; + } +} http://git-wip-us.apache.org/repos/asf/airavata/blob/8b9f5c89/modules/cloud/cloud-provisioning/src/main/resources/jetstream_openrc.properties ---------------------------------------------------------------------- diff --git a/modules/cloud/cloud-provisioning/src/main/resources/jetstream_openrc.properties b/modules/cloud/cloud-provisioning/src/main/resources/jetstream_openrc.properties index 9487bc1..cda2bec 100644 --- a/modules/cloud/cloud-provisioning/src/main/resources/jetstream_openrc.properties +++ b/modules/cloud/cloud-provisioning/src/main/resources/jetstream_openrc.properties @@ -27,3 +27,7 @@ OS_USERNAME=scigap OS_PASSWORD=xxxxxxxx OS_AUTH_URL=https://jblb.jetstream-cloud.org:35357/v3 OS_IDENTITY_API_VERSION=3 + +# Network Properties +OS_FLOATING_IP_POOL=public +OS_SUBNET_NAME=airavata http://git-wip-us.apache.org/repos/asf/airavata/blob/8b9f5c89/modules/cloud/cloud-provisioning/src/test/java/org/apache/airavata/cloud/test/CloudIntfTest.java ---------------------------------------------------------------------- diff --git a/modules/cloud/cloud-provisioning/src/test/java/org/apache/airavata/cloud/test/CloudIntfTest.java b/modules/cloud/cloud-provisioning/src/test/java/org/apache/airavata/cloud/test/CloudIntfTest.java index 71a8a53..c48c694 100644 --- a/modules/cloud/cloud-provisioning/src/test/java/org/apache/airavata/cloud/test/CloudIntfTest.java +++ b/modules/cloud/cloud-provisioning/src/test/java/org/apache/airavata/cloud/test/CloudIntfTest.java @@ -78,7 +78,9 @@ public class CloudIntfTest { // Sample data. This can be determined by the inputs from Airavata. String imageId = properties.getProperty("jetstream_imageId"); String flavorId = properties.getProperty("jetstream_flavorId"); - String networkId = properties.getProperty("jetstream_networkId"); + + // Delay in milliseconds used for waiting for server create and delete. + Integer delay = 30000; /* Create Keypair */ String publicKeyFile = properties.getProperty("publicKeyFile"); @@ -95,19 +97,30 @@ public class CloudIntfTest { logger.info("Keypair created/ retrieved: " + kp.getFingerprint()); /* Create Server */ - Server newServer = cloudIntf.createServer("AiravataTest", imageId, flavorId, networkId, kp.getName()); + Server newServer = cloudIntf.createServer("AiravataTest", imageId, flavorId, kp.getName()); logger.info("Server Created: " + newServer.getId()); + /* Wait 30 seconds until server is active */ + logger.info("Waiting for instance to go ACTIVE..."); + Thread.sleep(delay); + + /* Associate floating ip */ + cloudIntf.addFloatingIP(newServer.getId()); + /* Delete Server */ cloudIntf.deleteServer(newServer.getId()); logger.info("Server deleted: " + newServer.getId()); - Server deleted = cloudIntf.getServer(newServer.getId()); + /* Wait 30 seconds until server is terminated */ + logger.info("Waiting for instance to terminate..."); + Thread.sleep(delay); /* Delete Keypair */ cloudIntf.deleteKeyPair(kp.getName()); logger.info("Keypair deleted: " + kp.getName()); + Server deleted = cloudIntf.getServer(newServer.getId()); + assertTrue(newServer != null && deleted == null); } catch( Exception ex ) { http://git-wip-us.apache.org/repos/asf/airavata/blob/8b9f5c89/modules/cloud/cloud-provisioning/src/test/resources/test_data.properties ---------------------------------------------------------------------- diff --git a/modules/cloud/cloud-provisioning/src/test/resources/test_data.properties b/modules/cloud/cloud-provisioning/src/test/resources/test_data.properties index 2ebf7c7..df87b8e 100644 --- a/modules/cloud/cloud-provisioning/src/test/resources/test_data.properties +++ b/modules/cloud/cloud-provisioning/src/test/resources/test_data.properties @@ -24,4 +24,3 @@ publicKeyFile=/path/id_rsa.pub # Jetstream properties jetstream_imageId=7048bb41-bbbbb-4caa-9370-xxxxxxxxxxx jetstream_flavorId=3 -jetstream_networkId=4367cd20-cccc-4dc2-97e8-kkkkkkkkkkk
