/**
* This file is part of CloudML [ http://cloudml.org ]
*
* Copyright (C) 2012 - SINTEF ICT
* Contact: Franck Chauvel <franck.chauvel@sintef.no>
*
* Module: root
*
* CloudML is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* CloudML is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with CloudML. If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.cloudml.connectors;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import org.cloudml.core.ComponentInstance;
import org.cloudml.core.VM;
import org.cloudml.core.VMInstance;
import org.cloudml.core.Property;
import net.flexiant.extility.*;
public class FlexiantConnector implements Connector{
private static final Logger journal = Logger.getLogger(FlexiantConnector.class.getName());
private final String endpoint;
private UserService service;
private BindingProvider portBP;
private HashMap<String,Object> runtimeInformation=new HashMap<String, Object>();
@SuppressWarnings("restriction")
public FlexiantConnector(String endPoint, String login, String secretKey) throws MalformedURLException{
this.endpoint=endPoint;
System.setProperty ("jsse.enableSNIExtension", "false");
journal.log(Level.INFO, ">> Connecting to Flexiant ...");
URL url = ClassLoader.getSystemClassLoader().getResource(
"UserAdmin.wsdl");
// Get the UserAPI
UserAPI api = new UserAPI(url,
new QName("http://extility.flexiant.net", "UserAPI"));
// and set the service port on the service
service = api.getUserServicePort();
// Get the binding provider
BindingProvider portBP = (BindingProvider) service;
// and set the service endpoint
portBP.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
endPoint);
journal.log(Level.INFO, ">> Authenticating ...");
// and the caller's authentication details and password
portBP.getRequestContext().put(BindingProvider.USERNAME_PROPERTY,
login);
portBP.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY,
secretKey);
}
public List<Object> getListServer(){
try {
// Create an FQL filter and a filter condition
SearchFilter sf = new SearchFilter();
FilterCondition fc = new FilterCondition();
// set the condition type
fc.setCondition(Condition.IS_EQUAL_TO);
// the field to be matched
fc.setField("status");
// and a list of values
fc.getValue().add(ServerStatus.RUNNING.name());
fc.getValue().add(ServerStatus.STARTING.name());
// Add the filter condition to the query
sf.getFilterConditions().add(fc);
// Set a limit to the number of results
QueryLimit lim = new QueryLimit();
lim.setMaxRecords(50);
// Call the service to execute the query
ListResult result = service.listResources(sf,lim, ResourceType.SERVER);
return result.getList();
} catch (Exception e) {
journal.log(Level.SEVERE, e.getMessage());
return null;
}
}
public List<Object> getListImages(){
try {
// Create an FQL filter and a filter condition
SearchFilter sf = new SearchFilter();
FilterCondition fc = new FilterCondition();
// the field to be matched
fc.setField("ImageType");
// set the condition type
fc.setCondition(Condition.IS_EQUAL_TO);
// Add the filter condition to the query
sf.getFilterConditions().add(fc);
// and a list of values
fc.getValue().add(ImageType.DISK.name());
// Set a limit to the number of results
QueryLimit lim = new QueryLimit();
lim.setMaxRecords(50);
// Call the service to execute the query
ListResult result = service.listResources(sf,lim, ResourceType.IMAGE);
return result.getList();
} catch (Exception e) {
journal.log(Level.SEVERE, e.getMessage());
return null;
}
}
public HashMap<String,Object> createInstance(VMInstance a){
ComponentInstance.State state = ComponentInstance.State.UNRECOGNIZED;
try {
Server template = new Server();
if(findResourceByName(a.getName(), ResourceType.SERVER).equals("")){
VM vm = a.getType();
List<String> sshKeyList = new ArrayList<String> ();
template.setResourceType(ResourceType.SERVER);
journal.log(Level.INFO, ">> Provisioning a vm ...");
if (vm.getMinCores() > 0 && vm.getMinRam() > 0)
template.setProductOfferUUID(findProduct(((double) vm.getMinRam()), vm.getMinCores()));
if (!vm.getGroupName().equals(""))
template.setVdcUUID(findResourceByName(vm.getGroupName(),ResourceType.VDC));
if(!vm.getImageId().equals("")){
String imId=findResourceByName(vm.getImageId(), ResourceType.IMAGE);
if(!imId.equals("")) {
template.setImageUUID(imId); //TODO: find by OS
}
}
if(!vm.getSshKey().equals(""))
sshKeyList.add(findResourceByName(vm.getSshKey(),ResourceType.SSHKEY));
template.setResourceName(a.getName());
Nic n=new Nic();
if(findResourceByName("Default network - Default cluster", ResourceType.NETWORK).equals(""))
n.setNetworkUUID(findResourceByName("Default network - KVM", ResourceType.NETWORK));
else n.setNetworkUUID(findResourceByName("Default network - Default cluster", ResourceType.NETWORK));
n.setNetworkName(a.getName());
template.getNics().add(n);
Disk d = new Disk();
d.setSize(vm.getMinStorage());
d.setResourceName(a.getName());
template.getDisks().add(d);
//TODO: Add disk
Job job=service.createServer(template, sshKeyList, null);
service.waitForJob(job.getResourceUUID(), false);
a.getProperties().add(new Property("ProviderSpecificInstanceType", findProductName(((double) vm.getMinRam()), vm.getMinCores())));
a.setProviderSpecificType(findProductName(((double) vm.getMinRam()), vm.getMinCores()));
a.setId(findResourceByName(a.getName(), ResourceType.SERVER));
/*Job nicJob=service.createNetworkInterface(n, null);
service.waitForJob(nicJob.getResourceUUID(), false);
service.attachNetworkInterface(job.getItemUUID(), nicJob.getItemUUID(), 0, null);*/
journal.log(Level.INFO, ">> vm type: "+ findProductName(((double) vm.getMinRam()), vm.getMinCores()) + " named " + template.getResourceName());
Job startJob=service.changeServerStatus(a.getId(), ServerStatus.RUNNING, true, null, null);
service.waitForJob(startJob.getResourceUUID(), false);
Thread.sleep(100000);
//System.out.println(((Server) findObjectResourceByName(a.getName(), ResourceType.SERVER)).getInitialPassword());
}
a.setId(findResourceByName(a.getName(), ResourceType.SERVER));
Server temp=(Server)findObjectResourceByName(a.getName(), ResourceType.SERVER);
a.setCore(temp.getCpu());
//a.setPublicAddress(temp.getNics().get(0).getIpAddresses().get(0).getIpAddress());
runtimeInformation.put("publicAddress", temp.getNics().get(0).getIpAddresses().get(0).getIpAddress());
journal.log(Level.INFO, ">> Running VM: " + a.getName() + " id: " + a.getId() + " with public address: " + a.getPublicAddress());
//a.setStatusAsRunning();
state = ComponentInstance.State.RUNNING;
} catch (ExtilityException e) {
// TODO Auto-generated catch block
journal.log(Level.SEVERE, e.getMessage());
//a.setStatusAsError();
state = ComponentInstance.State.ERROR;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
journal.log(Level.SEVERE, e.getMessage());
//a.setStatusAsError();
state = ComponentInstance.State.ERROR;
}
runtimeInformation.put("status", state);
return runtimeInformation;
}
public void execCommand(VMInstance n, String command, String login, String keyPath){
SSHConnector sc=new SSHConnector(keyPath, login, n.getPublicAddress());
sc.execCommandSsh(command);
}
public void execCommand(String id, String command, String login, String keyPath){
Server temp=(Server)findObjectResourceByID(id, ResourceType.SERVER);
String ip=temp.getNics().get(0).getIpAddresses().get(0).getIpAddress();
SSHConnector sc=new SSHConnector(keyPath, login, ip);
while (!sc.checkConnectivity()){
try {
Thread.sleep(32000);
} catch (InterruptedException e) {
journal.log(Level.SEVERE, e.getMessage());
}
}
try {
Thread.sleep(32000);
} catch (InterruptedException e) {
journal.log(Level.SEVERE, e.getMessage());
}
sc.execCommandSsh(command);
}
public String findResourceByName(String name, ResourceType t){
try {
// Create an FQL filter and a filter condition
SearchFilter sf = new SearchFilter();
FilterCondition fc = new FilterCondition();
// the field to be matched
fc.setField("ResourceName");
// set the condition type
fc.setCondition(Condition.IS_EQUAL_TO);
// Add the filter condition to the query
sf.getFilterConditions().add(fc);
// and a list of values
fc.getValue().add(name);
// Set a limit to the number of results
QueryLimit lim = new QueryLimit();
lim.setMaxRecords(50);
lim.setLoadChildren(true);
// Call the service to execute the query
ListResult result = service.listResources(sf,lim, t);
if(result.getList().size() >= 0){
Resource s= (Resource) result.getList().get(0);
return s.getResourceUUID();
}else{
return "";
}
} catch (Exception e) {
return "";
}
}
public Object findObjectResourceByName(String name, ResourceType t){
try {
// Create an FQL filter and a filter condition
SearchFilter sf = new SearchFilter();
FilterCondition fc = new FilterCondition();
// the field to be matched
fc.setField("ResourceName");
// set the condition type
fc.setCondition(Condition.IS_EQUAL_TO);
// Add the filter condition to the query
sf.getFilterConditions().add(fc);
// and a list of values
fc.getValue().add(name);
// Set a limit to the number of results
QueryLimit lim = new QueryLimit();
lim.setMaxRecords(50);
lim.setLoadChildren(true);
// Call the service to execute the query
ListResult result = service.listResources(sf,lim, t);
return result.getList().get(0);
} catch (Exception e) {
journal.log(Level.SEVERE, e.getMessage());
return null;
}
}
public Object findObjectResourceByID(String id, ResourceType t){
try {
// Create an FQL filter and a filter condition
SearchFilter sf = new SearchFilter();
FilterCondition fc = new FilterCondition();
// the field to be matched
fc.setField("ResourceUUID");
// set the condition type
fc.setCondition(Condition.IS_EQUAL_TO);
// Add the filter condition to the query
sf.getFilterConditions().add(fc);
// and a list of values
fc.getValue().add(id);
// Set a limit to the number of results
QueryLimit lim = new QueryLimit();
lim.setMaxRecords(100);
lim.setLoadChildren(true);
// Call the service to execute the query
ListResult result = service.listResources(sf,lim, t);
return result.getList().get(0);
} catch (Exception e) {
journal.log(Level.SEVERE, e.getMessage());
return null;
}
}
public String findProductName(double ram, int CPU){
try {
// Create an FQL filter and a filter condition
SearchFilter sf = new SearchFilter();
FilterCondition fc = new FilterCondition();
// the field to be matched
fc.setField("ResourceName");
// set the condition type
fc.setCondition(Condition.CONTAINS);
// Add the filter condition to the query
sf.getFilterConditions().add(fc);
// and a list of values
fc.getValue().add(CPU+" CPU");
// Set a limit to the number of results
QueryLimit lim = new QueryLimit();
lim.setMaxRecords(50);
// Call the service to execute the query
ListResult result = service.listResources(sf,lim, ResourceType.PRODUCTOFFER);
if(result.getList().size() > 0){
ProductOffer p=(ProductOffer)result.getList().get(0);
Double min=5000.0;
for(Object o : result.getList()) {
ProductOffer s = ((ProductOffer)o);
for(ProductComponent t : s.getComponentConfig()){
for(Value v: t.getProductConfiguredValues()){
if(v.getKey().equals("ram")){
double productRam=Double.parseDouble(v.getValue()); //RAM value
if(productRam >= ram && productRam <= min){
min=productRam;
p=s;
}
}
}
}
}
return p.getResourceName();
}
return "";
} catch (Exception e) {
journal.log(Level.SEVERE, e.getMessage());
return "";
}
}
public String findProduct(double ram, int CPU){
try {
// Create an FQL filter and a filter condition
SearchFilter sf = new SearchFilter();
FilterCondition fc = new FilterCondition();
// the field to be matched
fc.setField("ResourceName");
// set the condition type
fc.setCondition(Condition.CONTAINS);
// Add the filter condition to the query
sf.getFilterConditions().add(fc);
// and a list of values
fc.getValue().add(CPU+" CPU");
// Set a limit to the number of results
QueryLimit lim = new QueryLimit();
lim.setMaxRecords(50);
// Call the service to execute the query
ListResult result = service.listResources(sf,lim, ResourceType.PRODUCTOFFER);
if(result.getList().size() > 0){
ProductOffer p=(ProductOffer)result.getList().get(0);
Double min=5000.0;
for(Object o : result.getList()) {
ProductOffer s = ((ProductOffer)o);
for(ProductComponent t : s.getComponentConfig()){
for(Value v: t.getProductConfiguredValues()){
if(v.getKey().equals("ram")){
double productRam=Double.parseDouble(v.getValue()); //RAM value
if(productRam >= ram && productRam <= min){
min=productRam;
p=s;
}
}
}
}
}
return p.getResourceUUID();
}
return "";
} catch (Exception e) {
journal.log(Level.SEVERE, e.getMessage());
return "";
}
}
public String getEndpoint(){
return this.endpoint;
}
public void destroyVM(String id) {
try {
Job job=service.deleteResource(id,true, null);
service.waitForJob(job.getResourceUUID(), false);
} catch (ExtilityException e) {
e.printStackTrace();
}
}
/**
* create the snapshot of a disk (only feature supported now on the MODAClouds platform)
* @param vmi a VM instance
* @return id of the snapshot
*/
public String createSnapshot(VMInstance vmi){
journal.log(Level.INFO, ">> Creating a snapshot of VM id: "+vmi.getId());
Snapshot snapshot=new Snapshot();
Server temp=(Server)findObjectResourceByID(vmi.getId(), ResourceType.SERVER);
snapshot.setParentUUID(temp.getDisks().get(0).getResourceUUID());
snapshot.setResourceName(vmi.getName()+"-snapshot");
snapshot.setType(SnapshotType.DISK);
snapshot.setResourceType(ResourceType.SNAPSHOT);
snapshot.setClusterUUID(temp.getClusterUUID());
try {
Job job=service.createSnapshot(snapshot,null);
service.waitForJob(job.getResourceUUID(), false);
} catch (ExtilityException e) {
e.printStackTrace();
}
journal.log(Level.INFO, ">> Snapshot created with id: "+vmi.getName()+"-snapshot");
return vmi.getName()+"-snapshot";
}
/**
* Create an image of the specified VM
* @param vmi a VM instance
* @return id of the image
*/
public String createImage(VMInstance vmi){
journal.log(Level.INFO, ">> Creating an image of VM id: "+vmi.getId());
Image image=new Image();
Server temp=(Server)findObjectResourceByID(vmi.getId(), ResourceType.SERVER);
image.setBaseUUID(temp.getDisks().get(0).getResourceUUID());
image.setClusterUUID(temp.getClusterUUID());
image.setResourceName(vmi.getName()+"-image");
image.setResourceType(ResourceType.IMAGE);
image.setVdcUUID(temp.getVdcUUID());
try {
Job job1=service.changeServerStatus(temp.getResourceUUID(),ServerStatus.STOPPED,true,null,null);
service.waitForJob(job1.getResourceUUID(), false);
Job job2=service.createImage(image, null);
service.waitForJob(job2.getResourceUUID(), false);
Job job3=service.changeServerStatus(temp.getResourceUUID(),ServerStatus.RUNNING,true,null,null);
service.waitForJob(job3.getResourceUUID(), false);
} catch (ExtilityException e) {
journal.log(Level.SEVERE, e.getMessage());
}
journal.log(Level.INFO, ">> Image created with id: "+vmi.getName()+"-image");
return vmi.getName()+"-image";
}
@Override
public void startVM(VMInstance a) {
try {
journal.log(Level.INFO, ">> Starting VM: "+a.getName());
Job startJob=service.changeServerStatus(a.getId(), ServerStatus.RUNNING, true, null, null);
service.waitForJob(startJob.getResourceUUID(), false);
} catch (ExtilityException e) {
e.printStackTrace();
}
}
@Override
public void stopVM(VMInstance a) {
try {
journal.log(Level.INFO, ">> Stopping VM: "+a.getName());
Job startJob=service.changeServerStatus(a.getId(), ServerStatus.STOPPED, true, null, null);
service.waitForJob(startJob.getResourceUUID(), false);
} catch (ExtilityException e) {
e.printStackTrace();
}
}
public void closeConnection() {}
public void updateVMMetadata(VMInstance a) {
a.setId(findResourceByName(a.getName(), ResourceType.SERVER));
Server temp=(Server)findObjectResourceByName(a.getName(), ResourceType.SERVER);
a.setPublicAddress(temp.getNics().get(0).getIpAddresses().get(0).getIpAddress());
}
public void uploadFile(String sourcePath, String destinationPath,
String VMId, String login, String key) {
Server temp=(Server)findObjectResourceByID(VMId, ResourceType.SERVER);
String ip=temp.getNics().get(0).getIpAddresses().get(0).getIpAddress();
SSHConnector sc=new SSHConnector(key, login, ip);
sc.upload(sourcePath,destinationPath);
}
}