001 /**
002 *
003 */
004 package de.jw.cloud42.webapp;
005
006 import java.io.File;
007 import java.util.ArrayList;
008 import java.util.HashMap;
009 import java.util.List;
010 import java.util.logging.Logger;
011
012 import javax.faces.application.FacesMessage;
013
014 import org.jboss.seam.ScopeType;
015 import org.jboss.seam.annotations.In;
016 import org.jboss.seam.annotations.Name;
017 import org.jboss.seam.annotations.Scope;
018 import org.jboss.seam.annotations.Synchronized;
019 import org.jboss.seam.faces.FacesMessages;
020 import org.richfaces.event.UploadEvent;
021
022 import de.jw.cloud42.core.domain.RemoteResult;
023 import de.jw.cloud42.core.remoting.RemoteControl;
024 import de.jw.cloud42.webapp.utils.FileUtils;
025
026
027 /**
028 * Seam component, handles bundling new AMIs and holds corresponding properties.
029 *
030 * @author fbitzer
031 *
032 */
033 @Name("bundlingManager")
034 @Scope(ScopeType.SESSION)
035 @Synchronized(timeout=1000000000)
036 public class BundlingManager {
037
038 @In
039 UserManager userManager;
040
041 /**
042 * Inject faces messages to trigger error and success messages.
043 */
044 @In
045 FacesMessages facesMessages;
046
047
048 private HashMap<String, BundlingThread> bundlingThreads = new HashMap<String, BundlingThread>();
049
050 //the Member variables for the input fields in the UI
051 private String bucket;
052 private String imageName;
053 private boolean use64Bit;
054
055 private boolean doNotify;
056 private String messageTopic;
057 private String messageText;
058 private String messageInfo;
059
060 private byte[] certFile;
061 private byte[] pkFile;
062
063 /**
064 * Starts bundling a new AMI.
065 *
066 * @param dnsName
067 * @param keyName
068 */
069 public void bundle(String dnsName, String keyName){
070
071 //check input first
072
073 if (this.bucket.equals("")){
074 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "msg_invalidInput", "No bucket.");
075 return;
076 }
077
078 if (this.certFile==null){
079 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "msg_invalidInput", "No certificate.");
080 return;
081 }
082 if (this.pkFile==null){
083 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "msg_invalidInput", "No key file.");
084 return;
085 }
086
087 if (this.imageName.equals("")){
088 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "msg_invalidInput", "No image name.");
089 return;
090 }
091
092
093
094 //get the private key for the keyname
095 String privateKey = userManager.getKeyForName(keyName);
096
097 //create a thread for bundling
098 BundlingThread t = new BundlingThread(dnsName, privateKey, userManager.getCurrentCredentials(),
099 bucket, imageName, use64Bit,
100 doNotify, messageTopic, messageText, messageInfo, privateKey.getBytes(), certFile);
101
102
103 t.start();
104
105 //add the thread to the list of currently running threads
106 bundlingThreads.put(dnsName, t);
107
108
109
110 }
111
112 /**
113 * Checks if bundling is in progress for a particular instance.
114 * @param dnsName Hostname of the instance to check
115 *
116 * @return
117 */
118 public boolean bundlingInProgress(String dnsName){
119
120 //check if there is a thread attached to the hostname
121 BundlingThread t = bundlingThreads.get(dnsName);
122
123
124 if (t != null){
125 //yes, there is a thread
126 if (t.getState() == Thread.State.TERMINATED) {
127 //its state is terminated so bundling has ended -> check the result
128 if (t.getResult().getExitCode() != 0) {
129 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR, "msg_bundlingError", t.getResult().getExceptionMessage());
130
131 } else {
132 facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_INFO, "msg_bundlingOK", dnsName);
133
134 }
135 //remove the ended thread
136 bundlingThreads.remove(dnsName);
137
138 return false;
139 } else {
140 //thread found, but not finished -> bundling is running
141 return true;
142 }
143 } else {
144 //no bundling thread found -> no bundling in progress
145 return false;
146 }
147
148 }
149
150
151 /**
152 * Resets the dialog by resetting the member variables.
153 */
154 public void resetBundlingDialog(){
155 bucket = "";
156 imageName ="";
157 use64Bit = false;
158 certFile = null;
159 pkFile = null;
160
161 doNotify = false;
162 messageTopic = "";
163 messageText = "";
164 messageInfo = "";
165 }
166
167 /**
168 * fileUploadListener function for RichFaces fileupload component.
169 * Reads the content of the uploaded file into a byte array and stores it in the
170 * <code>certFile</code> property.
171 * @param e
172 */
173 public void fileUploadListener(UploadEvent e){
174
175 this.certFile = getFile(e);
176
177 }
178
179 /**
180 * fileUploadListener function for RichFaces fileupload component.
181 * Reads the content of the uploaded file into a byte array and stores it in the
182 * <code>pkFile</code> property.
183 * @param e
184 */
185 public void fileUploadListenerPK(UploadEvent e){
186
187 this.pkFile = getFile(e);
188
189 }
190
191
192 //-------Getters and Setters---------------
193 /**
194 * @return the bucket
195 */
196 public String getBucket() {
197 return bucket;
198 }
199 /**
200 * @param bucket the bucket to set
201 */
202 public void setBucket(String bucket) {
203 this.bucket = bucket;
204 }
205 /**
206 * @return the imageName
207 */
208 public String getImageName() {
209 return imageName;
210 }
211 /**
212 * @param imageName the imageName to set
213 */
214 public void setImageName(String imageName) {
215 this.imageName = imageName;
216 }
217 /**
218 * @return the use64Bit
219 */
220 public boolean isUse64Bit() {
221 return use64Bit;
222 }
223 /**
224 * @param use64Bit the use64Bit to set
225 */
226 public void setUse64Bit(boolean use64Bit) {
227 this.use64Bit = use64Bit;
228 }
229 /**
230 * @return the doNotify
231 */
232 public boolean isDoNotify() {
233 return doNotify;
234 }
235 /**
236 * @param doNotify the doNotify to set
237 */
238 public void setDoNotify(boolean doNotify) {
239 this.doNotify = doNotify;
240 }
241 /**
242 * @return the messageTopic
243 */
244 public String getMessageTopic() {
245 return messageTopic;
246 }
247 /**
248 * @param messageTopic the messageTopic to set
249 */
250 public void setMessageTopic(String messageTopic) {
251 this.messageTopic = messageTopic;
252 }
253 /**
254 * @return the messageText
255 */
256 public String getMessageText() {
257 return messageText;
258 }
259 /**
260 * @param messageText the messageText to set
261 */
262 public void setMessageText(String messageText) {
263 this.messageText = messageText;
264 }
265 /**
266 * @return the messageInfo
267 */
268 public String getMessageInfo() {
269 return messageInfo;
270 }
271 /**
272 * @param messageInfo the messageInfo to set
273 */
274 public void setMessageInfo(String messageInfo) {
275 this.messageInfo = messageInfo;
276 }
277
278
279
280 /**
281 * @return the certFile
282 */
283 public byte[] getCertFile() {
284 return certFile;
285 }
286
287
288
289 /**
290 * @param certFile the certFile to set
291 */
292 public void setCertFile(byte[] certFile) {
293 this.certFile = certFile;
294 }
295
296
297
298 /**
299 * @return the pkFile
300 */
301 public byte[] getPkFile() {
302 return pkFile;
303 }
304
305
306
307 /**
308 * @param pkFile the pkFile to set
309 */
310 public void setPkFile(byte[] pkFile) {
311 this.pkFile = pkFile;
312 }
313
314
315 /**
316 * Private helper function, extracts an uploaded private key or certificate file.
317 * @param e RichFaces upload event
318 * @return
319 */
320 private byte[] getFile(UploadEvent e){
321 try {
322 File f = e.getUploadItem().getFile();
323
324 byte[] result = FileUtils.getBytesFromFile(f);
325
326 e.getUploadItem().getFile().delete();
327
328 return result;
329
330 } catch (Exception ex) {
331 Logger.getAnonymousLogger().warning("Uploading file failed: " + ex.getMessage());
332 }
333 return null;
334 }
335
336
337
338
339 }