Skip to content

Commit b4bc020

Browse files
Merge branch 'main' into 4.21-reconcile-commands
2 parents 39979a6 + 4c31f9d commit b4bc020

File tree

85 files changed

+1445
-929
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+1445
-929
lines changed

.asf.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,11 @@ github:
5454
- gpordeus
5555
- hsato03
5656
- bernardodemarco
57-
- abh1sar
5857
- FelipeM525
5958
- lucas-a-martins
6059
- nicoschmdt
60+
- abh1sar
61+
- sudo87
6162

6263
protected_branches: ~
6364

CONTRIBUTING.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ Contributing to Apache CloudStack (ACS)
44
Summary
55
-------
66
This document covers how to contribute to the ACS project. ACS uses GitHub PRs to manage code contributions.
7-
These instructions assume you have a GitHub.com account, so if you don't have one you will have to create one. Your proposed code changes will be published to your own fork of the ACS project and you will submit a Pull Request for your changes to be added.
7+
These instructions assume you have a GitHub.com account, so if you don't have one you will have to create one. Your proposed code changes will be published to your own fork of the ACS project, and you will submit a Pull Request for your changes to be added.
88

9-
_Lets get started!!!_
9+
_Let's get started!!!_
1010

1111
Bug fixes
1212
---------
@@ -26,7 +26,7 @@ No back porting / cherry-picking features to existing branches!
2626

2727
PendingReleaseNotes file
2828
------------------------
29-
When developing a new feature or making a (major) change to a existing feature you are encouraged to append this to the PendingReleaseNotes file so that the Release Manager can
29+
When developing a new feature or making a (major) change to an existing feature you are encouraged to append this to the PendingReleaseNotes file so that the Release Manager can
3030
use this file as a source of information when compiling the Release Notes for a new release.
3131

3232
When adding information to the PendingReleaseNotes file make sure that you write a good and understandable description of the new feature or change which you have developed.
@@ -38,9 +38,9 @@ Fork the code
3838

3939
In your browser, navigate to: [https://github.com/apache/cloudstack](https://github.com/apache/cloudstack)
4040

41-
Fork the repository by clicking on the 'Fork' button on the top right hand side. The fork will happen and you will be taken to your own fork of the repository. Copy the Git repository URL by clicking on the clipboard next to the URL on the right hand side of the page under '**HTTPS** clone URL'. You will paste this URL when doing the following `git clone` command.
41+
Fork the repository by clicking on the 'Fork' button on the top right hand side. The fork will happen, and you will be taken to your own fork of the repository. Copy the Git repository URL by clicking on the clipboard next to the URL on the right hand side of the page under '**HTTPS** clone URL'. You will paste this URL when doing the following `git clone` command.
4242

43-
On your computer, follow these steps to setup a local repository for working on ACS:
43+
On your computer, follow these steps to set up a local repository for working on ACS:
4444

4545
```bash
4646
$ git clone https://github.com/YOUR_ACCOUNT/cloudstack.git
@@ -92,9 +92,9 @@ $ git rebase main
9292
Make a GitHub Pull Request to contribute your changes
9393
-----------------------------------------------------
9494

95-
When you are happy with your changes and you are ready to contribute them, you will create a Pull Request on GitHub to do so. This is done by pushing your local changes to your forked repository (default remote name is `origin`) and then initiating a pull request on GitHub.
95+
When you are happy with your changes, and you are ready to contribute them, you will create a Pull Request on GitHub to do so. This is done by pushing your local changes to your forked repository (default remote name is `origin`) and then initiating a pull request on GitHub.
9696

97-
Please include JIRA id, detailed information about the bug/feature, what all tests are executed, how the reviewer can test this feature etc. Incase of UI PRs, a screenshot is preferred.
97+
Please include JIRA id, detailed information about the bug/feature, what all tests are executed, how the reviewer can test this feature etc. In case of UI PRs, a screenshot is preferred.
9898

9999
> **IMPORTANT:** Make sure you have rebased your `feature_x` branch to include the latest code from `upstream/main` _before_ you do this.
100100

agent/bindir/cloud-setup-agent.in

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@ import os
2020
import logging
2121
import sys
2222
import socket
23+
24+
# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
25+
# ---- We do this so cloud_utils can be looked up in the following order:
26+
# ---- 1) Sources directory
27+
# ---- 2) waf configured PYTHONDIR
28+
# ---- 3) System Python path
29+
for pythonpath in (
30+
"@PYTHONDIR@",
31+
os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"),
32+
):
33+
if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath)
34+
# ---- End snippet of code ----
35+
2336
from cloudutils.cloudException import CloudRuntimeException, CloudInternalException
2437
from cloudutils.utilities import initLoging, bash
2538
from cloudutils.configFileOps import configFileOps

agent/bindir/libvirtqemuhook.in

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@ import sys
2020
import os
2121
import subprocess
2222
from threading import Timer
23+
24+
# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
25+
# ---- We do this so cloud_utils can be looked up in the following order:
26+
# ---- 1) Sources directory
27+
# ---- 2) waf configured PYTHONDIR
28+
# ---- 3) System Python path
29+
for pythonpath in (
30+
"@PYTHONDIR@",
31+
os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"),
32+
):
33+
if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath)
34+
# ---- End snippet of code ----
35+
2336
from xml.dom.minidom import parse
2437
from cloudutils.configFileOps import configFileOps
2538
from cloudutils.networkConfig import networkConfig

api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,11 @@
2828
import org.apache.cloudstack.api.EntityReference;
2929

3030
import com.cloud.network.Network;
31-
import com.cloud.projects.ProjectAccount;
3231
import com.cloud.serializer.Param;
3332
import com.google.gson.annotations.SerializedName;
3433

3534
@SuppressWarnings("unused")
36-
@EntityReference(value = {Network.class, ProjectAccount.class})
35+
@EntityReference(value = {Network.class})
3736
public class NetworkResponse extends BaseResponseWithAssociatedNetwork implements ControlledEntityResponse, SetResourceIconResponse {
3837

3938
@SerializedName(ApiConstants.ID)

api/src/main/java/org/apache/cloudstack/api/response/StoragePoolResponse.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ public class StoragePoolResponse extends BaseResponseWithAnnotations {
149149
@Param(description = "whether this pool is managed or not")
150150
private Boolean managed;
151151

152+
@SerializedName(ApiConstants.DETAILS)
153+
@Param(description = "the storage pool details")
154+
private Map<String, String> details;
155+
152156
public Map<String, String> getCaps() {
153157
return caps;
154158
}
@@ -407,4 +411,12 @@ public Boolean getManaged() {
407411
public void setManaged(Boolean managed) {
408412
this.managed = managed;
409413
}
414+
415+
public Map<String, String> getDetails() {
416+
return details;
417+
}
418+
419+
public void setDetails(Map<String, String> details) {
420+
this.details = details;
421+
}
410422
}

client/bindir/cloud-setup-management.in

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,27 @@
1616
# specific language governing permissions and limitations
1717
# under the License.
1818

19+
import os
1920
import sys
21+
# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
22+
# ---- We do this so cloud_utils can be looked up in the following order:
23+
# ---- 1) Sources directory
24+
# ---- 2) waf configured PYTHONDIR
25+
# ---- 3) System Python path
26+
for pythonpath in (
27+
"@PYTHONDIR@",
28+
os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"),
29+
):
30+
if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath)
31+
# ---- End snippet of code ----
32+
2033
from cloudutils.syscfg import sysConfigFactory
2134
from cloudutils.utilities import initLoging, UnknownSystemException
2235
from cloudutils.cloudException import CloudRuntimeException, CloudInternalException
2336
from cloudutils.globalEnv import globalEnv
2437
from cloudutils.serviceConfigServer import cloudManagementConfig
2538
from optparse import OptionParser
39+
2640
if __name__ == '__main__':
2741
initLoging("@MSLOGDIR@/setupManagement.log")
2842
glbEnv = globalEnv()

engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/lifecycle/BasePrimaryDataStoreLifeCycleImpl.java

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,29 @@
2222

2323
import javax.inject.Inject;
2424

25-
import com.cloud.dc.dao.DataCenterDao;
2625
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
2726
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
27+
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
28+
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
2829
import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper;
2930

3031
import com.cloud.agent.AgentManager;
3132
import com.cloud.agent.api.Answer;
3233
import com.cloud.agent.api.DeleteStoragePoolCommand;
34+
import com.cloud.dc.dao.DataCenterDao;
3335
import com.cloud.host.HostVO;
3436
import com.cloud.host.dao.HostDao;
3537
import com.cloud.hypervisor.Hypervisor.HypervisorType;
3638
import com.cloud.resource.ResourceManager;
3739
import com.cloud.storage.StorageManager;
3840
import com.cloud.storage.StoragePool;
3941
import com.cloud.storage.StoragePoolHostVO;
42+
import com.cloud.storage.VMTemplateStoragePoolVO;
43+
import com.cloud.storage.VMTemplateStorageResourceAssoc;
4044
import com.cloud.storage.dao.StoragePoolHostDao;
45+
import com.cloud.template.TemplateManager;
4146
import com.cloud.utils.Pair;
47+
4248
import org.apache.logging.log4j.LogManager;
4349
import org.apache.logging.log4j.Logger;
4450

@@ -59,6 +65,10 @@ public class BasePrimaryDataStoreLifeCycleImpl {
5965
protected DataCenterDao zoneDao;
6066
@Inject
6167
protected StoragePoolHostDao storagePoolHostDao;
68+
@Inject
69+
private PrimaryDataStoreDao primaryDataStoreDao;
70+
@Inject
71+
private TemplateManager templateMgr;
6272

6373
private List<HostVO> getPoolHostsList(ClusterScope clusterScope, HypervisorType hypervisorType) {
6474
List<HostVO> hosts;
@@ -81,7 +91,7 @@ public void changeStoragePoolScopeToZone(DataStore store, ClusterScope clusterSc
8191
try {
8292
storageMgr.connectHostToSharedPool(host, store.getId());
8393
} catch (Exception e) {
84-
logger.warn("Unable to establish a connection between " + host + " and " + store, e);
94+
logger.warn("Unable to establish a connection between {} and {}", host, store, e);
8595
}
8696
}
8797
}
@@ -99,7 +109,7 @@ public void changeStoragePoolScopeToCluster(DataStore store, ClusterScope cluste
99109

100110
if (answer != null) {
101111
if (!answer.getResult()) {
102-
logger.debug("Failed to delete storage pool: " + answer.getResult());
112+
logger.debug("Failed to delete storage pool: {}", answer.getResult());
103113
} else if (HypervisorType.KVM != hypervisorType) {
104114
break;
105115
}
@@ -108,4 +118,42 @@ public void changeStoragePoolScopeToCluster(DataStore store, ClusterScope cluste
108118
}
109119
dataStoreHelper.switchToCluster(store, clusterScope);
110120
}
121+
122+
private void evictTemplates(StoragePoolVO storagePoolVO) {
123+
List<VMTemplateStoragePoolVO> unusedTemplatesInPool = templateMgr.getUnusedTemplatesInPool(storagePoolVO);
124+
for (VMTemplateStoragePoolVO templatePoolVO : unusedTemplatesInPool) {
125+
if (templatePoolVO.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
126+
templateMgr.evictTemplateFromStoragePool(templatePoolVO);
127+
}
128+
}
129+
}
130+
131+
private void deleteAgentStoragePools(StoragePool storagePool) {
132+
List<StoragePoolHostVO> poolHostVOs = storagePoolHostDao.listByPoolId(storagePool.getId());
133+
for (StoragePoolHostVO poolHostVO : poolHostVOs) {
134+
DeleteStoragePoolCommand deleteStoragePoolCommand = new DeleteStoragePoolCommand(storagePool);
135+
final Answer answer = agentMgr.easySend(poolHostVO.getHostId(), deleteStoragePoolCommand);
136+
if (answer != null && answer.getResult()) {
137+
logger.info("Successfully deleted storage pool: {} from host: {}", storagePool.getId(), poolHostVO.getHostId());
138+
} else {
139+
if (answer != null) {
140+
logger.error("Failed to delete storage pool: {} from host: {} , result: {}", storagePool.getId(), poolHostVO.getHostId(), answer.getResult());
141+
} else {
142+
logger.error("Failed to delete storage pool: {} from host: {}", storagePool.getId(), poolHostVO.getHostId());
143+
}
144+
}
145+
}
146+
}
147+
148+
protected boolean cleanupDatastore(DataStore store) {
149+
StoragePool storagePool = (StoragePool)store;
150+
StoragePoolVO storagePoolVO = primaryDataStoreDao.findById(storagePool.getId());
151+
if (storagePoolVO == null) {
152+
return false;
153+
}
154+
155+
evictTemplates(storagePoolVO);
156+
deleteAgentStoragePools(storagePool);
157+
return true;
158+
}
111159
}

engine/storage/volume/src/main/java/org/apache/cloudstack/storage/datastore/provider/DefaultHostListener.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
import com.cloud.storage.StoragePoolHostVO;
4444
import com.cloud.storage.StorageService;
4545
import com.cloud.storage.dao.StoragePoolHostDao;
46-
import com.cloud.utils.Pair;
4746
import com.cloud.utils.exception.CloudRuntimeException;
4847

4948
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
@@ -60,6 +59,7 @@
6059

6160
import java.util.List;
6261
import java.util.Map;
62+
import java.util.Optional;
6363

6464
public class DefaultHostListener implements HypervisorHostListener {
6565
protected Logger logger = LogManager.getLogger(getClass());
@@ -133,9 +133,11 @@ private NicTO createNicTOFromNetworkAndOffering(NetworkVO networkVO, NetworkOffe
133133
@Override
134134
public boolean hostConnect(long hostId, long poolId) throws StorageConflictException {
135135
StoragePool pool = (StoragePool) this.dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary);
136-
Pair<Map<String, String>, Boolean> nfsMountOpts = storageManager.getStoragePoolNFSMountOpts(pool, null);
136+
Map<String, String> detailsMap = storagePoolDetailsDao.listDetailsKeyPairs(poolId);
137+
Map<String, String> nfsMountOpts = storageManager.getStoragePoolNFSMountOpts(pool, null).first();
137138

138-
ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(true, pool, nfsMountOpts.first());
139+
Optional.ofNullable(nfsMountOpts).ifPresent(detailsMap::putAll);
140+
ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(true, pool, detailsMap);
139141
cmd.setWait(modifyStoragePoolCommandWait);
140142
HostVO host = hostDao.findById(hostId);
141143
logger.debug("Sending modify storage pool command to agent: {} for storage pool: {} with timeout {} seconds", host, pool, cmd.getWait());

framework/cluster/src/main/java/com/cloud/cluster/ClusterManagerImpl.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,9 +1113,19 @@ public boolean stop() {
11131113
if (_mshostId != null) {
11141114
final ManagementServerHostVO mshost = _mshostDao.findByMsid(_msId);
11151115
if (mshost != null) {
1116-
final ManagementServerStatusVO mshostStatus = mshostStatusDao.findByMsId(mshost.getUuid());
1117-
mshostStatus.setLastJvmStop(new Date());
1118-
mshostStatusDao.update(mshostStatus.getId(), mshostStatus);
1116+
ManagementServerStatusVO mshostStatus = mshostStatusDao.findByMsId(mshost.getUuid());
1117+
if (mshostStatus != null) {
1118+
mshostStatus.setLastJvmStop(new Date());
1119+
mshostStatusDao.update(mshostStatus.getId(), mshostStatus);
1120+
} else {
1121+
logger.warn("Found a management server host [{}] without a status. This should never happen!", mshost);
1122+
mshostStatus = new ManagementServerStatusVO();
1123+
mshostStatus.setMsId(mshost.getUuid());
1124+
mshostStatus.setLastSystemBoot(new Date());
1125+
mshostStatus.setLastJvmStart(new Date());
1126+
mshostStatus.setUpdated(new Date());
1127+
mshostStatusDao.persist(mshostStatus);
1128+
}
11191129

11201130
ManagementServerHost.State msHostState = ManagementServerHost.State.Down;
11211131
if (ManagementServerHost.State.Maintenance.equals(mshost.getState()) || ManagementServerHost.State.PreparingForMaintenance.equals(mshost.getState())) {

0 commit comments

Comments
 (0)