Hello Shmuel Melamud,

I'd like you to do a code review.  Please visit

    https://gerrit.ovirt.org/41620

to review the following change.

Change subject: core: VmDeviceUtils refactoring
......................................................................

core: VmDeviceUtils refactoring

* Extracted common actions performed on a device into separate methods;
* Unified naming scheme applied to all methods related to the same
  device and all similar methods across the devices;
* Reordered methods to group related methods together.
* Given more meaningful names to some methods;
* Given meaningful names to methods' parameters and local variables;
* Simplified parameter lists of some methods;
* Removed redundant comments, corrected spelling in others and added doc
  comments to methods.

Change-Id: Iffa1ae3176b4082ef3b96277f6ea351e82f3e613
Signed-off-by: Shmuel Melamud <smela...@redhat.com>
---
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVmCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVmTemplateCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AttachDiskToVmCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ChangeVmClusterValidator.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportRepoImageCopyTaskHandler.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/RunVmCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmTemplateCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmManagementCommandBase.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/template/AddVmTemplateInterfaceCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/template/UpdateVmTemplateInterfaceCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AbstractVmInterfaceCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/ActivateDeactivateVmNicCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AddVmInterfaceCommand.java
D 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/smartcard/SmartcardSpecParams.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/storage/DiskValidator.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmDeviceCommonUtils.java
M 
frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/instancetypes/InstanceTypeManager.java
25 files changed, 1,624 insertions(+), 1,082 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/20/41620/1

diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java
index cbc7448..752597b 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java
@@ -131,15 +131,15 @@
     }
 
     protected boolean isVirtioScsiControllerAttached(Guid vmId) {
-        return VmDeviceUtils.isVirtioScsiControllerAttached(vmId);
+        return VmDeviceUtils.hasVirtioScsiController(vmId);
     }
 
     protected boolean isBalloonEnabled(Guid vmId) {
-        return VmDeviceUtils.isBalloonEnabled(vmId);
+        return VmDeviceUtils.hasMemoryBalloon(vmId);
     }
 
     protected boolean isSoundDeviceEnabled(Guid vmId) {
-        return VmDeviceUtils.isSoundDeviceEnabled(vmId);
+        return VmDeviceUtils.hasSoundDevice(vmId);
     }
 
     protected boolean hasWatchdog(Guid vmId) {
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java
index 95edd6c..b5def46 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java
@@ -41,8 +41,6 @@
 import org.ovirt.engine.core.common.businessentities.VM;
 import org.ovirt.engine.core.common.businessentities.VMStatus;
 import org.ovirt.engine.core.common.businessentities.VmDevice;
-import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType;
-import org.ovirt.engine.core.common.businessentities.VmDeviceId;
 import org.ovirt.engine.core.common.businessentities.storage.CinderDisk;
 import org.ovirt.engine.core.common.businessentities.storage.Disk;
 import org.ovirt.engine.core.common.businessentities.storage.DiskStorageType;
@@ -57,7 +55,6 @@
 import org.ovirt.engine.core.common.errors.VdcBllMessages;
 import org.ovirt.engine.core.common.locks.LockingGroup;
 import org.ovirt.engine.core.common.utils.Pair;
-import org.ovirt.engine.core.common.utils.VmDeviceType;
 import org.ovirt.engine.core.common.validation.group.UpdateEntity;
 import org.ovirt.engine.core.compat.Guid;
 import org.ovirt.engine.core.dal.dbbroker.DbFacade;
@@ -427,13 +424,11 @@
     }
 
     protected VmDevice addManagedDeviceForDisk(Guid diskId, Boolean 
isUsingScsiReservation) {
-        return VmDeviceUtils.addManagedDevice(new VmDeviceId(diskId, 
getVmId()),
-                VmDeviceGeneralType.DISK,
-                VmDeviceType.DISK,
-                null,
+        return  VmDeviceUtils.addDiskDevice(
+                getVmId(),
+                diskId,
                 shouldDiskBePlugged(),
                 
Boolean.TRUE.equals(getParameters().getDiskInfo().getReadOnly()),
-                null,
                 Boolean.TRUE.equals(isUsingScsiReservation));
     }
 
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 bcb64b7..b0184d2 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
@@ -932,9 +932,7 @@
                     payload.getDeviceType(),
                     payload.getSpecParams(),
                     true,
-                    true,
-                    null,
-                    false);
+                    true);
         }
     }
 
@@ -1438,7 +1436,7 @@
     }
 
     protected boolean isVirtioScsiControllerAttached(Guid vmId) {
-        return VmDeviceUtils.isVirtioScsiControllerAttached(vmId);
+        return VmDeviceUtils.hasVirtioScsiController(vmId);
     }
 
     /**
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVmTemplateCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVmTemplateCommand.java
index 5a527da..855a2aa 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVmTemplateCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddVmTemplateCommand.java
@@ -312,7 +312,7 @@
                             getParameters().isSoundDeviceEnabled(),
                             getParameters().isConsoleEnabled(),
                             getParameters().isVirtioScsiEnabled(),
-                            VmDeviceUtils.isBalloonEnabled(getVmId()),
+                            VmDeviceUtils.hasMemoryBalloon(getVmId()),
                             graphicsToSkip,
                             false);
                 } else {
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AttachDiskToVmCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AttachDiskToVmCommand.java
index e344108..82d4250 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AttachDiskToVmCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AttachDiskToVmCommand.java
@@ -217,7 +217,7 @@
     }
 
     protected void updateBootOrderInVmDevice() {
-        
VmDeviceUtils.updateBootOrderInVmDeviceAndStoreToDB(getVm().getStaticData());
+        VmDeviceUtils.updateBootOrder(getVm().getId());
     }
 
     private void updateDiskVmSnapshotId() {
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ChangeVmClusterValidator.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ChangeVmClusterValidator.java
index fc36910..e89e5d3 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ChangeVmClusterValidator.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ChangeVmClusterValidator.java
@@ -79,7 +79,7 @@
                 return false;
             }
 
-            if (VmDeviceUtils.isVirtioScsiControllerAttached(vm.getId())) {
+            if (VmDeviceUtils.hasVirtioScsiController(vm.getId())) {
                 // Verify cluster compatibility
                 if 
(!FeatureSupported.virtIoScsi(targetCluster.getCompatibilityVersion())) {
                     return 
parentCommand.failCanDoAction(VdcBllMessages.VIRTIO_SCSI_INTERFACE_IS_NOT_AVAILABLE_FOR_CLUSTER_LEVEL);
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java
index 94bf7c4..f65bcb8 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java
@@ -94,7 +94,7 @@
         // update cached image
         VmHandler.updateDisksFromDb(getVm());
         // update vm device boot order
-        
VmDeviceUtils.updateBootOrderInVmDeviceAndStoreToDB(getVm().getStaticData());
+        VmDeviceUtils.updateBootOrder(getVm().getId());
         getVmStaticDAO().incrementDbGeneration(getVm().getId());
         setSucceeded(true);
     }
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java
index 401cd82..72f86c2 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java
@@ -161,7 +161,7 @@
         TransactionSupport.executeInNewTransaction(new 
TransactionMethod<Void>() {
             @Override
             public Void runInTransaction() {
-                
VmDeviceUtils.updateBootOrderInVmDeviceAndStoreToDB(getVm().getStaticData());
+                VmDeviceUtils.updateBootOrder(getVm().getId());
                 return null;
             }
         });
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java
index 71d00e0..e6bdf46 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImagesHandler.java
@@ -25,7 +25,6 @@
 import org.ovirt.engine.core.common.businessentities.StorageDomainStatic;
 import org.ovirt.engine.core.common.businessentities.StorageDomainStatus;
 import org.ovirt.engine.core.common.businessentities.VM;
-import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType;
 import org.ovirt.engine.core.common.businessentities.VmDeviceId;
 import org.ovirt.engine.core.common.businessentities.VmTemplate;
 import 
org.ovirt.engine.core.common.businessentities.network.VmNetworkInterface;
@@ -47,7 +46,6 @@
 import org.ovirt.engine.core.common.errors.VdcBLLException;
 import org.ovirt.engine.core.common.errors.VdcBllErrors;
 import org.ovirt.engine.core.common.errors.VdcBllMessages;
-import org.ovirt.engine.core.common.utils.VmDeviceType;
 import 
org.ovirt.engine.core.common.vdscommands.GetImageInfoVDSCommandParameters;
 import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
 import org.ovirt.engine.core.common.vdscommands.VdsAndPoolIDVDSParametersBase;
@@ -375,14 +373,7 @@
      */
     public static void addDiskToVm(BaseDisk disk, Guid vmId) {
         DbFacade.getInstance().getBaseDiskDao().save(disk);
-        VmDeviceUtils.addManagedDevice(new VmDeviceId(disk.getId(), vmId),
-                VmDeviceGeneralType.DISK,
-                VmDeviceType.DISK,
-                null,
-                true,
-                false,
-                null,
-                false);
+        VmDeviceUtils.addDiskDevice(vmId, disk.getId());
     }
 
     /**
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportRepoImageCopyTaskHandler.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportRepoImageCopyTaskHandler.java
index 15e284c..e8f8042 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportRepoImageCopyTaskHandler.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ImportRepoImageCopyTaskHandler.java
@@ -14,8 +14,6 @@
 import org.ovirt.engine.core.common.businessentities.GraphicsType;
 import org.ovirt.engine.core.common.businessentities.HttpLocationInfo;
 import org.ovirt.engine.core.common.businessentities.VDSGroup;
-import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType;
-import org.ovirt.engine.core.common.businessentities.VmDeviceId;
 import org.ovirt.engine.core.common.businessentities.VmStatic;
 import org.ovirt.engine.core.common.businessentities.VmTemplate;
 import org.ovirt.engine.core.common.businessentities.storage.DiskImage;
@@ -23,7 +21,6 @@
 import org.ovirt.engine.core.common.osinfo.OsRepository;
 import org.ovirt.engine.core.common.utils.Pair;
 import org.ovirt.engine.core.common.utils.SimpleDependecyInjector;
-import org.ovirt.engine.core.common.utils.VmDeviceType;
 import 
org.ovirt.engine.core.common.vdscommands.DownloadImageVDSCommandParameters;
 import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
 import org.ovirt.engine.core.common.vdscommands.VDSParametersBase;
@@ -147,15 +144,7 @@
 
     private void attachDiskToTemplate(Guid templateId) {
         DiskImage templateDiskImage = 
getEnclosingCommand().getParameters().getDiskImage();
-        VmDeviceUtils.addManagedDevice(new 
VmDeviceId(templateDiskImage.getId(),
-                templateId),
-                VmDeviceGeneralType.DISK,
-                VmDeviceType.DISK,
-                null,
-                true,
-                Boolean.FALSE,
-                null,
-                false);
+        VmDeviceUtils.addDiskDevice(templateId, templateDiskImage.getId());
     }
 
     @Override
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 4be4497..7b097a3 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
@@ -704,7 +704,7 @@
 
         // Before running the VM we update its devices, as they may
         // need to be changed due to configuration option change
-        VmDeviceUtils.updateVmDevices(getVm().getStaticData());
+        VmDeviceUtils.updateVmDevicesOnRun(getVm().getStaticData());
 
         getVm().setKvmEnable(getParameters().getKvmEnable());
         getVm().setRunAndPause(getParameters().getRunAndPause() == null ? 
getVm().isRunAndPause() : getParameters().getRunAndPause());
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 dc83d92..c171511 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
@@ -404,9 +404,7 @@
                         payload.getDeviceType(),
                         payload.getSpecParams(),
                         true,
-                        true,
-                        null,
-                        false);
+                        true);
             }
         }
     }
@@ -922,18 +920,18 @@
     }
 
     public boolean isVirtioScsiEnabledForVm(Guid vmId) {
-        return VmDeviceUtils.isVirtioScsiControllerAttached(vmId);
+        return VmDeviceUtils.hasVirtioScsiController(vmId);
     }
 
     protected boolean isBalloonEnabled() {
         Boolean balloonEnabled = getParameters().isBalloonEnabled();
-        return balloonEnabled != null ? balloonEnabled : 
VmDeviceUtils.isBalloonEnabled(getVmId());
+        return balloonEnabled != null ? balloonEnabled : 
VmDeviceUtils.hasMemoryBalloon(getVmId());
     }
 
     protected boolean isSoundDeviceEnabled() {
         Boolean soundDeviceEnabled = getParameters().isSoundDeviceEnabled();
         return soundDeviceEnabled != null ? soundDeviceEnabled :
-                VmDeviceUtils.isSoundDeviceEnabled(getVmId());
+                VmDeviceUtils.hasSoundDevice(getVmId());
     }
 
     protected boolean hasWatchdog() {
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java
index 0244931..b0c905b 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java
@@ -226,10 +226,10 @@
                     vm.getNumOfMonitors(),
                     allVmInterfaces,
                     allVmDisks,
-                    VmDeviceUtils.isVirtioScsiControllerAttached(vm.getId()),
+                    VmDeviceUtils.hasVirtioScsiController(vm.getId()),
                     VmDeviceUtils.hasWatchdog(vm.getId()),
-                    VmDeviceUtils.isBalloonEnabled(vm.getId()),
-                    VmDeviceUtils.isSoundDeviceEnabled(vm.getId()),
+                    VmDeviceUtils.hasMemoryBalloon(vm.getId()),
+                    VmDeviceUtils.hasSoundDevice(vm.getId()),
                     getReturnValue().getCanDoActionMessages())) {
                 return false;
             }
@@ -531,7 +531,7 @@
     }
 
     protected void updateBootOrder() {
-        
VmDeviceUtils.updateBootOrderInVmDeviceAndStoreToDB(getVm().getStaticData());
+        VmDeviceUtils.updateBootOrder(getVm().getId());
     }
 
     private void extendDiskImageSize() {
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmTemplateCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmTemplateCommand.java
index 771bc04..f6201c8 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmTemplateCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmTemplateCommand.java
@@ -183,9 +183,9 @@
                     getParameters().getVmTemplateData().getNumOfMonitors(),
                     interfaces,
                     new 
ArrayList<DiskImageBase>(getParameters().getVmTemplateData().getDiskList()),
-                    
VmDeviceUtils.isVirtioScsiControllerAttached(getParameters().getVmTemplateData().getId()),
+                    
VmDeviceUtils.hasVirtioScsiController(getParameters().getVmTemplateData().getId()),
                     hasWatchdog(getParameters().getVmTemplateData().getId()),
-                    
VmDeviceUtils.isBalloonEnabled(getParameters().getVmTemplateData().getId()),
+                    
VmDeviceUtils.hasMemoryBalloon(getParameters().getVmTemplateData().getId()),
                     isSoundDeviceEnabled(),
                     getReturnValue().getCanDoActionMessages())) {
                 returnValue = false;
@@ -222,7 +222,7 @@
     protected boolean isSoundDeviceEnabled() {
         Boolean soundDeviceEnabled = getParameters().isSoundDeviceEnabled();
         return soundDeviceEnabled != null ? soundDeviceEnabled :
-                
VmDeviceUtils.isSoundDeviceEnabled(getParameters().getVmTemplateData().getId());
+                
VmDeviceUtils.hasSoundDevice(getParameters().getVmTemplateData().getId());
     }
 
     @Override
@@ -297,7 +297,7 @@
         // also update the smartcard device
         VmDeviceUtils.updateSmartcardDevice(getVmTemplateId(), 
getParameters().getVmTemplateData().isSmartcardEnabled());
         // update audio device
-        VmDeviceUtils.updateAudioDevice(mOldTemplate,
+        VmDeviceUtils.updateSoundDevice(mOldTemplate,
                 getVmTemplate(),
                 getVdsGroup() != null ? 
getVdsGroup().getCompatibilityVersion() : null,
                 getParameters().isSoundDeviceEnabled());
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmManagementCommandBase.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmManagementCommandBase.java
index e5e46f7..8453ead 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmManagementCommandBase.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmManagementCommandBase.java
@@ -246,7 +246,7 @@
             vmStatic.setPriority(instanceType.getPriority());
             vmStatic.setTunnelMigration(instanceType.getTunnelMigration());
 
-            List<VmDevice> vmDevices = 
VmDeviceUtils.getBalloonDevices(instanceType.getId());
+            List<VmDevice> vmDevices = 
VmDeviceUtils.getMemoryBalloons(instanceType.getId());
             vmStatic.setMinAllocatedMem(instanceType.getMinAllocatedMem());
             if (vmDevices.isEmpty()) {
                 getParameters().setBalloonEnabled(false);
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/template/AddVmTemplateInterfaceCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/template/AddVmTemplateInterfaceCommand.java
index f80bbdb..0a9ec62 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/template/AddVmTemplateInterfaceCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/template/AddVmTemplateInterfaceCommand.java
@@ -11,7 +11,6 @@
 import org.ovirt.engine.core.common.AuditLogType;
 import org.ovirt.engine.core.common.VdcObjectType;
 import org.ovirt.engine.core.common.action.AddVmTemplateInterfaceParameters;
-import org.ovirt.engine.core.common.businessentities.VmDeviceId;
 import org.ovirt.engine.core.common.businessentities.VmEntityType;
 import org.ovirt.engine.core.common.businessentities.network.VmInterfaceType;
 import 
org.ovirt.engine.core.common.businessentities.network.VmNetworkInterface;
@@ -37,8 +36,9 @@
                         getParameters().getInterface().getType()).getSpeed());
 
         getVmNicDao().save(getParameters().getInterface());
-        VmDeviceUtils.addNetworkInterfaceDevice(
-                new VmDeviceId(getParameters().getInterface().getId(), 
getParameters().getVmTemplateId()),
+        VmDeviceUtils.addInterface(
+                getParameters().getVmTemplateId(),
+                getParameters().getInterface().getId(),
                 getParameters().getInterface().isPlugged(),
                 getParameters().getInterface().isPassthrough());
 
@@ -73,10 +73,10 @@
                     getVmTemplate().getNumOfMonitors(),
                     interfacesForCheckPciLimit,
                     new 
ArrayList<DiskImageBase>(getVmTemplate().getDiskList()),
-                    
VmDeviceUtils.isVirtioScsiControllerAttached(getVmTemplate().getId()),
+                    
VmDeviceUtils.hasVirtioScsiController(getVmTemplate().getId()),
                     VmDeviceUtils.hasWatchdog(getVmTemplate().getId()),
-                    VmDeviceUtils.isBalloonEnabled(getVmTemplate().getId()),
-                    
VmDeviceUtils.isSoundDeviceEnabled(getVmTemplate().getId()),
+                    VmDeviceUtils.hasMemoryBalloon(getVmTemplate().getId()),
+                    VmDeviceUtils.hasSoundDevice(getVmTemplate().getId()),
                     getReturnValue().getCanDoActionMessages())) {
                 return false;
             }
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/template/UpdateVmTemplateInterfaceCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/template/UpdateVmTemplateInterfaceCommand.java
index 786eef5..47344a9 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/template/UpdateVmTemplateInterfaceCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/template/UpdateVmTemplateInterfaceCommand.java
@@ -113,10 +113,10 @@
                 getVmTemplate().getNumOfMonitors(),
                 interfaces,
                 new ArrayList<DiskImageBase>(getVmTemplate().getDiskList()),
-                
VmDeviceUtils.isVirtioScsiControllerAttached(getVmTemplate().getId()),
+                VmDeviceUtils.hasVirtioScsiController(getVmTemplate().getId()),
                 VmDeviceUtils.hasWatchdog(getVmTemplate().getId()),
-                VmDeviceUtils.isBalloonEnabled(getVmTemplate().getId()),
-                VmDeviceUtils.isSoundDeviceEnabled(getVmTemplate().getId()),
+                VmDeviceUtils.hasMemoryBalloon(getVmTemplate().getId()),
+                VmDeviceUtils.hasSoundDevice(getVmTemplate().getId()),
                 getReturnValue().getCanDoActionMessages());
     }
 
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AbstractVmInterfaceCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AbstractVmInterfaceCommand.java
index d78d4fc..a52a9ae 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AbstractVmInterfaceCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AbstractVmInterfaceCommand.java
@@ -80,10 +80,10 @@
         return checkPciAndIdeLimit(vm.getOs(),
                 vm.getVdsGroupCompatibilityVersion(),
                 vm.getNumOfMonitors(), allInterfaces, allDisks,
-                VmDeviceUtils.isVirtioScsiControllerAttached(getVmId()),
+                VmDeviceUtils.hasVirtioScsiController(getVmId()),
                 VmDeviceUtils.hasWatchdog(getVmId()),
-                VmDeviceUtils.isBalloonEnabled(getVmId()),
-                VmDeviceUtils.isSoundDeviceEnabled(getVmId()),
+                VmDeviceUtils.hasMemoryBalloon(getVmId()),
+                VmDeviceUtils.hasSoundDevice(getVmId()),
                 getReturnValue().getCanDoActionMessages());
     }
 
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/ActivateDeactivateVmNicCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/ActivateDeactivateVmNicCommand.java
index 1ff9a3c..4d48f37 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/ActivateDeactivateVmNicCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/ActivateDeactivateVmNicCommand.java
@@ -182,7 +182,7 @@
             public Void runInTransaction() {
                 vmDevice.setIsPlugged(getParameters().getAction() == 
PlugAction.PLUG ? true : false);
                 getVmDeviceDao().update(vmDevice);
-                
VmDeviceUtils.updateBootOrderInVmDeviceAndStoreToDB(getVm().getStaticData());
+                VmDeviceUtils.updateBootOrder(getVm().getId());
                 return null;
             }
         };
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AddVmInterfaceCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AddVmInterfaceCommand.java
index 806f63b..5c7bd4c 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AddVmInterfaceCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/network/vm/AddVmInterfaceCommand.java
@@ -13,7 +13,6 @@
 import org.ovirt.engine.core.common.action.AddVmInterfaceParameters;
 import org.ovirt.engine.core.common.action.PlugAction;
 import org.ovirt.engine.core.common.businessentities.VmDevice;
-import org.ovirt.engine.core.common.businessentities.VmDeviceId;
 import org.ovirt.engine.core.common.businessentities.VmStatic;
 import org.ovirt.engine.core.common.businessentities.network.VmInterfaceType;
 import org.ovirt.engine.core.common.businessentities.network.VmNic;
@@ -76,9 +75,11 @@
     }
 
     private void addInterfaceDeviceToDb() {
-        VmDevice vmDevice = VmDeviceUtils.addNetworkInterfaceDevice(
-                new VmDeviceId(getInterface().getId(), 
getParameters().getVmId()),
-                getInterface().isPlugged(), getInterface().isPassthrough());
+        VmDevice vmDevice = VmDeviceUtils.addInterface(
+                getParameters().getVmId(),
+                getInterface().getId(),
+                getInterface().isPlugged(),
+                getInterface().isPassthrough());
         getCompensationContext().snapshotNewEntity(vmDevice);
     }
 
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/smartcard/SmartcardSpecParams.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/smartcard/SmartcardSpecParams.java
deleted file mode 100644
index ef72aca..0000000
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/smartcard/SmartcardSpecParams.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.ovirt.engine.core.bll.smartcard;
-
-import java.util.HashMap;
-
-public class SmartcardSpecParams extends HashMap<String, Object> {
-
-    private static final long serialVersionUID = 4548406604400880935L;
-
-    public SmartcardSpecParams() {
-        put("mode", "passthrough");
-        put("type", "spicevmc");
-    }
-
-}
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java
index 1097c77..21f1ac4 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java
@@ -3,7 +3,6 @@
 import org.apache.commons.lang.StringUtils;
 import org.ovirt.engine.core.bll.VmHandler;
 import org.ovirt.engine.core.bll.network.VmInterfaceManager;
-import org.ovirt.engine.core.bll.smartcard.SmartcardSpecParams;
 import org.ovirt.engine.core.bll.validator.VirtIoRngValidator;
 import org.ovirt.engine.core.common.action.VmManagementParametersBase;
 import org.ovirt.engine.core.common.businessentities.DisplayType;
@@ -16,7 +15,6 @@
 import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType;
 import org.ovirt.engine.core.common.businessentities.VmDeviceId;
 import org.ovirt.engine.core.common.businessentities.VmRngDevice;
-import org.ovirt.engine.core.common.businessentities.VmStatic;
 import org.ovirt.engine.core.common.businessentities.VmType;
 import org.ovirt.engine.core.common.businessentities.network.VmNic;
 import org.ovirt.engine.core.common.businessentities.storage.BaseDisk;
@@ -54,794 +52,594 @@
     private final static int COMPANION_USB_CONTROLLERS = 3;
     private final static int VNC_MIN_MONITORS = 1;
     private final static int SINGLE_QXL_MONITORS = 1;
+    public final static Map<String, Object> EMPTY_SPEC_PARAMS = 
Collections.emptyMap();
     private static OsRepository osRepository = 
SimpleDependecyInjector.getInstance().get(OsRepository.class);
     private static DbFacade dbFacade = 
SimpleDependecyInjector.getInstance().get(DbFacade.class);
     private static VmDeviceDAO dao = dbFacade.getVmDeviceDao();
 
-    /**
-     * Update the vm devices according to changes made in vm static for 
existing VM
+    /*
+     * CD-ROM device
      */
