Merge branch '2.1.x' of ssh://git.cloud.com/var/lib/git/cloudstack-oss into 2.1.x

This commit is contained in:
Jessica Wang 2010-08-19 14:41:55 -07:00
commit d0f960a50c
9 changed files with 421 additions and 289 deletions

3
.gitignore vendored
View File

@ -12,4 +12,5 @@ dist
*~
*.bak
cloud-*.tar.bz2
*.pyc
build.number

View File

@ -125,7 +125,7 @@ except IndexError: e("The first argument must be the license file to use")
if options.all:
if len(args) != 0: e("IP addresses cannot be specified if -a is specified")
config = cloud_utils.read_properties(cfg)
config = read_properties(cfg)
creds = getknownhosts(config["db.cloud.host"],config["db.cloud.username"],config["db.cloud.password"])
hosts = creds.keys()
else:

View File

@ -52,6 +52,7 @@ public class DataCenterLinkLocalIpAddressDaoImpl extends GenericDaoBase<DataCent
SearchCriteria sc = FreeIpSearch.create();
sc.setParameters("dc", dcId);
sc.setParameters("pod", podId);
sc.setParameters("ipAddr", NetUtils.getLinkLocalGateway()); /*explicitly removing the gateway*/
Transaction txn = Transaction.currentTxn();
try {
@ -141,6 +142,7 @@ public class DataCenterLinkLocalIpAddressDaoImpl extends GenericDaoBase<DataCent
FreeIpSearch = createSearchBuilder();
FreeIpSearch.and("dc", FreeIpSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
FreeIpSearch.and("pod", FreeIpSearch.entity().getPodId(), SearchCriteria.Op.EQ);
FreeIpSearch.and("ipAddr", FreeIpSearch.entity().getIpAddress(), SearchCriteria.Op.NEQ);
FreeIpSearch.and("taken", FreeIpSearch.entity().getTakenAt(), SearchCriteria.Op.NULL);
FreeIpSearch.done();

View File

@ -167,6 +167,7 @@ public enum Status {
s_fsm.addTransition(Status.Disconnected, Event.Ping, Status.Up);
s_fsm.addTransition(Status.Disconnected, Event.ManagementServerDown, Status.Disconnected);
s_fsm.addTransition(Status.Disconnected, Event.WaitedTooLong, Status.Alert);
s_fsm.addTransition(Status.Disconnected, Event.Remove, Status.Removed);
s_fsm.addTransition(Status.Down, Event.MaintenanceRequested, Status.PrepareForMaintenance);
s_fsm.addTransition(Status.Down, Event.AgentConnected, Status.Connecting);
s_fsm.addTransition(Status.Down, Event.Remove, Status.Removed);

View File

@ -75,6 +75,13 @@ public class AddHostCmd extends BaseCmd {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Can't specify cluster by both id and name");
}
if (clusterName == null && clusterId == null) {
// Stand alone, assign a name to it
String[] stringarray = url.split("//");
String address = stringarray[stringarray.length - 1];
clusterName = "Standalone-" + address;
}
if ((clusterName != null || clusterId != null) && podId == null) {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Can't specify cluster without specifying the pod");
}

View File

@ -81,7 +81,6 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
protected String _privateNic;
protected String _storageNic1;
protected String _storageNic2;
protected boolean _formPoolsInPod;
protected int _wait;
protected XenServerConnectionPool _connPool;
protected String _increase;
@ -132,19 +131,6 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
String cluster = null;
if (clusterId != null) {
cluster = Long.toString(clusterId);
} else if (_formPoolsInPod) {
if (podId != null) {
List<ClusterVO> clusters = _clusterDao.listByPodId(podId);
if (clusters.size() > 1) {
throw new DiscoveryException("There are more than one cluster in the pod and we don't know which to add to.");
} else if (clusters.size() == 1) {
clusterId = clusters.get(0).getId();
cluster = Long.toString(clusterId);
} else {
Map<Pool, Pool.Record> pools = Pool.getAllRecords(conn);
cluster = pools.values().iterator().next().uuid;
}
}
}
Map<Host, Host.Record> hosts = Host.getAllRecords(conn);
@ -300,7 +286,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
if ( resources.size() == 0 ) {
return false;
}
if (clusterId == null && !_formPoolsInPod) {
if (clusterId == null ) {
if (resources.size() > 1) {
s_logger.warn("There's no cluster specified but we found a pool of xenservers " + resources.size());
throw new DiscoveryException("There's no cluster specified but we found a pool of xenservers " + resources.size());
@ -437,9 +423,6 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
value = _params.get("xen.check.hvm");
_checkHvm = value == null ? true : Boolean.parseBoolean(value);
value = _params.get(Config.CreatePoolsInPod.key());
_formPoolsInPod = Boolean.parseBoolean(value);
_connPool = XenServerConnectionPool.getInstance();

66
server/src/com/cloud/network/NetworkManagerImpl.java Executable file → Normal file
View File

@ -221,6 +221,9 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager
final long accountId = account.getId();
// use a dedicated account object for locking test, so that when we get SQL exception
// we won't be misled to release an actually un-owned lock
AccountVO lockedAccount = null;
Transaction txn = Transaction.currentTxn();
try {
final EventVO event = new EventVO();
@ -230,8 +233,8 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager
txn.start();
account = _accountDao.acquire(accountId);
if (account == null) {
lockedAccount = _accountDao.acquire(accountId);
if (lockedAccount == null) {
s_logger.warn("Unable to lock account " + accountId);
return null;
}
@ -339,7 +342,7 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager
txn.commit();
return null;
} finally {
if (account != null) {
if (lockedAccount != null) {
if(s_logger.isDebugEnabled())
s_logger.debug("Releasing lock account " + accountId);
@ -767,6 +770,9 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager
if(s_logger.isDebugEnabled())
s_logger.debug("Lock on router " + routerId + " is acquired");
boolean started = false;
String vnet = null;
boolean vnetAllocated = false;
try {
final State state = router.getState();
if (state == State.Running) {
@ -813,10 +819,7 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager
throw new ConcurrentOperationException("Someone else is starting the router: " + router.toString());
}
String vnet = null;
boolean vnetAllocated = false;
final boolean mirroredVols = router.isMirroredVols();
boolean started = false;
try {
event = new EventVO();
event.setUserId(1L);
@ -829,6 +832,7 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager
for (final UserVmVO vm : vms) {
if (vm.getVnet() != null) {
vnet = vm.getVnet();
break;
}
}
}
@ -841,7 +845,9 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager
vnet = _dcDao.allocateVnet(router.getDataCenterId(), router.getAccountId());
}
vnetAllocated = true;
routerMacAddress = getRouterMacForVnet(dc, vnet);
if(vnet != null){
routerMacAddress = getRouterMacForVnet(dc, vnet);
}
} else if (router.getRole() == Role.DHCP_USERDATA) {
if (!Vlan.UNTAGGED.equals(router.getVlanId())) {
vnet = router.getVlanId().trim();
@ -964,28 +970,6 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager
return _routerDao.findById(routerId);
} catch (final Throwable th) {
Transaction txn = Transaction.currentTxn();
if (!started) {
txn.start();
if (vnetAllocated == true && vnet != null) {
_dcDao.releaseVnet(vnet, router.getDataCenterId(), router.getAccountId());
}
router.setVnet(null);
String privateIpAddress = router.getPrivateIpAddress();
router.setPrivateIpAddress(null);
if (privateIpAddress != null) {
_dcDao.releasePrivateIpAddress(privateIpAddress, router.getDataCenterId(), router.getId());
}
if (_routerDao.updateIf(router, Event.OperationFailed, null)) {
txn.commit();
}
}
if (th instanceof ExecutionException) {
s_logger.error("Error while starting router due to " + th.getMessage());
} else if (th instanceof ConcurrentOperationException) {
@ -998,8 +982,30 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager
return null;
}
} finally {
if (!started){
Transaction txn = Transaction.currentTxn();
txn.start();
if (vnetAllocated == true && vnet != null) {
_dcDao.releaseVnet(vnet, router.getDataCenterId(), router.getAccountId());
}
router.setVnet(null);
String privateIpAddress = router.getPrivateIpAddress();
router.setPrivateIpAddress(null);
if (privateIpAddress != null) {
_dcDao.releasePrivateIpAddress(privateIpAddress, router.getDataCenterId(), router.getId());
}
if (_routerDao.updateIf(router, Event.OperationFailed, null)) {
txn.commit();
}
}
if (router != null) {
if(s_logger.isDebugEnabled())
s_logger.debug("Releasing lock on router " + routerId);
_routerDao.release(routerId);

View File

@ -16,56 +16,81 @@
*
*/
package com.cloud.servlet;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
package com.cloud.servlet;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import org.apache.log4j.Logger;
import com.cloud.api.BaseCmd;
import com.cloud.host.HostVO;
import com.cloud.server.ManagementServer;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.encoding.Base64;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
/**
* Thumbnail access : /console?cmd=thumbnail&vm=xxx&w=xxx&h=xxx
* Console access : /conosole?cmd=access&vm=xxx
* Authentication : /console?cmd=auth&vm=xxx&sid=xxx
*/
public class ConsoleProxyServlet extends HttpServlet {
private static final long serialVersionUID = -5515382620323808168L;
public static final Logger s_logger = Logger.getLogger(ConsoleProxyServlet.class.getName());
private static final int DEFAULT_THUMBNAIL_WIDTH = 144;
private static final int DEFAULT_THUMBNAIL_HEIGHT = 110;
private final ManagementServer _ms = (ManagementServer)ComponentLocator.getComponent(ManagementServer.Name);
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
/**
* Thumbnail access : /console?cmd=thumbnail&vm=xxx&w=xxx&h=xxx
* Console access : /conosole?cmd=access&vm=xxx
* Authentication : /console?cmd=auth&vm=xxx&sid=xxx
*/
public class ConsoleProxyServlet extends HttpServlet {
private static final long serialVersionUID = -5515382620323808168L;
public static final Logger s_logger = Logger.getLogger(ConsoleProxyServlet.class.getName());
private static final int DEFAULT_THUMBNAIL_WIDTH = 144;
private static final int DEFAULT_THUMBNAIL_HEIGHT = 110;
private final ManagementServer _ms = (ManagementServer)ComponentLocator.getComponent(ManagementServer.Name);
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
try {
String userId = null;
String account = null;
Account accountObj = null;
Map<String, Object[]> params = new HashMap<String, Object[]>();
params.putAll(req.getParameterMap());
HttpSession session = req.getSession(false);
if(session == null) {
s_logger.info("Invalid web session, reject console/thumbnail access");
sendResponse(resp, "Access denied. You haven't logged in or your web session has timed out");
return;
if(verifyRequest(params)) {
userId = (String)params.get(BaseCmd.Properties.USER_ID.getName())[0];
account = (String)params.get(BaseCmd.Properties.ACCOUNT.getName())[0];
accountObj = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName())[0];
} else {
s_logger.info("Invalid web session or API key in request, reject console/thumbnail access");
sendResponse(resp, "Access denied. Invalid web session or API key in request");
return;
}
} else {
userId = (String)session.getAttribute(BaseCmd.Properties.USER_ID.getName());
account = (String)session.getAttribute(BaseCmd.Properties.ACCOUNT.getName());
accountObj = (Account)session.getAttribute(BaseCmd.Properties.ACCOUNT_OBJ.getName());
}
String userId = (String)session.getAttribute("userId");
String account = (String)session.getAttribute("account");
Account accountObj = (Account)session.getAttribute("accountobj");
// Do a sanity check here to make sure the user hasn't already been deleted
if ((userId == null) || (account == null) || (accountObj == null) || !verifyUser(Long.valueOf(userId))) {
@ -73,202 +98,199 @@ public class ConsoleProxyServlet extends HttpServlet {
sendResponse(resp, "Access denied. Invalid or inconsistent account is found");
return;
}
String cmd = req.getParameter("cmd");
if(cmd == null || !isValidCmd(cmd)) {
s_logger.info("invalid console servlet command: " + cmd);
sendResponse(resp, "");
return;
}
String vmIdString = req.getParameter("vm");
long vmId = 0;
try {
vmId = Long.parseLong(vmIdString);
} catch(NumberFormatException e) {
s_logger.info("invalid console servlet command parameter: " + vmIdString);
sendResponse(resp, "");
return;
}
if(!checkSessionPermision(req, vmId)) {
sendResponse(resp, "Permission denied");
return;
}
if(cmd.equalsIgnoreCase("thumbnail"))
handleThumbnailRequest(req, resp, vmId);
else if(cmd.equalsIgnoreCase("access"))
handleAccessRequest(req, resp, vmId);
else
handleAuthRequest(req, resp, vmId);
} catch (Throwable e) {
s_logger.error("Unexepected exception in ConsoleProxyServlet", e);
sendResponse(resp, "");
}
}
private void handleThumbnailRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) {
VMInstanceVO vm = _ms.findVMInstanceById(vmId);
if(vm == null) {
s_logger.warn("VM " + vmId + " does not exist, sending blank response for thumbnail request");
sendResponse(resp, "");
return;
}
if(vm.getHostId() == null) {
s_logger.warn("VM " + vmId + " lost host info, sending blank response for thumbnail request");
sendResponse(resp, "");
return;
}
HostVO host = _ms.getHostBy(vm.getHostId());
if(host == null) {
s_logger.warn("VM " + vmId + "'s host does not exist, sending blank response for thumbnail request");
sendResponse(resp, "");
return;
}
String rootUrl = _ms.getConsoleAccessUrlRoot(vmId);
if(rootUrl == null) {
sendResponse(resp, "");
return;
}
int w = DEFAULT_THUMBNAIL_WIDTH;
int h = DEFAULT_THUMBNAIL_HEIGHT;
String value = req.getParameter("w");
try {
w = Integer.parseInt(value);
} catch(NumberFormatException e) {
}
value = req.getParameter("h");
try {
h = Integer.parseInt(value);
} catch(NumberFormatException e) {
}
try {
resp.sendRedirect(composeThumbnailUrl(rootUrl, vm, host, w, h));
} catch (IOException e) {
if(s_logger.isInfoEnabled())
s_logger.info("Client may already close the connection");
}
}
private void handleAccessRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) {
VMInstanceVO vm = _ms.findVMInstanceById(vmId);
if(vm == null) {
s_logger.warn("VM " + vmId + " does not exist, sending blank response for console access request");
sendResponse(resp, "");
return;
}
if(vm.getHostId() == null) {
s_logger.warn("VM " + vmId + " lost host info, sending blank response for console access request");
sendResponse(resp, "");
return;
}
HostVO host = _ms.getHostBy(vm.getHostId());
if(host == null) {
s_logger.warn("VM " + vmId + "'s host does not exist, sending blank response for console access request");
sendResponse(resp, "");
return;
}
String rootUrl = _ms.getConsoleAccessUrlRoot(vmId);
if(rootUrl == null) {
sendResponse(resp, "<html><body><p>Console access will be ready in a few minutes. Please try it again later.</p></body></html>");
return;
}
String cmd = req.getParameter("cmd");
if(cmd == null || !isValidCmd(cmd)) {
s_logger.info("invalid console servlet command: " + cmd);
sendResponse(resp, "");
return;
}
String vmIdString = req.getParameter("vm");
long vmId = 0;
try {
vmId = Long.parseLong(vmIdString);
} catch(NumberFormatException e) {
s_logger.info("invalid console servlet command parameter: " + vmIdString);
sendResponse(resp, "");
return;
}
if(!checkSessionPermision(req, vmId, accountObj)) {
sendResponse(resp, "Permission denied");
return;
}
if(cmd.equalsIgnoreCase("thumbnail"))
handleThumbnailRequest(req, resp, vmId);
else if(cmd.equalsIgnoreCase("access"))
handleAccessRequest(req, resp, vmId);
else
handleAuthRequest(req, resp, vmId);
} catch (Throwable e) {
s_logger.error("Unexepected exception in ConsoleProxyServlet", e);
sendResponse(resp, "Server Internal Error");
}
}
private void handleThumbnailRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) {
VMInstanceVO vm = _ms.findVMInstanceById(vmId);
if(vm == null) {
s_logger.warn("VM " + vmId + " does not exist, sending blank response for thumbnail request");
sendResponse(resp, "");
return;
}
if(vm.getHostId() == null) {
s_logger.warn("VM " + vmId + " lost host info, sending blank response for thumbnail request");
sendResponse(resp, "");
return;
}
HostVO host = _ms.getHostBy(vm.getHostId());
if(host == null) {
s_logger.warn("VM " + vmId + "'s host does not exist, sending blank response for thumbnail request");
sendResponse(resp, "");
return;
}
String rootUrl = _ms.getConsoleAccessUrlRoot(vmId);
if(rootUrl == null) {
sendResponse(resp, "");
return;
}
int w = DEFAULT_THUMBNAIL_WIDTH;
int h = DEFAULT_THUMBNAIL_HEIGHT;
String value = req.getParameter("w");
try {
w = Integer.parseInt(value);
} catch(NumberFormatException e) {
}
value = req.getParameter("h");
try {
h = Integer.parseInt(value);
} catch(NumberFormatException e) {
}
try {
resp.sendRedirect(composeThumbnailUrl(rootUrl, vm, host, w, h));
} catch (IOException e) {
if(s_logger.isInfoEnabled())
s_logger.info("Client may already close the connection");
}
}
private void handleAccessRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) {
VMInstanceVO vm = _ms.findVMInstanceById(vmId);
if(vm == null) {
s_logger.warn("VM " + vmId + " does not exist, sending blank response for console access request");
sendResponse(resp, "");
return;
}
if(vm.getHostId() == null) {
s_logger.warn("VM " + vmId + " lost host info, sending blank response for console access request");
sendResponse(resp, "");
return;
}
HostVO host = _ms.getHostBy(vm.getHostId());
if(host == null) {
s_logger.warn("VM " + vmId + "'s host does not exist, sending blank response for console access request");
sendResponse(resp, "");
return;
}
String rootUrl = _ms.getConsoleAccessUrlRoot(vmId);
if(rootUrl == null) {
sendResponse(resp, "<html><body><p>Console access will be ready in a few minutes. Please try it again later.</p></body></html>");
return;
}
String vmName = vm.getName();
if(vmName == null)
vmName = vm.getInstanceName();
StringBuffer sb = new StringBuffer();
sb.append("<html><title>").append(vmName).append("</title><frameset><frame src=\"").append(composeConsoleAccessUrl(rootUrl, vm, host));
sb.append("\"></frame></frameset></html>");
sendResponse(resp, sb.toString());
}
private void handleAuthRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) {
// TODO authentication channel between console proxy VM and management server needs to be secured,
// the data is now being sent through private network, but this is apparently not enough
VMInstanceVO vm = _ms.findVMInstanceById(vmId);
if(vm == null) {
s_logger.warn("VM " + vmId + " does not exist, sending failed response for authentication request from console proxy");
sendResponse(resp, "failed");
return;
}
if(vm.getHostId() == null) {
s_logger.warn("VM " + vmId + " lost host info, failed response for authentication request from console proxy");
sendResponse(resp, "failed");
return;
}
HostVO host = _ms.getHostBy(vm.getHostId());
if(host == null) {
s_logger.warn("VM " + vmId + "'s host does not exist, sending failed response for authentication request from console proxy");
sendResponse(resp, "failed");
return;
}
String sid = req.getParameter("sid");
if(sid == null || !sid.equals(vm.getVncPassword())) {
s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword());
sendResponse(resp, "failed");
return;
}
sendResponse(resp, "success");
}
private String composeThumbnailUrl(String rootUrl, VMInstanceVO vm, HostVO host, int w, int h) {
StringBuffer sb = new StringBuffer(rootUrl);
sb.append("/getscreen?host=").append(host.getPrivateIpAddress());
sb.append("&port=").append(_ms.getVncPort(vm));
sb.append("&sid=").append(vm.getVncPassword());
sb.append("&w=").append(w).append("&h=").append(h);
sb.append("&tag=").append(vm.getId());
if(s_logger.isInfoEnabled())
s_logger.info("Compose thumbnail url: " + sb.toString());
return sb.toString();
}
private String composeConsoleAccessUrl(String rootUrl, VMInstanceVO vm, HostVO host) {
StringBuffer sb = new StringBuffer(rootUrl);
sb.append("/ajax?host=").append(host.getPrivateIpAddress());
sb.append("&port=").append(_ms.getVncPort(vm));
sb.append("&sid=").append(vm.getVncPassword());
sb.append("&tag=").append(vm.getId());
if(s_logger.isInfoEnabled())
s_logger.info("Compose console url: " + sb.toString());
return sb.toString();
}
private void sendResponse(HttpServletResponse resp, String content) {
try {
resp.getWriter().print(content);
} catch(IOException e) {
if(s_logger.isInfoEnabled())
s_logger.info("Client may already close the connection");
}
}
private boolean checkSessionPermision(HttpServletRequest req, long vmId) {
StringBuffer sb = new StringBuffer();
sb.append("<html><title>").append(vmName).append("</title><frameset><frame src=\"").append(composeConsoleAccessUrl(rootUrl, vm, host));
sb.append("\"></frame></frameset></html>");
sendResponse(resp, sb.toString());
}
private void handleAuthRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) {
// TODO authentication channel between console proxy VM and management server needs to be secured,
// the data is now being sent through private network, but this is apparently not enough
VMInstanceVO vm = _ms.findVMInstanceById(vmId);
if(vm == null) {
s_logger.warn("VM " + vmId + " does not exist, sending failed response for authentication request from console proxy");
sendResponse(resp, "failed");
return;
}
if(vm.getHostId() == null) {
s_logger.warn("VM " + vmId + " lost host info, failed response for authentication request from console proxy");
sendResponse(resp, "failed");
return;
}
HostVO host = _ms.getHostBy(vm.getHostId());
if(host == null) {
s_logger.warn("VM " + vmId + "'s host does not exist, sending failed response for authentication request from console proxy");
sendResponse(resp, "failed");
return;
}
String sid = req.getParameter("sid");
if(sid == null || !sid.equals(vm.getVncPassword())) {
s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword());
sendResponse(resp, "failed");
return;
}
sendResponse(resp, "success");
}
private String composeThumbnailUrl(String rootUrl, VMInstanceVO vm, HostVO host, int w, int h) {
StringBuffer sb = new StringBuffer(rootUrl);
sb.append("/getscreen?host=").append(host.getPrivateIpAddress());
sb.append("&port=").append(_ms.getVncPort(vm));
sb.append("&sid=").append(vm.getVncPassword());
sb.append("&w=").append(w).append("&h=").append(h);
sb.append("&tag=").append(vm.getId());
if(s_logger.isInfoEnabled())
s_logger.info("Compose thumbnail url: " + sb.toString());
return sb.toString();
}
private String composeConsoleAccessUrl(String rootUrl, VMInstanceVO vm, HostVO host) {
StringBuffer sb = new StringBuffer(rootUrl);
sb.append("/ajax?host=").append(host.getPrivateIpAddress());
sb.append("&port=").append(_ms.getVncPort(vm));
sb.append("&sid=").append(vm.getVncPassword());
sb.append("&tag=").append(vm.getId());
if(s_logger.isInfoEnabled())
s_logger.info("Compose console url: " + sb.toString());
return sb.toString();
}
private void sendResponse(HttpServletResponse resp, String content) {
try {
resp.getWriter().print(content);
} catch(IOException e) {
if(s_logger.isInfoEnabled())
s_logger.info("Client may already close the connection");
}
}
private boolean checkSessionPermision(HttpServletRequest req, long vmId, Account accountObj) {
HttpSession session = req.getSession(false);
Account accountObj = (Account)session.getAttribute("accountobj");
VMInstanceVO vm = _ms.findVMInstanceById(vmId);
UserVmVO userVm;
switch(vm.getType())
@ -295,14 +317,14 @@ public class ConsoleProxyServlet extends HttpServlet {
break;
}
return true;
}
private boolean isValidCmd(String cmd) {
if(cmd.equalsIgnoreCase("thumbnail") || cmd.equalsIgnoreCase("access") || cmd.equalsIgnoreCase("auth"))
return true;
return false;
return true;
}
private boolean isValidCmd(String cmd) {
if(cmd.equalsIgnoreCase("thumbnail") || cmd.equalsIgnoreCase("access") || cmd.equalsIgnoreCase("auth"))
return true;
return false;
}
public boolean verifyUser(Long userId) {
@ -320,4 +342,106 @@ public class ConsoleProxyServlet extends HttpServlet {
}
return true;
}
}
// copied and modified from ApiServer.java.
// TODO need to replace the whole servlet with a API command
private boolean verifyRequest(Map<String, Object[]> requestParameters) {
try {
String apiKey = null;
String secretKey = null;
String signature = null;
String unsignedRequest = null;
// - build a request string with sorted params, make sure it's all lowercase
// - sign the request, verify the signature is the same
List<String> parameterNames = new ArrayList<String>();
for (Object paramNameObj : requestParameters.keySet()) {
parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later
}
Collections.sort(parameterNames);
for (String paramName : parameterNames) {
// parameters come as name/value pairs in the form String/String[]
String paramValue = ((String[])requestParameters.get(paramName))[0];
if ("signature".equalsIgnoreCase(paramName)) {
signature = paramValue;
} else {
if ("apikey".equalsIgnoreCase(paramName)) {
apiKey = paramValue;
}
if (unsignedRequest == null) {
unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
} else {
unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20");
}
}
}
// if api/secret key are passed to the parameters
if ((signature == null) || (apiKey == null)) {
if (s_logger.isDebugEnabled()) {
s_logger.info("expired session, missing signature, or missing apiKey -- ignoring request...sig: " + signature + ", apiKey: " + apiKey);
}
return false; // no signature, bad request
}
Transaction txn = Transaction.open(Transaction.CLOUD_DB);
txn.close();
User user = null;
// verify there is a user with this api key
Pair<User, Account> userAcctPair = _ms.findUserByApiKey(apiKey);
if (userAcctPair == null) {
s_logger.info("apiKey does not map to a valid user -- ignoring request, apiKey: " + apiKey);
return false;
}
user = userAcctPair.first();
Account account = userAcctPair.second();
if (!user.getState().equals(Account.ACCOUNT_STATE_ENABLED) || !account.getState().equals(Account.ACCOUNT_STATE_ENABLED)) {
s_logger.info("disabled or locked user accessing the api, userid = " + user.getId() + "; name = " + user.getUsername() + "; state: " + user.getState() + "; accountState: " + account.getState());
return false;
}
if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) {
requestParameters.put(BaseCmd.Properties.USER_ID.getName(), new String[] { user.getId().toString() });
requestParameters.put(BaseCmd.Properties.ACCOUNT.getName(), new String[] { account.getAccountName() });
requestParameters.put(BaseCmd.Properties.DOMAIN_ID.getName(), new String[] { account.getDomainId().toString() });
requestParameters.put(BaseCmd.Properties.ACCOUNT_OBJ.getName(), new Object[] { account });
} else {
requestParameters.put(BaseCmd.Properties.USER_ID.getName(), new String[] { user.getId().toString() });
requestParameters.put(BaseCmd.Properties.ACCOUNT.getName(), new String[] { account.getAccountName() });
requestParameters.put(BaseCmd.Properties.ACCOUNT_OBJ.getName(), new Object[] { account });
}
// verify secret key exists
secretKey = user.getSecretKey();
if (secretKey == null) {
s_logger.info("User does not have a secret key associated with the account -- ignoring request, username: " + user.getUsername());
return false;
}
unsignedRequest = unsignedRequest.toLowerCase();
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1");
mac.init(keySpec);
mac.update(unsignedRequest.getBytes());
byte[] encryptedBytes = mac.doFinal();
String computedSignature = Base64.encodeBytes(encryptedBytes);
boolean equalSig = signature.equals(computedSignature);
if (!equalSig) {
s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature);
}
return equalSig;
} catch (Exception ex) {
s_logger.error("unable to verifty request signature", ex);
}
return false;
}
}

View File

@ -668,7 +668,15 @@ public class NetUtils {
return null;
}
/*reserve gateway*/
return getIpRangeFromCidr(getLinkLocalGateway(), 32 - size);
String[] range = getIpRangeFromCidr(getLinkLocalGateway(), 32 - size);
if (range[0].equalsIgnoreCase(getLinkLocalGateway())) {
/*remove the gateway*/
long ip = ip2Long(range[0]);
ip += 1;
range[0] = long2Ip(ip);
}
return range;
}
public static String getLinkLocalIpEnd() {