Skip to content

Commit c405e5d

Browse files
committed
Add new API to check storage policy compatible pools and fix marvin test for storage policies
1 parent a831ad1 commit c405e5d

4 files changed

Lines changed: 166 additions & 5 deletions

File tree

plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/VmwareDatacenterService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020
import com.cloud.dc.VsphereStoragePolicy;
2121
import com.cloud.exception.DiscoveryException;
2222
import com.cloud.exception.ResourceInUseException;
23+
import com.cloud.storage.StoragePool;
2324
import com.cloud.utils.component.PluggableService;
2425
import com.cloud.utils.exception.CloudRuntimeException;
2526
import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
2627
import org.apache.cloudstack.api.command.admin.zone.ImportVsphereStoragePoliciesCmd;
2728
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
2829
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePoliciesCmd;
30+
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePolicyCompatiblePoolsCmd;
2931
import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
3032
import org.apache.cloudstack.api.command.admin.zone.UpdateVmwareDcCmd;
3133

@@ -45,4 +47,5 @@ public interface VmwareDatacenterService extends PluggableService {
4547

4648
List<? extends VsphereStoragePolicy> listVsphereStoragePolicies(ListVsphereStoragePoliciesCmd cmd);
4749

50+
List<StoragePool> listVsphereStoragePolicyCompatibleStoragePools(ListVsphereStoragePolicyCompatiblePoolsCmd cmd);
4851
}

plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.cloud.agent.api.Command;
2626
import com.cloud.agent.api.StartupCommand;
2727
import com.cloud.agent.api.StartupRoutingCommand;
28+
import com.cloud.agent.api.to.StorageFilerTO;
2829
import com.cloud.api.query.dao.TemplateJoinDao;
2930
import com.cloud.cluster.ClusterManager;
3031
import com.cloud.cluster.dao.ManagementServerHostPeerDao;
@@ -41,16 +42,19 @@
4142
import com.cloud.dc.dao.VsphereStoragePolicyDao;
4243
import com.cloud.event.ActionEvent;
4344
import com.cloud.event.EventTypes;
45+
import com.cloud.exception.AgentUnavailableException;
4446
import com.cloud.exception.DiscoveredWithErrorException;
4547
import com.cloud.exception.DiscoveryException;
4648
import com.cloud.exception.InvalidParameterValueException;
49+
import com.cloud.exception.OperationTimedoutException;
4750
import com.cloud.exception.ResourceInUseException;
4851
import com.cloud.host.Host;
4952
import com.cloud.host.Status;
5053
import com.cloud.host.dao.HostDao;
5154
import com.cloud.host.dao.HostDetailsDao;
5255
import com.cloud.hypervisor.Hypervisor;
5356
import com.cloud.hypervisor.Hypervisor.HypervisorType;
57+
import com.cloud.hypervisor.HypervisorGuruManager;
5458
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
5559
import com.cloud.hypervisor.vmware.LegacyZoneVO;
5660
import com.cloud.hypervisor.vmware.VmwareCleanupMaid;
@@ -89,6 +93,8 @@
8993
import com.cloud.storage.JavaStorageLayer;
9094
import com.cloud.storage.StorageLayer;
9195
import com.cloud.storage.StorageManager;
96+
import com.cloud.storage.StoragePool;
97+
import com.cloud.storage.StoragePoolStatus;
9298
import com.cloud.storage.dao.VMTemplatePoolDao;
9399
import com.cloud.template.TemplateManager;
94100
import com.cloud.utils.FileUtil;
@@ -116,6 +122,7 @@
116122
import org.apache.cloudstack.api.command.admin.zone.ImportVsphereStoragePoliciesCmd;
117123
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
118124
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePoliciesCmd;
125+
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePolicyCompatiblePoolsCmd;
119126
import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
120127
import org.apache.cloudstack.api.command.admin.zone.UpdateVmwareDcCmd;
121128
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
@@ -125,7 +132,9 @@
125132
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
126133
import org.apache.cloudstack.framework.jobs.impl.AsyncJobManagerImpl;
127134
import org.apache.cloudstack.management.ManagementServerHost;
135+
import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand;
128136
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
137+
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
129138
import org.apache.cloudstack.utils.identity.ManagementServerNode;
130139
import org.apache.log4j.Logger;
131140

@@ -217,6 +226,10 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
217226
private TemplateManager templateManager;
218227
@Inject
219228
private VsphereStoragePolicyDao vsphereStoragePolicyDao;
229+
@Inject
230+
private StorageManager storageManager;
231+
@Inject
232+
private HypervisorGuruManager hypervisorGuruManager;
220233

