Merge LTS branch '4.19' into main

This commit is contained in:
Daan Hoogland 2024-04-18 08:54:58 +02:00
commit 7de8a6d082
9 changed files with 488 additions and 624 deletions

View File

@ -60,6 +60,7 @@ import javax.persistence.Table;
import javax.persistence.TableGenerator;
import com.amazonaws.util.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
@ -2194,6 +2195,9 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
@Override
public List<T> findByUuids(String... uuidArray) {
if (ArrayUtils.isEmpty(uuidArray)) {
return new ArrayList<T>();
}
SearchCriteria<T> sc = createSearchCriteria();
sc.addAnd("uuid", SearchCriteria.Op.IN, uuidArray);
return search(sc, null);

View File

@ -42,6 +42,7 @@ import com.linbit.linstor.api.model.ApiCallRc;
import com.linbit.linstor.api.model.ApiCallRcList;
import com.linbit.linstor.api.model.Properties;
import com.linbit.linstor.api.model.ProviderKind;
import com.linbit.linstor.api.model.Resource;
import com.linbit.linstor.api.model.ResourceDefinition;
import com.linbit.linstor.api.model.ResourceDefinitionModify;
import com.linbit.linstor.api.model.ResourceGroupSpawn;
@ -285,8 +286,8 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
@Override
public boolean disconnectPhysicalDisk(String volumePath, KVMStoragePool pool)
{
logger.debug("Linstor: disconnectPhysicalDisk " + pool.getUuid() + ":" + volumePath);
return true;
logger.debug("Linstor: disconnectPhysicalDisk {}:{}", pool.getUuid(), volumePath);
return false;
}
@Override
@ -322,39 +323,44 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
logger.debug("Linstor: Using storpool: " + pool.getUuid());
final DevelopersApi api = getLinstorAPI(pool);
try
{
Optional<ResourceWithVolumes> optRsc;
try {
List<ResourceWithVolumes> resources = api.viewResources(
Collections.singletonList(localNodeName),
null,
null,
null,
null,
null);
Collections.singletonList(localNodeName),
null,
null,
null,
null,
null);
Optional<ResourceWithVolumes> rsc = getResourceByPath(resources, localPath);
optRsc = getResourceByPath(resources, localPath);
} catch (ApiException apiEx) {
// couldn't query linstor controller
logger.error(apiEx.getBestMessage());
return false;
}
if (rsc.isPresent())
{
if (optRsc.isPresent()) {
try {
Resource rsc = optRsc.get();
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
rdm.deleteProps(Collections.singletonList("DrbdOptions/Net/allow-two-primaries"));
ApiCallRcList answers = api.resourceDefinitionModify(rsc.get().getName(), rdm);
ApiCallRcList answers = api.resourceDefinitionModify(rsc.getName(), rdm);
if (answers.hasError()) {
logger.error(
String.format("Failed to remove 'allow-two-primaries' on %s: %s",
rsc.get().getName(), LinstorUtil.getBestErrorMessage(answers)));
rsc.getName(), LinstorUtil.getBestErrorMessage(answers)));
// do not fail here as removing allow-two-primaries property isn't fatal
}
} catch(ApiException apiEx){
logger.error(apiEx.getBestMessage());
// do not fail here as removing allow-two-primaries property isn't fatal
return true;
}
logger.warn("Linstor: Couldn't find resource for this path: " + localPath);
} catch (ApiException apiEx) {
logger.error(apiEx.getBestMessage());
// do not fail here as removing allow-two-primaries property isn't fatal
}
}
return true;
logger.info("Linstor: Couldn't find resource for this path: {}", localPath);
return false;
}
@Override

View File

@ -217,7 +217,7 @@ NetworkMigrationResponder, AggregatedCommandExecutor, RedundantResource, DnsServ
return false;
}
final Map<VirtualMachineProfile.Param, Object> params = new HashMap<VirtualMachineProfile.Param, Object>(1);
final Map<VirtualMachineProfile.Param, Object> params = new HashMap<>(1);
params.put(VirtualMachineProfile.Param.ReProgramGuestNetworks, true);
if (network.isRollingRestart()) {
@ -262,27 +262,13 @@ NetworkMigrationResponder, AggregatedCommandExecutor, RedundantResource, DnsServ
return false;
}
final NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
if (offering.isSystemOnly()) {
return false;
}
if (!_networkMdl.isProviderEnabledInPhysicalNetwork(_networkMdl.getPhysicalNetworkId(network), getProvider().getName())) {
return false;
}
final RouterDeploymentDefinition routerDeploymentDefinition =
routerDeploymentDefinitionBuilder.create()
.setGuestNetwork(network)
.setDeployDestination(dest)
.setAccountOwner(_accountMgr.getAccount(network.getAccountId()))
.setParams(vm.getParameters())
.build();
final NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId());
implement(network, offering, dest, context);
final List<DomainRouterVO> routers = routerDeploymentDefinition.deployVirtualRouter();
if (routers == null || routers.size() == 0) {
throw new ResourceUnavailableException("Can't find at least one running router!", DataCenter.class, network.getDataCenterId());
}
return true;
}

