From 71c9c90e0c81ea9e0f90ab71d3430d62cd8fa02e Mon Sep 17 00:00:00 2001 From: Nick Livens Date: Mon, 2 May 2016 13:16:14 +0200 Subject: [PATCH] CLOUDSTACK-9365 : updateVirtualMachine with userdata should not error when a VM is attached to multiple networks from which one or more doesn't support userdata --- .../src/com/cloud/vm/UserVmManagerImpl.java | 40 ++++++++------ .../test/com/cloud/vm/UserVmManagerTest.java | 52 +++++++++++++++++++ 2 files changed, 77 insertions(+), 15 deletions(-) diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index cc007d90210..83ee2489c61 100644 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2492,24 +2492,34 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir return false; } + boolean userDataApplied = false; for (Nic nic : nics) { - Network network = _networkDao.findById(nic.getNetworkId()); - NicProfile nicProfile = new NicProfile(nic, network, null, null, null, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag( - template.getHypervisorType(), network)); - - VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vm); - - UserDataServiceProvider element = _networkModel.getUserDataUpdateProvider(network); - if (element == null) { - throw new CloudRuntimeException("Can't find network element for " + Service.UserData.getName() + " provider needed for UserData update"); - } - boolean result = element.saveUserData(network, nicProfile, vmProfile); - if (!result) { - s_logger.error("Failed to update userdata for vm " + vm + " and nic " + nic); - } + userDataApplied |= applyUserData(template.getHypervisorType(), vm, nic); } + return userDataApplied; + } - return true; + protected boolean applyUserData(HypervisorType hyperVisorType, UserVm vm, Nic nic) throws ResourceUnavailableException, InsufficientCapacityException { + Network network = _networkDao.findById(nic.getNetworkId()); + NicProfile nicProfile = new NicProfile(nic, network, null, null, null, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag( + hyperVisorType, network)); + VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vm); + + if (_networkModel.areServicesSupportedByNetworkOffering(network.getNetworkOfferingId(), Service.UserData)) { + UserDataServiceProvider element = _networkModel.getUserDataUpdateProvider(network); + if (element == null) { + throw new CloudRuntimeException("Can't find network element for " + Service.UserData.getName() + " provider needed for UserData update"); + } + boolean result = element.saveUserData(network, nicProfile, vmProfile); + if (!result) { + s_logger.error("Failed to update userdata for vm " + vm + " and nic " + nic); + } else { + return true; + } + } else { + s_logger.debug("Not applying userdata for nic id=" + nic.getId() + " in vm id=" + vmProfile.getId() + " because it is not supported in network id=" + network.getId()); + } + return false; } @Override diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java b/server/test/com/cloud/vm/UserVmManagerTest.java index 637a3092219..9df3f689714 100644 --- a/server/test/com/cloud/vm/UserVmManagerTest.java +++ b/server/test/com/cloud/vm/UserVmManagerTest.java @@ -17,6 +17,8 @@ package com.cloud.vm; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyFloat; @@ -37,9 +39,11 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; +import com.cloud.network.element.UserDataServiceProvider; import com.cloud.storage.Storage; import com.cloud.user.User; import com.cloud.event.dao.UsageEventDao; +import com.cloud.uservm.UserVm; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -929,6 +933,54 @@ public class UserVmManagerTest { } } + @Test + public void testApplyUserDataInNetworkWithoutUserDataSupport() throws Exception { + UserVm userVm = mock(UserVm.class); + when(userVm.getId()).thenReturn(1L); + + when(_nicMock.getNetworkId()).thenReturn(2L); + when(_networkMock.getNetworkOfferingId()).thenReturn(3L); + when(_networkDao.findById(2L)).thenReturn(_networkMock); + + // No userdata support + assertFalse(_userVmMgr.applyUserData(HypervisorType.KVM, userVm, _nicMock)); + } + + @Test(expected = CloudRuntimeException.class) + public void testApplyUserDataInNetworkWithoutElement() throws Exception { + UserVm userVm = mock(UserVm.class); + when(userVm.getId()).thenReturn(1L); + + when(_nicMock.getNetworkId()).thenReturn(2L); + when(_networkMock.getNetworkOfferingId()).thenReturn(3L); + when(_networkDao.findById(2L)).thenReturn(_networkMock); + + UserDataServiceProvider userDataServiceProvider = mock(UserDataServiceProvider.class); + when(userDataServiceProvider.saveUserData(any(Network.class), any(NicProfile.class), any(VirtualMachineProfile.class))).thenReturn(true); + + // Userdata support, but no implementing element + when(_networkModel.areServicesSupportedByNetworkOffering(3L, Service.UserData)).thenReturn(true); + _userVmMgr.applyUserData(HypervisorType.KVM, userVm, _nicMock); + } + + @Test + public void testApplyUserDataSuccessful() throws Exception { + UserVm userVm = mock(UserVm.class); + when(userVm.getId()).thenReturn(1L); + + when(_nicMock.getNetworkId()).thenReturn(2L); + when(_networkMock.getNetworkOfferingId()).thenReturn(3L); + when(_networkDao.findById(2L)).thenReturn(_networkMock); + + UserDataServiceProvider userDataServiceProvider = mock(UserDataServiceProvider.class); + when(userDataServiceProvider.saveUserData(any(Network.class), any(NicProfile.class), any(VirtualMachineProfile.class))).thenReturn(true); + + // Userdata support with implementing element + when(_networkModel.areServicesSupportedByNetworkOffering(3L, Service.UserData)).thenReturn(true); + when(_networkModel.getUserDataUpdateProvider(_networkMock)).thenReturn(userDataServiceProvider); + assertTrue(_userVmMgr.applyUserData(HypervisorType.KVM, userVm, _nicMock)); + } + @Test public void testPersistDeviceBusInfoWithNullController() { when(_vmMock.getDetail(any(String.class))).thenReturn(null);