diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index 8b9df63605e..93f6e5ebd49 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -256,6 +256,7 @@ public class ApiConstants { public static final String OLD_FORMAT = "oldformat"; public static final String OP = "op"; public static final String OS_CATEGORY_ID = "oscategoryid"; + public static final String OS_CATEGORY_NAME = "oscategoryname"; public static final String OS_ID = "osid"; public static final String OS_TYPE_ID = "ostypeid"; public static final String OS_DISPLAY_NAME = "osdisplayname"; diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java index 8710790a507..7bcb1afd2d2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.response; -import com.google.gson.annotations.SerializedName; - -import org.apache.cloudstack.api.ApiConstants; - -import com.cloud.serializer.Param; -import org.apache.cloudstack.api.BaseResponseWithTagInformation; - import java.util.LinkedHashSet; import java.util.Set; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponseWithTagInformation; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + @SuppressWarnings("unused") public class UsageRecordResponse extends BaseResponseWithTagInformation implements ControlledEntityResponse { @SerializedName(ApiConstants.ACCOUNT) @@ -89,8 +88,20 @@ public class UsageRecordResponse extends BaseResponseWithTagInformation implemen private String templateId; @SerializedName(ApiConstants.OS_TYPE_ID) - @Param(description = "virtual machine os type id") - private Long osTypeId; + @Param(description = "virtual machine os type ID") + private String osTypeId; + + @SerializedName(ApiConstants.OS_DISPLAY_NAME) + @Param(description = "virtual machine os display name") + private String osDisplayName; + + @SerializedName(ApiConstants.OS_CATEGORY_ID) + @Param(description = "virtual machine guest os category ID") + private String osCategoryId; + + @SerializedName(ApiConstants.OS_CATEGORY_NAME) + @Param(description = "virtual machine os category name") + private String osCategoryName; @SerializedName("usageid") @Param(description = "id of the resource") @@ -206,10 +217,22 @@ public class UsageRecordResponse extends BaseResponseWithTagInformation implemen this.templateId = templateId; } - public void setOsTypeId(Long osTypeId) { + public void setOsTypeId(String osTypeId) { this.osTypeId = osTypeId; } + public void setOsDisplayName(String osDisplayName) { + this.osDisplayName = osDisplayName; + } + + public void setOsCategoryId(String osCategoryId) { + this.osCategoryId = osCategoryId; + } + + public void setOsCategoryName(String osCategoryName) { + this.osCategoryName = osCategoryName; + } + public void setUsageId(String usageId) { this.usageId = usageId; } diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41500to41510.sql b/engine/schema/src/main/resources/META-INF/db/schema-41500to41510.sql index caafde62556..5c25c0b745e 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41500to41510.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41500to41510.sql @@ -19,3 +19,7 @@ -- Schema upgrade from 4.15.0.0 to 4.15.1.0 --; +-- Correct guest OS names +UPDATE `cloud`.`guest_os` SET display_name='Fedora Linux (32 bit)' WHERE id=320; +UPDATE `cloud`.`guest_os` SET display_name='Mandriva Linux (32 bit)' WHERE id=323; +UPDATE `cloud`.`guest_os` SET display_name='OpenSUSE Linux (32 bit)' WHERE id=327; diff --git a/python/lib/cloudutils/serviceConfig.py b/python/lib/cloudutils/serviceConfig.py index 4cbab59560d..8294914e90e 100755 --- a/python/lib/cloudutils/serviceConfig.py +++ b/python/lib/cloudutils/serviceConfig.py @@ -535,6 +535,12 @@ class libvirtConfigRedhat(serviceCfgBase): cfo.addEntry("export CGROUP_DAEMON", "'cpu:/virt'") cfo.addEntry("LIBVIRTD_ARGS", "-l") cfo.save() + if os.path.exists("/lib/systemd/system/libvirtd.socket"): + bash("/bin/systemctl mask libvirtd.socket"); + bash("/bin/systemctl mask libvirtd-ro.socket"); + bash("/bin/systemctl mask libvirtd-admin.socket"); + bash("/bin/systemctl mask libvirtd-tls.socket"); + bash("/bin/systemctl mask libvirtd-tcp.socket"); filename = "/etc/libvirt/qemu.conf" diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index d1ce33982ab..27e0d58b48e 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -306,6 +306,7 @@ import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.GuestOS; import com.cloud.storage.GuestOSCategoryVO; import com.cloud.storage.GuestOSHypervisor; +import com.cloud.storage.GuestOsCategory; import com.cloud.storage.ImageStore; import com.cloud.storage.Snapshot; import com.cloud.storage.SnapshotVO; @@ -315,6 +316,8 @@ import com.cloud.storage.UploadVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.GuestOSCategoryDao; +import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.snapshot.SnapshotPolicy; import com.cloud.storage.snapshot.SnapshotSchedule; @@ -394,6 +397,10 @@ public class ApiResponseHelper implements ResponseGenerator { private VMSnapshotDao vmSnapshotDao; @Inject private BackupOfferingDao backupOfferingDao; + @Inject + private GuestOSCategoryDao _guestOsCategoryDao; + @Inject + private GuestOSDao _guestOsDao; @Override public UserResponse createUserResponse(User user) { @@ -3401,7 +3408,16 @@ public class ApiResponseHelper implements ResponseGenerator { resourceType = ResourceTag.ResourceObjectType.UserVm; usageRecResponse.setUsageId(vm.getUuid()); resourceId = vm.getId(); - usageRecResponse.setOsTypeId(vm.getGuestOSId()); + final GuestOS guestOS = _guestOsDao.findById(vm.getGuestOSId()); + if (guestOS != null) { + usageRecResponse.setOsTypeId(guestOS.getUuid()); + usageRecResponse.setOsDisplayName(guestOS.getDisplayName()); + final GuestOsCategory guestOsCategory = _guestOsCategoryDao.findById(guestOS.getCategoryId()); + if (guestOsCategory != null) { + usageRecResponse.setOsCategoryId(guestOsCategory.getUuid()); + usageRecResponse.setOsCategoryName(guestOsCategory.getName()); + } + } } //Hypervisor Type usageRecResponse.setType(usageRecord.getType()); @@ -3962,7 +3978,6 @@ public class ApiResponseHelper implements ResponseGenerator { NicResponse response = new NicResponse(); NetworkVO network = _entityMgr.findById(NetworkVO.class, result.getNetworkId()); VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, result.getInstanceId()); - UserVmJoinVO userVm = _entityMgr.findById(UserVmJoinVO.class, result.getInstanceId()); List nicExtraDhcpOptionVOs = _nicExtraDhcpOptionDao.listByNicId(result.getId()); // The numbered comments are to keep track of the data returned from here and UserVmJoinDaoImpl.setUserVmResponse() @@ -3976,15 +3991,13 @@ public class ApiResponseHelper implements ResponseGenerator { response.setVmId(vm.getUuid()); } - if (userVm != null){ - if (userVm.getTrafficType() != null) { - /*4: trafficType*/ - response.setTrafficType(userVm.getTrafficType().toString()); - } - if (userVm.getGuestType() != null) { - /*5: guestType*/ - response.setType(userVm.getGuestType().toString()); - } + if (network.getTrafficType() != null) { + /*4: trafficType*/ + response.setTrafficType(network.getTrafficType().toString()); + } + if (network.getGuestType() != null) { + /*5: guestType*/ + response.setType(network.getGuestType().toString()); } /*6: ipAddress*/ response.setIpaddress(result.getIPv4Address()); @@ -3993,9 +4006,7 @@ public class ApiResponseHelper implements ResponseGenerator { /*8: netmask*/ response.setNetmask(result.getIPv4Netmask()); /*9: networkName*/ - if(userVm != null && userVm.getNetworkName() != null) { - response.setNetworkName(userVm.getNetworkName()); - } + response.setNetworkName(network.getName()); /*10: macAddress*/ response.setMacAddress(result.getMacAddress()); /*11: IPv6Address*/ diff --git a/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java index afda5068b0c..30fb6a141f3 100644 --- a/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java +++ b/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java @@ -26,12 +26,6 @@ import java.util.concurrent.ExecutionException; import javax.inject.Inject; -import com.cloud.configuration.Config; -import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao; -import com.cloud.storage.dao.VMTemplateDetailsDao; -import com.cloud.utils.db.Transaction; -import com.cloud.utils.db.TransactionCallback; -import com.cloud.utils.db.TransactionStatus; import org.apache.cloudstack.agent.directdownload.CheckUrlAnswer; import org.apache.cloudstack.agent.directdownload.CheckUrlCommand; import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd; @@ -62,14 +56,17 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity; import org.apache.cloudstack.utils.security.DigestHelper; +import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.alert.AlertManager; +import com.cloud.configuration.Config; import com.cloud.configuration.Resource.ResourceType; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.DataCenterDao; +import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; import com.cloud.exception.InvalidParameterValueException; @@ -87,6 +84,7 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplateDetailsDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.download.DownloadMonitor; import com.cloud.template.VirtualMachineTemplate.State; @@ -95,6 +93,9 @@ import com.cloud.utils.Pair; import com.cloud.utils.UriUtils; import com.cloud.utils.db.DB; import com.cloud.utils.db.EntityManager; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.TransactionCallback; +import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.exception.CloudRuntimeException; public class HypervisorTemplateAdapter extends TemplateAdapterBase { @@ -169,6 +170,12 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase { return ans.getTemplateSize(); } + private void checkZoneImageStores(final List zoneIdList) { + if (zoneIdList != null && CollectionUtils.isEmpty(storeMgr.getImageStoresByScope(new ZoneScope(zoneIdList.get(0))))) { + throw new InvalidParameterValueException("Failed to find a secondary storage in the specified zone."); + } + } + @Override public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException { TemplateProfile profile = super.prepare(cmd); @@ -637,29 +644,17 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase { public TemplateProfile prepareDelete(DeleteTemplateCmd cmd) { TemplateProfile profile = super.prepareDelete(cmd); VMTemplateVO template = profile.getTemplate(); - List zoneIdList = profile.getZoneIdList(); - if (template.getTemplateType() == TemplateType.SYSTEM) { throw new InvalidParameterValueException("The DomR template cannot be deleted."); } - - if (zoneIdList != null && (storeMgr.getImageStoreWithFreeCapacity(zoneIdList.get(0)) == null)) { - throw new InvalidParameterValueException("Failed to find a secondary storage in the specified zone."); - } - + checkZoneImageStores(profile.getZoneIdList()); return profile; } @Override public TemplateProfile prepareDelete(DeleteIsoCmd cmd) { TemplateProfile profile = super.prepareDelete(cmd); - List zoneIdList = profile.getZoneIdList(); - - if (zoneIdList != null && - (storeMgr.getImageStoreWithFreeCapacity(zoneIdList.get(0)) == null)) { - throw new InvalidParameterValueException("Failed to find a secondary storage in the specified zone."); - } - + checkZoneImageStores(profile.getZoneIdList()); return profile; } } diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index a64293be297..1499e49fa76 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -1363,7 +1363,7 @@ class TestMigrateVMwithVolume(cloudstackTestCase): Volume.migrate(self.apiclient, storageid=target_pool.id, volumeid=volume1.id) - vol = Volume.list(self.apiclient, volume=volume1.id)[0] + vol = Volume.list(self.apiclient, id=volume1.id)[0] self.assertEqual(vol.storageid, target_pool.id, "Storage pool was not the same as expected") diff --git a/ui/src/components/view/DetailSettings.vue b/ui/src/components/view/DetailSettings.vue index eaa446cddcf..2817e1c2b5b 100644 --- a/ui/src/components/view/DetailSettings.vue +++ b/ui/src/components/view/DetailSettings.vue @@ -176,6 +176,13 @@ export default { }) this.disableSettings = (this.$route.meta.name === 'vm' && this.resource.state !== 'Stopped') }, + filterOrReadOnlyDetails () { + for (var i = 0; i < this.details.length; i++) { + if (!this.allowEditOfDetail(this.details[i].name)) { + this.details.splice(i, 1) + } + } + }, allowEditOfDetail (name) { if (this.resource.readonlyuidetails) { if (this.resource.readonlyuidetails.split(',').map(item => item.trim()).includes(name)) { @@ -257,13 +264,16 @@ export default { } this.error = false this.details.push({ name: this.newKey, value: this.newValue }) + this.filterOrReadOnlyDetails() this.runApi() }, updateDetail (index) { + this.filterOrReadOnlyDetails() this.runApi() }, deleteDetail (index) { this.details.splice(index, 1) + this.filterOrReadOnlyDetails() this.runApi() }, onShowAddDetail () { diff --git a/ui/src/components/view/InfoCard.vue b/ui/src/components/view/InfoCard.vue index 8200b8114fb..2229f8ee976 100644 --- a/ui/src/components/view/InfoCard.vue +++ b/ui/src/components/view/InfoCard.vue @@ -713,7 +713,6 @@ export default { }, data () { return { - name: '', ipaddress: '', resourceType: '', annotationType: '', @@ -769,10 +768,14 @@ export default { created () { this.setData() }, + computed: { + name () { + return this.resource.displayname || this.resource.displaytext || this.resource.name || this.resource.username || + this.resource.ipaddress || this.resource.virtualmachinename || this.resource.templatetype + } + }, methods: { setData () { - this.name = this.resource.displayname || this.resource.displaytext || this.resource.name || this.resource.username || - this.resource.ipaddress || this.resource.virtualmachinename || this.resource.templatetype if (this.resource.nic && this.resource.nic.length > 0) { this.ipaddress = this.resource.nic.filter(e => { return e.ipaddress }).map(e => { return e.ipaddress }).join(', ') } else { diff --git a/ui/src/components/widgets/Breadcrumb.vue b/ui/src/components/widgets/Breadcrumb.vue index fdcb304f7df..c91ef630ff1 100644 --- a/ui/src/components/widgets/Breadcrumb.vue +++ b/ui/src/components/widgets/Breadcrumb.vue @@ -26,12 +26,15 @@ {{ $t(item.meta.title) }} - diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js index c3d2623885d..3a98f4965f6 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -38,7 +38,7 @@ export default { return filters }, columns: () => { - const fields = ['name', 'state', 'ipaddress'] + const fields = ['displayname', 'name', 'state', 'ipaddress'] const metricsFields = ['cpunumber', 'cpuused', 'cputotal', { memoryused: (record) => { diff --git a/ui/src/views/compute/DeployVM.vue b/ui/src/views/compute/DeployVM.vue index bee2a386579..b2a5fee8bcb 100644 --- a/ui/src/views/compute/DeployVM.vue +++ b/ui/src/views/compute/DeployVM.vue @@ -603,7 +603,7 @@ - + diff --git a/ui/src/views/compute/MigrateWizard.vue b/ui/src/views/compute/MigrateWizard.vue index f5082e9a696..f34a778fe1c 100644 --- a/ui/src/views/compute/MigrateWizard.vue +++ b/ui/src/views/compute/MigrateWizard.vue @@ -47,6 +47,9 @@
{{ record.memoryused | byteToGigabyte }} GB
+
+ {{ record.memoryallocatedpercentage }} +
{{ record.clustername }}
@@ -122,6 +125,10 @@ export default { title: this.$t('label.cpuused'), dataIndex: 'cpuused' }, + { + title: this.$t('label.memoryallocated'), + scopedSlots: { customRender: 'memoryallocatedpercentage' } + }, { title: this.$t('label.memused'), scopedSlots: { customRender: 'memused' }