Skip to content

Commit 15e271d

Browse files
committed
Merge pull request #236 from fogbow/persistOrders
Persist orders
2 parents c4b7a61 + 70b6d8c commit 15e271d

File tree

16 files changed

+1135
-5
lines changed

16 files changed

+1135
-5
lines changed

manager.conf.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ xmpp_port=5347
66
rendezvous_jid=rendezvous.test.com
77
greensitter_jid=greensitter.test.com
88

9+
## Order database
10+
order_datastore_url=jdbc:h2:/home/chicog/Backup/dbmanager
11+
order_bd_updater_period=30000
12+
913
## Static mapping from flavors to requirements (Optional)
1014
# flavor_fogbow_small={mem=512, cpu=1}
1115
# flavor_fogbow_medium={mem=1024, cpu=2}

src/main/java/org/fogbowcloud/manager/core/ConfigurationConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class ConfigurationConstants {
2727
public static final String PREFIX_FLAVORS = "flavor_";
2828

2929
// periods
30+
public static final String ORDER_BD_UPDATER_PERIOD_KEY = "order_bd_updater_period";
3031
public static final String SCHEDULER_PERIOD_KEY = "scheduler_period";
3132
public static final String INSTANCE_MONITORING_PERIOD_KEY = "instance_monitoring_period";
3233
public static final String TOKEN_UPDATE_PERIOD_KEY = "token_update_period";

src/main/java/org/fogbowcloud/manager/core/ManagerController.java

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.File;
44
import java.io.FileInputStream;
55
import java.io.IOException;
6+
import java.sql.SQLException;
67
import java.util.ArrayList;
78
import java.util.Calendar;
89
import java.util.Collection;
@@ -47,9 +48,9 @@
4748
import org.fogbowcloud.manager.core.plugins.ComputePlugin;
4849
import org.fogbowcloud.manager.core.plugins.FederationMemberAuthorizationPlugin;
4950
import org.fogbowcloud.manager.core.plugins.FederationMemberPickerPlugin;
50-
import org.fogbowcloud.manager.core.plugins.LocalCredentialsPlugin;
5151
import org.fogbowcloud.manager.core.plugins.IdentityPlugin;
5252
import org.fogbowcloud.manager.core.plugins.ImageStoragePlugin;
53+
import org.fogbowcloud.manager.core.plugins.LocalCredentialsPlugin;
5354
import org.fogbowcloud.manager.core.plugins.PrioritizationPlugin;
5455
import org.fogbowcloud.manager.core.plugins.accounting.ResourceUsage;
5556
import org.fogbowcloud.manager.core.plugins.util.SshClientPool;
@@ -62,6 +63,7 @@
6263
import org.fogbowcloud.manager.occi.model.ResourceRepository;
6364
import org.fogbowcloud.manager.occi.model.ResponseConstants;
6465
import org.fogbowcloud.manager.occi.model.Token;
66+
import org.fogbowcloud.manager.occi.request.OrderDataStore;
6567
import org.fogbowcloud.manager.occi.request.Request;
6668
import org.fogbowcloud.manager.occi.request.RequestAttribute;
6769
import org.fogbowcloud.manager.occi.request.RequestConstants;
@@ -70,6 +72,7 @@
7072
import org.fogbowcloud.manager.occi.request.RequestType;
7173
import org.fogbowcloud.manager.xmpp.AsyncPacketSender;
7274
import org.fogbowcloud.manager.xmpp.ManagerPacketHelper;
75+
import org.json.JSONException;
7376
import org.json.JSONObject;
7477
import org.restlet.Response;
7578

@@ -84,6 +87,7 @@ public class ManagerController {
8487
private static final Logger LOGGER = Logger.getLogger(ManagerController.class);
8588

8689
private static final int DEFAULT_MAX_WHOISALIVE_MANAGER_COUNT = 100;
90+
private static final long DEFAULT_BD_UPDATE_PERIOD = 300000; // 5 minute
8791
private static final long DEFAULT_SCHEDULER_PERIOD = 30000; // 30 seconds
8892
protected static final int DEFAULT_ASYNC_REQUEST_WAITING_INTERVAL = 300000; // 5 minutes
8993
private static final long DEFAULT_INSTANCE_MONITORING_PERIOD = 120000; // 2 minutes
@@ -99,6 +103,7 @@ public class ManagerController {
99103
private final ManagerTimer servedRequestMonitoringTimer;
100104
private final ManagerTimer garbageCollectorTimer;
101105
private final ManagerTimer accountingUpdaterTimer;
106+
private final ManagerTimer requestDBUpdaterTimer;
102107

103108
private Map<String, Token> instanceIdToToken = new HashMap<String, Token>();
104109
private final List<FederationMember> members = Collections.synchronizedList(new LinkedList<FederationMember>());
@@ -126,6 +131,8 @@ public class ManagerController {
126131
private DateUtils dateUtils = new DateUtils();
127132

128133
private PoolingHttpClientConnectionManager cm;
134+
135+
private OrderDataStore requestDB;
129136

130137
public ManagerController(Properties properties) {
131138
this(properties, null);
@@ -143,15 +150,24 @@ public ManagerController(Properties properties, ScheduledExecutorService executo
143150
this.servedRequestMonitoringTimer = new ManagerTimer(Executors.newScheduledThreadPool(1));
144151
this.garbageCollectorTimer = new ManagerTimer(Executors.newScheduledThreadPool(1));
145152
this.accountingUpdaterTimer = new ManagerTimer(Executors.newScheduledThreadPool(1));
153+
this.requestDBUpdaterTimer = new ManagerTimer(Executors.newScheduledThreadPool(1));
146154
} else {
147155
this.requestSchedulerTimer = new ManagerTimer(executor);
148156
this.instanceMonitoringTimer = new ManagerTimer(executor);
149157
this.servedRequestMonitoringTimer = new ManagerTimer(executor);
150158
this.garbageCollectorTimer = new ManagerTimer(executor);
151159
this.accountingUpdaterTimer = new ManagerTimer(executor);
160+
this.requestDBUpdaterTimer = new ManagerTimer(executor);
152161
}
162+
requestDB = new OrderDataStore(properties);
163+
recoverPreviousRequests();
164+
triggerRequestDBUpdater();
153165
}
154166

167+
public void setDatabase(OrderDataStore database) {
168+
this.requestDB = database;
169+
}
170+
155171
public void setBenchmarkExecutor(ExecutorService benchmarkExecutor) {
156172
this.benchmarkExecutor = benchmarkExecutor;
157173
}
@@ -180,6 +196,45 @@ public void setAccountingPlugin(AccountingPlugin accountingPlugin) {
180196
}
181197
}
182198

199+
private void recoverPreviousRequests() {
200+
new Thread(new Runnable() {
201+
@Override
202+
public void run() {
203+
try {
204+
initializeManager();
205+
} catch (Exception e) {
206+
LOGGER.error("Could not recover requests.", e);
207+
}
208+
}
209+
}).start();
210+
}
211+
212+
protected void initializeManager() throws SQLException, JSONException {
213+
LOGGER.debug("Recovering previous requests." );
214+
for (Request request : this.requestDB.getOrders()) {
215+
Instance instance = null;
216+
try {
217+
if (request.getState().equals(RequestState.FULFILLED) ||
218+
request.getState().equals(RequestState.DELETED)) {
219+
instance = getInstance(request);
220+
LOGGER.debug(instance.getId() + " was recovered to request " + request.getId());
221+
}
222+
} catch (Exception e) {
223+
LOGGER.debug(request.getGlobalInstanceId() + " does not exist anymore.");
224+
if (request.getState().equals(RequestState.DELETED)) {
225+
continue;
226+
}
227+
instanceRemoved(request);
228+
}
229+
requests.addRequest(request.getFederationToken().getUser(), request);
230+
}
231+
if (!requestSchedulerTimer.isScheduled() &&
232+
requests.getRequestsIn(RequestState.OPEN).size() > 0) {
233+
triggerRequestScheduler();
234+
}
235+
LOGGER.debug("Previous requests recovered.");
236+
}
237+
183238
private String getSSHCommonUser() {
184239
String sshCommonUser = properties.getProperty(ConfigurationConstants.SSH_COMMON_USER);
185240
return sshCommonUser == null ? DEFAULT_COMMON_SSH_USER : sshCommonUser;
@@ -935,6 +990,45 @@ public List<Request> createRequests(String federationAccessTokenStr, List<Catego
935990

936991
return currentRequests;
937992
}
993+
994+
private void triggerRequestDBUpdater() {
995+
String bdUpdaterPeriodStr = properties
996+
.getProperty(ConfigurationConstants.ORDER_BD_UPDATER_PERIOD_KEY);
997+
long schedulerPeriod = bdUpdaterPeriodStr == null ? DEFAULT_BD_UPDATE_PERIOD : Long
998+
.valueOf(bdUpdaterPeriodStr);
999+
requestDBUpdaterTimer.scheduleAtFixedRate(new TimerTask() {
1000+
@Override
1001+
public void run() {
1002+
try {
1003+
updateRequestDB();
1004+
} catch (Exception e) {
1005+
LOGGER.error("Could not update the database.", e);
1006+
}
1007+
}
1008+
}, 60000, schedulerPeriod);
1009+
}
1010+
1011+
protected void updateRequestDB() throws SQLException, JSONException {
1012+
LOGGER.debug("Database update start." );
1013+
List<Request> orders = this.requestDB.getOrders();
1014+
Map<String, Request> ordersDB = new HashMap<String, Request>();
1015+
for (Request request : orders) {
1016+
ordersDB.put(request.getId(), request);
1017+
}
1018+
List<Request> allRequests = new ArrayList<Request>(requests.getAllRequests());
1019+
for (Request request : allRequests) {
1020+
if (ordersDB.get(request.getId()) == null) {
1021+
requestDB.addOrder(request);
1022+
} else {
1023+
requestDB.updateOrder(request);
1024+
ordersDB.remove(request.getId());
1025+
}
1026+
}
1027+
for (String key : ordersDB.keySet()) {
1028+
requestDB.removeOrder(ordersDB.get(key));
1029+
}
1030+
LOGGER.debug("Database update finish." );
1031+
}
9381032

9391033
private Token getTokenFromLocalIdP(String localAccessTokenStr) {
9401034
return localIdentityPlugin.getToken(localAccessTokenStr);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.fogbowcloud.manager.occi;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
public class OrderDataStoreHelper {
7+
8+
public static Map<String, String> toMap(String jsonStr) {
9+
Map<String, String> newMap = new HashMap<String, String>();
10+
jsonStr = jsonStr.replace("{", "").replace("}", "");
11+
String[] blocks = jsonStr.split(",");
12+
for (int i = 0; i < blocks.length; i++) {
13+
String block = blocks[i];
14+
int indexOfCarac = block.indexOf("=");
15+
if (indexOfCarac < 0) {
16+
continue;
17+
}
18+
String key = block.substring(0, indexOfCarac).trim();
19+
String value = block.substring(indexOfCarac + 1, block.length()).trim();
20+
newMap.put(key, value);
21+
}
22+
return newMap;
23+
}
24+
}

src/main/java/org/fogbowcloud/manager/occi/model/Category.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import java.util.List;
66
import java.util.Map;
77

8+
import org.json.JSONException;
9+
import org.json.JSONObject;
10+
811
public class Category {
912

1013
private String term;
@@ -105,4 +108,15 @@ public boolean equals(Object obj) {
105108
public String toString() {
106109
return toHeader();
107110
}
111+
112+
public JSONObject toJSON() throws JSONException {
113+
return new JSONObject().put("term", term).put("class", catClass).put("scheme", scheme);
114+
}
115+
116+
public static Category fromJSON(String jsonStr) throws JSONException {
117+
JSONObject jsonObject = new JSONObject(jsonStr);
118+
return new Category(jsonObject.optString("term"), jsonObject.optString("scheme"),
119+
jsonObject.optString("class"));
120+
}
121+
108122
}

src/main/java/org/fogbowcloud/manager/occi/model/Token.java

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@
22

33
import java.util.Date;
44
import java.util.HashMap;
5+
import java.util.HashSet;
56
import java.util.Map;
67

78
import org.fogbowcloud.manager.core.model.DateUtils;
9+
import org.fogbowcloud.manager.occi.OrderDataStoreHelper;
10+
import org.json.JSONException;
11+
import org.json.JSONObject;
812

913
public class Token {
10-
14+
1115
private static final String DATE_EXPIRATION = "dateExpiration";
1216

1317
private Map<String, String> attributes;
@@ -75,4 +79,51 @@ public String toString() {
7579
public String getUser() {
7680
return this.user;
7781
}
82+
83+
public JSONObject toJSON() throws JSONException {
84+
return new JSONObject().put("access_id", accessId).put("user", user)
85+
.put("attributes", attributes != null ? attributes.toString() : null);
86+
}
87+
88+
public static Token fromJSON(String jsonStr) throws JSONException {
89+
JSONObject jsonObject = new JSONObject(jsonStr);
90+
String accessId = jsonObject.optString("access_id");
91+
String user = jsonObject.optString("user");
92+
return new Token(!accessId.isEmpty() ? accessId : null, !user.isEmpty() ? user : null,
93+
null, OrderDataStoreHelper.toMap(jsonObject.optString("attributes")));
94+
}
95+
96+
@SuppressWarnings({ "unchecked", "rawtypes" })
97+
@Override
98+
public boolean equals(Object obj) {
99+
if (this == obj)
100+
return true;
101+
if (obj == null)
102+
return false;
103+
if (getClass() != obj.getClass())
104+
return false;
105+
Token other = (Token) obj;
106+
if (accessId == null) {
107+
if (other.accessId != null)
108+
return false;
109+
} else if (!accessId.equals(other.accessId))
110+
return false;
111+
if (attributes == null) {
112+
if (other.attributes != null)
113+
return false;
114+
} else if (attributes != null
115+
&& !new HashSet(attributes.values()).equals(new HashSet(other.attributes.values())))
116+
return false;
117+
if (dateUtils == null) {
118+
if (other.dateUtils != null)
119+
return false;
120+
}
121+
if (user == null) {
122+
if (other.user != null)
123+
return false;
124+
} else if (!user.equals(other.user))
125+
return false;
126+
return true;
127+
}
128+
78129
}

0 commit comments

Comments
 (0)