221234
private String _mountParent;
222235
private StorageLayer _storage;
@@ -1057,6 +1070,7 @@ public List<Class<?>> getCommands() {
10571070
cmdList.add(ListVmwareDcsCmd.class);
10581071
cmdList.add(ImportVsphereStoragePoliciesCmd.class);
10591072
cmdList.add(ListVsphereStoragePoliciesCmd.class);
1073+
cmdList.add(ListVsphereStoragePolicyCompatiblePoolsCmd.class);
10601074
return cmdList;
10611075
}
10621076

@@ -1469,6 +1483,35 @@ public List<? extends VsphereStoragePolicy> listVsphereStoragePolicies(ListVsphe
14691483
return Collections.emptyList();
14701484
}
14711485

1486+
@Override
1487+
public List<StoragePool> listVsphereStoragePolicyCompatibleStoragePools(ListVsphereStoragePolicyCompatiblePoolsCmd cmd) {
1488+
Long policyId = cmd.getPolicyId();
1489+
VsphereStoragePolicyVO storagePolicy = vsphereStoragePolicyDao.findById(policyId);
1490+
if (storagePolicy == null) {
1491+
throw new CloudRuntimeException("Storage policy with ID = " + policyId + " was not found");
1492+
}
1493+
long zoneId = storagePolicy.getZoneId();
1494+
List<StoragePoolVO> poolsInZone = primaryStorageDao.listByStatusInZone(zoneId, StoragePoolStatus.Up);
1495+
List<StoragePool> compatiblePools = new ArrayList<>();
1496+
for (StoragePoolVO pool : poolsInZone) {
1497+
StorageFilerTO storageFilerTO = new StorageFilerTO(pool);
1498+
List<Long> hostIds = storageManager.getUpHostsInPool(pool.getId());
1499+
Collections.shuffle(hostIds);
1500+
CheckDataStoreStoragePolicyComplainceCommand command = new CheckDataStoreStoragePolicyComplainceCommand(storagePolicy.getPolicyId(), storageFilerTO);
1501+
long targetHostId = hypervisorGuruManager.getGuruProcessedCommandTargetHost(hostIds.get(0), command);
1502+
try {
1503+
Answer answer = _agentMgr.send(targetHostId, command);
1504+
boolean result = answer != null && answer.getResult();
1505+
if (result) {
1506+
compatiblePools.add(pool);
1507+
}
1508+
} catch (AgentUnavailableException | OperationTimedoutException e) {
1509+
s_logger.error("Could not verify if storage policy " + storagePolicy.getName() + " is compatible with storage pool " + pool.getName());
1510+
}
1511+
}
1512+
return compatiblePools;
1513+
}
1514+
14721515
@Override
14731516
public boolean hasNexusVSM(Long clusterId) {
14741517
ClusterVSMMapVO vsmMapVo = null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.api.command.admin.zone;
18+
19+
import com.cloud.exception.ConcurrentOperationException;
20+
import com.cloud.hypervisor.vmware.VmwareDatacenterService;
21+
import com.cloud.storage.StoragePool;
22+
import org.apache.cloudstack.acl.RoleType;
23+
import org.apache.cloudstack.api.APICommand;
24+
import org.apache.cloudstack.api.ApiConstants;
25+
import org.apache.cloudstack.api.BaseCmd;
26+
import org.apache.cloudstack.api.BaseListCmd;
27+
import org.apache.cloudstack.api.Parameter;
28+
import org.apache.cloudstack.api.ServerApiException;
29+
import org.apache.cloudstack.api.response.ListResponse;
30+
import org.apache.cloudstack.api.response.StoragePoolResponse;
31+
import org.apache.cloudstack.api.response.VsphereStoragePoliciesResponse;
32+
import org.apache.cloudstack.api.response.ZoneResponse;
33+
import org.apache.cloudstack.context.CallContext;
34+
35+
import javax.inject.Inject;
36+
import java.util.ArrayList;
37+
import java.util.List;
38+
39+
@APICommand(name = ListVsphereStoragePolicyCompatiblePoolsCmd.APINAME, description = "List storage pools compatible with a vSphere storage policy",
40+
responseObject = StoragePoolResponse.class,
41+
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
42+
authorized = {RoleType.Admin})
43+
public class ListVsphereStoragePolicyCompatiblePoolsCmd extends BaseListCmd {
44+
public static final String APINAME = "listVsphereStoragePolicyCompatiblePools";
45+
46+
@Inject
47+
public VmwareDatacenterService vmwareDatacenterService;
48+
49+
/////////////////////////////////////////////////////
50+
//////////////// API parameters /////////////////////
51+
/////////////////////////////////////////////////////
52+
53+
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class,
54+
description = "ID of the zone")
55+
private Long zoneId;
56+
57+
@Parameter(name = ApiConstants.POLICY_ID, type = BaseCmd.CommandType.UUID, entityType = VsphereStoragePoliciesResponse.class,
58+
description = "ID of the storage policy")
59+
private Long policyId;
60+
61+
/////////////////////////////////////////////////////
62+
/////////////// API Implementation///////////////////
63+
/////////////////////////////////////////////////////
64+
65+
@Override
66+
public void execute() throws ServerApiException, ConcurrentOperationException {
67+
List<StoragePool> pools = vmwareDatacenterService.listVsphereStoragePolicyCompatibleStoragePools(this);
68+
ListResponse<StoragePoolResponse> response = new ListResponse<>();
69+
List<StoragePoolResponse> poolResponses = new ArrayList<>();
70+
for (StoragePool pool : pools) {
71+
StoragePoolResponse poolResponse = _responseGenerator.createStoragePoolForMigrationResponse(pool);
72+
poolResponse.setObjectName("storagepool");
73+
poolResponses.add(poolResponse);
74+
}
75+
response.setResponses(poolResponses);
76+
response.setResponseName(getCommandName());
77+
this.setResponseObject(response);
78+
}
79+
80+
@Override
81+
public String getCommandName() {
82+
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
83+
}
84+
85+
@Override
86+
public long getEntityOwnerId() {
87+
return CallContext.current().getCallingAccountId();
88+
}
89+
90+
public Long getZoneId() {
91+
return zoneId;
92+
}
93+
94+
public Long getPolicyId() {
95+
return policyId;
96+
}
97+
}