View File

@ -1894,7 +1894,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
} else if (jobResult instanceof ResourceAllocationException) {
throw (ResourceAllocationException)jobResult;
} else if (jobResult instanceof Throwable) {
throw new RuntimeException("Unexpected exception", (Throwable)jobResult);
Throwable throwable = (Throwable) jobResult;
throw new RuntimeException(String.format("Unexpected exception: %s", throwable.getMessage()), throwable);
}
}

View File

@ -8,13 +8,13 @@ A modern role-based progressive CloudStack UI based on Vue.js and Ant Design.
Install node: (Debian/Ubuntu)
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs
# Or use distro provided: sudo apt-get install npm nodejs
Install node: (CentOS/Fedora/RHEL)
curl -sL https://rpm.nodesource.com/setup_14.x | sudo bash -
curl -sL https://rpm.nodesource.com/setup_16.x | sudo bash -
sudo yum install nodejs
Install node: (Mac OS)

1000
ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -34,14 +34,14 @@
"test:unit": "vue-cli-service test:unit"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.4.2",
"@fortawesome/free-brands-svg-icons": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/vue-fontawesome": "^3.0.3",
"@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-brands-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/vue-fontawesome": "^3.0.6",
"@vue-js-cron/ant": "^1.1.3",
"@vue-js-cron/core": "^3.7.1",
"ant-design-vue": "^3.2.20",
"antd": "^4.21.4",
"antd": "^4.24.16",
"antd-theme-webpack-plugin": "^1.3.9",
"axios": "^0.21.4",
"babel-plugin-require-context-hook": "^1.0.0",
@ -65,7 +65,7 @@
"vue-clipboard2": "^0.3.1",
"vue-cropper": "^1.0.2",
"vue-i18n": "^9.1.6",
"vue-loader": "^16.2.0",
"vue-loader": "^16.8.3",
"vue-qrious": "^3.1.0",
"vue-router": "^4.0.14",
"vue-social-auth": "^1.4.9",

View File

@ -46,6 +46,15 @@
{{ service.name }} : {{ service.provider?.[0]?.name }}
</div>
</div>
<div v-else-if="$route.meta.name === 'backup' && (item === 'size' || item === 'virtualsize')">
{{ $bytesToHumanReadableSize(dataResource[item]) }}
<a-tooltip placement="right">
<template #title>
{{ dataResource[item] }} bytes
</template>
<QuestionCircleOutlined />
</a-tooltip>
</div>
<div v-else-if="$route.meta.name === 'backup' && item === 'volumes'">
<div v-for="(volume, idx) in JSON.parse(dataResource[item])" :key="idx">
<router-link :to="{ path: '/volume/' + volume.uuid }">{{ volume.type }} - {{ volume.path }}</router-link> ({{ parseFloat(volume.size / (1024.0 * 1024.0 * 1024.0)).toFixed(1) }} GB)

View File

@ -290,10 +290,20 @@
</div>
</div>
<div class="resource-detail-item" v-if="resource.volumes || resource.sizegb">
<div class="resource-detail-item__label">{{ $t('label.disksize') }}</div>
<div class="resource-detail-item__label" v-if="$route.meta.name === 'backup'">{{ $t('label.size') }}</div>
<div class="resource-detail-item__label" v-else>{{ $t('label.disksize') }}</div>
<div class="resource-detail-item__details">
<hdd-outlined />
<span style="width: 100%;" v-if="$route.meta.name === 'vm' && resource.volumes">{{ (resource.volumes.reduce((total, item) => total += item.size, 0) / (1024 * 1024 * 1024.0)).toFixed(2) }} GB Storage</span>
<span style="width: 100%;" v-else-if="$route.meta.name === 'backup'">
{{ $bytesToHumanReadableSize(resource.size) }}
<a-tooltip placement="right">
<template #title>
{{ resource.size }} bytes
</template>
<QuestionCircleOutlined />
</a-tooltip>
</span>
<span style="width: 100%;" v-else-if="resource.sizegb || resource.size">{{ resource.sizegb || (resource.size/1024.0) }}</span>
</div>
<div style="margin-left: 25px; margin-top: 5px" v-if="resource.diskkbsread && resource.diskkbswrite && resource.diskioread && resource.diskiowrite">