Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don’t worry, you can still create the pull request.
  • 8 commits
  • 19 files changed
  • 0 commit comments
  • 1 contributor
Showing with 1,112 additions and 16 deletions.
  1. +1 −0  service-api/java/source/src/org/nimbustools/api/_repr/vm/_Schedule.java
  2. +10 −0 service-api/java/source/src/org/nimbustools/api/defaults/repr/vm/DefaultSchedule.java
  3. +1 −0  service-api/java/source/src/org/nimbustools/api/repr/vm/Schedule.java
  4. +112 −0 service/service/java/source/etc/workspace-service/backfill.conf
  5. +10 −0 service/service/java/source/etc/workspace-service/other/main.conflocator.xml
  6. +31 −0 service/service/java/source/etc/workspace-service/other/main.xml
  7. +1 −0  service/service/java/source/etc/workspace-service/other/resource-locator-ACTIVE.xml
  8. +1 −0  service/service/java/source/etc/workspace-service/other/resource-locator-default.xml
  9. +484 −0 service/service/java/source/src/org/globus/workspace/Backfill.java
  10. +65 −0 service/service/java/source/src/org/globus/workspace/BackfillTimer.java
  11. +51 −7 service/service/java/source/src/org/globus/workspace/creation/defaults/DefaultCreation.java
  12. +11 −1 service/service/java/source/src/org/globus/workspace/manager/DelegatingManager.java
  13. +3 −1 service/service/java/source/src/org/globus/workspace/scheduler/Scheduler.java
  14. +85 −0 service/service/java/source/src/org/globus/workspace/scheduler/defaults/BackfillNode.java
  15. +50 −4 service/service/java/source/src/org/globus/workspace/scheduler/defaults/DefaultSchedulerAdapter.java
  16. +157 −1 service/service/java/source/src/org/globus/workspace/scheduler/defaults/DefaultSlotManagement.java
  17. +15 −2 service/service/java/source/src/org/globus/workspace/scheduler/defaults/NodeRequest.java
  18. +5 −0 service/service/java/source/src/org/globus/workspace/scheduler/defaults/SlotManagement.java
  19. +19 −0 service/service/java/source/src/org/globus/workspace/scheduler/defaults/pilot/PilotSlotManagement.java
