diff --git a/server/src/com/cloud/api/ApiDispatcher.java b/server/src/com/cloud/api/ApiDispatcher.java index 326191b9b3a..12e45a8df8a 100644 --- a/server/src/com/cloud/api/ApiDispatcher.java +++ b/server/src/com/cloud/api/ApiDispatcher.java @@ -224,12 +224,12 @@ public class ApiDispatcher { if (cause instanceof AsyncCommandQueued) { throw (AsyncCommandQueued)cause; } - s_logger.warn("Exception executing method " + methodName + " for command " + cmd.getClass().getSimpleName(), ite); if (cause instanceof InvalidParameterValueException) { throw new ServerApiException(BaseCmd.PARAM_ERROR, cause.getMessage()); } else if (cause instanceof PermissionDeniedException) { throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, cause.getMessage()); } + s_logger.warn("Exception executing method " + methodName + " for command " + cmd.getClass().getSimpleName(), ite); throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Unable to execute method " + methodName + " for command " + cmd.getClass().getSimpleName() + ", internal error in the implementation."); } catch (IllegalAccessException iae) { s_logger.warn("Exception executing method " + methodName + " for command " + cmd.getClass().getSimpleName(), iae); diff --git a/server/src/com/cloud/api/commands/CreateVolumeCmd.java b/server/src/com/cloud/api/commands/CreateVolumeCmd.java index 31ec30f5c70..4cfb29a6139 100644 --- a/server/src/com/cloud/api/commands/CreateVolumeCmd.java +++ b/server/src/com/cloud/api/commands/CreateVolumeCmd.java @@ -163,6 +163,9 @@ public class CreateVolumeCmd extends BaseAsyncCreateCmd { if (volume.getPoolId() != null) { response.setStoragePoolName(ApiDBUtils.findStoragePoolById(volume.getPoolId()).getName()); } + + // if the volume was created from a snapshot, snapshotId will be set so we pass it back in the response + response.setSnapshotId(getSnapshotId()); response.setZoneId(volume.getDataCenterId()); response.setZoneName(ApiDBUtils.findZoneById(volume.getDataCenterId()).getName()); diff --git a/server/src/com/cloud/api/commands/DeployVMCmd.java b/server/src/com/cloud/api/commands/DeployVMCmd.java index 565dfa693b4..818748f0ad2 100644 --- a/server/src/com/cloud/api/commands/DeployVMCmd.java +++ b/server/src/com/cloud/api/commands/DeployVMCmd.java @@ -40,7 +40,7 @@ import com.cloud.user.UserContext; import com.cloud.uservm.UserVm; import com.cloud.vm.InstanceGroupVO; -@Implementation(createMethod="createVirtualMachine", method="startVirtualMachine", manager=Manager.UserVmManager, description="Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.") +@Implementation(method="deployVirtualMachine", description="Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.") public class DeployVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeployVMCmd.class.getName()); diff --git a/server/src/com/cloud/api/commands/ListCapacityCmd.java b/server/src/com/cloud/api/commands/ListCapacityCmd.java index e2826cbb113..348318ad3ab 100644 --- a/server/src/com/cloud/api/commands/ListCapacityCmd.java +++ b/server/src/com/cloud/api/commands/ListCapacityCmd.java @@ -44,7 +44,7 @@ import com.cloud.storage.StoragePoolVO; public class ListCapacityCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListCapacityCmd.class.getName()); - private static final DecimalFormat s_percentFormat = new DecimalFormat("####.##"); + private static final DecimalFormat s_percentFormat = new DecimalFormat("##.##"); private static final String s_name = "listcapacityresponse"; @@ -120,12 +120,15 @@ public class ListCapacityCmd extends BaseListCmd { capacityResponse.setPodId(summedCapacity.getPodId()); if (summedCapacity.getPodId() > 0) { capacityResponse.setPodName(ApiDBUtils.findPodById(summedCapacity.getPodId()).getName()); + } else { + capacityResponse.setPodName("All"); } } capacityResponse.setZoneId(summedCapacity.getDataCenterId()); capacityResponse.setZoneName(ApiDBUtils.findZoneById(summedCapacity.getDataCenterId()).getName()); if (summedCapacity.getTotalCapacity() != 0) { - capacityResponse.setPercentUsed(s_percentFormat.format(summedCapacity.getUsedCapacity() / summedCapacity.getTotalCapacity())); + float computed = ((float)summedCapacity.getUsedCapacity() / (float)summedCapacity.getTotalCapacity() * 100f); + capacityResponse.setPercentUsed(s_percentFormat.format((float)summedCapacity.getUsedCapacity() / (float)summedCapacity.getTotalCapacity() * 100f)); } else { capacityResponse.setPercentUsed(s_percentFormat.format(0L)); } diff --git a/server/src/com/cloud/api/commands/ListVolumesCmd.java b/server/src/com/cloud/api/commands/ListVolumesCmd.java index 12f6bbb2493..44f55c1c21f 100755 --- a/server/src/com/cloud/api/commands/ListVolumesCmd.java +++ b/server/src/com/cloud/api/commands/ListVolumesCmd.java @@ -206,6 +206,7 @@ public class ListVolumesCmd extends BaseListCmd { volResponse.setSourceType(volume.getSourceType().toString()); } volResponse.setHypervisor(ApiDBUtils.getVolumeHyperType(volume.getId()).toString()); + volResponse.setAttached(volume.getAttached()); volResponse.setResponseName("volume"); volResponses.add(volResponse); diff --git a/server/src/com/cloud/api/commands/RebootVMCmd.java b/server/src/com/cloud/api/commands/RebootVMCmd.java index 0d6bfc283a2..25f537db263 100644 --- a/server/src/com/cloud/api/commands/RebootVMCmd.java +++ b/server/src/com/cloud/api/commands/RebootVMCmd.java @@ -21,13 +21,19 @@ import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; import com.cloud.api.BaseAsyncCmd; +import com.cloud.api.BaseCmd; import com.cloud.api.BaseCmd.Manager; import com.cloud.api.Implementation; import com.cloud.api.Parameter; -import com.cloud.api.response.SuccessResponse; +import com.cloud.api.response.UserVmResponse; import com.cloud.event.EventTypes; +import com.cloud.offering.ServiceOffering; +import com.cloud.storage.StoragePoolVO; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VolumeVO; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.InstanceGroupVO; @Implementation(method="rebootVirtualMachine", manager=Manager.UserVmManager, description="Reboots a virtual machine.") public class RebootVMCmd extends BaseAsyncCmd { @@ -79,10 +85,102 @@ public class RebootVMCmd extends BaseAsyncCmd { } @Override @SuppressWarnings("unchecked") - public SuccessResponse getResponse() { - Boolean success = (Boolean)getResponseObject(); - SuccessResponse response = new SuccessResponse(); - response.setSuccess(success); + public UserVmResponse getResponse() { + UserVm vm = (UserVm)getResponseObject(); + + UserVmResponse response = new UserVmResponse(); + response.setId(vm.getId()); + response.setName(vm.getName()); + response.setCreated(vm.getCreated()); + response.setZoneId(vm.getDataCenterId()); + response.setZoneName(ApiDBUtils.findZoneById(vm.getDataCenterId()).getName()); + response.setIpAddress(vm.getPrivateIpAddress()); + response.setServiceOfferingId(vm.getServiceOfferingId()); + response.setHaEnable(vm.isHaEnabled()); + if (vm.getDisplayName() == null || vm.getDisplayName().length() == 0) { + response.setDisplayName(vm.getName()); + } else { + response.setDisplayName(vm.getDisplayName()); + } + + InstanceGroupVO group = ApiDBUtils.findInstanceGroupForVM(vm.getId()); + if (group != null) { + response.setGroup(group.getName()); + response.setGroupId(group.getId()); + } + + if (vm.getState() != null) { + response.setState(vm.getState().toString()); + } + + Account acct = ApiDBUtils.findAccountById(vm.getAccountId()); + if (acct != null) { + response.setAccountName(acct.getAccountName()); + response.setDomainId(acct.getDomainId()); + response.setDomainName(ApiDBUtils.findDomainById(acct.getDomainId()).getName()); + } + + if (BaseCmd.isAdmin(acct.getType()) && (vm.getHostId() != null)) { + response.setHostName(ApiDBUtils.findHostById(vm.getHostId()).getName()); + response.setHostId(vm.getHostId()); + } + + String templateName = "ISO Boot"; + boolean templatePasswordEnabled = false; + String templateDisplayText = "ISO Boot"; + + VMTemplateVO template = ApiDBUtils.findTemplateById(vm.getTemplateId()); + if (template != null) { + templateName = template.getName(); + templatePasswordEnabled = template.getEnablePassword(); + templateDisplayText = template.getDisplayText(); + if (templateDisplayText == null) { + templateDisplayText = templateName; + } + } + + response.setTemplateId(vm.getTemplateId()); + response.setTemplateName(templateName); + response.setTemplateDisplayText(templateDisplayText); + response.setPasswordEnabled(templatePasswordEnabled); + if (templatePasswordEnabled) { + response.setPassword(null); // FIXME: Where should password come from? In the old framework, password was always passed + // in to composeResultObject() as null, so that behavior is preserved... + } else { + response.setPassword(""); + } + + String isoName = null; + if (vm.getIsoId() != null) { + VMTemplateVO iso = ApiDBUtils.findTemplateById(vm.getIsoId().longValue()); + if (iso != null) { + isoName = iso.getName(); + } + } + + response.setIsoId(vm.getIsoId()); + response.setIsoName(isoName); + + ServiceOffering offering = ApiDBUtils.findServiceOfferingById(vm.getServiceOfferingId()); + response.setServiceOfferingId(vm.getServiceOfferingId()); + response.setServiceOfferingName(offering.getName()); + + response.setCpuNumber(offering.getCpu()); + response.setCpuSpeed(offering.getSpeed()); + response.setMemory(offering.getRamSize()); + + VolumeVO rootVolume = ApiDBUtils.findRootVolume(vm.getId()); + if (rootVolume != null) { + response.setRootDeviceId(rootVolume.getDeviceId()); + StoragePoolVO storagePool = ApiDBUtils.findStoragePoolById(rootVolume.getPoolId()); + response.setRootDeviceType(storagePool.getPoolType().toString()); + } + + response.setGuestOsId(vm.getGuestOSId()); + + //Network groups + response.setNetworkGroupList(ApiDBUtils.getNetworkGroupsNamesForVm(vm.getId())); + response.setResponseName(getName()); return response; } diff --git a/server/src/com/cloud/api/response/CapacityResponse.java b/server/src/com/cloud/api/response/CapacityResponse.java index 560fb88cda1..4cb5ca5f300 100644 --- a/server/src/com/cloud/api/response/CapacityResponse.java +++ b/server/src/com/cloud/api/response/CapacityResponse.java @@ -39,7 +39,7 @@ public class CapacityResponse extends BaseResponse { @SerializedName("capacityused") @Param(description="the capacity currently in use") private Long capacityUsed; - @SerializedName("capacityTotal") @Param(description="the total capacity available") + @SerializedName("capacitytotal") @Param(description="the total capacity available") private Long capacityTotal; @SerializedName("percentused") @Param(description="the percentage of capacity currently in use") diff --git a/server/src/com/cloud/api/response/VolumeResponse.java b/server/src/com/cloud/api/response/VolumeResponse.java index 8a2099d380f..36ffd97513a 100644 --- a/server/src/com/cloud/api/response/VolumeResponse.java +++ b/server/src/com/cloud/api/response/VolumeResponse.java @@ -101,6 +101,12 @@ public class VolumeResponse extends BaseResponse { @SerializedName("storage") @Param(description="name of the primary storage hosting the disk volume") private String storagePoolName; + @SerializedName("snapshotid") @Param(description="ID of the snapshot from which this volume was created") + private Long snapshotId; + + @SerializedName("attached") @Param(description="the date the volume was attached to a VM instance") + private Date attached; + public Long getId() { return id; } @@ -308,4 +314,20 @@ public class VolumeResponse extends BaseResponse { public void setStoragePoolName(String storagePoolName) { this.storagePoolName = storagePoolName; } + + public Long getSnapshotId() { + return snapshotId; + } + + public void setSnapshotId(Long snapshotId) { + this.snapshotId = snapshotId; + } + + public Date getAttached() { + return attached; + } + + public void setAttached(Date attached) { + this.attached = attached; + } } diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 8e4b680ab54..842e0330602 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -73,7 +73,6 @@ import com.cloud.api.commands.PreparePrimaryStorageForMaintenanceCmd; import com.cloud.api.commands.UpdateStoragePoolCmd; import com.cloud.async.AsyncInstanceCreateStatus; import com.cloud.async.AsyncJobManager; -import com.cloud.async.executor.VolumeOperationParam.VolumeOp; import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; import com.cloud.configuration.Config; @@ -507,7 +506,7 @@ public class StorageManagerImpl implements StorageManager { @DB protected Pair createVolumeFromSnapshot(VolumeVO volume, SnapshotVO snapshot, VMTemplateVO template, long virtualsize) { VolumeVO createdVolume = null; - Long volumeId = null; + Long volumeId = volume.getId(); String volumeFolder = null; @@ -524,7 +523,7 @@ public class StorageManagerImpl implements StorageManager { DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); DataCenterVO dc = _dcDao.findById(volume.getDataCenterId()); - DiskProfile dskCh = createDiskCharacteristics(volume, template, dc, diskOffering); + DiskProfile dskCh = new DiskProfile(volume, diskOffering, template.getHypervisorType()); int retry = 0; // Determine what pod to store the volume in @@ -624,7 +623,7 @@ public class StorageManagerImpl implements StorageManager { VolumeVO originalVolume = _volsDao.findById(origVolumeId); // NOTE: Original volume could be destroyed and removed. VMTemplateVO template = null; if (originalVolume != null) { - template = _templateDao.findById(originalVolume.getTemplateId()); + template = _templateDao.findById(originalVolume.getTemplateId()); } // everything went well till now @@ -1669,15 +1668,18 @@ public class StorageManagerImpl implements StorageManager { throw rae; } + Long zoneId = null; + Long diskOfferingId = null; + Long size = null; // validate input parameters before creating the volume if (cmd.getSnapshotId() == null) { - Long zoneId = cmd.getZoneId(); + zoneId = cmd.getZoneId(); if ((zoneId == null)) { throw new InvalidParameterValueException("Missing parameter, zoneid must be specified."); } - Long diskOfferingId = cmd.getDiskOfferingId(); - Long size = cmd.getSize(); + diskOfferingId = cmd.getDiskOfferingId(); + size = cmd.getSize(); if ((diskOfferingId == null) && (size == null)) { throw new InvalidParameterValueException("Missing parameter(s),either a positive volume size or a valid disk offering id must be specified."); } else if ((diskOfferingId == null) && (size != null)) { @@ -1696,6 +1698,7 @@ public class StorageManagerImpl implements StorageManager { if ((diskOffering == null) || !DiskOfferingVO.Type.Disk.equals(diskOffering.getType())) { throw new InvalidParameterValueException("Please specify a valid disk offering."); } + size = diskOffering.getDiskSize(); } } else { Long snapshotId = cmd.getSnapshotId(); @@ -1703,7 +1706,12 @@ public class StorageManagerImpl implements StorageManager { if (snapshotCheck == null) { throw new ServerApiException (BaseCmd.SNAPSHOT_INVALID_PARAM_ERROR, "unable to find a snapshot with id " + snapshotId); } - + + VolumeVO vol = _volsDao.findById(snapshotCheck.getVolumeId()); + zoneId = vol.getDataCenterId(); + diskOfferingId = vol.getDiskOfferingId(); + size = vol.getSize(); + if (account != null) { if (isAdmin(account.getType())) { Account snapshotOwner = _accountDao.findById(snapshotCheck.getAccountId()); @@ -1715,13 +1723,6 @@ public class StorageManagerImpl implements StorageManager { } } } - - Long zoneId = cmd.getZoneId(); - // Check that the zone is valid - DataCenterVO zone = _dcDao.findById(zoneId); - if (zone == null) { - throw new InvalidParameterValueException("Please specify a valid zone."); - } // Check that there is a shared primary storage pool in the specified zone List storagePools = _storagePoolDao.listByDataCenterId(zoneId); @@ -1754,7 +1755,8 @@ public class StorageManagerImpl implements StorageManager { volume.setAccountId(targetAccount.getId()); volume.setDomainId(((account == null) ? Domain.ROOT_DOMAIN : account.getDomainId())); volume.setMirrorState(MirrorState.NOT_MIRRORED); - volume.setDiskOfferingId(cmd.getDiskOfferingId()); + volume.setDiskOfferingId(diskOfferingId); + volume.setSize(size); volume.setStorageResourceType(StorageResourceType.STORAGE_POOL); volume.setInstanceId(null); volume.setUpdated(new Date()); diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index f8e3ca732e0..d01fba559ce 100644 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -3512,7 +3512,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService { } @Override - public boolean rebootVirtualMachine(RebootVMCmd cmd) { + public UserVm rebootVirtualMachine(RebootVMCmd cmd) { Account account = UserContext.current().getAccount(); Long userId = UserContext.current().getUserId(); Long vmId = cmd.getId(); @@ -3529,15 +3529,12 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService { boolean status = rebootVirtualMachine(userId, vmId); - if(status) - { + if (status) { EventUtils.saveEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_REBOOT, "Successfully rebooted vm with id:"+vmId); - return status; - } - else - { + return _vmDao.findById(vmId); + } else { EventUtils.saveEvent(userId, vmInstance.getAccountId(), EventTypes.EVENT_VM_REBOOT, "Failed to reboot vm with id:"+vmId); - return status; + throw new CloudRuntimeException("Failed to reboot vm with id: " + vmId); } } diff --git a/server/src/com/cloud/vm/UserVmService.java b/server/src/com/cloud/vm/UserVmService.java index eac0b62a985..a3d9072f597 100644 --- a/server/src/com/cloud/vm/UserVmService.java +++ b/server/src/com/cloud/vm/UserVmService.java @@ -81,7 +81,7 @@ public interface UserVmService extends Manager { UserVmVO startVirtualMachine(StartVMCmd cmd) throws StorageUnavailableException, ExecutionException, ConcurrentOperationException; UserVmVO stopVirtualMachine(StopVMCmd cmd) throws ServerApiException; - boolean rebootVirtualMachine(RebootVMCmd cmd); + UserVm rebootVirtualMachine(RebootVMCmd cmd); @Deprecated OperationResponse executeRebootVM(RebootVMExecutor executor, VMOperationParam param); diff --git a/ui/new/css/main.css b/ui/new/css/main.css index b1c2a5547f9..f36f25ec010 100644 --- a/ui/new/css/main.css +++ b/ui/new/css/main.css @@ -1810,7 +1810,10 @@ a:hover.search_button { .actionpanel_button:hover{ background:url(../images/actionpanel_hover.gif) repeat-x top right; - +} + +.actionpanel_button.selected{ + background:url(../images/actionpanel_hover.gif) repeat-x top right; } .action_ddarrow { @@ -1865,7 +1868,7 @@ a:hover.search_button { position:absolute; background:#FFF repeat top left; border:1px solid #999; - top:20px; + top:65px; right:7px; margin:0; padding:0; @@ -3909,3 +3912,78 @@ a:hover.search_button { .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: -0.2em 1em .5em .4em; } .ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: -0.2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } + + +.ui_dialog_loaderbox{ + width:250px; + height:auto; + float:left; + background:#FFF repeat top left; + border:1px solid #CCC; + margin:10px 0 0 0; + padding:0 10px 5px 0; +} + +.ui_dialog_loader { + width:16px; + height:16px; + float:left; + background:url(../images/mid_default.gif) no-repeat top left; + margin:5px 0 0 7px; + display:inline; + padding:0; +} + +.ui_dialog_loaderbox p{ + width:auto; + height:auto; + float:left; + color:#333; + font-size:12px; + font-weight:normal; + margin:7px 0 0 10px; + padding:0; +} + +.ui_dialog_messagebox{ + width:250px; + height:auto; + float:left; + background:#fff7e3 repeat top left; + border:1px solid #CCC; + margin:10px 0 0 0; + padding:0 10px 5px 0; +} + +.ui_dialog_messagebox.error{ + background:#ffe5e5 repeat top left; +} + +.ui_dialog_msgicon { + width:18px; + height:20px; + float:left; + background:url(../images/tick_review.png) no-repeat top left; + margin:5px 0 0 7px; + display:inline; + padding:0; +} + +.ui_dialog_msgicon.error { + background:url(../images/cross_review.png) no-repeat top left; +} +.ui_dialog_messagebox_text{ + width:auto; + height:auto; + float:left; + color:#333; + font-size:11px; + font-weight:normal; + margin:10px 0 0 10px; + padding:0; +} + +.ui_dialog_messagebox_text.error{ + + color:#ae0000; +} \ No newline at end of file diff --git a/ui/new/images/cross_review.png b/ui/new/images/cross_review.png new file mode 100644 index 00000000000..ba95024d76a Binary files /dev/null and b/ui/new/images/cross_review.png differ diff --git a/ui/new/index.jsp b/ui/new/index.jsp index dc68a470ba8..9833a974946 100644 --- a/ui/new/index.jsp +++ b/ui/new/index.jsp @@ -1,182 +1,810 @@ -<%@ page import="java.util.Date" %> +<%@ page import="java.util.*" %> +<%@ page import="com.cloud.utils.*" %> + +<% + Locale browserLocale = request.getLocale(); + CloudResourceBundle t = CloudResourceBundle.getBundle("resources/resource", browserLocale); +%> <% long milliseconds = new Date().getTime(); %> - - - - - - + + + + + + + + - cloud.com - User Console - - - - - - - - - - - - - + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - Cloud.com CloudStack + + Cloud.com CloudStack Management Console -