Hello Greg Padgett,
I'd like you to do a code review. Please visit
http://gerrit.ovirt.org/21447
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=990572
Change-Id: I6ad0bfeca23cf8d4b2887010081d63c258032611
Signed-off-by: Greg Padgett <[email protected]>
Signed-off-by: Omer Frenkel <[email protected]>
---
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, 353 insertions(+), 9 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/47/21447/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 022687c..7974288 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
@@ -283,6 +283,24 @@
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.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/21447
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
Gerrit-Owner: Omer Frenkel <[email protected]>
Gerrit-Reviewer: Greg Padgett <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches