mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
Merge remote-tracking branch 'origin/4.19'
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com> Conflicts: plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java
This commit is contained in:
commit
93d4816ee8
@ -223,9 +223,7 @@ public class LibvirtVMDef {
|
|||||||
guestDef.append("<boot dev='" + bo + "'/>\n");
|
guestDef.append("<boot dev='" + bo + "'/>\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_arch == null || !_arch.equals("aarch64")) {
|
|
||||||
guestDef.append("<smbios mode='sysinfo'/>\n");
|
guestDef.append("<smbios mode='sysinfo'/>\n");
|
||||||
}
|
|
||||||
guestDef.append("</os>\n");
|
guestDef.append("</os>\n");
|
||||||
if (iothreads) {
|
if (iothreads) {
|
||||||
guestDef.append(String.format("<iothreads>%s</iothreads>", NUMBER_OF_IOTHREADS));
|
guestDef.append(String.format("<iothreads>%s</iothreads>", NUMBER_OF_IOTHREADS));
|
||||||
|
|||||||
@ -240,6 +240,28 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given resource is in use by drbd on any host and
|
||||||
|
* if so set the drbd option allow-two-primaries
|
||||||
|
* @param api linstor api object
|
||||||
|
* @param rscName resource name to set allow-two-primaries if in use
|
||||||
|
* @throws ApiException if any problem connecting to the Linstor controller
|
||||||
|
*/
|
||||||
|
private void allow2PrimariesIfInUse(DevelopersApi api, String rscName) throws ApiException {
|
||||||
|
if (LinstorUtil.isResourceInUse(api, rscName)) {
|
||||||
|
// allow 2 primaries for live migration, should be removed by disconnect on the other end
|
||||||
|
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.put("DrbdOptions/Net/allow-two-primaries", "yes");
|
||||||
|
rdm.setOverrideProps(props);
|
||||||
|
ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm);
|
||||||
|
if (answers.hasError()) {
|
||||||
|
s_logger.error("Unable to set 'allow-two-primaries' on " + rscName);
|
||||||
|
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<String, String> details)
|
public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<String, String> details)
|
||||||
{
|
{
|
||||||
@ -266,16 +288,7 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// allow 2 primaries for live migration, should be removed by disconnect on the other end
|
allow2PrimariesIfInUse(api, rscName);
|
||||||
ResourceDefinitionModify rdm = new ResourceDefinitionModify();
|
|
||||||
Properties props = new Properties();
|
|
||||||
props.put("DrbdOptions/Net/allow-two-primaries", "yes");
|
|
||||||
rdm.setOverrideProps(props);
|
|
||||||
ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm);
|
|
||||||
if (answers.hasError()) {
|
|
||||||
logger.error("Unable to set 'allow-two-primaries' on " + rscName);
|
|
||||||
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
|
|
||||||
}
|
|
||||||
} catch (ApiException apiEx) {
|
} catch (ApiException apiEx) {
|
||||||
logger.error(apiEx);
|
logger.error(apiEx);
|
||||||
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
|
// do not fail here as adding allow-two-primaries property is only a problem while live migrating
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import com.linbit.linstor.api.model.ApiCallRc;
|
|||||||
import com.linbit.linstor.api.model.ApiCallRcList;
|
import com.linbit.linstor.api.model.ApiCallRcList;
|
||||||
import com.linbit.linstor.api.model.Node;
|
import com.linbit.linstor.api.model.Node;
|
||||||
import com.linbit.linstor.api.model.ProviderKind;
|
import com.linbit.linstor.api.model.ProviderKind;
|
||||||
|
import com.linbit.linstor.api.model.Resource;
|
||||||
import com.linbit.linstor.api.model.ResourceGroup;
|
import com.linbit.linstor.api.model.ResourceGroup;
|
||||||
import com.linbit.linstor.api.model.ResourceWithVolumes;
|
import com.linbit.linstor.api.model.ResourceWithVolumes;
|
||||||
import com.linbit.linstor.api.model.StoragePool;
|
import com.linbit.linstor.api.model.StoragePool;
|
||||||
@ -184,4 +185,22 @@ public class LinstorUtil {
|
|||||||
throw new CloudRuntimeException(apiEx);
|
throw new CloudRuntimeException(apiEx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if any resource of the given name is InUse on any host.
|
||||||
|
*
|
||||||
|
* @param api developer api object to use
|
||||||
|
* @param rscName resource name to check in use state.
|
||||||
|
* @return True if a resource found that is in use(primary) state, else false.
|
||||||
|
* @throws ApiException forwards api errors
|
||||||
|
*/
|
||||||
|
public static boolean isResourceInUse(DevelopersApi api, String rscName) throws ApiException {
|
||||||
|
List<Resource> rscs = api.resourceList(rscName, null, null);
|
||||||
|
if (rscs != null) {
|
||||||
|
return rscs.stream()
|
||||||
|
.anyMatch(rsc -> rsc.getState() != null && Boolean.TRUE.equals(rsc.getState().isInUse()));
|
||||||
|
}
|
||||||
|
s_logger.error("isResourceInUse: null returned from resourceList");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -351,6 +351,9 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
|||||||
if (possibleAddr.getState() != State.Free) {
|
if (possibleAddr.getState() != State.Free) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (s_logger.isDebugEnabled()) {
|
||||||
|
s_logger.debug(String.format("trying ip address %s", possibleAddr.getAddress()));
|
||||||
|
}
|
||||||
possibleAddr.setSourceNat(sourceNat);
|
possibleAddr.setSourceNat(sourceNat);
|
||||||
possibleAddr.setAllocatedTime(new Date());
|
possibleAddr.setAllocatedTime(new Date());
|
||||||
possibleAddr.setAllocatedInDomainId(owner.getDomainId());
|
possibleAddr.setAllocatedInDomainId(owner.getDomainId());
|
||||||
@ -365,17 +368,11 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
|||||||
possibleAddr.setAssociatedWithNetworkId(guestNetworkId);
|
possibleAddr.setAssociatedWithNetworkId(guestNetworkId);
|
||||||
possibleAddr.setVpcId(vpcId);
|
possibleAddr.setVpcId(vpcId);
|
||||||
}
|
}
|
||||||
if (_ipAddressDao.lockRow(possibleAddr.getId(), true) != null) {
|
finalAddress = assignIpAddressWithLock(possibleAddr);
|
||||||
final IPAddressVO userIp = _ipAddressDao.findById(possibleAddr.getId());
|
if (finalAddress != null) {
|
||||||
if (userIp.getState() == State.Free) {
|
|
||||||
possibleAddr.setState(State.Allocating);
|
|
||||||
if (_ipAddressDao.update(possibleAddr.getId(), possibleAddr)) {
|
|
||||||
finalAddress = possibleAddr;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (finalAddress == null) {
|
if (finalAddress == null) {
|
||||||
logger.error("Failed to fetch any free public IP address");
|
logger.error("Failed to fetch any free public IP address");
|
||||||
@ -395,6 +392,29 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IPAddressVO assignIpAddressWithLock(IPAddressVO possibleAddr) {
|
||||||
|
IPAddressVO finalAddress = null;
|
||||||
|
IPAddressVO userIp = _ipAddressDao.acquireInLockTable(possibleAddr.getId());
|
||||||
|
if (userIp != null) {
|
||||||
|
if (s_logger.isDebugEnabled()) {
|
||||||
|
s_logger.debug(String.format("locked row for ip address %s (id: %s)", possibleAddr.getAddress(), possibleAddr.getUuid()));
|
||||||
|
}
|
||||||
|
if (userIp.getState() == State.Free) {
|
||||||
|
possibleAddr.setState(State.Allocating);
|
||||||
|
if (_ipAddressDao.update(possibleAddr.getId(), possibleAddr)) {
|
||||||
|
s_logger.info(String.format("successfully allocated ip address %s", possibleAddr.getAddress()));
|
||||||
|
finalAddress = possibleAddr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (s_logger.isDebugEnabled()) {
|
||||||
|
s_logger.debug(String.format("locked ip address %s is not free (%s)", possibleAddr.getAddress(), userIp.getState()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ipAddressDao.releaseFromLockTable(possibleAddr.getId());
|
||||||
|
}
|
||||||
|
return finalAddress;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean configure(String name, Map<String, Object> params) {
|
public boolean configure(String name, Map<String, Object> params) {
|
||||||
// populate providers
|
// populate providers
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
<a-button
|
<a-button
|
||||||
type="dashed"
|
type="dashed"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
:disabled="!('updateTemplate' in $store.getters.apis && 'updateVirtualMachine' in $store.getters.apis && isAdminOrOwner())"
|
:disabled="!(isAdminOrOwner() && hasSettingUpdatePermission())"
|
||||||
@click="onShowAddDetail">
|
@click="onShowAddDetail">
|
||||||
<template #icon><plus-outlined /></template>
|
<template #icon><plus-outlined /></template>
|
||||||
{{ $t('label.add.setting') }}
|
{{ $t('label.add.setting') }}
|
||||||
@ -96,8 +96,7 @@
|
|||||||
</a-list-item-meta>
|
</a-list-item-meta>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<div
|
<div
|
||||||
v-if="!disableSettings && 'updateTemplate' in $store.getters.apis &&
|
v-if="!disableSettings && isAdminOrOwner() && allowEditOfDetail(item.name) && hasSettingUpdatePermission()">
|
||||||
'updateVirtualMachine' in $store.getters.apis && isAdminOrOwner() && allowEditOfDetail(item.name)">
|
|
||||||
<tooltip-button
|
<tooltip-button
|
||||||
:tooltip="$t('label.edit')"
|
:tooltip="$t('label.edit')"
|
||||||
icon="edit-outlined"
|
icon="edit-outlined"
|
||||||
@ -106,8 +105,7 @@
|
|||||||
@onClick="showEditDetail(index)" />
|
@onClick="showEditDetail(index)" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="!disableSettings && 'updateTemplate' in $store.getters.apis &&
|
v-if="!disableSettings && isAdminOrOwner() && allowEditOfDetail(item.name) && hasSettingUpdatePermission()">
|
||||||
'updateVirtualMachine' in $store.getters.apis && isAdminOrOwner() && allowEditOfDetail(item.name)">
|
|
||||||
<a-popconfirm
|
<a-popconfirm
|
||||||
:title="`${$t('label.delete.setting')}?`"
|
:title="`${$t('label.delete.setting')}?`"
|
||||||
@confirm="deleteDetail(index)"
|
@confirm="deleteDetail(index)"
|
||||||
@ -342,6 +340,12 @@ export default {
|
|||||||
this.newValue = ''
|
this.newValue = ''
|
||||||
this.error = false
|
this.error = false
|
||||||
this.showAddDetail = false
|
this.showAddDetail = false
|
||||||
|
},
|
||||||
|
hasSettingUpdatePermission () {
|
||||||
|
return (
|
||||||
|
(this.resourceType === 'Template' && 'updateTemplate' in this.$store.getters.apis) ||
|
||||||
|
(this.resourceType === 'UserVm' && 'updateVirtualMachine' in this.$store.getters.apis)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user