1
/*******************************************************************************
2
*Copyright (c) 2009 Eucalyptus Systems, Inc.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation, only version 3 of the License.
9
* This file is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* You should have received a copy of the GNU General Public License along
15
* with this program. If not, see <http://www.gnu.org/licenses/>.
17
* Please contact Eucalyptus Systems, Inc., 130 Castilian
18
* Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
19
* if you need additional information or have any questions.
21
* This file may incorporate work covered under the following copyright and
24
* Software License Agreement (BSD License)
26
* Copyright (c) 2008, Regents of the University of California
27
* All rights reserved.
29
* Redistribution and use of this software in source and binary forms, with
30
* or without modification, are permitted provided that the following
33
* Redistributions of source code must retain the above copyright notice,
34
* this list of conditions and the following disclaimer.
36
* Redistributions in binary form must reproduce the above copyright
37
* notice, this list of conditions and the following disclaimer in the
38
* documentation and/or other materials provided with the distribution.
40
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
41
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
42
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
43
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
44
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
46
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
48
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
49
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
51
* THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
52
* LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
53
* SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
54
* IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
55
* BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
56
* THE REGENTS’ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
57
* OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
58
* WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
59
* ANY SUCH LICENSES OR RIGHTS.
60
*******************************************************************************/
63
* Author: Dmitrii Zagorodnov dmitrii@cs.ucsb.edu
66
package edu.ucsb.eucalyptus.admin.server;
68
import com.eucalyptus.auth.Debugging;
69
import com.eucalyptus.auth.Groups;
70
import com.eucalyptus.auth.UserInfo;
71
import com.eucalyptus.auth.Users;
72
import com.eucalyptus.auth.principal.User;
73
import com.eucalyptus.auth.util.Hashes;
74
import com.eucalyptus.component.Component;
75
import com.eucalyptus.component.Components;
76
import com.eucalyptus.component.Service;
77
import com.eucalyptus.component.ServiceConfiguration;
78
import com.eucalyptus.config.ClusterConfiguration;
79
import com.eucalyptus.config.Configuration;
80
import com.eucalyptus.system.BaseDirectory;
81
import com.eucalyptus.system.SubDirectory;
82
import com.eucalyptus.util.EucalyptusCloudException;
83
import com.google.gwt.user.client.rpc.SerializableException;
84
import com.google.gwt.user.client.rpc.SerializationException;
85
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
86
import com.google.gwt.user.server.rpc.UnexpectedException;
87
import edu.ucsb.eucalyptus.admin.client.CloudInfoWeb;
88
import edu.ucsb.eucalyptus.admin.client.ClusterInfoWeb;
89
import edu.ucsb.eucalyptus.admin.client.DownloadsWeb;
90
import edu.ucsb.eucalyptus.admin.client.EucalyptusWebBackend;
91
import edu.ucsb.eucalyptus.admin.client.SystemConfigWeb;
92
import edu.ucsb.eucalyptus.admin.client.StorageInfoWeb;
93
import edu.ucsb.eucalyptus.admin.client.UserInfoWeb;
94
import edu.ucsb.eucalyptus.admin.client.VmTypeWeb;
95
import edu.ucsb.eucalyptus.admin.client.WalrusInfoWeb;
97
import org.apache.commons.httpclient.HttpClient;
98
import org.apache.commons.httpclient.ProxyHost;
99
import org.apache.commons.httpclient.methods.GetMethod;
100
import org.apache.log4j.Logger;
101
import org.w3c.dom.Document;
102
import org.w3c.dom.NodeList;
104
import java.io.ByteArrayInputStream;
106
import java.io.FilenameFilter;
107
import java.io.InputStream;
108
import java.io.FileInputStream;
109
import java.io.IOException;
110
import java.net.MalformedURLException;
111
import java.util.ArrayList;
112
import java.util.Enumeration;
113
import java.util.HashMap;
114
import java.util.HashSet;
115
import java.util.List;
116
import java.util.Map;
117
import java.util.Properties;
118
import java.util.Set;
119
import javax.xml.parsers.DocumentBuilder;
120
import javax.xml.parsers.DocumentBuilderFactory;
121
import javax.xml.xpath.XPath;
122
import javax.xml.xpath.XPathConstants;
123
import javax.xml.xpath.XPathFactory;
125
public class EucalyptusWebBackendImpl extends RemoteServiceServlet implements EucalyptusWebBackend {
127
private static Logger LOG = Logger.getLogger( EucalyptusWebBackendImpl.class );
128
private static String PROPERTIES_FILE = BaseDirectory.CONF.toString() + File.separator + "eucalyptus-web.properties";
129
private static HashMap sessions = new HashMap();
130
private static Properties props = new Properties();
131
private static long session_timeout_ms = 1000 * 60 * 60 * 24 * 14L; /* 2 weeks (TODO: put into config?) */
132
private static long pass_expiration_ms = 1000 * 60 * 60 * 24 * 365L; /* 1 year (TODO: put into config?) */
134
/* parameters to be read from config file */
135
private static String thanks_for_signup;
136
private static String signup_request_subject;
137
private static String signup_approval_subject;
138
private static String signup_approval_header;
139
private static String signup_approval_footer;
140
private static String signup_rejection_subject;
141
private static String signup_rejection_message;
142
private static String password_recovery_message;
143
private static String password_recovery_subject;
145
/* if these are not in config file, we'll use admin's email */
146
private static String signup_email;
147
private static String reply_email;
148
private boolean system_ready;
150
private void load_props() throws SerializableException
152
FileInputStream fileInputStream = null;
154
fileInputStream = new FileInputStream(PROPERTIES_FILE);
155
props.load(fileInputStream);
156
props.setProperty("version", System.getProperty("euca.version"));
157
thanks_for_signup = props.getProperty("thanks-for-signup");
158
signup_email = props.getProperty("signup-email-address");
159
reply_email = props.getProperty("reply-email-address");
160
signup_request_subject = props.getProperty("signup-request-subject");
161
signup_approval_subject = props.getProperty("signup-approval-subject");
162
signup_approval_header = props.getProperty("signup-approval-header");
163
signup_approval_footer = props.getProperty("signup-approval-footer");
164
signup_rejection_subject = props.getProperty("signup-rejection-subject");
165
signup_rejection_message = props.getProperty("signup-rejection-message");
166
password_recovery_message = props.getProperty("password-recovery-message");
167
password_recovery_subject = props.getProperty("password-recovery-subject");
169
if (thanks_for_signup==null) {
170
throw new SerializableException("Server configuration is missing 'thanks-for-signup' value");
172
if (signup_request_subject==null) {
173
throw new SerializableException("Server configuration is missing 'signup-request-subject' value");
175
if (signup_approval_subject==null) {
176
throw new SerializableException("Server configuration is missing 'signup-approval-subject' value");
178
if (signup_approval_header==null) {
179
throw new SerializableException("Server configuration is missing 'signup-approval-header' value");
181
if (signup_approval_footer==null) {
182
throw new SerializableException("Server configuration is missing 'signup-approval-footer' value");
184
if (signup_rejection_subject==null) {
185
throw new SerializableException("Server configuration is missing 'signup-rejection-subject' value");
187
if (signup_rejection_message==null) {
188
throw new SerializableException("Server configuration is missing 'signup-rejection-message' value");
190
if (password_recovery_message==null) {
191
throw new SerializableException("Server configuration is missing 'password-recovery-message' value");
193
if (password_recovery_subject==null) {
194
throw new SerializableException("Server configuration is missing 'password-recovery-subject' value");
197
if ( signup_email==null) {
199
signup_email = EucalyptusManagement.getAdminEmail();
200
} catch (Exception e) {
201
signup_email = ""; /* signup will not work until admin email address is set */
202
system_ready = false;
205
if (reply_email==null) {
206
reply_email = signup_email;
209
} catch (IOException e) {
210
throw new SerializableException("Could not read server configuration");
211
} catch (IllegalArgumentException e) {
212
throw new SerializableException("Malformed escape sequence in server configuration");
214
if(fileInputStream != null)
216
fileInputStream.close();
217
} catch (IOException e) {
223
public String addUserRecord ( UserInfoWeb user )
224
throws SerializableException
226
return addUserRecord(null, user);
229
private void notifyAdminOfSignup (UserInfoWeb user)
230
throws SerializableException
233
String http_eucalyptus = ServletUtils.getRequestUrl(getThreadLocalRequest());
234
String approve_link = http_eucalyptus + "?action=approve&user=" + user.getUserName();
235
String reject_link = http_eucalyptus + "?action=reject&user=" + user.getUserName();
237
String email_message =
238
"Someone has requested an account on the Eucalyptus system\n" +
239
"\n Name: " + user.getRealName() +
240
"\n Username: " + user.getUserName() +
241
"\n Email address: " + user.getEmail() +
242
"\n Telephone: " + user.getTelephoneNumber() +
243
"\n Affiliation: " + user.getAffiliation() +
244
"\n Project PI: " + user.getProjectPIName() +
245
"\n Project description: " +
246
"\n=====\n" + user.getProjectDescription() +
248
"To APPROVE this request, click on the following link:\n\n " +
251
"To REJECT this request, click on the following link:\n\n " +
255
ServletUtils.sendMail( reply_email, signup_email,
256
signup_request_subject + " (" + user.getEmail() + ")",
259
} catch (Exception e) {
260
LOG.error ("Signup mailing problem: " + e.getMessage()); /* TODO: log properly */
261
throw new SerializableException ("Internal problem (failed to notify administrator by email)");
265
public String addUserRecord(String sessionId, UserInfoWeb user)
266
throws SerializableException
269
throw new SerializableException("Invalid RPC arguments");
271
if (user.getUserName().equalsIgnoreCase( "eucalyptus" )) {
272
throw new SerializableException("User 'eucalyptus' is not allowed");
274
// these two won't happen unless the user hacks the client side
275
if ( user.getUserName().matches(".*[^\\w\\-\\.@]+.*") ) {
276
throw new SerializableException ("Invalid characters in the username");
278
if ( user.getUserName().length() < 1 || user.getUserName().length() > 30)
280
throw new SerializableException ( "Invalid length of username" );
283
load_props(); /* get parameters from config file */
284
boolean admin = false;
286
SessionInfo session = verifySession (sessionId);
287
UserInfoWeb requestingUser = verifyUser (session, session.getUserId(), true);
288
if ( !requestingUser.isAdministrator().booleanValue()) {
289
throw new SerializableException("Administrative privileges required");
293
} catch (Exception e) { } /* that's OK, this was an anonymous request */
296
long now = System.currentTimeMillis();
297
user.setPasswordExpires( new Long(now + pass_expiration_ms) );
298
EucalyptusManagement.addWebUser(user);
302
/* enable the new user right away */
303
user.setApproved(true);
304
user.setEnabled(true);
305
response = notifyUserApproved(user);
307
/* if anonymous, then notify admin */
308
user.setApproved(false);
309
user.setEnabled(false);
310
notifyAdminOfSignup (user);
311
response = thanks_for_signup;
313
EucalyptusManagement.commitWebUser(user);
318
private String notifyUserRecovery(UserInfoWeb user)
321
String http_eucalyptus = ServletUtils.getRequestUrl(getThreadLocalRequest());
322
String confirm_link = http_eucalyptus + "?action=recover"
323
+ "&code=" + user.getConfirmationCode();
325
String email_message = password_recovery_message + "\n\n" +
329
ServletUtils.sendMail(reply_email, user.getEmail(),
330
password_recovery_subject,
333
} catch (Exception e) {
334
// TODO: log this using the proper procedure
335
LOG.error ("Password recovery mailing problem: " + e.getMessage());
336
LOG.error ("Confirmation code for user '" + user.getUserName()
337
+ "' and address " + user.getEmail()
338
+ " is " + user.getConfirmationCode());
340
return "Internal problem (failed to notify " + user.getEmail() + " by email)";
342
return "Notified '" + user.getUserName() + "' by email, thank you.";
345
public String recoverPassword ( UserInfoWeb web_user )
346
throws SerializableException
348
if (web_user==null) {
349
throw new SerializableException("Invalid RPC arguments");
354
/* try login first */
355
db_user = EucalyptusManagement.getWebUser(web_user.getUserName());
356
} catch (Exception e) {
358
db_user = EucalyptusManagement.getWebUserByEmail(web_user.getEmail());
360
db_user.setPassword (web_user.getPassword());
361
EucalyptusManagement.commitWebUser(db_user);
362
return notifyUserRecovery(db_user);
365
/* ensure the sessionId is (still) valid */
366
public static SessionInfo verifySession (String sessionId)
367
throws SerializableException
369
if (sessionId==null) {
370
throw new SerializableException("Invalid RPC arguments");
372
SessionInfo session = (SessionInfo)sessions.get(sessionId);
374
throw new SerializableException("Earlier session not found");
376
final long now = System.currentTimeMillis();
377
if ((now-session.getLastAccessed()) > session_timeout_ms) {
378
sessions.remove(sessionId);
379
throw new SerializableException("Earlier session expired");
381
session.setLastAccessed(System.currentTimeMillis());
385
private static boolean isPasswordExpired (UserInfoWeb user) {
386
final long now = System.currentTimeMillis();
387
if ((now > 0) && (now >= user.getPasswordExpires().longValue())) {
393
/* ensure the user exists and valid */
394
private static UserInfoWeb verifyUser (SessionInfo session, String userName, boolean verifyPasswordAge)
395
throws SerializableException
398
if (userName==null) {
399
throw new SerializableException("Invalid RPC arguments: userIname is missing");
402
user = EucalyptusManagement.getWebUser(userName);
403
} catch (Exception e) {
405
sessions.remove(session.getSessionId());
407
throw new SerializableException("Username '" + userName + "' not found");
409
if (!user.isApproved()) {
410
throw new SerializableException("User not approved yet");
412
if (!user.isEnabled()) {
413
throw new SerializableException("Disabled user account");
415
if (!user.isConfirmed()) {
416
throw new SerializableException("Unconfirmed account (click on the link in confirmation email)");
418
if (verifyPasswordAge) {
419
if (isPasswordExpired(user) &&
420
!(user.isAdministrator() && user.getEmail().equalsIgnoreCase(UserInfo.BOGUS_ENTRY))) { // first-time config will catch that
421
throw new SerializableException("Password expired");
427
public String getNewSessionID (String userId, String md5Password)
428
throws SerializableException
430
String sessionId = null;
433
if (md5Password==null) {
434
throw new SerializableException("Invalid RPC arguments: password is missing");
436
// you can get a sessionId with an expired password so you can change it => false
437
user = verifyUser (null, userId, false);
438
if (!user.getPassword().equals( md5Password )) {
439
throw new SerializableException("Incorrect password");
442
sessionId = ServletUtils.genGUID();
443
SessionInfo session = new SessionInfo(sessionId, userId, System.currentTimeMillis());
444
session.setStartedOn(session.getLastAccessed());
445
sessions.put(session.getSessionId(), session);
447
return session.getSessionId();
450
private String notifyUserApproved(UserInfoWeb user)
452
String confString = " and confirmed";
454
if (!user.isConfirmed().booleanValue()) {
456
String http_eucalyptus = ServletUtils.getRequestUrl(getThreadLocalRequest());
457
String confirm_link = http_eucalyptus + "?action=confirm"
458
+ "&code=" + user.getConfirmationCode();
460
String email_message = signup_approval_header + "\n\n" +
462
"\n\n" + signup_approval_footer;
464
ServletUtils.sendMail(reply_email, user.getEmail(),
465
signup_approval_subject,
468
} catch (Exception e) {
469
// TODO: log this using the proper procedure
470
LOG.error ("Approval mailing problem: " + e.getMessage());
471
LOG.error ("Confirmation code for user " + user.getUserName()
472
+ " is " + user.getConfirmationCode());
474
return "Internal problem (failed to notify user " + user.getEmail() + " by email)";
476
return "User '" + user.getUserName() + "' was approved" + confString + ", thank you.";
479
private String notifyUserRejected(UserInfoWeb user)
482
ServletUtils.sendMail(reply_email, user.getEmail(),
483
signup_rejection_subject,
484
signup_rejection_message);
486
} catch (Exception e) {
487
LOG.error ("Rejection mailing problem: " + e.getMessage());
488
return "Internal problem (failed to notify user " + user.getEmail() + ")";
490
return "User '" + user.getUserName() + "' was rejected.";
493
public String performAction (String sessionId, String action, String param)
494
throws SerializableException
497
if (action==null || param==null) {
498
throw new SerializableException("Invalid RPC arguments: action or param are missing");
501
/* these don't need a session */
502
if (action.equals("recover") ||
503
action.equals("confirm")) {
504
UserInfoWeb user = EucalyptusManagement.getWebUserByCode(param);
507
if (action.equals("confirm")) {
508
if ( user != null ) {
509
user.setConfirmed(true);
511
EucalyptusManagement.commitWebUser(user);
512
response = "Your account is now active.";
515
user.setPassword (user.getPassword());
516
long now = System.currentTimeMillis();
517
user.setPasswordExpires( new Long(now + pass_expiration_ms) );
518
EucalyptusManagement.commitWebUser(user);
520
response = "Your password has been reset.";
525
final SessionInfo session = verifySession (sessionId);
526
final UserInfoWeb user = verifyUser (session, session.getUserId(), true);
528
String response = "Your `" + action + "` request succeeded."; /* generic response */
529
if (action.equals("approve")
530
|| action.equals("reject")
531
|| action.equals ( "delete" )
532
|| action.equals ( "disable" )
533
|| action.equals ( "enable" )) {
534
String userName = param;
535
if (!user.isAdministrator()) {
536
throw new SerializableException("Administrative privileges required");
538
UserInfoWeb new_user = EucalyptusManagement.getWebUser(userName);
539
if (action.equals("approve")) {
540
new_user.setApproved(true);
541
new_user.setEnabled(true);
542
new_user.setConfirmed(false);
543
EucalyptusManagement.commitWebUser(new_user);
544
response = notifyUserApproved(new_user);
545
} else if (action.equals("reject")) {
546
EucalyptusManagement.deleteWebUser(new_user);
547
response = notifyUserRejected(new_user);
548
} else if (action.equals("delete")) {
549
EucalyptusManagement.deleteWebUser(new_user);
550
/* TODO: maybe tell the user that his account was deleted? */
551
} else if (action.equals("disable")) {
552
new_user.setEnabled(false);
553
EucalyptusManagement.commitWebUser(new_user);
554
} else if (action.equals("enable")) {
555
new_user.setEnabled(true);
556
EucalyptusManagement.commitWebUser(new_user);
558
response = "Request to " + action + " user '" + userName + "' succeeded.";
560
} else if (action.equals("delete_image")
561
|| action.equals("enable_image")
562
|| action.equals("disable_image")) {
563
String imageId = param;
564
if (!user.isAdministrator()) {
565
throw new SerializableException("Administrative privileges required");
567
if (action.equals("delete_image")) {
568
EucalyptusManagement.deleteImage(imageId);
569
} else if (action.equals("disable_image")) {
570
EucalyptusManagement.disableImage(imageId);
571
} else if (action.equals("enable_image")) {
572
EucalyptusManagement.enableImage(imageId);
574
response = "Your request succeeded, thank you.";
577
throw new SerializableException("Action '" + action + "' is not implemented.");
583
public void logoutSession(String sessionId)
584
throws SerializableException
586
if (sessionId==null) {
587
throw new SerializableException("Invalid RPC arguments: sessionId is missing");
589
SessionInfo session = (SessionInfo)sessions.get(sessionId);
591
sessions.remove(sessionId);
592
SessionInfo old = (SessionInfo)sessions.get(sessionId);
596
public List getUserRecord (String sessionId, String userId)
597
throws SerializableException
599
SessionInfo session = verifySession (sessionId);
600
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
602
List l = new ArrayList();
606
if (!user.isAdministrator()) {
607
throw new SerializableException("Only administrators can view users");
609
if (userId.equals("*")) {
610
l.addAll( EucalyptusManagement.getWebUsers(userId) ); /* NOTE: userId is currently ignored */
612
l.add(EucalyptusManagement.getWebUser(user.getUserName()));
618
public static UserInfoWeb getUserRecord (String sessionId) // a *static* getUserRecord, for ImageStoreService
619
throws SerializableException
621
SessionInfo session = verifySession (sessionId);
622
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
626
public List getImageInfo (String sessionId, String userId)
627
throws SerializableException
629
SessionInfo session = verifySession (sessionId);
630
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
632
/* TODO: right now userId parameter is ignored since we only have public images */
633
return EucalyptusManagement.getWebImages(userId);
636
/* from here on down, all requests require users to be enabled, approved, and confirmed */
638
public String getNewCert(String sessionId)
639
throws SerializableException
641
/* perform full checks */
642
SessionInfo session = verifySession (sessionId);
643
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
645
return user.getToken();
648
public HashMap getProperties()
649
throws SerializableException
652
HashMap h = new HashMap();
654
for (Enumeration e = props.propertyNames(); e.hasMoreElements() ;) {
655
String key = (String)e.nextElement();
656
h.put(key, props.getProperty(key));
658
h.put("ready", system_ready);
663
public String changePassword (String sessionId, String oldPassword, String newPassword )
664
throws SerializableException
666
/* check everything except password expiration */
667
SessionInfo session = verifySession (sessionId);
668
// naturally, it is OK to change the password if it expired => false
669
UserInfoWeb user = verifyUser (session, session.getUserId(), false);
671
/* check old password if the user is changing password voluntarily */
672
if ( !isPasswordExpired((UserInfoWeb)user) ) {
673
if ( !oldPassword.equals(user.getPassword()) ) {
674
throw new SerializableException("Old password is incorrect");
677
user.setPassword( newPassword );
678
final long now = System.currentTimeMillis();
679
user.setPasswordExpires( new Long(now + pass_expiration_ms) );
680
EucalyptusManagement.commitWebUser( user );
682
return "Password has been changed";
685
public String updateUserRecord (String sessionId, UserInfoWeb newRecord )
686
throws SerializableException
688
/* perform full checks */
689
SessionInfo session = verifySession (sessionId);
690
UserInfoWeb callerRecord = verifyUser (session, session.getUserId(), true);
691
String userName = newRecord.getUserName();
692
UserInfoWeb oldRecord;
694
oldRecord = EucalyptusManagement.getWebUser(userName);
695
} catch (Exception e) {
696
throw new SerializableException("Username '" + userName + "' not found");
698
if (! callerRecord.isAdministrator()
699
&& ! callerRecord.getUserName().equals(userName)) {
700
throw new SerializableException ("Operation restricted to owner and administrator");
703
// set expiration for admin setting password for the first time
704
if (oldRecord.isAdministrator() && oldRecord.getEmail().equalsIgnoreCase(UserInfo.BOGUS_ENTRY)) {
705
long now = System.currentTimeMillis();
706
oldRecord.setPasswordExpires( new Long(now + pass_expiration_ms) );
709
/* TODO: Any checks? */
710
oldRecord.setRealName (newRecord.getRealName());
711
oldRecord.setEmail (newRecord.getEmail());
712
oldRecord.setPassword (newRecord.getPassword());
713
oldRecord.setTelephoneNumber (newRecord.getTelephoneNumber());
714
oldRecord.setAffiliation (newRecord.getAffiliation());
715
oldRecord.setProjectDescription (newRecord.getProjectDescription());
716
oldRecord.setProjectPIName (newRecord.getProjectPIName());
717
oldRecord.setAdministrator(newRecord.isAdministrator());
718
oldRecord.setEnabled(newRecord.isEnabled( ));
720
// once confirmed, cannot be unconfirmed; also, confirmation implies approval and enablement
721
if (!oldRecord.isConfirmed() && newRecord.isConfirmed()) {
722
oldRecord.setConfirmed(true);
723
oldRecord.setEnabled(true);
724
oldRecord.setApproved(true);
727
EucalyptusManagement.commitWebUser( oldRecord );
729
return "Account of user '" + userName + "' was updated";
732
public List<ClusterInfoWeb> getClusterList(String sessionId) throws SerializableException
734
SessionInfo session = verifySession (sessionId);
735
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
737
return RemoteInfoHandler.getClusterList();
738
} catch ( EucalyptusCloudException e ) {
739
throw new SerializableException( e.getMessage( ) );
743
public void setClusterList(String sessionId, List<ClusterInfoWeb> clusterList ) throws SerializableException
745
SessionInfo session = verifySession (sessionId);
746
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
748
RemoteInfoHandler.setClusterList( clusterList );
749
} catch ( EucalyptusCloudException e ) {
750
throw new SerializableException( e.getMessage( ) );
754
public List<StorageInfoWeb> getStorageList(String sessionId) throws SerializableException
756
SessionInfo session = verifySession (sessionId);
757
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
759
return RemoteInfoHandler.getStorageList();
760
} catch(EucalyptusCloudException e) {
761
throw new SerializableException(e.getMessage());
765
public void setStorageList(String sessionId, List<StorageInfoWeb> storageList ) throws SerializableException
767
SessionInfo session = verifySession (sessionId);
768
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
770
RemoteInfoHandler.setStorageList(storageList);
771
} catch(EucalyptusCloudException e) {
772
throw new SerializableException(e.getMessage());
776
public List<WalrusInfoWeb> getWalrusList(String sessionId) throws SerializableException
778
SessionInfo session = verifySession (sessionId);
779
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
781
return RemoteInfoHandler.getWalrusList();
782
} catch(EucalyptusCloudException e) {
783
throw new SerializableException(e.getMessage());
787
public void setWalrusList(String sessionId, List<WalrusInfoWeb> walrusList ) throws SerializableException
789
SessionInfo session = verifySession (sessionId);
790
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
793
RemoteInfoHandler.setWalrusList(walrusList);
794
} catch(EucalyptusCloudException e) {
795
throw new SerializableException(e.getMessage());
799
public SystemConfigWeb getSystemConfig( final String sessionId ) throws SerializableException
801
SessionInfo session = verifySession (sessionId);
802
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
804
return EucalyptusManagement.getSystemConfig();
807
public void setSystemConfig( final String sessionId, final SystemConfigWeb systemConfig ) throws SerializableException
809
SessionInfo session = verifySession (sessionId);
810
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
812
EucalyptusManagement.setSystemConfig(systemConfig);
815
public List<VmTypeWeb> getVmTypes( final String sessionId ) throws SerializableException
817
SessionInfo session = verifySession (sessionId);
818
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
820
return RemoteInfoHandler.getVmTypes();
823
public void setVmTypes( final String sessionId, final List<VmTypeWeb> vmTypes ) throws SerializableException
825
SessionInfo session = verifySession (sessionId);
826
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
828
RemoteInfoHandler.setVmTypes(vmTypes);
831
public CloudInfoWeb getCloudInfo(final String sessionId, final boolean setExternalHostPort) throws SerializableException
833
SessionInfo session = verifySession (sessionId);
834
UserInfoWeb user = verifyUser (session, session.getUserId(), true);
836
return EucalyptusManagement.getCloudInfo(setExternalHostPort);
839
private static List<DownloadsWeb> getDownloadsFromUrl(final String downloadsUrl) {
840
List<DownloadsWeb> downloadsList = new ArrayList<DownloadsWeb>();
842
HttpClient httpClient = new HttpClient();
843
//support for http proxy
844
if(System.getProperty("http.proxyHost") != null) {
845
String proxyHost = System.getProperty("http.proxyHost");
846
if(System.getProperty("http.proxyPort") != null) {
847
int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort"));
848
httpClient.getHostConfiguration().setProxy(proxyHost, proxyPort);
850
httpClient.getHostConfiguration().setProxyHost(new ProxyHost(proxyHost));
853
GetMethod method = new GetMethod(downloadsUrl);
854
Integer timeoutMs = new Integer(3 * 1000);
855
method.getParams().setSoTimeout(timeoutMs);
858
httpClient.executeMethod(method);
860
InputStream in = method.getResponseBodyAsStream();
861
byte[] readBytes = new byte[1024];
863
while((bytesRead = in.read(readBytes)) > 0) {
864
str += new String(readBytes, 0, bytesRead);
866
String entries[] = str.split("[\\r\\n]+");
867
for (int i=0; i<entries.length; i++) {
868
String entry[] = entries[i].split("\\t");
869
if (entry.length == 3) {
870
downloadsList.add (new DownloadsWeb(entry[0], entry[1], entry[2]));
874
} catch (MalformedURLException e) {
875
LOG.warn("Malformed URL exception: " + e.getMessage());
878
} catch (IOException e) {
879
LOG.warn("I/O exception: " + e.getMessage());
883
method.releaseConnection();
886
return downloadsList;
889
public List<DownloadsWeb> getDownloads(final String sessionId, final String downloadsUrl) throws SerializableException {
890
SessionInfo session = verifySession(sessionId);
891
UserInfoWeb user = verifyUser(session, session.getUserId(), true);
892
return getDownloadsFromUrl(downloadsUrl);
896
* Overridden to really throw Jetty RetryRequest Exception (as opposed to sending failure to client).
898
* @param caught the exception
900
protected void doUnexpectedFailure(Throwable caught)
902
throwIfRetryRequest(caught);
903
super.doUnexpectedFailure(caught);
905
private static final String JETTY_RETRY_REQUEST_EXCEPTION = "org.mortbay.jetty.RetryRequest";
907
* Throws the Jetty RetryRequest if found.
909
* @param caught the exception
911
protected void throwIfRetryRequest(Throwable caught)
913
if (caught instanceof UnexpectedException )
915
caught = caught.getCause();
918
if (JETTY_RETRY_REQUEST_EXCEPTION.equals(caught.getClass().getName()))
920
throw (RuntimeException)caught;