116116import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .DevicesDef ;
117117import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .DiskDef ;
118118import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .DiskDef .DeviceType ;
119+ import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .DiskDef .DiscardType ;
119120import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .DiskDef .DiskProtocol ;
120121import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .FeaturesDef ;
121122import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .FilesystemDef ;
125126import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .InputDef ;
126127import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .InterfaceDef ;
127128import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .InterfaceDef .GuestNetType ;
129+ import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .SCSIDef ;
128130import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .SerialDef ;
129131import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .TermPolicy ;
130132import com .cloud .hypervisor .kvm .resource .LibvirtVMDef .VideoDef ;
162164import com .cloud .utils .ssh .SshHelper ;
163165import com .cloud .vm .VirtualMachine ;
164166import com .cloud .vm .VirtualMachine .PowerState ;
167+ import com .cloud .vm .VmDetailConstants ;
165168
166169/**
167170 * LibvirtComputingResource execute requests on the computing/routing host using
@@ -2059,6 +2062,19 @@ So if getMinSpeed() returns null we fall back to getSpeed().
20592062 final InputDef input = new InputDef ("tablet" , "usb" );
20602063 devices .addDevice (input );
20612064
2065+
2066+ DiskDef .DiskBus busT = getDiskModelFromVMDetail (vmTO );
2067+
2068+ if (busT == null ) {
2069+ busT = getGuestDiskModel (vmTO .getPlatformEmulator ());
2070+ }
2071+
2072+ // If we're using virtio scsi, then we need to add a virtual scsi controller
2073+ if (busT == DiskDef .DiskBus .SCSI ) {
2074+ final SCSIDef sd = new SCSIDef ((short )0 , 0 , 0 , 9 , 0 );
2075+ devices .addDevice (sd );
2076+ }
2077+
20622078 vm .addComp (devices );
20632079
20642080 return vm ;
@@ -2142,23 +2158,16 @@ public int compare(final DiskTO arg0, final DiskTO arg1) {
21422158 }
21432159
21442160 // if params contains a rootDiskController key, use its value (this is what other HVs are doing)
2145- DiskDef .DiskBus diskBusType = null ;
2146- final Map <String , String > params = vmSpec .getDetails ();
2147- if (params != null && params .get ("rootDiskController" ) != null && !params .get ("rootDiskController" ).isEmpty ()) {
2148- final String rootDiskController = params .get ("rootDiskController" );
2149- s_logger .debug ("Passed custom disk bus " + rootDiskController );
2150- for (final DiskDef .DiskBus bus : DiskDef .DiskBus .values ()) {
2151- if (bus .toString ().equalsIgnoreCase (rootDiskController )) {
2152- s_logger .debug ("Found matching enum for disk bus " + rootDiskController );
2153- diskBusType = bus ;
2154- break ;
2155- }
2156- }
2157- }
2161+ DiskDef .DiskBus diskBusType = getDiskModelFromVMDetail (vmSpec );
21582162
21592163 if (diskBusType == null ) {
21602164 diskBusType = getGuestDiskModel (vmSpec .getPlatformEmulator ());
21612165 }
2166+
2167+ // I'm not sure why previously certain DATADISKs were hard-coded VIRTIO and others not, however this
2168+ // maintains existing functionality with the exception that SCSI will override VIRTIO.
2169+ DiskDef .DiskBus diskBusTypeData = (diskBusType == DiskDef .DiskBus .SCSI ) ? diskBusType : DiskDef .DiskBus .VIRTIO ;
2170+
21622171 final DiskDef disk = new DiskDef ();
21632172 if (volume .getType () == Volume .Type .ISO ) {
21642173 if (volPath == null ) {
@@ -2170,6 +2179,11 @@ public int compare(final DiskTO arg0, final DiskTO arg1) {
21702179 } else {
21712180 final int devId = volume .getDiskSeq ().intValue ();
21722181
2182+ if (diskBusType == DiskDef .DiskBus .SCSI ) {
2183+ disk .setQemuDriver (true );
2184+ disk .setDiscard (DiscardType .UNMAP );
2185+ }
2186+
21732187 if (pool .getType () == StoragePoolType .RBD ) {
21742188 /*
21752189 For RBD pools we use the secret mechanism in libvirt.
@@ -2188,7 +2202,7 @@ public int compare(final DiskTO arg0, final DiskTO arg1) {
21882202 disk .defBlockBasedDisk (physicalDisk .getPath (), devId , diskBusType );
21892203 } else {
21902204 if (volume .getType () == Volume .Type .DATADISK ) {
2191- disk .defFileBasedDisk (physicalDisk .getPath (), devId , DiskDef . DiskBus . VIRTIO , DiskDef .DiskFmtType .QCOW2 );
2205+ disk .defFileBasedDisk (physicalDisk .getPath (), devId , diskBusTypeData , DiskDef .DiskFmtType .QCOW2 );
21922206 } else {
21932207 disk .defFileBasedDisk (physicalDisk .getPath (), devId , diskBusType , DiskDef .DiskFmtType .QCOW2 );
21942208 }
@@ -2216,6 +2230,7 @@ public int compare(final DiskTO arg0, final DiskTO arg1) {
22162230 disk .setCacheMode (DiskDef .DiskCacheMode .valueOf (volumeObjectTO .getCacheMode ().toString ().toUpperCase ()));
22172231 }
22182232 }
2233+
22192234 vm .getDevices ().addDevice (disk );
22202235 }
22212236
@@ -2334,13 +2349,13 @@ public synchronized String attachOrDetachDisk(final Connect conn,
23342349 DiskDef diskdef = null ;
23352350 final KVMStoragePool attachingPool = attachingDisk .getPool ();
23362351 try {
2337- if (!attach ) {
2338- dm = conn .domainLookupByName (vmName );
2339- final LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser ();
2340- final String xml = dm .getXMLDesc (0 );
2341- parser .parseDomainXML (xml );
2342- disks = parser .getDisks ();
2352+ dm = conn .domainLookupByName (vmName );
2353+ final LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser ();
2354+ final String domXml = dm .getXMLDesc (0 );
2355+ parser .parseDomainXML (domXml );
2356+ disks = parser .getDisks ();
23432357
2358+ if (!attach ) {
23442359 for (final DiskDef disk : disks ) {
23452360 final String file = disk .getDiskPath ();
23462361 if (file != null && file .equalsIgnoreCase (attachingDisk .getPath ())) {
@@ -2352,17 +2367,31 @@ public synchronized String attachOrDetachDisk(final Connect conn,
23522367 throw new InternalErrorException ("disk: " + attachingDisk .getPath () + " is not attached before" );
23532368 }
23542369 } else {
2370+ DiskDef .DiskBus busT = DiskDef .DiskBus .VIRTIO ;
2371+ for (final DiskDef disk : disks ) {
2372+ if (disk .getDeviceType () == DeviceType .DISK ) {
2373+ if (disk .getBusType () == DiskDef .DiskBus .SCSI ) {
2374+ busT = DiskDef .DiskBus .SCSI ;
2375+ }
2376+ break ;
2377+ }
2378+ }
2379+
23552380 diskdef = new DiskDef ();
2381+ if (busT == DiskDef .DiskBus .SCSI ) {
2382+ diskdef .setQemuDriver (true );
2383+ diskdef .setDiscard (DiscardType .UNMAP );
2384+ }
23562385 if (attachingPool .getType () == StoragePoolType .RBD ) {
23572386 diskdef .defNetworkBasedDisk (attachingDisk .getPath (), attachingPool .getSourceHost (), attachingPool .getSourcePort (), attachingPool .getAuthUserName (),
2358- attachingPool .getUuid (), devId , DiskDef . DiskBus . VIRTIO , DiskProtocol .RBD , DiskDef .DiskFmtType .RAW );
2387+ attachingPool .getUuid (), devId , busT , DiskProtocol .RBD , DiskDef .DiskFmtType .RAW );
23592388 } else if (attachingPool .getType () == StoragePoolType .Gluster ) {
23602389 diskdef .defNetworkBasedDisk (attachingDisk .getPath (), attachingPool .getSourceHost (), attachingPool .getSourcePort (), null ,
2361- null , devId , DiskDef . DiskBus . VIRTIO , DiskProtocol .GLUSTER , DiskDef .DiskFmtType .QCOW2 );
2390+ null , devId , busT , DiskProtocol .GLUSTER , DiskDef .DiskFmtType .QCOW2 );
23622391 } else if (attachingDisk .getFormat () == PhysicalDiskFormat .QCOW2 ) {
2363- diskdef .defFileBasedDisk (attachingDisk .getPath (), devId , DiskDef . DiskBus . VIRTIO , DiskDef .DiskFmtType .QCOW2 );
2392+ diskdef .defFileBasedDisk (attachingDisk .getPath (), devId , busT , DiskDef .DiskFmtType .QCOW2 );
23642393 } else if (attachingDisk .getFormat () == PhysicalDiskFormat .RAW ) {
2365- diskdef .defBlockBasedDisk (attachingDisk .getPath (), devId , DiskDef . DiskBus . VIRTIO );
2394+ diskdef .defBlockBasedDisk (attachingDisk .getPath (), devId , busT );
23662395 }
23672396 if (bytesReadRate != null && bytesReadRate > 0 ) {
23682397 diskdef .setBytesReadRate (bytesReadRate );
@@ -2961,19 +2990,8 @@ private String getHypervisorPath(final Connect conn) {
29612990 }
29622991
29632992 boolean isGuestPVEnabled (final String guestOSName ) {
2964- if (guestOSName == null ) {
2965- return false ;
2966- }
2967- if (guestOSName .startsWith ("Ubuntu" ) || guestOSName .startsWith ("Fedora 13" ) || guestOSName .startsWith ("Fedora 12" ) || guestOSName .startsWith ("Fedora 11" ) ||
2968- guestOSName .startsWith ("Fedora 10" ) || guestOSName .startsWith ("Fedora 9" ) || guestOSName .startsWith ("CentOS 5.3" ) || guestOSName .startsWith ("CentOS 5.4" ) ||
2969- guestOSName .startsWith ("CentOS 5.5" ) || guestOSName .startsWith ("CentOS" ) || guestOSName .startsWith ("Fedora" ) ||
2970- guestOSName .startsWith ("Red Hat Enterprise Linux 5.3" ) || guestOSName .startsWith ("Red Hat Enterprise Linux 5.4" ) ||
2971- guestOSName .startsWith ("Red Hat Enterprise Linux 5.5" ) || guestOSName .startsWith ("Red Hat Enterprise Linux 6" ) || guestOSName .startsWith ("Debian GNU/Linux" ) ||
2972- guestOSName .startsWith ("FreeBSD 10" ) || guestOSName .startsWith ("Oracle" ) || guestOSName .startsWith ("Other PV" )) {
2973- return true ;
2974- } else {
2975- return false ;
2976- }
2993+ DiskDef .DiskBus db = getGuestDiskModel (guestOSName );
2994+ return db != DiskDef .DiskBus .IDE ;
29772995 }
29782996
29792997 public boolean isCentosHost () {
@@ -2984,14 +3002,42 @@ public boolean isCentosHost() {
29843002 }
29853003 }
29863004
3005+ public DiskDef .DiskBus getDiskModelFromVMDetail (final VirtualMachineTO vmTO ) {
3006+ Map <String , String > details = vmTO .getDetails ();
3007+ if (details == null ) {
3008+ return null ;
3009+ }
3010+
3011+ final String rootDiskController = details .get (VmDetailConstants .ROOT_DISK_CONTROLLER );
3012+ if (StringUtils .isNotBlank (rootDiskController )) {
3013+ s_logger .debug ("Passed custom disk bus " + rootDiskController );
3014+ for (final DiskDef .DiskBus bus : DiskDef .DiskBus .values ()) {
3015+ if (bus .toString ().equalsIgnoreCase (rootDiskController )) {
3016+ s_logger .debug ("Found matching enum for disk bus " + rootDiskController );
3017+ return bus ;
3018+ }
3019+ }
3020+ }
3021+ return null ;
3022+ }
3023+
29873024 private DiskDef .DiskBus getGuestDiskModel (final String platformEmulator ) {
2988- if (isGuestPVEnabled (platformEmulator )) {
3025+ if (platformEmulator == null ) {
3026+ return DiskDef .DiskBus .IDE ;
3027+ } else if (platformEmulator .startsWith ("Other PV Virtio-SCSI" )) {
3028+ return DiskDef .DiskBus .SCSI ;
3029+ } else if (platformEmulator .startsWith ("Ubuntu" ) || platformEmulator .startsWith ("Fedora 13" ) || platformEmulator .startsWith ("Fedora 12" ) || platformEmulator .startsWith ("Fedora 11" ) ||
3030+ platformEmulator .startsWith ("Fedora 10" ) || platformEmulator .startsWith ("Fedora 9" ) || platformEmulator .startsWith ("CentOS 5.3" ) || platformEmulator .startsWith ("CentOS 5.4" ) ||
3031+ platformEmulator .startsWith ("CentOS 5.5" ) || platformEmulator .startsWith ("CentOS" ) || platformEmulator .startsWith ("Fedora" ) ||
3032+ platformEmulator .startsWith ("Red Hat Enterprise Linux 5.3" ) || platformEmulator .startsWith ("Red Hat Enterprise Linux 5.4" ) ||
3033+ platformEmulator .startsWith ("Red Hat Enterprise Linux 5.5" ) || platformEmulator .startsWith ("Red Hat Enterprise Linux 6" ) || platformEmulator .startsWith ("Debian GNU/Linux" ) ||
3034+ platformEmulator .startsWith ("FreeBSD 10" ) || platformEmulator .startsWith ("Oracle" ) || platformEmulator .startsWith ("Other PV" )) {
29893035 return DiskDef .DiskBus .VIRTIO ;
29903036 } else {
29913037 return DiskDef .DiskBus .IDE ;
29923038 }
2993- }
29943039
3040+ }
29953041 private void cleanupVMNetworks (final Connect conn , final List <InterfaceDef > nics ) {
29963042 if (nics != null ) {
29973043 for (final InterfaceDef nic : nics ) {
0 commit comments