18
18
//
19
19
package com .cloud .hypervisor .kvm .resource .wrapper ;
20
20
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 ;
26
21
import java .net .URLEncoder ;
27
22
import java .nio .charset .Charset ;
28
- import java .util .ArrayList ;
29
23
import java .util .List ;
30
24
import java .util .UUID ;
31
- import java .util .stream .Collectors ;
32
25
33
26
import 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 ;
37
27
import org .apache .commons .lang3 .StringUtils ;
38
28
39
29
import com .cloud .agent .api .Answer ;
44
34
import com .cloud .agent .api .to .RemoteInstanceTO ;
45
35
import com .cloud .hypervisor .Hypervisor ;
46
36
import com .cloud .hypervisor .kvm .resource .LibvirtComputingResource ;
47
- import com .cloud .hypervisor .kvm .resource .LibvirtDomainXMLParser ;
48
37
import com .cloud .hypervisor .kvm .resource .LibvirtVMDef ;
49
- import com .cloud .hypervisor .kvm .storage .KVMPhysicalDisk ;
50
38
import com .cloud .hypervisor .kvm .storage .KVMStoragePool ;
51
39
import com .cloud .hypervisor .kvm .storage .KVMStoragePoolManager ;
52
40
import com .cloud .resource .CommandWrapper ;
53
41
import com .cloud .resource .ResourceWrapper ;
54
- import com .cloud .storage .Storage ;
55
42
import com .cloud .utils .FileUtil ;
56
- import com .cloud .utils .Pair ;
57
- import com .cloud .utils .exception .CloudRuntimeException ;
58
43
import com .cloud .utils .script .OutputInterpreter ;
59
44
import com .cloud .utils .script .Script ;
60
45
@@ -77,15 +62,15 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
77
62
String msg = String .format ("Cannot convert the instance %s from VMware as the virt-v2v binary is not found. " +
78
63
"Please install virt-v2v%s on the host before attempting the instance conversion." , sourceInstanceName , serverResource .isUbuntuHost ()? ", nbdkit" : "" );
79
64
logger .info (msg );
80
- return new ConvertInstanceAnswer (cmd , false , msg );
65
+ return new Answer (cmd , false , msg );
81
66
}
82
67
83
68
if (!areSourceAndDestinationHypervisorsSupported (sourceHypervisorType , destinationHypervisorType )) {
84
69
String err = destinationHypervisorType != Hypervisor .HypervisorType .KVM ?
85
70
String .format ("The destination hypervisor type is %s, KVM was expected, cannot handle it" , destinationHypervisorType ) :
86
71
String .format ("The source hypervisor type %s is not supported for KVM conversion" , sourceHypervisorType );
87
72
logger .error (err );
88
- return new ConvertInstanceAnswer (cmd , false , err );
73
+ return new Answer (cmd , false , err );
89
74
}
90
75
91
76
final KVMStoragePoolManager storagePoolMgr = serverResource .getStoragePoolMgr ();
@@ -103,7 +88,7 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
103
88
if (StringUtils .isBlank (exportInstanceOVAUrl )) {
104
89
String err = String .format ("Couldn't export OVA for the VM %s, due to empty url" , sourceInstanceName );
105
90
logger .error (err );
106
- return new ConvertInstanceAnswer (cmd , false , err );
91
+ return new Answer (cmd , false , err );
107
92
}
108
93
109
94
int noOfThreads = cmd .getThreadsCountToExportOvf ();
@@ -117,7 +102,7 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
117
102
if (!ovfExported ) {
118
103
String err = String .format ("Export OVA for the VM %s failed" , sourceInstanceName );
119
104
logger .error (err );
120
- return new ConvertInstanceAnswer (cmd , false , err );
105
+ return new Answer (cmd , false , err );
121
106
}
122
107
sourceOVFDirPath = String .format ("%s%s/" , sourceOVFDirPath , sourceInstanceName );
123
108
} else {
@@ -140,15 +125,15 @@ public Answer execute(ConvertInstanceCommand cmd, LibvirtComputingResource serve
140
125
"has a different virt-v2v version." ,
141
126
ovfTemplateDirOnConversionLocation );
142
127
logger .error (err );
143
- return new ConvertInstanceAnswer (cmd , false , err );
128
+ return new Answer (cmd , false , err );
144
129
}
145
130
return new ConvertInstanceAnswer (cmd , temporaryConvertUuid );
146
131
} catch (Exception e ) {
147
132
String error = String .format ("Error converting instance %s from %s, due to: %s" ,
148
133
sourceInstanceName , sourceHypervisorType , e .getMessage ());
149
134
logger .error (error , e );
150
135
cleanupSecondaryStorage = true ;
151
- return new ConvertInstanceAnswer (cmd , false , error );
136
+ return new Answer (cmd , false , error );
152
137
} finally {
153
138
if (ovfExported && StringUtils .isNotBlank (ovfTemplateDirOnConversionLocation )) {
154
139
String sourceOVFDir = String .format ("%s/%s" , temporaryConvertPath , ovfTemplateDirOnConversionLocation );
@@ -205,55 +190,6 @@ private String getExportOVAUrlFromRemoteInstance(RemoteInstanceTO vmwareInstance
205
190
encodedUsername , encodedPassword , vcenter , datacenter , vm );
206
191
}
207
192
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
-
257
193
protected void sanitizeDisksPath (List <LibvirtVMDef .DiskDef > disks ) {
258
194
for (LibvirtVMDef .DiskDef disk : disks ) {
259
195
String [] diskPathParts = disk .getDiskPath ().split ("/" );
@@ -262,114 +198,6 @@ protected void sanitizeDisksPath(List<LibvirtVMDef.DiskDef> disks) {
262
198
}
263
199
}
264
200
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
-
373
201
private boolean exportOVAFromVMOnVcenter (String vmExportUrl ,
374
202
String targetOvfDir ,
375
203
int noOfThreads ,
@@ -412,27 +240,6 @@ protected boolean performInstanceConversion(String sourceOVFDirPath,
412
240
return exitValue == 0 ;
413
241
}
414
242
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
-
436
243
protected String encodeUsername (String username ) {
437
244
return URLEncoder .encode (username , Charset .defaultCharset ());
438
245
}
0 commit comments