mirror of https://github.com/apache/cloudstack.git
changes
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
parent
a30eb280e5
commit
f52b114c8d
|
|
@ -0,0 +1,123 @@
|
|||
// 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.cloudstack.veeam.RouteHandler;
|
||||
import org.apache.cloudstack.veeam.VeeamControlServlet;
|
||||
import org.apache.cloudstack.veeam.api.converter.ClusterVOToClusterConverter;
|
||||
import org.apache.cloudstack.veeam.api.dto.Cluster;
|
||||
import org.apache.cloudstack.veeam.api.dto.Clusters;
|
||||
import org.apache.cloudstack.veeam.utils.Negotiation;
|
||||
import org.apache.cloudstack.veeam.utils.PathUtil;
|
||||
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
|
||||
public class ClustersRouteHandler extends ManagerBase implements RouteHandler {
|
||||
public static final String BASE_ROUTE = "/api/clusters";
|
||||
|
||||
@Inject
|
||||
ClusterDao clusterDao;
|
||||
|
||||
@Inject
|
||||
DataCenterDao dataCenterDao;
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int priority() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(String method, String path) {
|
||||
return getSanitizedPath(path).startsWith(BASE_ROUTE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(HttpServletRequest req, HttpServletResponse resp, String path, Negotiation.OutFormat outFormat, VeeamControlServlet io) throws IOException {
|
||||
final String method = req.getMethod();
|
||||
if (!"GET".equalsIgnoreCase(method)) {
|
||||
io.methodNotAllowed(resp, "GET", outFormat);
|
||||
return;
|
||||
}
|
||||
final String sanitizedPath = getSanitizedPath(path);
|
||||
if (sanitizedPath.equals(BASE_ROUTE)) {
|
||||
handleGet(req, resp, outFormat, io);
|
||||
return;
|
||||
}
|
||||
|
||||
Pair<String, String> idAndSubPath = PathUtil.extractIdAndSubPath(sanitizedPath, BASE_ROUTE);
|
||||
if (idAndSubPath != null) {
|
||||
// /api/disks/{id}
|
||||
if (idAndSubPath.first() != null) {
|
||||
if (idAndSubPath.second() == null) {
|
||||
handleGetById(idAndSubPath.first(), resp, outFormat, io);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found");
|
||||
}
|
||||
|
||||
public void handleGet(final HttpServletRequest req, final HttpServletResponse resp,
|
||||
Negotiation.OutFormat outFormat, VeeamControlServlet io) throws IOException {
|
||||
final List<Cluster> result = ClusterVOToClusterConverter.toClusterList(listClusters(), this::getZoneById);
|
||||
final Clusters response = new Clusters(result);
|
||||
|
||||
io.getWriter().write(resp, 200, response, outFormat);
|
||||
}
|
||||
|
||||
protected List<ClusterVO> listClusters() {
|
||||
return clusterDao.listAll();
|
||||
}
|
||||
|
||||
public void handleGetById(final String id, final HttpServletResponse resp, final Negotiation.OutFormat outFormat,
|
||||
final VeeamControlServlet io) throws IOException {
|
||||
final ClusterVO vo = clusterDao.findByUuid(id);
|
||||
if (vo == null) {
|
||||
io.notFound(resp, "DataCenter not found: " + id, outFormat);
|
||||
return;
|
||||
}
|
||||
Cluster response = ClusterVOToClusterConverter.toCluster(vo, this::getZoneById);
|
||||
|
||||
io.getWriter().write(resp, 200, response, outFormat);
|
||||
}
|
||||
|
||||
private DataCenterVO getZoneById(Long zoneId) {
|
||||
if (zoneId == null) {
|
||||
return null;
|
||||
}
|
||||
return dataCenterDao.findById(zoneId);
|
||||
}
|
||||
}
|
||||
|
|
@ -41,8 +41,10 @@ import org.apache.cloudstack.veeam.api.response.VmEntityResponse;
|
|||
import org.apache.cloudstack.veeam.utils.Negotiation;
|
||||
import org.apache.cloudstack.veeam.utils.PathUtil;
|
||||
|
||||
import com.cloud.api.query.dao.HostJoinDao;
|
||||
import com.cloud.api.query.dao.UserVmJoinDao;
|
||||
import com.cloud.api.query.dao.VolumeJoinDao;
|
||||
import com.cloud.api.query.vo.HostJoinVO;
|
||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
|
|
@ -56,6 +58,9 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
|
|||
@Inject
|
||||
UserVmJoinDao userVmJoinDao;
|
||||
|
||||
@Inject
|
||||
HostJoinDao hostJoinDao;
|
||||
|
||||
@Inject
|
||||
VolumeJoinDao volumeJoinDao;
|
||||
|
||||
|
|
@ -143,7 +148,7 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
final List<Vm> result = UserVmJoinVOToVmConverter.toVmList(listUserVms());
|
||||
final List<Vm> result = UserVmJoinVOToVmConverter.toVmList(listUserVms(), this::getHostById);
|
||||
final VmCollectionResponse response = new VmCollectionResponse(result);
|
||||
|
||||
io.getWriter().write(resp, 200, response, outFormat);
|
||||
|
|
@ -178,7 +183,7 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
|
|||
io.notFound(resp, "VM not found: " + id, outFormat);
|
||||
return;
|
||||
}
|
||||
VmEntityResponse response = new VmEntityResponse(UserVmJoinVOToVmConverter.toVm(userVmJoinVO));
|
||||
VmEntityResponse response = new VmEntityResponse(UserVmJoinVOToVmConverter.toVm(userVmJoinVO, this::getHostById));
|
||||
|
||||
io.getWriter().write(resp, 200, response, outFormat);
|
||||
}
|
||||
|
|
@ -196,4 +201,12 @@ public class VmsRouteHandler extends ManagerBase implements RouteHandler {
|
|||
|
||||
io.getWriter().write(resp, 200, response, outFormat);
|
||||
}
|
||||
|
||||
private HostJoinVO getHostById(Long hostId) {
|
||||
if (hostId == null) {
|
||||
return null;
|
||||
}
|
||||
return hostJoinDao.findById(hostId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
// 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.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.cloudstack.veeam.VeeamControlService;
|
||||
import org.apache.cloudstack.veeam.api.ClustersRouteHandler;
|
||||
import org.apache.cloudstack.veeam.api.DataCentersRouteHandler;
|
||||
import org.apache.cloudstack.veeam.api.dto.Actions;
|
||||
import org.apache.cloudstack.veeam.api.dto.Cluster;
|
||||
import org.apache.cloudstack.veeam.api.dto.Link;
|
||||
import org.apache.cloudstack.veeam.api.dto.Ref;
|
||||
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
|
||||
public class ClusterVOToClusterConverter {
|
||||
public static Cluster toCluster(final ClusterVO vo, final Function<Long, DataCenterVO> dataCenterResolver) {
|
||||
final Cluster c = new Cluster();
|
||||
final String basePath = VeeamControlService.ContextPath.value();
|
||||
|
||||
// NOTE: oVirt uses UUIDs. If your ClusterVO id is numeric, generate a stable UUID:
|
||||
// - Prefer: store a UUID in details table and reuse it
|
||||
// - Fallback: name-based UUID from "cluster:<id>"
|
||||
final String clusterId = vo.getUuid();
|
||||
c.id = clusterId;
|
||||
c.href = basePath + ClustersRouteHandler.BASE_ROUTE + "/" + clusterId;
|
||||
|
||||
c.name = vo.getName();
|
||||
c.description = vo.getName();
|
||||
c.comment = "";
|
||||
|
||||
// --- sensible defaults (match your sample)
|
||||
c.ballooningEnabled = "true";
|
||||
c.biosType = "q35_ovmf"; // or "q35_secure_boot" if you want to align with VM BIOS you saw
|
||||
c.fipsMode = "disabled";
|
||||
c.firewallType = "firewalld";
|
||||
c.glusterService = "false";
|
||||
c.haReservation = "false";
|
||||
c.switchType = "legacy";
|
||||
c.threadsAsCores = "false";
|
||||
c.trustedService = "false";
|
||||
c.tunnelMigration = "false";
|
||||
c.upgradeInProgress = "false";
|
||||
c.upgradePercentComplete = "0";
|
||||
c.virtService = "true";
|
||||
c.vncEncryption = "false";
|
||||
c.logMaxMemoryUsedThreshold = "95";
|
||||
c.logMaxMemoryUsedThresholdType = "percentage";
|
||||
|
||||
// --- cpu (best-effort defaults)
|
||||
final Cluster.ClusterCpu cpu = new Cluster.ClusterCpu();
|
||||
cpu.architecture = "x86_64";
|
||||
cpu.type = "x86_64"; // replace if you can detect host cpu model
|
||||
c.cpu = cpu;
|
||||
|
||||
// --- version (ovirt engine version; keep fixed unless you want to expose something else)
|
||||
final Cluster.Version ver = new Cluster.Version();
|
||||
ver.major = "4";
|
||||
ver.minor = "8";
|
||||
c.version = ver;
|
||||
|
||||
// --- ksm / memory policy (defaults)
|
||||
c.ksm = new Cluster.Ksm();
|
||||
c.ksm.enabled = "true";
|
||||
c.ksm.mergeAcrossNodes = "true";
|
||||
|
||||
c.memoryPolicy = new Cluster.MemoryPolicy();
|
||||
c.memoryPolicy.overCommit = new Cluster.OverCommit();
|
||||
c.memoryPolicy.overCommit.percent = "100";
|
||||
c.memoryPolicy.transparentHugepages = new Cluster.TransparentHugepages();
|
||||
c.memoryPolicy.transparentHugepages.enabled = "true";
|
||||
|
||||
// --- migration defaults
|
||||
c.migration = new Cluster.Migration();
|
||||
c.migration.autoConverge = "inherit";
|
||||
c.migration.bandwidth = new Cluster.Bandwidth();
|
||||
c.migration.bandwidth.assignmentMethod = "auto";
|
||||
c.migration.compressed = "inherit";
|
||||
c.migration.encrypted = "inherit";
|
||||
c.migration.parallelMigrationsPolicy = "disabled";
|
||||
// policy ref (dummy but valid shape)
|
||||
c.migration.policy = Ref.of(basePath + "/migrationpolicies/" + stableUuid("migrationpolicy:default"),
|
||||
stableUuid("migrationpolicy:default")
|
||||
);
|
||||
|
||||
// --- rng sources
|
||||
c.requiredRngSources = new Cluster.RequiredRngSources();
|
||||
c.requiredRngSources.requiredRngSource = Collections.singletonList("urandom");
|
||||
|
||||
// --- error handling
|
||||
c.errorHandling = new Cluster.ErrorHandling();
|
||||
c.errorHandling.onError = "migrate";
|
||||
|
||||
// --- fencing policy defaults
|
||||
c.fencingPolicy = new Cluster.FencingPolicy();
|
||||
c.fencingPolicy.enabled = "true";
|
||||
c.fencingPolicy.skipIfConnectivityBroken = new Cluster.SkipIfConnectivityBroken();
|
||||
c.fencingPolicy.skipIfConnectivityBroken.enabled = "false";
|
||||
c.fencingPolicy.skipIfConnectivityBroken.threshold = "50";
|
||||
c.fencingPolicy.skipIfGlusterBricksUp = "false";
|
||||
c.fencingPolicy.skipIfGlusterQuorumNotMet = "false";
|
||||
c.fencingPolicy.skipIfSdActive = new Cluster.SkipIfSdActive();
|
||||
c.fencingPolicy.skipIfSdActive.enabled = "false";
|
||||
|
||||
// --- scheduling policy props (optional; dummy ok)
|
||||
c.customSchedulingPolicyProperties = new Cluster.CustomSchedulingPolicyProperties();
|
||||
final Cluster.Property p1 = new Cluster.Property(); p1.name = "HighUtilization"; p1.value = "80";
|
||||
final Cluster.Property p2 = new Cluster.Property(); p2.name = "CpuOverCommitDurationMinutes"; p2.value = "2";
|
||||
c.customSchedulingPolicyProperties.property = List.of(p1, p2);
|
||||
|
||||
// --- data_center ref mapping (CloudStack cluster -> pod -> zone)
|
||||
if (dataCenterResolver != null) {
|
||||
final DataCenterVO zone = dataCenterResolver.apply(vo.getDataCenterId());
|
||||
if (zone != null) {
|
||||
c.dataCenter = Ref.of(basePath + DataCentersRouteHandler.BASE_ROUTE + "/" + zone.getUuid(), zone.getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
// --- mac pool & scheduling policy refs (dummy but consistent)
|
||||
c.macPool = Ref.of(basePath + "/macpools/" + stableUuid("macpool:default"),
|
||||
stableUuid("macpool:default"));
|
||||
c.schedulingPolicy = Ref.of(basePath + "/schedulingpolicies/" + stableUuid("schedpolicy:default"),
|
||||
stableUuid("schedpolicy:default"));
|
||||
|
||||
// --- actions.links (can be omitted; but Veeam sometimes expects actions to exist)
|
||||
final Actions actions = new Actions();
|
||||
actions.link = Collections.emptyList();
|
||||
c.actions = actions;
|
||||
|
||||
// --- related links (optional)
|
||||
c.link = List.of(
|
||||
new Link("networks", c.href + "/networks")
|
||||
);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public static List<Cluster> toClusterList(final List<ClusterVO> voList,
|
||||
final Function<Long, DataCenterVO> dataCenterResolver) {
|
||||
return voList.stream()
|
||||
.map(vo -> toCluster(vo, dataCenterResolver))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static String stableUuid(final String key) {
|
||||
// deterministic UUID, so the same ClusterVO maps to same "ovirt id" every time
|
||||
return UUID.nameUUIDFromBytes(key.getBytes()).toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ public class DataCenterVOToDataCenterConverter {
|
|||
public static DataCenter toDataCenter(final DataCenterVO zone) {
|
||||
final String id = zone.getUuid();
|
||||
final String basePath = VeeamControlService.ContextPath.value();
|
||||
final String href = basePath + DataCentersRouteHandler.BASE_ROUTE + "/datacenters/" + id;
|
||||
final String href = basePath + DataCentersRouteHandler.BASE_ROUTE + DataCentersRouteHandler.BASE_ROUTE + "/" + id;
|
||||
|
||||
final DataCenter dc = new DataCenter();
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public class StoreVOToStorageDomainConverter {
|
|||
// dc attachment
|
||||
String dcId = pool.getZoneUuid();
|
||||
DataCenter dc = new DataCenter();
|
||||
dc.href = href(basePath, DataCentersRouteHandler.BASE_ROUTE + dcId);
|
||||
dc.href = href(basePath, DataCentersRouteHandler.BASE_ROUTE + "/" + dcId);
|
||||
dc.id = dcId;
|
||||
sd.dataCenters = new DataCenters(List.of(dc));
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ public class StoreVOToStorageDomainConverter {
|
|||
// Optionally include dc attachment (your first object had it; second didn’t)
|
||||
String dcId = store.getZoneUuid();
|
||||
DataCenter dc = new DataCenter();
|
||||
dc.href = href(basePath, DataCentersRouteHandler.BASE_ROUTE + dcId);
|
||||
dc.href = href(basePath, DataCentersRouteHandler.BASE_ROUTE + "/" + dcId);
|
||||
dc.id = dcId;
|
||||
sd.dataCenters = new DataCenters(List.of(dc));
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package org.apache.cloudstack.veeam.api.converter;
|
|||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.cloudstack.veeam.VeeamControlService;
|
||||
|
|
@ -34,6 +35,7 @@ import org.apache.cloudstack.veeam.api.dto.Topology;
|
|||
import org.apache.cloudstack.veeam.api.dto.Vm;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.api.query.vo.HostJoinVO;
|
||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
||||
|
|
@ -47,7 +49,7 @@ public final class UserVmJoinVOToVmConverter {
|
|||
*
|
||||
* @param src UserVmJoinVO
|
||||
*/
|
||||
public static Vm toVm(final UserVmJoinVO src) {
|
||||
public static Vm toVm(final UserVmJoinVO src, final Function<Long, HostJoinVO> hostResolver) {
|
||||
if (src == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -71,14 +73,32 @@ public final class UserVmJoinVOToVmConverter {
|
|||
);
|
||||
dst.template = template;
|
||||
dst.originalTemplate = template;
|
||||
dst.host = buildRef(
|
||||
basePath + ApiService.BASE_ROUTE,
|
||||
"hosts",
|
||||
src.getHostUuid());
|
||||
dst.cluster = buildRef(
|
||||
basePath + ApiService.BASE_ROUTE,
|
||||
"clusters",
|
||||
src.getHostUuid());
|
||||
if (StringUtils.isNotBlank(src.getHostUuid())) {
|
||||
dst.host = buildRef(
|
||||
basePath + ApiService.BASE_ROUTE,
|
||||
"hosts",
|
||||
src.getHostUuid());
|
||||
|
||||
}
|
||||
if (hostResolver != null) {
|
||||
HostJoinVO hostVo = hostResolver.apply(src.getHostId() == null ? src.getLastHostId() : src.getHostId());
|
||||
if (hostVo != null) {
|
||||
dst.host = buildRef(
|
||||
basePath + ApiService.BASE_ROUTE,
|
||||
"hosts",
|
||||
hostVo.getUuid());
|
||||
dst.cluster = buildRef(
|
||||
basePath + ApiService.BASE_ROUTE,
|
||||
"clusters",
|
||||
hostVo.getClusterUuid());
|
||||
}
|
||||
}
|
||||
Long hostId = src.getHostId() != null ? src.getHostId() : src.getLastHostId();
|
||||
if (hostId != null) {
|
||||
// I want to get Host data from hostJoinDao but this is a static method without dao access.
|
||||
|
||||
}
|
||||
|
||||
dst.memory = src.getRamSize() * 1024L * 1024L;
|
||||
|
||||
dst.cpu = new Cpu(src.getArch(), new Topology(src.getCpu(), src.getCpu(), 1));
|
||||
|
|
@ -102,9 +122,9 @@ public final class UserVmJoinVOToVmConverter {
|
|||
return dst;
|
||||
}
|
||||
|
||||
public static List<Vm> toVmList(final List<UserVmJoinVO> srcList) {
|
||||
public static List<Vm> toVmList(final List<UserVmJoinVO> srcList, final Function<Long, HostJoinVO> hostResolver) {
|
||||
return srcList.stream()
|
||||
.map(UserVmJoinVOToVmConverter::toVm)
|
||||
.map(v -> toVm(v, hostResolver))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import java.util.stream.Collectors;
|
|||
|
||||
import org.apache.cloudstack.veeam.VeeamControlService;
|
||||
import org.apache.cloudstack.veeam.api.ApiService;
|
||||
import org.apache.cloudstack.veeam.api.DisksRouteHandler;
|
||||
import org.apache.cloudstack.veeam.api.dto.Actions;
|
||||
import org.apache.cloudstack.veeam.api.dto.Disk;
|
||||
import org.apache.cloudstack.veeam.api.dto.DiskAttachment;
|
||||
|
|
@ -38,10 +39,10 @@ import com.cloud.storage.VolumeStats;
|
|||
public class VolumeJoinVOToDiskConverter {
|
||||
public static Disk toDisk(final VolumeJoinVO vol) {
|
||||
final Disk disk = new Disk();
|
||||
final String apiBase = VeeamControlService.ContextPath.value() + ApiService.BASE_ROUTE;
|
||||
final String basePath = VeeamControlService.ContextPath.value() + ApiService.BASE_ROUTE;
|
||||
|
||||
final String diskId = vol.getUuid();
|
||||
final String diskHref = apiBase + "/disks/" + diskId;
|
||||
final String diskHref = basePath + DisksRouteHandler.BASE_ROUTE + "/" + diskId;
|
||||
|
||||
disk.id = diskId;
|
||||
disk.href = diskHref;
|
||||
|
|
@ -49,7 +50,7 @@ public class VolumeJoinVOToDiskConverter {
|
|||
// Names
|
||||
disk.name = vol.getName();
|
||||
disk.alias = vol.getName();
|
||||
disk.description = "";
|
||||
disk.description = vol.getName();
|
||||
|
||||
// Sizes (bytes)
|
||||
final long size = vol.getSize();
|
||||
|
|
@ -96,7 +97,7 @@ public class VolumeJoinVOToDiskConverter {
|
|||
|
||||
// Disk profile (optional)
|
||||
disk.diskProfile = Ref.of(
|
||||
apiBase + "/diskprofiles/" + vol.getDiskOfferingId(),
|
||||
basePath + "/diskprofiles/" + vol.getDiskOfferingId(),
|
||||
String.valueOf(vol.getDiskOfferingId())
|
||||
);
|
||||
|
||||
|
|
@ -105,7 +106,7 @@ public class VolumeJoinVOToDiskConverter {
|
|||
Disk.StorageDomains sds = new Disk.StorageDomains();
|
||||
sds.storageDomain = List.of(
|
||||
Ref.of(
|
||||
apiBase + "/storagedomains/" + vol.getPoolUuid(),
|
||||
basePath + "/storagedomains/" + vol.getPoolUuid(),
|
||||
vol.getPoolUuid()
|
||||
)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,280 @@
|
|||
// 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.JacksonXmlProperty;
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JacksonXmlRootElement(localName = "cluster")
|
||||
public final class Cluster {
|
||||
|
||||
// --- common identity
|
||||
public String href;
|
||||
public String id;
|
||||
public String name;
|
||||
public String description;
|
||||
public String comment;
|
||||
|
||||
// --- oVirt-ish knobs (strings in oVirt JSON)
|
||||
@JsonProperty("ballooning_enabled")
|
||||
@JacksonXmlProperty(localName = "ballooning_enabled")
|
||||
public String ballooningEnabled; // "true"/"false"
|
||||
|
||||
@JsonProperty("bios_type")
|
||||
@JacksonXmlProperty(localName = "bios_type")
|
||||
public String biosType; // e.g. "q35_ovmf"
|
||||
|
||||
public ClusterCpu cpu;
|
||||
|
||||
@JsonProperty("custom_scheduling_policy_properties")
|
||||
@JacksonXmlProperty(localName = "custom_scheduling_policy_properties")
|
||||
public CustomSchedulingPolicyProperties customSchedulingPolicyProperties;
|
||||
|
||||
@JsonProperty("error_handling")
|
||||
@JacksonXmlProperty(localName = "error_handling")
|
||||
public ErrorHandling errorHandling;
|
||||
|
||||
@JsonProperty("fencing_policy")
|
||||
@JacksonXmlProperty(localName = "fencing_policy")
|
||||
public FencingPolicy fencingPolicy;
|
||||
|
||||
@JsonProperty("fips_mode")
|
||||
@JacksonXmlProperty(localName = "fips_mode")
|
||||
public String fipsMode; // "disabled"
|
||||
|
||||
@JsonProperty("firewall_type")
|
||||
@JacksonXmlProperty(localName = "firewall_type")
|
||||
public String firewallType; // "firewalld"
|
||||
|
||||
@JsonProperty("gluster_service")
|
||||
@JacksonXmlProperty(localName = "gluster_service")
|
||||
public String glusterService;
|
||||
|
||||
@JsonProperty("ha_reservation")
|
||||
@JacksonXmlProperty(localName = "ha_reservation")
|
||||
public String haReservation;
|
||||
|
||||
public Ksm ksm;
|
||||
|
||||
@JsonProperty("log_max_memory_used_threshold")
|
||||
@JacksonXmlProperty(localName = "log_max_memory_used_threshold")
|
||||
public String logMaxMemoryUsedThreshold;
|
||||
|
||||
@JsonProperty("log_max_memory_used_threshold_type")
|
||||
@JacksonXmlProperty(localName = "log_max_memory_used_threshold_type")
|
||||
public String logMaxMemoryUsedThresholdType;
|
||||
|
||||
@JsonProperty("memory_policy")
|
||||
@JacksonXmlProperty(localName = "memory_policy")
|
||||
public MemoryPolicy memoryPolicy;
|
||||
|
||||
public Migration migration;
|
||||
|
||||
@JsonProperty("required_rng_sources")
|
||||
@JacksonXmlProperty(localName = "required_rng_sources")
|
||||
public RequiredRngSources requiredRngSources;
|
||||
|
||||
@JsonProperty("switch_type")
|
||||
@JacksonXmlProperty(localName = "switch_type")
|
||||
public String switchType;
|
||||
|
||||
@JsonProperty("threads_as_cores")
|
||||
@JacksonXmlProperty(localName = "threads_as_cores")
|
||||
public String threadsAsCores;
|
||||
|
||||
@JsonProperty("trusted_service")
|
||||
@JacksonXmlProperty(localName = "trusted_service")
|
||||
public String trustedService;
|
||||
|
||||
@JsonProperty("tunnel_migration")
|
||||
@JacksonXmlProperty(localName = "tunnel_migration")
|
||||
public String tunnelMigration;
|
||||
|
||||
@JsonProperty("upgrade_in_progress")
|
||||
@JacksonXmlProperty(localName = "upgrade_in_progress")
|
||||
public String upgradeInProgress;
|
||||
|
||||
@JsonProperty("upgrade_percent_complete")
|
||||
@JacksonXmlProperty(localName = "upgrade_percent_complete")
|
||||
public String upgradePercentComplete;
|
||||
|
||||
public Version version;
|
||||
|
||||
@JsonProperty("virt_service")
|
||||
@JacksonXmlProperty(localName = "virt_service")
|
||||
public String virtService;
|
||||
|
||||
@JsonProperty("vnc_encryption")
|
||||
@JacksonXmlProperty(localName = "vnc_encryption")
|
||||
public String vncEncryption;
|
||||
|
||||
// --- references
|
||||
@JsonProperty("data_center")
|
||||
@JacksonXmlProperty(localName = "data_center")
|
||||
public Ref dataCenter;
|
||||
|
||||
@JsonProperty("mac_pool")
|
||||
@JacksonXmlProperty(localName = "mac_pool")
|
||||
public Ref macPool;
|
||||
|
||||
@JsonProperty("scheduling_policy")
|
||||
@JacksonXmlProperty(localName = "scheduling_policy")
|
||||
public Ref schedulingPolicy;
|
||||
|
||||
// --- actions + links
|
||||
public Actions actions;
|
||||
|
||||
@JacksonXmlElementWrapper(useWrapping = false)
|
||||
public List<Link> link;
|
||||
|
||||
public Cluster() {}
|
||||
|
||||
// ===== nested DTOs =====
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class ClusterCpu {
|
||||
public String architecture;
|
||||
public String type;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class CustomSchedulingPolicyProperties {
|
||||
@JacksonXmlElementWrapper(useWrapping = false)
|
||||
@JsonProperty("property")
|
||||
public List<Property> property;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class Property {
|
||||
public String name;
|
||||
public String value;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class ErrorHandling {
|
||||
@JsonProperty("on_error")
|
||||
@JacksonXmlProperty(localName = "on_error")
|
||||
public String onError; // "migrate"
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class FencingPolicy {
|
||||
public String enabled;
|
||||
|
||||
@JsonProperty("skip_if_connectivity_broken")
|
||||
@JacksonXmlProperty(localName = "skip_if_connectivity_broken")
|
||||
public SkipIfConnectivityBroken skipIfConnectivityBroken;
|
||||
|
||||
@JsonProperty("skip_if_gluster_bricks_up")
|
||||
@JacksonXmlProperty(localName = "skip_if_gluster_bricks_up")
|
||||
public String skipIfGlusterBricksUp;
|
||||
|
||||
@JsonProperty("skip_if_gluster_quorum_not_met")
|
||||
@JacksonXmlProperty(localName = "skip_if_gluster_quorum_not_met")
|
||||
public String skipIfGlusterQuorumNotMet;
|
||||
|
||||
@JsonProperty("skip_if_sd_active")
|
||||
@JacksonXmlProperty(localName = "skip_if_sd_active")
|
||||
public SkipIfSdActive skipIfSdActive;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class SkipIfConnectivityBroken {
|
||||
public String enabled;
|
||||
public String threshold;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class SkipIfSdActive {
|
||||
public String enabled;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class Ksm {
|
||||
public String enabled;
|
||||
|
||||
@JsonProperty("merge_across_nodes")
|
||||
@JacksonXmlProperty(localName = "merge_across_nodes")
|
||||
public String mergeAcrossNodes;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class MemoryPolicy {
|
||||
@JsonProperty("over_commit")
|
||||
@JacksonXmlProperty(localName = "over_commit")
|
||||
public OverCommit overCommit;
|
||||
|
||||
@JsonProperty("transparent_hugepages")
|
||||
@JacksonXmlProperty(localName = "transparent_hugepages")
|
||||
public TransparentHugepages transparentHugepages;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class OverCommit {
|
||||
public String percent;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class TransparentHugepages {
|
||||
public String enabled;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class Migration {
|
||||
@JsonProperty("auto_converge")
|
||||
@JacksonXmlProperty(localName = "auto_converge")
|
||||
public String autoConverge;
|
||||
|
||||
public Bandwidth bandwidth;
|
||||
|
||||
public String compressed;
|
||||
public String encrypted;
|
||||
|
||||
@JsonProperty("parallel_migrations_policy")
|
||||
@JacksonXmlProperty(localName = "parallel_migrations_policy")
|
||||
public String parallelMigrationsPolicy;
|
||||
|
||||
public Ref policy;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class Bandwidth {
|
||||
@JsonProperty("assignment_method")
|
||||
@JacksonXmlProperty(localName = "assignment_method")
|
||||
public String assignmentMethod;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class RequiredRngSources {
|
||||
@JsonProperty("required_rng_source")
|
||||
@JacksonXmlElementWrapper(useWrapping = false)
|
||||
public List<String> requiredRngSource;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static final class Version {
|
||||
public String major;
|
||||
public String minor;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// 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 = "clusters")
|
||||
public final class Clusters {
|
||||
|
||||
@JsonProperty("cluster")
|
||||
@JacksonXmlElementWrapper(useWrapping = false)
|
||||
public List<Cluster> cluster;
|
||||
|
||||
public Clusters() {}
|
||||
|
||||
public Clusters(final List<Cluster> cluster) {
|
||||
this.cluster = cluster;
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,7 @@
|
|||
<bean id="veeamControlApiService" class="org.apache.cloudstack.veeam.api.ApiService" />
|
||||
<bean id="vmsRouteHandler" class="org.apache.cloudstack.veeam.api.VmsRouteHandler"/>
|
||||
<bean id="dataCentersRouteHandler" class="org.apache.cloudstack.veeam.api.DataCentersRouteHandler"/>
|
||||
<bean id="clustersRouteHandler" class="org.apache.cloudstack.veeam.api.ClustersRouteHandler"/>
|
||||
<bean id="disksRouteHandler" class="org.apache.cloudstack.veeam.api.DisksRouteHandler"/>
|
||||
<bean id="veeamControlSsoService" class="org.apache.cloudstack.veeam.sso.SsoService"/>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue