From 54b2b3b9c3a3b6ecb1da09735a4da2c6644588c7 Mon Sep 17 00:00:00 2001
From: wangge <wangge20@huawei.com>
Date: Tue, 28 Sep 2021 16:42:15 +0800
Subject: [PATCH 1/2] add support running on kunpeng platform

---
 automation/build-artifacts.sh                 |   3 +-
 .../ovirt/engine/core/bll/AddVmCommand.java   |   3 +-
 .../core/bll/ClusterOperationCommandBase.java |   2 +
 .../core/bll/CpuFlagsManagerHandler.java      |  41 ++++++-
 .../ovirt/engine/core/bll/RunVmCommand.java   |   3 +-
 .../engine/core/bll/UpdateVmCommand.java      |   3 +-
 .../architecture/HasMaximumNumberOfDisks.java |   5 +
 .../cluster/KubevirtProviderProxy.java        |   6 +-
 .../core/bll/validator/ClusterValidator.java  |   3 +-
 .../businessentities/ArchitectureType.java    |   5 +
 .../common/businessentities/BiosType.java     |   3 +-
 .../common/businessentities/ChipsetType.java  |   3 +-
 .../core/common/config/ConfigValues.java      |   3 +
 .../core/common/osinfo/OsRepository.java      |   1 +
 .../engine/core/common/utils/CpuVendor.java   |   3 +-
 .../core/common/utils/VmCommonUtils.java      |   6 +-
 .../core/common/utils/VmCpuCountHelper.java   |   4 +-
 .../src/main/resources/v3/capabilities.xml    |   8 ++
 .../engine/api/restapi/types/CPUMapper.java   |   4 +
 .../engine/core/utils/OsRepositoryImpl.java   |   3 +-
 .../org/ovirt/engine/core/utils/OvfUtils.java |   3 +-
 .../utils/archstrategy/Aarch64Strategy.java   |  18 +++
 .../core/utils/archstrategy/ArchCommand.java  |   2 +
 .../archstrategy/ArchStrategyFactory.java     |   1 +
 .../engine/core/utils/ovf/OvfOvaWriter.java   |   1 +
 .../ovirt/engine/core/utils/osinfo/osinfo.jj  |   4 +-
 .../CreateAdditionalControllers.java          |   5 +
 ...eateAdditionalControllersForDomainXml.java |   5 +
 .../architecture/GetBootableDiskIndex.java    |   5 +
 .../architecture/GetControllerIndices.java    |   6 +
 .../builder/vminfo/LibvirtVmXmlBuilder.java   | 111 ++++++++++++------
 .../builder/vminfo/VmInfoBuildUtils.java      |   2 +
 .../dataprovider/AsyncDataProvider.java       |  11 +-
 .../uicommonweb/models/hosts/HostModel.java   |   2 +
 .../models/vms/ImportVmFromOvaModel.java      |   2 +-
 .../column/ClusterAdditionalStatusColumn.java |   3 +-
 packaging/conf/osinfo-defaults.properties     |  19 +++
 ...eral_version_of_nongeneral_vdc_options.sql |   1 +
 .../upgrade/pre_upgrade/0000_config.sql       |  21 ++--
 .../engine_common/constants.py                |   1 +
 41 files changed, 264 insertions(+), 71 deletions(-)
 create mode 100644 backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/Aarch64Strategy.java

diff --git a/automation/build-artifacts.sh b/automation/build-artifacts.sh
index b830c5d..7f60f5f 100755
--- a/automation/build-artifacts.sh
+++ b/automation/build-artifacts.sh
@@ -19,7 +19,8 @@ export MAVEN_OPTS
 
 if [ -d /root/.m2/repository/org/ovirt ]; then
     echo "Deleting ovirt folder from maven cache"
-    rm -rf /root/.m2/repository/org/ovirt
+# Do not delete the existing packages for now,you can directly use the compiled ovirt-engine-api and other related jar packages
+#    rm -rf /root/.m2/repository/org/ovirt
 fi
 
 MAVEN_SETTINGS="/etc/maven/settings.xml"
diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVmCommand.java
index 1db572d..0dd46d7 100644
--- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVmCommand.java
+++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVmCommand.java
@@ -830,7 +830,8 @@ public class AddVmCommand<T extends AddVmParameters> extends VmManagementCommand
                 && vmFromParams.getCustomBiosType() != BiosType.CLUSTER_DEFAULT
                 && vmFromParams.getCustomBiosType() != BiosType.I440FX_SEA_BIOS
                 && getCluster().getArchitecture() != ArchitectureType.undefined
-                && getCluster().getArchitecture().getFamily() != ArchitectureType.x86) {
+                && getCluster().getArchitecture().getFamily() != ArchitectureType.x86
+                && getCluster().getArchitecture().getFamily() != ArchitectureType.aarch64) {
             return failValidation(EngineMessage.NON_DEFAULT_BIOS_TYPE_FOR_X86_ONLY);
         }
 
diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ClusterOperationCommandBase.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ClusterOperationCommandBase.java
index 1fd05a0..6f05339 100644
--- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ClusterOperationCommandBase.java
+++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ClusterOperationCommandBase.java
@@ -181,6 +181,8 @@ public abstract class ClusterOperationCommandBase<T extends ClusterOperationPara
                 && cluster.getArchitecture() != null
                 && cluster.getArchitecture().getFamily() == ArchitectureType.x86) {
             cluster.setBiosType(BiosType.Q35_SEA_BIOS);
+        } else if (cluster.getArchitecture().getFamily() == ArchitectureType.aarch64) {
+            cluster.setBiosType(BiosType.VIRT_OVMF);
         } else {
             cluster.setBiosType(BiosType.I440FX_SEA_BIOS);
         }
diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CpuFlagsManagerHandler.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CpuFlagsManagerHandler.java
index 6cd4419..40ab278 100644
--- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CpuFlagsManagerHandler.java
+++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CpuFlagsManagerHandler.java
@@ -157,15 +157,18 @@ public class CpuFlagsManagerHandler implements BackendService {
         private List<ServerCpu> amdCpuList;
         private List<ServerCpu> ibmCpuList;
         private List<ServerCpu> s390CpuList;
+        private List<ServerCpu> kunpengCpuList;
         private List<ServerCpu> allCpuList = new ArrayList<>();
         private Map<String, ServerCpu> intelCpuByNameDictionary = new HashMap<>();
         private Map<String, ServerCpu> amdCpuByNameDictionary = new HashMap<>();
         private Map<String, ServerCpu> ibmCpuByNameDictionary = new HashMap<>();
         private Map<String, ServerCpu> s390CpuByNameDictionary = new HashMap<>();
+        private Map<String, ServerCpu> kunpengCpuByNameDictionary = new HashMap<>();
         private Map<String, ServerCpu> intelCpuByVdsNameDictionary = new HashMap<>();
         private Map<String, ServerCpu> amdCpuByVdsNameDictionary = new HashMap<>();
         private Map<String, ServerCpu> ibmCpuByVdsNameDictionary = new HashMap<>();
         private Map<String, ServerCpu> s390CpuByVdsNameDictionary = new HashMap<>();
+        private Map<String, ServerCpu> kunpengCpuByVdsNameDictionary = new HashMap<>();
 
         public CpuFlagsManager(Version ver) {
             initDictionaries(ver);
@@ -200,6 +203,8 @@ public class CpuFlagsManagerHandler implements BackendService {
                     result = CpuVendor.IBM.name();
                 } else if (s390CpuByNameDictionary.get(cpuName) != null) {
                     result = CpuVendor.IBMS390.name();
+                } else if (kunpengCpuByNameDictionary.get(cpuName) != null) {
+                    result = CpuVendor.KUNPENG.name();
                 }
             }
             return result;
@@ -222,6 +227,10 @@ public class CpuFlagsManagerHandler implements BackendService {
                 if (result == null) {
                     result = s390CpuByNameDictionary.get(cpuName);
                 }
+
+                if (result == null) {
+                    result = kunpengCpuByNameDictionary.get(cpuName);
+                }
             }
             return result;
         }
