membersUsage, String memberId) {
double debt = 0;
+ if (localMemberId.equals(memberId)) {
+ if (prioritizeLocal) {
+ return Double.MAX_VALUE;
+ } else {
+ return -1;
+ }
+ }
+
if (membersUsage.containsKey(memberId)) {
debt = membersUsage.get(memberId).getConsumed()
- membersUsage.get(memberId).getDonated();
diff --git a/src/main/java/org/fogbowcloud/manager/core/plugins/util/CloudInitUserDataBuilder.java b/src/main/java/org/fogbowcloud/manager/core/plugins/util/CloudInitUserDataBuilder.java
new file mode 100644
index 00000000..6a210269
--- /dev/null
+++ b/src/main/java/org/fogbowcloud/manager/core/plugins/util/CloudInitUserDataBuilder.java
@@ -0,0 +1,482 @@
+package org.fogbowcloud.manager.core.plugins.util;
+/*
+ * Copyright 2008-2010 Xebia and the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.nio.charset.Charset;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import org.apache.commons.codec.binary.Base64;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Sets;
+import com.google.common.io.CharStreams;
+
+/**
+ *
+ * Build a CloudInit
+ * UserData file.
+ *
+ *
+ * Sample:
+ *
+ *
+ *
+ *
+ * // base64 encoded user data
+ * String userData = CloudInitUserDataBuilder.start() //
+ * .addShellScript(shellScript) //
+ * .addCloudConfig(cloudConfig) //
+ * .buildBase64UserData();
+ *
+ * RunInstancesRequest req = new RunInstancesRequest() //
+ * .withInstanceType("t1.micro") //
+ * .withImageId("ami-47cefa33") // amazon-linux in eu-west-1 region
+ * .withMinCount(1).withMaxCount(1) //
+ * .withSecurityGroupIds("default") //
+ * .withKeyName("my-key") //
+ * .withUserData(userData);
+ *
+ * RunInstancesResult runInstances = ec2.runInstances(runInstancesRequest);
+ *
+ *
+ *
+ * Inspired by ubuntu-on-ec2 cloud-utils write-mime-multipart python script.
+ *
+ *
+ * @see com.amazonaws.services.ec2.model.RunInstancesRequest#withUserData(String)
+ * @see com.amazonaws.services.ec2.AmazonEC2.runInstances(RunInstancesRequest)
+ *
+ * @author Cyrille Le Clerc
+ */
+public class CloudInitUserDataBuilder {
+
+ /**
+ * File types supported by CloudInit
+ */
+ public enum FileType {
+ /**
+ *
+ * This content is "boothook" data. It is stored in a file under
+ * /var/lib/cloud and then executed immediately. This is the earliest
+ * "hook" available. Note, that there is no mechanism provided for
+ * running only once. The boothook must take care of this itself. It is
+ * provided with the instance id in the environment variable
+ * "INSTANCE_ID". This could be made use of to provide a
+ * 'once-per-instance'
+ *
+ */
+ CLOUD_BOOTHOOK("text/cloud-boothook", "cloudinit-cloud-boothook.txt"), //
+ /**
+ *
+ * This content is "cloud-config" data. See the examples for a commented
+ * example of supported config formats.
+ *
+ *
+ * Example: cloud-config.txt
+ *
+ */
+ CLOUD_CONFIG("text/cloud-config", "cloudinit-cloud-config.txt"), //
+ /**
+ *
+ * This content is a "include" file. The file contains a list of urls,
+ * one per line. Each of the URLs will be read, and their content will
+ * be passed through this same set of rules. Ie, the content read from
+ * the URL can be gzipped, mime-multi-part, or plain text
+ *
+ *
+ * Example: include.txt
+ *
+ */
+ INCLUDE_URL("text/x-include-url", "cloudinit-x-include-url.txt"), //
+ /**
+ *
+ * This is a 'part-handler'. It will be written to a file in
+ * /var/lib/cloud/data based on its filename. This must be python code
+ * that contains a list_types method and a handle_type method. Once the
+ * section is read the 'list_types' method will be called. It must
+ * return a list of mime-types that this part-handler handlers.
+ *
+ *
+ * Example: part-handler.txt
+ *
+ */
+ PART_HANDLER("text/part-handler", "cloudinit-part-handler.txt"), //
+ /**
+ *
+ * Script will be executed at "rc.local-like" level during first boot.
+ * rc.local-like means "very late in the boot sequence"
+ *
+ *
+ * Example: user-script.txt
+ *
+ */
+ SHELL_SCRIPT("text/x-shellscript", "cloudinit-userdata-script.txt"), //
+ /**
+ *
+ * Content is placed into a file in /etc/init, and will be consumed by
+ * upstart as any other upstart job.
+ *
+ *
+ * Example: upstart-rclocal.txt
+ *
+ */
+ UPSTART_JOB("text/upstart-job", "cloudinit-upstart-job.txt");
+
+ /**
+ * Name of the file.
+ */
+ private final String fileName;
+ /**
+ * Mime Type of the file.
+ */
+ private final String mimeType;
+
+ private FileType( String mimeType, String fileName) {
+ this.mimeType = Preconditions.checkNotNull(mimeType);
+ this.fileName = Preconditions.checkNotNull(fileName);
+ }
+
+ /**
+ * @return name of the file
+ */
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ /**
+ * e.g. "cloud-config" for "text/cloud-config"
+ */
+
+ public String getMimeTextSubType() {
+ return getMimeType().substring("text/".length());
+ }
+
+ /**
+ * e.g. "text/cloud-config"
+ */
+
+ public String getMimeType() {
+ return mimeType;
+ }
+
+ @Override
+ public String toString() {
+ return name() + "[" + mimeType + "]";
+ }
+ }
+
+ /**
+ * Initiates a new instance of the builder with the "UTF-8" charset.
+ */
+ public static CloudInitUserDataBuilder start() {
+ return new CloudInitUserDataBuilder(Charsets.UTF_8);
+ }
+
+ /**
+ * Initiates a new instance of the builder.
+ *
+ * @param charset
+ * used to generate the mime message.
+ */
+ public static CloudInitUserDataBuilder start( String charset) {
+ return new CloudInitUserDataBuilder(Charset.forName(charset));
+ }
+
+ /**
+ * File types already added because cloud-init only supports one file of
+ * each type.
+ */
+ private final Set alreadyAddedFileTypes = Sets.newHashSet();
+
+ /**
+ * Charset used to generate the mime message.
+ */
+ private final Charset charset;
+
+ /**
+ * Mime message under creation
+ */
+ private final MimeMessage userDataMimeMessage;
+
+ /**
+ * Mime message's content under creation
+ */
+ private final MimeMultipart userDataMultipart;
+
+ private CloudInitUserDataBuilder( Charset charset) {
+ super();
+ userDataMimeMessage = new MimeMessage(Session.getDefaultInstance(new Properties()));
+ userDataMultipart = new MimeMultipart();
+ try {
+ userDataMimeMessage.setContent(userDataMultipart);
+ } catch (MessagingException e) {
+ throw Throwables.propagate(e);
+ }
+ this.charset = Preconditions.checkNotNull(charset, "'charset' can NOT be null");
+ }
+
+ /**
+ * Add a boot-hook file.
+ *
+ * @see FileType#CLOUD_BOOTHOOK
+ * @param bootHook
+ * @return the builder
+ * @throws IllegalArgumentException
+ * a boot-hook file was already added to this cloud-init mime
+ * message.
+ */
+ public CloudInitUserDataBuilder addBootHook( Readable bootHook) {
+ return addFile(FileType.CLOUD_BOOTHOOK, bootHook);
+ }
+
+ /**
+ * Add a cloud-config file.
+ *
+ * @see FileType#CLOUD_CONFIG
+ * @param cloudConfig
+ * @return the builder
+ * @throws IllegalArgumentException
+ * a cloud-config file was already added to this cloud-init mime
+ * message.
+ */
+ public CloudInitUserDataBuilder addCloudConfig(Readable cloudConfig) {
+ return addFile(FileType.CLOUD_CONFIG, cloudConfig);
+ }
+
+ /**
+ * Add a cloud-config file.
+ *
+ * @see FileType#CLOUD_CONFIG
+ * @param cloudConfig
+ * @return the builder
+ * @throws IllegalArgumentException
+ * a cloud-config file was already added to this cloud-init mime
+ * message.
+ */
+ public CloudInitUserDataBuilder addCloudConfig(String cloudConfig) {
+ return addCloudConfig(new StringReader(cloudConfig));
+ }
+
+ /**
+ * Add given file in
to the cloud-init mime message.
+ *
+ * @param fileType
+ * @param in
+ * file to add as readable
+ * @return the builder
+ * @throws IllegalArgumentException
+ * the given fileType
was already added to this
+ * cloud-init mime message.
+ */
+
+ public CloudInitUserDataBuilder addFile( FileType fileType, Readable in) throws IllegalArgumentException {
+ Preconditions.checkNotNull(fileType, "'fileType' can NOT be null");
+ Preconditions.checkNotNull(in, "'in' can NOT be null");
+ Preconditions.checkArgument(!alreadyAddedFileTypes.contains(fileType), "%s as already been added", fileType);
+ alreadyAddedFileTypes.add(fileType);
+
+ try {
+ StringWriter sw = new StringWriter();
+ CharStreams.copy(in, sw);
+ MimeBodyPart mimeBodyPart = new MimeBodyPart();
+ mimeBodyPart.setText(sw.toString(), charset.name(), fileType.getMimeTextSubType());
+ mimeBodyPart.setFileName(fileType.getFileName());
+ userDataMultipart.addBodyPart(mimeBodyPart);
+
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ } catch (MessagingException e) {
+ throw Throwables.propagate(e);
+ }
+ return this;
+ }
+
+ /**
+ * Add a include-url file.
+ *
+ * @see FileType#INCLUDE_URL
+ * @param includeUrl
+ * @return the builder
+ * @throws IllegalArgumentException
+ * a include-url file was already added to this cloud-init mime
+ * message.
+ */
+
+ public CloudInitUserDataBuilder addIncludeUrl( Readable includeUrl) {
+ return addFile(FileType.INCLUDE_URL, includeUrl);
+ }
+
+ /**
+ * Add a include-url file.
+ *
+ * @see FileType#INCLUDE_URL
+ * @param includeUrl
+ * @return the builder
+ * @throws IllegalArgumentException
+ * a include-url file was already added to this cloud-init mime
+ * message.
+ */
+
+ public CloudInitUserDataBuilder addIncludeUrl( String includeUrl) {
+ return addIncludeUrl(new StringReader(includeUrl));
+ }
+
+ /**
+ * Add a part-handler file.
+ *
+ * @see FileType#PART_HANDLER
+ * @param partHandler
+ * @return the builder
+ * @throws IllegalArgumentException
+ * a part-handler file was already added to this cloud-init mime
+ * message.
+ */
+
+ public CloudInitUserDataBuilder addPartHandler( Readable partHandler) {
+ return addFile(FileType.PART_HANDLER, partHandler);
+ }
+
+ /**
+ * Add a part-handler file.
+ *
+ * @see FileType#PART_HANDLER
+ * @param partHandler
+ * @return the builder
+ * @throws IllegalArgumentException
+ * a part-handler file was already added to this cloud-init mime
+ * message.
+ */
+
+ public CloudInitUserDataBuilder addPartHandler( String partHandler) {
+ return addPartHandler(new StringReader(partHandler));
+ }
+
+ /**
+ * Add a shell-script file.
+ *
+ * @see FileType#SHELL_SCRIPT
+ * @param shellScript
+ * @return the builder
+ * @throws IllegalArgumentException
+ * a shell-script file was already added to this cloud-init mime
+ * message.
+ */
+
+ public CloudInitUserDataBuilder addShellScript( Readable shellScript) {
+ return addFile(FileType.SHELL_SCRIPT, shellScript);
+ }
+
+ /**
+ * Add a shell-script file.
+ *
+ * @see FileType#SHELL_SCRIPT
+ * @param shellScript
+ * @return the builder
+ * @throws IllegalArgumentException
+ * a shell-script file was already added to this cloud-init mime
+ * message.
+ */
+
+ public CloudInitUserDataBuilder addShellScript( String shellScript) {
+ return addShellScript(new StringReader(shellScript));
+ }
+
+ /**
+ * Add a upstart-job file.
+ *
+ * @see FileType#UPSTART_JOB
+ * @param shellScript
+ * @return the builder
+ * @throws IllegalArgumentException
+ * a upstart-job file was already added to this cloud-init mime
+ * message.
+ */
+
+ public CloudInitUserDataBuilder addUpstartJob( Readable in) {
+ return addFile(FileType.UPSTART_JOB, in);
+ }
+
+ /**
+ * Add a upstart-job file.
+ *
+ * @see FileType#UPSTART_JOB
+ * @param shellScript
+ * @return the builder
+ * @throws IllegalArgumentException
+ * a upstart-job file was already added to this cloud-init mime
+ * message.
+ */
+
+ public CloudInitUserDataBuilder addUpstartJob( String upstartJob) {
+ return addUpstartJob(new StringReader(upstartJob));
+ }
+
+ /**
+ * Build the user-data mime message.
+ *
+ * @return the generate mime message
+ */
+
+ public String buildUserData() {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ userDataMimeMessage.writeTo(baos);
+ return new String(baos.toByteArray(), this.charset);
+
+ } catch (MessagingException e) {
+ throw Throwables.propagate(e);
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ /**
+ * Build a base64 encoded user-data mime message.
+ *
+ * @return the base64 encoded encoded mime message
+ */
+
+ public String buildBase64UserData() {
+ return Base64.encodeBase64String(buildUserData().getBytes());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fogbowcloud/manager/core/plugins/util/SshHelper.java b/src/main/java/org/fogbowcloud/manager/core/plugins/util/SshHelper.java
new file mode 100644
index 00000000..814724d3
--- /dev/null
+++ b/src/main/java/org/fogbowcloud/manager/core/plugins/util/SshHelper.java
@@ -0,0 +1,93 @@
+package org.fogbowcloud.manager.core.plugins.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.PublicKey;
+
+import net.schmizz.sshj.SSHClient;
+import net.schmizz.sshj.connection.channel.direct.Session;
+import net.schmizz.sshj.connection.channel.direct.Session.Command;
+import net.schmizz.sshj.transport.verification.HostKeyVerifier;
+import net.schmizz.sshj.xfer.FileSystemFile;
+import net.schmizz.sshj.xfer.scp.SCPFileTransfer;
+
+public class SshHelper {
+
+ private SSHClient client;
+ private Session session;
+
+ public SshHelper() {
+ this(new SSHClient());
+ }
+
+ public SshHelper(SSHClient ssh) {
+ this.client = ssh;
+ addBlankHostKeyVerifier(client);
+ }
+
+ private void addBlankHostKeyVerifier(SSHClient ssh) {
+ ssh.addHostKeyVerifier(new HostKeyVerifier() {
+ @Override
+ public boolean verify(String arg0, int arg1, PublicKey arg2) {
+ return true;
+ }
+ });
+ }
+
+ public SSHClient getSshClient() {
+ return client;
+ }
+
+ public Command doSshExecution(String command) throws IOException {
+ session = client.startSession();
+ Command cmd = session.exec(command);
+ cmd.join();
+ return cmd;
+ }
+
+ public void disconnect() throws IOException {
+ if (session != null) {
+ session.close();
+ session = null;
+ }
+ client.disconnect();
+ client.close();
+ }
+
+ public void doScpDownload(String localFilePath, String remoteFilePath)
+ throws IOException {
+ FileSystemFile localFile = new FileSystemFile(localFilePath);
+ client.newSCPFileTransfer().download(remoteFilePath, localFile);
+ }
+
+ public void doScpUpload(String localFilePath, String remoteFilePath)
+ throws IOException {
+ doSshExecution("mkdir -p " + new File(remoteFilePath).getParent());
+ FileSystemFile localFile = new FileSystemFile(localFilePath);
+ SCPFileTransfer scp = client.newSCPFileTransfer();
+ scp.upload(localFile, remoteFilePath);
+ }
+
+ public void connect(String host, int port, String userName,
+ String privateKeyFilePath, int timeOut) throws IOException {
+ client = new SSHClient();
+ if (timeOut > 0) {
+ client.setConnectTimeout(timeOut);
+ }
+ addBlankHostKeyVerifier(client);
+ client.connect(host, port);
+ if (userName != null && privateKeyFilePath != null) {
+ client.authPublickey(userName, privateKeyFilePath);
+ }
+ }
+
+ public void connect(String address, int port, String userName,
+ String privateKeyFilePath) throws IOException {
+ connect(address, port, userName, privateKeyFilePath, 0);
+ }
+
+ public void connect(String address, int port) throws IOException {
+ connect(address, port, null, null, 0);
+ }
+
+}
diff --git a/src/main/java/org/fogbowcloud/manager/occi/MemberServerResource.java b/src/main/java/org/fogbowcloud/manager/occi/MemberServerResource.java
index 13c7a434..811582c8 100644
--- a/src/main/java/org/fogbowcloud/manager/occi/MemberServerResource.java
+++ b/src/main/java/org/fogbowcloud/manager/occi/MemberServerResource.java
@@ -1,9 +1,12 @@
package org.fogbowcloud.manager.occi;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import org.fogbowcloud.manager.core.model.FederationMember;
-import org.fogbowcloud.manager.core.model.Flavor;
+import org.fogbowcloud.manager.core.model.ResourcesInfo;
import org.fogbowcloud.manager.occi.core.HeaderUtils;
import org.restlet.engine.adapter.HttpRequest;
import org.restlet.resource.Get;
@@ -28,24 +31,19 @@ public String fetch() {
private String generateResponse(List federationMembers) {
StringBuilder response = new StringBuilder();
for (FederationMember federationMember : federationMembers) {
- String id = federationMember.getResourcesInfo().getId();
- response.append("id=").append(id).append(";");
- String cpuIdle = federationMember.getResourcesInfo().getCpuIdle();
- response.append("cpuIdle=").append(cpuIdle).append(";");
- String cpuInUse = federationMember.getResourcesInfo().getCpuInUse();
- response.append("cpuInUse=").append(cpuInUse).append(";");
- String memIdle = federationMember.getResourcesInfo().getMemIdle();
- response.append("memIdle=").append(memIdle).append(";");
- String memInUse = federationMember.getResourcesInfo().getMemInUse();
- response.append("memInUse=").append(memInUse).append(";");
+ Map resourcesInfoMap = new HashMap();
+ ResourcesInfo resourcesInfo = federationMember.getResourcesInfo();
+ resourcesInfoMap.put("id", resourcesInfo.getId());
+ resourcesInfoMap.put("cpuIdle", resourcesInfo.getCpuIdle());
+ resourcesInfoMap.put("cpuInUse", resourcesInfo.getCpuInUse());
+ resourcesInfoMap.put("memIdle", resourcesInfo.getMemIdle());
+ resourcesInfoMap.put("memInUse", resourcesInfo.getMemInUse());
+ resourcesInfoMap.put("instancesIdle", resourcesInfo.getInstancesIdle());
+ resourcesInfoMap.put("instancesInUse", resourcesInfo.getInstancesInUse());
- if (federationMember.getResourcesInfo().getFlavors() != null) {
- for (Flavor flavor : federationMember.getResourcesInfo().getFlavors()) {
- String nameFlavor = flavor.getName();
- Integer capacityFlavor = flavor.getCapacity();
- response.append("flavor: '").append(nameFlavor).append(", capacity=\"")
- .append(capacityFlavor).append("\"';");
- }
+ for (Entry resourceInfoEntry : resourcesInfoMap.entrySet()) {
+ response.append(resourceInfoEntry.getKey()).append("=")
+ .append(resourceInfoEntry.getValue()).append(";");
}
response.append("\n");
}
diff --git a/src/main/java/org/fogbowcloud/manager/occi/instance/Instance.java b/src/main/java/org/fogbowcloud/manager/occi/instance/Instance.java
index 4f8ca300..02e77497 100644
--- a/src/main/java/org/fogbowcloud/manager/occi/instance/Instance.java
+++ b/src/main/java/org/fogbowcloud/manager/occi/instance/Instance.java
@@ -13,6 +13,7 @@ public class Instance {
public static final String PREFIX_DEFAULT_INSTANCE = "X-OCCI-Location: ";
public static final String SSH_PUBLIC_ADDRESS_ATT = "org.fogbowcloud.request.ssh-public-address";
+ public static final String SSH_USERNAME_ATT = "org.fogbowcloud.request.ssh-username";
private static final String PREFIX_DEFAULT_ATTRIBUTE = "X-OCCI-Attribute: ";
private static final String CATEGORY = "Category:";
diff --git a/src/main/java/org/fogbowcloud/manager/occi/request/Request.java b/src/main/java/org/fogbowcloud/manager/occi/request/Request.java
index 23bbf1af..6729050e 100644
--- a/src/main/java/org/fogbowcloud/manager/occi/request/Request.java
+++ b/src/main/java/org/fogbowcloud/manager/occi/request/Request.java
@@ -48,6 +48,11 @@ public Request(String id, Token federationToken, Token localToken,
this.dateUtils = dateUtils;
setState(RequestState.OPEN);
}
+
+ public Request(Request request) {
+ this(request.getId(), request.getFederationToken(), request.getLocalToken(), request.getCategories(),
+ request.getxOCCIAtt(), request.isLocal, request.getRequestingMemberId());
+ }
public List getCategories() {
if (categories == null) {
@@ -199,4 +204,5 @@ public boolean isExpired() {
long now = new DateUtils().currentTimeMillis();
return expirationDate.getTime() < now;
}
+
}
\ No newline at end of file
diff --git a/src/main/java/org/fogbowcloud/manager/xmpp/ManagerPacketHelper.java b/src/main/java/org/fogbowcloud/manager/xmpp/ManagerPacketHelper.java
index 5afca3c7..7d539a4f 100644
--- a/src/main/java/org/fogbowcloud/manager/xmpp/ManagerPacketHelper.java
+++ b/src/main/java/org/fogbowcloud/manager/xmpp/ManagerPacketHelper.java
@@ -3,7 +3,6 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -15,7 +14,6 @@
import org.dom4j.Element;
import org.fogbowcloud.manager.core.AsynchronousRequestCallback;
import org.fogbowcloud.manager.core.model.FederationMember;
-import org.fogbowcloud.manager.core.model.Flavor;
import org.fogbowcloud.manager.core.model.ResourcesInfo;
import org.fogbowcloud.manager.occi.core.Category;
import org.fogbowcloud.manager.occi.core.ErrorType;
@@ -54,14 +52,8 @@ public static void iAmAlive(ResourcesInfo resourcesInfo, String rendezvousAddres
statusEl.addElement("cpu-inuse").setText(resourcesInfo.getCpuInUse());
statusEl.addElement("mem-idle").setText(resourcesInfo.getMemIdle());
statusEl.addElement("mem-inuse").setText(resourcesInfo.getMemInUse());
- List flavours = resourcesInfo.getFlavors();
- for (Flavor f : flavours) {
- Element flavorElement = statusEl.addElement("flavor");
- flavorElement.addElement("name").setText(f.getName());
- flavorElement.addElement("cpu").setText(f.getCpu());
- flavorElement.addElement("mem").setText(f.getMem());
- flavorElement.addElement("capacity").setText(f.getCapacity().toString());
- }
+ statusEl.addElement("instances-idle").setText(resourcesInfo.getInstancesIdle());
+ statusEl.addElement("instances-inuse").setText(resourcesInfo.getInstancesInUse());
packetSender.syncSendPacket(iq);
}
@@ -122,52 +114,44 @@ private static ArrayList getMembersFromIQ(IQ responseFromWhoIs
Attribute id = itemEl.attribute("id");
Element statusEl = itemEl.element("status");
- String cpuIdle = statusEl.element("cpu-idle").getText();
- String cpuInUse = statusEl.element("cpu-inuse").getText();
- String memIdle = statusEl.element("mem-idle").getText();
- String memInUse = statusEl.element("mem-inuse").getText();
-
- List flavoursList = new LinkedList();
- Iterator flavourIterator = statusEl.elementIterator("flavor");
- while (flavourIterator.hasNext()) {
- Element flavour = (Element) flavourIterator.next();
- String name = flavour.element("name").getText();
- String cpu = flavour.element("cpu").getText();
- String mem = flavour.element("mem").getText();
- int capacity = Integer.parseInt(flavour.element("capacity").getText());
- Flavor flavor = new Flavor(name, cpu, mem, capacity);
- flavoursList.add(flavor);
- }
+ String cpuIdle = statusEl.elementText("cpu-idle");
+ String cpuInUse = statusEl.elementText("cpu-inuse");
+ String memIdle = statusEl.elementText("mem-idle");
+ String memInUse = statusEl.elementText("mem-inuse");
+ String instancesIdle = statusEl.elementText("instances-idle");
+ String instancesInUse = statusEl.elementText("instances-inuse");
ResourcesInfo resources = new ResourcesInfo(id.getValue(), cpuIdle, cpuInUse, memIdle,
- memInUse, flavoursList);
+ memInUse, instancesIdle, instancesInUse);
FederationMember item = new FederationMember(resources);
aliveItems.add(item);
}
return aliveItems;
}
- public static void asynchronousRemoteRequest(Request request, String memberAddress,
- Token userFederationToken, AsyncPacketSender packetSender, final AsynchronousRequestCallback callback) {
+ public static void asynchronousRemoteRequest(String requestId, List categories,
+ Map xOCCIAttr, String memberAddress,
+ Token userFederationToken, AsyncPacketSender packetSender,
+ final AsynchronousRequestCallback callback) {
IQ iq = new IQ();
- iq.setID(request.getId());
+ iq.setID(requestId);
iq.setTo(memberAddress);
iq.setType(Type.set);
Element queryEl = iq.getElement().addElement("query",
ManagerXmppComponent.REQUEST_NAMESPACE);
- for (Category category : request.getCategories()) {
+ for (Category category : categories) {
Element categoryEl = queryEl.addElement("category");
categoryEl.addElement("class").setText(category.getCatClass());
categoryEl.addElement("term").setText(category.getTerm());
categoryEl.addElement("scheme").setText(category.getScheme());
}
- for (Entry xOCCIEntry : request.getxOCCIAtt().entrySet()) {
+ for (Entry xOCCIEntry : xOCCIAttr.entrySet()) {
Element attributeEl = queryEl.addElement("attribute");
attributeEl.addAttribute("var", xOCCIEntry.getKey());
attributeEl.addElement("value").setText(xOCCIEntry.getValue());
}
Element requestEl = queryEl.addElement("request");
- requestEl.addElement("id").setText(request.getId());
+ requestEl.addElement("id").setText(requestId);
if (userFederationToken != null) {
Element tokenEl = queryEl.addElement("token");
diff --git a/src/test/java/org/fogbowcloud/manager/core/TestForwardedToken.java b/src/test/java/org/fogbowcloud/manager/core/TestForwardedToken.java
index 3dab75dc..ba6b2942 100644
--- a/src/test/java/org/fogbowcloud/manager/core/TestForwardedToken.java
+++ b/src/test/java/org/fogbowcloud/manager/core/TestForwardedToken.java
@@ -36,7 +36,8 @@ public void testTokenBeingForwarded() {
new HashMap(), true, DefaultDataTestHelper.LOCAL_MANAGER_COMPONENT_URL);
request1.setState(RequestState.OPEN);
- ManagerPacketHelper.asynchronousRemoteRequest(request1, "member1", new Token("accessId", "user",
+ ManagerPacketHelper.asynchronousRemoteRequest(request1.getId(), request1.getCategories(),
+ request1.getxOCCIAtt(), "member1", new Token("accessId", "user",
null, null), packetSender, null);
Mockito.verify(packetSender).sendPacket(Mockito.argThat(new ArgumentMatcher() {
@@ -63,7 +64,8 @@ public void testTokenNotBeingForwarded() {
new HashMap(), true, DefaultDataTestHelper.LOCAL_MANAGER_COMPONENT_URL);
request1.setState(RequestState.OPEN);
- ManagerPacketHelper.asynchronousRemoteRequest(request1, "member1", null, packetSender, null);
+ ManagerPacketHelper.asynchronousRemoteRequest(request1.getId(), request1.getCategories(),
+ request1.getxOCCIAtt(), "member1", null, packetSender, null);
Mockito.verify(packetSender).sendPacket(Mockito.argThat(new ArgumentMatcher() {
@Override
diff --git a/src/test/java/org/fogbowcloud/manager/core/TestManagerController.java b/src/test/java/org/fogbowcloud/manager/core/TestManagerController.java
index 997e0103..e448613d 100644
--- a/src/test/java/org/fogbowcloud/manager/core/TestManagerController.java
+++ b/src/test/java/org/fogbowcloud/manager/core/TestManagerController.java
@@ -1,5 +1,8 @@
package org.fogbowcloud.manager.core;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
@@ -9,6 +12,12 @@
import java.util.List;
import java.util.Map;
+import javax.mail.MessagingException;
+
+import net.schmizz.sshj.connection.channel.direct.Session.Command;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.IOUtils;
import org.dom4j.Element;
import org.fogbowcloud.manager.core.model.DateUtils;
import org.fogbowcloud.manager.core.model.FederationMember;
@@ -19,6 +28,7 @@
import org.fogbowcloud.manager.core.plugins.IdentityPlugin;
import org.fogbowcloud.manager.core.plugins.openstack.KeystoneIdentityPlugin;
import org.fogbowcloud.manager.core.plugins.openstack.OpenStackOCCIComputePlugin;
+import org.fogbowcloud.manager.core.plugins.util.SshHelper;
import org.fogbowcloud.manager.core.util.DefaultDataTestHelper;
import org.fogbowcloud.manager.core.util.ManagerTestHelper;
import org.fogbowcloud.manager.occi.core.Category;
@@ -116,7 +126,7 @@ public void testSubmitLocalUserRequests() throws InterruptedException {
@SuppressWarnings("unchecked")
@Test
public void testSubmitFederationUserRequests() throws InterruptedException {
- ResourcesInfo resourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo resourcesInfo = new ResourcesInfo("", "", "", "", "", "");
resourcesInfo.setId(DefaultDataTestHelper.LOCAL_MANAGER_COMPONENT_URL);
ComputePlugin computePlugin = Mockito.mock(ComputePlugin.class);
@@ -172,7 +182,7 @@ public void testSubmitToGreenSitter() {
ComputePlugin computePlugin = Mockito.mock(ComputePlugin.class);
- ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", "", "");
localResourcesInfo.setId(DefaultDataTestHelper.LOCAL_MANAGER_COMPONENT_URL);
Mockito.when(
@@ -242,10 +252,10 @@ public Void answer(InvocationOnMock invocation) throws Throwable {
}
}).when(packetSender).addPacketCallback(Mockito.any(Packet.class), Mockito.any(PacketCallback.class));
- ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", "", "");
localResourcesInfo.setId(DefaultDataTestHelper.LOCAL_MANAGER_COMPONENT_URL);
- ResourcesInfo remoteResourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo remoteResourcesInfo = new ResourcesInfo("", "", "", "", "", "");
remoteResourcesInfo.setId(DefaultDataTestHelper.REMOTE_MANAGER_COMPONENT_URL);
ComputePlugin computePlugin = Mockito.mock(ComputePlugin.class);
@@ -301,10 +311,10 @@ public void testRemoveForwardedRequestAfterTimeout() throws InterruptedException
AsyncPacketSender packetSender = Mockito.mock(AsyncPacketSender.class);
managerController.setPacketSender(packetSender);
- ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", "", "");
localResourcesInfo.setId(DefaultDataTestHelper.LOCAL_MANAGER_COMPONENT_URL);
- ResourcesInfo remoteResourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo remoteResourcesInfo = new ResourcesInfo("", "", "", "", "", "");
remoteResourcesInfo.setId(DefaultDataTestHelper.REMOTE_MANAGER_COMPONENT_URL);
ComputePlugin computePlugin = Mockito.mock(ComputePlugin.class);
@@ -375,10 +385,10 @@ public Void answer(InvocationOnMock invocation) throws Throwable {
}
}).when(packetSender).addPacketCallback(Mockito.any(Packet.class), Mockito.any(PacketCallback.class));
- ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", "", "");
localResourcesInfo.setId(DefaultDataTestHelper.LOCAL_MANAGER_COMPONENT_URL);
- ResourcesInfo remoteResourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo remoteResourcesInfo = new ResourcesInfo("", "", "", "", "", "");
remoteResourcesInfo.setId(DefaultDataTestHelper.REMOTE_MANAGER_COMPONENT_URL);
ComputePlugin computePlugin = Mockito.mock(ComputePlugin.class);
@@ -444,10 +454,10 @@ public Void answer(InvocationOnMock invocation) throws Throwable {
}
}).when(packetSender).addPacketCallback(Mockito.any(Packet.class), Mockito.any(PacketCallback.class));
- ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", "", "");
localResourcesInfo.setId(DefaultDataTestHelper.LOCAL_MANAGER_COMPONENT_URL);
- ResourcesInfo remoteResourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo remoteResourcesInfo = new ResourcesInfo("", "", "", "", "", "");
remoteResourcesInfo.setId(DefaultDataTestHelper.REMOTE_MANAGER_COMPONENT_URL);
ComputePlugin computePlugin = Mockito.mock(ComputePlugin.class);
@@ -1569,6 +1579,7 @@ public void testPersistentRequestValidityPeriodInFuture() throws InterruptedExce
Assert.assertNull(requests.get(0).getProvidingMemberId());
}
+ @SuppressWarnings("unchecked")
@Test
public void testSubmitRequestForRemoteMemberValidation() {
ResourcesInfo resources = Mockito.mock(ResourcesInfo.class);
@@ -1809,9 +1820,9 @@ public void testGetFlavors() {
@Test
public void testGetAllowedFederationMembers() {
- ResourcesInfo resourcesInfoOne = new ResourcesInfo("id1","", "", "", "", null);
- ResourcesInfo resourcesInfoTwo = new ResourcesInfo("id2","", "", "", "", null);
- ResourcesInfo resourcesInfoThree = new ResourcesInfo("id3","", "", "", "", null);
+ ResourcesInfo resourcesInfoOne = new ResourcesInfo("id1","", "", "", "", "", "");
+ ResourcesInfo resourcesInfoTwo = new ResourcesInfo("id2","", "", "", "", "", "");
+ ResourcesInfo resourcesInfoThree = new ResourcesInfo("id3","", "", "", "", "", "");
List listMembers = new ArrayList();
listMembers.add(new FederationMember(resourcesInfoOne));
@@ -1826,9 +1837,9 @@ public void testGetAllowedFederationMembers() {
@Test
public void testGetAllowedFederationMembersWithRequirements() {
- ResourcesInfo resourcesInfoOne = new ResourcesInfo("id1","", "", "", "", null);
- ResourcesInfo resourcesInfoTwo = new ResourcesInfo("id2","", "", "", "", null);
- ResourcesInfo resourcesInfoThree = new ResourcesInfo("id3","", "", "", "", null);
+ ResourcesInfo resourcesInfoOne = new ResourcesInfo("id1","", "", "", "", "", "");
+ ResourcesInfo resourcesInfoTwo = new ResourcesInfo("id2","", "", "", "", "", "");
+ ResourcesInfo resourcesInfoThree = new ResourcesInfo("id3","", "", "", "", "", "");
List listMembers = new ArrayList();
listMembers.add(new FederationMember(resourcesInfoOne));
@@ -1886,10 +1897,10 @@ public void testInstanceIsNotBeingUsedButRequestWasForwarded(){
AsyncPacketSender packetSender = Mockito.mock(AsyncPacketSender.class);
managerController.setPacketSender(packetSender);
- ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo localResourcesInfo = new ResourcesInfo("", "", "", "", "", "");
localResourcesInfo.setId(DefaultDataTestHelper.LOCAL_MANAGER_COMPONENT_URL);
- ResourcesInfo remoteResourcesInfo = new ResourcesInfo("", "", "", "", null);
+ ResourcesInfo remoteResourcesInfo = new ResourcesInfo("", "", "", "", "", "");
remoteResourcesInfo.setId(DefaultDataTestHelper.REMOTE_MANAGER_COMPONENT_URL);
ComputePlugin computePlugin = Mockito.mock(ComputePlugin.class);
@@ -2213,7 +2224,370 @@ public void testGarbageCollectorWithServedRequest() {
}
@Test
- public void testPreemption(){
+ @SuppressWarnings("unchecked")
+ public void testSSHKeyReplacementWhenOriginalRequestHasPublicKey()
+ throws FileNotFoundException, IOException, MessagingException {
+ Map extraProperties = new HashMap();
+ extraProperties.put(ConfigurationConstants.SSH_PUBLIC_KEY_PATH,
+ DefaultDataTestHelper.LOCAL_MANAGER_SSH_PUBLIC_KEY_PATH);
+ ManagerController localManagerController =
+ managerTestHelper.createDefaultManagerController(extraProperties);
+ ManagerController spiedManageController = Mockito.spy(localManagerController);
+ String remoteRequestId = "id1";
+
+ SshHelper sshHelper = createFakeSSHHelper();
+ Mockito.doReturn(sshHelper).when(spiedManageController).createSshHelper();
+
+ Map newXOCCIAttr = new HashMap(this.xOCCIAtt);
+ ArrayList categories = new ArrayList();
+ final Category publicKeyCategory = new Category(RequestConstants.PUBLIC_KEY_TERM,
+ RequestConstants.CREDENTIALS_RESOURCE_SCHEME, RequestConstants.MIXIN_CLASS);
+ categories.add(publicKeyCategory);
+ newXOCCIAttr.put(RequestAttribute.DATA_PUBLIC_KEY.getValue(), "public-key");
+
+ ComputePlugin computePlugin = Mockito.mock(ComputePlugin.class);
+ String newInstanceId = "newinstanceid";
+ Mockito.when(
+ computePlugin.requestInstance(Mockito.any(Token.class),
+ Mockito.anyList(), Mockito.anyMap(), Mockito.anyString())).thenReturn(newInstanceId);
+ spiedManageController.setComputePlugin(computePlugin);
+
+ Request servedRequest = new Request(remoteRequestId, managerTestHelper.getDefaultFederationToken(),
+ managerTestHelper.getDefaultLocalToken(), categories,
+ newXOCCIAttr, true,
+ DefaultDataTestHelper.REMOTE_MANAGER_COMPONENT_URL);
+ servedRequest.setState(RequestState.FULFILLED);
+ servedRequest.setInstanceId(newInstanceId);
+ servedRequest.setProvidingMemberId(DefaultDataTestHelper.LOCAL_MANAGER_COMPONENT_URL);
+
+ Instance instance = new Instance(newInstanceId);
+ instance.addAttribute(Instance.SSH_PUBLIC_ADDRESS_ATT, "127.0.0.1:5555");
+ instance.addAttribute(Instance.SSH_USERNAME_ATT, "fogbow");
+
+ Mockito.when(computePlugin.getInstance(Mockito.any(Token.class),
+ Mockito.eq(newInstanceId))).thenReturn(instance);
+
+ spiedManageController.createInstanceWithFederationUser(servedRequest);
+
+ final String localManagerPublicKeyData = IOUtils.toString(new FileInputStream(
+ new File(DefaultDataTestHelper.LOCAL_MANAGER_SSH_PUBLIC_KEY_PATH)));
+
+ Mockito.verify(computePlugin).requestInstance(Mockito.any(Token.class),
+ Mockito.argThat(new ArgumentMatcher>() {
+
+ @Override
+ public boolean matches(Object argument) {
+ List categories = (List) argument;
+ return !categories.contains(publicKeyCategory);
+ }
+ }), Mockito.argThat(new ArgumentMatcher