/**
*
* 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.intf.impl;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
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.apache.airavata.cloud.util.OpenstackIntfUtil;
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.AttachInterfaceType;
import org.openstack4j.model.network.IPVersionType;
import org.openstack4j.model.network.Network;
import org.openstack4j.model.network.Router;
import org.openstack4j.model.network.RouterInterface;
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 {
/** The properties. */
private String propertiesFile;
private Properties properties;
// Initializing Logger
private Logger logger = LoggerFactory.getLogger(OpenstackIntfImpl.class);
OSClient os = null;
/**
* Default Constructor
* Initializing the properties.
*/
public OpenstackIntfImpl(String propFile) {
try {
this.propertiesFile = propFile;
InputStream inputStream = getClass().getClassLoader()
.getResourceAsStream(propertiesFile);
if(inputStream != null) {
properties = new Properties();
properties.load(inputStream);
}
else {
throw new FileNotFoundException("property file: " + propertiesFile + " not found!");
}
// Initialize the OSClient.
os = OS4JClientProvider.getOSClient(properties);
}
catch(Exception ex) {
ex.printStackTrace();
// TODO: Check with the team on how to handle exceptions.
}
}
@Override
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_NETWORK_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);
ServerCreate sc = Builders.server()
.name(serverName)
.flavor(flavorId)
.image(imageId)
.networks(srvNet)
.keypairName(keyPairName)
.build();
//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;
}
}
@Override
public Server getServer(String serverId) {
try {
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;
}
}
@Override
public void deleteServer(String serverId) {
try {
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_NETWORK_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);
}
}
@Override
public Keypair createKeyPair(String keyPairName, String publicKey) {
try {
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;
}
}
@Override
public Keypair getKeyPair(String keyPairName) {
try {
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;
}
}
@Override
public void deleteKeyPair(String keyPairName) {
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);
// Floating IP to allocate.
FloatingIP floatIp = null;
if(server != null) {
List<? extends FloatingIP> floatIPList = os.compute().floatingIps().list();
// Iterate through the floating ips from the pool present if any.
if(floatIPList.size() > 0) {
for(FloatingIP ip : floatIPList) {
logger.info("Checking if floating ip : " + ip.getFloatingIpAddress() + " is free to use.");
Boolean isFloatingIpUsed = OpenstackIntfUtil.isFloatingIPUsed(ip);
if( isFloatingIpUsed != null && !isFloatingIpUsed ) {
floatIp = ip;
logger.info("Floating ip " + ip.getFloatingIpAddress() + " found to be free.");
break;
}
}
}
// If all floating IPs are used, or there are no free floating ips, create new one.
if(floatIp == null){
floatIp = os.compute().floatingIps().allocateIP(properties.getProperty(Constants.OS_FLOATING_IP_POOL));
logger.info("Created new floating ip " + floatIp.getFloatingIpAddress());
}
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());
if(response.isSuccess()) {
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);
}
}
@Override
public Object createNetwork(String networkName) {
Network network = null;
try {
network = os.networking().network().create(Builders.network()
.name(networkName)
.adminStateUp(true)
.build());
logger.info("Created a new network : " + network);
} catch( Exception ex ) {
ex.printStackTrace();
// TODO: Check with the team on how to handle exceptions.
logger.error("Failed to create network: " + networkName + ". Exception: " + ex.getMessage(), ex);
}
return network;
}
@Override
public Object createRouter(String routerName, String externalGatewayName) {
String publicNetId = null;
Router router = null;
try {
for(Network net : os.networking().network().list()) {
if(net.getName().equals(externalGatewayName)) {
publicNetId = net.getId();
}
}
if(publicNetId != null) {
router = os.networking().router().create(Builders.router()
.name(routerName)
.adminStateUp(true)
.externalGateway(publicNetId)
.build());
logger.info("Created a new router " + router + " for external gateway : [" + externalGatewayName + "]");
} else {
logger.error("Failed to create router because external gateway [ " + externalGatewayName + "] is not found!");
}
} catch( Exception ex ) {
ex.printStackTrace();
// TODO: Check with the team on how to handle exceptions.
logger.error("Failed to create network: " + routerName + ". Exception: " + ex.getMessage(), ex);
}
return router;
}
@Override
public Object createSubnet(String subnetName, String networkName, String subnetCIDR, int ipVersion) {
String networkId = null;
Subnet subnet = null;
try {
// get network id
for(Network network : os.networking().network().list()) {
if(network.getName().equals(networkName)) {
networkId = network.getId();
}
}
if(networkId != null) {
subnet = os.networking().subnet().create(Builders.subnet()
.enableDHCP(true)
.name(subnetName)
.networkId(networkId)
.ipVersion(IPVersionType.valueOf(ipVersion))
.cidr(subnetCIDR)
.build());
logger.info("Created a subnet : " + subnetName + " for network [ " + networkName + "]");
} else {
logger.error("Failed to create subnet because network [ " + networkName + "] is not found!");
}
} catch( Exception ex ) {
ex.printStackTrace();
// TODO: Check with the team on how to handle exceptions.
logger.error("Failed to create subnet: " + subnetName + ". Exception: " + ex.getMessage(), ex);
}
return subnet;
}
@Override
public Object createRouterSubnetInterface(String routerName, String subnetName) {
String subnetId = null, routerId = null;
RouterInterface iface = null;
try {
// get subnetid from name
for(Subnet subnet : os.networking().subnet().list()) {
if(subnet.getName().equals(subnetName)) {
subnetId = subnet.getId();
}
}
// get routerid from name
for(Router router : os.networking().router().list()) {
if(router.getName().equals(routerName)) {
routerId = router.getId();
}
}
if(routerId != null && subnetId != null) {
// attach external interface to gateway
iface = os.networking().router()
.attachInterface(routerId, AttachInterfaceType.SUBNET, subnetId);
logger.info("Attached external interface to router : " + iface);
} else {
logger.error("Either router or network is not found. Kindly re-check and try again.");
}
} catch( Exception ex ) {
ex.printStackTrace();
// TODO: Check with the team on how to handle exceptions.
logger.error("Failed to create subnet-router interface. Exception: " + ex.getMessage(), ex);
}
return iface;
}
@Override
public void deleteRouterSubnetInterface(String routerName, String subnetName) {
String routerId = null, subnetId = null;
try {
// get subnet id
for(Subnet subnet : os.networking().subnet().list()) {
if(subnet.getName().equals(subnetName)) {
subnetId = subnet.getId();
}
}
// get router id
for(Router router : os.networking().router().list()) {
if(router.getName().equals(routerName)) {
routerId = router.getId();
}
}
// detach the interface
if(routerId != null && subnetId != null) {
os.networking().router().detachInterface(routerId, subnetId, null);
} else {
logger.error("Failed to delete router subnet interface. Either router/subnet not found.");
}
} catch( Exception ex ) {
ex.printStackTrace();
// TODO: Check with the team on how to handle exceptions.
logger.error("Failed to delete subnet: " + subnetName + ". Exception: " + ex.getMessage(), ex);
}
}
@Override
public void deleteSubnet(String subnetName) {
try {
for(Subnet subnet : os.networking().subnet().list()) {
if(subnet.getName().equals(subnetName)) {
os.networking().subnet().delete(subnet.getId());
logger.info("Deleted Subnet [" + subnet.getName() + "] Successfully.");
}
}
} catch( Exception ex ) {
ex.printStackTrace();
// TODO: Check with the team on how to handle exceptions.
logger.error("Failed to delete subnet: " + subnetName + ". Exception: " + ex.getMessage(), ex);
}
}
@Override
public void deleteRouter(String routerName) {
try {
for(Router router : os.networking().router().list()) {
if(router.getName().equals(routerName)) {
os.networking().router().delete(router.getId());
logger.info("Deleted Router [" + router.getName() + "] Successfully.");
}
}
} catch( Exception ex ) {
ex.printStackTrace();
// TODO: Check with the team on how to handle exceptions.
logger.error("Failed to delete router: " + routerName + ". Exception: " + ex.getMessage(), ex);
}
}
@Override
public void deleteNetwork(String networkName) {
try {
for(Network network : os.networking().network().list()) {
if(network.getName().equals(networkName)) {
os.networking().network().delete(network.getId());
logger.info("Deleted Network [" + network.getName() + "] Successfully.");
}
}
} catch( Exception ex ) {
ex.printStackTrace();
// TODO: Check with the team on how to handle exceptions.
logger.error("Failed to delete network: " + networkName + ". Exception: " + ex.getMessage(), ex);
}
}
}