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

This commit is contained in:
Nick Livens 2016-05-02 13:16:14 +02:00
parent dc5b52937b
commit 71c9c90e0c
2 changed files with 77 additions and 15 deletions

View File

@ -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

View File

@ -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);