|
18 | 18 |
|
19 | 19 | import static com.cloud.host.Host.HOST_INSTANCE_CONVERSION; |
20 | 20 | import static com.cloud.host.Host.HOST_OVFTOOL_VERSION; |
| 21 | +import static com.cloud.host.Host.HOST_VDDK_LIB_DIR; |
21 | 22 | import static com.cloud.host.Host.HOST_VDDK_SUPPORT; |
| 23 | +import static com.cloud.host.Host.HOST_VDDK_VERSION; |
22 | 24 | import static com.cloud.host.Host.HOST_VIRTV2V_VERSION; |
23 | 25 | import static com.cloud.host.Host.HOST_VOLUME_ENCRYPTION; |
24 | 26 | import static org.apache.cloudstack.utils.linux.KVMHostInfo.isHostS390x; |
@@ -364,6 +366,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv |
364 | 366 | public static final String WINDOWS_GUEST_CONVERSION_SUPPORTED_CHECK_CMD = "rpm -qa | grep -i virtio-win"; |
365 | 367 | public static final String UBUNTU_WINDOWS_GUEST_CONVERSION_SUPPORTED_CHECK_CMD = "dpkg -l virtio-win"; |
366 | 368 | public static final String UBUNTU_NBDKIT_PKG_CHECK_CMD = "dpkg -l nbdkit"; |
| 369 | + public static final String VDDK_AUTODETECT_PATH_CMD = "find / -type d -name 'vmware-vix-disklib-distrib' 2>/dev/null | head -n 1"; |
367 | 370 |
|
368 | 371 | public static final int LIBVIRT_CGROUP_CPU_SHARES_MIN = 2; |
369 | 372 | public static final int LIBVIRT_CGROUP_CPU_SHARES_MAX = 262144; |
@@ -892,6 +895,7 @@ protected enum HealthCheckResult { |
892 | 895 | protected String cachePath; |
893 | 896 | private String vddkTransports = null; |
894 | 897 | private String vddkThumbprint = null; |
| 898 | + private String vddkVersion = null; |
895 | 899 | private String detectedPasswordFileOption = null; |
896 | 900 | protected String javaTempDir = System.getProperty("java.io.tmpdir"); |
897 | 901 |
|
@@ -973,6 +977,10 @@ public String getVddkThumbprint() { |
973 | 977 | return vddkThumbprint; |
974 | 978 | } |
975 | 979 |
|
| 980 | + public String getVddkVersion() { |
| 981 | + return vddkVersion; |
| 982 | + } |
| 983 | + |
976 | 984 | /** |
977 | 985 | * Defines resource's public and private network interface according to what is configured in agent.properties. |
978 | 986 | */ |
@@ -1178,7 +1186,25 @@ public boolean configure(final String name, final Map<String, Object> params) th |
1178 | 1186 |
|
1179 | 1187 | setConvertInstanceEnv(convertEnvTmpDir, convertEnvVirtv2vTmpDir); |
1180 | 1188 |
|
1181 | | - vddkLibDir = AgentPropertiesFileHandler.getPropertyValue(AgentProperties.VDDK_LIB_DIR); |
| 1189 | + vddkLibDir = StringUtils.trimToNull(AgentPropertiesFileHandler.getPropertyValue(AgentProperties.VDDK_LIB_DIR)); |
| 1190 | + if (StringUtils.isNotBlank(vddkLibDir) && !isVddkLibDirValid(vddkLibDir)) { |
| 1191 | + LOGGER.warn("Configured VDDK library dir [{}] is invalid (missing lib64/libvixDiskLib.so), attempting auto-detection", vddkLibDir); |
| 1192 | + vddkLibDir = null; |
| 1193 | + } |
| 1194 | + if (StringUtils.isBlank(vddkLibDir)) { |
| 1195 | + vddkLibDir = detectVddkLibDir(); |
| 1196 | + } |
| 1197 | + if (StringUtils.isNotBlank(vddkLibDir)) { |
| 1198 | + LOGGER.info("Detected VDDK library dir: {}", vddkLibDir); |
| 1199 | + } else { |
| 1200 | + LOGGER.warn("Could not detect a valid VDDK library dir; VDDK conversion will be unavailable"); |
| 1201 | + } |
| 1202 | + |
| 1203 | + vddkVersion = detectVddkVersion(); |
| 1204 | + if (StringUtils.isNotBlank(vddkVersion)) { |
| 1205 | + LOGGER.info("Detected nbdkit VDDK plugin version: {}", vddkVersion); |
| 1206 | + } |
| 1207 | + |
1182 | 1208 | libguestfsBackend = StringUtils.defaultIfBlank( |
1183 | 1209 | AgentPropertiesFileHandler.getPropertyValue(AgentProperties.LIBGUESTFS_BACKEND), "direct"); |
1184 | 1210 | vddkTransports = StringUtils.trimToNull( |
@@ -4255,6 +4281,12 @@ public StartupCommand[] initialize() { |
4255 | 4281 | boolean instanceConversionSupported = hostSupportsInstanceConversion(); |
4256 | 4282 | cmd.getHostDetails().put(HOST_INSTANCE_CONVERSION, String.valueOf(instanceConversionSupported)); |
4257 | 4283 | cmd.getHostDetails().put(HOST_VDDK_SUPPORT, String.valueOf(hostSupportsVddk())); |
| 4284 | + if (StringUtils.isNotBlank(vddkLibDir)) { |
| 4285 | + cmd.getHostDetails().put(HOST_VDDK_LIB_DIR, vddkLibDir); |
| 4286 | + } |
| 4287 | + if (StringUtils.isNotBlank(vddkVersion)) { |
| 4288 | + cmd.getHostDetails().put(HOST_VDDK_VERSION, vddkVersion); |
| 4289 | + } |
4258 | 4290 | if (instanceConversionSupported) { |
4259 | 4291 | cmd.getHostDetails().put(HOST_VIRTV2V_VERSION, getHostVirtV2vVersion()); |
4260 | 4292 | } |
@@ -5971,7 +6003,52 @@ public boolean hostSupportsInstanceConversion() { |
5971 | 6003 | } |
5972 | 6004 |
|
5973 | 6005 | public boolean hostSupportsVddk() { |
5974 | | - return hostSupportsInstanceConversion() && StringUtils.isNotBlank(vddkLibDir) && new File(vddkLibDir).isDirectory(); |
| 6006 | + return hostSupportsInstanceConversion() && isVddkLibDirValid(vddkLibDir) && StringUtils.isNotBlank(vddkVersion); |
| 6007 | + } |
| 6008 | + |
| 6009 | + protected boolean isVddkLibDirValid(String path) { |
| 6010 | + if (StringUtils.isBlank(path)) { |
| 6011 | + return false; |
| 6012 | + } |
| 6013 | + File libDir = new File(path, "lib64"); |
| 6014 | + if (!libDir.isDirectory()) { |
| 6015 | + return false; |
| 6016 | + } |
| 6017 | + File[] libs = libDir.listFiles((dir, name) -> name.startsWith("libvixDiskLib.so")); |
| 6018 | + return libs != null && libs.length > 0; |
| 6019 | + } |
| 6020 | + |
| 6021 | + protected String detectVddkLibDir() { |
| 6022 | + String detectedPath = StringUtils.trimToNull(Script.runSimpleBashScript(VDDK_AUTODETECT_PATH_CMD)); |
| 6023 | + if (StringUtils.isNotBlank(detectedPath) && isVddkLibDirValid(detectedPath)) { |
| 6024 | + return detectedPath; |
| 6025 | + } |
| 6026 | + return null; |
| 6027 | + } |
| 6028 | + |
| 6029 | + protected String detectVddkVersion() { |
| 6030 | + try { |
| 6031 | + ProcessBuilder pb = new ProcessBuilder("nbdkit", "vddk", "--version"); |
| 6032 | + Process process = pb.start(); |
| 6033 | + |
| 6034 | + String output = new String(process.getInputStream().readAllBytes()); |
| 6035 | + process.waitFor(); |
| 6036 | + |
| 6037 | + if (StringUtils.isBlank(output)) { |
| 6038 | + return null; |
| 6039 | + } |
| 6040 | + |
| 6041 | + for (String line : output.split("\\R")) { |
| 6042 | + String trimmed = StringUtils.trimToEmpty(line); |
| 6043 | + if (trimmed.startsWith("vddk ")) { |
| 6044 | + return StringUtils.trimToNull(trimmed.substring("vddk ".length())); |
| 6045 | + } |
| 6046 | + } |
| 6047 | + return null; |
| 6048 | + } catch (Exception e) { |
| 6049 | + LOGGER.error("Failed to detect vddk version: {}", e.getMessage()); |
| 6050 | + return null; |
| 6051 | + } |
5975 | 6052 | } |
5976 | 6053 |
|
5977 | 6054 | public boolean hostSupportsWindowsGuestConversion() { |
|
0 commit comments