test/integration/smoke/test_storage_policy.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
from marvin.lib.common import (get_zone,
3232
get_domain,
3333
get_test_template)
34-
from marvin.codes import PASS
35-
from marvin.cloudstackAPI import (importVsphereStoragePolicies)
36-
from marvin.cloudstackAPI import (listVsphereStoragePolicies)
34+
from marvin.cloudstackAPI import (importVsphereStoragePolicies,
35+
listVsphereStoragePolicies,
36+
listVsphereStoragePolicyCompatiblePools)
3737

3838

3939
class TestVMWareStoragePolicies(cloudstackTestCase):
@@ -103,6 +103,12 @@ def list_storage_policies(self, apiclient):
103103
cmd.zoneid = self.zone.id
104104
return apiclient.listVsphereStoragePolicies(cmd)
105105

106+
def list_storage_policy_compatible_pools(self, apiclient, policyid):
107+
cmd = listVsphereStoragePolicyCompatiblePools.listVsphereStoragePolicyCompatiblePoolsCmd()
108+
cmd.zoneid = self.zone.id
109+
cmd.policyid = policyid
110+
return apiclient.listVsphereStoragePolicyCompatiblePools(cmd)
111+
106112
def create_volume(self, apiclient):
107113
cmd = create
108114

@@ -155,19 +161,31 @@ def test_01_import_storage_policies(self):
155161
"Check if the number of imported policies is identical to the number of listed policies"
156162
)
157163

164+
are_compatible_pools = False
165+
selected_policy = None
166+
for imported_policy in imported_policies:
167+
compatible_pools = self.list_storage_policy_compatible_pools(self.apiclient, imported_policy.id)
168+
if len(compatible_pools) > 0:
169+
are_compatible_pools = True
170+
selected_policy = imported_policy
171+
break
172+
173+
if not are_compatible_pools:
174+
self.skipTest("There are no compatible storage pools with the imported policies")
175+
158176
# Create service offering with the first storage policy from the list
159177
service_offering = ServiceOffering.create(
160178
self.apiclient,
161179
self.testdata["service_offering"],
162-
storagepolicy=listed_policies[0].id
180+
storagepolicy=selected_policy.id
163181
)
164182
self.cleanup.append(service_offering)
165183

166184
# Create disk offering with the first storage policy from the list
167185
disk_offering = DiskOffering.create(
168186
self.apiclient,
169187
self.testdata["disk_offering"],
170-
storagepolicy=listed_policies[0].id
188+
storagepolicy=selected_policy.id
171189
)
172190
self.cleanup.append(disk_offering)
173191

0 commit comments

Comments
 (0)