-
[study43] Vmware 가상머신 서비스 제공 웹 만들기FISA 2026. 3. 15. 15:19
VMware 가상머신 배포를 웹에서 자동화한 포털 만들기
VMware 환경에서 가상머신을 생성하는 작업을 웹에서 요청하고, 배포 결과까지 확인할 수 있는 간단한 포털을 구현 할겁니다.
<목표>
기존에는 vCenter에 직접 접속해서 템플릿, CPU, 메모리, 네트워크 같은 항목을 일일이 선택하며 가상머신을 만들어야 했는데,
이 과정을 웹 페이지에서 입력값만 넣으면 처리되도록 자동화하는 것이 목표입니다.
<구현목표>
구현할 기능은 단순하게
사용자가 웹 화면에서 VM 이름, 운영체제, CPU, 메모리, 템플릿, 네트워크 등의 정보를 입력하면,
Spring Boot 백엔드에서 이 요청을 받아 vCenter API와 연동해 실제 가상머신을 배포합니다.
그리고 그 결과를 사용자에게 다시 반환하고, 요청 이력은 데이터베이스에 저장해 나중에 조회할 수 있도록 구성합니다.
전체 흐름은 웹 UI → 백엔드 API → vCenter 연동 → VM 배포 → 결과 저장 및 반환이 되겠습니다!
<왜?>
vCenter 콘솔에 직접 접속하여 네트워크 설정, 리소스 할당, 템플릿 선택 등의 과정을 하나씩 수동으로 설정하며 배포를 진행하게 됩니다. 만약 VMware 실습 수업을 진행하는 입장에서 수십 명의 실습용 VM을 준비해야 한다면, 이러한 작업을 매번 직접 수행하는 것은 시간도 오래 걸리고 설정 실수가 발생할 가능성이 높지 않을까?에서 출발했습니다.
여기서 생성 가능한 VM은 Rocky로 한정합니다.
전체 구성
다음과 같은 흐름으로 진행됩니다.
- 사용자가 웹 페이지에서 가상머신 배포 정보를 입력한다.
- Controller가 요청을 받아 DTO로 매핑한다.
- Service 계층이 비즈니스 로직을 처리하면서 vCenter와 통신한다.
- 배포 요청 및 결과는 Entity 형태로 데이터베이스에 저장된다.
- 최종적으로 배포 성공 여부, VM 정보, 접속 정보 등을 사용자에게 응답한다.
화면은 입력을 받고, Controller는 요청을 전달하고, Service는 실제 배포 작업을 수행하고, Entity는 이력을 저장하는 패턴으로 코드를 작성 할 예정입니다.
기술 스택
다음과 같은 기술 스택을 사용했습니다.
- Backend: Spring Boot
- Frontend: HTML, CSS, JavaScript
- Database: PostgreSQL
- ORM: Spring Data JPA
- Build Tool: Gradle
- Virtualization Platform: VMware vSphere, vCenter
- Remote Access 연동: Guacamole
- Language: Java
1. Spring Boot 프로젝트 생성
1-1. 프로젝트 생성
설정은 다음과 같이 구성했습니다.
- Project: Gradle
- Language: Java
- Spring Boot: 4.0.3
- Group: com.vmportal
- Artifact: vmportal
- Packaging: Jar
- Java Version: 17
프로젝트 이름은 vmportal입니다.
1-2. 의존성 추가
프로젝트 생성 시 아래 의존성을 함께 추가했습니다.
- Spring Web
- Spring Data JPA
- PostgreSQL Driver
- Lombok
- Validation
각 의존성의 역할은 다음과 같습니다.
- Spring Web: 사용자의 요청을 받아 REST API를 만들기 위해 사용
- Spring Data JPA: 배포 요청 이력과 상태를 DB에 저장하기 위해 사용
- PostgreSQL Driver: PostgreSQL 데이터베이스 연결을 위해 사용
- Lombok: getter, setter, 생성자 같은 반복 코드를 줄이기 위해 사용
- Validation: 요청값 검증을 위해 사용
1-3. 프로젝트 구조
프로젝트를 생성한 뒤에는 아래와 같은 구조로 패키지를 나누어 관리할 예정입니다.
- controller : 사용자의 요청을 받는 계층
- service : 실제 배포 로직을 처리하는 계층
- entity : DB에 저장할 객체를 정의하는 계층
- dto : 요청/응답 데이터를 전달하는 객체
- repository : DB 접근을 담당하는 계층
- config / properties : VMware, Guacamole, DB 설정값 관리
폴더 구조
src/main/java/com/jihye/vmportal ┣ controller ┣ dto ┣ entity ┣ repository ┣ service ┗ VmportalApplication.java src/main/resources ┣ templates ┣ static ┗ application.yml
1.2. Docker를 이용해서 DB올리기해당 부분은 자주 했으므로 넘어가겠습니다. dockerfile설정해주고, docker 데스크탑에서 실행해준 뒤, 컴포즈 업만 해주시면 돼요

