Skip to content

Commit 02ece53

Browse files
GabrielBrascheryadvr
authored andcommitted
addNicToVirtualMachine: Fixes #2540 handle invalid MAC address arg (#2653)
Look for the next available MAC address if the given MAC address in command addNicToVirtualMachine is invalid (null, empty, blank). Fixes #2540
1 parent e471a46 commit 02ece53

2 files changed

Lines changed: 70 additions & 0 deletions

File tree

server/src/com/cloud/vm/UserVmManagerImpl.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,8 @@ public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterV
11691169
}
11701170
}
11711171

1172+
macAddress = validateOrReplaceMacAddress(macAddress, network.getId());
1173+
11721174
if(_nicDao.findByNetworkIdAndMacAddress(networkId, macAddress) != null) {
11731175
throw new CloudRuntimeException("A NIC with this MAC address exists for network: " + network.getUuid());
11741176
}
@@ -1239,6 +1241,19 @@ public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterV
12391241
return _vmDao.findById(vmInstance.getId());
12401242
}
12411243

1244+
/**
1245+
* If the given MAC address is invalid it replaces the given MAC with the next available MAC address
1246+
*/
1247+
protected String validateOrReplaceMacAddress(String macAddress, long networkId) {
1248+
if (!NetUtils.isValidMac(macAddress)) {
1249+
try {
1250+
macAddress = _networkModel.getNextAvailableMacAddressInNetwork(networkId);
1251+
} catch (InsufficientAddressCapacityException e) {
1252+
throw new CloudRuntimeException(String.format("A MAC address cannot be generated for this NIC in the network [id=%s] ", networkId));
1253+
}
1254+
}
1255+
return macAddress;
1256+
}
12421257

12431258
private void saveExtraDhcpOptions(long nicId, Map<Integer, String> dhcpOptions) {
12441259
List<NicExtraDhcpOptionVO> nicExtraDhcpOptionVOList = dhcpOptions

server/test/com/cloud/vm/UserVmManagerImplTest.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
2323
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
2424
import org.apache.cloudstack.context.CallContext;
25+
import org.junit.Assert;
2526
import org.junit.Before;
2627
import org.junit.Test;
2728
import org.junit.runner.RunWith;
@@ -34,9 +35,11 @@
3435
import org.powermock.core.classloader.annotations.PrepareForTest;
3536
import org.powermock.modules.junit4.PowerMockRunner;
3637

38+
import com.cloud.exception.InsufficientAddressCapacityException;
3739
import com.cloud.exception.InsufficientCapacityException;
3840
import com.cloud.exception.InvalidParameterValueException;
3941
import com.cloud.exception.ResourceUnavailableException;
42+
import com.cloud.network.NetworkModel;
4043
import com.cloud.storage.GuestOSVO;
4144
import com.cloud.storage.dao.GuestOSDao;
4245
import com.cloud.user.Account;
@@ -70,6 +73,9 @@ public class UserVmManagerImplTest {
7073
@Mock
7174
private UserVmVO userVmVoMock;
7275

76+
@Mock
77+
private NetworkModel networkModel;
78+
7379
private long vmId = 1l;
7480

7581
@Before
@@ -221,4 +227,53 @@ private void configureDoNothingForMethodsThatWeDoNotWantToTest() throws Resource
221227
Mockito.anyString(), Mockito.anyBoolean(), Mockito.any(HTTPMethod.class), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyListOf(Long.class),
222228
Mockito.anyMap());
223229
}
230+
231+
@Test
232+
public void validateOrReplaceMacAddressTestMacAddressValid() throws InsufficientAddressCapacityException {
233+
configureValidateOrReplaceMacAddressTest(0, "01:23:45:67:89:ab", "01:23:45:67:89:ab");
234+
}
235+
236+
@Test
237+
public void validateOrReplaceMacAddressTestMacAddressNull() throws InsufficientAddressCapacityException {
238+
configureValidateOrReplaceMacAddressTest(1, null, "01:23:45:67:89:ab");
239+
}
240+
241+
@Test
242+
public void validateOrReplaceMacAddressTestMacAddressBlank() throws InsufficientAddressCapacityException {
243+
configureValidateOrReplaceMacAddressTest(1, " ", "01:23:45:67:89:ab");
244+
}
245+
246+
@Test
247+
public void validateOrReplaceMacAddressTestMacAddressEmpty() throws InsufficientAddressCapacityException {
248+
configureValidateOrReplaceMacAddressTest(1, "", "01:23:45:67:89:ab");
249+
}
250+
251+
@Test
252+
public void validateOrReplaceMacAddressTestMacAddressNotValidOption1() throws InsufficientAddressCapacityException {
253+
configureValidateOrReplaceMacAddressTest(1, "abcdef:gh:ij:kl", "01:23:45:67:89:ab");
254+
}
255+
256+
@Test
257+
public void validateOrReplaceMacAddressTestMacAddressNotValidOption2() throws InsufficientAddressCapacityException {
258+
configureValidateOrReplaceMacAddressTest(1, "01:23:45:67:89:", "01:23:45:67:89:ab");
259+
}
260+
261+
@Test
262+
public void validateOrReplaceMacAddressTestMacAddressNotValidOption3() throws InsufficientAddressCapacityException {
263+
configureValidateOrReplaceMacAddressTest(1, "01:23:45:67:89:az", "01:23:45:67:89:ab");
264+
}
265+
266+
@Test
267+
public void validateOrReplaceMacAddressTestMacAddressNotValidOption4() throws InsufficientAddressCapacityException {
268+
configureValidateOrReplaceMacAddressTest(1, "@1:23:45:67:89:ab", "01:23:45:67:89:ab");
269+
}
270+
271+
private void configureValidateOrReplaceMacAddressTest(int times, String macAddress, String expectedMacAddress) throws InsufficientAddressCapacityException {
272+
Mockito.when(networkModel.getNextAvailableMacAddressInNetwork(Mockito.anyLong())).thenReturn(expectedMacAddress);
273+
274+
String returnedMacAddress = userVmManagerImpl.validateOrReplaceMacAddress(macAddress, 1l);
275+
276+
Mockito.verify(networkModel, Mockito.times(times)).getNextAvailableMacAddressInNetwork(Mockito.anyLong());
277+
Assert.assertEquals(expectedMacAddress, returnedMacAddress);
278+
}
224279
}

0 commit comments

Comments
 (0)