@@ -233,6 +242,7 @@ public class CpuFlagsManagerHandler implements BackendService {
             amdCpuByNameDictionary.clear();
             ibmCpuByNameDictionary.clear();
             s390CpuByNameDictionary.clear();
+            kunpengCpuByNameDictionary.clear();
             allCpuList.clear();
 
             String[] cpus = Config.<String> getValue(ConfigValues.ServerCPUList, ver.toString()).trim().split("[;]", -1);
@@ -271,6 +281,9 @@ public class CpuFlagsManagerHandler implements BackendService {
                         } else if (sc.getFlags().contains(CpuVendor.IBMS390.getFlag())) {
                             s390CpuByNameDictionary.put(sc.getCpuName(), sc);
                             s390CpuByVdsNameDictionary.put(sc.getVdsVerbData(), sc);
+                        } else if (sc.getFlags().contains(CpuVendor.KUNPENG.getFlag())) {
+                            kunpengCpuByNameDictionary.put(sc.getCpuName(), sc);
+                            kunpengCpuByVdsNameDictionary.put(sc.getVdsVerbData(), sc);
                         }
 
                         allCpuList.add(sc);
@@ -283,6 +296,7 @@ public class CpuFlagsManagerHandler implements BackendService {
             amdCpuList = new ArrayList<>(amdCpuByNameDictionary.values());
             ibmCpuList = new ArrayList<>(ibmCpuByNameDictionary.values());
             s390CpuList = new ArrayList<>(s390CpuByNameDictionary.values());
+            kunpengCpuList = new ArrayList<>(kunpengCpuByNameDictionary.values());
 
             Comparator<ServerCpu> cpuComparator = Comparator.comparingInt(ServerCpu::getLevel);
 
@@ -292,6 +306,7 @@ public class CpuFlagsManagerHandler implements BackendService {
             Collections.sort(amdCpuList, cpuComparator);
             Collections.sort(ibmCpuList, cpuComparator);
             Collections.sort(s390CpuList, cpuComparator);
+            Collections.sort(kunpengCpuList, cpuComparator);
         }
 
         public String getVDSVerbDataByCpuName(String name) {
@@ -301,7 +316,8 @@ public class CpuFlagsManagerHandler implements BackendService {
                 if ((sc = intelCpuByNameDictionary.get(name)) != null
                         || (sc = amdCpuByNameDictionary.get(name)) != null
                         || (sc = ibmCpuByNameDictionary.get(name)) != null
-                        || (sc = s390CpuByNameDictionary.get(name)) != null) {
+                        || (sc = s390CpuByNameDictionary.get(name)) != null
+                        || (sc = kunpengCpuByNameDictionary.get(name)) != null) {
                     result = sc.getVdsVerbData();
                 }
             }
@@ -315,7 +331,8 @@ public class CpuFlagsManagerHandler implements BackendService {
                 if ((sc = intelCpuByVdsNameDictionary.get(vdsName)) != null
                         || (sc = amdCpuByVdsNameDictionary.get(vdsName)) != null
                         || (sc = ibmCpuByVdsNameDictionary.get(vdsName)) != null
-                        || (sc = s390CpuByVdsNameDictionary.get(vdsName)) != null) {
+                        || (sc = s390CpuByVdsNameDictionary.get(vdsName)) != null
+                        || (sc = kunpengCpuByVdsNameDictionary.get(vdsName)) != null) {
                     result = sc.getCpuName();
                 }
             }
@@ -346,6 +363,7 @@ public class CpuFlagsManagerHandler implements BackendService {
                             || (clusterCpu = amdCpuByNameDictionary.get(clusterCpuName)) != null
                             || (clusterCpu = ibmCpuByNameDictionary.get(clusterCpuName)) != null
                             || (clusterCpu = s390CpuByNameDictionary.get(clusterCpuName)) != null
+                            || (clusterCpu = kunpengCpuByNameDictionary.get(clusterCpuName)) != null
                     )) {
                 for (String flag : clusterCpu.getFlags()) {
                     if (!lstServerflags.contains(flag)) {
@@ -393,6 +411,10 @@ public class CpuFlagsManagerHandler implements BackendService {
                 return s390CpuByNameDictionary.containsKey(cpuName2);
             }
 
+            if (kunpengCpuByNameDictionary.containsKey(cpuName1)) {
+                return kunpengCpuByNameDictionary.containsKey(cpuName2);
+            }
+
             return false;
         }
 
@@ -401,7 +423,8 @@ public class CpuFlagsManagerHandler implements BackendService {
                     && (intelCpuByNameDictionary.containsKey(cpuName)
                             || amdCpuByNameDictionary.containsKey(cpuName)
                             || ibmCpuByNameDictionary.containsKey(cpuName)
-                            || s390CpuByNameDictionary.containsKey(cpuName));
+                            || s390CpuByNameDictionary.containsKey(cpuName)
+                            || kunpengCpuByNameDictionary.containsKey(cpuName));
         }
 
         /**
@@ -441,6 +464,12 @@ public class CpuFlagsManagerHandler implements BackendService {
                         foundCpus.add(s390CpuList.get(i));
                     }
                 }
+            } else if (lstFlags.contains(CpuVendor.KUNPENG.getFlag())) {
+                for (int i = kunpengCpuList.size() - 1; i >= 0; i--) {
+                    if (checkIfFlagsContainsCpuFlags(kunpengCpuList.get(i), lstFlags)) {
+                        foundCpus.add(kunpengCpuList.get(i));
+                    }
+                }
             }
             return foundCpus;
         }
@@ -478,6 +507,12 @@ public class CpuFlagsManagerHandler implements BackendService {
                 for (int i = 0; i <= selectedCpuIndex; i++) {
                     supportedCpus.add(s390CpuList.get(i));
                 }
+            } else if (kunpengCpuByNameDictionary.containsKey(maxCpuName)) {
+                ServerCpu selected = kunpengCpuByNameDictionary.get(maxCpuName);
+                int selectedCpuIndex = kunpengCpuList.indexOf(selected);
+                for (int i = 0; i <= selectedCpuIndex; i++) {
+                    supportedCpus.add(kunpengCpuList.get(i));
+                }
             }
             return supportedCpus;
 
diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java
index 11155e4..7782b90 100644
--- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java
+++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java
@@ -1133,7 +1133,8 @@ public class RunVmCommand<T extends RunVmParams> extends RunVmCommandBase<T>
         if (FeatureSupported.isBiosTypeSupported(getCluster().getCompatibilityVersion())
                 && getVm().getCustomBiosType() != BiosType.CLUSTER_DEFAULT
                 && getVm().getCustomBiosType() != BiosType.I440FX_SEA_BIOS
-                && getCluster().getArchitecture().getFamily() != ArchitectureType.x86) {
+                && getCluster().getArchitecture().getFamily() != ArchitectureType.x86
+                && getCluster().getArchitecture().getFamily() != ArchitectureType.aarch64) {
             return failValidation(EngineMessage.NON_DEFAULT_BIOS_TYPE_FOR_X86_ONLY);
         }
 
diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java
index 05b5a87..b131326 100644
--- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java
+++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java
@@ -1339,7 +1339,8 @@ public class UpdateVmCommand<T extends VmManagementParametersBase> extends VmMan
                 && vmFromParams.getCustomBiosType() != BiosType.CLUSTER_DEFAULT
                 && vmFromParams.getCustomBiosType() != BiosType.I440FX_SEA_BIOS
                 && getCluster().getArchitecture() != ArchitectureType.undefined
-                && getCluster().getArchitecture().getFamily() != ArchitectureType.x86) {
+                && getCluster().getArchitecture().getFamily() != ArchitectureType.x86
+                && getCluster().getArchitecture().getFamily() != ArchitectureType.aarch64) {
             return failValidation(EngineMessage.NON_DEFAULT_BIOS_TYPE_FOR_X86_ONLY);
         }
 
diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/architecture/HasMaximumNumberOfDisks.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/architecture/HasMaximumNumberOfDisks.java
index fd0afd7..9812295 100644
--- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/architecture/HasMaximumNumberOfDisks.java
+++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/architecture/HasMaximumNumberOfDisks.java
@@ -38,6 +38,11 @@ public class HasMaximumNumberOfDisks implements ArchCommand {
         hasMaximum = VmCommand.MAX_VIRTIO_CCW_DISKS == countDisks(DiskInterface.VirtIO);
     }
 
+    @Override
+    public void runForAarch64() {
+        hasMaximum = VmCommand.MAX_VIRTIO_CCW_DISKS == countDisks(DiskInterface.VirtIO);
+    }
+
     public boolean returnValue() {
         return hasMaximum;
     }
diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/cluster/KubevirtProviderProxy.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/cluster/KubevirtProviderProxy.java
index 7f048b4..1773be7 100644
--- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/cluster/KubevirtProviderProxy.java
+++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/provider/cluster/KubevirtProviderProxy.java
@@ -173,8 +173,10 @@ public class KubevirtProviderProxy implements ProviderProxy<ProviderValidator<Ku
         cluster.setStoragePoolId(findOrCreateKubevirtDataCenterId());
         cluster.setDescription(provider.getDescription());
         cluster.setCompatibilityVersion(Version.getLast());
-        cluster.setArchitecture(ArchitectureType.x86_64);
-        cluster.setCpuName("Intel Nehalem Family");
+        cluster.setArchitecture(ArchitectureType.aarch64);
+        cluster.setCpuName("Kunpeng 920");
+//        cluster.setArchitecture(ArchitectureType.x86_64);
+//        cluster.setCpuName("Intel Nehalem Family");
         cluster.setId(provider.getId());
         cluster.setManaged(false);
         FencingPolicy fencingPolicy = new FencingPolicy();
diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/ClusterValidator.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/ClusterValidator.java
index b38e073..9e13a3d 100644
--- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/ClusterValidator.java
+++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/ClusterValidator.java
@@ -462,7 +462,8 @@ public class ClusterValidator {
                     && eCluster.getBiosType() != null
                     && eCluster.getBiosType() != BiosType.CLUSTER_DEFAULT
                     && eCluster.getBiosType() != BiosType.I440FX_SEA_BIOS
-                    && architecture.getFamily() != ArchitectureType.x86);
+                    && architecture.getFamily() != ArchitectureType.x86
+                    && architecture.getFamily() != ArchitectureType.aarch64);
     }
 
     private boolean attestationServerEnabled() {
diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ArchitectureType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ArchitectureType.java
index bea8567..1168b43 100644
--- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ArchitectureType.java
+++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ArchitectureType.java
@@ -14,6 +14,8 @@ public enum ArchitectureType implements Identifiable {
     ppc(3),
     /* Host & Guest architecture */
     s390x(7),
+    /* Host & Guest architecture */
+    aarch64(8),
 
     // Specific architectures
     /* Host & Guest architecture */
@@ -27,6 +29,7 @@ public enum ArchitectureType implements Identifiable {
 
     public static final int HOTPLUG_MEMORY_FACTOR_PPC_MB = 256;
     public static final int HOTPLUG_MEMORY_FACTOR_X86_MB = 128;
+    public static final int HOTPLUG_MEMORY_FACTOR_AARCH64_MB = 128;
     private int value;
     private int family;
     private static final Map<Integer, ArchitectureType> valueToArchitecture =
@@ -64,6 +67,8 @@ public enum ArchitectureType implements Identifiable {
                 return HOTPLUG_MEMORY_FACTOR_X86_MB;
             case ppc:
                 return HOTPLUG_MEMORY_FACTOR_PPC_MB;
+            case aarch64:
+                return HOTPLUG_MEMORY_FACTOR_AARCH64_MB;
             default:
                 return getFamily().getHotplugMemorySizeFactorMb();
         }
diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/BiosType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/BiosType.java
index a72352c..bd696dd 100644
--- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/BiosType.java
+++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/BiosType.java
@@ -20,7 +20,8 @@ public enum BiosType implements Identifiable {
     I440FX_SEA_BIOS(1, ChipsetType.I440FX, false),
     Q35_SEA_BIOS(2, ChipsetType.Q35, false),
     Q35_OVMF(3, ChipsetType.Q35, true),
-    Q35_SECURE_BOOT(4, ChipsetType.Q35, true);
+    Q35_SECURE_BOOT(4, ChipsetType.Q35, true),
+    VIRT_OVMF(5, ChipsetType.VIRT, true);
 
     private int value;
     private ChipsetType chipsetType;
diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ChipsetType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ChipsetType.java
index 26588ba..7b77fe0 100644
--- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ChipsetType.java
+++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/ChipsetType.java
@@ -3,7 +3,8 @@ package org.ovirt.engine.core.common.businessentities;
 public enum ChipsetType {
 
     I440FX("i440fx"),
-    Q35("q35");
+    Q35("q35"),
+    VIRT("virt");
 
     private String chipsetName;
 
diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
index 6de8d47..19f2e91 100644
--- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
+++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
@@ -1431,6 +1431,9 @@ public enum ConfigValues {
     @TypeConverterAttribute(Integer.class)
     VMPpc64BitMaxMemorySizeInMB(ClientAccessLevel.User),
 
+    @TypeConverterAttribute(Integer.class)
+    VMAarch64BitMaxMemorySizeInMB(ClientAccessLevel.User),
+
     @TypeConverterAttribute(Boolean.class)
     AutoImportHostedEngine,
 
diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/osinfo/OsRepository.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/osinfo/OsRepository.java
index 523df02..63605f2 100644
--- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/osinfo/OsRepository.java
+++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/osinfo/OsRepository.java
@@ -22,6 +22,7 @@ public interface OsRepository {
     int DEFAULT_X86_OS = 0;
     int DEFAULT_PPC_OS = 1001;
     int DEFAULT_S390_OS = 2001;
+    int DEFAULT_AARCH64_OS = 3001;
 
     /*
      * This value is used to enable the auto selection of an appropriate OS when
diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/CpuVendor.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/CpuVendor.java
index 66bde41..09909ff 100644
--- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/CpuVendor.java
+++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/CpuVendor.java
@@ -8,7 +8,8 @@ public enum CpuVendor implements Serializable {
     INTEL("vmx"),
     AMD("svm"),
     IBM("powernv"),
-    IBMS390("sie");
+    IBMS390("sie"),
+    KUNPENG("asimd");
 
     private final String flag;
 
diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmCommonUtils.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmCommonUtils.java
index 34d5168..cc73d5c 100644
--- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmCommonUtils.java
+++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmCommonUtils.java
@@ -78,9 +78,11 @@ public class VmCommonUtils {
     private static ConfigValues getMaxMemConfigValueByOsId(int osId) {
          OsRepository osRepository = SimpleDependencyInjector.getInstance().get(OsRepository.class);
          return osRepository.get64bitOss().contains(osId)
-                 ? (osRepository.getOsArchitectures().get(osId).getFamily() == ArchitectureType.ppc
+                ? ((osRepository.getOsArchitectures().get(osId).getFamily() == ArchitectureType.aarch64)
+                        ? ConfigValues.VMAarch64BitMaxMemorySizeInMB
+                         : (osRepository.getOsArchitectures().get(osId).getFamily() == ArchitectureType.ppc
                         ? ConfigValues.VMPpc64BitMaxMemorySizeInMB
-                        : ConfigValues.VM64BitMaxMemorySizeInMB)
+                        : ConfigValues.VM64BitMaxMemorySizeInMB))
                  : ConfigValues.VM32BitMaxMemorySizeInMB;
      }
 
diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmCpuCountHelper.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmCpuCountHelper.java
index ca1f77d..97c375b 100644
--- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmCpuCountHelper.java
+++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmCpuCountHelper.java
@@ -25,7 +25,7 @@ public class VmCpuCountHelper {
 
     static Integer calcMaxVCpu(ArchitectureType architecture, Integer maxSockets, Integer maxVCpus,
                                       int threadsPerCore, int cpuPerSocket) {
-        if (architecture == null || architecture == ArchitectureType.x86) {
+        if (architecture == null || architecture == ArchitectureType.x86 || architecture == ArchitectureType.aarch64) {
             // As described in https://bugzilla.redhat.com/1406243#c13, the
             // maximum number of vCPUs is limited by thread and core numbers on
             // x86, to fit into an 8-bit APIC ID value organized by certain
@@ -114,7 +114,7 @@ public class VmCpuCountHelper {
      */
     public static boolean validateCpuCounts(VM vm) {
         ArchitectureType architecture = architectureFamily(vm);
-        if (architecture == null || architecture == ArchitectureType.x86) {
+        if (architecture == null || architecture == ArchitectureType.x86 || architecture == ArchitectureType.aarch64) {
             return bitWidth(vm.getThreadsPerCpu()) + bitWidth(vm.getCpuPerSocket()) <= maxBitWidth;
         }
         return true;
diff --git a/backend/manager/modules/restapi/jaxrs/src/main/resources/v3/capabilities.xml b/backend/manager/modules/restapi/jaxrs/src/main/resources/v3/capabilities.xml
index 0501810..1dffa6c 100644
--- a/backend/manager/modules/restapi/jaxrs/src/main/resources/v3/capabilities.xml
+++ b/backend/manager/modules/restapi/jaxrs/src/main/resources/v3/capabilities.xml
@@ -366,6 +366,10 @@
                 <level>3</level>
                 <architecture>PPC64</architecture>
             </cpu>
+            <cpu id="Kunpeng 920">
+                <level>3</level>
+                <architecture>AARCH64</architecture>
+            </cpu>
         </cpus>
         <power_managers>
             <power_management type="apc">
@@ -545,6 +549,7 @@
             <os_type>ubuntu_13_04</os_type>
             <os_type>ubuntu_12_10</os_type>
             <os_type>windows_7x64</os_type>
+            <os_type>other_aarch64</os_type>
         </os_types>
         <disk_formats>
             <disk_format>cow</disk_format>
@@ -1237,18 +1242,21 @@
                 <architectures>undefined</architectures>
                 <architectures>x86_64</architectures>
                 <architectures>ppc64</architectures>
+                <architectures>aarch64</architectures>
             </architecture_capability>
             <architecture_capability>
                 <name>memory snapshot</name>
                 <architectures>undefined</architectures>
                 <architectures>x86_64</architectures>
                 <architectures>ppc64</architectures>
+                <architectures>aarch64</architectures>
             </architecture_capability>
             <architecture_capability>
                 <name>suspend</name>
                 <architectures>undefined</architectures>
                 <architectures>x86_64</architectures>
                 <architectures>ppc64</architectures>
+                <architectures>aarch64</architectures>
             </architecture_capability>
         </architecture_capabilities>
         <serial_number_policies>
diff --git a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/CPUMapper.java b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/CPUMapper.java
index 422595f..ce33104 100644
--- a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/CPUMapper.java
+++ b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/CPUMapper.java
@@ -32,6 +32,8 @@ public class CPUMapper {
                 return ArchitectureType.ppc64;
             case S390X:
                 return ArchitectureType.s390x;
+            case AARCH64:
+                return ArchitectureType.aarch64;
             default:
                 return null;
             }
@@ -52,6 +54,8 @@ public class CPUMapper {
                 return Architecture.PPC64;
             case s390x:
                 return Architecture.S390X;
+            case aarch64:
+                return Architecture.AARCH64;
             default:
                 return null;
             }
diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/OsRepositoryImpl.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/OsRepositoryImpl.java
index 251ff83..956fc6c 100644
--- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/OsRepositoryImpl.java
+++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/OsRepositoryImpl.java
@@ -49,12 +49,13 @@ public enum OsRepositoryImpl implements OsRepository {
      */
     private Map<Integer, String> idToUnameLookup;
     private Map<String, Integer> backwardCompatibleNamesToIds;
-    private static Map<ArchitectureType, Integer> defaultOsMap = new HashMap<>(3);
+    private static Map<ArchitectureType, Integer> defaultOsMap = new HashMap<>(4);
 
     static {
         defaultOsMap.put(ArchitectureType.x86_64, DEFAULT_X86_OS);
         defaultOsMap.put(ArchitectureType.ppc64, DEFAULT_PPC_OS);
         defaultOsMap.put(ArchitectureType.s390x, DEFAULT_S390_OS);
+        defaultOsMap.put(ArchitectureType.aarch64, DEFAULT_AARCH64_OS);
     }
 
     public void init(MapBackedPreferences preferences) {
diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/OvfUtils.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/OvfUtils.java
index b960cb9..cda5a53 100644
--- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/OvfUtils.java
+++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/OvfUtils.java
@@ -300,7 +300,8 @@ public class OvfUtils {
                 String value = section.attributes.get("xsi:type").getValue();
 
                 if (value.equals("ovf:OperatingSystemSection_Type")) {
-                    selectedSection = section;
+                    XmlNode nodeDescription = section.selectSingleNode("Description");
+                    selectedSection = nodeDescription;
                     break;
                 }
             }
diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/Aarch64Strategy.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/Aarch64Strategy.java
new file mode 100644
index 0000000..33dabb1
--- /dev/null
+++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/Aarch64Strategy.java
@@ -0,0 +1,18 @@
+package org.ovirt.engine.core.utils.archstrategy;
+
+import org.ovirt.engine.core.common.businessentities.ArchitectureType;
+
+public class Aarch64Strategy implements ArchStrategy {
+
+    @Override
+    public ArchitectureType getArchitecture() {
+        return ArchitectureType.aarch64;
+    }
+
+    @Override
+    public <T extends ArchCommand> T run(T c) {
+        c.runForAarch64();
+        return c;
+    }
+
+}
diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/ArchCommand.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/ArchCommand.java
index c35bb52..4f1cdda 100644
--- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/ArchCommand.java
+++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/ArchCommand.java
@@ -6,4 +6,6 @@ public interface ArchCommand {
     void runForPPC64();
 
     void runForS390X();
+
+    void runForAarch64();
 }
diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/ArchStrategyFactory.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/ArchStrategyFactory.java
index eddd753..d5ae95b 100644
--- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/ArchStrategyFactory.java
+++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/archstrategy/ArchStrategyFactory.java
@@ -13,6 +13,7 @@ public class ArchStrategyFactory {
         architectureArchStrategyMap.put(ArchitectureType.x86_64, new X86_64Strategy());
         architectureArchStrategyMap.put(ArchitectureType.ppc64, new PPC64Strategy());
         architectureArchStrategyMap.put(ArchitectureType.s390x, new S390XStrategy());
+        architectureArchStrategyMap.put(ArchitectureType.aarch64, new Aarch64Strategy());
     }
 
     public static ArchStrategy getStrategy(ArchitectureType architecture) {
diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfOvaWriter.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfOvaWriter.java
index c0ae977..0f15f69 100644
--- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfOvaWriter.java
+++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfOvaWriter.java
@@ -164,6 +164,7 @@ public abstract class OvfOvaWriter extends OvfWriter {
             return 80; // RHEL x64
         case 1001:
         case 2001:
+        case 3001:
         default:
             return 1; // Other
         }
diff --git a/backend/manager/modules/utils/src/main/javacc/org/ovirt/engine/core/utils/osinfo/osinfo.jj b/backend/manager/modules/utils/src/main/javacc/org/ovirt/engine/core/utils/osinfo/osinfo.jj
index ca11993..55a66ca 100644
--- a/backend/manager/modules/utils/src/main/javacc/org/ovirt/engine/core/utils/osinfo/osinfo.jj
+++ b/backend/manager/modules/utils/src/main/javacc/org/ovirt/engine/core/utils/osinfo/osinfo.jj
@@ -92,7 +92,7 @@ void booleanValue() : {} {
 }
 
 void archValue() : {} {
-    valueSpecifier() ("x86_64" | "ppc64" | "s390x")
+    valueSpecifier() ("x86_64" | "ppc64" | "s390x" | "aarch64")
 }
 
 void busValue() : {} {
@@ -192,7 +192,7 @@ void valueSpecifier() : {} {
     >
 |   < CHIPSET_TYPE
     :
-    ("i440fx" | "q35")
+    ("i440fx" | "q35" | "virt")
     >
 |   < CD_INTERFACE_TYPE
     :
diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/CreateAdditionalControllers.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/CreateAdditionalControllers.java
index e8b49ab..2d4511e 100644
--- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/CreateAdditionalControllers.java
+++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/CreateAdditionalControllers.java
@@ -43,4 +43,9 @@ public class CreateAdditionalControllers implements ArchCommand {
         // For now same as on x86
         runForX86_64();
     }
+    @Override
+    public void runForAarch64() {
+        // For now same as on x86
+        runForX86_64();
+    }
 }
diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/CreateAdditionalControllersForDomainXml.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/CreateAdditionalControllersForDomainXml.java
index 55b73ba..b06514c 100644
--- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/CreateAdditionalControllersForDomainXml.java
+++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/CreateAdditionalControllersForDomainXml.java
@@ -61,4 +61,9 @@ public class CreateAdditionalControllersForDomainXml implements ArchCommand {
         // For now same as on x86
         runForX86_64();
     }
+    @Override
+    public void runForAarch64() {
+        // For now same as on x86
+        runForX86_64();
+    }
 }
diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/GetBootableDiskIndex.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/GetBootableDiskIndex.java
index 7cbaf04..69a6bd3 100644
--- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/GetBootableDiskIndex.java
+++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/GetBootableDiskIndex.java
@@ -36,6 +36,11 @@ public class GetBootableDiskIndex implements ArchCommand {
         diskIndex = 0;
     }
 
+    @Override
+    public void runForAarch64() {
+        diskIndex = 0;
+    }
+
     public int returnValue() {
         return diskIndex;
     }
diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/GetControllerIndices.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/GetControllerIndices.java
index 30c289e..086f2ed 100644
--- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/GetControllerIndices.java
+++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/architecture/GetControllerIndices.java
@@ -35,6 +35,12 @@ public class GetControllerIndices implements ArchCommand {
         runForX86_64();
     }
 
+    @Override
+    public void runForAarch64() {
+        // For now the same as x86
+        runForX86_64();
+    }
+
     public Map<DiskInterface, Integer> returnValue() {
         return controllerIndexMap;
     }
diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/LibvirtVmXmlBuilder.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/LibvirtVmXmlBuilder.java
index 129816c..cbf5c9e 100644
--- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/LibvirtVmXmlBuilder.java
+++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/LibvirtVmXmlBuilder.java
@@ -410,7 +410,7 @@ public class LibvirtVmXmlBuilder {
         writer.writeStartElement("cpu");
 
         String cpuType = vm.getCpuName();
-        if (vm.isUseHostCpuFlags()){
+        if (vm.isUseHostCpuFlags() || vm.getClusterArch().getFamily() == ArchitectureType.aarch64){
             cpuType = "hostPassthrough";
         }
         if (vm.getUseTscFrequency() && tscFrequencySupplier.get() != null) {
@@ -430,6 +430,7 @@ public class LibvirtVmXmlBuilder {
         switch(vm.getClusterArch().getFamily()) {
         case x86:
         case s390x:
+        case aarch64:
             writer.writeAttributeString("match", "exact");
 
             // is this a list of strings??..
@@ -690,13 +691,21 @@ public class LibvirtVmXmlBuilder {
             boolean secureBoot = vm.getEffectiveBiosType() == BiosType.Q35_SECURE_BOOT;
             writer.writeAttributeString("secure", secureBoot ? "yes" : "no");
             writer.writeAttributeString("type", "pflash");
-            writer.writeRaw("/usr/share/OVMF/OVMF_CODE.secboot.fd");
+            if (vm.getClusterArch().getFamily() == ArchitectureType.aarch64) {
+                writer.writeRaw("/usr/share/AAVMF/AAVMF_CODE.fd");
+            } else {
+                writer.writeRaw("/usr/share/OVMF/OVMF_CODE.secboot.fd");
+            }
             writer.writeEndElement();
             writer.writeStartElement("nvram");
             String nvramTemplate = vmCustomProperties.get("nvram_template");
             if (nvramTemplate == null) {
-                nvramTemplate = String.format("/usr/share/OVMF/%s",
+               if(vm.getClusterArch().getFamily() == ArchitectureType.aarch64){
+                   nvramTemplate = "/usr/share/AAVMF/AAVMF_CODE.fd";
+               } else {
+                   nvramTemplate = String.format("/usr/share/OVMF/%s",
                         secureBoot ? "OVMF_VARS.secboot.fd" : "OVMF_VARS.fd");
+               }
             }
             writer.writeAttributeString("template", nvramTemplate);
             writer.writeRaw(String.format("/var/lib/libvirt/qemu/nvram/%s.fd", vm.getId()));
@@ -729,8 +738,12 @@ public class LibvirtVmXmlBuilder {
         //   <timer name="rtc" tickpolicy="catchup">
         // </clock>
         writer.writeStartElement("clock");
-        writer.writeAttributeString("offset", "variable");
-        writer.writeAttributeString("adjustment", String.valueOf(vmInfoBuildUtils.getVmTimeZone(vm)));
+        if (vm.getClusterArch().getFamily() == ArchitectureType.aarch64) {
+            writer.writeAttributeString("offset", "utc");
+        } else {
+            writer.writeAttributeString("offset", "variable");
+            writer.writeAttributeString("adjustment", String.valueOf(vmInfoBuildUtils.getVmTimeZone(vm)));
+        }
 
         if (hypervEnabled) {
             writer.writeStartElement("timer");
@@ -738,16 +751,16 @@ public class LibvirtVmXmlBuilder {
             writer.writeAttributeString("present", "yes");
             writer.writeEndElement();
         }
-
-        writer.writeStartElement("timer");
-        writer.writeAttributeString("name", "rtc");
-        writer.writeAttributeString("tickpolicy", "catchup");
-        writer.writeEndElement();
-
-        writer.writeStartElement("timer");
-        writer.writeAttributeString("name", "pit");
-        writer.writeAttributeString("tickpolicy", "delay");
-        writer.writeEndElement();
+        if(vm.getClusterArch().getFamily() != ArchitectureType.aarch64) {
+            writer.writeStartElement("timer");
+            writer.writeAttributeString("name", "rtc");
+            writer.writeAttributeString("tickpolicy", "catchup");
+            writer.writeEndElement();
+            writer.writeStartElement("timer");
+            writer.writeAttributeString("name", "pit");
+            writer.writeAttributeString("tickpolicy", "delay");
+            writer.writeEndElement();
+        }
 
         if (vm.getClusterArch().getFamily() == ArchitectureType.x86) {
             writer.writeStartElement("timer");
@@ -767,7 +780,8 @@ public class LibvirtVmXmlBuilder {
     }
 
     private void writeFeatures() {
-        if (vm.getClusterArch().getFamily() != ArchitectureType.x86) {
+        if (vm.getClusterArch().getFamily() != ArchitectureType.x86 &&
+            vm.getClusterArch().getFamily() != ArchitectureType.aarch64) {
             return;
         }
 
@@ -782,6 +796,11 @@ public class LibvirtVmXmlBuilder {
 
         if (acpiEnabled) {
             writer.writeElement("acpi");
+            if( vm.getClusterArch().getFamily() == ArchitectureType.aarch64 ) {
+                writer.writeStartElement("gic");
+                writer.writeAttributeString("version", "3");
+            }
+            writer.writeEndElement();
         }
 
         if (hypervEnabled) {
@@ -1037,7 +1056,8 @@ public class LibvirtVmXmlBuilder {
 
         writeGuestAgentChannels();
 
-        if (vm.getClusterArch() == ArchitectureType.ppc64 || vm.getClusterArch() == ArchitectureType.ppc64le) {
+        if (vm.getClusterArch() == ArchitectureType.ppc64 || vm.getClusterArch() == ArchitectureType.ppc64le ||
+            vm.getClusterArch() == ArchitectureType.aarch64) {
             writeEmulator();
         }
 
@@ -1195,8 +1215,9 @@ public class LibvirtVmXmlBuilder {
             writeSpiceVmcChannel();
         }
 
-        if (vm.getClusterArch().getFamily() == ArchitectureType.x86
-                && vm.getEffectiveBiosType().getChipsetType() == ChipsetType.Q35) {
+        if ((vm.getClusterArch().getFamily() == ArchitectureType.x86
+                && vm.getEffectiveBiosType().getChipsetType() == ChipsetType.Q35)
+             || vm.getClusterArch().getFamily() == ArchitectureType.aarch64) {
             writePciEControllers(pciERootExists, pciEPorts);
         }
 
@@ -2853,22 +2874,28 @@ public class LibvirtVmXmlBuilder {
         writer.writeStartElement("video");
 
         writer.writeStartElement("model");
-        if (mdevDisplayOn) {
-            writer.writeAttributeString("type", "none");
-        } else {
-            writer.writeAttributeString("type", device.getDevice());
-            Object vram = device.getSpecParams().get(VdsProperties.VIDEO_VRAM);
-            writer.writeAttributeString("vram", vram != null ? vram.toString() : "32768");
+        if (vm.getClusterArch().getFamily() == ArchitectureType.aarch64) {
+            writer.writeAttributeString("type", "virtio");
             Object heads = device.getSpecParams().get(VdsProperties.VIDEO_HEADS);
             writer.writeAttributeString("heads", heads != null ? heads.toString() : "1");
-            if (device.getSpecParams().containsKey(VdsProperties.VIDEO_RAM)) {
-                writer.writeAttributeString("ram", device.getSpecParams().get(VdsProperties.VIDEO_RAM).toString());
-            }
-            if (device.getSpecParams().containsKey(VdsProperties.VIDEO_VGAMEM)) {
-                writer.writeAttributeString("vgamem", device.getSpecParams().get(VdsProperties.VIDEO_VGAMEM).toString());
-            }
-        }
-
+            writer.writeAttributeString("primary", "yes");
+        } else {
+            if (mdevDisplayOn) {
+                writer.writeAttributeString("type", "none");
+            } else {
+                writer.writeAttributeString("type", device.getDevice());
+                Object vram = device.getSpecParams().get(VdsProperties.VIDEO_VRAM);
+                writer.writeAttributeString("vram", vram != null ? vram.toString() : "32768");
+                Object heads = device.getSpecParams().get(VdsProperties.VIDEO_HEADS);
+                writer.writeAttributeString("heads", heads != null ? heads.toString() : "1");
+                if (device.getSpecParams().containsKey(VdsProperties.VIDEO_RAM)) {
+                    writer.writeAttributeString("ram", device.getSpecParams().get(VdsProperties.VIDEO_RAM).toString());
+                }
+                if (device.getSpecParams().containsKey(VdsProperties.VIDEO_VGAMEM)) {
+                    writer.writeAttributeString("vgamem", device.getSpecParams().get(VdsProperties.VIDEO_VGAMEM).toString());
+                }
+             }
+        }
         writer.writeEndElement();
         writeAlias(device);
         writeAddress(device);
@@ -2922,14 +2949,26 @@ public class LibvirtVmXmlBuilder {
     private void writeInput() {
         writer.writeStartElement("input");
 
-        if (vmInfoBuildUtils.isTabletEnabled(vm)) {
+        if (vm.getClusterArch().getFamily() == ArchitectureType.aarch64) {
             writer.writeAttributeString("type", "tablet");
             writer.writeAttributeString("bus", "usb");
         } else {
-            writer.writeAttributeString("type", "mouse");
-            writer.writeAttributeString("bus", vm.getClusterArch().getFamily() == ArchitectureType.x86 ? "ps2" :"usb");
+            if (vmInfoBuildUtils.isTabletEnabled(vm)) {
+                writer.writeAttributeString("type", "tablet");
+                writer.writeAttributeString("bus", "usb");
+            } else {
+                writer.writeAttributeString("type", "mouse");
+                writer.writeAttributeString("bus", vm.getClusterArch().getFamily() == ArchitectureType.x86 ? "ps2" :"usb");
+            }
         }
 
         writer.writeEndElement();
+
+        if (vm.getClusterArch().getFamily() == ArchitectureType.aarch64){
+            writer.writeStartElement("input");
+            writer.writeAttributeString("type", "keyboard");
+            writer.writeAttributeString("bus", "usb");
+            writer.writeEndElement();
+        }
     }
 }
diff --git a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/VmInfoBuildUtils.java b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/VmInfoBuildUtils.java
index 0a1c245..8d3315c 100644
--- a/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/VmInfoBuildUtils.java
+++ b/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/VmInfoBuildUtils.java
@@ -861,6 +861,8 @@ public class VmInfoBuildUtils {
         case ppc64:
         case ppc64le:
             return "pseries";
+        case aarch64:
+            return "";
         case x86_64:
         default:
             return "pc";
diff --git a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
index b0413dd..1ad5f14 100644
--- a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
+++ b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/dataprovider/AsyncDataProvider.java
@@ -1180,14 +1180,19 @@ public class AsyncDataProvider {
                 (Integer) getConfigValuePreConverted(ConfigValues.VM64BitMaxMemorySizeInMB, version);
         final int ppc64MaxMaxMemory =
                 (Integer) getConfigValuePreConverted(ConfigValues.VMPpc64BitMaxMemorySizeInMB, version);
-        return Math.max(Math.max(x86_32MaxMaxMemory, x86_64MaxMaxMemory), ppc64MaxMaxMemory);
+        final int aarch64MaxMaxMemory =
+                (Integer) getConfigValuePreConverted(ConfigValues.VMAarch64BitMaxMemorySizeInMB, version);
+        return Math.max(Math.max(Math.max(x86_32MaxMaxMemory, x86_64MaxMaxMemory), ppc64MaxMaxMemory), aarch64MaxMaxMemory);
     }
 
     private ConfigValues getMaxMaxMemoryConfigValue(int osId) {
         return oses64bit.contains(osId)
-                ? (osArchitectures.get(osId).getFamily() == ArchitectureType.ppc
+                //? (osArchitectures.get(osId).getFamily() == ArchitectureType.ppc
+                ? ((osArchitectures.get(osId).getFamily() == ArchitectureType.aarch64)
+                    ? ConfigValues.VMAarch64BitMaxMemorySizeInMB
+                    : (osArchitectures.get(osId).getFamily() == ArchitectureType.ppc
                         ? ConfigValues.VMPpc64BitMaxMemorySizeInMB
-                        : ConfigValues.VM64BitMaxMemorySizeInMB)
+                        : ConfigValues.VM64BitMaxMemorySizeInMB))
                 : ConfigValues.VM32BitMaxMemorySizeInMB;
     }
 
diff --git a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/HostModel.java b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/HostModel.java
index 6e6158a..bf9e8b3 100644
--- a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/HostModel.java
+++ b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/hosts/HostModel.java
@@ -1355,6 +1355,7 @@ public abstract class HostModel extends Model implements HasValidatedTabs {
             case INTEL:
             case AMD:
             case IBMS390:
+            case KUNPENG:
                 resetKernelCmdlineCheckboxesValue();
                 break;
             case IBM:
@@ -1375,6 +1376,7 @@ public abstract class HostModel extends Model implements HasValidatedTabs {
             case INTEL:
             case AMD:
             case IBMS390:
+            case KUNPENG:
                 setKernelCmdlineCheckboxesChangeability(
                         isKernelCmdlineParsable(),
                         constants.kernelCmdlineCheckboxesAndDirectCustomizationNotAllowed());
diff --git a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/ImportVmFromOvaModel.java b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/ImportVmFromOvaModel.java
index dff9b7e..8451e9e 100644
--- a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/ImportVmFromOvaModel.java
+++ b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/ImportVmFromOvaModel.java
@@ -38,7 +38,7 @@ public class ImportVmFromOvaModel extends ImportVmFromExternalProviderModel {
 
     @Override
     protected void setTargetArchitecture(List<VM> externalVms) {
-        setTargetArchitecture(ArchitectureType.x86_64);
+        setTargetArchitecture(ArchitectureType.aarch64);
     }
 
     public void setIsoName(String ovaPath) {
diff --git a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/ClusterAdditionalStatusColumn.java b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/ClusterAdditionalStatusColumn.java
index 9ac4b68..aa9037c 100644
--- a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/ClusterAdditionalStatusColumn.java
+++ b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/widget/table/column/ClusterAdditionalStatusColumn.java
@@ -29,7 +29,8 @@ public class ClusterAdditionalStatusColumn extends EntityAdditionalStatusColumn<
                                                       "Intel Broadwell IBRS Family", //$NON-NLS-1$
                                                       "Intel Skylake Client IBRS Family", //$NON-NLS-1$
                                                       "Intel Skylake Server IBRS Family", //$NON-NLS-1$
-                                                      "AMD EPYC IBPB"}; //$NON-NLS-1$
+                                                      "AMD EPYC IBPB", //$NON-NLS-1$
+                                                      "Kunpeng 920"}; //$NON-NLS-1$
     private static final String[] versions = new String[]{"4.2",  //$NON-NLS-1$
                                                           "4.1",  //$NON-NLS-1$
                                                           "4.0",  //$NON-NLS-1$

diff --git a/packaging/conf/osinfo-defaults.properties b/packaging/conf/osinfo-defaults.properties
index d9d5ce4..307c188 100644
--- a/packaging/conf/osinfo-defaults.properties
+++ b/packaging/conf/osinfo-defaults.properties
@@ -497,6 +497,25 @@ os.ubuntu_16_04_s390x.id.value = 2005
 os.ubuntu_16_04_s390x.name.value = Ubuntu Xenial Xerus LTS+
 os.ubuntu_16_04_s390x.derivedFrom.value = other_linux_s390x
 
+# centos arm architecture
+os.other_aarch64.id.value = 3001
+os.other_aarch64.name.value = Other OS
+os.other_aarch64.derivedFrom.value = other
+os.other_aarch64.cpuArchitecture.value = aarch64
+os.other_aarch64.cpu.hotplugSupport.value = true
+os.other_aarch64.cpu.hotunplugSupport.value = true
+os.other_aarch64.devices.audio.enabled.value = false
+os.other_aarch64.devices.network.value = pv
+os.other_aarch64.devices.cdInterface.value = scsi
+os.other_aarch64.devices.balloon.enabled.value = true
+os.other_aarch64.devices.diskInterfaces.value = VirtIO, VirtIO_SCSI
+os.other_aarch64.devices.disk.hotpluggableInterfaces.value = VirtIO, VirtIO_SCSI
+os.other_aarch64.devices.network.hotplugSupport.value = true
+os.other_aarch64.devices.floppy.support.value = false
+os.other_aarch64.devices.watchdog.models.value = i6300esb
+os.other_aarch64.devices.usb.controller.value = qemu-xhci
+os.other_aarch64.devices.console.target.type.value = sclp
+
 # Backward Compatibility Section
 # Keep a mapping of the old os unique names to new od IDs
 # in order to support correct imports of pre-osinfo VMs
diff --git a/packaging/dbscripts/upgrade/04_02_0590_remove_general_version_of_nongeneral_vdc_options.sql b/packaging/dbscripts/upgrade/04_02_0590_remove_general_version_of_nongeneral_vdc_options.sql
index 0fe77ee..8836bfd 100644
--- a/packaging/dbscripts/upgrade/04_02_0590_remove_general_version_of_nongeneral_vdc_options.sql
+++ b/packaging/dbscripts/upgrade/04_02_0590_remove_general_version_of_nongeneral_vdc_options.sql
@@ -3,3 +3,4 @@ SELECT fn_db_delete_config_value('IsMigrationSupported', 'general');
 SELECT fn_db_delete_config_value('IsSuspendSupported', 'general');
 SELECT fn_db_delete_config_value('VM32BitMaxMemorySizeInMB', 'general');
 SELECT fn_db_delete_config_value('VMPpc64BitMaxMemorySizeInMB', 'general');
+SELECT fn_db_delete_config_value('VMAarch64BitMaxMemorySizeInMB', 'general');
diff --git a/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql b/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql
index 71f266b..f50171b 100644
--- a/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql
+++ b/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql
@@ -173,23 +173,23 @@ select fn_db_add_config_value('HighUtilizationForEvenlyDistribute','75','general
 select fn_db_add_config_value('HighUtilizationForPowerSave','75','general');
 select fn_db_add_config_value('HostPreparingForMaintenanceIdleTime', '300', 'general');
 select fn_db_add_config_value('HostTimeDriftInSec','300','general');
-select fn_db_add_config_value_for_versions_up_to('HotPlugCpuSupported','{"x86":"true","ppc":"true","s390x":"true"}', '4.5');
-select fn_db_add_config_value_for_versions_up_to('HotUnplugCpuSupported', '{"x86":"true","ppc":"true","s390x":"false"}', '4.5');
-select fn_db_add_config_value_for_versions_up_to('HotPlugMemorySupported', '{"x86":"true","ppc":"true","s390x":"false"}', '4.5');
+select fn_db_add_config_value_for_versions_up_to('HotPlugCpuSupported','{"x86":"true","ppc":"true","s390x":"true","aarch64":"true"}', '4.5');
+select fn_db_add_config_value_for_versions_up_to('HotUnplugCpuSupported', '{"x86":"true","ppc":"true","s390x":"false","aarch64":"true"}', '4.5');
+select fn_db_add_config_value_for_versions_up_to('HotPlugMemorySupported', '{"x86":"true","ppc":"true","s390x":"false","aarch64":"true"}', '4.5');
 select fn_db_add_config_value('MaxMemorySlots','16','general');
 select fn_db_add_config_value('HotPlugMemoryMultiplicationSizeMb','256','general');
-select fn_db_add_config_value_for_versions_up_to('HotUnplugMemorySupported', '{"x86":"true","ppc":"true","s390x":"false"}', '4.5');
+select fn_db_add_config_value_for_versions_up_to('HotUnplugMemorySupported', '{"x86":"true","ppc":"true","s390x":"false","aarch64":"true"}', '4.5');
 select fn_db_add_config_value_for_versions_up_to('CopyPreallocatedFileBasedDiskSupported', 'false', '4.2');
 select fn_db_add_config_value_for_versions_up_to('CopyPreallocatedFileBasedDiskSupported', 'true', '4.5');
 select fn_db_add_config_value_for_versions_up_to('ManagedBlockDomainSupported', 'false', '4.2');
 select fn_db_add_config_value_for_versions_up_to('ManagedBlockDomainSupported', 'false', '4.5');
 
 -- migration support per architecture
-select fn_db_add_config_value_for_versions_up_to('IsMigrationSupported','{"undefined": "true", "x86": "true", "ppc" : "true", "s390x" : "true"}','4.5');
+select fn_db_add_config_value_for_versions_up_to('IsMigrationSupported','{"undefined": "true", "x86": "true", "ppc" : "true", "s390x" : "true", "aarch64": "true"}','4.5');
 -- snapshot support per architecture
-select fn_db_add_config_value_for_versions_up_to('IsMemorySnapshotSupported','{"undefined": "true", "x86": "true", "ppc" : "true", "s390x" : "true"}','4.5');
+select fn_db_add_config_value_for_versions_up_to('IsMemorySnapshotSupported','{"undefined": "true", "x86": "true", "ppc" : "true", "s390x" : "true", "aarch64": "true"}','4.5');
 -- suspend support per architecture
-select fn_db_add_config_value_for_versions_up_to('IsSuspendSupported','{"undefined": "true", "x86": "true", "ppc" : "true", "s390x" : "true"}','4.5');
+select fn_db_add_config_value_for_versions_up_to('IsSuspendSupported','{"undefined": "true", "x86": "true", "ppc" : "true", "s390x" : "true", "aarch64": "true"}','4.5');
 select fn_db_add_config_value('OsRepositoryConfDir','/osinfo.conf.d','general');
 select fn_db_add_config_value('IterationsWithBalloonProblem','3','general');
 select fn_db_add_config_value('DefaultSysprepLocale','en_US','general');
@@ -464,7 +464,8 @@ select fn_db_add_config_value('ServerCPUList',
         || '1:IBM z114, z196:sie,model_z196-base:z196-base:s390x; '
         || '2:IBM zBC12, zEC12:sie,model_zEC12-base:zEC12-base:s390x; '
         || '3:IBM z13s, z13:sie,model_z13-base:z13-base:s390x; '
-        || '4:IBM z14:sie,model_z14-base:z14-base:s390x;',
+        || '4:IBM z14:sie,model_z14-base:z14-base:s390x;'
+        || '1:Kunpeng 920:asimd:asimd:aarch64;',
     '4.4');
 
 select fn_db_add_config_value('ServerCPUList',
@@ -578,6 +579,7 @@ select fn_db_add_config_value_for_versions_up_to('VM32BitMaxMemorySizeInMB','204
 select fn_db_add_config_value_for_versions_up_to('VM64BitMaxMemorySizeInMB','6291456','4.5');
 select fn_db_add_config_value_for_versions_up_to('VMPpc64BitMaxMemorySizeInMB', '1048576', '4.3');
 select fn_db_add_config_value_for_versions_up_to('VMPpc64BitMaxMemorySizeInMB', '6291456', '4.5');
+select fn_db_add_config_value_for_versions_up_to('VMAarch64BitMaxMemorySizeInMB', '1048576', '4.4');
 select fn_db_add_config_value('VmGracefulShutdownMessage','System Administrator has initiated shutdown of this Virtual Machine. Virtual Machine is shutting down.','general');
 select fn_db_add_config_value('VmGracefulShutdownTimeout','30','general');
 --Number of subsequent failures in VM creation in a pool before giving up and stop creating new VMs
@@ -1121,7 +1123,8 @@ select fn_db_update_config_value('ServerCPUList',
         || '1:IBM z114, z196:sie,model_z196-base:z196-base:s390x; '
         || '2:IBM zBC12, zEC12:sie,model_zEC12-base:zEC12-base:s390x; '
         || '3:IBM z13s, z13:sie,model_z13-base:z13-base:s390x; '
-        || '4:IBM z14:sie,model_z14-base:z14-base:s390x;',
+        || '4:IBM z14:sie,model_z14-base:z14-base:s390x;'
+        || '1:Kunpeng 920:asimd:asimd:aarch64;',
     '4.4');
 select fn_db_update_config_value('ServerCPUList',
     '1:Intel Nehalem Family:vmx,nx,model_Nehalem:Nehalem:x86_64; '
diff --git a/packaging/setup/ovirt_engine_setup/engine_common/constants.py b/packaging/setup/ovirt_engine_setup/engine_common/constants.py
index 98c0688..13b0485 100644
--- a/packaging/setup/ovirt_engine_setup/engine_common/constants.py
+++ b/packaging/setup/ovirt_engine_setup/engine_common/constants.py
@@ -95,6 +95,7 @@ class Defaults(object):
             'x86_64': 68719476736,
             'i686': 4294967295,
             'ppc64':  137438953472,
+            'aarch64': 137438953472,
             'default': 4294967295,
         }
         return SHMMAX.get(platform.machine(), SHMMAX['default'])
-- 
2.27.0