View
1  service-api/java/source/src/org/nimbustools/api/_repr/vm/_Schedule.java
@@ -25,4 +25,5 @@
public void setStartTime(Calendar startTime);
public void setDurationSeconds(int durationSeconds);
public void setDestructionTime(Calendar destructionTime);
+ public void setBackfillReq(boolean backfillReq);
}
View
10 service-api/java/source/src/org/nimbustools/api/defaults/repr/vm/DefaultSchedule.java
@@ -37,6 +37,7 @@
private Calendar startTime;
private int durationSeconds = -1;
private Calendar destructionTime;
+ private boolean backfillReq = false;
// -------------------------------------------------------------------------
@@ -55,6 +56,10 @@ public Calendar getDestructionTime() {
return this.destructionTime;
}
+ public boolean getBackfillReq() {
+ return this.backfillReq;
+ }
+
// -------------------------------------------------------------------------
// implements org.nimbustools.api._repr.vm._Schedule
@@ -72,6 +77,10 @@ public void setDestructionTime(Calendar destructionTime) {
this.destructionTime = destructionTime;
}
+ public void setBackfillReq(boolean backfillReq) {
+ this.backfillReq = backfillReq;
+ }
+
// -------------------------------------------------------------------------
// DEBUG STRING
@@ -82,6 +91,7 @@ public String toString() {
"startTime=" + calendarStr(this.startTime) +
", durationSeconds='" + this.durationSeconds +
"', destructionTime='" + calendarStr(this.destructionTime) +
+ ", backfillReq=" + this.backfillReq +
"'}";
}
View
1  service-api/java/source/src/org/nimbustools/api/repr/vm/Schedule.java
@@ -23,4 +23,5 @@
public Calendar getStartTime();
public int getDurationSeconds();
public Calendar getDestructionTime();
+ public boolean getBackfillReq();
}
View
112 service/service/java/source/etc/workspace-service/backfill.conf
@@ -0,0 +1,112 @@
+################################################################################
+#
+# This file is used for configuring VM backfill deployment on idle VMM nodes.
+#
+# The intent of backfill is to provide a Nimbus cloud with the ability to
+# deploy a generic VM on idle nodes. Such a VM could be configured with a
+# service like Condor, allowing the VM to contribute cycles to some other
+# purpose instead of wasting cycles on idle cloud nodes. When a user request is
+# recieved the VM is terminated immediately and the user VM is deployed.
+#
+# NOTE: Backfill must be configured and run by the Nimbus administrator. It is
+# not currently a feature that users can leverage directly.
+#
+# The VM used by backfill (and the services inside of it) must be able to
+# handle a hard shutdown. A hard shutdown is used to minimize the turn-
+# around time for responding to user requests.
+#
+################################################################################
+
+
+# BACKFILL
+#
+# If you would like to use backfill, you can enable it here.
+#
+# The default is disabled.
+
+backfill.disabled=true
+
+
+# MAX INSTANCES
+#
+# Max instances is the maximum number of VM instances that backfill will deploy
+# if it is enabled. If there is not enough space on the cloud for the maximum
+# number of instances it will deploy as many as it can. For example, if max
+# instances is set to 12 on a 16 node cloud but there are 10 active user VMs
+# then backfill will still launch 6 backfill nodes.
+#
+# If max instances is set to 0 then backfill will use all idle VMMs.
+#
+# The default is 0.
+
+max.instances=0
+
+
+# DISK IMAGE
+#
+# The disk image is currently a pointer to the image file on the VMM nodes.
+# The image must be in the same location on all nodes. Also, the image must
+# be copied there manually.
+
+disk.image=/usr/local/myawesomeimage.img
+
+
+# INSTANCE MEMORY
+#
+# The instance memory is the amount of memory (in MB) that the backfill image
+# will use.
+
+memory.MB=64
+
+
+# INSTANCE DURATION
+#
+# Instance duration is the amount of time (in seconds) that the backfill instance
+# will potentially be active. Obviously, the nature of backfill instances
+# necessitates that when a user request arrives the backfill instance will be
+# preempted, regardless of this setting. When the duration has elapsed the
+# instance will be terminated. It is possible that another backfill instance
+# will be dispatched almost immediately after the previous one was terminated.
+#
+# The default duration is one week.
+
+duration.seconds=604800
+
+
+# INSTANCE TERMINATION POLICY
+#
+# The instance termination policy specifies the mechanism that will be used
+# when selecting a backfill VM to terminate in order to satisfy a user
+# request.
+#
+# Options:
+#
+# - ANY this will pick any VM to terminate, it doesn't consider
+# any factors (such as time running) when deciding, it
+# simply grabs the next VM instance out of the hash table
+#
+# - MOST_RECENT this will pick the VM that has been running for the least
+# amount of time
+#
+# The default is MOST_RECENT.
+
+termination.policy=MOST_RECENT
+
+
+# INSTANCE RETRY PERIOD
+#
+# Instance retry period is the amount of time (in seconds) the backfill timer
+# waits in between attempts to launch backfill VMs on available cloud nodes.
+# This timer is restarted (and hence, it attempts to launch backfill VMs)
+# whenever a user VM is terminated (thus freeing a node for backfill).
+#
+# The default is five minutes.
+
+retry.period=300
+
+
+# NETWORK
+#
+# Set the network to public or private.
+
+network=public
View
10 service/service/java/source/etc/workspace-service/other/main.conflocator.xml
@@ -73,6 +73,16 @@
value="$ACCOUNTING{" />
</bean>
+ <bean id="backfillSettings"
+ class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+
+ <property name="location"
+ value="$NIMBUS_HOME/services/etc/nimbus/workspace-service/backfill.conf" />
+ <property name="placeholderPrefix"
+ value="$BACKFILL{" />
+
+ </bean>
+
<bean id="sshSettings"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
View
31 service/service/java/source/etc/workspace-service/other/main.xml
@@ -20,6 +20,7 @@
<constructor-arg ref="nimbus-repr.ReprFactory"/>
<constructor-arg ref="nimbus-rm.persistence.DataConvert"/>
<constructor-arg ref="nimbus-rm.loglevels" />
+ <constructor-arg ref="nimbus-rm.backfill" />
<property name="accounting"
ref="nimbus-rm.accounting" />
@@ -90,6 +91,7 @@
<constructor-arg ref="nimbus-rm.home.cosched" />
<constructor-arg ref="other.timerManager" />
<constructor-arg ref="nimbus-rm.loglevels" />
+ <constructor-arg ref="nimbus-rm.backfill" />
<property name="accountingEventAdapter"
ref="nimbus-rm.accounting" />
@@ -253,6 +255,34 @@
</bean>
+ <bean id="nimbus-rm.backfill"
+ class="org.globus.workspace.Backfill"
+ init-method="validate">
+
+ <constructor-arg ref="nimbus-repr.ReprFactory"/>
+ <constructor-arg ref="nimbus-rm.PathConfigs" />
+ <constructor-arg ref="other.timerManager" />
+ <constructor-arg ref="nimbus-rm.scheduler.SlotManagement" />
+
+ <property name="backfillDisabled"
+ value="$BACKFILL{backfill.disabled}" />
+ <property name="maxInstances"
+ value="$BACKFILL{max.instances}" />
+ <property name="diskImage"
+ value="$BACKFILL{disk.image}" />
+ <property name="memoryMB"
+ value="$BACKFILL{memory.MB}" />
+ <property name="durationSeconds"
+ value="$BACKFILL{duration.seconds}" />
+ <property name="terminationPolicy"
+ value="$BACKFILL{termination.policy}" />
+ <property name="retryPeriod"
+ value="$BACKFILL{retry.period}" />
+ <property name="network"
+ value="$BACKFILL{network}" />
+
+ </bean>
+
<!-- ===================================================================
org.globus.workspace.network.* interfaces
@@ -525,6 +555,7 @@
<constructor-arg ref="nimbus-rm.service.binding.GlobalPolicies" />
<constructor-arg ref="nimbus-rm.persistence.DataConvert" />
<constructor-arg ref="nimbus-rm.loglevels" />
+ <constructor-arg ref="nimbus-rm.backfill" />
View
1  service/service/java/source/etc/workspace-service/other/resource-locator-ACTIVE.xml
@@ -21,6 +21,7 @@
<constructor-arg ref="nimbus-rm.persistence.PersistenceAdapter" />
<constructor-arg ref="nimbus-rm.loglevels" />
+ <constructor-arg ref="nimbus-rm.PathConfigs" />
<!-- set after object creation time to avoid circular dep with home -->
<property name="home" ref="nimbus-rm.home.instance" />
View
1  service/service/java/source/etc/workspace-service/other/resource-locator-default.xml
@@ -21,6 +21,7 @@
<constructor-arg ref="nimbus-rm.persistence.PersistenceAdapter" />
<constructor-arg ref="nimbus-rm.loglevels" />
+ <constructor-arg ref="nimbus-rm.PathConfigs" />
<!-- set after object creation time to avoid circular dep with home -->
<property name="home" ref="nimbus-rm.home.instance" />
View
484 service/service/java/source/src/org/globus/workspace/Backfill.java
@@ -0,0 +1,484 @@
+/*
+ * Copyright 1999-2010 University of Chicago
+ *
+ * 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.
+ */
+
+package org.globus.workspace;
+
+import org.globus.workspace.manager.DelegatingManager;
+import org.globus.workspace.scheduler.defaults.SlotManagement;
+
+import org.nimbustools.api._repr._Caller;
+import org.nimbustools.api._repr._CreateRequest;
+import org.nimbustools.api._repr.vm._NIC;
+import org.nimbustools.api._repr.vm._RequiredVMM;
+import org.nimbustools.api._repr.vm._ResourceAllocation;
+import org.nimbustools.api._repr.vm._Schedule;
+import org.nimbustools.api._repr.vm._VMFile;
+import org.nimbustools.api.repr.Caller;
+import org.nimbustools.api.repr.CreateRequest;
+import org.nimbustools.api.repr.CreateResult;
+import org.nimbustools.api.repr.vm.NIC;
+import org.nimbustools.api.repr.vm.ResourceAllocation;
+import org.nimbustools.api.repr.vm.VMFile;
+import org.nimbustools.api.repr.ReprFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Date;
+import java.net.URI;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileNotFoundException;
+
+import commonj.timers.Timer;
+import commonj.timers.TimerManager;
+
+public class Backfill {
+
+ private static final Log logger =
+ LogFactory.getLog(Backfill.class.getName());
+
+ protected final ReprFactory repr;
+ protected final PathConfigs pathConfigs;
+ protected final TimerManager timerManager;
+ protected final SlotManagement slotManager;
+ protected DelegatingManager manager;
+
+ private boolean backfillDisabled;
+ private int maxInstances;
+ private int curNumInstances = 0;
+ private String diskImage;
+ private int memoryMB;
+ private int durationSeconds;
+ private String terminationPolicy;
+ private int retryPeriod;
+ private String network;
+ private File backfillReqFile;
+ private Timer backfillTimer = null;
+
+ public Backfill(ReprFactory reprFactory,
+ PathConfigs pathConfigs,
+ TimerManager timerManager,
+ SlotManagement slotManager) {
+
+ if (reprFactory == null) {
+ throw new IllegalArgumentException("reprFactory may not be null");
+ }
+ this.repr = reprFactory;
+
+ if (pathConfigs == null) {
+ throw new IllegalArgumentException("pathConfigs may not be null");
+ }
+ this.pathConfigs = pathConfigs;
+ this.backfillReqFile =
+ new File(this.pathConfigs.getLocalTempDirPath() +
+ "/backfill.request");
+
+ if (timerManager == null) {
+ throw new IllegalArgumentException("timerManager may not be null");
+ }
+ this.timerManager = timerManager;
+
+ if (slotManager == null) {
+ throw new IllegalArgumentException("slotManager may not be null");
+ }
+ this.slotManager = slotManager;
+ }
+
+ public boolean getBackfillDisabled() {
+ return this.backfillDisabled;
+ }
+
+ public int getMaxInstances() {
+ return this.maxInstances;
+ }
+
+ public int getCurNumInstances() {
+ return this.curNumInstances;
+ }
+
+ public String getDiskImage() {
+ return this.diskImage;
+ }
+
+ public int getMemoryMB() {
+ return this.memoryMB;
+ }
+
+ public int getDurationSeconds() {
+ return this.durationSeconds;
+ }
+
+ public String getTerminationPolicy() {
+ return this.terminationPolicy;
+ }
+
+ public int getRetryPeriod() {
+ return this.retryPeriod;
+ }
+
+ public String getNetwork() {
+ return this.network;
+ }
+
+ public void setBackfillDisabled(boolean backfillDisabled) {
+ this.backfillDisabled = backfillDisabled;
+ }
+
+ public void setMaxInstances(int maxInstances) {
+ this.maxInstances = maxInstances;
+ }
+
+ public void addCurInstances(int num) {
+ this.curNumInstances += num;
+ }
+
+ public void subCurInstances(int num) {
+ this.curNumInstances -= num;
+ }
+
+ public void setDiskImage(String diskImage) {
+ this.diskImage = diskImage;
+ }
+
+ public void setMemoryMB(int memoryMB) {
+ this.memoryMB = memoryMB;
+ }
+
+ public void setDurationSeconds(int durationSeconds) {
+ this.durationSeconds = durationSeconds;
+ }
+
+ public void setTerminationPolicy(String terminationPolicy) {
+ this.terminationPolicy = terminationPolicy;
+ }
+
+ public void setNetwork(String network) {
+ this.network = network;
+ }
+
+ public void setRetryPeriod(int retryPeriod) {
+ this.retryPeriod = retryPeriod;
+ }
+
+ public void setDelegatingManager(DelegatingManager manager) {
+ this.manager = manager;
+ }
+
+ /**
+ * This method should be called on service startup. It is responsible for
+ * starting the backfill timer (if the backfill feature is enabled).
+ *
+ * It also checks to see if a persistence backfill file exists, and if the
+ * backfill configuration has changed. If the backfill configuration has
+ * changed then it cancels the previous backfill request and submits a new
+ * one.
+ */
+ public void initiateBackfill() {
+
+ if (this.backfillDisabled == false) {
+ logger.debug("Backfill is enabled");
+
+ if (this.backfillReqFile.exists()) {
+ String curBackfillStr = buildCurBackfillReqStrB().toString();
+ String prevBackfillStr = readPrevBackfillReqStrB().toString();
+
+ if ((curBackfillStr.compareTo(prevBackfillStr)) == 0) {
+ logger.debug("Current and previous backfill requests " +
+ "match");
+ } else {
+ logger.debug("The current backfill request doesn't " +
+ "match the previous backfill request");
+
+ this.cancelBackfillRequest();
+ this.writeCurBackfillReq();
+
+ logger.debug("New backfill request file written.");
+ }
+ } else {
+ this.writeCurBackfillReq();
+ }
+
+ logger.debug("Launching backfill timer.");
+ this.launchBackfillTimer();
+ logger.debug("Backfill timer launched.");
+
+ } else {
+ logger.info("Backfill is disabled");
+ }
+ }
+
+ public void launchBackfillTimer() {
+
+ if (this.backfillDisabled == true) {
+ return;
+ }
+
+ if (this.backfillTimer != null) {
+ this.backfillTimer.cancel();
+ }
+
+ BackfillTimer backfillTimer;
+ backfillTimer = new BackfillTimer(this);
+ Date backfillStart = new Date();
+ this.backfillTimer = this.timerManager.schedule(backfillTimer,
+ backfillStart,
+ this.retryPeriod * 1000);
+ }
+
+ public void cancelBackfillRequest() {
+ logger.info("Cancelling backfill request");
+
+ try {
+ this.backfillTimer.cancel();
+ } catch (Exception e) {
+ logger.debug("Failed to kill backfill timer, error: " +
+ e.getMessage());
+ }
+
+ try {
+ this.backfillReqFile.delete();
+ } catch (Exception e) {
+ logger.debug("Problem deleting backfill request file: " +
+ e.getMessage());
+ }
+
+ logger.debug("Backfill request cancelled.");
+ }
+
+ // Returns the number of nodes successfully terminated
+ public int terminateBackfillNode(int numNodes) {
+
+ int vmid;
+ int count = 0;
+ int successfulTerminations = 0;
+
+ while (count < numNodes) {
+ if ((this.terminationPolicy.compareTo("ANY")) == 0) {
+ logger.debug("Backfill is using the ANY policy");
+ vmid = this.slotManager.getBackfillVMID();
+ } else {
+ logger.debug("Backfill is using the MOST_RECENT policy");
+ vmid = this.slotManager.getMostRecentBackfillVMID();
+ }
+
+ if (vmid != -1) {
+ String vmidStr = Integer.toString(vmid);
+ logger.debug("Terminating backfill node with ID: " + vmidStr);
+
+ Caller caller = this.getBackfillCaller();
+ try {
+ this.manager.trash(vmidStr, 0, caller);
+ this.subCurInstances(1);
+ successfulTerminations += 1;
+ } catch (Exception e) {
+ logger.error("Problem terminating backfill node: " +
+ e.getMessage());
+ }
+ } else {
+ logger.debug("No backfill VM to terminate");
+ }
+
+ count += 1;
+ }
+
+ return successfulTerminations;
+ }
+
+ /**
+ * This attempts to launch a new backfill node.
+ * It should only be called by the backfill timer (ugh,
+ * should really be changed so ONLY that can happen).
+ * If backfill nodes should be launched (at some place else
+ * in the code) then the backfill timer should simply be relaunched
+ * (via the launchBackfillTimer method in this class)
+ * as it will attempt to launch backfill nodes. The timer is what
+ * respects the max backfill instances configuration value, and if
+ * backfill is disabled then it won't be relaunched.
+ */
+ public void createBackfillNode() throws Exception {
+
+ CreateRequest req = this.getBackfillRequest("BACKFILL_REQUEST");
+ logger.debug("Backfill create request:\n" + req.toString());
+
+ Caller caller = this.getBackfillCaller();
+ logger.debug("Backfill caller:\n" + caller.toString());
+
+ CreateResult create = this.manager.create(req, caller);
+ }
+
+ /**
+ * writeCurBackfillReq, readPrevBackfillReqStrB, and
+ * buildCurBackfillReqStrB are simply a hack to support persistence
+ * between service restarts or crashes. Ideally, they should become
+ * obsolete once the backfill feature is integrated with support for Spot
+ * Instances.
+ */
+ private void writeCurBackfillReq() {
+
+ if (this.backfillReqFile.exists()) {
+ logger.debug("Backfill request file already exists");
+ logger.debug("Skipping write to backfill request file");
+ } else {
+ logger.debug("Attempting to write backfill file:\n" +
+ this.backfillReqFile.toString());
+
+ try {
+ FileWriter backfillFW = new FileWriter(this.backfillReqFile);
+ BufferedWriter backfillBW = new BufferedWriter(backfillFW);
+
+ this.backfillReqFile.createNewFile();
+
+ backfillBW.write(this.buildCurBackfillReqStrB().toString());
+
+ backfillBW.close();
+ } catch (Exception e) {
+ logger.debug("Error creating and writing a new backfill " +
+ "request file: " + e.getMessage());
+ }
+ }
+ }
+
+ private StringBuilder readPrevBackfillReqStrB() {
+
+ StringBuilder prevBackfillStrB = new StringBuilder();
+
+ try {
+ logger.debug("Attempting to read backfill request file:\n" +
+ this.backfillReqFile.toString());
+
+ FileReader backfillFR = new FileReader(this.backfillReqFile);
+ BufferedReader backfillBR = new BufferedReader(backfillFR);
+ String line;
+
+ while (( line = backfillBR.readLine()) != null) {
+ prevBackfillStrB.append(line);
+ prevBackfillStrB.append("\n");
+ }
+
+ logger.debug("For the previous backfill request file," +
+ " we read:\n" + prevBackfillStrB.toString());
+
+ backfillBR.close();
+ } catch (FileNotFoundException e) {
+ logger.debug("Can't read a file that doesn't exist:\n" +
+ this.backfillReqFile.toString());
+ } catch (Exception e) {
+ logger.info("Unknown problem reading backfill request file: " +
+ e.getMessage());
+ }
+
+ return prevBackfillStrB;
+ }
+
+ private StringBuilder buildCurBackfillReqStrB() {
+
+ StringBuilder curBackfillReqStrB = new StringBuilder();
+
+ curBackfillReqStrB.append(Boolean.toString(this.backfillDisabled));
+ curBackfillReqStrB.append("\n");
+ curBackfillReqStrB.append(Integer.toString(this.maxInstances));
+ curBackfillReqStrB.append("\n");
+ curBackfillReqStrB.append(this.diskImage);
+ curBackfillReqStrB.append("\n");
+ curBackfillReqStrB.append(Integer.toString(this.memoryMB));
+ curBackfillReqStrB.append("\n");
+ curBackfillReqStrB.append(Integer.toString(this.durationSeconds));
+ curBackfillReqStrB.append("\n");
+ curBackfillReqStrB.append(this.network);
+ curBackfillReqStrB.append("\n");
+ curBackfillReqStrB.append(this.pathConfigs.getLocalTempDirPath());
+ curBackfillReqStrB.append("\n");
+
+ return curBackfillReqStrB;
+ }
+
+ private Caller getBackfillCaller() {
+ final _Caller caller = this.repr._newCaller();
+ caller.setIdentity("BACKFILL_CALLER");
+ return caller;
+ }
+
+ private CreateRequest getBackfillRequest(String name) throws Exception {
+
+ final _CreateRequest req = this.repr._newCreateRequest();
+ req.setName(name);
+
+ final _NIC nic = this.repr._newNIC();
+ nic.setNetworkName(this.network);
+ nic.setAcquisitionMethod(NIC.ACQUISITION_AllocateAndConfigure);
+ req.setRequestedNics(new _NIC[]{nic});
+
+ final _ResourceAllocation ra = this.repr._newResourceAllocation();
+ req.setRequestedRA(ra);
+ final _Schedule schedule = this.repr._newSchedule();
+ schedule.setDurationSeconds(this.durationSeconds);
+ schedule.setBackfillReq(true);
+ req.setRequestedSchedule(schedule);
+ ra.setNodeNumber(1);
+ ra.setMemory(this.memoryMB);
+ req.setShutdownType(CreateRequest.SHUTDOWN_TYPE_TRASH);
+ req.setInitialStateRequest(CreateRequest.INITIAL_STATE_RUNNING);
+
+ ra.setArchitecture(ResourceAllocation.ARCH_x86);
+ final _RequiredVMM reqVMM = this.repr._newRequiredVMM();
+ reqVMM.setType("Xen");
+ reqVMM.setVersions(new String[]{"3"});
+ req.setRequiredVMM(reqVMM);
+
+ final _VMFile file = this.repr._newVMFile();
+ file.setRootFile(true);
+ file.setBlankSpaceName(null);
+ file.setBlankSpaceSize(-1);
+ file.setURI(new URI("file://" + this.diskImage));
+ file.setMountAs("sda1");
+ file.setDiskPerms(VMFile.DISKPERMS_ReadWrite);
+ req.setVMFiles(new _VMFile[]{file});
+
+ return req;
+ }
+
+ public void validate() throws Exception {
+
+ logger.debug("validating");
+
+ if (this.maxInstances < 0) {
+ throw new Exception("maxInstances may not be less than 0");
+ }
+ if (this.diskImage == null) {
+ throw new Exception("diskImage may not be null");
+ }
+ if (this.memoryMB < 8) {
+ throw new Exception("memoryMB must be a reasonable value. " +
+ "Have you considered at least 64 MB?");
+ }
+ if (this.durationSeconds < 60) {
+ throw new Exception("durationSeconds must be 60 seconds " +
+ "or longer.");
+ }
+ if (this.retryPeriod < 1) {
+ throw new Exception("retryPeriod must be 1 or greater");
+ }
+ if (this.network == null) {
+ throw new Exception("network may not be null");
+ }
+
+ logger.debug("validated");
+ }
+}
View
65 service/service/java/source/src/org/globus/workspace/BackfillTimer.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 1999-2010 University of Chicago
+ *
+ * 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.
+ */
+
+package org.globus.workspace;
+
+import org.nimbustools.api.services.rm.ResourceRequestDeniedException;
+
+import commonj.timers.TimerListener;
+import commonj.timers.Timer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class BackfillTimer implements TimerListener {
+
+ private static final Log logger =
+ LogFactory.getLog(BackfillTimer.class.getName());
+
+ private final Backfill backfill;
+
+ public BackfillTimer(Backfill backfill) {
+ this.backfill = backfill;
+ }
+
+ public void timerExpired(Timer timer) {
+
+ final int maxInstances = this.backfill.getMaxInstances();
+ int curNumInstances = this.backfill.getCurNumInstances();
+
+ if (maxInstances == 0) {
+ curNumInstances = -1;
+ }
+ boolean wantMoreBackfill = true;
+ while((wantMoreBackfill == true) &&
+ (curNumInstances < maxInstances)) {
+ try {
+ this.backfill.createBackfillNode();
+ this.backfill.addCurInstances(1);
+ } catch (ResourceRequestDeniedException rDE) {
+ logger.info("Backfill launch failed. " +
+ "Looks like we're full.");
+ wantMoreBackfill = false;
+ } catch (Exception e) {
+ logger.error("BackfillTimer caught " +
+ "an exception: " + e.getMessage());
+ wantMoreBackfill = false;
+ }
+ if (maxInstances > 0) {
+ curNumInstances = this.backfill.getCurNumInstances();
+ }
+ }
+ }
+}
View
58 service/service/java/source/src/org/globus/workspace/creation/defaults/DefaultCreation.java
@@ -45,6 +45,7 @@
import org.globus.workspace.service.binding.vm.VirtualMachine;
import org.globus.workspace.service.binding.vm.VirtualMachineDeployment;
import org.globus.workspace.service.binding.vm.CustomizationNeed;
+import org.globus.workspace.Backfill;
import org.nimbustools.api._repr._CreateResult;
import org.nimbustools.api._repr._Advertised;
@@ -113,6 +114,8 @@
protected final Lager lager;
protected final DateFormat localFormat = DateFormat.getDateTimeInstance();
+ private final Backfill backfill;
+
protected AccountingEventAdapter accounting;
@@ -134,7 +137,8 @@ public DefaultCreation(LockManager lockManagerImpl,
PersistenceAdapter persistenceAdapter,
DataConvert dataConvertImpl,
TimerManager timerManagerImpl,
- Lager lagerImpl) {
+ Lager lagerImpl,
+ Backfill backfill) {
if (lockManagerImpl == null) {
throw new IllegalArgumentException("lockManager may not be null");
@@ -210,6 +214,11 @@ public DefaultCreation(LockManager lockManagerImpl,
throw new IllegalArgumentException("lagerImpl may not be null");
}
this.lager = lagerImpl;
+
+ if (backfill == null) {
+ throw new IllegalArgumentException("backfill may not be null");
+ }
+ this.backfill = backfill;
}
@@ -316,7 +325,36 @@ protected CreateResult create1(CreateRequest req, Caller caller)
ResourceRequestDeniedException,
SchedulingException {
- final VirtualMachine[] bound = this.binding.processRequest(req);
+ // We trigger backfill termination here just in case the network
+ // binding causes a ResourceRequestDeniedException (because there
+ // are no more available IP addresses, for instance)
+ VirtualMachine[] bound = null;
+ try {
+ bound = this.binding.processRequest(req);
+ } catch (ResourceRequestDeniedException e) {
+ logger.debug("Failed to reserve the resource: " + e.getMessage());
+ if (req.getRequestedSchedule().getBackfillReq() == false) {
+ logger.debug("The request isn't a backfill request");
+ logger.debug("Attempting to terminate backfill nodes");
+ boolean continueTerminateBackfill = true;
+ while (continueTerminateBackfill == true) {
+ try {
+ bound = this.binding.processRequest(req);
+ continueTerminateBackfill = false;
+ } catch (ResourceRequestDeniedException rDE) {
+ int numNodes = req.getRequestedRA().getNodeNumber();
+ if (this.backfill.terminateBackfillNode(numNodes) == 0) {
+ throw rDE;
+ } else {
+ continueTerminateBackfill = true;
+ }
+ }
+ }
+ } else {
+ throw e;
+ }
+ }
+
if (bound == null || bound.length == 0) {
throw new CreationException("no binding result but no binding " +
"error: illegal binding implementation");
@@ -330,10 +368,13 @@ protected CreateResult create1(CreateRequest req, Caller caller)
final Context context = req.getContext();
final String groupID = this.getGroupID(creatorID, bound.length);
final String coschedID = this.getCoschedID(req, creatorID);
+ final boolean backfillReq =
+ req.getRequestedSchedule().getBackfillReq();
// From this point forward an error requires backOutAllocations
try {
- return this.create2(bound, caller, context, groupID, coschedID);
+ return this.create2(bound, caller, context, groupID, coschedID,
+ backfillReq);
} catch (CoSchedulingException e) {
this.backoutBound(bound);
throw e;
@@ -414,7 +455,8 @@ protected CreateResult create2(VirtualMachine[] bindings,
Caller caller,
Context context,
String groupID,
- String coschedID)
+ String coschedID,
+ boolean backfillReq)
throws AuthorizationException,
CoSchedulingException,
@@ -444,7 +486,8 @@ protected CreateResult create2(VirtualMachine[] bindings,
bindings.length,
groupID,
coschedID,
- caller.getIdentity());
+ caller.getIdentity(),
+ backfillReq);
if (res == null) {
throw new SchedulingException("reservation is missing, illegal " +
@@ -506,7 +549,8 @@ protected Reservation scheduleImpl(VirtualMachine vm,
int numNodes,
String groupid,
String coschedid,
- String callerID)
+ String callerID,
+ boolean backfillReq)
throws SchedulingException,
ResourceRequestDeniedException {
@@ -528,7 +572,7 @@ protected Reservation scheduleImpl(VirtualMachine vm,
}
return this.scheduler.schedule(memory, duration, assocs, numNodes,
- groupid, coschedid, callerID);
+ groupid, coschedid, callerID, backfillReq);
}
View
12 service/service/java/source/src/org/globus/workspace/manager/DelegatingManager.java
@@ -21,6 +21,7 @@
import org.globus.workspace.PathConfigs;
import org.globus.workspace.Lager;
+import org.globus.workspace.Backfill;
import org.globus.workspace.accounting.AccountingReaderAdapter;
import org.globus.workspace.accounting.ElapsedAndReservedMinutes;
import org.globus.workspace.creation.Creation;
@@ -88,6 +89,7 @@
protected final ReprFactory repr;
protected final DataConvert dataConvert;
protected final Lager lager;
+ protected final Backfill backfill;
protected AccountingReaderAdapter accounting;
@@ -102,7 +104,8 @@ public DelegatingManager(Creation creationImpl,
WorkspaceCoschedHome coschedHome,
ReprFactory reprFactory,
DataConvert dataConvertImpl,
- Lager lagerImpl) {
+ Lager lagerImpl,
+ Backfill backfill) {
if (creationImpl == null) {
throw new IllegalArgumentException("creationImpl may not be null");
@@ -143,6 +146,11 @@ public DelegatingManager(Creation creationImpl,
throw new IllegalArgumentException("lagerImpl may not be null");
}
this.lager = lagerImpl;
+
+ if (backfill == null) {
+ throw new IllegalArgumentException("backfill may not be null");
+ }
+ this.backfill = backfill;
}
@@ -188,6 +196,8 @@ public String report() {
*/
public void recover_initialize() throws Exception {
this.home.recover_initialize();
+ this.backfill.setDelegatingManager(this);
+ this.backfill.initiateBackfill();
}
public void shutdownImmediately() {
View
4 service/service/java/source/src/org/globus/workspace/scheduler/Scheduler.java
@@ -43,6 +43,7 @@
* @param groupid group ID, can be null
* @param coschedid co-scheduling ID, can be null
* @param creatorDN creator's identifying DN, can be null
+ * @param backfillReq whether this is a backfill request
* @return reservation never null
* @throws ResourceRequestDeniedException will not grant
* @throws SchedulingException internal problem
@@ -53,7 +54,8 @@ public Reservation schedule(int memory,
int numNodes,
String groupid,
String coschedid,
- String creatorDN)
+ String creatorDN,
+ boolean backfillReq)
throws SchedulingException,
ResourceRequestDeniedException;
View
85 service/service/java/source/src/org/globus/workspace/scheduler/defaults/BackfillNode.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 1999-2010 University of Chicago
+ *
+ * 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.
+ */
+
+package org.globus.workspace.scheduler.defaults;
+
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.Date;
+
+public class BackfillNode implements Serializable {
+ private int vmid;
+ private Date startDate;
+ private String hostname;
+
+ public BackfillNode(int vmid,
+ Date startDate,
+ String hostname) {
+
+ this.vmid = vmid;
+
+ if (startDate == null) {
+ throw new IllegalArgumentException("startDate may not be null");
+ }
+ this.startDate = startDate;
+
+ if (hostname == null) {
+ throw new IllegalArgumentException("hostname may not be null");
+ }
+ this.hostname = hostname;
+ }
+
+ public int getVMID() {
+ return this.vmid;
+ }
+
+ public Date getStartDate() {
+ return this.startDate;
+ }
+
+ public String getHostname() {
+ return this.hostname;
+ }
+
+ public void setVMID(int vmid) {
+ this.vmid = vmid;
+ }
+
+ public void setStartDate(Date startDate) {
+ this.startDate = startDate;
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
+
+ public String toString() {
+ return "BackfillNode{vmid=" + Integer.toString(this.vmid) +
+ ", startDate=" + this.startDate.toString() +
+ ", hostname=" + this.hostname + "}";
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ }
+
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ }
+}
View
54 ...vice/java/source/src/org/globus/workspace/scheduler/defaults/DefaultSchedulerAdapter.java
@@ -30,6 +30,7 @@
import org.globus.workspace.service.WorkspaceHome;
import org.globus.workspace.service.binding.GlobalPolicies;
import org.globus.workspace.LockAcquisitionFailure;
+import org.globus.workspace.Backfill;
import org.nimbustools.api.services.rm.ResourceRequestDeniedException;
import org.nimbustools.api.services.rm.SchedulingException;
import org.nimbustools.api.services.rm.DoesNotExistException;
@@ -80,6 +81,7 @@
// see CreationPending class comment
protected final CreationPending creationPending = new CreationPending();
+ private final Backfill backfill;
// -------------------------------------------------------------------------
// CONSTRUCTOR
@@ -91,7 +93,8 @@ public DefaultSchedulerAdapter(LockManager lockManager,
TimerManager timerManager,
GlobalPolicies globalPolicies,
DataConvert dataConvert,
- Lager lagerImpl) {
+ Lager lagerImpl,
+ Backfill backfill) {
if (lockManager == null) {
throw new IllegalArgumentException("lockManager may not be null");
@@ -127,6 +130,11 @@ public DefaultSchedulerAdapter(LockManager lockManager,
throw new IllegalArgumentException("lagerImpl may not be null");
}
this.lager = lagerImpl;
+
+ if (backfill == null) {
+ throw new IllegalArgumentException("backfill may not be null");
+ }
+ this.backfill = backfill;
}
@@ -219,7 +227,8 @@ public Reservation schedule(int memory,
int numNodes,
String groupid,
String coschedid,
- String creatorDN)
+ String creatorDN,
+ boolean backfillReq)
throws SchedulingException,
ResourceRequestDeniedException {
@@ -252,7 +261,7 @@ public Reservation schedule(int memory,
this.creationPending.pending(ids);
final NodeRequest req =
- new NodeRequest(ids, memory, duration, assocs, groupid, creatorDN);
+ new NodeRequest(ids, memory, duration, assocs, groupid, creatorDN, backfillReq);
try {
@@ -282,7 +291,35 @@ private Reservation scheduleImpl(NodeRequest req)
final String invalidResponse = "Implementation problem: slot " +
"manager returned invalid response";
- final Reservation res = this.slotManager.reserveSpace(req);
+ // If a request is denied (and it's not a backfill request) then we
+ // should attempt to kill backfill nodes until there are no more
+ // backfill nodes to kill or until the request can be satisfied.
+ Reservation res = null;
+ try {
+ res = this.slotManager.reserveSpace(req);
+ } catch (ResourceRequestDeniedException e) {
+ logger.debug("Failed to reserve the resource: " + e.getMessage());
+ if (req.getBackfillReq() == false) {
+ logger.debug("The request isn't a backfill request");
+ logger.debug("Attempting to terminate backfill nodes");
+ boolean continueTerminateBackfill = true;
+ while (continueTerminateBackfill == true) {
+ try {
+ res = this.slotManager.reserveSpace(req);
+ continueTerminateBackfill = false;
+ } catch (ResourceRequestDeniedException rDE) {
+ int numNodes = req.getNumNodes();
+ if (this.backfill.terminateBackfillNode(numNodes) == 0) {
+ throw rDE;
+ } else {
+ continueTerminateBackfill = true;
+ }
+ }
+ }
+ } else {
+ throw e;
+ }
+ }
if (res == null) {
throw new ResourceRequestDeniedException(
@@ -861,6 +898,15 @@ private void remove(int vmid) throws ManageException {
this.db.backOutTasks(vmid);
this.slotManager.releaseSpace(vmid);
this.db.deleteNodeRequest(vmid);
+
+ // Check to see if this was a backfill request being killed off.
+ // If not, relaunch the backfill timer to deploy backfill nodes
+ // on *potentially* empty slots.
+ if ((this.slotManager.isOldBackfillID(vmid) == false) &&
+ (this.slotManager.isCurrentBackfillID(vmid) == false)) {
+ logger.debug("Relaunching backfill timer");
+ this.backfill.launchBackfillTimer();
+ }
}
protected void markShutdown(int id) throws WorkspaceDatabaseException {
View
158 ...ervice/java/source/src/org/globus/workspace/scheduler/defaults/DefaultSlotManagement.java
@@ -19,6 +19,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.globus.workspace.Lager;
+import org.globus.workspace.PathConfigs;
import org.globus.workspace.ProgrammingError;
import org.globus.workspace.persistence.WorkspaceDatabaseException;
import org.globus.workspace.scheduler.*;
@@ -31,6 +32,13 @@
import org.nimbustools.api.services.rm.DoesNotExistException;
import org.nimbustools.api.services.rm.ManageException;
+import java.io.IOException;
+import java.io.File;
+import java.io.ObjectOutputStream;
+import java.io.FileOutputStream;
+import java.io.ObjectInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.util.*;
/**
@@ -56,13 +64,20 @@
private boolean greedy;
+ private Hashtable backfillVMs = new Hashtable();
+ private Set oldBackfillIDs = new HashSet();
+ private File backfillHashFile;
+
+ protected final PathConfigs pathConfigs;
+
// -------------------------------------------------------------------------
// CONSTRUCTOR
// -------------------------------------------------------------------------
public DefaultSlotManagement(PersistenceAdapter db,
- Lager lager) {
+ Lager lager,
+ PathConfigs pathConfigs) {
if (db == null) {
throw new IllegalArgumentException("db may not be null");
@@ -73,6 +88,15 @@ public DefaultSlotManagement(PersistenceAdapter db,
throw new IllegalArgumentException("lager may not be null");
}
this.lager = lager;
+
+ if (pathConfigs == null) {
+ throw new IllegalArgumentException("pathConfigs may not be null");
+ }
+ this.pathConfigs = pathConfigs;
+ this.backfillHashFile = new File(
+ this.pathConfigs.getLocalTempDirPath() +
+ "/backfill.hashtable");
+ this.populateBackfillHashTable();
}
@@ -133,6 +157,19 @@ public synchronized Reservation reserveSpace(NodeRequest req)
this.reserveSpace(vmids, req.getMemory(),
req.getNeededAssociations());
+ if (req.getBackfillReq() == true) {
+ for (int i=0; i < vmids.length; i++) {
+ Date start = new Date();
+ BackfillNode tmpNode = new BackfillNode(vmids[i],
+ start,
+ hostnames[i]);
+ this.backfillVMs.put(vmids[i], tmpNode);
+ }
+ logger.debug("Added backfill node to the hashtable: " +
+ this.backfillVMs.toString());
+ this.writeBackfillHashTable();
+ }
+
return new Reservation(vmids, hostnames);
}
@@ -428,6 +465,16 @@ public synchronized void releaseSpace(final int vmid) throws ManageException {
ResourcepoolUtil.retireMem(node, mem, this.db,
this.lager.eventLog, this.lager.traceLog,
vmid);
+
+ if (this.backfillVMs.remove(vmid) != null) {
+ logger.debug("Removed backfill node from the hashtable: " +
+ this.backfillVMs.toString());
+ this.oldBackfillIDs.add(vmid);
+ this.writeBackfillHashTable();
+ } else {
+ logger.debug("Failed to remove backfill node from the " +
+ "hashtable: " + Integer.toString(vmid));
+ }
}
public void setScheduler(Scheduler adapter) {
@@ -619,4 +666,113 @@ public synchronized boolean removeNode(String hostname)
}
}
+
+ public int getBackfillVMID() {
+ if (this.backfillVMs.isEmpty() == true) {
+ return -1;
+ } else {
+ Enumeration e = this.backfillVMs.keys();
+ String vmidStr = e.nextElement().toString();
+ int vmid = Integer.parseInt(vmidStr.trim());
+ return vmid;
+ }
+ }
+
+ public int getMostRecentBackfillVMID() {
+ if (this.backfillVMs.isEmpty() == true) {
+ return -1;
+ } else {
+ int randomVMID = this.getBackfillVMID();
+ BackfillNode randomNode =
+ (BackfillNode)this.backfillVMs.get(randomVMID);
+ Date mostRecentDate = randomNode.getStartDate();
+ int mostRecentVMID = randomNode.getVMID();
+ Enumeration e = this.backfillVMs.elements();
+ while (e.hasMoreElements()) {
+ BackfillNode tmpNode = (BackfillNode)e.nextElement();
+ if(mostRecentDate.compareTo(tmpNode.getStartDate()) < 0) {
+ mostRecentDate = tmpNode.getStartDate();
+ mostRecentVMID = tmpNode.getVMID();
+ }
+ }
+ return mostRecentVMID;
+ }
+ }
+
+ public boolean isOldBackfillID(int vmid) {
+ return this.oldBackfillIDs.contains(vmid);
+ }
+
+ public boolean isCurrentBackfillID(int vmid) {
+ return this.backfillVMs.contains(vmid);
+ }
+
+ /**
+ * The following two methods, populateBackfillHashTable and
+ * writeBackfillHashTable simply read and write a small file
+ * that contains the current status of the backfill hash table
+ * (for persistence).
+ *
+ * Thus, whenever the backfill hash table is updated,
+ * writeBackfillHashTable should be called (gross) to make sure
+ * the version on disk matches the current hash table. And
+ * whenever the service has started, populateBackfillHashTable
+ * should be called to read in the version on the disk.
+ */
+ private void populateBackfillHashTable() {
+ try {
+ logger.debug("Attempting to read backfill hash table file:\n" +
+ this.backfillHashFile.toString());
+ FileInputStream backfillFIS =
+ new FileInputStream(this.backfillHashFile);
+ ObjectInputStream backfillOIS =
+ new ObjectInputStream(backfillFIS);
+
+ this.backfillVMs = (Hashtable)backfillOIS.readObject();
+
+ logger.debug("For the backfill hash table file," +
+ " we read:\n" + this.backfillVMs.toString());
+ backfillOIS.close();
+ backfillFIS.close();
+ } catch (FileNotFoundException e) {
+ logger.debug("Can't read a file that doesn't exist:\n" +
+ this.backfillHashFile.toString());
+ } catch (Exception uE) {
+ logger.error("Caught unknown exception while attempting to " +
+ "read the backfill hash table file: " +
+ uE.getMessage());
+ }
+ }
+
+ private void writeBackfillHashTable() {
+ if (this.backfillHashFile.exists()) {
+ logger.debug("Backfill hash table file already exists");
+ logger.debug("Deleting existing backfill hash table file");
+ try {
+ this.backfillHashFile.delete();
+ } catch (Exception e) {
+ logger.error("There was a problem deleting the existing " +
+ "backfill hash table file: " + e.getMessage());
+ }
+ }
+ logger.debug("Attempting to write backfill file:\n" +
+ this.backfillHashFile.toString());
+ try {
+ this.backfillHashFile.createNewFile();
+ FileOutputStream backfillFOS =
+ new FileOutputStream(this.backfillHashFile);
+ ObjectOutputStream backfillOOS =
+ new ObjectOutputStream(backfillFOS);
+ backfillOOS.writeObject(this.backfillVMs);
+ backfillOOS.close();
+ backfillFOS.close();
+ logger.debug("For the backfill hash table file, we wrote:\n" +
+ this.backfillVMs.toString());
+ } catch (Exception cE) {
+ logger.error("There was a problem writing the backfill " +
+ "hash table to the file: " + cE.getMessage());
+ logger.error("There may be extra backfill VMs present that " +
+ "we are unable to manage.");
+ }
+ }
}
View
17 service/service/java/source/src/org/globus/workspace/scheduler/defaults/NodeRequest.java
@@ -26,6 +26,8 @@
private String groupid = null;
private String creatorDN = null;
+ private boolean backfillReq = false;
+
public NodeRequest(int memory,
int duration) {
if (duration < 1) {
@@ -44,15 +46,18 @@ public NodeRequest(int[] ids,
int duration,
String[] neededAssociations,
String groupid,
- String creatorDN) {
+ String creatorDN,
+ boolean backfillReq) {
this(memory, duration);
this.ids = ids;
this.neededAssociations = neededAssociations;
this.groupid = groupid;
this.creatorDN = creatorDN;
+ this.backfillReq = backfillReq;
}
+
public int[] getIds() {
return this.ids;
}
@@ -111,7 +116,7 @@ public String getGroupid() {
public void setGroupid(String groupid) {
this.groupid = groupid;
}
-
+
public String getCreatorDN() {
return this.creatorDN;
}
@@ -119,4 +124,12 @@ public String getCreatorDN() {
public void setCreatorDN(String creatorDN) {
this.creatorDN = creatorDN;
}
+
+ public boolean getBackfillReq() {
+ return this.backfillReq;
+ }
+
+ public void setBackfillReq(boolean backfillReq) {
+ this.backfillReq = backfillReq;
+ }
}
View
5 service/service/java/source/src/org/globus/workspace/scheduler/defaults/SlotManagement.java
@@ -87,4 +87,9 @@ public Reservation reserveCoscheduledSpace(NodeRequest[] requests,
* @return true if neededAssociations is supported
*/
public boolean isNeededAssociationsSupported();
+
+ public int getBackfillVMID();
+ public int getMostRecentBackfillVMID();
+ public boolean isOldBackfillID(int vmid);
+ public boolean isCurrentBackfillID(int vmid);
}
View
19 ...ce/java/source/src/org/globus/workspace/scheduler/defaults/pilot/PilotSlotManagement.java
@@ -1630,4 +1630,23 @@ private void cancelWorkspace(int vmid,
}
}
}
+
+ /* None of the below are used in the context of the pilot service at this time */
+ public int getBackfillVMID() {
+ int tmp=-1;
+ return tmp;
+ }
+
+ public int getMostRecentBackfillVMID() {
+ int tmp=-1;
+ return tmp;
+ }
+
+ public boolean isOldBackfillID(int vmid) {
+ return false;
+ }
+
+ public boolean isCurrentBackfillID(int vmid) {
+ return false;
+ }
}

No commit comments for this range

Something went wrong with that request. Please try again.