1818//
1919package com .cloud .hypervisor .kvm .resource .wrapper ;
2020
21- import java .io .BufferedInputStream ;
22- import java .io .File ;
23- import java .io .FileInputStream ;
24- import java .io .IOException ;
25- import java .io .InputStream ;
2621import java .net .URLEncoder ;
2722import java .nio .charset .Charset ;
28- import java .util .ArrayList ;
2923import java .util .List ;
3024import java .util .UUID ;
31- import java .util .stream .Collectors ;
3225
3326import org .apache .cloudstack .storage .to .PrimaryDataStoreTO ;
34- import org .apache .cloudstack .vm .UnmanagedInstanceTO ;
35- import org .apache .commons .collections .CollectionUtils ;
36- import org .apache .commons .io .IOUtils ;
3727import org .apache .commons .lang3 .StringUtils ;
3828
3929import com .cloud .agent .api .Answer ;
4434import com .cloud .agent .api .to .RemoteInstanceTO ;
4535import com .cloud .hypervisor .Hypervisor ;
4636import com .cloud .hypervisor .kvm .resource .LibvirtComputingResource ;
47- import com .cloud .hypervisor .kvm .resource .LibvirtDomainXMLParser ;
4837import com .cloud .hypervisor .kvm .resource .LibvirtVMDef ;
49- import com .cloud .hypervisor .kvm .storage .KVMPhysicalDisk ;
5038import com .cloud .hypervisor .kvm .storage .KVMStoragePool ;
5139import com .cloud .hypervisor .kvm .storage .KVMStoragePoolManager ;
5240import com .cloud .resource .CommandWrapper ;
5341import com .cloud .resource .ResourceWrapper ;
54- import com .cloud .storage .Storage ;
5542import com .cloud .utils .FileUtil ;
56- import com .cloud .utils .Pair ;
57- import com .cloud .utils .exception .CloudRuntimeException ;
5843import com .cloud .utils .script .OutputInterpreter ;
5944import com .cloud .utils .script .Script ;
6045
@@ -77,15 +62,15 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
7762 String msg = String .format ("Cannot convert the instance %s from VMware as the virt-v2v binary is not found. " +
7863 "Please install virt-v2v%s on the host before attempting the instance conversion." , sourceInstanceName , serverResource .isUbuntuHost ()? ", nbdkit" : "" );
7964 logger .info (msg );
80- return new ConvertInstanceAnswer (cmd , false , msg );
65+ return new Answer (cmd , false , msg );
8166 }
8267
8368 if (!areSourceAndDestinationHypervisorsSupported (sourceHypervisorType , destinationHypervisorType )) {
8469 String err = destinationHypervisorType != Hypervisor .HypervisorType .KVM ?
8570 String .format ("The destination hypervisor type is %s, KVM was expected, cannot handle it" , destinationHypervisorType ) :
8671 String .format ("The source hypervisor type %s is not supported for KVM conversion" , sourceHypervisorType );
8772 logger .error (err );
88- return new ConvertInstanceAnswer (cmd , false , err );
73+ return new Answer (cmd , false , err );
8974 }
9075
9176 final KVMStoragePoolManager storagePoolMgr = serverResource .getStoragePoolMgr ();
@@ -103,7 +88,7 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
10388 if (StringUtils .isBlank (exportInstanceOVAUrl )) {
10489 String err = String .format ("Couldn't export OVA for the VM %s, due to empty url" , sourceInstanceName );
10590 logger .error (err );
106- return new ConvertInstanceAnswer (cmd , false , err );
91+ return new Answer (cmd , false , err );
10792 }
10893
10994 int noOfThreads = cmd .getThreadsCountToExportOvf ();
@@ -117,7 +102,7 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
117102 if (!ovfExported ) {
118103 String err = String .format ("Export OVA for the VM %s failed" , sourceInstanceName );
119104 logger .error (err );
120- return new ConvertInstanceAnswer (cmd , false , err );
105+ return new Answer (cmd , false , err );
121106 }
122107 sourceOVFDirPath = String .format ("%s%s/" , sourceOVFDirPath , sourceInstanceName );
123108 } else {
@@ -140,15 +125,15 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
140125 "has a different virt-v2v version." ,
141126 ovfTemplateDirOnConversionLocation );
142127 logger .error (err );
143- return new ConvertInstanceAnswer (cmd , false , err );
128+ return new Answer (cmd , false , err );
144129 }
145130 return new ConvertInstanceAnswer (cmd , temporaryConvertUuid );
146131 } catch (Exception e ) {
147132 String error = String .format ("Error converting instance %s from %s, due to: %s" ,
148133 sourceInstanceName , sourceHypervisorType , e .getMessage ());
149134 logger .error (error , e );
150135 cleanupSecondaryStorage = true ;
151- return new ConvertInstanceAnswer (cmd , false , error );
136+ return new Answer (cmd , false , error );
152137 } finally {
153138 if (ovfExported && StringUtils .isNotBlank (ovfTemplateDirOnConversionLocation )) {
154139 String sourceOVFDir = String .format ("%s/%s" , temporaryConvertPath , ovfTemplateDirOnConversionLocation );
@@ -205,55 +190,6 @@ private String getExportOVAUrlFromRemoteInstance(RemoteInstanceTO vmwareInstance
205190 encodedUsername , encodedPassword , vcenter , datacenter , vm );
206191 }
207192
208- protected List <KVMPhysicalDisk > getTemporaryDisksFromParsedXml (KVMStoragePool pool , LibvirtDomainXMLParser xmlParser , String convertedBasePath ) {
209- List <LibvirtVMDef .DiskDef > disksDefs = xmlParser .getDisks ();
210- disksDefs = disksDefs .stream ().filter (x -> x .getDiskType () == LibvirtVMDef .DiskDef .DiskType .FILE &&
211- x .getDeviceType () == LibvirtVMDef .DiskDef .DeviceType .DISK ).collect (Collectors .toList ());
212- if (CollectionUtils .isEmpty (disksDefs )) {
213- String err = String .format ("Cannot find any disk defined on the converted XML domain %s.xml" , convertedBasePath );
214- logger .error (err );
215- throw new CloudRuntimeException (err );
216- }
217- sanitizeDisksPath (disksDefs );
218- return getPhysicalDisksFromDefPaths (disksDefs , pool );
219- }
220-
221- private List <KVMPhysicalDisk > getPhysicalDisksFromDefPaths (List <LibvirtVMDef .DiskDef > disksDefs , KVMStoragePool pool ) {
222- List <KVMPhysicalDisk > disks = new ArrayList <>();
223- for (LibvirtVMDef .DiskDef diskDef : disksDefs ) {
224- KVMPhysicalDisk physicalDisk = pool .getPhysicalDisk (diskDef .getDiskPath ());
225- disks .add (physicalDisk );
226- }
227- return disks ;
228- }
229-
230- protected List <KVMPhysicalDisk > getTemporaryDisksWithPrefixFromTemporaryPool (KVMStoragePool pool , String path , String prefix ) {
231- String msg = String .format ("Could not parse correctly the converted XML domain, checking for disks on %s with prefix %s" , path , prefix );
232- logger .info (msg );
233- pool .refresh ();
234- List <KVMPhysicalDisk > disksWithPrefix = pool .listPhysicalDisks ()
235- .stream ()
236- .filter (x -> x .getName ().startsWith (prefix ) && !x .getName ().endsWith (".xml" ))
237- .collect (Collectors .toList ());
238- if (CollectionUtils .isEmpty (disksWithPrefix )) {
239- msg = String .format ("Could not find any converted disk with prefix %s on temporary location %s" , prefix , path );
240- logger .error (msg );
241- throw new CloudRuntimeException (msg );
242- }
243- return disksWithPrefix ;
244- }
245-
246- private void cleanupDisksAndDomainFromTemporaryLocation (List <KVMPhysicalDisk > disks ,
247- KVMStoragePool temporaryStoragePool ,
248- String temporaryConvertUuid ) {
249- for (KVMPhysicalDisk disk : disks ) {
250- logger .info (String .format ("Cleaning up temporary disk %s after conversion from temporary location" , disk .getName ()));
251- temporaryStoragePool .deletePhysicalDisk (disk .getName (), Storage .ImageFormat .QCOW2 );
252- }
253- logger .info (String .format ("Cleaning up temporary domain %s after conversion from temporary location" , temporaryConvertUuid ));
254- FileUtil .deleteFiles (temporaryStoragePool .getLocalPath (), temporaryConvertUuid , ".xml" );
255- }
256-
257193 protected void sanitizeDisksPath (List <LibvirtVMDef .DiskDef > disks ) {
258194 for (LibvirtVMDef .DiskDef disk : disks ) {
259195 String [] diskPathParts = disk .getDiskPath ().split ("/" );
@@ -262,114 +198,6 @@ protected void sanitizeDisksPath(List<LibvirtVMDef.DiskDef> disks) {
262198 }
263199 }
264200
265- protected List <KVMPhysicalDisk > moveTemporaryDisksToDestination (List <KVMPhysicalDisk > temporaryDisks ,
266- List <String > destinationStoragePools ,
267- KVMStoragePoolManager storagePoolMgr ) {
268- List <KVMPhysicalDisk > targetDisks = new ArrayList <>();
269- if (temporaryDisks .size () != destinationStoragePools .size ()) {
270- String warn = String .format ("Discrepancy between the converted instance disks (%s) " +
271- "and the expected number of disks (%s)" , temporaryDisks .size (), destinationStoragePools .size ());
272- logger .warn (warn );
273- }
274- for (int i = 0 ; i < temporaryDisks .size (); i ++) {
275- String poolPath = destinationStoragePools .get (i );
276- KVMStoragePool destinationPool = storagePoolMgr .getStoragePool (Storage .StoragePoolType .NetworkFilesystem , poolPath );
277- if (destinationPool == null ) {
278- String err = String .format ("Could not find a storage pool by URI: %s" , poolPath );
279- logger .error (err );
280- continue ;
281- }
282- if (destinationPool .getType () != Storage .StoragePoolType .NetworkFilesystem ) {
283- String err = String .format ("Storage pool by URI: %s is not an NFS storage" , poolPath );
284- logger .error (err );
285- continue ;
286- }
287- KVMPhysicalDisk sourceDisk = temporaryDisks .get (i );
288- if (logger .isDebugEnabled ()) {
289- String msg = String .format ("Trying to copy converted instance disk number %s from the temporary location %s" +
290- " to destination storage pool %s" , i , sourceDisk .getPool ().getLocalPath (), destinationPool .getUuid ());
291- logger .debug (msg );
292- }
293-
294- String destinationName = UUID .randomUUID ().toString ();
295-
296- KVMPhysicalDisk destinationDisk = storagePoolMgr .copyPhysicalDisk (sourceDisk , destinationName , destinationPool , 7200 * 1000 );
297- targetDisks .add (destinationDisk );
298- }
299- return targetDisks ;
300- }
301-
302- private UnmanagedInstanceTO getConvertedUnmanagedInstance (String baseName ,
303- List <KVMPhysicalDisk > vmDisks ,
304- LibvirtDomainXMLParser xmlParser ) {
305- UnmanagedInstanceTO instanceTO = new UnmanagedInstanceTO ();
306- instanceTO .setName (baseName );
307- instanceTO .setDisks (getUnmanagedInstanceDisks (vmDisks , xmlParser ));
308- instanceTO .setNics (getUnmanagedInstanceNics (xmlParser ));
309- return instanceTO ;
310- }
311-
312- private List <UnmanagedInstanceTO .Nic > getUnmanagedInstanceNics (LibvirtDomainXMLParser xmlParser ) {
313- List <UnmanagedInstanceTO .Nic > nics = new ArrayList <>();
314- if (xmlParser != null ) {
315- List <LibvirtVMDef .InterfaceDef > interfaces = xmlParser .getInterfaces ();
316- for (LibvirtVMDef .InterfaceDef interfaceDef : interfaces ) {
317- UnmanagedInstanceTO .Nic nic = new UnmanagedInstanceTO .Nic ();
318- nic .setMacAddress (interfaceDef .getMacAddress ());
319- nic .setNicId (interfaceDef .getBrName ());
320- nic .setAdapterType (interfaceDef .getModel ().toString ());
321- nics .add (nic );
322- }
323- }
324- return nics ;
325- }
326-
327- protected List <UnmanagedInstanceTO .Disk > getUnmanagedInstanceDisks (List <KVMPhysicalDisk > vmDisks , LibvirtDomainXMLParser xmlParser ) {
328- List <UnmanagedInstanceTO .Disk > instanceDisks = new ArrayList <>();
329- List <LibvirtVMDef .DiskDef > diskDefs = xmlParser != null ? xmlParser .getDisks () : null ;
330- for (int i = 0 ; i < vmDisks .size (); i ++) {
331- KVMPhysicalDisk physicalDisk = vmDisks .get (i );
332- KVMStoragePool storagePool = physicalDisk .getPool ();
333- UnmanagedInstanceTO .Disk disk = new UnmanagedInstanceTO .Disk ();
334- disk .setPosition (i );
335- Pair <String , String > storagePoolHostAndPath = getNfsStoragePoolHostAndPath (storagePool );
336- disk .setDatastoreHost (storagePoolHostAndPath .first ());
337- disk .setDatastorePath (storagePoolHostAndPath .second ());
338- disk .setDatastoreName (storagePool .getUuid ());
339- disk .setDatastoreType (storagePool .getType ().name ());
340- disk .setCapacity (physicalDisk .getVirtualSize ());
341- disk .setFileBaseName (physicalDisk .getName ());
342- if (CollectionUtils .isNotEmpty (diskDefs )) {
343- LibvirtVMDef .DiskDef diskDef = diskDefs .get (i );
344- disk .setController (diskDef .getBusType () != null ? diskDef .getBusType ().toString () : LibvirtVMDef .DiskDef .DiskBus .VIRTIO .toString ());
345- } else {
346- // If the job is finished but we cannot parse the XML, the guest VM can use the virtio driver
347- disk .setController (LibvirtVMDef .DiskDef .DiskBus .VIRTIO .toString ());
348- }
349- instanceDisks .add (disk );
350- }
351- return instanceDisks ;
352- }
353-
354- protected Pair <String , String > getNfsStoragePoolHostAndPath (KVMStoragePool storagePool ) {
355- String sourceHostIp = null ;
356- String sourcePath = null ;
357- List <String []> commands = new ArrayList <>();
358- commands .add (new String []{Script .getExecutableAbsolutePath ("mount" )});
359- commands .add (new String []{Script .getExecutableAbsolutePath ("grep" ), storagePool .getLocalPath ()});
360- String storagePoolMountPoint = Script .executePipedCommands (commands , 0 ).second ();
361- logger .debug (String .format ("NFS Storage pool: %s - local path: %s, mount point: %s" , storagePool .getUuid (), storagePool .getLocalPath (), storagePoolMountPoint ));
362- if (StringUtils .isNotEmpty (storagePoolMountPoint )) {
363- String [] res = storagePoolMountPoint .strip ().split (" " );
364- res = res [0 ].split (":" );
365- if (res .length > 1 ) {
366- sourceHostIp = res [0 ].strip ();
367- sourcePath = res [1 ].strip ();
368- }
369- }
370- return new Pair <>(sourceHostIp , sourcePath );
371- }
372-
373201 private boolean exportOVAFromVMOnVcenter (String vmExportUrl ,
374202 String targetOvfDir ,
375203 int noOfThreads ,
@@ -412,27 +240,6 @@ protected boolean performInstanceConversion(String sourceOVFDirPath,
412240 return exitValue == 0 ;
413241 }
414242
415- protected LibvirtDomainXMLParser parseMigratedVMXmlDomain (String installPath ) throws IOException {
416- String xmlPath = String .format ("%s.xml" , installPath );
417- if (!new File (xmlPath ).exists ()) {
418- String err = String .format ("Conversion failed. Unable to find the converted XML domain, expected %s" , xmlPath );
419- logger .error (err );
420- throw new CloudRuntimeException (err );
421- }
422- InputStream is = new BufferedInputStream (new FileInputStream (xmlPath ));
423- String xml = IOUtils .toString (is , Charset .defaultCharset ());
424- final LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser ();
425- try {
426- parser .parseDomainXML (xml );
427- return parser ;
428- } catch (RuntimeException e ) {
429- String err = String .format ("Error parsing the converted instance XML domain at %s: %s" , xmlPath , e .getMessage ());
430- logger .error (err , e );
431- logger .debug (xml );
432- return null ;
433- }
434- }
435-
436243 protected String encodeUsername (String username ) {
437244 return URLEncoder .encode (username , Charset .defaultCharset ());
438245 }
0 commit comments