Alissa Bonas has uploaded a new change for review. Change subject: restapi: add template versions support ......................................................................
restapi: add template versions support Add to templates REST resource a new section that describes template version details. The user will be able to add this in POST (add template), update version name in PUT (update) and see version details in GET requests. Feature page: http://www.ovirt.org/Features/Template_Versions Change-Id: Id8e4c498c4a1856ac341237837db40db8375c6da Signed-off-by: Alissa Bonas <[email protected]> --- M backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd M backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml M backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplatesResource.java M backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplatesResourceTest.java M backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/TemplateMapper.java M backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/TemplateMapperTest.java 6 files changed, 155 insertions(+), 13 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/19/25019/1 diff --git a/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd b/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd index a849751..5e6d86f 100644 --- a/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd +++ b/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd @@ -479,6 +479,14 @@ </xs:sequence> </xs:complexType> + <xs:complexType name="TemplateVersion"> + <xs:sequence> + <xs:element name="base_template" type="Template" minOccurs="0" maxOccurs="1"/> + <xs:element name="version_number" type="xs:int" minOccurs="0" maxOccurs="1" /> + <xs:element name="version_name" type="xs:string" minOccurs="0" maxOccurs="1"/> + </xs:sequence> + </xs:complexType> + <!-- Version numbers --> <xs:element name="system_version" type="Version"/> @@ -2308,6 +2316,7 @@ <xs:element ref="virtio_scsi" minOccurs="0" maxOccurs="1"/> <xs:element ref="permissions" minOccurs="0" maxOccurs="1"/> <!-- also rel="cdroms/disks/nics/watchdogs" links, see Devices below --> + <xs:element name="version" type="TemplateVersion" minOccurs="0" maxOccurs="1"/> </xs:sequence> </xs:extension> </xs:complexContent> diff --git a/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml b/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml index dd314bb..89d19a9 100644 --- a/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml +++ b/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml @@ -3365,6 +3365,7 @@ template.tunnel_migration: xs:boolean template.migration_downtime: xs:int template.virtio_scsi.enabled: xs:boolean + template.version.version_name: xs:string description: update the specified template in the system urlparams: {} headers: @@ -3415,6 +3416,8 @@ template.virtio_scsi.enabled: xs:boolean template.vm.disks.disk--COLLECTION: {disk.id: 'xs:string', storage_domains.storage_domain--COLLECTION: {storage_domain.id: 'xs:string'}} template.permissions.clone: xs:boolean + template.version.version_name: xs:string + template.version.base_template.id: xs:string template.cpu.cpu_tune.vcpu_pin--COLLECTION: {vcpu_pin.vcpu: 'xs:int', vcpu_pin.cpu_set: 'xs:string'} description: add a new template to the system urlparams: {} diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplatesResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplatesResource.java index 2dd9677..2010020 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplatesResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendTemplatesResource.java @@ -66,6 +66,9 @@ clusterId = getClusterId(template); cluster = lookupCluster(clusterId); } + if (template.getVersion() != null) { + validateParameters(template.getVersion(), "baseTemplate"); + } VmStatic staticVm = getMapper(Template.class, VmStatic.class).map(template, getVm(cluster, template)); if (namedCluster(template)) { staticVm.setVdsGroupId(clusterId); @@ -78,6 +81,10 @@ AddVmTemplateParameters params = new AddVmTemplateParameters(staticVm, template.getName(), template.getDescription()); + if (template.getVersion() != null) { + params.setBaseTemplateId(Guid.createGuidFromString(template.getVersion().getBaseTemplate().getId())); + params.setTemplateVersionName(template.getVersion().getVersionName()); + } params.setConsoleEnabled(template.getConsole() != null && template.getConsole().isSetEnabled() ? template.getConsole().isEnabled() : !getConsoleDevicesForEntity(staticVm.getId()).isEmpty()); diff --git a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplatesResourceTest.java b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplatesResourceTest.java index d4e930b..3d1dac8 100644 --- a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplatesResourceTest.java +++ b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendTemplatesResourceTest.java @@ -4,17 +4,17 @@ import java.util.ArrayList; import java.util.List; - import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; - import javax.ws.rs.core.UriInfo; + import org.easymock.EasyMock; import org.junit.Test; import org.ovirt.engine.api.model.Cluster; import org.ovirt.engine.api.model.CreationStatus; import org.ovirt.engine.api.model.Permissions; import org.ovirt.engine.api.model.Template; +import org.ovirt.engine.api.model.TemplateVersion; import org.ovirt.engine.api.model.VM; import org.ovirt.engine.api.restapi.util.VmHelper; import org.ovirt.engine.core.common.action.AddVmTemplateParameters; @@ -35,6 +35,7 @@ extends AbstractBackendCollectionResourceTest<Template, VmTemplate, BackendTemplatesResource> { protected VmHelper vmHelper = VmHelper.getInstance(); + private static final String VERSION_NAME = "my new version"; public BackendTemplatesResourceTest() { super(new BackendTemplatesResource(), SearchType.VmTemplate, "Template : "); @@ -69,7 +70,7 @@ new String[] { "Id" }, new Object[] { GUIDS[1] }, setUpVm(GUIDS[1])); - setUpGetEntityExpectations(); + setUpGetEntityExpectations(0); setUpGetConsoleExpectations(new int[]{0, 0, 0}); setUpGetVirtioScsiExpectations(new int[]{0, 0}); setUpEntityQueryExpectations(VdcQueryType.GetVdsGroupByVdsGroupId, @@ -102,7 +103,7 @@ @Test public void testRemove() throws Exception { - setUpGetEntityExpectations(); + setUpGetEntityExpectations(0); setUriInfo(setUpActionExpectations(VdcActionType.RemoveVmTemplate, VmTemplateParametersBase.class, new String[] { "VmTemplateId" }, @@ -129,12 +130,12 @@ } } - private void setUpGetEntityExpectations() throws Exception { + private void setUpGetEntityExpectations(int index) throws Exception { setUpGetEntityExpectations(VdcQueryType.GetVmTemplate, GetVmTemplateParameters.class, new String[] { "Id" }, - new Object[] { GUIDS[0] }, - getEntity(0)); + new Object[] { GUIDS[index] }, + getEntity(index)); } @Test @@ -152,7 +153,7 @@ } protected void doTestBadRemove(boolean canDo, boolean success, String detail) throws Exception { - setUpGetEntityExpectations(); + setUpGetEntityExpectations(0); setUriInfo(setUpActionExpectations(VdcActionType.RemoveVmTemplate, VmTemplateParametersBase.class, new String[] { "VmTemplateId" }, @@ -235,7 +236,7 @@ new String[] { "Id" }, new Object[] { GUIDS[1] }, setUpVm(GUIDS[1])); - setUpGetEntityExpectations(); + setUpGetEntityExpectations(0); setUpEntityQueryExpectations(VdcQueryType.GetVdsGroupByVdsGroupId, IdQueryParameters.class, new String[] { "Id" }, @@ -265,6 +266,64 @@ } @Test + public void testAddVersionNoBaseTemplateId() throws Exception { + setUriInfo(setUpBasicUriExpectations()); + control.replay(); + Template t = getModel(2); + t.getVersion().setBaseTemplate(null); + try { + collection.add(t); + fail("Should have failed with 400 error due to a missing base template"); + } + catch (WebApplicationException e) { + assertNotNull(e.getResponse()); + assertEquals(400, e.getResponse().getStatus()); + } + } + + @Test + public void testAddVersion() throws Exception { + setUriInfo(setUpBasicUriExpectations()); + setUpHttpHeaderExpectations("Expect", "201-created"); + + setUpGetConsoleExpectations(new int[]{2, 0, 2}); + setUpGetVirtioScsiExpectations(new int[]{2, 2}); + setUpGetEntityExpectations(VdcQueryType.GetVmByVmId, + IdQueryParameters.class, + new String[] { "Id" }, + new Object[] { GUIDS[1] }, + setUpVm(GUIDS[1])); + setUpGetEntityExpectations(2); + setUpEntityQueryExpectations(VdcQueryType.GetVdsGroupByVdsGroupId, + IdQueryParameters.class, + new String[] { "Id" }, + new Object[] { GUIDS[2] }, + getVdsGroupEntity()); + + setUpCreationExpectations(VdcActionType.AddVmTemplate, + AddVmTemplateParameters.class, + new String[] { "Name", "Description" }, + new Object[] { NAMES[2], DESCRIPTIONS[2] }, + true, + true, + GUIDS[2], + asList(GUIDS[2]), + asList(new AsyncTaskStatus(AsyncTaskStatusEnum.finished)), + VdcQueryType.GetVmTemplate, + GetVmTemplateParameters.class, + new String[] { "Id" }, + new Object[] { GUIDS[2] }, + getEntity(2)); + + Response response = collection.add(getModel(2)); + assertEquals(201, response.getStatus()); + assertTrue(response.getEntity() instanceof Template); + assertEquals(((Template) response.getEntity()).getVersion().getVersionName(), VERSION_NAME); + assertEquals(((Template) response.getEntity()).getVersion().getBaseTemplate().getId(), GUIDS[1].toString()); + verifyModel((Template)response.getEntity(), 2); + } + + @Test public void testAddNamedVm() throws Exception { setUriInfo(setUpBasicUriExpectations()); setUpEntityQueryExpectations(VdcQueryType.GetVdsGroupByVdsGroupId, @@ -278,7 +337,7 @@ setUpGetEntityExpectations("VM: name=" + NAMES[1], SearchType.VM, setUpVm(GUIDS[1])); - setUpGetEntityExpectations(); + setUpGetEntityExpectations(0); setUpGetConsoleExpectations(new int[] {0, 0, 0}); setUpGetVirtioScsiExpectations(new int[] {0, 0}); @@ -326,7 +385,7 @@ new Object[] { NAMES[1] }, setUpVm(GUIDS[1])); - setUpGetEntityExpectations(); + setUpGetEntityExpectations(0); setUpGetConsoleExpectations(new int[] {0, 0, 0}); setUpGetVirtioScsiExpectations(new int[] {0, 0}); @@ -372,7 +431,7 @@ new String[] { "Id" }, new Object[] { GUIDS[1] }, setUpVm(GUIDS[1])); - setUpGetEntityExpectations(); + setUpGetEntityExpectations(0); setUpGetConsoleExpectations(new int[] {0, 0, 0}); setUpGetVirtioScsiExpectations(new int[] {0, 0}); @@ -418,7 +477,7 @@ new String[] { "Id" }, new Object[] { GUIDS[1] }, setUpVm(GUIDS[1])); - setUpGetEntityExpectations(); + setUpGetEntityExpectations(0); setUpGetConsoleExpectations(new int[] {0, 0, 0}); setUpGetVirtioScsiExpectations(new int[] {0, 0}); @@ -532,6 +591,18 @@ expect(entity.getDescription()).andReturn(DESCRIPTIONS[index]).anyTimes(); expect(entity.getNumOfCpus()).andReturn(8).anyTimes(); expect(entity.getNumOfSockets()).andReturn(2).anyTimes(); + if(index == 2) { + expect(entity.getTemplateVersionName()).andReturn(VERSION_NAME).anyTimes(); + expect(entity.getTemplateVersionNumber()).andReturn(2).anyTimes(); + expect(entity.getBaseTemplateId()).andReturn(GUIDS[1]).anyTimes(); + expect(entity.isBaseTemplate()).andReturn(false).anyTimes(); + } + else { + expect(entity.getTemplateVersionNumber()).andReturn(1).anyTimes(); + // same base template id as the template itself + expect(entity.getBaseTemplateId()).andReturn(GUIDS[index]).anyTimes(); + expect(entity.isBaseTemplate()).andReturn(true).anyTimes(); + } return entity; } @@ -543,7 +614,20 @@ model.getVm().setId(GUIDS[1].toString()); model.setCluster(new Cluster()); model.getCluster().setId(GUIDS[2].toString()); + if(index == 2) { + populateVersion(model); + } return model; + } + + public static void populateVersion(Template t) { + TemplateVersion templateVersion = new TemplateVersion(); + templateVersion.setVersionName(VERSION_NAME); + templateVersion.setVersionNumber(2); + Template base = new Template(); + base.setId(GUIDS[1].toString()); + templateVersion.setBaseTemplate(base); + t.setVersion(templateVersion); } @Override @@ -586,6 +670,14 @@ for (Template template : collection) { assertTrue(populated ? template.isSetConsole() : !template.isSetConsole()); + if(template.getId().equals(GUIDS[2].toString())) { + assertEquals(template.getVersion().getVersionName(), VERSION_NAME); + assertEquals(template.getVersion().getVersionNumber(), new Integer(2)); + assertEquals(template.getVersion().getBaseTemplate().getId(), GUIDS[1].toString()); + } + else { + assertNull(template.getVersion()); + } } } @@ -602,6 +694,10 @@ assertNotNull(model.getCpu().getTopology()); assertEquals(4, model.getCpu().getTopology().getCores().intValue()); assertEquals(2, model.getCpu().getTopology().getSockets().intValue()); + if(index == 2) { + assertNotNull(model.getVersion()); + assertNotSame(model.getVersion().getBaseTemplate().getId(), model.getId()); + } } private void setUpGetVirtioScsiExpectations(int ... idxs) throws Exception { diff --git a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/TemplateMapper.java b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/TemplateMapper.java index 1626db0..10cea77 100644 --- a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/TemplateMapper.java +++ b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/TemplateMapper.java @@ -1,5 +1,6 @@ package org.ovirt.engine.api.restapi.types; +import org.apache.commons.lang.StringUtils; import org.ovirt.engine.api.common.util.StatusUtils; import org.ovirt.engine.api.model.Architecture; import org.ovirt.engine.api.model.Boot; @@ -13,6 +14,7 @@ import org.ovirt.engine.api.model.OperatingSystem; import org.ovirt.engine.api.model.Template; import org.ovirt.engine.api.model.TemplateStatus; +import org.ovirt.engine.api.model.TemplateVersion; import org.ovirt.engine.api.model.Usb; import org.ovirt.engine.api.model.UsbType; import org.ovirt.engine.api.model.VmType; @@ -26,6 +28,7 @@ import org.ovirt.engine.core.common.businessentities.VmTemplateStatus; import org.ovirt.engine.core.common.osinfo.OsRepository; import org.ovirt.engine.core.common.utils.SimpleDependecyInjector; +import org.ovirt.engine.core.compat.Guid; import static org.ovirt.engine.api.restapi.types.IntegerMapper.mapNullToMinusOne; import static org.ovirt.engine.api.restapi.types.IntegerMapper.mapMinusOneToNull; @@ -162,6 +165,17 @@ if (model.isSetMigrationDowntime()) { entity.setMigrationDowntime(mapMinusOneToNull(model.getMigrationDowntime())); } + if (model.getVersion() != null) { + if (model.getVersion().getBaseTemplate() != null + && StringUtils.isNotEmpty(model.getVersion().getBaseTemplate().getId())) { + entity.setBaseTemplateId(Guid.createGuidFromString(model.getVersion().getBaseTemplate().getId())); + } + if (model.getVersion().isSetVersionName()) { + entity.setTemplateVersionName(model.getVersion().getVersionName()); + } + // numbering is generated in the backend, hence even if user specified version number, we ignore it. + } + return entity; } @@ -371,6 +385,17 @@ model.setTimezone(entity.getTimeZone()); model.setTunnelMigration(entity.getTunnelMigration()); model.setMigrationDowntime(mapNullToMinusOne(entity.getMigrationDowntime())); + // if this is not a base template, that means this is a template version + // so need to populate template version properties + if (!entity.isBaseTemplate()) { + TemplateVersion version = new TemplateVersion(); + version.setVersionName(entity.getTemplateVersionName()); + version.setVersionNumber(entity.getTemplateVersionNumber()); + Template baseTemplate = new Template(); + baseTemplate.setId(entity.getBaseTemplateId().toString()); + version.setBaseTemplate(baseTemplate); + model.setVersion(version); + } return model; } diff --git a/backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/TemplateMapperTest.java b/backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/TemplateMapperTest.java index 1c46fba..ad8b1eb 100644 --- a/backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/TemplateMapperTest.java +++ b/backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/TemplateMapperTest.java @@ -79,5 +79,7 @@ assertEquals(model.isDeleteProtected(), transform.isDeleteProtected()); assertEquals(model.isTunnelMigration(), transform.isTunnelMigration()); assertEquals(model.getMigrationDowntime(), transform.getMigrationDowntime()); + assertEquals(model.getVersion().getVersionName(), transform.getVersion().getVersionName()); + assertEquals(model.getVersion().getBaseTemplate().getId(), transform.getVersion().getBaseTemplate().getId()); } } -- To view, visit http://gerrit.ovirt.org/25019 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Id8e4c498c4a1856ac341237837db40db8375c6da Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.4 Gerrit-Owner: Alissa Bonas <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
