Hello Greg Padgett, I'd like you to do a code review. Please visit
http://gerrit.ovirt.org/22139 to review the following change. Change subject: restapi: cloud-init - rest api for start vm ...................................................................... restapi: cloud-init - rest api for start vm Support using cloud-init to perform initial setup of virtual machines. Further details available at: http://www.ovirt.org/Features/Cloud-Init_Integration This patch adds support for specifying Cloud-Init configuration when starting a VM using the REST API. Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1039009 Change-Id: I6ad0bfeca23cf8d4b2887010081d63c258032611 Signed-off-by: Greg Padgett <gpadg...@redhat.com> Signed-off-by: Omer Frenkel <ofren...@redhat.com> --- A backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/PayloadEncoding.java 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/BackendCapabilitiesResource.java M backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmResource.java M backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/utils/FeaturesHelper.java A backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/CloudInitValidator.java M backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/VmValidator.java M backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/VmMapper.java 9 files changed, 354 insertions(+), 10 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/39/22139/1 diff --git a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/PayloadEncoding.java b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/PayloadEncoding.java new file mode 100644 index 0000000..a6c1243 --- /dev/null +++ b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/PayloadEncoding.java @@ -0,0 +1,18 @@ +package org.ovirt.engine.api.model; + +public enum PayloadEncoding { + BASE64, + PLAINTEXT; + + public String value() { + return name().toLowerCase(); + } + + public static PayloadEncoding fromValue(String value) { + try { + return valueOf(value.toUpperCase()); + } catch (IllegalArgumentException e) { + return null; + } + } +} 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 ec4237a..47424ae 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 @@ -605,6 +605,7 @@ <xs:element ref="authentication_methods" minOccurs="0"/> <!-- Extrenal tasks --> <xs:element ref="step_types" minOccurs="0"/> + <xs:element ref="payload_encodings" minOccurs="0"/> <!-- Gluster related --> <xs:element ref="gluster_volume_types" minOccurs="0"/> <xs:element ref="transport_types" minOccurs="0"/> @@ -951,6 +952,20 @@ <xs:annotation> <xs:appinfo> <jaxb:property name="ScsiGenericIoOptions"/> + </xs:appinfo> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + + <xs:element name="payload_encodings" type="PayloadEncodings"/> + + <xs:complexType name="PayloadEncodings"> + <xs:sequence> + <xs:element name="payload_encodings" type="xs:string" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:appinfo> + <jaxb:property name="PayloadEncodings"/> </xs:appinfo> </xs:annotation> </xs:element> @@ -2368,8 +2383,74 @@ <xs:complexType name="Initialization"> <xs:sequence> <xs:element name="configuration" type="Configuration" minOccurs="0" maxOccurs="1"/> + <xs:element name="cloud_init" type="CloudInit" minOccurs="0" maxOccurs="1"/> </xs:sequence> - </xs:complexType> + </xs:complexType> + + <xs:element name="dns" type="DNS"/> + + <xs:complexType name="DNS"> + <xs:sequence> + <xs:element name="servers" type="Hosts" minOccurs="0" maxOccurs="1"/> + <xs:element name="search_domains" type="Hosts" minOccurs="0" maxOccurs="1"/> + </xs:sequence> + </xs:complexType> + + <xs:element name="authorized_key" type="AuthorizedKey"/> + + <xs:element name="authorized_keys" type="AuthorizedKeys"/> + + <xs:complexType name="AuthorizedKey"> + <xs:annotation> + <xs:appinfo> + <jaxb:class name="AuthorizedKey"/> + </xs:appinfo> + </xs:annotation> + <xs:complexContent> + <xs:extension base="BaseResource"> + <xs:sequence> + <xs:element ref="user" minOccurs="0" maxOccurs="1"/> + <xs:element name="key" type="xs:string" minOccurs="0" maxOccurs="1"/> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> + + <xs:complexType name="AuthorizedKeys"> + <xs:complexContent> + <xs:extension base="BaseResources"> + <xs:sequence> + <xs:annotation> + <xs:appinfo> + <jaxb:property name="AuthorizedKeys"/> + </xs:appinfo> + </xs:annotation> + <xs:element ref="authorized_key" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> + + <xs:element name="cloud_init" type="CloudInit"/> + + <xs:complexType name="CloudInit"> + <xs:sequence> + <xs:element ref="host" minOccurs="0"/> + <xs:element name="network" minOccurs="0"> + <xs:complexType> + <xs:sequence> + <xs:element ref="nics" minOccurs="0"/> + <xs:element ref="dns" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + </xs:element> <!-- </network> --> + <xs:element ref="authorized_keys" minOccurs="0"/> + <xs:element name="regenerate_ssh_keys" type="xs:boolean" minOccurs="0"/> + <xs:element name="timezone" type="xs:string" minOccurs="0"/> + <xs:element ref="users" minOccurs="0"/> + <xs:element ref="files" minOccurs="0" maxOccurs="1"/> + </xs:sequence> + </xs:complexType> <xs:complexType name="VmPlacementPolicy"> <xs:sequence> @@ -2807,6 +2888,8 @@ <xs:element ref="port_mirroring" minOccurs="0" maxOccurs="1"/> <!-- Deprecated, replaced by 'vnic_profile' --> <xs:element ref="reported_devices" minOccurs="0" maxOccurs="1"/> <xs:element ref="vnic_profile" minOccurs="0" maxOccurs="1"/> + <xs:element name="boot_protocol" type="xs:string" minOccurs="0"/> + <xs:element name="on_boot" type="xs:boolean" minOccurs="0"/> </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 2f6520d..ab0caa0 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 @@ -282,7 +282,25 @@ action.async: 'xs:boolean', action.vm.os.kernel: 'xs:string', action.grace_period.expiry: 'xs:long', action.vm.display.type: 'xs:string', action.vm.stateless: 'xs:boolean', action.vm.os.cmdline: 'xs:string', action.vm.domain.user.username: 'xs:string', action.pause: 'xs:boolean', - action.vm.os.boot--COLLECTION: {boot.dev: 'xs:string'}, action.vm.domain.user.password: 'xs:string'} + action.vm.os.boot--COLLECTION: {boot.dev: 'xs:string'}, action.vm.domain.user.password: 'xs:string', + action.vm.initialization.cloud-init: {cloud-init.hostname: 'xs:string', + cloud-init.network.nics.nic--COLLECTION: {nic.name: 'xs:string', + nic.boot_protocol: 'xs:string', + nic.network.address.ip: 'xs:string', + nic.network.address.netmask: 'xs:string', + nic.network.address.gateway: 'xs:string', + nic.onboot: 'xs:boolean'}, + cloud-init.network.dns.servers.host--COLLECTION: {host.address: 'xs:string'}, + cloud-init.network.dns.search_domains.host--COLLECTION: {host.address: 'xs:string'}, + cloud-init.authorized_keys.authorized_key--COLLECTION: {authorized_key.key: 'xs:string', + authorized_key.user.name: 'xs:string'}, + cloud-init.regenerate_ssh_keys: 'xs:boolean', + cloud-init.timezone: 'xs:string', + cloud-init.users.user--COLLECTION: {user.password: 'xs:string', + user.name: 'xs:string'}, + cloud-init.payload_files.payload_file--COLLECTION: {payload_file.name: 'xs:string', + payload_file.content: 'xs:string', + payload_file.type: 'xs:string'}}} description: start a virtual machine in the system identified by the given id with the options specified in the request body urlparams: {} headers: diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendCapabilitiesResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendCapabilitiesResource.java index 4c228d1..889d1af 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendCapabilitiesResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendCapabilitiesResource.java @@ -57,6 +57,8 @@ import org.ovirt.engine.api.model.OsType; import org.ovirt.engine.api.model.OsTypeUtils; import org.ovirt.engine.api.model.OsTypes; +import org.ovirt.engine.api.model.PayloadEncoding; +import org.ovirt.engine.api.model.PayloadEncodings; import org.ovirt.engine.api.model.Permit; import org.ovirt.engine.api.model.PermitType; import org.ovirt.engine.api.model.Permits; @@ -236,6 +238,7 @@ addWatchdogModels(version, WatchdogModel.values()); addConfigurationTypes(version, ConfigurationType.values()); addSnapshotStatuses(version, SnapshotStatus.values()); + addPayloadEncodings(version, PayloadEncoding.values()); // External tasks types addStepEnumTypes(version, StepEnum.values()); @@ -263,6 +266,15 @@ } } + private void addPayloadEncodings(VersionCaps version, PayloadEncoding[] values) { + if (VersionUtils.greaterOrEqual(version, VERSION_3_3)) { + version.setPayloadEncodings(new PayloadEncodings()); + for (PayloadEncoding mode : values) { + version.getPayloadEncodings().getPayloadEncodings().add(mode.value()); + } + } + } + private void addCpuModes(VersionCaps version, CpuMode[] values) { if (VersionUtils.greaterOrEqual(version, VERSION_3_2)) { version.setCpuModes(new CpuModes()); diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmResource.java index 3dccc3f..c0219ef 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendVmResource.java @@ -1,17 +1,25 @@ package org.ovirt.engine.api.restapi.resource; +import static org.ovirt.engine.api.restapi.resource.BackendVmsResource.SUB_COLLECTIONS; +import static org.ovirt.engine.core.utils.Ticketing.GenerateOTP; + import java.util.List; import java.util.Set; + +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; + import org.ovirt.engine.api.common.util.DetailHelper; import org.ovirt.engine.api.common.util.DetailHelper.Detail; import org.ovirt.engine.api.common.util.LinkHelper; import org.ovirt.engine.api.model.Action; +import org.ovirt.engine.api.model.AuthorizedKey; import org.ovirt.engine.api.model.CdRom; import org.ovirt.engine.api.model.CdRoms; import org.ovirt.engine.api.model.Certificate; +import org.ovirt.engine.api.model.CloudInit; import org.ovirt.engine.api.model.CreationStatus; import org.ovirt.engine.api.model.Display; import org.ovirt.engine.api.model.Statistic; @@ -34,6 +42,7 @@ import org.ovirt.engine.api.restapi.types.VmMapper; import org.ovirt.engine.core.common.VdcObjectType; import org.ovirt.engine.core.common.action.ChangeVMClusterParameters; +import org.ovirt.engine.core.common.action.CloudInitParameters; import org.ovirt.engine.core.common.action.MigrateVmParameters; import org.ovirt.engine.core.common.action.MigrateVmToServerParameters; import org.ovirt.engine.core.common.action.MoveVmParameters; @@ -48,6 +57,7 @@ import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VmManagementParametersBase; import org.ovirt.engine.core.common.action.VmOperationParameterBase; +import org.ovirt.engine.core.common.businessentities.InitializationType; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VDSGroup; import org.ovirt.engine.core.common.businessentities.VmStatic; @@ -57,10 +67,6 @@ import org.ovirt.engine.core.common.queries.VdcQueryReturnValue; import org.ovirt.engine.core.common.queries.VdcQueryType; import org.ovirt.engine.core.compat.Guid; - - -import static org.ovirt.engine.api.restapi.resource.BackendVmsResource.SUB_COLLECTIONS; -import static org.ovirt.engine.core.utils.Ticketing.GenerateOTP; public class BackendVmResource extends AbstractBackendActionableResource<VM, org.ovirt.engine.core.common.businessentities.VM> implements @@ -234,6 +240,23 @@ validateParameters(vm.getPlacementPolicy(), "host.id|name"); params.setDestinationVdsId(getHostId(vm.getPlacementPolicy().getHost())); } + if (vm.isSetInitialization() && vm.getInitialization().isSetCloudInit()) { + CloudInit cloudInit = vm.getInitialization().getCloudInit(); + // currently only 'root' user is supported, alert the user if other user sent + if (cloudInit.isSetAuthorizedKeys()) { + for (AuthorizedKey authKey : cloudInit.getAuthorizedKeys().getAuthorizedKeys()) { + if (!"root".equals(authKey.getUser().getUserName())) { + throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) +.entity("Currently only the user 'root' is supported for authorized keys") +.build()); + } + } + } + params.setInitializationType(InitializationType.CloudInit); + ((RunVmOnceParams) params).setCloudInitParameters( + getMapper(CloudInit.class, CloudInitParameters.class) + .map(cloudInit, null)); + } } else { actionType = VdcActionType.RunVm; params = new RunVmParams(guid); diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/utils/FeaturesHelper.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/utils/FeaturesHelper.java index 58f0bf2..c0dafe0 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/utils/FeaturesHelper.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/utils/FeaturesHelper.java @@ -70,6 +70,7 @@ addGlusterHooksFeature(features); addFeatureReportVmFQDN(features); addFeatureAttachDiskSnapshot(features); + addFeatureCloudInit(features); } return features; } @@ -374,4 +375,12 @@ feature.setDescription("Ability to report the fully qualified domain name (FQDN) of a Virtual Machine"); features.getFeature().add(feature); } + + private void addFeatureCloudInit(Features features) { + Feature feature = new Feature(); + feature.setName("Cloud Init"); + feature.setDescription("Support for VM initialization with Cloud Init."); + features.getFeature().add(feature); + } + } diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/CloudInitValidator.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/CloudInitValidator.java new file mode 100644 index 0000000..626225c --- /dev/null +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/CloudInitValidator.java @@ -0,0 +1,34 @@ +package org.ovirt.engine.api.restapi.resource.validation; + +import static org.ovirt.engine.api.common.util.EnumValidator.validateEnum; + +import org.ovirt.engine.api.model.BootProtocol; +import org.ovirt.engine.api.model.CloudInit; +import org.ovirt.engine.api.model.File; +import org.ovirt.engine.api.model.NIC; +import org.ovirt.engine.api.model.PayloadEncoding; + +@ValidatedClass(clazz = CloudInit.class) +public class CloudInitValidator implements Validator<CloudInit> { + + @Override + public void validateEnums(CloudInit model) { + if (model != null) { + if (model.isSetNetwork()) { + if (model.getNetwork().isSetNics() + && !model.getNetwork().getNics().getNics().isEmpty()) { + for (NIC iface : model.getNetwork().getNics().getNics()) { + validateEnum(BootProtocol.class, iface.getBootProtocol(), true); + } + } + } + if (model.isSetFiles() + && model.getFiles().isSetFiles() + && !model.getFiles().getFiles().isEmpty()) { + for (File file : model.getFiles().getFiles()) { + validateEnum(PayloadEncoding.class, file.getType(), true); + } + } + } + } +} diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/VmValidator.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/VmValidator.java index 69e53a4..06fa1ad 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/VmValidator.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/VmValidator.java @@ -1,10 +1,10 @@ package org.ovirt.engine.api.restapi.resource.validation; +import static org.ovirt.engine.api.common.util.EnumValidator.validateEnum; + import org.ovirt.engine.api.model.Payload; import org.ovirt.engine.api.model.VM; import org.ovirt.engine.api.model.VmType; - -import static org.ovirt.engine.api.common.util.EnumValidator.validateEnum; @ValidatedClass(clazz = VM.class) public class VmValidator implements Validator<VM> { @@ -15,6 +15,7 @@ private PlacementPolicyValidator placementPolicyValidator = new PlacementPolicyValidator(); private PayloadValidator payloadValidator = new PayloadValidator(); private ConfigurationValidator configurationValidator = new ConfigurationValidator(); + private CloudInitValidator cloudInitValidator = new CloudInitValidator(); @Override public void validateEnums(VM vm) { @@ -38,9 +39,13 @@ payloadValidator.validateEnums(payload); } } - if (vm.isSetInitialization() && vm.getInitialization().isSetConfiguration()) { configurationValidator.validateEnums(vm.getInitialization().getConfiguration()); } + if (vm.isSetInitialization()) { + if (vm.getInitialization().isSetCloudInit()) { + cloudInitValidator.validateEnums(vm.getInitialization().getCloudInit()); + } + } } } diff --git a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/VmMapper.java b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/VmMapper.java index 56450d4..e0e1795 100644 --- a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/VmMapper.java +++ b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/VmMapper.java @@ -3,6 +3,7 @@ import static org.ovirt.engine.core.compat.Guid.createGuidFromString; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -10,9 +11,12 @@ import org.apache.commons.lang.StringUtils; import org.ovirt.engine.api.common.util.StatusUtils; +import org.ovirt.engine.api.model.AuthorizedKey; import org.ovirt.engine.api.model.Boot; import org.ovirt.engine.api.model.BootDevice; +import org.ovirt.engine.api.model.BootProtocol; import org.ovirt.engine.api.model.CPU; +import org.ovirt.engine.api.model.CloudInit; import org.ovirt.engine.api.model.Cluster; import org.ovirt.engine.api.model.ConfigurationType; import org.ovirt.engine.api.model.CpuMode; @@ -24,20 +28,23 @@ import org.ovirt.engine.api.model.DisplayType; import org.ovirt.engine.api.model.Domain; import org.ovirt.engine.api.model.File; +import org.ovirt.engine.api.model.Files; import org.ovirt.engine.api.model.GuestInfo; import org.ovirt.engine.api.model.HighAvailability; import org.ovirt.engine.api.model.Host; import org.ovirt.engine.api.model.IP; import org.ovirt.engine.api.model.IPs; import org.ovirt.engine.api.model.MemoryPolicy; +import org.ovirt.engine.api.model.NIC; import org.ovirt.engine.api.model.OperatingSystem; import org.ovirt.engine.api.model.OsType; import org.ovirt.engine.api.model.Payload; -import org.ovirt.engine.api.model.Files; +import org.ovirt.engine.api.model.PayloadEncoding; import org.ovirt.engine.api.model.Quota; import org.ovirt.engine.api.model.Template; import org.ovirt.engine.api.model.Usb; import org.ovirt.engine.api.model.UsbType; +import org.ovirt.engine.api.model.User; import org.ovirt.engine.api.model.VCpuPin; import org.ovirt.engine.api.model.VM; import org.ovirt.engine.api.model.VmAffinity; @@ -48,6 +55,8 @@ import org.ovirt.engine.api.restapi.utils.CustomPropertiesParser; import org.ovirt.engine.api.restapi.utils.GuidUtils; import org.ovirt.engine.api.restapi.utils.UsbMapperUtils; +import org.ovirt.engine.core.common.action.CloudInitParameters; +import org.ovirt.engine.core.common.action.CloudInitParameters.Attachment; import org.ovirt.engine.core.common.action.RunVmOnceParams; import org.ovirt.engine.core.common.businessentities.BootSequence; import org.ovirt.engine.core.common.businessentities.MigrationSupport; @@ -58,6 +67,8 @@ import org.ovirt.engine.core.common.businessentities.VmPayload; import org.ovirt.engine.core.common.businessentities.VmStatic; import org.ovirt.engine.core.common.businessentities.VmTemplate; +import org.ovirt.engine.core.common.businessentities.network.NetworkBootProtocol; +import org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface; import org.ovirt.engine.core.common.osinfo.OsRepository; import org.ovirt.engine.core.common.utils.SimpleDependecyInjector; import org.ovirt.engine.core.common.utils.VmDeviceType; @@ -902,6 +913,137 @@ return entity; } + @Mapping(from = Attachment.AttachmentType.class, to = PayloadEncoding.class) + public static PayloadEncoding map(Attachment.AttachmentType attachmentType, PayloadEncoding template) { + switch (attachmentType) { + case BASE64: return PayloadEncoding.BASE64; + case PLAINTEXT: return PayloadEncoding.PLAINTEXT; + default: return null; + } + } + + @Mapping(from = PayloadEncoding.class, to = Attachment.AttachmentType.class) + public static Attachment.AttachmentType map(PayloadEncoding attachmentType, Attachment.AttachmentType template) { + switch (attachmentType) { + case BASE64: return Attachment.AttachmentType.BASE64; + case PLAINTEXT: return Attachment.AttachmentType.PLAINTEXT; + default: return null; + } + } + + @Mapping(from = CloudInit.class, to = CloudInitParameters.class) + public static CloudInitParameters map(CloudInit model, CloudInitParameters template) { + CloudInitParameters entity = template != null ? template : new CloudInitParameters(); + + if (model.isSetHost() && model.getHost().isSetAddress()) { + entity.setHostname(model.getHost().getAddress()); + } + + if (model.isSetAuthorizedKeys() + && model.getAuthorizedKeys().isSetAuthorizedKeys() + && !model.getAuthorizedKeys().getAuthorizedKeys().isEmpty()) { + StringBuilder keys = new StringBuilder(); + for (AuthorizedKey authKey : model.getAuthorizedKeys().getAuthorizedKeys()) { + if (keys.length() > 0) { + keys.append("\n"); + } + keys.append(authKey.getKey()); + } + entity.setAuthorizedKeys(keys.toString()); + } + + if (model.isSetRegenerateSshKeys()) { + entity.setRegenerateKeys(model.isRegenerateSshKeys()); + } + + if (model.isSetNetwork()) { + if (model.getNetwork().isSetNics()) { + Map<String, VdsNetworkInterface> interfaces = new HashMap<>(); + for (NIC iface : model.getNetwork().getNics().getNics()) { + VdsNetworkInterface vdsNetworkInterface = new VdsNetworkInterface(); + if (iface.isSetBootProtocol()) { + NetworkBootProtocol protocol = HostNicMapper.map(BootProtocol.fromValue(iface.getBootProtocol()), null); + vdsNetworkInterface.setBootProtocol(protocol); + if (protocol != NetworkBootProtocol.DHCP && iface.isSetNetwork() && iface.getNetwork().isSetIp()) { + if (iface.getNetwork().getIp().isSetAddress()) { + vdsNetworkInterface.setAddress(iface.getNetwork().getIp().getAddress()); + } + if (iface.getNetwork().getIp().isSetNetmask()) { + vdsNetworkInterface.setSubnet(iface.getNetwork().getIp().getNetmask()); + } + if (iface.getNetwork().getIp().isSetGateway()) { + vdsNetworkInterface.setGateway(iface.getNetwork().getIp().getGateway()); + } + } + } + + interfaces.put(iface.getName(), vdsNetworkInterface); + + if (iface.isSetOnBoot() && iface.isOnBoot()) { + if (entity.getStartOnBoot() == null) { + entity.setStartOnBoot(new ArrayList<String>()); + } + entity.getStartOnBoot().add(iface.getName()); + } + } + + entity.setInterfaces(interfaces); + } + if (model.getNetwork().isSetDns()) { + if (model.getNetwork().getDns().isSetServers() + && model.getNetwork().getDns().getServers().isSetHosts() + && !model.getNetwork().getDns().getServers().getHosts().isEmpty()) { + List<String> dnsServers = new ArrayList<>(); + for (Host host : model.getNetwork().getDns().getServers().getHosts()) { + if (host.isSetAddress()) { + dnsServers.add(host.getAddress()); + } + } + entity.setDnsServers(dnsServers); + } + + if (model.getNetwork().getDns().isSetSearchDomains() + && model.getNetwork().getDns().getSearchDomains().isSetHosts() + && !model.getNetwork().getDns().getSearchDomains().getHosts().isEmpty()) { + List<String> searchDomains = new ArrayList<>(); + for (Host host : model.getNetwork().getDns().getSearchDomains().getHosts()) { + if (host.isSetAddress()) { + searchDomains.add(host.getAddress()); + } + } + entity.setDnsSearch(searchDomains); + } + } + } + + if (model.isSetTimezone() && model.getTimezone() != null) { + entity.setTimeZone(model.getTimezone()); + } + + if (model.isSetUsers()) { + for (User user : model.getUsers().getUsers()) { + // currently only root password supported in backend + if ("root".equals(user.getUserName())) { + entity.setRootPassword(user.getPassword()); + } + } + } + + if (model.isSetFiles() + && model.getFiles().isSetFiles() + && !model.getFiles().getFiles().isEmpty()) { + entity.setAttachments(new HashMap<String, Attachment>()); + for (File file : model.getFiles().getFiles()) { + Attachment attachment = new Attachment(); + attachment.setAttachmentType(map(PayloadEncoding.fromValue(file.getType()), null)); + attachment.setContent(file.getContent()); + entity.getAttachments().put(file.getName(), attachment); + } + } + + return entity; + } + static String cpuTuneToString(final CpuTune tune) { final StringBuilder builder = new StringBuilder(); boolean first = true; -- To view, visit http://gerrit.ovirt.org/22139 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I6ad0bfeca23cf8d4b2887010081d63c258032611 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.3.2 Gerrit-Owner: Omer Frenkel <ofren...@redhat.com> Gerrit-Reviewer: Greg Padgett <gpadg...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches