Skip to content

Commit 75db42b

Browse files
author
Daan Hoogland
committed
Merge branch '4.20' into 4.22
2 parents 9dee137 + c0b5358 commit 75db42b

File tree

32 files changed

+317
-123
lines changed

32 files changed

+317
-123
lines changed

api/src/main/java/com/cloud/network/NetworkService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ Network createGuestNetwork(long networkOfferingId, String name, String displayTe
108108
PhysicalNetwork physicalNetwork, long zoneId, ControlledEntity.ACLType aclType) throws
109109
InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException;
110110

111+
Network createGuestNetwork(long networkOfferingId, String name, String displayText, Account owner,
112+
PhysicalNetwork physicalNetwork, long zoneId, ControlledEntity.ACLType aclType, Pair<Integer, Integer> vrIfaceMTUs) throws
113+
InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException;
114+
111115
Pair<List<? extends Network>, Integer> searchForNetworks(ListNetworksCmd cmd);
112116

113117
boolean deleteNetwork(long networkId, boolean forced);

api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ public class ListHostsCmd extends BaseListCmd {
118118
since = "4.21.0")
119119
private String storageAccessGroup;
120120

121+
@Parameter(name = ApiConstants.VERSION, type = CommandType.STRING, description = "the host version", since = "4.20.3")
122+
private String version;
123+
121124
/////////////////////////////////////////////////////
122125
/////////////////// Accessors ///////////////////////
123126
/////////////////////////////////////////////////////
@@ -222,6 +225,10 @@ public ListHostsCmd(String storageAccessGroup) {
222225
this.storageAccessGroup = storageAccessGroup;
223226
}
224227

228+
public String getVersion() {
229+
return version;
230+
}
231+
225232
/////////////////////////////////////////////////////
226233
/////////////// API Implementation///////////////////
227234
/////////////////////////////////////////////////////

api/src/main/java/org/apache/cloudstack/api/command/admin/management/ListMgmtsCmd.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ public class ListMgmtsCmd extends BaseListCmd {
4545
since = "4.20.1.0")
4646
private Boolean peers;
4747

48+
@Parameter(name = ApiConstants.VERSION, type = CommandType.STRING,
49+
description = "the version of the management server", since = "4.20.3")
50+
private String version;
51+
4852
/////////////////////////////////////////////////////
4953
/////////////////// Accessors ///////////////////////
5054
/////////////////////////////////////////////////////
@@ -61,6 +65,10 @@ public Boolean getPeers() {
6165
return BooleanUtils.toBooleanDefaultIfNull(peers, false);
6266
}
6367

68+
public String getVersion() {
69+
return version;
70+
}
71+
6472
/////////////////////////////////////////////////////
6573
/////////////// API Implementation///////////////////
6674
/////////////////////////////////////////////////////

