You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2012/12/23 07:35:44 UTC
[4/4] Create DB views to improve ListHostsCmd performance.
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/e7fa1a86/server/src/com/cloud/storage/StorageManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java
index 1f625d3..824af6a 100755
--- a/server/src/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/com/cloud/storage/StorageManagerImpl.java
@@ -431,8 +431,8 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
}
@Override
- public boolean isLocalStorageActiveOnHost(Host host) {
- List<StoragePoolHostVO> storagePoolHostRefs = _storagePoolHostDao.listByHostId(host.getId());
+ public boolean isLocalStorageActiveOnHost(Long hostId) {
+ List<StoragePoolHostVO> storagePoolHostRefs = _storagePoolHostDao.listByHostId(hostId);
for (StoragePoolHostVO storagePoolHostRef : storagePoolHostRefs) {
StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolHostRef.getPoolId());
if (storagePool.getPoolType() == StoragePoolType.LVM || storagePool.getPoolType() == StoragePoolType.EXT) {
@@ -652,7 +652,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
Pair<VolumeVO, String> volumeDetails = createVolumeFromSnapshot(volume, snapshot);
if (volumeDetails != null) {
createdVolume = volumeDetails.first();
- UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, createdVolume.getAccountId(), createdVolume.getDataCenterId(), createdVolume.getId(), createdVolume.getName(),
+ UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, createdVolume.getAccountId(), createdVolume.getDataCenterId(), createdVolume.getId(), createdVolume.getName(),
createdVolume.getDiskOfferingId(), null, createdVolume.getSize());
_usageEventDao.persist(usageEvent);
}
@@ -737,21 +737,21 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
@DB
public VolumeVO copyVolumeFromSecToPrimary(VolumeVO volume, VMInstanceVO vm, VMTemplateVO template, DataCenterVO dc, HostPodVO pod, Long clusterId, ServiceOfferingVO offering, DiskOfferingVO diskOffering,
List<StoragePoolVO> avoids, long size, HypervisorType hyperType) throws NoTransitionException {
-
+
final HashSet<StoragePool> avoidPools = new HashSet<StoragePool>(avoids);
DiskProfile dskCh = createDiskCharacteristics(volume, template, dc, diskOffering);
dskCh.setHyperType(vm.getHypervisorType());
- // Find a suitable storage to create volume on
+ // Find a suitable storage to create volume on
StoragePoolVO destPool = findStoragePool(dskCh, dc, pod, clusterId, null, vm, avoidPools);
-
- // Copy the volume from secondary storage to the destination storage pool
+
+ // Copy the volume from secondary storage to the destination storage pool
stateTransitTo(volume, Event.CopyRequested);
VolumeHostVO volumeHostVO = _volumeHostDao.findByVolumeId(volume.getId());
HostVO secStorage = _hostDao.findById(volumeHostVO.getHostId());
String secondaryStorageURL = secStorage.getStorageUrl();
String[] volumePath = volumeHostVO.getInstallPath().split("/");
String volumeUUID = volumePath[volumePath.length - 1].split("\\.")[0];
-
+
CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volumeUUID, destPool, secondaryStorageURL, false, _copyvolumewait);
CopyVolumeAnswer cvAnswer;
try {
@@ -764,23 +764,23 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
if (cvAnswer == null || !cvAnswer.getResult()) {
stateTransitTo(volume, Event.CopyFailed);
throw new CloudRuntimeException("Failed to copy the volume from secondary storage to the destination primary storage pool.");
- }
+ }
Transaction txn = Transaction.currentTxn();
- txn.start();
+ txn.start();
volume.setPath(cvAnswer.getVolumePath());
volume.setFolder(destPool.getPath());
volume.setPodId(destPool.getPodId());
- volume.setPoolId(destPool.getId());
+ volume.setPoolId(destPool.getId());
volume.setPodId(destPool.getPodId());
- stateTransitTo(volume, Event.CopySucceeded);
+ stateTransitTo(volume, Event.CopySucceeded);
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), volume.getDiskOfferingId(), null, volume.getSize());
_usageEventDao.persist(usageEvent);
_volumeHostDao.remove(volumeHostVO.getId());
txn.commit();
return volume;
-
+
}
-
+
@Override
@DB
public VolumeVO createVolume(VolumeVO volume, VMInstanceVO vm, VMTemplateVO template, DataCenterVO dc, HostPodVO pod, Long clusterId, ServiceOfferingVO offering, DiskOfferingVO diskOffering,
@@ -975,7 +975,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
value = configDao.getValue(Config.RecreateSystemVmEnabled.key());
_recreateSystemVmEnabled = Boolean.parseBoolean(value);
-
+
value = configDao.getValue(Config.StorageTemplateCleanupEnabled.key());
_templateCleanupEnabled = (value == null ? true : Boolean.parseBoolean(value));
@@ -1517,7 +1517,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
}
if(sPool.getStatus() != StoragePoolStatus.Maintenance){
s_logger.warn("Unable to delete storage id: " + id +" due to it is not in Maintenance state");
- throw new InvalidParameterValueException("Unable to delete storage due to it is not in Maintenance state, id: " + id);
+ throw new InvalidParameterValueException("Unable to delete storage due to it is not in Maintenance state, id: " + id);
}
if (sPool.getPoolType().equals(StoragePoolType.LVM) || sPool.getPoolType().equals(StoragePoolType.EXT)) {
s_logger.warn("Unable to delete local storage id:" + id);
@@ -1546,7 +1546,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
" for this pool");
}
}
-
+
// First get the host_id from storage_pool_host_ref for given pool id
StoragePoolVO lock = _storagePoolDao.acquireInLockTable(sPool.getId());
@@ -1740,10 +1740,10 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
return _volsDao.findById(volume.getId());
}
-
+
/*
* Upload the volume to secondary storage.
- *
+ *
*/
@Override
@DB
@@ -1755,13 +1755,13 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
String volumeName = cmd.getVolumeName();
String url = cmd.getUrl();
String format = cmd.getFormat();
-
+
validateVolume(caller, ownerId, zoneId, volumeName, url, format);
VolumeVO volume = persistVolume(caller, ownerId, zoneId, volumeName, url, cmd.getFormat());
_downloadMonitor.downloadVolumeToStorage(volume, zoneId, url, cmd.getChecksum(), ImageFormat.valueOf(format.toUpperCase()));
- return volume;
+ return volume;
}
-
+
private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format) throws ResourceAllocationException{
// permission check
@@ -1769,7 +1769,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
// Check that the resource limit for volumes won't be exceeded
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.volume);
-
+
// Verify that zone exists
DataCenterVO zone = _dcDao.findById(zoneId);
@@ -1781,22 +1781,22 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) {
throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: " + zoneId);
}
-
+
if (url.toLowerCase().contains("file://")) {
throw new InvalidParameterValueException("File:// type urls are currently unsupported");
}
-
+
ImageFormat imgfmt = ImageFormat.valueOf(format.toUpperCase());
if (imgfmt == null) {
throw new IllegalArgumentException("Image format is incorrect " + format + ". Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
}
-
+
String userSpecifiedName = volumeName;
if (userSpecifiedName == null) {
userSpecifiedName = getRandomVolumeName();
}
if((!url.toLowerCase().endsWith("vhd"))&&(!url.toLowerCase().endsWith("vhd.zip"))
- &&(!url.toLowerCase().endsWith("vhd.bz2"))&&(!url.toLowerCase().endsWith("vhd.gz"))
+ &&(!url.toLowerCase().endsWith("vhd.bz2"))&&(!url.toLowerCase().endsWith("vhd.gz"))
&&(!url.toLowerCase().endsWith("qcow2"))&&(!url.toLowerCase().endsWith("qcow2.zip"))
&&(!url.toLowerCase().endsWith("qcow2.bz2"))&&(!url.toLowerCase().endsWith("qcow2.gz"))
&&(!url.toLowerCase().endsWith("ova"))&&(!url.toLowerCase().endsWith("ova.zip"))
@@ -1804,7 +1804,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
&&(!url.toLowerCase().endsWith("img"))&&(!url.toLowerCase().endsWith("raw"))){
throw new InvalidParameterValueException("Please specify a valid " + format.toLowerCase());
}
-
+
if ((format.equalsIgnoreCase("vhd") && (!url.toLowerCase().endsWith(".vhd") && !url.toLowerCase().endsWith("vhd.zip") && !url.toLowerCase().endsWith("vhd.bz2") && !url.toLowerCase().endsWith("vhd.gz") ))
|| (format.equalsIgnoreCase("qcow2") && (!url.toLowerCase().endsWith(".qcow2") && !url.toLowerCase().endsWith("qcow2.zip") && !url.toLowerCase().endsWith("qcow2.bz2") && !url.toLowerCase().endsWith("qcow2.gz") ))
|| (format.equalsIgnoreCase("ova") && (!url.toLowerCase().endsWith(".ova") && !url.toLowerCase().endsWith("ova.zip") && !url.toLowerCase().endsWith("ova.bz2") && !url.toLowerCase().endsWith("ova.gz")))
@@ -1812,14 +1812,14 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
throw new InvalidParameterValueException("Please specify a valid URL. URL:" + url + " is an invalid for the format " + format.toLowerCase());
}
validateUrl(url);
-
+
return false;
}
-
+
private String validateUrl(String url){
try {
URI uri = new URI(url);
- if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("http")
+ if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("http")
&& !uri.getScheme().equalsIgnoreCase("https") && !uri.getScheme().equalsIgnoreCase("file"))) {
throw new IllegalArgumentException("Unsupported scheme for url: " + url);
}
@@ -1840,16 +1840,16 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
} catch (UnknownHostException uhe) {
throw new IllegalArgumentException("Unable to resolve " + host);
}
-
+
return uri.toString();
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid URL " + url);
}
-
+
}
-
+
private VolumeVO persistVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format) {
-
+
Transaction txn = Transaction.currentTxn();
txn.start();
@@ -1860,7 +1860,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
volume.setAccountId(ownerId);
volume.setDomainId(((caller == null) ? Domain.ROOT_DOMAIN : caller.getDomainId()));
long diskOfferingId = _diskOfferingDao.findByUniqueName("Cloud.com-Custom").getId();
- volume.setDiskOfferingId(diskOfferingId);
+ volume.setDiskOfferingId(diskOfferingId);
//volume.setSize(size);
volume.setInstanceId(null);
volume.setUpdated(new Date());
@@ -1881,8 +1881,8 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
txn.commit();
return volume;
}
-
-
+
+
/*
* Just allocate a volume in the database, don't send the createvolume cmd to hypervisor. The volume will be finally
* created
@@ -1984,7 +1984,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
* throw new UnsupportedServiceException("operation not supported, snapshot with id " + snapshotId +
* " is created from ROOT volume");
* }
- *
+ *
*/
}
@@ -2189,7 +2189,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
s_logger.debug("Successfully set Capacity - " + totalOverProvCapacity + " for capacity type - " + capacityType + " , DataCenterId - "
+ storagePool.getDataCenterId() + ", HostOrPoolId - " + storagePool.getId() + ", PodId " + storagePool.getPodId());
}
-
+
@Override
public List<Long> getUpHostsInPool(long poolId) {
SearchCriteria<Long> sc = UpHostsInPoolSearch.create();
@@ -2290,7 +2290,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
s_logger.warn("Unable to destroy " + vol.getId(), e);
}
}
-
+
// remove snapshots in Error state
List<SnapshotVO> snapshots = _snapshotDao.listAllByStatus(Snapshot.Status.Error);
for (SnapshotVO snapshotVO : snapshots) {
@@ -2300,7 +2300,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
s_logger.warn("Unable to destroy " + snapshotVO.getId(), e);
}
}
-
+
} finally {
scanLock.unlock();
}
@@ -2439,7 +2439,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
s_logger.warn("problem cleaning up snapshots in secondary storage " + secondaryStorageHost, e2);
}
}
-
+
//CleanUp volumes on Secondary Storage.
for (HostVO secondaryStorageHost : secondaryStorageHosts) {
try {
@@ -2467,7 +2467,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
_volumeHostDao.remove(destroyedVolumeHostVO.getId());
}
}
-
+
}catch (Exception e2) {
s_logger.warn("problem cleaning up volumes in secondary storage " + secondaryStorageHost, e2);
}
@@ -2899,14 +2899,14 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM.");
}
- // Check that volume is completely Uploaded
+ // Check that volume is completely Uploaded
if (volume.getState() == Volume.State.UploadOp){
VolumeHostVO volumeHost = _volumeHostDao.findByVolumeId(volume.getId());
if (volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS){
throw new InvalidParameterValueException("Please specify a volume that is not uploading");
- }
+ }
}
-
+
// Check that the volume is not already destroyed
if (volume.getState() != Volume.State.Destroy) {
if (!destroyVolume(volume)) {
@@ -3258,7 +3258,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
if (s_logger.isDebugEnabled()) {
s_logger.debug("Checking if we need to prepare " + vols.size() + " volumes for " + vm);
}
-
+
boolean recreate = _recreateSystemVmEnabled;
List<VolumeVO> recreateVols = new ArrayList<VolumeVO>(vols.size());
@@ -3270,7 +3270,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
}
if (assignedPool == null && recreate) {
assignedPool = _storagePoolDao.findById(vol.getPoolId());
-
+
}
if (assignedPool != null || recreate) {
Volume.State state = vol.getState();
@@ -3311,7 +3311,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
StoragePoolVO pool = _storagePoolDao.findById(vol.getPoolId());
vm.addDisk(new VolumeTO(vol, pool));
}
-
+
}
}
} else {
@@ -3333,7 +3333,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
existingPool = _storagePoolDao.findById(vol.getPoolId());
s_logger.debug("existing pool: " + existingPool.getId());
}
-
+
if (vol.getState() == Volume.State.Allocated || vol.getState() == Volume.State.Creating) {
newVol = vol;
} else {
@@ -3422,7 +3422,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
if (toBeCreated.getTemplateId() != null) {
template = _templateDao.findById(toBeCreated.getTemplateId());
}
-
+
StoragePool pool = null;
if (sPool != null) {
pool = sPool;
@@ -3506,27 +3506,27 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
if (s_logger.isDebugEnabled()) {
s_logger.debug("Expunging " + vol);
}
-
+
//Find out if the volume is present on secondary storage
VolumeHostVO volumeHost = _volumeHostDao.findByVolumeId(vol.getId());
if(volumeHost != null){
if (volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED){
HostVO ssHost = _hostDao.findById(volumeHost.getHostId());
- DeleteVolumeCommand dtCommand = new DeleteVolumeCommand(ssHost.getStorageUrl(), volumeHost.getInstallPath());
+ DeleteVolumeCommand dtCommand = new DeleteVolumeCommand(ssHost.getStorageUrl(), volumeHost.getInstallPath());
Answer answer = _agentMgr.sendToSecStorage(ssHost, dtCommand);
if (answer == null || !answer.getResult()) {
s_logger.debug("Failed to delete " + volumeHost + " due to " + ((answer == null) ? "answer is null" : answer.getDetails()));
return;
}
- }else if(volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS){
+ }else if(volumeHost.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS){
s_logger.debug("Volume: " + vol.getName() + " is currently being uploaded; cant' delete it.");
throw new CloudRuntimeException("Please specify a volume that is not currently being uploaded.");
}
_volumeHostDao.remove(volumeHost.getId());
_volumeDao.remove(vol.getId());
- return;
+ return;
}
-
+
String vmName = null;
if (vol.getVolumeType() == Type.ROOT && vol.getInstanceId() != null) {
VirtualMachine vm = _vmInstanceDao.findByIdIncludingRemoved(vol.getInstanceId());
@@ -3894,7 +3894,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
vmSearch.and("type", vmSearch.entity().getType(), SearchCriteria.Op.NIN);
vmSearch.or("nulltype", vmSearch.entity().getType(), SearchCriteria.Op.NULL);
sb.join("vmSearch", vmSearch, sb.entity().getInstanceId(), vmSearch.entity().getId(), JoinBuilder.JoinType.LEFTOUTER);
-
+
if (tags != null && !tags.isEmpty()) {
SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder();
for (int count=0; count < tags.size(); count++) {
@@ -3924,7 +3924,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
}
sc.setJoinParameters("diskOfferingSearch", "systemUse", 1);
-
+
if (tags != null && !tags.isEmpty()) {
int count = 0;
sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.Volume.toString());
@@ -3957,7 +3957,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
// Only return volumes that are not destroyed
sc.setParameters("state", Volume.State.Destroy);
-
+
Pair<List<VolumeVO>, Integer> volumes = _volumeDao.searchAndCount(sc, searchFilter);
return new Pair<List<? extends Volume>, Integer>(volumes.first(), volumes.second());
@@ -3979,14 +3979,14 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
return null;
}
}
-
+
@Override
public HypervisorType getHypervisorTypeFromFormat(ImageFormat format) {
-
+
if(format == null) {
return HypervisorType.None;
}
-
+
if (format == ImageFormat.VHD) {
return HypervisorType.XenServer;
} else if (format == ImageFormat.OVA) {
@@ -4075,5 +4075,5 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
}
return true;
}
-
+
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/e7fa1a86/server/test/com/cloud/api/APITest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/APITest.java b/server/test/com/cloud/api/APITest.java
new file mode 100644
index 0000000..69c488f
--- /dev/null
+++ b/server/test/com/cloud/api/APITest.java
@@ -0,0 +1,189 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// 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 com.cloud.api;
+
+import java.io.BufferedReader;
+import java.io.EOFException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.math.BigInteger;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.google.gson.Gson;
+
+/**
+ * Base class for API Test
+ *
+ * @author Min Chen
+ *
+ */
+public abstract class APITest {
+
+ protected String rootUrl = "http://localhost:8080/client/api";
+ protected String sessionKey = null;
+ protected String cookieToSent = null;
+
+
+ /**
+ * Sending an api request through Http GET
+ * @param command command name
+ * @param params command query parameters in a HashMap
+ * @return http request response string
+ */
+ protected String sendRequest(String command, HashMap<String, String> params){
+ try {
+ // Construct query string
+ StringBuilder sBuilder = new StringBuilder();
+ sBuilder.append("command=");
+ sBuilder.append(command);
+ if ( params != null && params.size() > 0){
+ Iterator<String> keys = params.keySet().iterator();
+ while (keys.hasNext()){
+ String key = keys.next();
+ sBuilder.append("&");
+ sBuilder.append(key);
+ sBuilder.append("=");
+ sBuilder.append(URLEncoder.encode(params.get(key), "UTF-8"));
+ }
+ }
+
+ // Construct request url
+ String reqUrl = rootUrl + "?" + sBuilder.toString();
+
+ // Send Http GET request
+ URL url = new URL(reqUrl);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("GET");
+
+ if ( !command.equals("login") && cookieToSent != null){
+ // add the cookie to a request
+ conn.setRequestProperty("Cookie", cookieToSent);
+ }
+ conn.connect();
+
+
+ if ( command.equals("login")){
+ // if it is login call, store cookie
+ String headerName=null;
+ for (int i=1; (headerName = conn.getHeaderFieldKey(i))!=null; i++) {
+ if (headerName.equals("Set-Cookie")) {
+ String cookie = conn.getHeaderField(i);
+ cookie = cookie.substring(0, cookie.indexOf(";"));
+ String cookieName = cookie.substring(0, cookie.indexOf("="));
+ String cookieValue = cookie.substring(cookie.indexOf("=") + 1, cookie.length());
+ cookieToSent = cookieName + "=" + cookieValue;
+ }
+ }
+ }
+
+ // Get the response
+ StringBuilder response = new StringBuilder();
+ BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+ String line;
+ try {
+ while ((line = rd.readLine()) != null) {
+ response.append(line);
+ }
+ } catch (EOFException ex) {
+ // ignore this exception
+ System.out.println("EOF exception due to java bug");
+ }
+ rd.close();
+
+
+
+ return response.toString();
+
+ } catch (Exception e) {
+ throw new CloudRuntimeException("Problem with sending api request", e);
+ }
+ }
+
+ protected String createMD5String(String password) {
+ MessageDigest md5;
+ try {
+ md5 = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ throw new CloudRuntimeException("Error", e);
+ }
+
+ md5.reset();
+ BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes()));
+
+ // make sure our MD5 hash value is 32 digits long...
+ StringBuffer sb = new StringBuffer();
+ String pwStr = pwInt.toString(16);
+ int padding = 32 - pwStr.length();
+ for (int i = 0; i < padding; i++) {
+ sb.append('0');
+ }
+ sb.append(pwStr);
+ return sb.toString();
+ }
+
+
+ protected Object fromSerializedString(String result, Class<?> repCls) {
+ try {
+ if (result != null && !result.isEmpty()) {
+
+ // get real content
+ int start = result.indexOf('{', result.indexOf('{') + 1); // find the second {
+ if ( start < 0 ){
+ throw new CloudRuntimeException("Response format is wrong: " + result);
+ }
+ int end = result.lastIndexOf('}', result.lastIndexOf('}')-1); // find the second } backwards
+ if ( end < 0 ){
+ throw new CloudRuntimeException("Response format is wrong: " + result);
+ }
+ String content = result.substring(start, end+1);
+ Gson gson = ApiGsonHelper.getBuilder().create();
+ return gson.fromJson(content, repCls);
+ }
+ return null;
+ } catch (RuntimeException e) {
+ throw new CloudRuntimeException("Caught runtime exception when doing GSON deserialization on: " + result, e);
+ }
+ }
+
+ /**
+ * Login call
+ * @param username user name
+ * @param password password (plain password, we will do MD5 hash here for you)
+ * @return login response string
+ */
+ protected void login(String username, String password)
+ {
+ //String md5Psw = createMD5String(password);
+ // send login request
+ HashMap<String, String> params = new HashMap<String, String>();
+ params.put("response", "json");
+ params.put("username", username);
+ params.put("password", password);
+ String result = this.sendRequest("login", params);
+ LoginResponse loginResp = (LoginResponse)fromSerializedString(result, LoginResponse.class);
+ sessionKey = loginResp.getSessionkey();
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/e7fa1a86/server/test/com/cloud/api/ListPerfTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/ListPerfTest.java b/server/test/com/cloud/api/ListPerfTest.java
new file mode 100644
index 0000000..47abcae
--- /dev/null
+++ b/server/test/com/cloud/api/ListPerfTest.java
@@ -0,0 +1,109 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// 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 com.cloud.api;
+
+import java.util.HashMap;
+
+import org.junit.Before;
+import org.junit.Test;
+
+
+/**
+ * Test fixture to do performance test for list command
+ * Currently we commented out this test suite since it requires a real MS and Db running.
+ *
+ * @author Min Chen
+ *
+ */
+public class ListPerfTest extends APITest {
+
+
+
+ @Before
+ public void setup(){
+ // always login for each testcase
+ login("admin", "password");
+ }
+
+ @Test
+ public void testListVM(){
+ // issue list VM calls
+ HashMap<String, String> params = new HashMap<String, String>();
+ params.put("response", "json");
+ params.put("listAll", "true");
+ params.put("sessionkey", sessionKey);
+ long before = System.currentTimeMillis();
+ String result = this.sendRequest("listVirtualMachines", params);
+ long after = System.currentTimeMillis();
+ System.out.println("Time taken to list VM: " + (after - before) + " ms");
+
+ }
+
+ @Test
+ public void testListVMXML(){
+ // issue list VM calls
+ HashMap<String, String> params = new HashMap<String, String>();
+ params.put("listAll", "true");
+ params.put("sessionkey", sessionKey);
+ long before = System.currentTimeMillis();
+ String result = this.sendRequest("listVirtualMachines", params);
+ long after = System.currentTimeMillis();
+ System.out.println("Time taken to list VM: " + (after - before) + " ms");
+
+ }
+
+ @Test
+ public void testListRouter(){
+ // issue list VM calls
+ HashMap<String, String> params = new HashMap<String, String>();
+ params.put("response", "json");
+ params.put("listAll", "true");
+ params.put("sessionkey", sessionKey);
+ long before = System.currentTimeMillis();
+ String result = this.sendRequest("listRouters", params);
+ long after = System.currentTimeMillis();
+ System.out.println("Time taken to list Routers: " + (after - before) + " ms");
+
+ }
+
+ @Test
+ public void testListRouterXML(){
+ // issue list VM calls
+ HashMap<String, String> params = new HashMap<String, String>();
+ params.put("listAll", "true");
+ params.put("sessionkey", sessionKey);
+ long before = System.currentTimeMillis();
+ String result = this.sendRequest("listRouters", params);
+ long after = System.currentTimeMillis();
+ System.out.println("Time taken to list Routers: " + (after - before) + " ms");
+
+ }
+
+ @Test
+ public void testListHosts(){
+ // issue list Hosts calls
+ HashMap<String, String> params = new HashMap<String, String>();
+ params.put("response", "json");
+ params.put("listAll", "true");
+ params.put("sessionkey", sessionKey);
+ long before = System.currentTimeMillis();
+ String result = this.sendRequest("listHosts", params);
+ long after = System.currentTimeMillis();
+ System.out.println("Time taken to list Hosts: " + (after - before) + " ms");
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/e7fa1a86/server/test/com/cloud/api/LoginResponse.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/api/LoginResponse.java b/server/test/com/cloud/api/LoginResponse.java
new file mode 100644
index 0000000..097ae42
--- /dev/null
+++ b/server/test/com/cloud/api/LoginResponse.java
@@ -0,0 +1,142 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// 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 com.cloud.api;
+
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Login Response object
+ *
+ * @author Min Chen
+ *
+ */
+public class LoginResponse extends BaseResponse {
+
+ @SerializedName("timeout")
+ @Param(description = "session timeout period")
+ private String timeout;
+
+ @SerializedName("sessionkey")
+ @Param(description = "login session key")
+ private String sessionkey;
+
+ @SerializedName("username")
+ @Param(description = "login username")
+ private String username;
+
+ @SerializedName("userid")
+ @Param(description = "login user internal uuid")
+ private String userid;
+
+ @SerializedName("firstname")
+ @Param(description = "login user firstname")
+ private String firstname;
+
+ @SerializedName("lastname")
+ @Param(description = "login user lastname")
+ private String lastname;
+
+ @SerializedName("account")
+ @Param(description = "login user account type")
+ private String account;
+
+ @SerializedName("domainid")
+ @Param(description = "login user domain id")
+ private String domainid;
+
+ @SerializedName("type")
+ @Param(description = "login user type")
+ private int type;
+
+ public String getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(String timeout) {
+ this.timeout = timeout;
+ }
+
+ public String getSessionkey() {
+ return sessionkey;
+ }
+
+ public void setSessionkey(String sessionkey) {
+ this.sessionkey = sessionkey;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getUserid() {
+ return userid;
+ }
+
+ public void setUserid(String userid) {
+ this.userid = userid;
+ }
+
+ public String getFirstname() {
+ return firstname;
+ }
+
+ public void setFirstname(String firstname) {
+ this.firstname = firstname;
+ }
+
+ public String getLastname() {
+ return lastname;
+ }
+
+ public void setLastname(String lastname) {
+ this.lastname = lastname;
+ }
+
+ public String getAccount() {
+ return account;
+ }
+
+ public void setAccount(String account) {
+ this.account = account;
+ }
+
+ public String getDomainid() {
+ return domainid;
+ }
+
+ public void setDomainid(String domainid) {
+ this.domainid = domainid;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public void setType(int type) {
+ this.type = type;
+ }
+
+
+
+}