Skip to content

Commit ea700b9

Browse files
committed
Allow multiple nics with configdrive
1 parent b8a1a90 commit ea700b9

File tree

5 files changed

+76
-36
lines changed

5 files changed

+76
-36
lines changed

engine/storage/configdrive/src/main/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilder.java

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ public static File base64StringToFile(String encodedIsoData, String folder, Stri
118118
* This method will build the metadata files required by OpenStack driver. Then, an ISO is going to be generated and returned as a String in base 64.
119119
* If vmData is null, we throw a {@link CloudRuntimeException}. Moreover, {@link IOException} are captured and re-thrown as {@link CloudRuntimeException}.
120120
*/
121-
public static String buildConfigDrive(NicProfile nic, List<String[]> vmData, String isoFileName, String driveLabel, Map<String, String> customUserdataParams, List<Network.Service> supportedServices) {
122-
if (vmData == null && nic == null) {
121+
public static String buildConfigDrive(List<NicProfile> nics, List<String[]> vmData, String isoFileName, String driveLabel, Map<String, String> customUserdataParams, Map<Long, List<Network.Service>> supportedServices) {
122+
if (vmData == null && nics == null) {
123123
throw new CloudRuntimeException("No VM metadata and nic profile provided");
124124
}
125125

@@ -132,11 +132,14 @@ public static String buildConfigDrive(NicProfile nic, List<String[]> vmData, Str
132132
File openStackFolder = new File(tempDirName + ConfigDrive.openStackConfigDriveName);
133133

134134
writeVendorEmptyJsonFile(openStackFolder);
135-
writeNetworkData(nic, supportedServices, openStackFolder);
136-
if (supportedServices.contains(Network.Service.UserData)) {
137-
writeVmMetadata(vmData, tempDirName, openStackFolder, customUserdataParams);
135+
writeNetworkData(nics, supportedServices, openStackFolder);
136+
for (NicProfile nic: nics) {
137+
if (supportedServices.get(nic.getId()).contains(Network.Service.UserData)) {
138+
writeVmMetadata(vmData, tempDirName, openStackFolder, customUserdataParams);
138139

139-
linkUserData(tempDirName);
140+
linkUserData(tempDirName);
141+
break;
142+
}
140143
}
141144

142145
return generateAndRetrieveIsoAsBase64Iso(isoFileName, driveLabel, tempDirName);
@@ -244,21 +247,24 @@ static JsonObject getExistingNetworkData(File openStackFolder) {
244247
/**
245248
* First we generate a JSON object using {@link #getNetworkDataJsonObjectForNic(NicProfile, List)}, then we write it to a file called "network_data.json".
246249
*/
247-
static void writeNetworkData(NicProfile nic, List<Network.Service> supportedServices, File openStackFolder) {
248-
JsonObject networkData = getNetworkDataJsonObjectForNic(nic, supportedServices);
249-
JsonObject existingNetworkData = getExistingNetworkData(openStackFolder);
250+
static void writeNetworkData(List<NicProfile> nics, Map<Long, List<Network.Service>> supportedServices, File openStackFolder) {
250251

251252
JsonObject finalNetworkData = new JsonObject();
252-
mergeJsonArraysAndUpdateObject(finalNetworkData, existingNetworkData, networkData, "links", "id", "type");
253-
mergeJsonArraysAndUpdateObject(finalNetworkData, existingNetworkData, networkData, "networks", "id", "type");
254-
mergeJsonArraysAndUpdateObject(finalNetworkData, existingNetworkData, networkData, "services", "address", "type");
253+
for (NicProfile nic: nics) {
254+
List<Network.Service> supportedService = supportedServices.get(nic.getId());
255+
JsonObject networkData = getNetworkDataJsonObjectForNic(nic, supportedService);
256+
257+
mergeJsonArraysAndUpdateObject(finalNetworkData, networkData, "links", "id", "type");
258+
mergeJsonArraysAndUpdateObject(finalNetworkData, networkData, "networks", "id", "type");
259+
mergeJsonArraysAndUpdateObject(finalNetworkData, networkData, "services", "address", "type");
260+
}
255261

256-
writeFile(openStackFolder, "network_data.json", existingNetworkData.toString());
262+
writeFile(openStackFolder, "network_data.json", finalNetworkData.toString());
257263
}
258264

259-
static void mergeJsonArraysAndUpdateObject(JsonObject finalObject, JsonObject obj1, JsonObject obj2, String memberName, String keyPart1, String keyPart2) {
260-
JsonArray existingMembers = obj1.has(memberName) ? obj1.get(memberName).getAsJsonArray() : new JsonArray();
261-
JsonArray newMembers = obj2.has(memberName) ? obj2.get(memberName).getAsJsonArray() : new JsonArray();
265+
static void mergeJsonArraysAndUpdateObject(JsonObject finalObject, JsonObject newObj, String memberName, String keyPart1, String keyPart2) {
266+
JsonArray existingMembers = finalObject.has(memberName) ? finalObject.get(memberName).getAsJsonArray() : new JsonArray();
267+
JsonArray newMembers = newObj.has(memberName) ? newObj.get(memberName).getAsJsonArray() : new JsonArray();
262268

263269
if (existingMembers.size() > 0 || newMembers.size() > 0) {
264270
JsonArray finalMembers = new JsonArray();

engine/storage/configdrive/src/test/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilderTest.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.Map;
3333

3434
import com.cloud.network.Network;
35+
import com.cloud.vm.NicProfile;
3536
import org.apache.commons.io.FileUtils;
3637
import org.apache.commons.lang3.StringUtils;
3738
import org.junit.Assert;
@@ -51,11 +52,11 @@
5152
@RunWith(MockitoJUnitRunner.class)
5253
public class ConfigDriveBuilderTest {
5354

54-
private static List<Network.Service> supportedServices;
55+
private static Map<Long, List<Network.Service>> supportedServices;
5556

5657
@BeforeClass
5758
public static void beforeClass() throws Exception {
58-
supportedServices = List.of(Network.Service.UserData, Network.Service.Dhcp, Network.Service.Dns);
59+
supportedServices = Map.of(1L, List.of(Network.Service.UserData, Network.Service.Dhcp, Network.Service.Dns));
5960
}
6061

6162
@Test
@@ -145,10 +146,14 @@ public void buildConfigDriveTest() {
145146
configDriveBuilderMocked.when(() -> ConfigDriveBuilder.linkUserData((Mockito.anyString()))).then(invocationOnMock -> null);
146147

147148
configDriveBuilderMocked.when(() -> ConfigDriveBuilder.generateAndRetrieveIsoAsBase64Iso(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenAnswer(invocation -> "mockIsoDataBase64");
149+
150+
NicProfile mockedNicProfile = Mockito.mock(NicProfile.class);
151+
Mockito.when(mockedNicProfile.getId()).thenReturn(1L);
152+
148153
//force execution of real method
149-
Mockito.when(ConfigDriveBuilder.buildConfigDrive(null, new ArrayList<>(), "teste", "C:", null, supportedServices)).thenCallRealMethod();
154+
Mockito.when(ConfigDriveBuilder.buildConfigDrive(List.of(mockedNicProfile), new ArrayList<>(), "teste", "C:", null, supportedServices)).thenCallRealMethod();
150155

151-
String returnedIsoData = ConfigDriveBuilder.buildConfigDrive(null, new ArrayList<>(), "teste", "C:", null, supportedServices);
156+
String returnedIsoData = ConfigDriveBuilder.buildConfigDrive(List.of(mockedNicProfile), new ArrayList<>(), "teste", "C:", null, supportedServices);
152157

153158
Assert.assertEquals("mockIsoDataBase64", returnedIsoData);
154159

server/src/main/java/com/cloud/network/NetworkModelImpl.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,7 +2174,6 @@ public NicProfile getNicProfile(VirtualMachine vm, long networkId, String broadc
21742174
NetworkVO network = _networksDao.findById(networkId);
21752175
Integer networkRate = getNetworkRate(network.getId(), vm.getId());
21762176

2177-
// NetworkGuru guru = _networkGurus.get(network.getGuruName());
21782177
NicProfile profile =
21792178
new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), networkRate, isSecurityGroupSupportedInNetwork(network), getNetworkTag(
21802179
vm.getHypervisorType(), network));
@@ -2184,7 +2183,17 @@ public NicProfile getNicProfile(VirtualMachine vm, long networkId, String broadc
21842183
if (network.getTrafficType() == TrafficType.Guest && network.getPrivateMtu() != null) {
21852184
profile.setMtu(network.getPrivateMtu());
21862185
}
2187-
// guru.updateNicProfile(profile, network);
2186+
2187+
DataCenter dc = _dcDao.findById(network.getDataCenterId());
2188+
2189+
Pair<String, String> ip4Dns = getNetworkIp4Dns(network, dc);
2190+
profile.setIPv4Dns1(ip4Dns.first());
2191+
profile.setIPv4Dns2(ip4Dns.second());
2192+
2193+
Pair<String, String> ip6Dns = getNetworkIp6Dns(network, dc);
2194+
profile.setIPv6Dns1(ip6Dns.first());
2195+
profile.setIPv6Dns2(ip6Dns.second());
2196+
21882197
return profile;
21892198
}
21902199

server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,10 @@ private boolean createConfigDriveIsoOnHostCache(NicProfile nic, VirtualMachinePr
546546

547547
final String isoFileName = ConfigDrive.configIsoFileName(profile.getInstanceName());
548548
final String isoPath = ConfigDrive.createConfigDrivePath(profile.getInstanceName());
549-
final String isoData = ConfigDriveBuilder.buildConfigDrive(nic, profile.getVmData(), isoFileName, profile.getConfigDriveLabel(), customUserdataParamMap, getSupportedServicesByElementForNetwork(nic.getNetworkId()));
549+
List<? extends Nic> nics = _networkModel.getNics(nic.getVirtualMachineId());
550+
List<NicProfile> nicProfiles = getNicProfilesForNic(profile.getVirtualMachine(), nics);
551+
final Map<Long, List<Service>> supportedServices = getSupportedServicesByElementForNetwork(nicProfiles);
552+
final String isoData = ConfigDriveBuilder.buildConfigDrive(nicProfiles, profile.getVmData(), isoFileName, profile.getConfigDriveLabel(), customUserdataParamMap, supportedServices);
550553
final HandleConfigDriveIsoCommand configDriveIsoCommand = new HandleConfigDriveIsoCommand(isoPath, isoData, null, false, true, true);
551554

552555
final HandleConfigDriveIsoAnswer answer = (HandleConfigDriveIsoAnswer) agentManager.easySend(hostId, configDriveIsoCommand);
@@ -596,18 +599,31 @@ private boolean deleteConfigDriveIsoOnHostCache(final VirtualMachine vm, final L
596599
return true;
597600
}
598601

599-
private List<Network.Service> getSupportedServicesByElementForNetwork(Long networkId) {
600-
601-
List<Network.Service> supportedServices = new ArrayList<>();
602-
if (_networkModel.isProviderSupportServiceInNetwork(networkId, Service.Dns, getProvider())) {
603-
supportedServices.add(Service.Dns);
604-
}
605-
if (_networkModel.isProviderSupportServiceInNetwork(networkId, Service.UserData, getProvider())) {
606-
supportedServices.add(Service.UserData);
602+
private List<NicProfile> getNicProfilesForNic(VirtualMachine vm, List<? extends Nic> nics) {
603+
List<NicProfile> nicProfiles = new ArrayList<>();
604+
for (Nic nic: nics) {
605+
nicProfiles.add(_networkModel.getNicProfile(vm, nic.getNetworkId(), null));
607606
}
608-
if (_networkModel.isProviderSupportServiceInNetwork(networkId, Service.Dhcp, getProvider())) {
609-
supportedServices.add(Service.Dhcp);
607+
return nicProfiles;
608+
}
609+
610+
private Map<Long, List<Network.Service>> getSupportedServicesByElementForNetwork(List<NicProfile> nics) {
611+
612+
Map<Long, List<Network.Service>> supportedServices = new HashMap<>();
613+
for (NicProfile nic: nics) {
614+
ArrayList<Network.Service> serviceList = new ArrayList<>();
615+
if (_networkModel.isProviderSupportServiceInNetwork(nic.getNetworkId(), Service.Dns, getProvider())) {
616+
serviceList.add(Service.Dns);
617+
}
618+
if (_networkModel.isProviderSupportServiceInNetwork(nic.getNetworkId(), Service.UserData, getProvider())) {
619+
serviceList.add(Service.UserData);
620+
}
621+
if (_networkModel.isProviderSupportServiceInNetwork(nic.getNetworkId(), Service.Dhcp, getProvider())) {
622+
serviceList.add(Service.Dhcp);
623+
}
624+
supportedServices.put(nic.getId(), serviceList);
610625
}
626+
611627
return supportedServices;
612628
}
613629

@@ -626,9 +642,11 @@ public boolean createConfigDriveIso(NicProfile nic, VirtualMachineProfile profil
626642

627643
final String isoFileName = ConfigDrive.configIsoFileName(profile.getInstanceName());
628644
final String isoPath = ConfigDrive.createConfigDrivePath(profile.getInstanceName());
629-
List<Service> supportedServices = getSupportedServicesByElementForNetwork(nic.getNetworkId());
645+
List<? extends Nic> nics = _networkModel.getNics(profile.getId());
646+
List<NicProfile> nicProfiles = getNicProfilesForNic(profile.getVirtualMachine(), nics);
647+
final Map<Long, List<Service>> supportedServices = getSupportedServicesByElementForNetwork(nicProfiles);
630648
final String isoData = ConfigDriveBuilder.buildConfigDrive(
631-
nic, profile.getVmData(), isoFileName, profile.getConfigDriveLabel(), customUserdataParamMap, supportedServices);
649+
nicProfiles, profile.getVmData(), isoFileName, profile.getConfigDriveLabel(), customUserdataParamMap, supportedServices);
632650
boolean useHostCacheOnUnsupportedPool = VirtualMachineManager.VmConfigDriveUseHostCacheOnUnsupportedPool.valueIn(dest.getDataCenter().getId());
633651
boolean preferHostCache = VirtualMachineManager.VmConfigDriveForceHostCacheUse.valueIn(dest.getDataCenter().getId());
634652
final HandleConfigDriveIsoCommand configDriveIsoCommand = new HandleConfigDriveIsoCommand(isoPath, isoData, dataStore.getTO(), useHostCacheOnUnsupportedPool, preferHostCache, true);

server/src/test/java/com/cloud/network/element/ConfigDriveNetworkElementTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ public void setUp() throws NoSuchFieldException, IllegalAccessException {
170170
when(_dcDao.findById(DATACENTERID)).thenReturn(dataCenterVO);
171171
when(_domainDao.findById(DOMAINID)).thenReturn(domainVO);
172172
doReturn(nic).when(_networkModel).getDefaultNic(VMID);
173+
doReturn(List.of(nic)).when(_networkModel).getNics(VMID);
174+
doReturn(nicp).when(_networkModel).getNicProfile(virtualMachine, NETWORK_ID, null);
173175
when(_serviceOfferingDao.findByIdIncludingRemoved(VMID, SOID)).thenReturn(serviceOfferingVO);
174176
when(_guestOSDao.findById(Mockito.anyLong())).thenReturn(guestOSVO);
175177
when(_guestOSCategoryDao.findById(Mockito.anyLong())).thenReturn(guestOSCategoryVo);
@@ -292,7 +294,7 @@ public void testAddPasswordAndUserData() throws Exception {
292294
public void testCreateConfigDriveIso() throws Exception {
293295
try (MockedStatic<ConfigDriveBuilder> ignored1 = Mockito.mockStatic(ConfigDriveBuilder.class); MockedStatic<CallContext> ignored2 = Mockito.mockStatic(CallContext.class)) {
294296
Mockito.when(CallContext.current()).thenReturn(callContextMock);
295-
Mockito.when(ConfigDriveBuilder.buildConfigDrive(Mockito.any(NicProfile.class), Mockito.anyList(), Mockito.anyString(), Mockito.anyString(), Mockito.anyMap(), Mockito.anyList())).thenReturn("content");
297+
Mockito.when(ConfigDriveBuilder.buildConfigDrive(Mockito.anyList(), Mockito.anyList(), Mockito.anyString(), Mockito.anyString(), Mockito.anyMap(), Mockito.anyMap())).thenReturn("content");
296298

297299
final HandleConfigDriveIsoAnswer answer = mock(HandleConfigDriveIsoAnswer.class);
298300
when(agentManager.easySend(Mockito.anyLong(), Mockito.any(HandleConfigDriveIsoCommand.class))).thenReturn(answer);

0 commit comments

Comments
 (0)