api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVnfApplianceCmd.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
public class DeployVnfApplianceCmd extends DeployVMCmd implements UserCmd {
4444

4545
@Parameter(name = ApiConstants.VNF_CONFIGURE_MANAGEMENT, type = CommandType.BOOLEAN, required = false,
46-
description = "True by default, security group or network rules (source nat and firewall rules) will be configured for VNF management interfaces. False otherwise. " +
46+
description = "False by default, security group or network rules (source nat and firewall rules) will be configured for VNF management interfaces. True otherwise. " +
4747
"Network rules are configured if management network is an isolated network or shared network with security groups.")
4848
private Boolean vnfConfigureManagement;
4949

api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateManager.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.cloudstack.api.command.user.vm.DeployVnfApplianceCmd;
3030
import org.apache.cloudstack.framework.config.ConfigKey;
3131
import java.util.List;
32+
import java.util.Map;
3233

3334
public interface VnfTemplateManager {
3435

@@ -42,11 +43,12 @@ public interface VnfTemplateManager {
4243

4344
void updateVnfTemplate(long templateId, UpdateVnfTemplateCmd cmd);
4445

45-
void validateVnfApplianceNics(VirtualMachineTemplate template, List<Long> networkIds);
46+
void validateVnfApplianceNics(VirtualMachineTemplate template, List<Long> networkIds, Map<Integer, Long> vmNetworkMap);
4647

4748
SecurityGroup createSecurityGroupForVnfAppliance(DataCenter zone, VirtualMachineTemplate template, Account owner, DeployVnfApplianceCmd cmd);
4849

4950
void createIsolatedNetworkRulesForVnfAppliance(DataCenter zone, VirtualMachineTemplate template, Account owner,
5051
UserVm vm, DeployVnfApplianceCmd cmd)
5152
throws InsufficientAddressCapacityException, ResourceAllocationException, ResourceUnavailableException;
53+
5254
}

api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateUtils.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package org.apache.cloudstack.storage.template;
1818

19+
import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
1920
import com.cloud.exception.InvalidParameterValueException;
2021
import com.cloud.network.VNF;
2122
import com.cloud.storage.Storage;
@@ -124,6 +125,9 @@ public static void validateVnfNics(List<VNF.VnfNic> nicsList) {
124125
public static void validateApiCommandParams(BaseCmd cmd, VirtualMachineTemplate template) {
125126
if (cmd instanceof RegisterVnfTemplateCmd) {
126127
RegisterVnfTemplateCmd registerCmd = (RegisterVnfTemplateCmd) cmd;
128+
if (registerCmd.isDeployAsIs() && CollectionUtils.isNotEmpty(registerCmd.getVnfNics())) {
129+
throw new InvalidParameterValueException("VNF nics cannot be specified when register a deploy-as-is Template. Please wait until Template settings are read from OVA.");
130+
}
127131
validateApiCommandParams(registerCmd.getVnfDetails(), registerCmd.getVnfNics(), registerCmd.getTemplateType());
128132
} else if (cmd instanceof UpdateVnfTemplateCmd) {
129133
UpdateVnfTemplateCmd updateCmd = (UpdateVnfTemplateCmd) cmd;
@@ -149,4 +153,18 @@ public static void validateVnfCidrList(List<String> cidrList) {
149153
}
150154
}
151155
}
156+
157+
public static void validateDeployAsIsTemplateVnfNics(List<OVFNetworkTO> ovfNetworks, List<VNF.VnfNic> vnfNics) {
158+
if (CollectionUtils.isEmpty(vnfNics)) {
159+
return;
160+
}
161+
if (CollectionUtils.isEmpty(ovfNetworks)) {
162+
throw new InvalidParameterValueException("The list of networks read from OVA is empty. Please wait until the template is fully downloaded and processed.");
163+
}
164+
for (VNF.VnfNic vnfNic : vnfNics) {
165+
if (vnfNic.getDeviceId() < ovfNetworks.size() && !vnfNic.isRequired()) {
166+
throw new InvalidParameterValueException(String.format("The VNF nic [device ID: %s ] is required as it is defined in the OVA template.", vnfNic.getDeviceId()));
167+
}
168+
}
169+
}
152170
}

engine/components-api/src/main/java/com/cloud/template/TemplateManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ public interface TemplateManager {
153153

154154
TemplateType validateTemplateType(BaseCmd cmd, boolean isAdmin, boolean isCrossZones, Hypervisor.HypervisorType hypervisorType);
155155

156+
DataStore verifyHeuristicRulesForZone(VMTemplateVO template, Long zoneId);
157+
156158
List<DatadiskTO> getTemplateDisksOnImageStore(VirtualMachineTemplate template, DataStoreRole role, String configurationId);
157159

158160
static Boolean getValidateUrlIsResolvableBeforeRegisteringTemplateValue() {

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachinePowerStateSyncImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ protected void updateAndPublishVmPowerStates(long hostId, Map<Long, VirtualMachi
8989
return;
9090
}
9191
for (Long vmId : vmIds) {
92-
if (!notUpdated.containsKey(vmId)) {
92+
if (MapUtils.isEmpty(notUpdated) || !notUpdated.containsKey(vmId)) {
9393
logger.debug("VM state report is updated. {}, {}, power state: {}",
9494
() -> hostCache.get(hostId), () -> vmCache.get(vmId), () -> instancePowerStates.get(vmId));
9595
_messageBus.publish(null, VirtualMachineManager.Topics.VM_POWER_STATE,
@@ -158,8 +158,8 @@ private void processMissingVmReport(long hostId, Set<Long> vmIds, boolean force)
158158
// an update might have occurred that we should not override in case of out of band migration
159159
instancePowerStates.put(instance.getId(), VirtualMachine.PowerState.PowerReportMissing);
160160
} else {
161-
logger.debug("vm id: {} - time since last state update({} ms) has not passed graceful period yet",
162-
instance.getId(), milliSecondsSinceLastStateUpdate);
161+
logger.debug("vm id: {} - time since last state update({} ms) has not passed graceful period ({} ms) yet",
162+
instance.getId(), milliSecondsSinceLastStateUpdate, milliSecondsGracefulPeriod);
163163
}
164164
}
165165
updateAndPublishVmPowerStates(hostId, instancePowerStates, startTime);

engine/storage/image/src/main/java/org/apache/cloudstack/storage/image/TemplateServiceImpl.java

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -291,21 +291,41 @@ public void handleSysTemplateDownload(HypervisorType hostHyper, Long dcId) {
291291
}
292292
}
293293

294-
protected boolean isSkipTemplateStoreDownload(VMTemplateVO template, Long zoneId) {
295-
if (template.isPublicTemplate()) {
294+
protected boolean shouldDownloadTemplateToStore(VMTemplateVO template, DataStore store) {
295+
Long zoneId = store.getScope().getScopeId();
296+
DataStore directedStore = _tmpltMgr.verifyHeuristicRulesForZone(template, zoneId);
297+
if (directedStore != null && store.getId() != directedStore.getId()) {
298+
logger.info("Template [{}] will not be download to image store [{}], as a heuristic rule is directing it to another store.",
299+
template.getUniqueName(), store.getName());
296300
return false;
297301
}
302+
303+
if (template.isPublicTemplate()) {
304+
logger.debug("Download of template [{}] to image store [{}] cannot be skipped, as it is public.", template.getUniqueName(),
305+
store.getName());
306+
return true;
307+
}
308+
298309
if (template.isFeatured()) {
299-
return false;
310+
logger.debug("Download of template [{}] to image store [{}] cannot be skipped, as it is featured.", template.getUniqueName(),
311+
store.getName());
312+
return true;
300313
}
314+
301315
if (TemplateType.SYSTEM.equals(template.getTemplateType())) {
302-
return false;
316+
logger.debug("Download of template [{}] to image store [{}] cannot be skipped, as it is a system VM template.",
317+
template.getUniqueName(),store.getName());
318+
return true;
303319
}
320+
304321
if (zoneId != null && _vmTemplateStoreDao.findByTemplateZone(template.getId(), zoneId, DataStoreRole.Image) == null) {
305-
logger.debug("Template {} is not present on any image store for the zone ID: {}, its download cannot be skipped", template, zoneId);
306-
return false;
322+
logger.debug("Download of template [{}] to image store [{}] cannot be skipped, as it is not present on any image store of zone [{}].",
323+
template.getUniqueName(), store.getName(), zoneId);
324+
return true;
307325
}
308-
return true;
326+
327+
logger.info("Skipping download of template [{}] to image store [{}].", template.getUniqueName(), store.getName());
328+
return false;
309329
}
310330

311331
@Override
@@ -533,8 +553,7 @@ public void handleTemplateSync(DataStore store) {
533553
// download.
534554
for (VMTemplateVO tmplt : toBeDownloaded) {
535555
// if this is private template, skip sync to a new image store
536-
if (isSkipTemplateStoreDownload(tmplt, zoneId)) {
537-
logger.info("Skip sync downloading private template {} to a new image store", tmplt);
556+
if (!shouldDownloadTemplateToStore(tmplt, store)) {
538557
continue;
539558
}
540559

engine/storage/image/src/test/java/org/apache/cloudstack/storage/image/TemplateServiceImplTest.java

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.cloudstack.storage.image;
2020

2121
import com.cloud.storage.template.TemplateProp;
22+
import com.cloud.template.TemplateManager;
2223
import org.apache.cloudstack.engine.orchestration.service.StorageOrchestrationService;
2324
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
2425
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
@@ -70,6 +71,9 @@ public class TemplateServiceImplTest {
7071
@Mock
7172
TemplateObject templateInfoMock;
7273

74+
@Mock
75+
DataStore dataStoreMock;
76+
7377
@Mock
7478
DataStore sourceStoreMock;
7579

@@ -82,6 +86,9 @@ public class TemplateServiceImplTest {
8286
@Mock
8387
StorageOrchestrationService storageOrchestrator;
8488

89+
@Mock
90+
TemplateManager templateManagerMock;
91+
8592
Map<String, TemplateProp> templatesInSourceStore = new HashMap<>();
8693

8794
@Before
@@ -96,45 +103,45 @@ public void setUp() {
96103
Mockito.doReturn(null).when(templateService).listTemplate(destStoreMock);
97104
Mockito.doReturn("install-path").when(templateInfoMock).getInstallPath();
98105
Mockito.doReturn(templateInfoMock).when(templateDataFactoryMock).getTemplate(2L, sourceStoreMock);
106+
Mockito.doReturn(3L).when(dataStoreMock).getId();
107+
Mockito.doReturn(zoneScopeMock).when(dataStoreMock).getScope();
108+
}
109+
110+
@Test
111+
public void shouldDownloadTemplateToStoreTestSkipsTemplateDirectedToAnotherStorage() {
112+
DataStore destinedStore = Mockito.mock(DataStore.class);
113+
Mockito.doReturn(dataStoreMock.getId() + 1L).when(destinedStore).getId();
114+
Mockito.when(templateManagerMock.verifyHeuristicRulesForZone(tmpltMock, zoneScopeMock.getScopeId())).thenReturn(destinedStore);
115+
Assert.assertFalse(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
99116
}
100117

101118
@Test
102-
public void testIsSkipTemplateStoreDownloadPublicTemplate() {
103-
VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class);
104-
Mockito.when(templateVO.isPublicTemplate()).thenReturn(true);
105-
Assert.assertFalse(templateService.isSkipTemplateStoreDownload(templateVO, 1L));
119+
public void shouldDownloadTemplateToStoreTestDownloadsPublicTemplate() {
120+
Mockito.when(tmpltMock.isPublicTemplate()).thenReturn(true);
121+
Assert.assertTrue(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
106122
}
107123

108124
@Test
109-
public void testIsSkipTemplateStoreDownloadFeaturedTemplate() {
110-
VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class);
111-
Mockito.when(templateVO.isFeatured()).thenReturn(true);
112-
Assert.assertFalse(templateService.isSkipTemplateStoreDownload(templateVO, 1L));
125+
public void shouldDownloadTemplateToStoreTestDownloadsFeaturedTemplate() {
126+
Mockito.when(tmpltMock.isFeatured()).thenReturn(true);
127+
Assert.assertTrue(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
113128
}
114129

115130
@Test
116-
public void testIsSkipTemplateStoreDownloadSystemTemplate() {
117-
VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class);
118-
Mockito.when(templateVO.getTemplateType()).thenReturn(Storage.TemplateType.SYSTEM);
119-
Assert.assertFalse(templateService.isSkipTemplateStoreDownload(templateVO, 1L));
131+
public void shouldDownloadTemplateToStoreTestDownloadsSystemTemplate() {
132+
Mockito.when(tmpltMock.getTemplateType()).thenReturn(Storage.TemplateType.SYSTEM);
133+
Assert.assertTrue(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
120134
}
121135

122136
@Test
123-
public void testIsSkipTemplateStoreDownloadPrivateNoRefTemplate() {
124-
VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class);
125-
long id = 1L;
126-
Mockito.when(templateVO.getId()).thenReturn(id);
127-
Mockito.when(templateDataStoreDao.findByTemplateZone(id, id, DataStoreRole.Image)).thenReturn(null);
128-
Assert.assertFalse(templateService.isSkipTemplateStoreDownload(templateVO, id));
137+
public void shouldDownloadTemplateToStoreTestDownloadsPrivateNoRefTemplate() {
138+
Assert.assertTrue(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
129139
}
130140

131141
@Test
132-
public void testIsSkipTemplateStoreDownloadPrivateExistingTemplate() {
133-
VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class);
134-
long id = 1L;
135-
Mockito.when(templateVO.getId()).thenReturn(id);
136-
Mockito.when(templateDataStoreDao.findByTemplateZone(id, id, DataStoreRole.Image)).thenReturn(Mockito.mock(TemplateDataStoreVO.class));
137-
Assert.assertTrue(templateService.isSkipTemplateStoreDownload(templateVO, id));
142+
public void shouldDownloadTemplateToStoreTestSkipsPrivateExistingTemplate() {
143+
Mockito.when(templateDataStoreDao.findByTemplateZone(tmpltMock.getId(), zoneScopeMock.getScopeId(), DataStoreRole.Image)).thenReturn(Mockito.mock(TemplateDataStoreVO.class));
144+
Assert.assertFalse(templateService.shouldDownloadTemplateToStore(tmpltMock, dataStoreMock));
138145
}
139146

140147
@Test

0 commit comments

Comments
 (0)