import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Base64; /** * Minimal Java 11+ cookbook against the vSphere REST gateway using a Basic-auth * session (vmware-api-session-id). * * javac Cookbook.java && java Cookbook */ public final class Cookbook { private static final HttpClient CLIENT = HttpClient.newBuilder().sslContext(insecureSslContext()).build(); public static void main(String[] args) throws Exception { String base = env("VSPHERE_BASE", "https://localhost"); String user = env("VSPHERE_USER", "administrator@vsphere.local"); String password = env("VSPHERE_PASSWORD", "VMware1!"); String vmName = env("VSPHERE_VM_NAME", "java-lab-01"); String auth = "Basic " + Base64.getEncoder().encodeToString((user + ":" + password).getBytes(StandardCharsets.UTF_8)); String sessionId = unquote(send(post(base + "/api/session", auth, null))); System.out.println("session: " + sessionId); String vms = send(get(base + "/api/vcenter/vm", sessionId)); System.out.println("vms before: " + vms.length() + " bytes"); String createBody = "{\"name\":\"" + vmName + "\",\"guest_OS\":\"OTHER_GUEST_64\"," + "\"placement\":{\"folder\":\"group-v23\",\"host\":\"host-11\"," + "\"datastore\":\"datastore-31\",\"resource_pool\":\"resgroup-22\"}," + "\"cpu\":{\"count\":1},\"memory\":{\"size_MiB\":512}}"; String moid = unquote(send(postJson(base + "/api/vcenter/vm", sessionId, createBody))); System.out.println("created: " + moid); String power = send(post(base + "/api/vcenter/vm/" + moid + "/power?action=start", sessionId, null)); waitTask(base, sessionId, extractField(power, "task")); String detail = send(get(base + "/api/vcenter/vm/" + moid, sessionId)); System.out.println("power_state: " + extractField(detail, "power_state")); power = send(post(base + "/api/vcenter/vm/" + moid + "/power?action=stop", sessionId, null)); waitTask(base, sessionId, extractField(power, "task")); send(delete(base + "/api/vcenter/vm/" + moid, sessionId)); send(delete(base + "/api/session", sessionId)); System.out.println("ok"); } private static void waitTask(String base, String sessionId, String task) throws Exception { if (task == null || task.isBlank()) { return; } long deadline = System.currentTimeMillis() + 120_000; while (System.currentTimeMillis() < deadline) { String body = send(get(base + "/api/cis/tasks/" + task, sessionId)); String status = extractField(body, "status"); if ("SUCCEEDED".equals(status) || "FAILED".equals(status)) { return; } Thread.sleep(300); } throw new IllegalStateException("timeout waiting for task " + task); } private static String env(String key, String def) { String value = System.getenv(key); return value == null || value.isBlank() ? def : value; } private static HttpRequest get(String uri, String sessionId) { return HttpRequest.newBuilder(URI.create(uri)) .timeout(Duration.ofSeconds(60)) .header("vmware-api-session-id", sessionId) .GET() .build(); } private static HttpRequest post(String uri, String auth, String body) { HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create(uri)).timeout(Duration.ofSeconds(60)); if (auth.startsWith("Basic ")) { builder.header("Authorization", auth); } else { builder.header("vmware-api-session-id", auth); } return builder.POST(body == null ? BodyPublishers.noBody() : BodyPublishers.ofString(body)).build(); } private static HttpRequest postJson(String uri, String sessionId, String body) { return HttpRequest.newBuilder(URI.create(uri)) .timeout(Duration.ofSeconds(60)) .header("vmware-api-session-id", sessionId) .header("Content-Type", "application/json") .POST(BodyPublishers.ofString(body)) .build(); } private static HttpRequest delete(String uri, String sessionId) { return HttpRequest.newBuilder(URI.create(uri)) .timeout(Duration.ofSeconds(60)) .header("vmware-api-session-id", sessionId) .DELETE() .build(); } private static String send(HttpRequest request) throws Exception { HttpResponse response = CLIENT.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() >= 300) { throw new RuntimeException(response.statusCode() + ": " + response.body()); } return response.body(); } private static String unquote(String value) { String trimmed = value.trim(); if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) { return trimmed.substring(1, trimmed.length() - 1); } return trimmed; } /** Tiny string-based field extraction — good enough for a lab smoke, no JSON library required. */ private static String extractField(String body, String field) { String marker = "\"" + field + "\":"; int start = body.indexOf(marker); if (start < 0) { return ""; } start += marker.length(); while (start < body.length() && (body.charAt(start) == ' ' || body.charAt(start) == '"')) { start++; } int end = start; while (end < body.length() && body.charAt(end) != '"' && body.charAt(end) != ',' && body.charAt(end) != '}') { end++; } return body.substring(start, end); } private static javax.net.ssl.SSLContext insecureSslContext() { try { javax.net.ssl.TrustManager[] trustAll = new javax.net.ssl.TrustManager[] { new javax.net.ssl.X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[0]; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {} public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {} } }; javax.net.ssl.SSLContext context = javax.net.ssl.SSLContext.getInstance("TLS"); context.init(null, trustAll, new java.security.SecureRandom()); return context; } catch (Exception error) { throw new RuntimeException(error); } } }