1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
package org.openslx.firmware;
import java.io.File;
import java.io.FileFilter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.function.Predicate;
import org.openslx.util.LevenshteinDistance;
import org.openslx.virtualization.configuration.transformation.TransformationException;
/**
* Utilities to process QEMU firmware specification files.
*
* @author Manuel Bentele
* @version 1.0
*/
public class QemuFirmwareUtil
{
/**
* Lookup a virtual machine's target OS loader based on QEMU firmware specification files.
*
* @param fwSpecDir QEMU firmware specification directory of the target host.
* @param sourceOsLoader OS loader of the virtual machine.
* @param sourceOsArch OS architecture of the virtual machine.
* @param sourceOsMachine OS machine type of the virtual machine.
* @return Path to the new target OS loader file for the virtual machine.
*
* @throws TransformationException Failed to lookup target OS loader for virtual machine.
*/
public static String lookupTargetOsLoader( String fwSpecDir, String sourceOsLoader, String sourceOsArch,
String sourceOsMachine )
throws FirmwareException
{
String lookupOsLoader = null;
// parse and check firmware specification directory
final File fwSpecDirFile = new File( fwSpecDir );
if ( !fwSpecDirFile.exists() || !fwSpecDirFile.isDirectory() ) {
throw new FirmwareException( "Path to QEMU firmware specifications directory is invalid!" );
}
// get all firmware specification files
final FileFilter fwSpecFilesFilter = file -> !file.isDirectory() && file.getName().endsWith( ".json" );
final File[] fwSpecFiles = fwSpecDirFile.listFiles( fwSpecFilesFilter );
// get paths to firmware files from firmware specification files
if ( fwSpecFiles != null ) {
final ArrayList<QemuFirmware> uefiFirmwares = new ArrayList<QemuFirmware>();
for ( final File fwSpecFile : fwSpecFiles ) {
// parse the firmware file
final QemuFirmware firmware = QemuFirmware.fromFwSpec( fwSpecFile );
if ( firmware == null ) {
throw new FirmwareException( "Firmware '" + fwSpecFile.toString() + "' can not be parsed correctly!" );
} else {
final Predicate<String> byInterfaceType = s -> s.toLowerCase().equals( "uefi" );
if ( firmware.getInterfaceTypes().stream().filter( byInterfaceType ).findAny().isPresent() ) {
// found valid UEFI firmware
// check if architecture and machine type of the VM is supported by the firmware
final Predicate<FirmwareTarget> byArchitecture = t -> sourceOsArch.equals( t.getArchitecture() );
final Predicate<String> byMachineType = s -> sourceOsMachine.startsWith( s.replace( "*", "" ) );
final Predicate<FirmwareTarget> byMachines = t -> t.getMachines().stream().filter( byMachineType )
.findAny().isPresent();
if ( firmware.getTargets().stream().filter( byArchitecture ).filter( byMachines ).findAny()
.isPresent() ) {
// found UEFI firmware supporting suitable architecture and machine type from VM
uefiFirmwares.add( firmware );
}
}
}
}
if ( uefiFirmwares.isEmpty() ) {
throw new FirmwareException( "There aren't any suitable UEFI firmwares locally available!" );
} else {
final LevenshteinDistance distance = new LevenshteinDistance( 1, 1, 1 );
int minFileNameDistance = Integer.MAX_VALUE;
Path suitablestUefiFirmwarePath = null;
for ( final QemuFirmware uefiFirmware : uefiFirmwares ) {
final Path uefiFirmwarePath = Paths.get( uefiFirmware.getMapping().getExecutable().getFileName() );
final Path sourceOsLoaderPath = Paths.get( sourceOsLoader );
final String uefiFirmwareFileName = uefiFirmwarePath.getFileName().toString().toLowerCase();
final String sourceOsLoaderFileName = sourceOsLoaderPath.getFileName().toString().toLowerCase();
final int fileNameDistance = distance.calculateDistance( uefiFirmwareFileName, sourceOsLoaderFileName );
if ( fileNameDistance < minFileNameDistance ) {
minFileNameDistance = fileNameDistance;
suitablestUefiFirmwarePath = uefiFirmwarePath;
}
}
lookupOsLoader = suitablestUefiFirmwarePath.toString();
}
}
return lookupOsLoader;
}
/**
* Lookup a virtual machine's target OS loader based on QEMU firmware specification files under
* the default path.
*
* @param sourceOsLoader OS loader of the virtual machine.
* @param sourceOsArch OS architecture of the virtual machine.
* @param sourceOsMachine OS machine type of the virtual machine.
* @return Path to the new target OS loader file for the virtual machine.
*
* @throws TransformationException Failed to lookup target OS loader for virtual machine.
*/
public static String lookupTargetOsLoaderDefaultFwSpecDir( String sourceOsLoader, String sourceOsArch,
String sourceOsMachine )
throws FirmwareException
{
return QemuFirmwareUtil.lookupTargetOsLoader( QemuFirmware.DEFAULT_SPEC_DIR, sourceOsLoader, sourceOsArch,
sourceOsMachine );
}
}
|