-    public static void updateVmDevices(VmManagementParametersBase params, VM 
oldVm) {
-        VmBase oldVmBase = oldVm.getStaticData();
-        VmBase entity = params.getVmStaticData();
-        if (entity != null) {
-            updateCdInVmDevice(oldVmBase, entity);
-            if (oldVmBase.getDefaultBootSequence() != entity
-                    .getDefaultBootSequence()) {
-                updateBootOrderInVmDeviceAndStoreToDB(entity);
-            }
 
-            // if the console type has changed, recreate Video devices
-            boolean displayTypeChanged = oldVmBase.getDefaultDisplayType() != 
entity.getDefaultDisplayType();
-            boolean numOfMonitorsChanged = entity.getDefaultDisplayType() == 
DisplayType.qxl && oldVmBase.getNumOfMonitors() != entity.getNumOfMonitors();
-            boolean singleQxlChanged = oldVmBase.getSingleQxlPci() != 
entity.getSingleQxlPci();
-
-            if(displayTypeChanged || numOfMonitorsChanged || singleQxlChanged) 
{
-                // delete all video device
-                for (VmDevice device : 
dao.getVmDeviceByVmIdAndType(oldVmBase.getId(), VmDeviceGeneralType.VIDEO)) {
-                    dao.remove(device.getId());
-                }
-                // add video device per each monitor
-                int monitors = entity.getSingleQxlPci() ? 1 : 
entity.getNumOfMonitors();
-                for (int i = 0; i<monitors; i++) {
-                    addManagedDevice(new VmDeviceId(Guid.newGuid(), 
entity.getId()),
-                            VmDeviceGeneralType.VIDEO,
-                            
entity.getDefaultDisplayType().getDefaultVmDeviceType(),
-                            getMemExpr(entity.getNumOfMonitors(), 
entity.getSingleQxlPci()),
-                            true,
-                            false,
-                            null,
-                            false);
-                }
-            }
-            updateUSBSlots(oldVmBase, entity);
-            updateMemoryBalloon(entity, isBalloonEnabled(params));
-            updateAudioDevice(oldVm.getStaticData(), entity, 
oldVm.getVdsGroupCompatibilityVersion(), params.isSoundDeviceEnabled());
-            updateSmartcardDevice(oldVm, entity);
-            updateConsoleDevice(entity, params.isConsoleEnabled());
-            updateVirtioScsiController(entity.getId(), 
params.isVirtioScsiEnabled());
+    private static String getCdPath(String srcCdPath, String dstCdPath) {
+        if (!StringUtils.isEmpty(dstCdPath)) {
+            return dstCdPath;
+        } else if (!StringUtils.isEmpty(srcCdPath)) {
+            return srcCdPath;
+        } else {
+            return "";
         }
     }
 
+    /**
+     * Copy CD path from old to new VM.
+     *
+     * <b>Note:</b> Only one CD is currently supported.
+     *
+     * @param oldVmBase
+     * @param newVmBase
+     */
+    private static void updateCdPath(VmBase oldVmBase, VmBase newVmBase) {
+        List<VmDevice> cdList = getCdDevices(oldVmBase.getId());
+        if (cdList.size() > 0) { // this is done only for safety, each VM must 
have at least an empty CD
+            VmDevice cd = cdList.get(0); // only one managed CD is currently 
supported.
+            cd.getSpecParams().putAll(getCdDeviceSpecParams("", 
newVmBase.getIsoPath()));
+            dao.update(cd);
+        }
+    }
+
+    /**
+     * Get list of all CD-ROM devices in the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static List<VmDevice> getCdDevices(Guid vmId) {
+        return dao.getVmDeviceByVmIdTypeAndDevice(
+                vmId,
+                VmDeviceGeneralType.DISK,
+                VmDeviceType.CDROM.getName());
+    }
+
+    /**
+     * Check if the VM has a CD-ROM device.
+     *
+     * @param vmId
+     * @return
+     */
+    public static boolean hasCdDevice(Guid vmId) {
+        return !getCdDevices(vmId).isEmpty();
+    }
+
+    /**
+     * Get CD-ROM device spec params.
+     *
+     * @param srcCdPath
+     * @param dstCdPath
+     * @return
+     */
+    private static Map<String, Object> getCdDeviceSpecParams(String srcCdPath, 
String dstCdPath) {
+        return Collections.<String, Object> singletonMap(VdsProperties.Path, 
getCdPath(srcCdPath, dstCdPath));
+    }
+
+    /**
+     * Add CD-ROM device with given CD path to the VM.
+     *
+     * @param vmId
+     * @param cdPath
+     * @return
+     */
+    public static VmDevice addCdDevice(Guid vmId, String cdPath) {
+        return addManagedDevice(
+                new VmDeviceId(Guid.newGuid(), vmId),
+                VmDeviceGeneralType.DISK,
+                VmDeviceType.CDROM,
+                getCdDeviceSpecParams("", cdPath),
+                true,
+                true);
+    }
+
+    /**
+     * Add CD-ROM device with empty CD path to the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static VmDevice addCdDevice(Guid vmId) {
+        return addCdDevice(vmId, "");
+    }
+
+    /*
+     * Smartcard device
+     */
+
+    /**
+     * Update smartcard device in the new VM, if its state should be different 
from the old VM.
+     *
+     * @param oldVm
+     * @param newVm
+     */
     private static void updateSmartcardDevice(VM oldVm, VmBase newVm) {
         if (newVm.isSmartcardEnabled() == oldVm.isSmartcardEnabled()) {
-            // the smartcard device did not changed, do nothing
             return;
         }
 
         updateSmartcardDevice(newVm.getId(), newVm.isSmartcardEnabled());
     }
 
+    /**
+     * Enable/disable smartcard device in a VM.
+     *
+     * @param vmId  id of the VM to be modified
+     * @param smartcardEnabled  enable/disable flag
+     */
     public static void updateSmartcardDevice(Guid vmId, boolean 
smartcardEnabled) {
-        List<VmDevice> vmDevices =
-                dbFacade
-                        .getVmDeviceDao()
-                        .getVmDeviceByVmIdTypeAndDevice(vmId,
-                                VmDeviceGeneralType.SMARTCARD,
-                                VmDeviceType.SMARTCARD.getName());
-
-        if (!smartcardEnabled) {
-            for (VmDevice device : vmDevices) {
-                dao.remove(device.getId());
+        if (smartcardEnabled) {
+            if (!hasSmartcardDevice(vmId)) {
+                addSmartcardDevice(vmId);
             }
-        } else if (vmDevices.isEmpty()) {
-            addSmartcardDevice(vmId);
+        } else {
+            removeSmartcardDevices(vmId);
         }
     }
 
-    public static void addSmartcardDevice(Guid vmId) {
-        VmDeviceUtils.addManagedDevice(new VmDeviceId(Guid.newGuid(), vmId),
+    /**
+     * Get list of all smartcard devices in the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static List<VmDevice> getSmartcardDevices(Guid vmId) {
+        return dao.getVmDeviceByVmIdTypeAndDevice(
+                vmId,
+                VmDeviceGeneralType.SMARTCARD,
+                VmDeviceType.SMARTCARD.getName());
+    }
+
+    /**
+     * Remove all smartcard devices from the VM.
+     *
+     * @param vmId
+     */
+    public static void removeSmartcardDevices(Guid vmId) {
+        removeVmDevices(getSmartcardDevices(vmId));
+    }
+
+    /**
+     * Check if the VM has a smartcard device.
+     *
+     * @param vmId
+     * @return
+     */
+    public static boolean hasSmartcardDevice(Guid vmId) {
+        return !getSmartcardDevices(vmId).isEmpty();
+    }
+
+    /**
+     * Add new smartcard device to the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static VmDevice addSmartcardDevice(Guid vmId) {
+        return addManagedDevice(
+                new VmDeviceId(Guid.newGuid(), vmId),
                 VmDeviceGeneralType.SMARTCARD,
                 VmDeviceType.SMARTCARD,
-                new SmartcardSpecParams(),
+                getSmartcardDeviceSpecParams(),
                 true,
-                false,
-                null,
                 false);
     }
 
-    private static void updateConsoleDevice(VmBase newVmBase, Boolean 
consoleEnabled) {
-            updateConsoleDevice(newVmBase.getId(), consoleEnabled);
+    /**
+     * Returns smartcard device spec params.
+     *
+     * @return
+     */
+    private static Map<String, Object> getSmartcardDeviceSpecParams() {
+        Map<String, Object> specParams = new HashMap<>();
+        specParams.put("mode", "passthrough");
+        specParams.put("type", "spicevmc");
+        return specParams;
     }
 
+    /*
+     * Console device
+     */
+
+    /**
+     * Enable/disable console device in the VM.
+     *
+     * @param vmId
+     * @param consoleEnabled true/false to enable/disable device respectively, 
null to leave it untouched
+     */
     public static void updateConsoleDevice(Guid vmId, Boolean consoleEnabled) {
         if (consoleEnabled == null) {
             return; //we don't want to update the device
         }
 
-        List<VmDevice> consoles = dbFacade
-                    .getVmDeviceDao()
-                    .getVmDeviceByVmIdTypeAndDevice(vmId,
-                            VmDeviceGeneralType.CONSOLE, 
VmDeviceType.CONSOLE.getName());
-
         if (consoleEnabled) {
-            if (consoles.isEmpty()) {
+            if (!hasConsoleDevice(vmId)) {
                 addConsoleDevice(vmId);
             }
         } else {
-            for (VmDevice device : consoles) {
-                dao.remove(device.getId());
-            }
+            removeConsoleDevices(vmId);
         }
     }
 
+    /**
+     * Get list of all console devices in the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static List<VmDevice> getConsoleDevices(Guid vmId) {
+        return dao.getVmDeviceByVmIdTypeAndDevice(
+                vmId,
+                VmDeviceGeneralType.CONSOLE,
+                VmDeviceType.CONSOLE.getName());
+    }
+
+    /**
+     * Remove all console devices from the VM.
+     *
+     * @param vmId
+     */
+    public static void removeConsoleDevices(Guid vmId) {
+        removeVmDevices(getConsoleDevices(vmId));
+    }
+
+    /**
+     * Check if the VM has a console device.
+     *
+     * @param vmId
+     * @return
+     */
+    public static boolean hasConsoleDevice(Guid vmId) {
+        return !getConsoleDevices(vmId).isEmpty();
+    }
+
+    /**
+     * Add new console device to the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static VmDevice addConsoleDevice(Guid vmId) {
+        return addManagedDevice(
+                new VmDeviceId(Guid.newGuid(), vmId),
+                VmDeviceGeneralType.CONSOLE,
+                VmDeviceType.CONSOLE,
+                EMPTY_SPEC_PARAMS,
+                true,
+                false);
+    }
+
+    /*
+     * VirtIO-SCSI controller
+     */
+
+    /**
+     * Enable/disable VirtIO-SCSI controller in the VM.
+     *
+     * @param vmId
+     * @param isVirtioScsiEnabled    true/false to enable/disable device 
respectively, null to leave it untouched
+     */
     public static void updateVirtioScsiController(Guid vmId, Boolean 
isVirtioScsiEnabled) {
         if (isVirtioScsiEnabled == null) {
             return; //we don't want to update the device
         }
 
-        List<VmDevice> controllers = dbFacade
-                .getVmDeviceDao()
-                .getVmDeviceByVmIdTypeAndDevice(vmId,
-                        VmDeviceGeneralType.CONTROLLER, 
VmDeviceType.VIRTIOSCSI.getName());
-
         if (isVirtioScsiEnabled) {
-            if (controllers.isEmpty()) {
+            if (!hasVirtioScsiController(vmId)) {
                 addVirtioScsiController(vmId);
             }
         } else {
-            for (VmDevice device : controllers) {
-                dao.remove(device.getId());
-            }
+            removeVirtioScsiControllers(vmId);
         }
     }
 
-    private static void addConsoleDevice(Guid vmId) {
-        VmDeviceUtils.addManagedDevice(new VmDeviceId(Guid.newGuid(), vmId),
-                VmDeviceGeneralType.CONSOLE,
-                VmDeviceType.CONSOLE,
-                new HashMap<String, Object>(),
-                true,
-                false,
-                null,
-                false);
-    }
-
-    private static void addVirtioScsiController(Guid vmId) {
-        VmDeviceUtils.addManagedDevice(new VmDeviceId(Guid.newGuid(), vmId),
+    /**
+     * Add new VirtIO-SCSI controller to the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static VmDevice addVirtioScsiController(Guid vmId) {
+        return addManagedDevice(
+                new VmDeviceId(Guid.newGuid(), vmId),
                 VmDeviceGeneralType.CONTROLLER,
                 VmDeviceType.VIRTIOSCSI,
-                new HashMap<String, Object>(),
+                EMPTY_SPEC_PARAMS,
                 true,
-                false,
-                null,
                 false);
     }
 
     /**
-     * Replace desktop-vm audio device if OS has changed
+     * Get list of all VirtIO-SCSI controllers in the VM.
      *
-     * @param oldVm
-     * @param newVmBase
-     * @param compatibilityVersion cluster compatibility version
-     * @param isSoundDeviceEnabled device enabled - if null, keep old state
+     * @param vmId
+     * @return
      */
-    public static void updateAudioDevice(VmBase oldVm, VmBase newVmBase, 
Version compatibilityVersion, Boolean isSoundDeviceEnabled) {
+    public static List<VmDevice> getVirtioScsiControllers(Guid vmId) {
+        return getVirtioScsiControllers(vmId, null, false);
+    }
+
+    /**
+     * Get list of VirtIO-SCSI controllers in the VM.
+     *
+     * @param vmId
+     * @param userID
+     * @param isFiltered
+     * @return
+     */
+    public static List<VmDevice> getVirtioScsiControllers(Guid vmId, Guid 
userID, boolean isFiltered) {
+        return dao.getVmDeviceByVmIdTypeAndDevice(
+                vmId,
+                VmDeviceGeneralType.CONTROLLER,
+                VmDeviceType.VIRTIOSCSI.getName(),
+                userID,
+                isFiltered);
+    }
+
+    /**
+     * Remove all VirtIO-SCSI controllers from the VM.
+     *
+     * @param vmId
+     */
+    public static void removeVirtioScsiControllers(Guid vmId) {
+        removeVmDevices(getVirtioScsiControllers(vmId));
+    }
+
+    /**
+     * Check if the VM has a VirtIO-SCSI controller.
+     *
+     * @param vmId
+     * @return
+     */
+    public static boolean hasVirtioScsiController(Guid vmId) {
+        return !getVirtioScsiControllers(vmId).isEmpty();
+    }
+
+    /*
+     * Sound device
+     */
+
+    /**
+     * Update sound device in the new VM, if its state should be different 
from the old VM. Recreate the device in any
+     * case, if OS has been changed.
+     *
+     * @param oldVmBase
+     * @param newVmBase
+     * @param compatibilityVersion  cluster compatibility version
+     * @param isSoundDeviceEnabled  true/false to enable/disable device 
respectively, null to leave it untouched
+     */
+    public static void updateSoundDevice(VmBase oldVmBase, VmBase newVmBase, 
Version compatibilityVersion,
+                                         Boolean isSoundDeviceEnabled) {
+        boolean osChanged = oldVmBase.getOsId() != newVmBase.getOsId();
+        updateSoundDevice(newVmBase.getId(), newVmBase.getOsId(), 
compatibilityVersion, isSoundDeviceEnabled, osChanged);
+    }
+
+    /**
+     * Enable/disable sound device in the VM.
+     *
+     * @param vmId
+     * @param osId
+     * @param compatibilityVersion  cluster compatibility version
+     * @param isSoundDeviceEnabled  true/false to enable/disable device 
respectively, null to leave it untouched
+     * @param recreate              true to recreate the device even if it 
already exists
+     */
+    public static void updateSoundDevice(Guid vmId, int osId, Version 
compatibilityVersion,
+                                         Boolean isSoundDeviceEnabled, boolean 
recreate) {
         boolean removeDevice = false;
         boolean createDevice = false;
 
-        Guid vmId = oldVm.getId();
-        boolean osChanged = oldVm.getOsId() != newVmBase.getOsId();
+        List<VmDevice> list = getSoundDevices(vmId);
 
-        List<VmDevice> list =
-                dbFacade
-                        .getVmDeviceDao()
-                        .getVmDeviceByVmIdAndType(vmId, 
VmDeviceGeneralType.SOUND);
-
-        // if isSoundDeviceEnabled is null,
-        // recreate device only if previously existed and os has changed
         if (isSoundDeviceEnabled == null) {
-            if (!list.isEmpty() && osChanged) {
+            if (!list.isEmpty() && recreate) {
                 removeDevice = createDevice = true;
             }
         } else {
-            // if soundeDevice disabled or os changed, and device exist, remove
-            removeDevice = (!isSoundDeviceEnabled || osChanged) && 
!list.isEmpty();
+            // if sound device is to be disabled or must be recreated, and the 
device exists, remove it
+            removeDevice = (!isSoundDeviceEnabled || recreate) && 
!list.isEmpty();
 
-            // if soundDevice enabled and missing or os changed, create
-            createDevice = isSoundDeviceEnabled && (list.isEmpty() || 
osChanged);
+            // if sound device is to be enabled or must be recreated, and the 
device does not exist, create it
+            createDevice = isSoundDeviceEnabled && (list.isEmpty() || 
recreate);
         }
 
         if (removeDevice) {
-            removeNumberOfDevices(list, list.size());
+            removeVmDevices(list);
         }
         if (createDevice) {
-            String soundDevice =
-                    osRepository.getSoundDevice(newVmBase.getOsId(), 
compatibilityVersion);
-            addManagedDevice(new VmDeviceId(Guid.newGuid(), vmId),
-                    VmDeviceGeneralType.SOUND,
-                    VmDeviceType.getSoundDeviceType(soundDevice),
-                    new HashMap<String, Object>(),
+            addSoundDevice(vmId, osId, compatibilityVersion);
+        }
+    }
+
+    /**
+     * Get list of all sound devices in the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static List<VmDevice> getSoundDevices(Guid vmId) {
+        return dao.getVmDeviceByVmIdAndType(vmId, VmDeviceGeneralType.SOUND);
+    }
+
+    /**
+     * Add new sound device to the VM.
+     *
+     * @param vmBase
+     * @return
+     */
+    public static VmDevice addSoundDevice(VmBase vmBase) {
+        return addSoundDevice(vmBase.getId(), vmBase.getOsId(), 
ClusterUtils.getCompatibilityVersion(vmBase));
+    }
+
+    /**
+     * Add new sound device to the VM.
+     *
+     * @param vmId
+     * @param osId
+     * @param compatibilityVersion
+     * @return
+     */
+    public static VmDevice addSoundDevice(Guid vmId, int osId, Version 
compatibilityVersion) {
+        String soundDevice = osRepository.getSoundDevice(osId, 
compatibilityVersion);
+        return addManagedDevice(
+                new VmDeviceId(Guid.newGuid(), vmId),
+                VmDeviceGeneralType.SOUND,
+                VmDeviceType.getSoundDeviceType(soundDevice),
+                EMPTY_SPEC_PARAMS,
+                true,
+                true);
+    }
+
+    /**
+     * Check if the VM has a sound device.
+     *
+     * @param vmId
+     * @return
+     */
+    public static boolean hasSoundDevice(Guid vmId) {
+        return !getSoundDevices(vmId).isEmpty();
+    }
+
+    /*
+     * Video device
+     */
+
+    private static void updateVideoDevices(VmBase oldVmBase, VmBase newVmBase) 
{
+        boolean displayTypeChanged = oldVmBase.getDefaultDisplayType() != 
newVmBase.getDefaultDisplayType();
+        boolean numOfMonitorsChanged = newVmBase.getDefaultDisplayType() == 
DisplayType.qxl &&
+                oldVmBase.getNumOfMonitors() != newVmBase.getNumOfMonitors();
+        boolean singleQxlChanged = oldVmBase.getSingleQxlPci() != 
newVmBase.getSingleQxlPci();
+
+        if (displayTypeChanged || numOfMonitorsChanged || singleQxlChanged) {
+            removeVideoDevices(oldVmBase.getId());
+            addVideoDevices(newVmBase, 
getNeededNumberOfVideoDevices(newVmBase));
+        }
+    }
+
+    private static int getNeededNumberOfVideoDevices(VmBase vmBase) {
+        int maxMonitorsSpice = vmBase.getSingleQxlPci() ? SINGLE_QXL_MONITORS 
: vmBase.getNumOfMonitors();
+        int maxMonitorsVnc = Math.max(VNC_MIN_MONITORS, 
vmBase.getNumOfMonitors());
+
+        return Math.min(maxMonitorsSpice, maxMonitorsVnc);
+    }
+
+    /**
+     * Add given number of video devices to the VM.
+     *
+     * @param vmBase
+     * @param numberOfVideoDevices
+     */
+    public static void addVideoDevices(VmBase vmBase, int 
numberOfVideoDevices) {
+        for (int i = 0; i < numberOfVideoDevices; i++) {
+            addManagedDevice(
+                    new VmDeviceId(Guid.newGuid(), vmBase.getId()),
+                    VmDeviceGeneralType.VIDEO,
+                    vmBase.getDefaultDisplayType().getDefaultVmDeviceType(),
+                    getVideoDeviceSpecParams(vmBase),
                     true,
-                    true,
-                    null,
                     false);
         }
     }
 
     /**
-     * Update the vm devices according to changes made configuration
-     */
-    public static <T extends VmBase> void updateVmDevices(T entity) {
-        if (entity != null) {
-            updateUSBSlots(entity, entity);
-        }
-    }
-
-    /**
-     * Copy related data from the given VM/VmBase/VmDevice list to the 
destination VM/VmTemplate.
-     */
-    public static void copyVmDevices(Guid srcId,
-                                     Guid dstId,
-                                     VM vm,
-                                     VmBase vmBase,
-                                     boolean isVm,
-                                     List<VmDevice> devicesDataToUse,
-                                     Map<Guid, Guid> 
srcDeviceIdToTargetDeviceIdMapping,
-                                     boolean soundDeviceEnabled,
-                                     boolean isConsoleEnabled,
-                                     Boolean isVirtioScsiEnabled,
-                                     boolean isBalloonEnabled,
-                                     Set<GraphicsType> graphicsToSkip,
-                                     boolean copySnapshotDevices) {
-        Guid id;
-        if (graphicsToSkip == null) {
-            graphicsToSkip = new HashSet<>();
-        }
-        String isoPath=vmBase.getIsoPath();
-        // indicates that VM should have CD either from its own (iso_path) or 
from the snapshot it was cloned from.
-        boolean shouldHaveCD = StringUtils.isNotEmpty(isoPath);
-        // indicates if VM has already a non empty CD in DB
-        boolean hasAlreadyCD =
-                
(!(dbFacade.getVmDeviceDao().getVmDeviceByVmIdTypeAndDevice(vmBase.getId(),
-                        VmDeviceGeneralType.DISK,
-                        VmDeviceType.CDROM.getName())).isEmpty());
-        boolean addCD = (!hasAlreadyCD && shouldHaveCD);
-        boolean hasSoundDevice = false;
-        boolean hasAlreadyConsoleDevice = false;
-        boolean hasVirtioScsiController = false;
-        boolean hasAlreadyBalloonDevice = false;
-
-        VDSGroup cluster = vmBase.getVdsGroupId() != null ? 
DbFacade.getInstance().getVdsGroupDao().get(vmBase.getVdsGroupId()) : null;
-
-        for (VmDevice device : devicesDataToUse) {
-            if (device.getSnapshotId() != null && !copySnapshotDevices) {
-                continue;
-            }
-
-            id = Guid.newGuid();
-            Map<String, Object> specParams = new HashMap<>();
-            if (srcId.equals(Guid.Empty)) {
-                //add CD if not exists
-                if (addCD) {
-                    setCdPath(specParams, "", isoPath);
-                    addManagedDevice(new VmDeviceId(Guid.newGuid(), dstId) , 
VmDeviceGeneralType.DISK, VmDeviceType.CDROM, specParams, true, true, null, 
false);
-                    hasAlreadyCD = true;
-                    addCD = false;
-                }
-                // updating USB slots
-                updateUSBSlots(null, vmBase);
-                // add mem balloon if defined
-                updateMemoryBalloon(vmBase, isBalloonEnabled);
-            }
-
-            switch(device.getType()) {
-                case DISK:
-                    if 
(VmDeviceType.DISK.getName().equals(device.getDevice())) {
-                        if 
(srcDeviceIdToTargetDeviceIdMapping.containsKey(device.getDeviceId())) {
-                            id = 
srcDeviceIdToTargetDeviceIdMapping.get(device.getDeviceId());
-                        }
-                    } else if 
(VmDeviceType.CDROM.getName().equals(device.getDevice())) {
-                        // check here is source VM had CD (Vm from snapshot)
-                        String srcCdPath = (String) 
device.getSpecParams().get(VdsProperties.Path);
-                        shouldHaveCD = (!StringUtils.isEmpty(srcCdPath) || 
shouldHaveCD);
-                        if (!hasAlreadyCD && shouldHaveCD) {
-                            setCdPath(specParams, srcCdPath, isoPath);
-                        }
-                        else {// CD already exists
-                            continue;
-                        }
-                    }
-                    break;
-
-                case INTERFACE:
-                    if 
(srcDeviceIdToTargetDeviceIdMapping.containsKey(device.getDeviceId())) {
-                        id = 
srcDeviceIdToTargetDeviceIdMapping.get(device.getDeviceId());
-                    }
-                    break;
-
-                case CONTROLLER:
-                    if (VmDeviceType.USB.getName().equals(device.getDevice())) 
{
-                        specParams = device.getSpecParams();
-                    }
-                    else if 
(VmDeviceType.VIRTIOSCSI.getName().equals(device.getDevice())) {
-                        hasVirtioScsiController = true;
-                        if (Boolean.FALSE.equals(isVirtioScsiEnabled)) {
-                            continue;
-                        }
-                    }
-                    break;
-
-                case VIDEO:
-                    if (isVm) {
-                        // src is template and target is VM. video devices 
will be created according
-                        // to the new VMStatic params
-                        continue;
-                    } else {
-                    specParams.putAll(getMemExpr(vmBase.getNumOfMonitors(), 
vmBase.getSingleQxlPci()));
-                    }
-                    break;
-
-                case BALLOON:
-                    hasAlreadyBalloonDevice = true;
-                    if (!isBalloonEnabled) {
-                        continue;
-                    }
-                    specParams.put(VdsProperties.Model, VdsProperties.Virtio);
-                    break;
-
-                case SMARTCARD:
-                    specParams = new SmartcardSpecParams();
-                    break;
-
-                case WATCHDOG:
-                    specParams.putAll(device.getSpecParams());
-                    break;
-
-                case RNG:
-                    if (hasVmRngDevice(dstId)) {
-                        continue; // don't copy rng device if we already have 
it
-                    }
-                    if (!new VirtIoRngValidator().canAddRngDevice(cluster, new 
VmRngDevice(device)).isValid()) {
-                        continue;
-                    }
-                    specParams.putAll(device.getSpecParams());
-                    break;
-
-                case CONSOLE:
-                    hasAlreadyConsoleDevice = true;
-                    if (!isConsoleEnabled) {
-                        continue;
-                    }
-                    break;
-
-                case SOUND:
-                    hasSoundDevice = true;
-                    if (!soundDeviceEnabled) {
-                        continue;
-                    }
-                    break;
-
-                case GRAPHICS:
-                    GraphicsType type = 
GraphicsType.fromVmDeviceType(VmDeviceType.getByName(device.getDevice()));
-                    // don't add device from the template if it should be 
skipped (i.e. it's overriden in params)
-                    // OR if we already have it
-                    if (graphicsToSkip.contains(type) ||
-                            hasVmGraphicsDeviceOfType(dstId, 
GraphicsType.fromString(device.getDevice())))
-                    {
-                        continue;
-                    }
-                    break;
-
-                default:
-                    break;
-            }
-            device.setId(new VmDeviceId(id, dstId));
-            device.setSpecParams(specParams);
-            dao.save(device);
-        }
-        // if VM does not has CD, add an empty CD
-        if (!shouldHaveCD) {
-            addEmptyCD(dstId);
-        }
-
-        // if source doesnt have sound device and requested, add it
-        if (soundDeviceEnabled && !hasSoundDevice) {
-            if (isVm) {
-                addSoundCard(vm.getStaticData(), 
vm.getVdsGroupCompatibilityVersion());
-            } else {
-                addSoundCard(vmBase, cluster != null ? 
cluster.getCompatibilityVersion() : null);
-            }
-        }
-
-        if (isConsoleEnabled && !hasAlreadyConsoleDevice) {
-            addConsoleDevice(dstId);
-        }
-
-        if (Boolean.TRUE.equals(isVirtioScsiEnabled) && 
!hasVirtioScsiController) {
-            addVirtioScsiController(dstId);
-        }
-
-        if (isBalloonEnabled && !hasAlreadyBalloonDevice) {
-            addEmptyMemoryBalloon(dstId);
-        }
-
-        if (isVm) {
-            //  update devices boot order
-            updateBootOrderInVmDeviceAndStoreToDB(vmBase);
-
-            int numOfMonitors = getNumOfMonitors(vm);
-
-            // create Video device. Multiple if display type is spice
-            for (int i = 0; i < numOfMonitors; i++) {
-                addVideoDevice(vmBase);
-            }
-        }
-    }
-
-    private static int getNumOfMonitors(VM vm) {
-        int maxMonitorsSpice = vm.getSingleQxlPci() ? SINGLE_QXL_MONITORS : 
vm.getNumOfMonitors();
-        int maxMonitorsVnc = Math.max(VNC_MIN_MONITORS, vm.getNumOfMonitors());
-
-        return Math.min(maxMonitorsSpice, maxMonitorsVnc);
-    }
-
-    private static void addSoundCard(VmBase vmBase) {
-        addSoundCard(vmBase, ClusterUtils.getCompatibilityVersion(vmBase));
-    }
-
-    private static void addSoundCard(VmBase vmBase, Version 
vdsGroupCompatibilityVersion) {
-        String soundDevice = osRepository.getSoundDevice(vmBase.getOsId(), 
vdsGroupCompatibilityVersion);
-        addManagedDevice(new VmDeviceId(Guid.newGuid(), vmBase.getId()),
-                VmDeviceGeneralType.SOUND,
-                VmDeviceType.getSoundDeviceType(soundDevice),
-                new HashMap<String, Object>(),
-                true,
-                true,
-                null,
-                false);
-    }
-
-    public static void copyVmDevices(Guid srcId,
-                                     Guid dstId,
-                                     Map<Guid, Guid> 
srcDeviceIdToTargetDeviceIdMapping,
-                                     boolean soundDeviceEnabled,
-                                     boolean isConsoleEnabled,
-                                     Boolean isVirtioScsiEnabled,
-                                     boolean isBalloonEnabled,
-                                     Set<GraphicsType> graphicsToSkip,
-                                     boolean copySnapshotDevices) {
-        VM vm = dbFacade.getVmDao().get(dstId);
-        VmBase vmBase = (vm != null) ? vm.getStaticData() : null;
-        boolean isVm = (vmBase != null);
-
-        if (!isVm) {
-            vmBase = dbFacade.getVmTemplateDao().get(dstId);
-        }
-
-        List<VmDevice> devices = dao.getVmDeviceByVmId(srcId);
-        copyVmDevices(srcId, dstId, vm, vmBase, isVm, devices, 
srcDeviceIdToTargetDeviceIdMapping,
-                soundDeviceEnabled, isConsoleEnabled, isVirtioScsiEnabled, 
isBalloonEnabled, graphicsToSkip, copySnapshotDevices);
-    }
-
-    public static void copyDiskDevices(Guid dstId, List<VmDevice> 
devicesDataToUse, Map<Guid, Guid> srcDeviceIdToTargetDeviceIdMapping) {
-        for (VmDevice device : devicesDataToUse) {
-            if (VmDeviceType.DISK.getName().equals(device.getDevice())) {
-                if 
(srcDeviceIdToTargetDeviceIdMapping.containsKey(device.getDeviceId())) {
-                    Guid id = 
srcDeviceIdToTargetDeviceIdMapping.get(device.getDeviceId());
-                    device.setId(new VmDeviceId(id, dstId));
-                    device.setSpecParams(new HashMap<String, Object>());
-                    dao.save(device);
-                }
-            }
-        }
-    }
-
-    private static void addVideoDevice(VmBase vm) {
-        addManagedDevice(
-                new VmDeviceId(Guid.newGuid(), vm.getId()),
-                VmDeviceGeneralType.VIDEO,
-                vm.getDefaultDisplayType().getDefaultVmDeviceType(),
-                getMemExpr(vm.getNumOfMonitors(), vm.getSingleQxlPci()),
-                true,
-                true,
-                null,
-                false);
-    }
-
-    private static void setCdPath(Map<String, Object> specParams, String 
srcCdPath, String isoPath) {
-        // check if CD was set specifically for this VM
-        if (!StringUtils.isEmpty(isoPath)){
-            specParams.put(VdsProperties.Path, isoPath);
-        } else if (!StringUtils.isEmpty(srcCdPath)) { // get the path from the 
source device spec params
-            specParams.put(VdsProperties.Path, srcCdPath);
-        } else {
-            specParams.put(VdsProperties.Path, "");
-        }
-    }
-
-    /**
-     * Add a NIC device for the VM.
+     * Returns video device spec params.
      *
-     * @param id
-     *            The NIC id (must correspond with the ID of the NIC in the 
VM).
-     * @param plugged
-     *            Is the NIC plugged to the VM or not.
-     * @return The device that was added.
+     * @param vmBase
+     * @return
      */
-    public static VmDevice addNetworkInterfaceDevice(VmDeviceId id, boolean 
plugged, boolean hostDev) {
-        return addManagedDevice(id,
+    private static Map<String, Object> getVideoDeviceSpecParams(VmBase vmBase) 
{
+        return getVideoDeviceSpecParams(vmBase.getNumOfMonitors(), 
vmBase.getSingleQxlPci());
+    }
+
+    /**
+     * Returns video device spec params.
+     *
+     * @param numOfMonitors number of monitors
+     * @param singleQxlPci
+     * @return
+     */
+    private static Map<String, Object> getVideoDeviceSpecParams(int 
numOfMonitors, boolean singleQxlPci) {
+        int heads = singleQxlPci ? numOfMonitors : 1;
+        Map<String, Object> specParams = new HashMap<>();
+        specParams.put(HEADS, String.valueOf(heads));
+        specParams.put(VRAM, VmDeviceCommonUtils.singlePciVRamByHeads(heads));
+        if (singleQxlPci) {
+            specParams.put(RAM, 
VmDeviceCommonUtils.singlePciRamByHeads(heads));
+        }
+        return specParams;
+    }
+
+    /**
+     * Get list of all video devices in the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static List<VmDevice> getVideoDevices(Guid vmId) {
+        return dao.getVmDeviceByVmIdAndType(vmId, VmDeviceGeneralType.VIDEO);
+    }
+
+    /**
+     * Remove all video devices from the VM.
+     *
+     * @param vmId
+     */
+    public static void removeVideoDevices(Guid vmId) {
+        removeVmDevices(getVideoDevices(vmId));
+    }
+
+    /*
+     * Network interface
+     */
+
+    /**
+     * Add new network interface to the VM.
+     *
+     * @param vmId
+     * @param deviceId    the NIC id in the VM
+     * @param plugged     is NIC plugged to the VM or not
+     * @param hostDev     true if NIC is a host device, false if it is a bridge
+     * @return  the device added
+     */
+    public static VmDevice addInterface(Guid vmId, Guid deviceId, boolean 
plugged, boolean hostDev) {
+        return addInterface(vmId, deviceId, plugged, hostDev, null);
+    }
+
+    /**
+     * Add new network interface to the VM.
+     *
+     * @param vmId
+     * @param deviceId    the NIC id in the VM
+     * @param plugged     is NIC plugged to the VM or not
+     * @param hostDev     true if NIC is a host device, false if it is a bridge
+     * @param address
+     * @return  the device added
+     */
+    public static VmDevice addInterface(Guid vmId, Guid deviceId, boolean 
plugged, boolean hostDev, String address) {
+        return addManagedDevice(
+                new VmDeviceId(deviceId, vmId),
                 VmDeviceGeneralType.INTERFACE,
                 hostDev ? VmDeviceType.HOST_DEVICE : VmDeviceType.BRIDGE,
-                Collections.<String, Object> emptyMap(),
+                EMPTY_SPEC_PARAMS,
                 plugged,
                 false,
+                address,
                 null,
                 false);
     }
 
     /**
-     * @param id
-     * @param type
-     * @param device
-     * @param specParams
-     * @param plugged
-     * @param readOnly
-     * @param address
-     * @param customProp device custom properties
-     * @return newly created VmDevice instance
-     */
-    public static VmDevice addManagedDevice(VmDeviceId id,
-            VmDeviceGeneralType type,
-            VmDeviceType device,
-            Map<String, Object> specParams,
-            boolean plugged,
-            Boolean readOnly,
-            String address,
-            Map<String, String> customProp) {
-        VmDevice managedDevice = addManagedDevice(id, type, device, 
specParams, plugged, readOnly, customProp, false);
-        if (StringUtils.isNotBlank(address)){
-            managedDevice.setAddress(address);
-        }
-        return managedDevice;
-    }
-
-    /**
-     * adds managed device to vm_device
+     * Check if the network interface can be plugged.
      *
-     * @param id device id
-     * @param type device type
-     * @param device the device
-     * @param specParams device spec params
-     * @param is_plugged is device plugged-in
-     * @param isReadOnly is device read-only
-     * @param customProp device custom properties
-     * @param isUsingScsiReservation is device using scsi reservation
-     * @return New created VmDevice instance
-     */
-    public static VmDevice addManagedDevice(VmDeviceId id,
-                                            VmDeviceGeneralType type,
-                                            VmDeviceType device,
-                                            Map<String, Object> specParams,
-                                            boolean is_plugged,
-                                            Boolean isReadOnly,
-                                            Map<String, String> customProp,
-                                            boolean isUsingScsiReservation) {
-        VmDevice managedDevice =
-                new VmDevice(id,
-                        type,
-                        device.getName(),
-                        "",
-                        0,
-                        specParams,
-                        true,
-                        is_plugged,
-                        isReadOnly,
-                        "",
-                        customProp,
-                        null,
-                        null,
-                        isUsingScsiReservation);
-        dao.save(managedDevice);
-        // If we add Disk/Interface/CD/Floppy, we have to recalculate boot 
order
-        if (type == VmDeviceGeneralType.DISK || type == 
VmDeviceGeneralType.INTERFACE) {
-            // recalculate boot sequence
-            VmBase vmBase = dbFacade.getVmStaticDao().get(id.getVmId());
-            updateBootOrderInVmDeviceAndStoreToDB(vmBase);
-        }
-        return managedDevice;
-    }
-
-    /**
-     * adds imported VM or Template devices
-     * @param entity
-     */
-    public static <T extends VmBase> void addImportedDevices(T entity, boolean 
isImportAsNewEntity) {
-        if (isImportAsNewEntity) {
-            setNewIdInImportedCollections(entity);
-        }
-        List<VmDevice> vmDeviceToAdd = new ArrayList<>();
-        List<VmDevice> vmDeviceToUpdate = new ArrayList<>();
-        VmDeviceDAO dao = dbFacade.getVmDeviceDao();
-        addImportedDisks(entity, vmDeviceToUpdate);
-        addImportedInterfaces(entity, vmDeviceToUpdate);
-        addOtherDevices(entity, vmDeviceToAdd);
-        dao.saveAll(vmDeviceToAdd);
-        dao.updateAll(vmDeviceToUpdate);
-    }
-
-    public static void setVmDevices(VmBase vmBase) {
-        Map<Guid, VmDevice> vmManagedDeviceMap = new HashMap<>();
-        List<VmDevice> devices = 
dbFacade.getVmDeviceDao().getVmDeviceByVmId(vmBase.getId());
-        
vmBase.setUnmanagedDeviceList(dbFacade.getVmDeviceDao().getUnmanagedDevicesByVmId(vmBase.getId()));
-        for (VmDevice device : devices) {
-            if (device.getIsManaged()) {
-                vmManagedDeviceMap.put(device.getDeviceId(), device);
-            }
-        }
-        vmBase.setManagedDeviceMap(vmManagedDeviceMap);
-    }
-
-    /**
-     * Updates VM boot order in vm device according to the BootSequence enum 
value.
-     * Stores the updated devices in DB
-     * @param vmBase
-     */
-    public static void updateBootOrderInVmDeviceAndStoreToDB(VmBase vmBase) {
-        List<VmDevice> devices = updateBootOrderInVmDevice(vmBase);
-        dao.updateBootOrderInBatch(devices);
-    }
-
-    /**
-     * Updates boot order in all VM devices according to the default boot 
sequence.
+     * The network interface cannot be plugged if another plugged network 
interface has the same MAC address.
      *
-     * @param vmBase
-     * @return the updated VmDevice list
-     */
-    public static List<VmDevice> updateBootOrderInVmDevice(VmBase vmBase) {
-        if (vmBase instanceof VmStatic) {
-            //Returns the devices sorted in ascending order
-            List<VmDevice> devices = dao.getVmDeviceByVmId(vmBase.getId());
-            // reset current boot order
-            for (VmDevice device: devices) {
-                device.setBootOrder(0);
-            }
-            VM vm = dbFacade.getVmDao().get(vmBase.getId());
-            VmHandler.updateDisksForVm(vm, 
dbFacade.getDiskDao().getAllForVm(vm.getId()));
-            VmHandler.updateNetworkInterfacesFromDb(vm);
-            boolean isOldCluster = 
VmDeviceCommonUtils.isOldClusterVersion(vm.getVdsGroupCompatibilityVersion());
-            VmDeviceCommonUtils.updateVmDevicesBootOrder(vm, devices, 
isOldCluster);
-            return devices;
-        }
-        return Collections.emptyList();
-    }
-
-    /**
-     * updates existing VM CD ROM in vm_device
-     *
-     * @param oldVmBase
-     * @param newVmBase
-     *            NOTE : Only one CD is currently supported.
-     */
-    private static void updateCdInVmDevice(VmBase oldVmBase, VmBase newVmBase) 
{
-        List<VmDevice> cdList =
-                
dbFacade.getVmDeviceDao().getVmDeviceByVmIdTypeAndDevice(oldVmBase.getId(),
-                        VmDeviceGeneralType.DISK,
-                        VmDeviceType.CDROM.getName());
-        if (cdList.size() > 0){ // this is done only for safety, each VM must 
have at least an Empty CD
-            VmDevice cd = cdList.get(0); // only one managed CD is currently 
supported.
-            cd.getSpecParams()
-                    .put(VdsProperties.Path, (newVmBase.getIsoPath() == null) 
? "" : newVmBase.getIsoPath());
-            dao.update(cd);
-        }
-    }
-
-    /**
-     * Updates new/existing VM USB slots in vm device
-     * Currently assuming the number of slots is between 0 and 
SLOTS_PER_CONTROLLER, i.e., no more than one controller
-     * @param oldVm
-     * @param newVm
-     */
-    private static void updateUSBSlots(VmBase oldVm, VmBase newVm) {
-        UsbPolicy oldUsbPolicy = UsbPolicy.DISABLED;
-        UsbPolicy newUsbPolicy = newVm.getUsbPolicy();
-        int currentNumberOfSlots = 0;
-
-        if (oldVm != null) {
-            oldUsbPolicy = oldVm.getUsbPolicy();
-            currentNumberOfSlots = getUsbRedirectDevices(oldVm).size();
-        }
-
-        final int usbSlots = Config.<Integer> 
getValue(ConfigValues.NumberOfUSBSlots);
-
-        // We add USB slots in case support doesn't exist in the oldVm 
configuration, but exists in the new one
-        if (!oldUsbPolicy.equals(UsbPolicy.ENABLED_NATIVE) && 
newUsbPolicy.equals(UsbPolicy.ENABLED_NATIVE)) {
-            if (usbSlots > 0) {
-                removeUsbControllers(newVm);
-                addUsbControllers(newVm, 
getNeededNumberOfUsbControllers(usbSlots));
-                addUsbSlots(newVm, usbSlots);
-            }
-        }
-        // Remove USB slots and controllers in case we are either in disabled 
policy or legacy one
-        else if (newUsbPolicy.equals(UsbPolicy.DISABLED) || 
newUsbPolicy.equals(UsbPolicy.ENABLED_LEGACY)) {
-            removeUsbControllers(newVm);
-            removeUsbSlots(newVm);
-        // if the USB policy is enabled (and was enabled before), we need to 
update the number of slots
-        } else if (newUsbPolicy.equals(UsbPolicy.ENABLED_NATIVE)) {
-            if (currentNumberOfSlots < usbSlots) {
-                // Add slots
-                if (currentNumberOfSlots == 0) {
-                    addUsbControllers(newVm, 
getNeededNumberOfUsbControllers(usbSlots));
-                }
-                addUsbSlots(newVm, usbSlots - currentNumberOfSlots);
-            } else if (currentNumberOfSlots > usbSlots) {
-                // Remove slots
-                removeUsbSlots(newVm, currentNumberOfSlots - usbSlots);
-                // Remove controllers
-                if (usbSlots == 0) {
-                    removeUsbControllers(newVm);
-                }
-            }
-        }
-    }
-
-    private static int getNeededNumberOfUsbControllers(int numberOfSlots) {
-        int numOfcontrollers = numberOfSlots / SLOTS_PER_CONTROLLER;
-        // Need to add another controller in case mod result is not 0
-        if (numberOfSlots % SLOTS_PER_CONTROLLER != 0) {
-            numOfcontrollers++;
-        }
-        return numOfcontrollers;
-    }
-    /**
-     * Adds imported disks to VM devices
-     * @param entity
-     */
-    private static <T extends VmBase> void addImportedDisks(T entity, 
List<VmDevice> vmDeviceToUpdate) {
-        final Guid id = entity.getId();
-        for (BaseDisk disk : getDisks(entity.getImages())) {
-            Guid deviceId = disk.getId();
-            VmDevice vmDevice =
-                    addManagedDevice(new VmDeviceId(deviceId, id),
-                            VmDeviceGeneralType.DISK,
-                            VmDeviceType.DISK,
-                            null,
-                            true,
-                            false,
-                            getAddress(entity, id),
-                            null);
-            updateVmDevice(entity, vmDevice, deviceId, vmDeviceToUpdate);
-        }
-    }
-
-    /**
-     * Gets a set of disks from disk images. For VM with snapshots, several 
DiskImage elements may contain the same Disk
-     *
-     * @param diskImages
-     *            collection DiskImage objects to get a set of Disks from
-     * @return set of disks of the images collection
-     */
-    protected static Set<BaseDisk> getDisks(Collection<DiskImage> diskImages) {
-        Map<Guid, BaseDisk> diskMap = new HashMap<>();
-        for (Disk diskImage : diskImages) {
-            diskMap.put(diskImage.getId(), diskImage);
-        }
-        return new HashSet<>(diskMap.values());
-    }
-
-    private static <T extends VmBase> void updateVmDevice(T entity,
-            VmDevice vmDevice,
-            Guid deviceId,
-            List<VmDevice> vmDeviceToUpdate) {
-        // update device information only if ovf support devices - from 3.1
-        Version ovfVer = new Version(entity.getOvfVersion());
-        if (!VmDeviceCommonUtils.isOldClusterVersion(ovfVer)) {
-            VmDevice exportedDevice = 
entity.getManagedDeviceMap().get(deviceId);
-            if (exportedDevice != null) {
-                vmDevice.setAddress(exportedDevice.getAddress());
-                vmDevice.setBootOrder(exportedDevice.getBootOrder());
-                vmDevice.setIsPlugged(exportedDevice.getIsPlugged());
-                vmDevice.setIsReadOnly(exportedDevice.getIsReadOnly());
-                vmDeviceToUpdate.add(vmDevice);
-            }
-        }
-    }
-
-    /**
-     * If another plugged network interface has the same MAC address, return 
false, otherwise returns true
-     *
-     * @param iface
-     *            the network interface to check if can be plugged
+     * @param iface the network interface to be checked
+     * @return true if the network interface can be plugged, false otherwise
      */
     private static boolean canPlugInterface(VmNic iface) {
         VmInterfaceManager vmIfaceManager = new VmInterfaceManager();
@@ -853,139 +651,40 @@
         }
     }
 
-    /**
-     * Adds imported interfaces to VM devices
-     * @param entity
+    /*
+     * USB controller
      */
-    private static <T extends VmBase> void addImportedInterfaces(T entity, 
List<VmDevice> vmDeviceToUpdate) {
-        final Guid id = entity.getId();
-        for (VmNic iface : entity.getInterfaces()) {
-            Guid deviceId = iface.getId();
-            VmDevice vmDevice =
-                    addManagedDevice(new VmDeviceId(deviceId, id),
-                            VmDeviceGeneralType.INTERFACE,
-                            iface.isPassthrough() ? VmDeviceType.HOST_DEVICE : 
VmDeviceType.BRIDGE,
-                            null,
-                            true,
-                            false,
-                            getAddress(entity, id),
-                            null);
-
-            VmDevice exportedDevice = 
entity.getManagedDeviceMap().get(deviceId);
-            if (exportedDevice == null) {
-                entity.getManagedDeviceMap().put(deviceId, vmDevice);
-                exportedDevice = vmDevice;
-            }
-
-            exportedDevice.setIsPlugged(exportedDevice.getIsPlugged() && 
canPlugInterface(iface));
-            updateVmDevice(entity, vmDevice, deviceId, vmDeviceToUpdate);
-        }
-    }
-
-    private static <T extends VmBase> String getAddress(T entity, final Guid 
id) {
-        VmDevice device = entity.getManagedDeviceMap().get(id);
-        if (device != null)
-            return device.getAddress();
-        else
-            return StringUtils.EMPTY;
-    }
 
     /**
-     * Adds Special managed devices (monitor/CDROM ) and unmanaged devices
+     * Add given number of USB controllers to the VM.
      *
-     * @param <T>
-     * @param entity
+     * @param vmId
+     * @param numberOfControllers
      */
-    private static <T extends VmBase> void addOtherDevices(T entity, 
List<VmDevice> vmDeviceToAdd) {
-        boolean hasCD = false;
-        boolean hasSoundCard = false;
-        for (VmDevice vmDevice : entity.getManagedDeviceMap().values()) {
-            if (isDiskOrInterface(vmDevice)) {
-                continue; // skip disks/interfaces that were added separately.
-            }
-            vmDevice.setIsManaged(true);
-            if (vmDevice.getType() == VmDeviceGeneralType.VIDEO) {
-                vmDevice.setSpecParams(getMemExpr(entity.getNumOfMonitors(), 
entity.getSingleQxlPci()));
-            }
-            if (vmDevice.getDevice().equals(VmDeviceType.CDROM.getName())){
-                hasCD = true;
-            }
-            if (VmDeviceCommonUtils.isSound(vmDevice)) {
-                hasSoundCard = true;
-            }
-            vmDeviceToAdd.add(vmDevice);
-        }
-        if (!hasCD) { // add an empty CD
-            addEmptyCD(entity.getId());
-        }
-
-        // add sound card for desktops imported from old versions only, since 
devices didnt exist
-        Version ovfVer = new Version(entity.getOvfVersion());
-        if (!hasSoundCard && VmDeviceCommonUtils.isOldClusterVersion(ovfVer) 
&& entity.getVmType() == VmType.Desktop) {
-            addSoundCard(entity);
-        }
-        for (VmDevice vmDevice : entity.getUnmanagedDeviceList()) {
-            vmDeviceToAdd.add(vmDevice);
-        }
-    }
-
-    /**
-     * gets Monitor memory expression
-     *
-     * @param numOfMonitors
-     *            Number of monitors
-     * @return
-     */
-    private static Map<String, Object> getMemExpr(int numOfMonitors, boolean 
singleQxlPci) {
-        int heads = singleQxlPci ? numOfMonitors : 1;
-        Map<String, Object> specParams = new HashMap<>();
-        specParams.put(HEADS, String.valueOf(heads));
-        specParams.put(VRAM, VmDeviceCommonUtils.singlePciVRamByHeads(heads));
-        if (singleQxlPci) {
-            specParams.put(RAM, 
VmDeviceCommonUtils.singlePciRamByHeads(heads));
-        }
-        return specParams;
-    }
-
-    private static void addUsbSlots(VmBase vm, int numOfSlots) {
-        for (int index = 1; index <= numOfSlots; index++) {
-            VmDeviceUtils.addManagedDevice(new VmDeviceId(Guid.newGuid(), 
vm.getId()),
-                    VmDeviceGeneralType.REDIR,
-                    VmDeviceType.SPICEVMC,
-                    getUsbSlotSpecParams(),
-                    true,
-                    false,
-                    null,
-                    false);
-        }
-    }
-
-    private static void addUsbControllers(VmBase vm, int numOfControllers) {
+    public static void addUsbControllers(Guid vmId, int numberOfControllers) {
         // For each controller we need to create one EHCI and companion UHCI 
controllers
-        for (int index = 0; index < numOfControllers; index++) {
-            VmDeviceUtils.addManagedDevice(new VmDeviceId(Guid.newGuid(), 
vm.getId()),
+        for (int index = 0; index < numberOfControllers; index++) {
+            addManagedDevice(
+                    new VmDeviceId(Guid.newGuid(), vmId),
                     VmDeviceGeneralType.CONTROLLER,
                     VmDeviceType.USB,
                     getUsbControllerSpecParams(EHCI_MODEL, 1, index),
                     true,
-                    false,
-                    null,
                     false);
             for (int companionIndex = 1; companionIndex <= 
COMPANION_USB_CONTROLLERS; companionIndex++) {
-                VmDeviceUtils.addManagedDevice(new VmDeviceId(Guid.newGuid(), 
vm.getId()),
+                addManagedDevice(
+                        new VmDeviceId(Guid.newGuid(), vmId),
                         VmDeviceGeneralType.CONTROLLER,
                         VmDeviceType.USB,
                         getUsbControllerSpecParams(UHCI_MODEL, companionIndex, 
index),
                         true,
-                        false,
-                        null,
                         false);
             }
         }
     }
 
     /**
-     * gets USB controller
+     * Returns USB controller spec params.
      *
      * @return
      */
@@ -997,33 +696,504 @@
     }
 
     /**
-     * gets USB slot specParams
+     * Get list of all USB controllers in the VM.
      *
+     * @param vmId
      * @return
      */
-    private static Map<String, Object> getUsbSlotSpecParams() {
-        Map<String, Object> specParams = new HashMap<>();
-        return specParams;
+    public static List<VmDevice> getUsbControllers(Guid vmId) {
+        return dao.getVmDeviceByVmIdTypeAndDevice(
+                vmId,
+                VmDeviceGeneralType.CONTROLLER,
+                VmDeviceType.USB.getName());
     }
 
-    private static List<VmDevice> getUsbRedirectDevices(VmBase vm) {
-        List<VmDevice> list = dao.getVmDeviceByVmIdTypeAndDevice(vm.getId(), 
VmDeviceGeneralType.REDIR, VmDeviceType.SPICEVMC.getName());
-
-        return list;
+    /**
+     * Remove all USB controllers from the VM.
+     *
+     * @param vmId
+     */
+    public static void removeUsbControllers(Guid vmId) {
+        removeVmDevices(getUsbControllers(vmId));
     }
-    private static void removeUsbSlots(VmBase vm) {
-        List<VmDevice> list = getUsbRedirectDevices(vm);
-        for(VmDevice vmDevice : list) {
-            dao.remove(vmDevice.getId());
+
+    /*
+     * USB slot
+     */
+
+    /**
+     * Update USB slots in the new VM, if USB policy of the new VM differs 
from one of the old VM.
+     *
+     * @param oldVm
+     * @param newVm
+     */
+    private static void updateUsbSlots(VmBase oldVm, VmBase newVm) {
+        UsbPolicy oldUsbPolicy = UsbPolicy.DISABLED;
+        UsbPolicy newUsbPolicy = newVm.getUsbPolicy();
+        int currentNumberOfSlots = 0;
+
+        if (oldVm != null) {
+            oldUsbPolicy = oldVm.getUsbPolicy();
+            currentNumberOfSlots = getUsbSlots(oldVm.getId()).size();
+        }
+
+        final int usbSlots = Config.<Integer> 
getValue(ConfigValues.NumberOfUSBSlots);
+
+        // We add USB slots if they are disabled in oldVm configuration, but 
enabled in newVm
+        if (!oldUsbPolicy.equals(UsbPolicy.ENABLED_NATIVE) && 
newUsbPolicy.equals(UsbPolicy.ENABLED_NATIVE)) {
+            if (usbSlots > 0) {
+                removeUsbControllers(newVm.getId());
+                addUsbControllers(newVm.getId(), 
getNeededNumberOfUsbControllers(usbSlots));
+                addUsbSlots(newVm.getId(), usbSlots);
+            }
+        // Remove USB slots and controllers if the policy is to disable or 
legacy one
+        } else if (newUsbPolicy.equals(UsbPolicy.DISABLED) || 
newUsbPolicy.equals(UsbPolicy.ENABLED_LEGACY)) {
+            removeUsbControllers(newVm.getId());
+            removeUsbSlots(newVm.getId());
+        // If the USB policy is to enable (and was enabled before), we need to 
update the number of slots
+        } else if (newUsbPolicy.equals(UsbPolicy.ENABLED_NATIVE)) {
+            if (currentNumberOfSlots < usbSlots) {
+                // Add slots and controllers
+                if (currentNumberOfSlots == 0) {
+                    addUsbControllers(newVm.getId(), 
getNeededNumberOfUsbControllers(usbSlots));
+                }
+                addUsbSlots(newVm.getId(), usbSlots - currentNumberOfSlots);
+            } else if (currentNumberOfSlots > usbSlots) {
+                // Remove slots and controllers
+                removeUsbSlots(newVm.getId(), currentNumberOfSlots - usbSlots);
+                if (usbSlots == 0) {
+                    removeUsbControllers(newVm.getId());
+                }
+            }
         }
     }
 
-    private static void removeUsbSlots(VmBase vm, int numberOfSlotsToRemove) {
-        List<VmDevice> list = getUsbRedirectDevices(vm);
-        removeNumberOfDevices(list, numberOfSlotsToRemove);
+    /**
+     * Returns number of USB controllers that needs to be created for the 
given number of USB slots.
+     *
+     * @param numberOfSlots
+     * @return
+     */
+    private static int getNeededNumberOfUsbControllers(int numberOfSlots) {
+        int numberOfControllers = numberOfSlots / SLOTS_PER_CONTROLLER;
+        // Need to add another controller if we have a remainder
+        if (numberOfSlots % SLOTS_PER_CONTROLLER != 0) {
+            numberOfControllers++;
+        }
+        return numberOfControllers;
     }
 
-    private static void removeNumberOfDevices(List<VmDevice> devices, int 
numberOfDevicesToRemove) {
+    /**
+     * Add given number of USB slots to the VM
+     *
+     * @param vmId
+     * @param numberOfSlots
+     */
+    public static void addUsbSlots(Guid vmId, int numberOfSlots) {
+        for (int index = 1; index <= numberOfSlots; index++) {
+            addManagedDevice(
+                    new VmDeviceId(Guid.newGuid(), vmId),
+                    VmDeviceGeneralType.REDIR,
+                    VmDeviceType.SPICEVMC,
+                    EMPTY_SPEC_PARAMS,
+                    true,
+                    false);
+        }
+    }
+
+    /**
+     * Get list of all USB slots in the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static List<VmDevice> getUsbSlots(Guid vmId) {
+        return dao.getVmDeviceByVmIdTypeAndDevice(
+                vmId,
+                VmDeviceGeneralType.REDIR,
+                VmDeviceType.SPICEVMC.getName());
+    }
+
+    /**
+     * Remove all USB slots from the VM.
+     *
+     * @param vmId
+     */
+    public static void removeUsbSlots(Guid vmId) {
+        removeVmDevices(getUsbSlots(vmId));
+    }
+
+    /**
+     * Remove the given number of USB slots from the VM.
+     *
+     * @param vmId
+     * @param numberOfSlotsToRemove
+     */
+    public static void removeUsbSlots(Guid vmId, int numberOfSlotsToRemove) {
+        removeVmDevices(getUsbSlots(vmId), numberOfSlotsToRemove);
+    }
+
+    /*
+     * Memory balloon device
+     */
+
+    /**
+     * Enable/disable memory balloon device in the VM.
+     *
+     * @param vmId
+     * @param isBalloonEnabled    true/false to enable/disable device 
respectively, null to leave it untouched
+     */
+    public static void updateMemoryBalloon(Guid vmId, Boolean 
isBalloonEnabled) {
+        if (isBalloonEnabled == null) {
+            return; //we don't want to update the device
+        }
+
+        if (isBalloonEnabled) {
+            if (!hasMemoryBalloon(vmId)) {
+                addMemoryBalloon(vmId);
+            }
+        } else {
+            removeMemoryBalloons(vmId);
+        }
+    }
+
+    /**
+     * Add new memory balloon device to the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static VmDevice addMemoryBalloon(Guid vmId) {
+        return addManagedDevice(
+                new VmDeviceId(Guid.newGuid(), vmId),
+                VmDeviceGeneralType.BALLOON,
+                VmDeviceType.MEMBALLOON,
+                getMemoryBalloonSpecParams(),
+                true,
+                true);
+    }
+
+    private static Map<String, Object> getMemoryBalloonSpecParams() {
+        return Collections.<String, Object> singletonMap(VdsProperties.Model, 
VdsProperties.Virtio);
+    }
+
+    /**
+     * Get list of all memory balloon devices in the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static List<VmDevice> getMemoryBalloons(Guid vmId) {
+        return dao.getVmDeviceByVmIdAndType(vmId, VmDeviceGeneralType.BALLOON);
+    }
+
+    /**
+     * Remove all memory balloon devices from the VM.
+     *
+     * @param vmId
+     */
+    public static void removeMemoryBalloons(Guid vmId) {
+        removeVmDevices(getMemoryBalloons(vmId), 1);
+    }
+
+    /**
+     * Check if the VM has a memory balloon device.
+     *
+     * @param vmId
+     * @return
+     */
+    public static boolean hasMemoryBalloon(Guid vmId) {
+        return dao.isMemBalloonEnabled(vmId);
+    }
+
+    /*
+     * RNG device
+     */
+
+    /**
+     * Get list of all RNG devices in the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static List<VmDevice> getRngDevices(Guid vmId) {
+        return dao.getVmDeviceByVmIdAndType(vmId, VmDeviceGeneralType.RNG);
+    }
+
+    /**
+     * Check if the VM has an RNG device.
+     *
+     * @param vmId
+     * @return
+     */
+    public static boolean hasRngDevice(Guid vmId) {
+        return !getRngDevices(vmId).isEmpty();
+    }
+
+    /*
+     * Graphics device
+     */
+
+    /**
+     * Get list of graphics device types present in the VM.
+     *
+     * @param entityId
+     * @return
+     */
+    public static List<GraphicsType> getGraphicsTypesOfEntity(Guid entityId) {
+        List<GraphicsType> result = new ArrayList<>();
+
+        if (entityId != null) {
+            List<VmDevice> devices = getGraphicsDevices(entityId);
+            if (devices != null) {
+                for (VmDevice device : devices) {
+                    result.add(GraphicsType.fromString(device.getDevice()));
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Get list of all graphics devices in the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static List<VmDevice> getGraphicsDevices(Guid vmId) {
+        return dao.getVmDeviceByVmIdAndType(vmId, 
VmDeviceGeneralType.GRAPHICS);
+    }
+
+    /**
+     * Get list of graphics devices of the given type present in the VM.
+     *
+     * @param vmId
+     * @param type
+     * @return
+     */
+    public static List<VmDevice> getGraphicsDevices(Guid vmId, GraphicsType 
type) {
+        return dao.getVmDeviceByVmIdTypeAndDevice(
+                vmId,
+                VmDeviceGeneralType.GRAPHICS,
+                type.name().toLowerCase());
+    }
+
+    /**
+     * Check if the VM has a graphics device of the given type.
+     *
+     * @param vmId
+     * @param type
+     * @return
+     */
+    public static boolean hasGraphicsDevice(Guid vmId, GraphicsType type) {
+        return !getGraphicsDevices(vmId, type).isEmpty();
+    }
+
+    /*
+     * Watchdog
+     */
+
+    /**
+     * Get list of all watchdogs in the VM.
+     *
+     * @param vmId
+     * @return
+     */
+    public static List<VmDevice> getWatchdogs(Guid vmId) {
+        return dao.getVmDeviceByVmIdAndType(vmId, 
VmDeviceGeneralType.WATCHDOG);
+    }
+
+    /**
+     * Check if the VM has a watchdog.
+     *
+     * @param vmId
+     * @return
+     */
+    public static boolean hasWatchdog(Guid vmId) {
+        return !getWatchdogs(vmId).isEmpty();
+    }
+
+    /*
+     * Disk device
+     */
+
+    /**
+     * Copy disk devices from the given list of devices to the destination VM. 
Device ids are changed in accordance
+     * with the mapping given.
+     *
+     * @param dstId
+     * @param srcDevices
+     * @param srcDeviceIdToDstDeviceIdMapping
+     */
+    public static void copyDiskDevices(Guid dstId,
+                                       List<VmDevice> srcDevices,
+                                       Map<Guid, Guid> 
srcDeviceIdToDstDeviceIdMapping) {
+        for (VmDevice device : srcDevices) {
+            if (VmDeviceType.DISK.getName().equals(device.getDevice())) {
+                if 
(srcDeviceIdToDstDeviceIdMapping.containsKey(device.getDeviceId())) {
+                    Guid dstDeviceId = 
srcDeviceIdToDstDeviceIdMapping.get(device.getDeviceId());
+                    device.setId(new VmDeviceId(dstDeviceId, dstId));
+                    device.setSpecParams(EMPTY_SPEC_PARAMS);
+                    dao.save(device);
+                }
+            }
+        }
+    }
+
+    /**
+     * Add a new disk device to the VM.
+     *
+     * @param vmId
+     * @param deviceId
+     * @return
+     */
+    public static VmDevice addDiskDevice(Guid vmId, Guid deviceId) {
+        return addDiskDevice(vmId, deviceId, true, false, "", false);
+    }
+
+    /**
+     * Add a new disk device to the VM.
+     *
+     * @param vmId
+     * @param deviceId
+     * @param address
+     * @return
+     */
+    public static VmDevice addDiskDevice(Guid vmId, Guid deviceId, String 
address) {
+        return addDiskDevice(vmId, deviceId, true, false, address, false);
+    }
+
+    /**
+     * Add a new disk device to the VM.
+     *
+     * @param vmId
+     * @param deviceId
+     * @param isPlugged
+     * @param isReadOnly
+     * @param isUsingScsiReservation
+     * @return
+     */
+    public static VmDevice addDiskDevice(Guid vmId, Guid deviceId, Boolean 
isPlugged, Boolean isReadOnly,
+                                         boolean isUsingScsiReservation) {
+        return addDiskDevice(vmId, deviceId, isPlugged, isReadOnly, "", 
isUsingScsiReservation);
+    }
+
+    /**
+     * Add a new disk device to the VM.
+     *
+     * @param vmId
+     * @param deviceId
+     * @param isPlugged
+     * @param isReadOnly
+     * @param address
+     * @param isUsingScsiReservation
+     * @return
+     */
+    public static VmDevice addDiskDevice(Guid vmId, Guid deviceId, Boolean 
isPlugged, Boolean isReadOnly,
+                                         String address, boolean 
isUsingScsiReservation) {
+        return addManagedDevice(
+                new VmDeviceId(deviceId, vmId),
+                VmDeviceGeneralType.DISK,
+                VmDeviceType.DISK,
+                EMPTY_SPEC_PARAMS,
+                isPlugged,
+                isReadOnly,
+                address,
+                null,
+                isUsingScsiReservation);
+    }
+
+    /**
+     * Gets a set of disks from disk images. For VM with snapshots, several 
DiskImage elements may contain
+     * the same Disk.
+     *
+     * @param diskImages collection of DiskImage objects to get the set of 
Disks from
+     * @return the resulting set of disks
+     */
+    public static Set<BaseDisk> getDisks(Collection<DiskImage> diskImages) {
+        Map<Guid, BaseDisk> diskMap = new HashMap<>();
+        for (Disk diskImage : diskImages) {
+            diskMap.put(diskImage.getId(), diskImage);
+        }
+        return new HashSet<>(diskMap.values());
+    }
+
+    /*
+     * Boot order
+     */
+
+    /**
+     * If default boot sequence differs in the old and new VMs, updates boot 
order in all devices in the new VM
+     * according to the new default boot sequence. Stores the updated devices 
in the DB.
+     *
+     * @param oldVmBase
+     * @param newVmBase
+     */
+    private static void updateBootOrder(VmBase oldVmBase, VmBase newVmBase) {
+        if (oldVmBase.getDefaultBootSequence() != 
newVmBase.getDefaultBootSequence()) {
+            updateBootOrder(newVmBase.getId());
+        }
+    }
+
+    /**
+     * Updates boot order in all devices in the VM according to the default 
boot sequence.
+     * Stores the updated devices in the DB.
+     *
+     * @param vmId
+     */
+    public static void updateBootOrder(Guid vmId) {
+        // Returns the devices sorted in ascending order
+        List<VmDevice> devices = dao.getVmDeviceByVmId(vmId);
+        // Reset current boot order
+        for (VmDevice device: devices) {
+            device.setBootOrder(0);
+        }
+        VM vm = dbFacade.getVmDao().get(vmId);
+        VmHandler.updateDisksForVm(vm, 
dbFacade.getDiskDao().getAllForVm(vmId));
+        VmHandler.updateNetworkInterfacesFromDb(vm);
+        boolean isOldCluster = 
VmDeviceCommonUtils.isOldClusterVersion(vm.getVdsGroupCompatibilityVersion());
+        VmDeviceCommonUtils.updateVmDevicesBootOrder(vm, devices, 
isOldCluster);
+        dao.updateBootOrderInBatch(devices);
+    }
+
+    /*
+     * Generic device methods
+     */
+
+    /**
+     * Get address of the given managed device in the VM. If the device does 
not exist, returns empty string.
+     *
+     * @param vmBase
+     * @param deviceId
+     * @return
+     */
+    public static String getVmDeviceAddress(VmBase vmBase, final Guid 
deviceId) {
+        VmDevice device = vmBase.getManagedDeviceMap().get(deviceId);
+        if (device != null)
+            return device.getAddress();
+        else
+            return StringUtils.EMPTY;
+    }
+
+    /**
+     * Remove all devices in the list.
+     *
+     * @param devices
+     */
+    public static void removeVmDevices(List<VmDevice> devices) {
+        for (VmDevice device : devices) {
+            dao.remove(device.getId());
+        }
+    }
+
+    /**
+     * Remove the given number of devices starting from the end of the list.
+     *
+     * @param devices
+     * @param numberOfDevicesToRemove
+     */
+    public static void removeVmDevices(List<VmDevice> devices, int 
numberOfDevicesToRemove) {
         int size = devices.size();
         for (int index = 1; index <= numberOfDevicesToRemove; index++) {
             if (size >= index) {
@@ -1032,136 +1202,528 @@
         }
     }
 
-    private static void removeUsbControllers(VmBase vm) {
-        List<VmDevice> list = dao.getVmDeviceByVmIdTypeAndDevice(vm.getId(), 
VmDeviceGeneralType.CONTROLLER, VmDeviceType.USB.getName());
-        for(VmDevice vmDevice : list) {
-            dao.remove(vmDevice.getId());
+    /**
+     * Read devices from the DB and set managed and unmanaged device lists in 
VmBase.
+     *
+     * @param vmBase
+     */
+    public static void setVmDevices(VmBase vmBase) {
+        List<VmDevice> devices = dao.getVmDeviceByVmId(vmBase.getId());
+        
vmBase.setUnmanagedDeviceList(dao.getUnmanagedDevicesByVmId(vmBase.getId()));
+        Map<Guid, VmDevice> vmManagedDeviceMap = new HashMap<>();
+        for (VmDevice device : devices) {
+            if (device.getIsManaged()) {
+                vmManagedDeviceMap.put(device.getDeviceId(), device);
+            }
         }
+        vmBase.setManagedDeviceMap(vmManagedDeviceMap);
     }
 
     /**
-     * adds an empty CD in the case that we have no CDROM inside the device
-     * @param dstId
+     * Check if the given device is disk or network interface device.
+     *
+     * @param vmDevice
+     * @return
      */
-    private static void addEmptyCD(Guid dstId) {
-        VmDeviceUtils.addManagedDevice(new VmDeviceId(Guid.newGuid(), dstId),
-                VmDeviceGeneralType.DISK,
-                VmDeviceType.CDROM,
-                Collections.<String, Object>singletonMap(VdsProperties.Path, 
""),
-                true,
-                true,
-                null,
-                false);
-    }
-
-    private static void updateMemoryBalloon(VmBase newVm, boolean 
shouldHaveBalloon) {
-        updateMemoryBalloon(newVm.getId(), shouldHaveBalloon);
-
-    }
-
-    public static void updateMemoryBalloon(Guid id, boolean shouldHaveBalloon) 
{
-        boolean hasBalloon = dao.isMemBalloonEnabled(id);
-        if (hasBalloon != shouldHaveBalloon) {
-            if (!hasBalloon && shouldHaveBalloon) {
-                addEmptyMemoryBalloon(id);
-            }
-            else {
-                // remove the balloon device
-                List<VmDevice> list = DbFacade
-                        .getInstance()
-                        .getVmDeviceDao()
-                        .getVmDeviceByVmIdAndType(id,
-                                VmDeviceGeneralType.BALLOON);
-                removeNumberOfDevices(list, 1);
-            }
-        }
-    }
-
-    private static void addEmptyMemoryBalloon(Guid id) {
-        addManagedDevice(new VmDeviceId(Guid.newGuid(), id),
-                VmDeviceGeneralType.BALLOON,
-                VmDeviceType.MEMBALLOON,
-                Collections.<String, Object>singletonMap(VdsProperties.Model, 
VdsProperties.Virtio),
-                true,
-                true,
-                null,
-                false);
-    }
-
-    private static void setNewIdInImportedCollections(VmBase entity) {
-        for (VmDevice managedDevice : entity.getManagedDeviceMap().values()){
-            if (!isDiskOrInterface(managedDevice)) {
-                managedDevice.setId(new VmDeviceId(Guid.newGuid(), 
entity.getId()));
-            }
-        }
-        for (VmDevice unMnagedDevice : entity.getUnmanagedDeviceList()) {
-            unMnagedDevice.setId(new VmDeviceId(Guid.newGuid(), 
entity.getId()));
-        }
-    }
-
     private static boolean isDiskOrInterface(VmDevice vmDevice) {
         return VmDeviceCommonUtils.isDisk(vmDevice) || 
VmDeviceCommonUtils.isNetwork(vmDevice);
     }
 
-    private static boolean isBalloonEnabled(VmManagementParametersBase params) 
{
-        Boolean balloonEnabled = params.isBalloonEnabled();
-        return (balloonEnabled != null) ? balloonEnabled : 
isBalloonEnabled(params.getVmStaticData().getId());
-    }
+    /**
+     * Update the VM devices according to the changes made.
+     *
+     * @param params    changes made
+     * @param oldVm     previous state of the VM being modified
+     */
+    public static void updateVmDevices(VmManagementParametersBase params, VM 
oldVm) {
+        VmBase oldVmBase = oldVm.getStaticData();
+        VmBase newVmBase = params.getVmStaticData();
+        if (newVmBase == null) {
+            return;
+        }
 
-    public static boolean isVirtioScsiControllerAttached(Guid vmId) {
-        return !getVirtioScsiControllers(vmId).isEmpty();
-    }
-
-    public static boolean hasWatchdog(Guid vmId) {
-        return !getWatchdogs(vmId).isEmpty();
-    }
-
-    public static boolean isBalloonEnabled(Guid vmId) {
-        return !getBalloonDevices(vmId).isEmpty();
-    }
-
-    public static boolean isSoundDeviceEnabled(Guid vmId) {
-        return !getSoundDevices(vmId).isEmpty();
-    }
-
-    public static boolean hasVmRngDevice(Guid vmId) {
-        return !dbFacade.getVmDeviceDao().getVmDeviceByVmIdAndType(vmId,
-                VmDeviceGeneralType.RNG).isEmpty();
-    }
-
-    public static boolean hasVmGraphicsDeviceOfType(Guid vmId, GraphicsType 
type) {
-        return !dbFacade.getVmDeviceDao().getVmDeviceByVmIdTypeAndDevice(vmId,
-                VmDeviceGeneralType.GRAPHICS,
-                type.name().toLowerCase()).isEmpty();
-    }
-
-
-    public static List<VmDevice> getSoundDevices(Guid vmId) {
-        return dbFacade.getVmDeviceDao().getVmDeviceByVmIdAndType(vmId,
-                VmDeviceGeneralType.SOUND);
-    }
-
-    public static List<VmDevice> getBalloonDevices(Guid vmId) {
-        return dbFacade.getVmDeviceDao().getVmDeviceByVmIdAndType(vmId,
-                VmDeviceGeneralType.BALLOON);
-    }
-
-    public static List<VmDevice> getWatchdogs(Guid vmId) {
-        return dbFacade.getVmDeviceDao().getVmDeviceByVmIdAndType(vmId,
-                VmDeviceGeneralType.WATCHDOG);
-    }
-
-    public static List<VmDevice> getVirtioScsiControllers(Guid vmId) {
-        return getVirtioScsiControllers(vmId, null, false);
-    }
-
-    public static List<VmDevice> getVirtioScsiControllers(Guid vmId, Guid 
userID, boolean isFiltered) {
-        return dao.getVmDeviceByVmIdTypeAndDevice(
-                vmId, VmDeviceGeneralType.CONTROLLER, 
VmDeviceType.VIRTIOSCSI.getName(), userID, isFiltered);
+        updateCdPath(oldVmBase, newVmBase);
+        updateBootOrder(oldVmBase, newVmBase);
+        updateVideoDevices(oldVmBase, newVmBase);
+        updateUsbSlots(oldVmBase, newVmBase);
+        updateMemoryBalloon(newVmBase.getId(), params.isBalloonEnabled());
+        updateSoundDevice(oldVmBase, newVmBase, 
oldVm.getVdsGroupCompatibilityVersion(),
+                params.isSoundDeviceEnabled());
+        updateSmartcardDevice(oldVm, newVmBase);
+        updateConsoleDevice(newVmBase.getId(), params.isConsoleEnabled());
+        updateVirtioScsiController(newVmBase.getId(), 
params.isVirtioScsiEnabled());
     }
 
     /**
-     * Determines whether a VM device change has been request by the user.
+     * Update the VM devices according to changes made in configuration.
+     *
+     * This method is executed before running the VM.
+     */
+    public static void updateVmDevicesOnRun(VmBase vmBase) {
+        if (vmBase != null) {
+            updateUsbSlots(vmBase, vmBase);
+        }
+    }
+
+    /**
+     * Copy devices from the given VmDevice list to the destination VM/VmBase.
+     *
+     * @param srcId
+     * @param dstId
+     * @param dstVm
+     * @param dstVmBase
+     * @param dstIsVm
+     * @param srcDevices
+     * @param srcDeviceIdToDstDeviceIdMapping
+     * @param isSoundEnabled
+     * @param isConsoleEnabled
+     * @param isVirtioScsiEnabled
+     * @param isBalloonEnabled
+     * @param graphicsToSkip
+     * @param copySnapshotDevices
+     */
+    public static void copyVmDevices(Guid srcId,
+                                     Guid dstId,
+                                     VM dstVm,
+                                     VmBase dstVmBase,
+                                     boolean dstIsVm,
+                                     List<VmDevice> srcDevices,
+                                     Map<Guid, Guid> 
srcDeviceIdToDstDeviceIdMapping,
+                                     boolean isSoundEnabled,
+                                     boolean isConsoleEnabled,
+                                     Boolean isVirtioScsiEnabled,
+                                     boolean isBalloonEnabled,
+                                     Set<GraphicsType> graphicsToSkip,
+                                     boolean copySnapshotDevices) {
+        if (graphicsToSkip == null) {
+            graphicsToSkip = Collections.emptySet();
+        }
+
+        String dstCdPath = dstVmBase.getIsoPath();
+        boolean hasCd = hasCdDevice(dstVmBase.getId());
+        boolean hasSound = false;
+        boolean hasConsole = false;
+        boolean hasVirtioScsi = false;
+        boolean hasBalloon = false;
+        boolean hasRng = hasRngDevice(dstId);
+
+        VDSGroup cluster = null;
+        if (dstVmBase.getVdsGroupId() != null) {
+            cluster = 
DbFacade.getInstance().getVdsGroupDao().get(dstVmBase.getVdsGroupId());
+        }
+
+        for (VmDevice device : srcDevices) {
+            if (device.getSnapshotId() != null && !copySnapshotDevices) {
+                continue;
+            }
+
+            Guid deviceId = Guid.newGuid();
+            Map<String, Object> specParams = new HashMap<>();
+
+            switch (device.getType()) {
+                case DISK:
+                    if 
(VmDeviceType.DISK.getName().equals(device.getDevice())) {
+                        if 
(srcDeviceIdToDstDeviceIdMapping.containsKey(device.getDeviceId())) {
+                            deviceId = 
srcDeviceIdToDstDeviceIdMapping.get(device.getDeviceId());
+                        }
+                    } else if 
(VmDeviceType.CDROM.getName().equals(device.getDevice())) {
+                        if (!hasCd) {
+                            hasCd = true;
+                            // check here is source VM had CD (VM from 
snapshot)
+                            String srcCdPath = (String) 
device.getSpecParams().get(VdsProperties.Path);
+                            specParams.putAll(getCdDeviceSpecParams(srcCdPath, 
dstCdPath));
+                        } else { // CD already exists
+                            continue;
+                        }
+                    }
+                    break;
+
+                case INTERFACE:
+                    if 
(srcDeviceIdToDstDeviceIdMapping.containsKey(device.getDeviceId())) {
+                        deviceId = 
srcDeviceIdToDstDeviceIdMapping.get(device.getDeviceId());
+                    }
+                    break;
+
+                case CONTROLLER:
+                    if (VmDeviceType.USB.getName().equals(device.getDevice())) 
{
+                        specParams = device.getSpecParams();
+                    } else if 
(VmDeviceType.VIRTIOSCSI.getName().equals(device.getDevice())) {
+                        hasVirtioScsi = true;
+                        if (Boolean.FALSE.equals(isVirtioScsiEnabled)) {
+                            continue;
+                        }
+                    }
+                    break;
+
+                case VIDEO:
+                    if (dstIsVm) {
+                        // Source is template and target is VM. Video devices 
will be created according
+                        // to the new VmStatic params.
+                        continue;
+                    }
+                    specParams.putAll(getVideoDeviceSpecParams(dstVmBase));
+                    break;
+
+                case BALLOON:
+                    if (!isBalloonEnabled) {
+                        continue;
+                    }
+                    hasBalloon = true;
+                    specParams.putAll(getMemoryBalloonSpecParams());
+                    break;
+
+                case SMARTCARD:
+                    specParams.putAll(getSmartcardDeviceSpecParams());
+                    break;
+
+                case WATCHDOG:
+                    specParams.putAll(device.getSpecParams());
+                    break;
+
+                case RNG:
+                    if (hasRng) {
+                        continue;
+                    }
+                    if (!new VirtIoRngValidator().canAddRngDevice(cluster, new 
VmRngDevice(device)).isValid()) {
+                        continue;
+                    }
+                    specParams.putAll(device.getSpecParams());
+                    break;
+
+                case CONSOLE:
+                    if (!isConsoleEnabled) {
+                        continue;
+                    }
+                    hasConsole = true;
+                    break;
+
+                case SOUND:
+                    if (!isSoundEnabled) {
+                        continue;
+                    }
+                    hasSound = true;
+                    break;
+
+                case GRAPHICS:
+                    GraphicsType type = 
GraphicsType.fromVmDeviceType(VmDeviceType.getByName(device.getDevice()));
+                    // don't add device from the template if it should be 
skipped (i.e. it's overridden in params)
+                    // OR if we already have it
+                    if (graphicsToSkip.contains(type) ||
+                            hasGraphicsDevice(dstId, 
GraphicsType.fromString(device.getDevice()))) {
+                        continue;
+                    }
+                    break;
+
+                default:
+                    break;
+            }
+            device.setId(new VmDeviceId(deviceId, dstId));
+            device.setSpecParams(specParams);
+            dao.save(device);
+        }
+
+        if (!hasCd) {
+            addCdDevice(dstId, dstCdPath);
+        }
+
+        // if copying from Blank template, adding USB slots to the destination
+        // according to the destination USB policy
+        if (srcId.equals(Guid.Empty)) {
+            updateUsbSlots(null, dstVmBase);
+        }
+
+        if (isSoundEnabled && !hasSound) {
+            if (dstIsVm) {
+                addSoundDevice(dstVm.getStaticData());
+            } else {
+                addSoundDevice(dstVmBase.getId(), dstVmBase.getOsId(),
+                        cluster != null ? cluster.getCompatibilityVersion() : 
null);
+            }
+        }
+
+        if (isConsoleEnabled && !hasConsole) {
+            addConsoleDevice(dstId);
+        }
+
+        if (Boolean.TRUE.equals(isVirtioScsiEnabled) && !hasVirtioScsi) {
+            addVirtioScsiController(dstId);
+        }
+
+        if (isBalloonEnabled && !hasBalloon) {
+            addMemoryBalloon(dstId);
+        }
+
+        if (dstIsVm) {
+            updateBootOrder(dstVmBase.getId());
+            addVideoDevices(dstVmBase, 
getNeededNumberOfVideoDevices(dstVmBase));
+        }
+    }
+
+    /**
+     * Copy devices from the source to the destination VM.
+     *
+     * @param srcId
+     * @param dstId
+     * @param srcDeviceIdToDstDeviceIdMapping
+     * @param isSoundEnabled
+     * @param isConsoleEnabled
+     * @param isVirtioScsiEnabled
+     * @param isBalloonEnabled
+     * @param graphicsToSkip
+     * @param copySnapshotDevices
+     */
+    public static void copyVmDevices(Guid srcId,
+                                     Guid dstId,
+                                     Map<Guid, Guid> 
srcDeviceIdToDstDeviceIdMapping,
+                                     boolean isSoundEnabled,
+                                     boolean isConsoleEnabled,
+                                     Boolean isVirtioScsiEnabled,
+                                     boolean isBalloonEnabled,
+                                     Set<GraphicsType> graphicsToSkip,
+                                     boolean copySnapshotDevices) {
+        VM dstVm = dbFacade.getVmDao().get(dstId);
+        VmBase dstVmBase = (dstVm != null) ? dstVm.getStaticData() : null;
+        boolean dstIsVm = (dstVmBase != null);
+
+        if (!dstIsVm) {
+            dstVmBase = dbFacade.getVmTemplateDao().get(dstId);
+        }
+
+        List<VmDevice> srcDevices = dao.getVmDeviceByVmId(srcId);
+
+        copyVmDevices(srcId, dstId, dstVm, dstVmBase, dstIsVm, srcDevices, 
srcDeviceIdToDstDeviceIdMapping,
+                isSoundEnabled, isConsoleEnabled, isVirtioScsiEnabled, 
isBalloonEnabled, graphicsToSkip,
+                copySnapshotDevices);
+    }
+
+    /**
+     * Create new managed device.
+     *
+     * @param id            device id
+     * @param generalType   device general type
+     * @param type          device type
+     * @param specParams    device spec params
+     * @param isPlugged     is device plugged-in
+     * @param isReadOnly    is device read-only
+     * @return      newly created VmDevice instance
+     */
+    public static VmDevice addManagedDevice(VmDeviceId id,
+                                            VmDeviceGeneralType generalType,
+                                            VmDeviceType type,
+                                            Map<String, Object> specParams,
+                                            boolean isPlugged,
+                                            Boolean isReadOnly) {
+        return addManagedDevice(id, generalType, type, specParams, isPlugged, 
isReadOnly, "", null, false);
+    }
+
+    /**
+     * Create new managed device.
+     *
+     * @param id            device id
+     * @param generalType   device general type
+     * @param type          device type
+     * @param specParams    device spec params
+     * @param isPlugged     is device plugged-in
+     * @param isReadOnly    is device read-only
+     * @param address       device address
+     * @param customProps   device custom properties
+     * @param isUsingScsiReservation    is device using SCSI reservation
+     * @return      newly created VmDevice instance
+     */
+    public static VmDevice addManagedDevice(VmDeviceId id,
+                                            VmDeviceGeneralType generalType,
+                                            VmDeviceType type,
+                                            Map<String, Object> specParams,
+                                            Boolean isPlugged,
+                                            Boolean isReadOnly,
+                                            String address,
+                                            Map<String, String> customProps,
+                                            boolean isUsingScsiReservation) {
+        VmDevice managedDevice =
+                new VmDevice(
+                        id,
+                        generalType,
+                        type.getName(),
+                        StringUtils.isNotBlank(address) ? address : "",
+                        0,
+                        specParams,
+                        true,
+                        isPlugged,
+                        isReadOnly,
+                        "",
+                        customProps,
+                        null,
+                        null,
+                        isUsingScsiReservation);
+        dao.save(managedDevice);
+
+        // If we've added Disk/Interface/CD/Floppy, we have to recalculate 
boot order
+        if (generalType == VmDeviceGeneralType.DISK || generalType == 
VmDeviceGeneralType.INTERFACE) {
+            updateBootOrder(id.getVmId());
+        }
+
+        return managedDevice;
+    }
+
+    /**
+     * Add devices to an imported VM or template.
+     *
+     * @param vmBase
+     * @param isImportAsNewEntity
+     */
+    public static void addImportedDevices(VmBase vmBase, boolean 
isImportAsNewEntity) {
+        if (isImportAsNewEntity) {
+            setNewIdInImportedCollections(vmBase);
+        }
+
+        List<VmDevice> vmDevicesToAdd = new ArrayList<>();
+        List<VmDevice> vmDevicesToUpdate = new ArrayList<>();
+
+        addImportedDiskDevices(vmBase, vmDevicesToUpdate);
+        addImportedInterfaces(vmBase, vmDevicesToUpdate);
+        addImportedOtherDevices(vmBase, vmDevicesToAdd);
+
+        dao.saveAll(vmDevicesToAdd);
+        dao.updateAll(vmDevicesToUpdate);
+    }
+
+    /**
+     * Add disk devices to an imported VM or template.
+     *
+     * @param vmBase
+     * @param vmDevicesToUpdate    list of devices to be updated in the DB
+     */
+    private static void addImportedDiskDevices(VmBase vmBase, List<VmDevice> 
vmDevicesToUpdate) {
+        final Guid vmId = vmBase.getId();
+        for (BaseDisk disk : getDisks(vmBase.getImages())) {
+            Guid deviceId = disk.getId();
+            VmDevice vmDevice = addDiskDevice(vmId, deviceId, 
getVmDeviceAddress(vmBase, vmId));
+            updateImportedVmDevice(vmBase, vmDevice, deviceId, 
vmDevicesToUpdate);
+        }
+    }
+
+    /**
+     * Add network interfaces to an imported VM or template.
+     *
+     * @param vmBase
+     * @param vmDevicesToUpdate    list of devices to be updated in the DB
+     */
+    private static void addImportedInterfaces(VmBase vmBase, List<VmDevice> 
vmDevicesToUpdate) {
+        for (VmNic iface : vmBase.getInterfaces()) {
+            Guid deviceId = iface.getId();
+            VmDevice vmDevice = addInterface(vmBase.getId(), deviceId, true, 
iface.isPassthrough(),
+                    getVmDeviceAddress(vmBase, deviceId));
+
+            VmDevice exportedDevice = 
vmBase.getManagedDeviceMap().get(deviceId);
+            if (exportedDevice == null) {
+                vmBase.getManagedDeviceMap().put(deviceId, vmDevice);
+                exportedDevice = vmDevice;
+            }
+
+            exportedDevice.setIsPlugged(exportedDevice.getIsPlugged() && 
canPlugInterface(iface));
+            updateImportedVmDevice(vmBase, vmDevice, deviceId, 
vmDevicesToUpdate);
+        }
+    }
+
+    /**
+     * Add other managed and unmanaged devices to imported VM or template.
+     *
+     * @param vmBase
+     * @param vmDeviceToAdd     list of devices to be added to the DB
+     */
+    private static void addImportedOtherDevices(VmBase vmBase, List<VmDevice> 
vmDeviceToAdd) {
+        boolean hasCd = false;
+        boolean hasSound = false;
+
+        for (VmDevice vmDevice : vmBase.getManagedDeviceMap().values()) {
+            switch (vmDevice.getType()) {
+                case DISK:
+                    if 
(VmDeviceType.CDROM.getName().equals(vmDevice.getDevice())) {
+                        hasCd = true;
+                    } else {
+                        // disks are added separately
+                        continue;
+                    }
+                    break;
+
+                case INTERFACE:
+                    // network interfaces are added separately
+                    continue;
+
+                case VIDEO:
+                    vmDevice.setSpecParams(getVideoDeviceSpecParams(vmBase));
+                    break;
+
+                case SOUND:
+                    hasSound = true;
+                    break;
+            }
+            vmDevice.setIsManaged(true);
+            vmDeviceToAdd.add(vmDevice);
+        }
+
+        if (!hasCd) { // add an empty CD
+            addCdDevice(vmBase.getId());
+        }
+
+        // add sound card for desktops imported from old versions only, since 
devices didn't exist
+        Version ovfVer = new Version(vmBase.getOvfVersion());
+        if (!hasSound && VmDeviceCommonUtils.isOldClusterVersion(ovfVer) && 
vmBase.getVmType() == VmType.Desktop) {
+            addSoundDevice(vmBase);
+        }
+
+        // add unmanaged devices
+        for (VmDevice vmDevice : vmBase.getUnmanagedDeviceList()) {
+            vmDeviceToAdd.add(vmDevice);
+        }
+    }
+
+    /**
+     * Set common properties in a device for imported VM or template and add 
the device
+     * to the list of devices to be updated in the DB.
+     *
+     * @param vmBase
+     * @param vmDevice
+     * @param deviceId
+     * @param vmDevicesToUpdate    list of devices to be updated in the DB
+     */
+    private static void updateImportedVmDevice(VmBase vmBase,
+                                               VmDevice vmDevice,
+                                               Guid deviceId,
+                                               List<VmDevice> 
vmDevicesToUpdate) {
+        // update device information only if OVF supports devices - from 3.1
+        Version ovfVer = new Version(vmBase.getOvfVersion());
+        if (!VmDeviceCommonUtils.isOldClusterVersion(ovfVer)) {
+            VmDevice exportedDevice = 
vmBase.getManagedDeviceMap().get(deviceId);
+            if (exportedDevice != null) {
+                vmDevice.setAddress(exportedDevice.getAddress());
+                vmDevice.setBootOrder(exportedDevice.getBootOrder());
+                vmDevice.setIsPlugged(exportedDevice.getIsPlugged());
+                vmDevice.setIsReadOnly(exportedDevice.getIsReadOnly());
+                vmDevicesToUpdate.add(vmDevice);
+            }
+        }
+    }
+
+    /**
+     * Set newly generated ids for all devices in the VM, except disks and 
network interfaces.
+     *
+     * @param vmBase
+     */
+    private static void setNewIdInImportedCollections(VmBase vmBase) {
+        for (VmDevice managedDevice : vmBase.getManagedDeviceMap().values()) {
+            if (!isDiskOrInterface(managedDevice)) {
+                managedDevice.setId(new VmDeviceId(Guid.newGuid(), 
vmBase.getId()));
+            }
+        }
+        for (VmDevice unmanagedDevice : vmBase.getUnmanagedDeviceList()) {
+            unmanagedDevice.setId(new VmDeviceId(Guid.newGuid(), 
vmBase.getId()));
+        }
+    }
+
+    /**
+     * Determines whether a VM device change has been requested by the user.
+     *
      * @param deviceGeneralType VmDeviceGeneralType.
      * @param deviceTypeName VmDeviceType name.
      * @param deviceEnabled indicates whether the user asked to enable the 
device.
@@ -1177,7 +1739,8 @@
     }
 
     /**
-     * Determines whether a VM device change has been request by the user.
+     * Determines whether a VM device change has been requested by the user.
+     *
      * @param deviceGeneralType VmDeviceGeneralType.
      * @param deviceTypeName VmDeviceType name.
      * @param device device object provided by user
@@ -1189,10 +1752,12 @@
                 dao.getVmDeviceByVmIdTypeAndDevice(vmId, deviceGeneralType, 
deviceTypeName):
                 dao.getVmDeviceByVmIdAndType(vmId, deviceGeneralType);
 
-        if (device == null)
+        if (device == null) {
             return !vmDevices.isEmpty();
-        if (vmDevices.isEmpty()) // && device != null
+        }
+        if (vmDevices.isEmpty()) { // && device != null
             return true;
+        }
         if (device.getSpecParams() != null) { // if device.getSpecParams() == 
null, it is not used for comparison
             for (VmDevice vmDevice : vmDevices) {
                 if (!vmDevice.getSpecParams().equals(device.getSpecParams())) {
@@ -1204,24 +1769,43 @@
         return false;
     }
 
+    /**
+     * Determines whether a VM device change has been requested by the user.
+     *
+     * @param vmId
+     * @param deviceType
+     * @param deviceEnabled
+     * @return
+     */
     public static boolean vmDeviceChanged(Guid vmId, VmDeviceGeneralType 
deviceType, boolean deviceEnabled) {
         return vmDeviceChanged(vmId, deviceType, null, deviceEnabled);
     }
 
+    /**
+     * Determines whether a VM device change has been requested by the user.
+     *
+     * @param vmId
+     * @param deviceType
+     * @param device
+     * @return
+     */
     public static boolean vmDeviceChanged(Guid vmId, VmDeviceGeneralType 
deviceType, VmDevice device) {
         return vmDeviceChanged(vmId, deviceType, null, device);
     }
 
     /**
-     * Returns a map (device ID to VmDevice) of devices that are relevant for 
next run by examining
-     * properties that are annotated by EditableDeviceOnVmStatusField.
+     * Returns a map (device ID to VmDevice) of devices that are relevant for 
next run.
+     *
+     * The list of devices is built by examining properties that are annotated 
with EditableDeviceOnVmStatusField
+     * annotation.
+     *
      * @param vm the relevant VM
      * @param objectWithEditableDeviceFields object that contains properties 
which are annotated with
-     *                                       EditableDeviceField (e.g. 
parameters file)
-     * @return a map of device ID to VmDevice object of relevant devices for 
next run
+     *                                       EditableDeviceOnVmStatusField 
(e.g. parameters file)
+     * @return a map of device ID to VmDevice
      */
     public static Map<Guid, VmDevice> getVmDevicesForNextRun(VM vm, Object 
objectWithEditableDeviceFields) {
-        VmDeviceUtils.setVmDevices(vm.getStaticData());
+        setVmDevices(vm.getStaticData());
         Map<Guid, VmDevice> vmManagedDeviceMap = vm.getManagedVmDeviceMap();
 
         List<VmDeviceUpdate> fieldList =
@@ -1232,12 +1816,13 @@
             if (update.isEnable()) {
                 VmDevice device;
                 if (update.getDevice() == null) {
-                    device = new VmDevice(new VmDeviceId(Guid.newGuid(), 
vm.getId()),
+                    device = new VmDevice(
+                                    new VmDeviceId(Guid.newGuid(), vm.getId()),
                                     update.getGeneralType(),
                                     update.getType().getName(),
                                     "",
                                     0,
-                                    new HashMap<String, Object>(),
+                                    EMPTY_SPEC_PARAMS,
                                     true,
                                     true,
                                     update.isReadOnly(),
@@ -1257,40 +1842,17 @@
 
                 vmManagedDeviceMap.put(device.getDeviceId(), device);
             } else {
-                
vmManagedDeviceMap.remove(getVmDeviceIdByName(vmManagedDeviceMap, 
update.getGeneralType(),
-                        update.getType().getName()));
+                if (update.getType() != VmDeviceType.UNKNOWN) {
+                    vmManagedDeviceMap.remove(
+                            
VmDeviceCommonUtils.findVmDeviceByType(vmManagedDeviceMap, update.getType()));
+                } else {
+                    vmManagedDeviceMap.remove(
+                            
VmDeviceCommonUtils.findVmDeviceByGeneralType(vmManagedDeviceMap, 
update.getGeneralType()));
+                }
             }
         }
 
         return vmManagedDeviceMap;
     }
 
-    private static Guid getVmDeviceIdByName(Map<Guid, VmDevice> 
vmManagedDeviceMap, VmDeviceGeneralType generalType, String name) {
-        for (Map.Entry<Guid, VmDevice> entry : vmManagedDeviceMap.entrySet()) {
-            // first check by specific name
-            // if no match, and specific name is unknown, look by general type
-            if (entry.getValue().getDevice().equals(name)
-                    || (VmDeviceType.UNKNOWN.getName().equals(name) && 
entry.getValue().getType() == generalType)) {
-                return entry.getKey();
-            }
-        }
-
-        return null;
-    }
-
-    public static List<GraphicsType> getGraphicsTypesOfEntity(Guid entityId) {
-        List<GraphicsType> result = new ArrayList<>();
-
-        if (entityId != null) {
-            List<VmDevice> devices =
-                    
dbFacade.getVmDeviceDao().getVmDeviceByVmIdAndType(entityId, 
VmDeviceGeneralType.GRAPHICS);
-            if (devices != null) {
-                for (VmDevice device : devices) {
-                    result.add(GraphicsType.fromString(device.getDevice()));
-                }
-            }
-        }
-
-        return result;
-    }
 }
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/storage/DiskValidator.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/storage/DiskValidator.java
index b1287a0..f163ac9 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/storage/DiskValidator.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/validator/storage/DiskValidator.java
@@ -85,7 +85,7 @@
     }
 
     public boolean isVirtioScsiControllerAttached(Guid vmId) {
-        return VmDeviceUtils.isVirtioScsiControllerAttached(vmId);
+        return VmDeviceUtils.hasVirtioScsiController(vmId);
     }
 
     public ValidationResult isDiskPluggedToVmsThatAreNotDown(boolean 
checkOnlyVmsSnapshotPluggedTo, List<Pair<VM, VmDevice>> vmsForDisk) {
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmDeviceCommonUtils.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmDeviceCommonUtils.java
index 16111fe..7713e40 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmDeviceCommonUtils.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmDeviceCommonUtils.java
@@ -393,15 +393,26 @@
     }
 
     /**
-     * Find a device in the map given by device name.
+     * Find a device in the map with the given type.
      *
      * @param vmManagedDeviceMap
-     * @param name
+     * @param type
      * @return
      */
-    public static VmDevice findVmDeviceByName(Map<Guid, VmDevice> 
vmManagedDeviceMap, String name) {
+    public static VmDevice findVmDeviceByType(Map<Guid, VmDevice> 
vmManagedDeviceMap, VmDeviceType type) {
+        return findVmDeviceByType(vmManagedDeviceMap, type.getName());
+    }
+
+    /**
+     * Find a device in the map with the given type.
+     *
+     * @param vmManagedDeviceMap
+     * @param typeName
+     * @return
+     */
+    public static VmDevice findVmDeviceByType(Map<Guid, VmDevice> 
vmManagedDeviceMap, String typeName) {
         for (VmDevice vmDevice : vmManagedDeviceMap.values()) {
-            if (vmDevice.getDevice().equals(name)) {
+            if (vmDevice.getDevice().equals(typeName)) {
                 return vmDevice;
             }
         }
@@ -410,14 +421,14 @@
     }
 
     /**
-     * Find a device in the map given by device general type.
+     * Find a device in the map with the given general type.
      *
      * @param vmManagedDeviceMap
      * @param generalType
      * @return
      */
     public static VmDevice findVmDeviceByGeneralType(Map<Guid, VmDevice> 
vmManagedDeviceMap,
-                                               VmDeviceGeneralType 
generalType) {
+                                                     VmDeviceGeneralType 
generalType) {
         for (VmDevice vmDevice : vmManagedDeviceMap.values()) {
             if (vmDevice.getType() == generalType) {
                 return vmDevice;
@@ -428,14 +439,25 @@
     }
 
     /**
-     * Check if device with the name given exists in the map.
+     * Check if device with the type given exists in the map.
      *
      * @param vmManagedDeviceMap
-     * @param name
+     * @param type
      * @return
      */
-    public static boolean isVmDeviceExists(Map<Guid, VmDevice> 
vmManagedDeviceMap, String name) {
-        return findVmDeviceByName(vmManagedDeviceMap, name) != null;
+    public static boolean isVmDeviceExists(Map<Guid, VmDevice> 
vmManagedDeviceMap, VmDeviceType type) {
+        return isVmDeviceExists(vmManagedDeviceMap, type.getName());
+    }
+
+    /**
+     * Check if device with the type given exists in the map.
+     *
+     * @param vmManagedDeviceMap
+     * @param typeName
+     * @return
+     */
+    public static boolean isVmDeviceExists(Map<Guid, VmDevice> 
vmManagedDeviceMap, String typeName) {
+        return findVmDeviceByType(vmManagedDeviceMap, typeName) != null;
     }
 
 }
diff --git 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/instancetypes/InstanceTypeManager.java
 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/instancetypes/InstanceTypeManager.java
index 1fc26e5..e6b2f56 100644
--- 
a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/instancetypes/InstanceTypeManager.java
+++ 
b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/instancetypes/InstanceTypeManager.java
@@ -319,14 +319,14 @@
         if (isNextRunConfigurationExists()) {
             deactivate();
             getModel().getIsSoundcardEnabled().setEntity(
-                    
VmDeviceCommonUtils.isVmDeviceExists(vmBase.getManagedDeviceMap(), 
VmDeviceType.SOUND.getName()));
+                    
VmDeviceCommonUtils.isVmDeviceExists(vmBase.getManagedDeviceMap(), 
VmDeviceType.SOUND));
             getModel().getIsConsoleDeviceEnabled().setEntity(
-                    
VmDeviceCommonUtils.isVmDeviceExists(vmBase.getManagedDeviceMap(), 
VmDeviceType.CONSOLE.getName()));
+                    
VmDeviceCommonUtils.isVmDeviceExists(vmBase.getManagedDeviceMap(), 
VmDeviceType.CONSOLE));
 
             Set<GraphicsType> graphicsTypeSet = new HashSet<>();
             for (GraphicsType graphicsType : GraphicsType.values()) {
                 if 
(VmDeviceCommonUtils.isVmDeviceExists(vmBase.getManagedDeviceMap(),
-                        graphicsType.getCorrespondingDeviceType().getName())) {
+                        graphicsType.getCorrespondingDeviceType())) {
                     graphicsTypeSet.add(graphicsType);
                 }
             }
@@ -431,7 +431,7 @@
     private void updateVirtioScsi(VmBase vmBase) {
         if (isNextRunConfigurationExists()) {
             getModel().getIsVirtioScsiEnabled().setEntity(
-                    
VmDeviceCommonUtils.isVmDeviceExists(vmBase.getManagedDeviceMap(), 
VmDeviceType.VIRTIOSCSI.getName()));
+                    
VmDeviceCommonUtils.isVmDeviceExists(vmBase.getManagedDeviceMap(), 
VmDeviceType.VIRTIOSCSI));
             model.stopProgress();
             return;
         }


-- 
To view, visit https://gerrit.ovirt.org/41620
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iffa1ae3176b4082ef3b96277f6ea351e82f3e613
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Shmuel Leib Melamud <smela...@redhat.com>
Gerrit-Reviewer: Shmuel Melamud <smela...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to