설정하구요

업해주기
2. application.yml 설정 및 설정값 분리
2-1. application.yml
이거까지만 전체코드를 올리겠습니다.
spring: datasource: url: jdbc:postgresql://localhost:5432/vm_portal username: postgres password: 1234 driver-class-name: org.postgresql.Driver jpa: hibernate: ddl-auto: update show-sql: true properties: hibernate: format_sql: true thymeleaf: cache: false server: port: 8080 vcenter: url: https://10.30.10.102/sdk username: administrator@seoul.seung.fisa password: VMware1! datacenter: Seoul-DC cluster: Seoul-Cluster network: VM Network datastore: vsanDatastore rocky-template: rocky-template guacamole: base-url: http://10.30.10.70:8080/guacamole username: guacadmin password: guacadmin datasource: mysql4가지 역할을 합니다.
- spring.datasource: PostgreSQL 데이터베이스 연결
- spring.jpa: JPA 동작 방식과 SQL 출력 설정
- vcenter: VMware vCenter 접속 및 배포 기본값 관리
- url부분ㄴ에선, vCenter url뒤에 sdk를 붙여야 vCenter API가 작동합니다. 그냥 url만 붙이면 api안먹어요
- username과 password는 vCenter접속 아이디입니다.
- 데이터센터와 클러스터등은 각자 가상환경이 만들어질 셋팅으로 해주시면 됩니다.
- 템플릿은 유저가 window, rocky, unbuntu등의 os를 선택했을 때 선택될 템플릿이름입니다. 지금은 테스트용으로 로키만 해두었습니다
- guacamole: 원격 접속 연동을 위한 Guacamole 정보 관리
- 유저네임과 패스워드는 과카몰리 어드민 권한이 있는 계정으로 설정 해주시면 됩니다. 기본은 과카어드민이구용
- datasource는 과카몰리 셋팅시 설정했던 DB로 해주시면 됩니다.
실제 배포시에는 주요 환경변수 ( 비밀번호 등)는 꼭! Env로 따로 관리해줍니다.
지금은 실제 배포 환경이 아니기때문에, 하드코딩 했습니다.
3. 설정값을 객체로 매핑하기
application.yml에 작성한 설정값은 그대로 문자열로 읽는 것이 아니라, 각각 전용 클래스에 매핑해서 사용했습니다.
Spring Boot의 @ConfigurationProperties를 사용하면 특정 prefix 아래의 값을 하나의 객체로 묶어서 관리할 수 있어서 훨씬 깔끔합니다.
3-1. GuacamoleProperties
package com.vmportal.config; import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Getter @Setter @Component @ConfigurationProperties(prefix = "guacamole") public class GuacamoleProperties { private String baseUrl; private String username; private String password; private String datasource; }이 클래스는 guacamole 아래에 있는 설정값을 자바 객체로 바인딩하는 역할을 합니다.
즉, guacamole.base-url, guacamole.username, guacamole.password 같은 값을 코드에서 편하게 사용할 수 있도록 묶어주는 설정 클래스입니다.Guacamole 관련 설정만 따로 모아두었기 때문에, 이후 원격 접속 기능을 구현할 때도 필요한 값을 한 객체에서 바로 꺼내 쓸 수 있습니다.
3-2. VCenterProperties
package com.vmportal.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "vcenter") public class VCenterProperties { private String url; private String username; private String password; private String datacenter; private String cluster; private String resourcePool; private String network; private String datastore; private String rockyTemplate; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getDatacenter() { return datacenter; } public void setDatacenter(String datacenter) { this.datacenter = datacenter; } public String getCluster() { return cluster; } public void setCluster(String cluster) { this.cluster = cluster; } public String getResourcePool() { return resourcePool; } public void setResourcePool(String resourcePool) { this.resourcePool = resourcePool; } public String getNetwork() { return network; } public void setNetwork(String network) { this.network = network; } public String getDatastore() { return datastore; } public void setDatastore(String datastore) { this.datastore = datastore; } public String getRockyTemplate() { return rockyTemplate; } public void setRockyTemplate(String rockyTemplate) { this.rockyTemplate = rockyTemplate; } }이 클래스는 vcenter 설정값을 자바 객체로 받아오는 역할을 합니다.
VMware 배포에 필요한 외부 설정을 모아두는 설정 객체라고 보면 됩니다. 나중에 다른 템플릿을 쓰거나 네트워크 이름이 바뀌더라도 서비스 코드 자체를 수정할 필요 없이 설정값만 바꿔주면 됩니다.
3. 배포 요청 정보 저장 Entity 작성
이제 실제로 사용자의 VM 배포 요청을 데이터베이스에 저장하기 위한 Entity를 작성합니다.
단순히 입력값만 담는 객체가 아니라, 배포 요청 시점의 설정값, 배포 진행 상태, 배포 결과, 원격 접속 정보, 에러 메시지까지 함께 저장하는 역할을 합니다.
즉, 사용자가 웹에서 VM 생성을 요청하면 그 요청 하나가 ProvisionRequest 엔티티로 기록되고, 이후 배포가 진행되면서 상태가 바뀌는 구조입니다.
ProvisionRequest
package com.vmportal.entity; import jakarta.persistence.*; import lombok.*; import java.time.LocalDateTime; @Entity @Table(name = "provision_request") @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder public class ProvisionRequest { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "vm_name", nullable = false) private String vmName; @Column(name = "os_type", nullable = false) private String osType; @Column(nullable = false) private Integer cpu; @Column(name = "memory_gb", nullable = false) private Integer memoryGb; @Column(name = "template_name") private String templateName; @Column(name = "cluster_name") private String clusterName; @Column(name = "resource_pool_name") private String resourcePoolName; @Column(name = "network_name") private String networkName; @Column(name = "datastore_name") private String datastoreName; @Enumerated(EnumType.STRING) @Column(nullable = false) private ProvisionStatus status; @Column(name = "vc_task_id") private String vcTaskId; @Column(name = "vm_id") private String vmId; @Column(name = "ip_address") private String ipAddress; @Column(name = "remote_protocol") private String remoteProtocol; @Column(name = "remote_port") private Integer remotePort; @Column(name = "remote_username") private String remoteUsername; @Column(name = "guac_ready") private Boolean guacReady; @Column(name = "guac_connection_id") private String guacConnectionId; @Column(name = "guac_identifier") private String guacIdentifier; @Column(name = "guac_url", length = 1000) private String guacUrl; @Column(name = "error_message", columnDefinition = "TEXT") private String errorMessage; @Column(name = "created_at", nullable = false) private LocalDateTime createdAt; }처음 요청이 들어왔을 때는 VM 이름, 운영체제, CPU, 메모리, 템플릿, 네트워크 같은 기본 배포 정보가 저장되고, 이후 실제 배포가 진행되면서 상태값이 변경됩니다.
예를 들어 요청이 들어오면 REQUESTED, 설정값 검증 중이면 VALIDATING, 실제 배포 중이면 PROVISIONING, 완료되면 COMPLETED, 실패하면 FAILED로 상태가 바뀝니다.
vmId, ipAddress, vcTaskId는 VMware 측 작업 결과를 추적하기 위한 값이고, remoteProtocol, remotePort, remoteUsername, guacUrl 등은 이후 원격 접속 기능과 연결하기 위한 값입니다.
1) 기본 배포 요청 정보
vmName / osType / cpu / memoryGb / templateName / clusterName / resourcePoolName / networkName / datastoreName
이 필드들은 사용자가 웹에서 입력하거나, 시스템이 기본값으로 결정한 배포 설정을 저장하는 영역입니다. 어떤 VM을 어떤 자원으로 어떤 위치에 배포할지에 대한 정보라고 볼 수 있습니다.
2) 배포 진행 상태 정보
status / vcTaskId / vmId / errorMessage
이 부분은 실제 vCenter 작업과 연결되는 정보입니다. 현재 배포가 어느 단계인지 status로 관리하고, vCenter 작업 ID나 생성된 VM ID를 저장해 배포 결과를 추적할 수 있도록 했습니다. 실패한 경우에는 errorMessage에 원인을 남겨 디버깅이 가능하도록 했습니다.
3) 원격 접속 연동 정보
ipAddress / remoteProtocol / remotePort / remoteUsername / guacReady / guacConnectiond / guacIdentifier / guacUrl
이 필드들은 VM 배포 이후 원격 접속까지 이어지도록 하기 위한 정보입니다. 단순히 VM만 생성하는 것이 아니라, 이후 Guacamole과 연결해 웹에서 바로 접근할 수 있는 구조를 고려했기 때문에 별도 필드로 분리해 두었습니다.
4) 생성 시각
createdAt
4. 요청과 응답을 전달하는 DTO 구성
Controller와 Service 사이에서는 직접 Entity를 주고받지 않고 DTO를 사용해 데이터를 전달했습니다.
DTO는 API 요청값이나 응답값을 담기 위한 객체로, 외부 요청 형식과 내부 데이터 구조를 분리하는 역할을 합니다.1) VM 배포 요청 DTO
먼저 사용자가 웹 화면에서 VM 배포를 요청할 때 전달되는 데이터입니다.
VM 이름, CPU, 메모리, 네트워크 정보, IP 설정 등을 받아 실제 vCenter 배포 작업에 전달하는 역할을 합니다.@Getter @Setter public class CreateProvisionRequestDto { private String vmName; private String osType; private Integer cpu; private Integer memoryGb; private String ipAddress; private String subnetMask; private String gateway; private String dns; } public class DeployVmRequest { private String vmName; private String osType; private String templateName; private Integer cpu; private Long memoryMb; private String networkName; private boolean powerOn = true; private String hostName; private String ipAddress; private String subnetMask; private String gateway; private String dnsServer; }CreateProvisionRequestDto는 웹에서 전달된 배포 요청을 받아오는 객체이고,
DeployVmRequest는 실제로 vCenter 배포 로직에서 사용하는 내부 요청 객체입니다.2) Guacamole 연결 생성 DTO
VM이 배포된 이후에는 웹에서 바로 접속할 수 있도록 Guacamole 연결을 생성하는 단계가 있습니다.
이 과정에서 필요한 요청값과 응답값을 DTO로 분리했습니다.@Getter @Builder public class GuacConnectionCreateRequest { private String connectionName; private String protocol; private String hostname; private String port; private String username; private String password; } @Getter @Builder public class GuacConnectionCreateResponse { private boolean success; private String connectionId; private String identifier; private String url; private String rawMessage; }이 DTO들은 Guacamole REST API와 통신할 때 사용하는 객체입니다.
Service 계층에서 이 객체를 이용해 Guacamole에 연결을 생성하고, 생성된 connectionId와 접속 URL을 받아옵니다3) Guacamole 인증 DTO
Guacamole API를 사용하려면 먼저 인증을 통해 authToken을 받아야 합니다.
이 토큰은 이후 API 요청 시 인증에 사용됩니다.public class GuacLoginResponse { private String authToken; private String dataSource; }Guacamole 로그인 요청 이후 응답으로 받은 토큰 정보를 저장하는 역할을 합니다.
4) 원격 콘솔 세션 요청 DTO
VM이 생성된 이후 사용자가 웹에서 바로 접속할 수 있도록 원격 콘솔 세션을 생성하는 요청 DTO도 따로 구성했습니다.
@Getter @Setter public class CreateGuacSessionRequest { private String vmName; private String osType; private String ipAddress; private String username; private String password; } @Getter @Setter public class OpenRemoteConsoleRequest { private String vmName; private String osType; private String ipAddress; private String username; private String password; }VM의 IP와 계정 정보를 기반으로 원격 접속 세션을 생성하기 위한 입력값을 전달하는 역할을 합니다.
5. 웹 요청을 처리하는 Controller
이제 사용자의 요청을 실제 서비스 로직으로 전달하는 Controller 계층을 구현했습니다.
Controller는 웹 요청을 받아 DTO로 변환하고, Service 계층에 전달한 뒤 결과를 화면이나 API 응답 형태로 반환하는 역할을 합니다.- PageController : 화면 페이지 이동 담당
- ProvisionRequestController : VM 배포 요청 관리
- VCenterController : VMware API 및 원격 콘솔 API
실제 코드에서는 각각 별도의 클래스로 분리되어 있으며, 여기서는 핵심 메서드만 정리했습니다.
5.1. PageController (페이지 이동)
가장 단순한 Controller로, 특정 URL 요청이 들어왔을 때 화면(View)을 반환하는 역할을 합니다.
@Controller public class PageController { @GetMapping("/deploy-form") public String deployForm() { return "deploy-form"; } }VM 배포 화면에 접근할 수 있도록 페이지 라우팅을 담당하는 Controller입니다.
5.2. VCenterController (VMware API 연동)
실제 VMware 작업을 수행하는 API Controller입니다. 앞의 Controller와 달리 View를 반환하지 않고 JSON API 형태로 동작합니다.
대표적으로 다음 기능들을 제공합니다.
- vCenter 연결 테스트
- 배포 리소스 검증
- VM 배포
- Guacamole 원격 콘솔 생성
@GetMapping("/api/vcenter/test") public ResponseEntity<Map<String, Object>> testVCenterConnection() { Map<String, Object> result = vCenterService.testConnection(); return ResponseEntity.ok(result); }vCenter와 정상적으로 연결되는지 확인하기 위한 테스트용 API입니다.
@PostMapping("/api/vcenter/deploy") public ResponseEntity<Map<String, Object>> deployVm(@RequestBody DeployVmRequest request) { Map<String, Object> result = vCenterService.deployVm(request); return ResponseEntity.ok(result); }사용자가 전달한 배포 요청 DTO를 받아 Service 계층에서 실제 VM 배포를 수행하도록 전달합니다.
또한 VM 생성 이후 웹에서 바로 접속할 수 있도록 Guacamole 원격 콘솔 생성 API도 구현했습니다.
@PostMapping("/api/guacamole/open") public ResponseEntity<Map<String, Object>> openRemoteConsole(@RequestBody OpenRemoteConsoleRequest request) { public ResponseEntity<Map<String, Object>> openRemoteConsole(@RequestBody OpenRemoteConsoleRequest request) { Map<String, Object> result = new LinkedHashMap<>(); try { if (request.getIpAddress() == null || request.getIpAddress().isBlank()) { throw new IllegalArgumentException("ipAddress는 필수입니다."); } String osType = request.getOsType() != null ? request.getOsType().toLowerCase() : "linux"; String protocol = osType.contains("windows") ? "rdp" : "ssh"; String port = osType.contains("windows") ? "3389" : "22"; String username = (request.getUsername() != null && !request.getUsername().isBlank()) ? request.getUsername() : (osType.contains("windows") ? "Administrator" : "rocky"); String connectionName = (request.getVmName() != null && !request.getVmName().isBlank()) ? request.getVmName() : "vm-" + request.getIpAddress(); GuacConnectionCreateRequest guacReq = GuacConnectionCreateRequest.builder() .connectionName(connectionName) .protocol(protocol) .hostname(request.getIpAddress()) .port(port) .username(username) .password(request.getPassword()) .build(); GuacConnectionCreateResponse guacRes = guacamoleService.createConnection(guacReq); result.put("success", true); result.put("message", "원격 화면 URL 생성 성공"); result.put("vmName", request.getVmName()); result.put("ipAddress", request.getIpAddress()); result.put("protocol", protocol); result.put("port", port); result.put("username", username); result.put("guacConnectionId", guacRes.getConnectionId()); result.put("guacIdentifier", guacRes.getIdentifier()); result.put("guacUrl", guacRes.getUrl()); result.put("rawMessage", guacRes.getRawMessage()); return ResponseEntity.ok(result); } catch (Exception e) { result.put("success", false); result.put("message", "원격 화면 URL 생성 실패"); result.put("error", e.getClass().getSimpleName()); result.put("detail", e.getMessage()); return ResponseEntity.status(500).body(result); }}이 API는 VM IP와 계정 정보를 이용해 Guacamole 연결을 생성하고 접속 URL을 반환합니다.
6. GuacamoleService (원격 접속 연결 생성)
VM이 생성된 이후에는 사용자가 웹에서 바로 접속할 수 있도록 Guacamole을 이용한 원격 콘솔 연결을 생성했습니다.
Guacamole은 웹 브라우저에서 SSH, RDP 같은 원격 접속을 사용할 수 있도록 해주는 오픈소스 게이트웨이입니다.이 서비스는 크게 세 가지 역할을 합니다.
- Guacamole 로그인 후 인증 토큰 획득
- Guacamole REST API를 통해 접속 연결 생성
- 웹에서 바로 접속 가능한 URL 생성
실제 코드에서는 여러 메서드로 분리되어 있지만, 핵심 흐름만 보면 다음과 같습니다.
<Guacamole 로그인 (토큰 획득)>
public GuacLoginResponse login() { String url = properties.getBaseUrl() + "/api/tokens"; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); MultiValueMap<String, String> form = new LinkedMultiValueMap<>(); form.add("username", properties.getUsername()); form.add("password", properties.getPassword()); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(form, headers); ResponseEntity<Map> response = restTemplate.postForEntity(url, requestEntity, Map.class); return new GuacLoginResponse( body.get("authToken").toString(), body.get("dataSource").toString() ); }/api/tokens API 호출 > Guacamole 계정으로 로그인 > authToken과 dataSource 반환
< Guacamole 연결 생성 >
public GuacConnectionCreateResponse createConnection(GuacConnectionCreateRequest req) { GuacLoginResponse login = login(); String url = properties.getBaseUrl() + "/api/session/data/" + login.getDataSource() + "/connections?token=" + login.getAuthToken(); Map<String, String> parameters = new LinkedHashMap<>(); parameters.put("hostname", req.getHostname()); parameters.put("port", req.getPort()); parameters.put("username", req.getUsername()); parameters.put("password", req.getPassword()); Map<String, Object> payload = new LinkedHashMap<>(); payload.put("protocol", req.getProtocol()); payload.put("parameters", parameters); ResponseEntity<Map> response = restTemplate.postForEntity(url, requestEntity, Map.class); }여기서는
접속 프로토콜 (SSH / RDP) / VM IP 주소 / 접속 포트 / 사용자 계정 / 비밀번호
기반으로 Guacamole 연결을 생성합니다.
이 요청이 성공하면 Guacamole 내부에 커넥션이 생성됩니다.
< Guacamole 접속 url 생성 >
private String buildGuacClientIdentifier(String connectionId, String dataSource) { String raw = connectionId + '\0' + "c" + '\0' + dataSource; return Base64.getEncoder() .withoutPadding() .encodeToString(raw.getBytes(StandardCharsets.UTF_8)); }Guacamole은 단순히 connectionId를 사용하는 것이 아니라 connectionId + dataSource 값을 Base64로 인코딩한 identifier를 사용합니다. 아마 mysql데이터베이스 규칙으로 바꾸면 되는 거 같아요. 실제로 12를 반환했을때는 접속이 안됐는데, 12를 mysql 인코딩하니까 접속이 되더라구요
이 값을 이용해 다음과 같은 접속 URL을 생성할 수 있습니다.
http://guacamole-server:8080/guacamole/#/client/{identifier}6. vCenterService (vm배포로직)
VCenterService는 사용자의 배포 요청을 받아 vCenter API를 이용해 VM을 생성하고, 생성된 VM의 정보와 원격 접속 정보를 반환하는 역할을 합니다.
6.1. vCenter연결 테스트
먼저 vCenter와 정상적으로 연결되는지 확인하는 기능입니다.
ServiceInstance serviceInstance = new ServiceInstance( new URL(properties.getUrl()), properties.getUsername(), properties.getPassword(), true );ServiceInstance는 VMware API에서 제공하는 vCenter와 연결을 생성하는 객체입니다.
이 객체를 통해 datacenter, cluster, datastore 같은 인프라 정보를 조회할 수 있습니다Datacenter datacenter = (Datacenter) new InventoryNavigator(rootFolder) .searchManagedEntity("Datacenter", properties.getDatacenter());연결 이후에는 InventoryNavigator를 이용해 필요한 리소스를 조회합니다.
이 과정을 통해 실제 배포에 필요한 Datacenter / Cluster / Network / Datastore / Template 리소스들이 존재하는지 확인합니다.
6.2. 템플릿 기반 VM Clone
먼저 vCenter와 정상적으로 연결되는지 확인하는 기능입니다.
VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec(); cloneSpec.setLocation(relocateSpec); cloneSpec.setPowerOn(request.isPowerOn()); cloneSpec.setTemplate(false); cloneSpec.setConfig(configSpec);6.3. 네트워크 재매핑
템플릿 VM의 네트워크 설정을 그대로 사용하면 다른 네트워크로 배포하기 어렵기 때문에
배포 시점에 네트워크 카드를 원하는 네트워크로 재매핑합니다.VirtualEthernetCardNetworkBackingInfo backing = new VirtualEthernetCardNetworkBackingInfo(); backing.setDeviceName(network.getName()); backing.setNetwork(network.getMOR());6.4. Guest Customization (IP 설정)
VM 생성 이후 내부 OS의 IP를 자동으로 설정하기 위해 Guest Customization 기능을 사용했습니다.
CustomizationFixedIp ip = new CustomizationFixedIp(); ip.setIpAddress(request.getIpAddress());6.5. VM Clone Task 실행
VMware에서는 VM 생성 작업이 Task 형태로 실행됩니다.
Task task = template.cloneVM_Task(vmFolder, request.getVmName(), cloneSpec); String taskStatus = task.waitForTask();6.6. VM IP 조회
VM이 생성되고 전원이 켜지면 VMware Tools를 통해 Guest OS의 IP 주소를 조회할 수 있습니다.
String ip = vm.getGuest().getIpAddress();하지만 VM이 부팅되는 동안 IP가 바로 나타나지 않을 수 있기 때문에 여러 번 재시도하는 방식으로 IP를 확인합니다.
6.7. Guacamole 원격 접속 연결마지막 단계에서는 VM에 웹 브라우저로 접속할 수 있도록 Guacamole 연결을 자동으로 생성합니다.
GuacConnectionCreateRequest guacReq = GuacConnectionCreateRequest.builder() .connectionName(request.getVmName()) .protocol("ssh") .hostname(effectiveIp) .port("22") .build();그다음 css와 html을 적당히 예쁘게 다듬어주면...

