fixes to allow worker vm deployment

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
Abhishek Kumar 2026-02-11 18:22:25 +05:30
parent a89f872b4f
commit 106fbdbe30
27 changed files with 651 additions and 158 deletions

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.veeam;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -64,4 +65,10 @@ public interface RouteHandler extends Adapter {
return null;
}
}
static Map<String, String> getRequestParams(HttpServletRequest req) {
return req.getParameterMap().entrySet().stream()
.filter(e -> e.getValue() != null && e.getValue().length > 0)
.collect(java.util.stream.Collectors.toMap(Map.Entry::getKey, e -> e.getValue()[0]));
}
}

View File

@ -27,8 +27,8 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.cloudstack.veeam.utils.Negotiation;
import org.apache.cloudstack.veeam.utils.Mapper;
import org.apache.cloudstack.veeam.utils.Negotiation;
import org.apache.cloudstack.veeam.utils.ResponseWriter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.logging.log4j.LogManager;
@ -36,6 +36,7 @@ import org.apache.logging.log4j.Logger;
public class VeeamControlServlet extends HttpServlet {
private static final Logger LOGGER = LogManager.getLogger(VeeamControlServlet.class);
private static final boolean LOG_REQUESTS = false;
private final ResponseWriter writer;
private final Mapper mapper;
@ -63,6 +64,32 @@ public class VeeamControlServlet extends HttpServlet {
LOGGER.info("Received {} request for {} with out format: {}", method, path, outFormat);
logRequest(req, method, path);
try {
if ("/".equals(path)) {
handleRoot(req, resp, outFormat);
return;
}
if (CollectionUtils.isNotEmpty(this.routeHandlers)) {
for (RouteHandler handler : this.routeHandlers) {
if (handler.canHandle(method, path)) {
handler.handle(req, resp, path, outFormat, this);
return;
}
}
}
notFound(resp, null, outFormat);
} catch (Error e) {
writer.writeFault(resp, e.status, e.message, null, outFormat);
}
}
private static void logRequest(HttpServletRequest req, String method, String path) {
if (!LOG_REQUESTS) {
return;
}
// Add a log to give all info about the request
try {
StringBuilder details = new StringBuilder();
@ -91,25 +118,6 @@ public class VeeamControlServlet extends HttpServlet {
} catch (Exception e) {
LOGGER.debug("Failed to capture request details", e);
}
try {
if ("/".equals(path)) {
handleRoot(req, resp, outFormat);
return;
}
if (CollectionUtils.isNotEmpty(this.routeHandlers)) {
for (RouteHandler handler : this.routeHandlers) {
if (handler.canHandle(method, path)) {
handler.handle(req, resp, path, outFormat, this);
return;
}
}
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
} catch (Error e) {
writer.writeFault(resp, e.status, e.message, null, outFormat);
}
}
private String normalize(String pathInfo) {
@ -133,16 +141,16 @@ public class VeeamControlServlet extends HttpServlet {
public void methodNotAllowed(final HttpServletResponse resp, final String allow, final Negotiation.OutFormat outFormat) throws IOException {
resp.setHeader("Allow", allow);
writer.writeFault(resp, 405, "Method Not Allowed", "Allowed methods: " + allow, outFormat);
writer.writeFault(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method Not Allowed", "Allowed methods: " + allow, outFormat);
}
public void badRequest(final HttpServletResponse resp, String detail, Negotiation.OutFormat outFormat) throws IOException {
writer.writeFault(resp, 400, "Bad request", detail, outFormat);
writer.writeFault(resp, HttpServletResponse.SC_BAD_REQUEST, "Bad request", detail, outFormat);
}
public void notFound(final HttpServletResponse resp, String detail, Negotiation.OutFormat outFormat) throws IOException {
writer.writeFault(resp, 404, "Not found", detail, outFormat);
writer.writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", detail, outFormat);
}
public static class Error extends RuntimeException {

View File

@ -17,6 +17,7 @@
package org.apache.cloudstack.veeam.adapter;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
@ -24,7 +25,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Inject;
@ -46,6 +46,8 @@ import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd;
import org.apache.cloudstack.api.command.user.vm.ListVMsCmd;
import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
import org.apache.cloudstack.api.command.user.vm.StopVMCmd;
import org.apache.cloudstack.api.command.user.vmsnapshot.CreateVMSnapshotCmd;
import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DeleteVolumeCmd;
@ -73,6 +75,7 @@ import org.apache.cloudstack.veeam.api.converter.NetworkVOToVnicProfileConverter
import org.apache.cloudstack.veeam.api.converter.NicVOToNicConverter;
import org.apache.cloudstack.veeam.api.converter.StoreVOToStorageDomainConverter;
import org.apache.cloudstack.veeam.api.converter.UserVmJoinVOToVmConverter;
import org.apache.cloudstack.veeam.api.converter.VmSnapshotVOToSnapshotConverter;
import org.apache.cloudstack.veeam.api.converter.VolumeJoinVOToDiskConverter;
import org.apache.cloudstack.veeam.api.dto.Cluster;
import org.apache.cloudstack.veeam.api.dto.DataCenter;
@ -84,6 +87,7 @@ import org.apache.cloudstack.veeam.api.dto.Job;
import org.apache.cloudstack.veeam.api.dto.Network;
import org.apache.cloudstack.veeam.api.dto.Nic;
import org.apache.cloudstack.veeam.api.dto.Ref;
import org.apache.cloudstack.veeam.api.dto.Snapshot;
import org.apache.cloudstack.veeam.api.dto.StorageDomain;
import org.apache.cloudstack.veeam.api.dto.Vm;
import org.apache.cloudstack.veeam.api.dto.VmAction;
@ -139,8 +143,12 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicVO;
import com.cloud.vm.UserVmService;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.snapshot.VMSnapshotService;
import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
public class ServerAdapter extends ManagerBase {
private static final String SERVICE_ACCOUNT_NAME = "veemserviceuser";
@ -162,6 +170,7 @@ public class ServerAdapter extends ManagerBase {
ResizeVolumeCmd.class,
ListNetworksCmd.class
);
public static final String GUEST_CPU_MODE = "host-passthrough";
@Inject
RoleService roleService;
@ -238,7 +247,13 @@ public class ServerAdapter extends ManagerBase {
@Inject
AsyncJobJoinDao asyncJobJoinDao;
private Map<String, Long> jobsMap = new ConcurrentHashMap<>();
@Inject
VMSnapshotDao vmSnapshotDao;
@Inject
VMSnapshotService vmSnapshotService;
//ToDo: check access on objects
protected Role createServiceAccountRole() {
Role role = roleService.createRole(SERVICE_ACCOUNT_ROLE_NAME, RoleType.User,
@ -383,13 +398,13 @@ public class ServerAdapter extends ManagerBase {
return NetworkVOToVnicProfileConverter.toVnicProfile(vo, this::getZoneById);
}
public List<Vm> listAllUserVms() {
public List<Vm> listAllInstances() {
// Todo: add filtering, pagination
List<UserVmJoinVO> vms = userVmJoinDao.listAll();
return UserVmJoinVOToVmConverter.toVmList(vms, this::getHostById);
}
public Vm getVm(String uuid) {
public Vm getInstance(String uuid) {
UserVmJoinVO vo = userVmJoinDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
@ -398,7 +413,7 @@ public class ServerAdapter extends ManagerBase {
this::listNicsByInstance);
}
public Vm handleCreateVm(Vm request) {
public Vm createInstance(Vm request) {
if (request == null) {
throw new InvalidParameterValueException("Request disk data is empty");
}
@ -424,14 +439,14 @@ public class ServerAdapter extends ManagerBase {
}
Long memory = null;
try {
memory = request.memory;
memory = Long.valueOf(request.memory);
} catch (Exception ignored) {}
if (memory == null) {
throw new InvalidParameterValueException("Memory must be specified");
}
String userdata = null;
if (request.getInitialization() != null) {
userdata = request.getInitialization().getContentData();
userdata = request.getInitialization().getCustomScript();
}
ApiConstants.BootType bootType = ApiConstants.BootType.BIOS;
ApiConstants.BootMode bootMode = ApiConstants.BootMode.LEGACY;
@ -442,7 +457,7 @@ public class ServerAdapter extends ManagerBase {
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
try {
return createVm(zoneId, clusterId, name, cpu, memory, userdata, bootType, bootMode);
return createInstance(zoneId, clusterId, name, cpu, memory, userdata, bootType, bootMode);
} finally {
CallContext.unregister();
}
@ -463,20 +478,21 @@ public class ServerAdapter extends ManagerBase {
return serviceOfferingDao.findByUuid(uuid);
}
protected Vm createVm(Long zoneId, Long clusterId, String name, int cpu, long memory, String userdata,
ApiConstants.BootType bootType, ApiConstants.BootMode bootMode) {
protected Vm createInstance(Long zoneId, Long clusterId, String name, int cpu, long memory, String userdata,
ApiConstants.BootType bootType, ApiConstants.BootMode bootMode) {
ServiceOffering serviceOffering = getServiceOfferingIdForVmCreation(zoneId, cpu, memory);
if (serviceOffering == null) {
throw new CloudRuntimeException("No service offering found for VM creation with specified CPU and memory");
}
DeployVMCmdByAdmin cmd = new DeployVMCmdByAdmin();
cmd.setHttpMethod(BaseCmd.HTTPMethod.POST.name());
ComponentContext.inject(cmd);
cmd.setZoneId(zoneId);
cmd.setClusterId(clusterId);
cmd.setName(name);
cmd.setServiceOfferingId(serviceOffering.getId());
if (StringUtils.isNotEmpty(userdata)) {
cmd.setUserData(Base64.getEncoder().encodeToString(userdata.getBytes()));
cmd.setUserData(Base64.getEncoder().encodeToString(userdata.getBytes(StandardCharsets.UTF_8)));
}
if (bootType != null) {
cmd.setBootType(bootType.toString());
@ -487,6 +503,11 @@ public class ServerAdapter extends ManagerBase {
// ToDo: handle other.
cmd.setHypervisor(Hypervisor.HypervisorType.KVM.name());
cmd.setBlankInstance(true);
Map<String, String> details = new HashMap<>();
details.put(VmDetailConstants.GUEST_CPU_MODE, GUEST_CPU_MODE);
Map<Integer, Map<String, String>> map = new HashMap<>();
map.put(0, details);
cmd.setDetails(map);
try {
UserVm vm = userVmService.createVirtualMachine(cmd);
vm = userVmService.finalizeCreateVirtualMachine(vm.getId());
@ -498,7 +519,11 @@ public class ServerAdapter extends ManagerBase {
}
}
public void deleteVm(String uuid) {
public Vm updateInstance(String uuid, Vm request) {
return getInstance(uuid);
}
public void deleteInstance(String uuid) {
UserVmVO vo = userVmDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
@ -510,7 +535,7 @@ public class ServerAdapter extends ManagerBase {
}
}
public VmAction startVm(String uuid) {
public VmAction startInstance(String uuid) {
UserVmVO vo = userVmDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
@ -519,6 +544,7 @@ public class ServerAdapter extends ManagerBase {
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
try {
StartVMCmd cmd = new StartVMCmd();
cmd.setHttpMethod(BaseCmd.HTTPMethod.POST.name());
ComponentContext.inject(cmd);
Map<String, String> params = new HashMap<>();
params.put(ApiConstants.ID, vo.getUuid());
@ -534,7 +560,7 @@ public class ServerAdapter extends ManagerBase {
}
}
public VmAction stopVm(String uuid) {
public VmAction stopInstance(String uuid) {
UserVmVO vo = userVmDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
@ -543,6 +569,7 @@ public class ServerAdapter extends ManagerBase {
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
try {
StopVMCmd cmd = new StopVMCmd();
cmd.setHttpMethod(BaseCmd.HTTPMethod.POST.name());
ComponentContext.inject(cmd);
Map<String, String> params = new HashMap<>();
params.put(ApiConstants.ID, vo.getUuid());
@ -559,7 +586,7 @@ public class ServerAdapter extends ManagerBase {
}
}
public VmAction shutdownVm(String uuid) {
public VmAction shutdownInstance(String uuid) {
UserVmVO vo = userVmDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
@ -568,6 +595,7 @@ public class ServerAdapter extends ManagerBase {
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
try {
StopVMCmd cmd = new StopVMCmd();
cmd.setHttpMethod(BaseCmd.HTTPMethod.POST.name());
ComponentContext.inject(cmd);
Map<String, String> params = new HashMap<>();
params.put(ApiConstants.ID, vo.getUuid());
@ -610,7 +638,7 @@ public class ServerAdapter extends ManagerBase {
return listDiskAttachmentsByInstanceId(vo.getId());
}
public DiskAttachment handleVmAttachDisk(final String vmUuid, final DiskAttachment request) {
public DiskAttachment handleInstanceAttachDisk(final String vmUuid, final DiskAttachment request) {
UserVmVO vmVo = userVmDao.findByUuid(vmUuid);
if (vmVo == null) {
throw new InvalidParameterValueException("VM with ID " + vmUuid + " not found");
@ -729,7 +757,7 @@ public class ServerAdapter extends ManagerBase {
return listNicsByInstance(vo.getId(), vo.getUuid());
}
public List<Nic> listNicsByInstanceId(final String uuid) {
public List<Nic> listNicsByInstanceUuid(final String uuid) {
UserVmVO vo = userVmDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
@ -737,7 +765,7 @@ public class ServerAdapter extends ManagerBase {
return listNicsByInstance(vo.getId(), vo.getUuid());
}
public Nic handleVmAttachNic(final String vmUuid, final Nic request) {
public Nic handleAttachInstanceNic(final String vmUuid, final Nic request) {
UserVmVO vmVo = userVmDao.findByUuid(vmUuid);
if (vmVo == null) {
throw new InvalidParameterValueException("VM with ID " + vmUuid + " not found");
@ -860,28 +888,98 @@ public class ServerAdapter extends ManagerBase {
}
public List<Job> listAllJobs() {
// ToDo: find active jobs for service account
return Collections.emptyList();
}
public Job getTempJob(String uuid) {
// final ClusterVO vo = clusterDao.findByUuid(uuid);
// if (vo == null) {
// throw new InvalidParameterValueException("Cluster with ID " + uuid + " not found");
// }
long startTime = jobsMap.computeIfAbsent(uuid, k -> System.currentTimeMillis());
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > 10000L) {
return AsyncJobJoinVOToJobConverter.toJob(uuid, "finished", startTime);
} else {
return AsyncJobJoinVOToJobConverter.toJob(uuid, "started", startTime);
}
}
public Job getJob(String uuid) {
final AsyncJobJoinVO vo = asyncJobJoinDao.findByUuid(uuid);
final AsyncJobJoinVO vo = asyncJobJoinDao.findByUuidIncludingRemoved(uuid);
if (vo == null) {
throw new InvalidParameterValueException("Job with ID " + uuid + " not found");
}
return AsyncJobJoinVOToJobConverter.toJob(vo);
}
public List<Snapshot> listSnapshotsByInstanceUuid(final String uuid) {
UserVmVO vo = userVmDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("VM with ID " + uuid + " not found");
}
List<VMSnapshotVO> snapshots = vmSnapshotDao.findByVm(vo.getId());
return VmSnapshotVOToSnapshotConverter.toSnapshotList(snapshots, vo.getUuid());
}
public Snapshot handleCreateInstanceSnapshot(final String vmUuid, final Snapshot request) {
UserVmVO vmVo = userVmDao.findByUuid(vmUuid);
if (vmVo == null) {
throw new InvalidParameterValueException("VM with ID " + vmUuid + " not found");
}
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
try {
CreateVMSnapshotCmd cmd = new CreateVMSnapshotCmd();
ComponentContext.inject(cmd);
Map<String, String> params = new HashMap<>();
params.put(ApiConstants.VIRTUAL_MACHINE_ID, vmVo.getUuid());
params.put(ApiConstants.VM_SNAPSHOT_DESCRIPTION, request.getDescription());
params.put(ApiConstants.VM_SNAPSHOT_MEMORY, String.valueOf(Boolean.parseBoolean(request.getPersistMemorystate())));
ApiServerService.AsyncCmdResult result =
apiServerService.processAsyncCmd(cmd, params, ctx, serviceUserAccount.first().getId(),
serviceUserAccount.second());
if (result.objectId == null) {
throw new CloudRuntimeException("No snapshot ID returned");
}
VMSnapshotVO vo = vmSnapshotDao.findById(result.objectId);
if (vo == null) {
throw new CloudRuntimeException("Snapshot not found");
}
return VmSnapshotVOToSnapshotConverter.toSnapshot(vo, vmVo.getUuid());
} catch (Exception e) {
throw new CloudRuntimeException("Failed to create snapshot: " + e.getMessage(), e);
} finally {
CallContext.unregister();
}
}
public Snapshot getSnapshot(String uuid) {
VMSnapshotVO vo = vmSnapshotDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("Snapshot with ID " + uuid + " not found");
}
UserVmVO vm = userVmDao.findById(vo.getVmId());
return VmSnapshotVOToSnapshotConverter.toSnapshot(vo, vm.getUuid());
}
public Snapshot deleteSnapshot(String uuid, boolean async) {
Snapshot snapshot = null;
VMSnapshotVO vo = vmSnapshotDao.findByUuid(uuid);
if (vo == null) {
throw new InvalidParameterValueException("Snapshot with ID " + uuid + " not found");
}
Pair<User, Account> serviceUserAccount = createServiceAccountIfNeeded();
CallContext ctx = CallContext.register(serviceUserAccount.first(), serviceUserAccount.second());
try {
if (async) {
DeleteVMSnapshotCmd cmd = new DeleteVMSnapshotCmd();
ComponentContext.inject(cmd);
Map<String, String> params = new HashMap<>();
params.put(ApiConstants.ID, vo.getUuid());
apiServerService.processAsyncCmd(cmd, params, ctx, serviceUserAccount.first().getId(),
serviceUserAccount.second());
vo = vmSnapshotDao.findById(vo.getId());
if (vo == null) {
throw new CloudRuntimeException("Snapshot not found");
}
UserVmVO vm = userVmDao.findById(vo.getVmId());
snapshot = VmSnapshotVOToSnapshotConverter.toSnapshot(vo, vm.getUuid());
} else {
vmSnapshotService.deleteVMSnapshot(vo.getId());
}
} catch (Exception e) {
throw new CloudRuntimeException("Failed to delete snapshot: " + e.getMessage(), e);
} finally {
CallContext.unregister();
}
return snapshot;
}
}

View File

@ -61,7 +61,7 @@ public class ApiService extends ManagerBase implements RouteHandler {
handleRootApiRequest(req, resp, outFormat, io);
return;
}
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", null, outFormat);
io.notFound(resp, null, outFormat);
}
private void handleRootApiRequest(HttpServletRequest req, HttpServletResponse resp, Negotiation.OutFormat outFormat, VeeamControlServlet io) throws IOException {

View File

@ -79,7 +79,7 @@ public class ClustersRouteHandler extends ManagerBase implements RouteHandler {
}
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
io.notFound(resp, null, outFormat);
}
protected void handleGet(final HttpServletRequest req, final HttpServletResponse resp,
@ -96,7 +96,7 @@ public class ClustersRouteHandler extends ManagerBase implements RouteHandler {
Cluster response = serverAdapter.getCluster(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
}

View File

@ -93,7 +93,7 @@ public class DataCentersRouteHandler extends ManagerBase implements RouteHandler
}
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
io.notFound(resp, null, outFormat);
}
protected void handleGet(final HttpServletRequest req, final HttpServletResponse resp,
@ -110,7 +110,7 @@ public class DataCentersRouteHandler extends ManagerBase implements RouteHandler
DataCenter response = serverAdapter.getDataCenter(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
@ -121,7 +121,7 @@ public class DataCentersRouteHandler extends ManagerBase implements RouteHandler
StorageDomains response = new StorageDomains(storageDomains);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
@ -132,7 +132,7 @@ public class DataCentersRouteHandler extends ManagerBase implements RouteHandler
Networks response = new Networks(networks);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
}

View File

@ -93,7 +93,7 @@ public class DisksRouteHandler extends ManagerBase implements RouteHandler {
}
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
io.notFound(resp, null, outFormat);
}
protected void handleGet(final HttpServletRequest req, final HttpServletResponse resp,
@ -113,7 +113,7 @@ public class DisksRouteHandler extends ManagerBase implements RouteHandler {
Disk response = serverAdapter.handleCreateDisk(request);
io.getWriter().write(resp, HttpServletResponse.SC_CREATED, response, outFormat);
} catch (JsonProcessingException | CloudRuntimeException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_BAD_REQUEST, "Bad request", e.getMessage(), outFormat);
io.badRequest(resp, e.getMessage(), outFormat);
}
}
@ -123,7 +123,7 @@ public class DisksRouteHandler extends ManagerBase implements RouteHandler {
Disk response = serverAdapter.getDisk(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
@ -133,7 +133,7 @@ public class DisksRouteHandler extends ManagerBase implements RouteHandler {
serverAdapter.deleteDisk(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, "Deleted disk ID: " + id, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_BAD_REQUEST, "Bad request", e.getMessage(), outFormat);
io.badRequest(resp, e.getMessage(), outFormat);
}
}
}

View File

@ -79,7 +79,7 @@ public class HostsRouteHandler extends ManagerBase implements RouteHandler {
}
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
io.notFound(resp, null, outFormat);
}
protected void handleGet(final HttpServletRequest req, final HttpServletResponse resp,
@ -96,7 +96,7 @@ public class HostsRouteHandler extends ManagerBase implements RouteHandler {
Host response = serverAdapter.getHost(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
}

View File

@ -100,7 +100,7 @@ public class ImageTransfersRouteHandler extends ManagerBase implements RouteHand
}
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
io.notFound(resp, null, outFormat);
}
protected void handleGet(final HttpServletRequest req, final HttpServletResponse resp,
@ -120,7 +120,7 @@ public class ImageTransfersRouteHandler extends ManagerBase implements RouteHand
ImageTransfer response = serverAdapter.handleCreateImageTransfer(request);
io.getWriter().write(resp, HttpServletResponse.SC_CREATED, response, outFormat);
} catch (JsonProcessingException | CloudRuntimeException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_BAD_REQUEST, "Bad Request", e.getMessage(), outFormat);
io.badRequest(resp, e.getMessage(), outFormat);
}
}
@ -130,7 +130,7 @@ public class ImageTransfersRouteHandler extends ManagerBase implements RouteHand
ImageTransfer response = serverAdapter.getImageTransfer(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
@ -140,7 +140,7 @@ public class ImageTransfersRouteHandler extends ManagerBase implements RouteHand
serverAdapter.handleCancelImageTransfer(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, "Image transfer cancelled successfully", outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
@ -150,7 +150,7 @@ public class ImageTransfersRouteHandler extends ManagerBase implements RouteHand
serverAdapter.handleFinalizeImageTransfer(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, "Image transfer finalized successfully", outFormat);
} catch (CloudRuntimeException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
}

View File

@ -79,7 +79,7 @@ public class JobsRouteHandler extends ManagerBase implements RouteHandler {
}
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
io.notFound(resp, null, outFormat);
}
protected void handleGet(final HttpServletRequest req, final HttpServletResponse resp,
@ -93,10 +93,10 @@ public class JobsRouteHandler extends ManagerBase implements RouteHandler {
protected void handleGetById(final String id, final HttpServletResponse resp, final Negotiation.OutFormat outFormat,
final VeeamControlServlet io) throws IOException {
try {
Job response = serverAdapter.getTempJob(id);
Job response = serverAdapter.getJob(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
}

View File

@ -79,7 +79,7 @@ public class NetworksRouteHandler extends ManagerBase implements RouteHandler {
}
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
io.notFound(resp, null, outFormat);
}
protected void handleGet(final HttpServletRequest req, final HttpServletResponse resp,
@ -96,7 +96,7 @@ public class NetworksRouteHandler extends ManagerBase implements RouteHandler {
Network response = serverAdapter.getNetwork(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
}

View File

@ -32,6 +32,8 @@ import org.apache.cloudstack.veeam.api.dto.DiskAttachment;
import org.apache.cloudstack.veeam.api.dto.DiskAttachments;
import org.apache.cloudstack.veeam.api.dto.Nic;
import org.apache.cloudstack.veeam.api.dto.Nics;
import org.apache.cloudstack.veeam.api.dto.Snapshot;
import org.apache.cloudstack.veeam.api.dto.Snapshots;
import org.apache.cloudstack.veeam.api.dto.Vm;
import org.apache.cloudstack.veeam.api.dto.VmAction;
import org.apache.cloudstack.veeam.api.dto.Vms;
@ -105,7 +107,7 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
io.methodNotAllowed(resp, "GET, PUT, DELETE", outFormat);
} else if ("GET".equalsIgnoreCase(method)) {
handleGetById(id, resp, outFormat, io);
} else if ("DELETE".equalsIgnoreCase(method)) {
} else if ("PUT".equalsIgnoreCase(method)) {
handleUpdateById(id, req, resp, outFormat, io);
} else if ("DELETE".equalsIgnoreCase(method)) {
handleDeleteById(id, resp, outFormat, io);
@ -152,11 +154,51 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
handlePostNicForVmId(id, req, resp, outFormat, io);
}
return;
} else if ("snapshots".equals(subPath)) {
if (!"GET".equalsIgnoreCase(method) && !"POST".equalsIgnoreCase(method)) {
io.methodNotAllowed(resp, "GET, POST", outFormat);
} else if ("GET".equalsIgnoreCase(method)) {
handleGetSnapshotsByVmId(id, resp, outFormat, io);
} else if ("POST".equalsIgnoreCase(method)) {
handlePostSnapshotForVmId(id, req, resp, outFormat, io);
}
return;
}
} else if (idAndSubPath.size() == 3) {
String subPath = idAndSubPath.get(1);
String subId = idAndSubPath.get(2);
if ("snapshots".equals(subPath)) {
if (!"GET".equalsIgnoreCase(method) && !"DELETE".equalsIgnoreCase(method)) {
io.methodNotAllowed(resp, "GET, DELETE", outFormat);
} else if ("GET".equalsIgnoreCase(method)) {
handleGetSnapshotsById(subId, resp, outFormat, io);
} else if ("DELETE".equalsIgnoreCase(method)) {
handleDeleteSnapshotById(subId, req, resp, outFormat, io);
}
return;
}
} else if (idAndSubPath.size() == 4) {
String subPath = idAndSubPath.get(1);
String subId = idAndSubPath.get(2);
String action = idAndSubPath.get(3);
if ("snapshots".equals(subPath) && "restore".equals(action)) {
if ("POST".equalsIgnoreCase(method)) {
handleRestoreSnapshotById(subId, req, resp, outFormat, io);
} else {
io.methodNotAllowed(resp, "POST", outFormat);
}
return;
}
}
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
io.notFound(resp, null, outFormat);
}
protected String getRequestData(final HttpServletRequest req) {
String data = RouteHandler.getRequestData(req);
logger.info("Received method: {} request. Request-data: {}", req.getMethod(), data);
return data;
}
protected void handleGet(final HttpServletRequest req, final HttpServletResponse resp,
@ -192,7 +234,7 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
return;
}
final List<Vm> result = serverAdapter.listAllUserVms();
final List<Vm> result = serverAdapter.listAllInstances();
final Vms response = new Vms(result);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
@ -217,71 +259,76 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
protected void handlePost(final HttpServletRequest req, final HttpServletResponse resp,
Negotiation.OutFormat outFormat, VeeamControlServlet io) throws IOException {
String data = RouteHandler.getRequestData(req);
logger.info("Received method: POST request. Request-data: {}", data);
String data = getRequestData(req);
try {
Vm request = io.getMapper().jsonMapper().readValue(data, Vm.class);
Vm response = serverAdapter.handleCreateVm(request);
Vm response = serverAdapter.createInstance(request);
io.getWriter().write(resp, HttpServletResponse.SC_CREATED, response, outFormat);
} catch (JsonProcessingException | CloudRuntimeException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_BAD_REQUEST, "Bad request", e.getMessage(), outFormat);
io.badRequest(resp, e.getMessage(), outFormat);
}
}
protected void handleGetById(final String id, final HttpServletResponse resp, final Negotiation.OutFormat outFormat,
final VeeamControlServlet io) throws IOException {
try {
Vm response = serverAdapter.getVm(id);
Vm response = serverAdapter.getInstance(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handleUpdateById(final String id, final HttpServletRequest req, final HttpServletResponse resp, final Negotiation.OutFormat outFormat,
final VeeamControlServlet io) throws IOException {
String data = RouteHandler.getRequestData(req);
logger.info("Received POST request, but method: POST is not supported atm. Request-data: {}", data);
io.getWriter().writeFault(resp, HttpServletResponse.SC_BAD_REQUEST, "Not implemented", "", outFormat);
logger.info("Received PUT request. Request-data: {}", data);
try {
Vm request = io.getMapper().jsonMapper().readValue(data, Vm.class);
Vm response = serverAdapter.updateInstance(id, request);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handleDeleteById(final String id, final HttpServletResponse resp, final Negotiation.OutFormat outFormat,
final VeeamControlServlet io) throws IOException {
try {
serverAdapter.deleteVm(id);
serverAdapter.deleteInstance(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, "", outFormat);
} catch (CloudRuntimeException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handleStartVmById(final String id, final HttpServletRequest req, final HttpServletResponse resp, final Negotiation.OutFormat outFormat,
final VeeamControlServlet io) throws IOException {
try {
VmAction vm = serverAdapter.startVm(id);
VmAction vm = serverAdapter.startInstance(id);
io.getWriter().write(resp, HttpServletResponse.SC_ACCEPTED, vm, outFormat);
} catch (CloudRuntimeException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handleStopVmById(final String id, final HttpServletRequest req, final HttpServletResponse resp, final Negotiation.OutFormat outFormat,
final VeeamControlServlet io) throws IOException {
try {
VmAction vm = serverAdapter.stopVm(id);
VmAction vm = serverAdapter.stopInstance(id);
io.getWriter().write(resp, HttpServletResponse.SC_ACCEPTED, vm, outFormat);
} catch (CloudRuntimeException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handleShutdownVmById(final String id, final HttpServletRequest req, final HttpServletResponse resp, final Negotiation.OutFormat outFormat,
final VeeamControlServlet io) throws IOException {
try {
VmAction vm = serverAdapter.shutdownVm(id);
VmAction vm = serverAdapter.shutdownInstance(id);
io.getWriter().write(resp, HttpServletResponse.SC_ACCEPTED, vm, outFormat);
} catch (CloudRuntimeException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
@ -292,46 +339,101 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
DiskAttachments response = new DiskAttachments(disks);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handlePostDiskAttachmentForVmId(final String id, final HttpServletRequest req,
final HttpServletResponse resp, final Negotiation.OutFormat outFormat, final VeeamControlServlet io)
throws IOException {
String data = RouteHandler.getRequestData(req);
logger.info("Received method: POST request. Request-data: {}", data);
String data = getRequestData(req);
try {
DiskAttachment request = io.getMapper().jsonMapper().readValue(data, DiskAttachment.class);
DiskAttachment response = serverAdapter.handleVmAttachDisk(id, request);
DiskAttachment response = serverAdapter.handleInstanceAttachDisk(id, request);
io.getWriter().write(resp, HttpServletResponse.SC_CREATED, response, outFormat);
} catch (JsonProcessingException | CloudRuntimeException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_BAD_REQUEST, "Bad request", e.getMessage(), outFormat);
io.badRequest(resp, e.getMessage(), outFormat);
}
}
protected void handleGetNicsByVmId(final String id, final HttpServletResponse resp, final Negotiation.OutFormat outFormat,
final VeeamControlServlet io) throws IOException {
try {
List<Nic> nics = serverAdapter.listNicsByInstanceId(id);
List<Nic> nics = serverAdapter.listNicsByInstanceUuid(id);
Nics response = new Nics(nics);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handlePostNicForVmId(final String id, final HttpServletRequest req,
final HttpServletResponse resp, final Negotiation.OutFormat outFormat, final VeeamControlServlet io)
throws IOException {
String data = RouteHandler.getRequestData(req);
logger.info("Received method: POST request. Request-data: {}", data);
String data = getRequestData(req);
try {
Nic request = io.getMapper().jsonMapper().readValue(data, Nic.class);
Nic response = serverAdapter.handleVmAttachNic(id, request);
Nic response = serverAdapter.handleAttachInstanceNic(id, request);
io.getWriter().write(resp, HttpServletResponse.SC_CREATED, response, outFormat);
} catch (JsonProcessingException | CloudRuntimeException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_BAD_REQUEST, "Bad request", e.getMessage(), outFormat);
io.badRequest(resp, e.getMessage(), outFormat);
}
}
protected void handleGetSnapshotsByVmId(final String id, final HttpServletResponse resp,
final Negotiation.OutFormat outFormat, final VeeamControlServlet io) throws IOException {
try {
List<Snapshot> snapshots = serverAdapter.listSnapshotsByInstanceUuid(id);
Snapshots response = new Snapshots(snapshots);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handlePostSnapshotForVmId(final String id, final HttpServletRequest req,
final HttpServletResponse resp, final Negotiation.OutFormat outFormat, final VeeamControlServlet io)
throws IOException {
String data = getRequestData(req);
try {
Snapshot request = io.getMapper().jsonMapper().readValue(data, Snapshot.class);
Snapshot response = serverAdapter.handleCreateInstanceSnapshot(id, request);
io.getWriter().write(resp, HttpServletResponse.SC_ACCEPTED, response, outFormat);
} catch (JsonProcessingException | CloudRuntimeException e) {
io.badRequest(resp, e.getMessage(), outFormat);
}
}
protected void handleGetSnapshotsById(final String id, final HttpServletResponse resp,
final Negotiation.OutFormat outFormat, final VeeamControlServlet io) throws IOException {
try {
Snapshot response = serverAdapter.getSnapshot(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.notFound(resp, e.getMessage(), outFormat);
}
}
protected void handleDeleteSnapshotById(final String id, final HttpServletRequest req,
final HttpServletResponse resp, final Negotiation.OutFormat outFormat, final VeeamControlServlet io)
throws IOException {
boolean async = Boolean.parseBoolean(req.getParameter("async"));
try {
Snapshot snapshot = serverAdapter.deleteSnapshot(id, async);
if (snapshot != null) {
io.getWriter().write(resp, HttpServletResponse.SC_ACCEPTED, null, outFormat);
} else {
io.getWriter().write(resp, HttpServletResponse.SC_ACCEPTED, null, outFormat);
}
} catch (CloudRuntimeException e) {
io.badRequest(resp, e.getMessage(), outFormat);
}
}
protected void handleRestoreSnapshotById(final String id, final HttpServletRequest req,
final HttpServletResponse resp, final Negotiation.OutFormat outFormat, final VeeamControlServlet io)
throws IOException {
String data = getRequestData(req);
io.badRequest(resp, "Not implemented", outFormat);
}
}

View File

@ -79,7 +79,7 @@ public class VnicProfilesRouteHandler extends ManagerBase implements RouteHandle
}
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
io.notFound(resp, null, outFormat);
}
protected void handleGet(final HttpServletRequest req, final HttpServletResponse resp,
@ -96,7 +96,7 @@ public class VnicProfilesRouteHandler extends ManagerBase implements RouteHandle
VnicProfile response = serverAdapter.getVnicProfile(id);
io.getWriter().write(resp, HttpServletResponse.SC_OK, response, outFormat);
} catch (InvalidParameterValueException e) {
io.getWriter().writeFault(resp, HttpServletResponse.SC_NOT_FOUND, "Not found", e.getMessage(), outFormat);
io.notFound(resp, e.getMessage(), outFormat);
}
}
}

View File

@ -22,6 +22,7 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.cloudstack.veeam.VeeamControlService;
import org.apache.cloudstack.veeam.api.VmsRouteHandler;
import org.apache.cloudstack.veeam.api.VnicProfilesRouteHandler;
import org.apache.cloudstack.veeam.api.dto.Ip;
import org.apache.cloudstack.veeam.api.dto.Ips;
@ -46,10 +47,11 @@ public class NicVOToNicConverter {
Mac mac = new Mac();
mac.setAddress(vo.getMacAddress());
nic.setMac(mac);
nic.setLinked(true);
nic.setPlugged(true);
if (StringUtils.isBlank(vmUuid)) {
nic.setVm(Ref.of(basePath + "/vms/" + vmUuid, vmUuid));
nic.setLinked(Boolean.TRUE.toString());
nic.setPlugged(Boolean.TRUE.toString());
nic.setSynced(Boolean.TRUE.toString());
if (StringUtils.isNotBlank(vmUuid)) {
nic.setVm(Ref.of(basePath + VmsRouteHandler.BASE_ROUTE + "/" + vmUuid, vmUuid));
nic.setHref(nic.getVm().href + "/nics/" + vo.getUuid());
}
nic.setInterfaceType("virtio");
@ -70,6 +72,7 @@ public class NicVOToNicConverter {
device.setType("network");
device.setId(vo.getUuid());
device.setName("eth0");
device.setDescription(String.format("%s device", vo.getReserver()));
device.setMac(mac);
Ip ip = new Ip();
if (vo.getIPv4Address() != null) {
@ -82,6 +85,7 @@ public class NicVOToNicConverter {
ip.setVersion("v6");
}
device.setIps(new Ips(List.of(ip)));
device.setHref(vm.href + "/reporteddevices/" + vo.getUuid());
device.setVm(vm);
return device;
}

View File

@ -28,12 +28,12 @@ import org.apache.cloudstack.veeam.api.ApiService;
import org.apache.cloudstack.veeam.api.JobsRouteHandler;
import org.apache.cloudstack.veeam.api.VmsRouteHandler;
import org.apache.cloudstack.veeam.api.dto.Actions;
import org.apache.cloudstack.veeam.api.dto.BaseDto;
import org.apache.cloudstack.veeam.api.dto.Bios;
import org.apache.cloudstack.veeam.api.dto.Cpu;
import org.apache.cloudstack.veeam.api.dto.DiskAttachment;
import org.apache.cloudstack.veeam.api.dto.DiskAttachments;
import org.apache.cloudstack.veeam.api.dto.EmptyElement;
import org.apache.cloudstack.veeam.api.dto.Link;
import org.apache.cloudstack.veeam.api.dto.Nic;
import org.apache.cloudstack.veeam.api.dto.Nics;
import org.apache.cloudstack.veeam.api.dto.Os;
@ -71,6 +71,7 @@ public final class UserVmJoinVOToVmConverter {
dst.description = src.getDisplayName();
dst.href = basePath + VmsRouteHandler.BASE_ROUTE + "/" + src.getUuid();
dst.status = mapStatus(src.getState());
dst.setCreationTime(src.getCreated().getTime());
final Date lastUpdated = src.getLastUpdated() != null ? src.getLastUpdated() : src.getCreated();
if ("down".equals(dst.status)) {
dst.stopTime = lastUpdated.getTime();
@ -106,7 +107,7 @@ public final class UserVmJoinVOToVmConverter {
}
}
dst.memory = src.getRamSize() * 1024L * 1024L;
dst.memory = String.valueOf(src.getRamSize() * 1024L * 1024L);
dst.cpu = new Cpu(src.getArch(), new Topology(src.getCpu(), 1, 1));
dst.os = new Os();
@ -129,17 +130,15 @@ public final class UserVmJoinVOToVmConverter {
}
dst.actions = new Actions(List.of(
new Link("start", dst.href + "/start"),
new Link("stop", dst.href + "/stop"),
new Link("shutdown", dst.href + "/shutdown")
BaseDto.getActionLink("start", dst.href),
BaseDto.getActionLink("stop", dst.href),
BaseDto.getActionLink("shutdown", dst.href)
));
dst.link = List.of(
new Link("diskattachments",
dst.href + "/diskattachments"),
new Link("nics",
dst.href + "/nics"),
new Link("snapshots",
dst.href + "/snapshots")
BaseDto.getActionLink("diskattachments", dst.href),
BaseDto.getActionLink("nics", dst.href),
BaseDto.getActionLink("reporteddevices", dst.href),
BaseDto.getActionLink("snapshots", dst.href)
);
dst.tags = new EmptyElement();
@ -162,21 +161,12 @@ public final class UserVmJoinVOToVmConverter {
}
private static String mapStatus(final VirtualMachine.State state) {
if (state == null) {
return null;
}
// CloudStack-ish states -> oVirt-ish up/down
if (Arrays.asList(VirtualMachine.State.Running, VirtualMachine.State.Starting,
VirtualMachine.State.Migrating, VirtualMachine.State.Restoring).contains(state)) {
return "up";
}
if (Arrays.asList(VirtualMachine.State.Stopped, VirtualMachine.State.Stopping,
VirtualMachine.State.Shutdown, VirtualMachine.State.Error,
VirtualMachine.State.Expunging).contains(state)) {
return "down";
}
return null;
return "down";
}
private static Ref buildRef(final String baseHref, final String suffix, final String id) {

View File

@ -0,0 +1,54 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.veeam.api.converter;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.cloudstack.veeam.VeeamControlService;
import org.apache.cloudstack.veeam.api.VmsRouteHandler;
import org.apache.cloudstack.veeam.api.dto.Actions;
import org.apache.cloudstack.veeam.api.dto.BaseDto;
import org.apache.cloudstack.veeam.api.dto.Ref;
import org.apache.cloudstack.veeam.api.dto.Snapshot;
import com.cloud.vm.snapshot.VMSnapshot;
import com.cloud.vm.snapshot.VMSnapshotVO;
public class VmSnapshotVOToSnapshotConverter {
public static Snapshot toSnapshot(final VMSnapshotVO vmSnapshotVO, String vmUuid) {
final String basePath = VeeamControlService.ContextPath.value();
final Snapshot snapshot = new Snapshot();
snapshot.setId(vmSnapshotVO.getUuid());
snapshot.setHref(basePath + VmsRouteHandler.BASE_ROUTE + "/" + vmUuid + "/snapshots/" + vmSnapshotVO.getUuid());
snapshot.setVm(Ref.of(basePath + VmsRouteHandler.BASE_ROUTE + "/" + vmUuid, vmUuid));
snapshot.setDescription(vmSnapshotVO.getDescription());
snapshot.setSnapshotType("active");
snapshot.setDate(vmSnapshotVO.getCreated().getTime());
snapshot.setPersistMemorystate(String.valueOf(VMSnapshotVO.Type.DiskAndMemory.equals(vmSnapshotVO.getType())));
snapshot.setSnapshotStatus(VMSnapshot.State.Ready.equals(vmSnapshotVO.getState()) ? "ok" : "locked");
snapshot.setActions(new Actions(List.of(BaseDto.getActionLink("restore", snapshot.getHref()))));
return snapshot;
}
public static List<Snapshot> toSnapshotList(final List<VMSnapshotVO> vmSnapshotVOList, final String vmUuid) {
return vmSnapshotVOList.stream()
.map(v -> toSnapshot(v, vmUuid))
.collect(Collectors.toList());
}
}

View File

@ -40,13 +40,14 @@ import com.cloud.storage.VolumeStats;
public class VolumeJoinVOToDiskConverter {
public static Disk toDisk(final VolumeJoinVO vol) {
final Disk disk = new Disk();
final String basePath = VeeamControlService.ContextPath.value() + ApiService.BASE_ROUTE;
final String basePath = VeeamControlService.ContextPath.value();
final String apiBasePath = basePath + ApiService.BASE_ROUTE;
final String diskId = vol.getUuid();
final String diskHref = basePath + DisksRouteHandler.BASE_ROUTE + "/" + diskId;
disk.id = diskId;
disk.href = diskHref;
disk.setBootable(String.valueOf(Volume.Type.ROOT.equals(vol.getVolumeType())));
// Names
disk.name = vol.getName();
@ -98,7 +99,7 @@ public class VolumeJoinVOToDiskConverter {
// Disk profile (optional)
disk.diskProfile = Ref.of(
basePath + "/diskprofiles/" + vol.getDiskOfferingUuid(),
apiBasePath + "/diskprofiles/" + vol.getDiskOfferingUuid(),
String.valueOf(vol.getDiskOfferingUuid())
);
@ -107,7 +108,7 @@ public class VolumeJoinVOToDiskConverter {
Disk.StorageDomains sds = new Disk.StorageDomains();
sds.storageDomain = List.of(
Ref.of(
basePath + "/storagedomains/" + vol.getPoolUuid(),
apiBasePath + "/storagedomains/" + vol.getPoolUuid(),
vol.getPoolUuid()
)
);
@ -134,7 +135,6 @@ public class VolumeJoinVOToDiskConverter {
public static DiskAttachment toDiskAttachment(final VolumeJoinVO vol) {
final DiskAttachment da = new DiskAttachment();
final String basePath = VeeamControlService.ContextPath.value();
final String apiBase = basePath + ApiService.BASE_ROUTE;
final String diskAttachmentId = vol.getUuid();
da.vm = Ref.of(
@ -143,7 +143,7 @@ public class VolumeJoinVOToDiskConverter {
);
da.id = diskAttachmentId;
da.href = da.vm.href + "/diskattachements/" + diskAttachmentId;;
da.href = da.vm.href + "/diskattachments/" + diskAttachmentId;;
// Links
da.disk = toDisk(vol);

View File

@ -0,0 +1,47 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.veeam.api.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class BaseDto {
private String href;
private String id;
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public static Link getActionLink(final String action, final String baseHref) {
return new Link(action, baseHref + "/" + action);
}
}

View File

@ -28,6 +28,8 @@ import java.util.List;
@JacksonXmlRootElement(localName = "disk")
public final class Disk {
private String bootable;
@JsonProperty("actual_size")
public String actualSize;
@ -88,6 +90,14 @@ public final class Disk {
public Disk() {}
public String getBootable() {
return bootable;
}
public void setBootable(String bootable) {
this.bootable = bootable;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "storage_domains")
public static final class StorageDomains {

View File

@ -34,6 +34,7 @@ public class Nic {
private String linked;
private Mac mac;
private String plugged;
public String synced;
private Ref vnicProfile;
private Ref vm;
private ReportedDevices reportedDevices;
@ -81,12 +82,12 @@ public class Nic {
this.interfaceType = interfaceType;
}
public boolean isLinked() {
return Boolean.parseBoolean(linked);
public String getLinked() {
return linked;
}
public void setLinked(boolean linked) {
this.linked = Boolean.toString(linked);
public void setLinked(String linked) {
this.linked = linked;
}
public Mac getMac() {
@ -97,12 +98,20 @@ public class Nic {
this.mac = mac;
}
public boolean isPlugged() {
return Boolean.parseBoolean(plugged);
public String getPlugged() {
return plugged;
}
public void setPlugged(boolean plugged) {
this.plugged = Boolean.toString(plugged);
public void setPlugged(String plugged) {
this.plugged = plugged;
}
public String getSynced() {
return synced;
}
public void setSynced(String synced) {
this.synced = synced;
}
public Ref getVnicProfile() {

View File

@ -25,6 +25,7 @@ public class ReportedDevice {
private Mac Mac;
private String name;
private String type;
private String href;
private Ref vm;
public String getComment() {
@ -83,6 +84,14 @@ public class ReportedDevice {
this.type = type;
}
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
public Ref getVm() {
return vm;
}

View File

@ -0,0 +1,104 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Snapshot extends BaseDto {
// epoch millis
private Long date;
private String persistMemorystate;
private String snapshotStatus;
private String snapshotType;
private Actions actions;
private String description;
@JacksonXmlElementWrapper(useWrapping = false)
private List<Link> link;
private Ref vm;
public Snapshot() {}
public Long getDate() {
return date;
}
public void setDate(final Long date) {
this.date = date;
}
public String getPersistMemorystate() {
return persistMemorystate;
}
public void setPersistMemorystate(final String persistMemorystate) {
this.persistMemorystate = persistMemorystate;
}
public String getSnapshotStatus() {
return snapshotStatus;
}
public void setSnapshotStatus(final String snapshotStatus) {
this.snapshotStatus = snapshotStatus;
}
public String getSnapshotType() {
return snapshotType;
}
public void setSnapshotType(final String snapshotType) {
this.snapshotType = snapshotType;
}
public Actions getActions() {
return actions;
}
public void setActions(final Actions actions) {
this.actions = actions;
}
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
public List<Link> getLink() {
return link;
}
public void setLink(final List<Link> link) {
this.link = link;
}
public Ref getVm() {
return vm;
}
public void setVm(Ref vm) {
this.vm = vm;
}
}

View File

@ -0,0 +1,41 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.veeam.api.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "snapshots")
public final class Snapshots {
@JsonProperty("snapshot")
@JacksonXmlElementWrapper(useWrapping = false)
public List<Snapshot> snapshot;
public Snapshots() {}
public Snapshots(final List<Snapshot> snapshot) {
this.snapshot = snapshot;
}
}

View File

@ -43,6 +43,8 @@ public final class Vm {
@JacksonXmlProperty(localName = "stop_reason")
public String stopReason; // empty string allowed
private Long creationTime;
@JsonProperty("stop_time")
@JacksonXmlProperty(localName = "stop_time")
public Long stopTime; // epoch millis
@ -57,7 +59,7 @@ public final class Vm {
public Ref cluster;
public Ref host;
public Long memory; // bytes
public String memory; // bytes
public Cpu cpu;
public Os os;
public Bios bios;
@ -77,6 +79,14 @@ public final class Vm {
public Vm() {}
public Long getCreationTime() {
return creationTime;
}
public void setCreationTime(Long creationTime) {
this.creationTime = creationTime;
}
public Long getStartTime() {
return startTime;
}

View File

@ -22,13 +22,13 @@ import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class VmInitialization {
private String contentData;
private String customScript;
public String getContentData() {
return contentData;
public String getCustomScript() {
return customScript;
}
public void setContentData(String contentData) {
this.contentData = contentData;
public void setCustomScript(String customScript) {
this.customScript = customScript;
}
}

View File

@ -65,7 +65,7 @@ public class PkiResourceRouteHandler extends ManagerBase implements RouteHandler
return;
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
io.notFound(resp, null, outFormat);
}
protected void handleGet(HttpServletRequest req, HttpServletResponse resp,

View File

@ -55,7 +55,7 @@ public class SsoService extends ManagerBase implements RouteHandler {
return;
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
io.notFound(resp, null, outFormat);
}
protected void handleToken(HttpServletRequest req, HttpServletResponse resp,