이러케 예쁜 화면 완성~
<마무리>
VMware vCenter에 직접 접속하여 VM을 생성하는 방식이 아니라, VMware에서 제공하는 개발자용 API를 이용해 VM 배포 작업을 자동화했습니다.
VMware에선 개발자가 가상화 환경을 프로그램으로 제어할 수 있도록 여러 형태의 API를 제공하고 있습니다.
대표적으로 다음과 같은 방식이 있습니다.
- vSphere Web Services API (SOAP 기반)
- vSphere Automation API (REST 기반)
- PowerCLI
- SDK (Java, Python 등)
이번 프로젝트에서는 Java 기반 VMware SDK (vSphere Web Services API) 를 사용했습니다.
<사용한 VMware API>
코드에서 사용한 주요 API들은 VMware vSphere SDK에서 제공하는 클래스들입니다.
대표적으로 다음과 같은 객체들을 활용했습니다ServiceInstance vCenter 서버 연결 InventoryNavigator Datacenter, Cluster, Network 검색 VirtualMachine VM 조회 및 제어 VirtualMachineCloneSpec VM Clone 설정 VirtualMachineRelocateSpec VM 위치 설정 (Datastore / ResourcePool) VirtualMachineConfigSpec CPU / Memory 설정 CustomizationSpec Guest OS IP 설정 Task VM 생성 작업 실행 VM 생성 이후 사용자가 웹에서 바로 접속할 수 있도록 Apache Guacamole의 REST API를 이용해 원격 접속 연결을 자동으로 생성했습니다. Guacamole은 웹 브라우저에서 SSH, RDP, VNC 같은 원격 접속을 사용할 수 있게 해주는 게이트웨이이며, 내부적으로 REST API를 제공하기 때문에 개발자가 프로그램으로 접속 연결을 생성할 수 있습니다.
<사용한 Guacamole API>
/api/tokens Guacamole 로그인 /api/session/data/{datasource}/connections 원격 접속 연결 생성 728x90'FISA' 카테고리의 다른 글
[회고]12주차_우리FISA클라우드 엔지니어링 (0) 2026.03.22 [회고]11주차_우리FISA클라우드 엔지니어링 (1) 2026.03.15 [study42] VMware Developer Portal (0) 2026.03.13 [study40] 기본 셋팅 이후의 추가 셋팅 03/12(5)FT(실습후 정리다시) (0) 2026.03.12 [study39] 기본 셋팅 이후의 추가셋팅 03/12(4)HA(실습후 정리다시) (0) 2026.03.12