Skip to content

Commit 8520324

Browse files
fmaximusrafaelweingartner
authored andcommitted
ConfigDrive fixes: CLOUDSTACK-10288, CLOUDSTACK-10289 (#2566)
* CLOUDSTACK-10289: Config Drive Metadata: Use VM UUID instead of VM id * CLOUDSTACK-10288: Config Drive Userdata: support for binary userdata * CLOUDSTACK-10358: SSH keys are missing on Config Drive disk in some cases
1 parent b6d420b commit 8520324

14 files changed

Lines changed: 986 additions & 1033 deletions

File tree

api/src/com/cloud/network/NetworkModel.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public interface NetworkModel {
5959
String SERVICE_OFFERING_FILE = "service-offering";
6060
String AVAILABILITY_ZONE_FILE = "availability-zone";
6161
String LOCAL_HOSTNAME_FILE = "local-hostname";
62+
String LOCAL_IPV4_FILE = "local-ipv4";
63+
String PUBLIC_HOSTNAME_FILE = "public-hostname";
64+
String PUBLIC_IPV4_FILE = "public-ipv4";
6265
String INSTANCE_ID_FILE = "instance-id";
6366
String VM_ID_FILE = "vm-id";
6467
String PUBLIC_KEYS_FILE = "public-keys";
@@ -309,8 +312,8 @@ public interface NetworkModel {
309312

310313
boolean getNetworkEgressDefaultPolicy(Long networkId);
311314

312-
List<String[]> generateVmData(String userData, String serviceOffering, String zoneName,
313-
String vmName, long vmId, String publicKey, String password, Boolean isWindows);
315+
List<String[]> generateVmData(String userData, String serviceOffering, long datacenterId,
316+
String vmName, long vmId, String vmUuid, String guestIpAddress, String publicKey, String password, Boolean isWindows);
314317

315318
String getValidNetworkCidr(Network guestNetwork);
316319

engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2518,16 +2518,15 @@ private void orchestrateMigrateWithStorage(final String vmUuid, final long srcHo
25182518
if (defaultNic != null) {
25192519
UserVmVO userVm = _userVmDao.findById(vm.getId());
25202520
Map<String, String> details = _vmDetailsDao.listDetailsKeyPairs(vm.getId());
2521-
vm.setDetails(details);
2521+
userVm.setDetails(details);
25222522

25232523
Network network = _networkModel.getNetwork(defaultNic.getNetworkId());
25242524
if (_networkModel.isSharedNetworkWithoutServices(network.getId())) {
25252525
final String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText();
2526-
final String zoneName = _dcDao.findById(vm.getDataCenterId()).getName();
25272526
boolean isWindows = _guestOSCategoryDao.findById(_guestOSDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
25282527

2529-
vmData = _networkModel.generateVmData(userVm.getUserData(), serviceOffering, zoneName, vm.getInstanceName(), vm.getId(),
2530-
(String) profile.getParameter(VirtualMachineProfile.Param.VmSshPubKey), (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
2528+
vmData = _networkModel.generateVmData(userVm.getUserData(), serviceOffering, vm.getDataCenterId(), vm.getInstanceName(), vm.getId(),
2529+
vm.getUuid(), defaultNic.getMacAddress(), userVm.getDetail("SSH.PublicKey"), (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
25312530
String vmName = vm.getInstanceName();
25322531
String configDriveIsoRootFolder = "/tmp";
25332532
String isoFile = configDriveIsoRootFolder + "/" + vmName + "/configDrive/" + vmName + ".iso";

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

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,31 +22,32 @@
2222
import java.security.MessageDigest;
2323
import java.security.NoSuchAlgorithmException;
2424
import java.util.ArrayList;
25+
import java.util.Collections;
2526
import java.util.HashMap;
2627
import java.util.HashSet;
2728
import java.util.Iterator;
2829
import java.util.List;
2930
import java.util.Map;
3031
import java.util.Set;
3132
import java.util.TreeSet;
32-
import java.util.Collections;
33+
3334
import javax.inject.Inject;
3435
import javax.naming.ConfigurationException;
3536

36-
import org.apache.commons.codec.binary.Base64;
3737
import org.apache.log4j.Logger;
3838

39+
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
3940
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
4041
import org.apache.cloudstack.framework.config.ConfigKey;
4142
import org.apache.cloudstack.framework.config.Configurable;
42-
43-
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
4443
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
4544
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
45+
4646
import com.cloud.api.ApiDBUtils;
4747
import com.cloud.configuration.Config;
4848
import com.cloud.configuration.ConfigurationManager;
4949
import com.cloud.dc.DataCenter;
50+
import com.cloud.dc.DataCenterVO;
5051
import com.cloud.dc.PodVlanMapVO;
5152
import com.cloud.dc.Vlan;
5253
import com.cloud.dc.Vlan.VlanType;
@@ -2344,18 +2345,47 @@ public boolean getNetworkEgressDefaultPolicy(Long networkId) {
23442345
}
23452346

23462347
@Override
2347-
public List<String[]> generateVmData(String userData, String serviceOffering, String zoneName,
2348-
String vmName, long vmId, String publicKey, String password, Boolean isWindows) {
2348+
public List<String[]> generateVmData(String userData, String serviceOffering, long datacenterId,
2349+
String vmName, long vmId, String vmUuid,
2350+
String guestIpAddress, String publicKey, String password, Boolean isWindows) {
2351+
2352+
DataCenterVO dcVo = _dcDao.findById(datacenterId);
2353+
final String zoneName = dcVo.getName();
2354+
2355+
IPAddressVO publicIp = _ipAddressDao.findByAssociatedVmId(vmId);
2356+
23492357
final List<String[]> vmData = new ArrayList<String[]>();
23502358

23512359
if (userData != null) {
2352-
vmData.add(new String[]{USERDATA_DIR, USERDATA_FILE, new String(Base64.decodeBase64(userData),StringUtils.getPreferredCharset())});
2360+
vmData.add(new String[]{USERDATA_DIR, USERDATA_FILE, userData});
23532361
}
23542362
vmData.add(new String[]{METATDATA_DIR, SERVICE_OFFERING_FILE, StringUtils.unicodeEscape(serviceOffering)});
23552363
vmData.add(new String[]{METATDATA_DIR, AVAILABILITY_ZONE_FILE, StringUtils.unicodeEscape(zoneName)});
23562364
vmData.add(new String[]{METATDATA_DIR, LOCAL_HOSTNAME_FILE, StringUtils.unicodeEscape(vmName)});
2357-
vmData.add(new String[]{METATDATA_DIR, INSTANCE_ID_FILE, vmName});
2358-
vmData.add(new String[]{METATDATA_DIR, VM_ID_FILE, String.valueOf(vmId)});
2365+
vmData.add(new String[]{METATDATA_DIR, LOCAL_IPV4_FILE, guestIpAddress});
2366+
2367+
String publicIpAddress = guestIpAddress;
2368+
String publicHostName = StringUtils.unicodeEscape(vmName);
2369+
2370+
if (dcVo.getNetworkType() != DataCenter.NetworkType.Basic) {
2371+
if (publicIp != null) {
2372+
publicIpAddress = publicIp.getAddress().addr();
2373+
publicHostName = publicIp.getAddress().addr();
2374+
} else {
2375+
publicHostName = null;
2376+
}
2377+
}
2378+
vmData.add(new String[]{METATDATA_DIR, PUBLIC_IPV4_FILE, publicIpAddress});
2379+
vmData.add(new String[]{METATDATA_DIR, PUBLIC_HOSTNAME_FILE, publicHostName});
2380+
2381+
if (vmUuid == null) {
2382+
vmData.add(new String[]{METATDATA_DIR, INSTANCE_ID_FILE, vmName});
2383+
vmData.add(new String[]{METATDATA_DIR, VM_ID_FILE, String.valueOf(vmId)});
2384+
} else {
2385+
vmData.add(new String[]{METATDATA_DIR, INSTANCE_ID_FILE, vmUuid});
2386+
vmData.add(new String[]{METATDATA_DIR, VM_ID_FILE, vmUuid});
2387+
}
2388+
23592389
vmData.add(new String[]{METATDATA_DIR, PUBLIC_KEYS_FILE, publicKey});
23602390

23612391
String cloudIdentifier = _configDao.getValue("cloud.identifier");

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

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -206,30 +206,37 @@ public boolean canEnableIndividualServices() {
206206
return false;
207207
}
208208

209+
private String getSshKey(VirtualMachineProfile profile) {
210+
UserVmDetailVO vmDetailSshKey = _userVmDetailsDao.findDetail(profile.getId(), "SSH.PublicKey");
211+
return (vmDetailSshKey!=null ? vmDetailSshKey.getValue() : null);
212+
}
213+
209214
@Override
210215
public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context)
211216
throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
212-
UserVmDetailVO vmDetailSshKey = _userVmDetailsDao.findDetail(profile.getId(), "SSH.PublicKey");
213-
return (canHandle(network.getTrafficType()) && updateConfigDrive(profile,
214-
(vmDetailSshKey!=null?vmDetailSshKey.getValue():null)))
217+
String sshPublicKey = getSshKey(profile);
218+
return (canHandle(network.getTrafficType())
219+
&& updateConfigDrive(profile, sshPublicKey, nic))
215220
&& updateConfigDriveIso(network, profile, dest.getHost(), false);
216221
}
217222

218223
@Override
219224
public boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile profile) throws ResourceUnavailableException {
220-
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(profile, (String) profile.getParameter(VirtualMachineProfile.Param.VmSshPubKey)))) return false;
225+
String sshPublicKey = getSshKey(profile);
226+
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(profile, sshPublicKey, nic))) return false;
221227
return updateConfigDriveIso(network, profile, true);
222228
}
223229

224230
@Override
225231
public boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile vm, String sshPublicKey) throws ResourceUnavailableException {
226-
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(vm, sshPublicKey))) return false;
232+
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(vm, sshPublicKey, nic))) return false;
227233
return updateConfigDriveIso(network, vm, true);
228234
}
229235

230236
@Override
231237
public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile profile) throws ResourceUnavailableException {
232-
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(profile, (String) profile.getParameter(VirtualMachineProfile.Param.VmSshPubKey)))) return false;
238+
String sshPublicKey = getSshKey(profile);
239+
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(profile, sshPublicKey, nic))) return false;
233240
return updateConfigDriveIso(network, profile, true);
234241
}
235242

@@ -330,7 +337,7 @@ private boolean updateConfigDriveIso(Network network, VirtualMachineProfile prof
330337
Answer createIsoAnswer = endpoint.sendMessage(configDriveIsoCommand);
331338
if (!createIsoAnswer.getResult()) {
332339
throw new ResourceUnavailableException(String.format("%s ISO failed, details: %s",
333-
(update?"Update":"Create"), createIsoAnswer.getDetails()),ConfigDriveNetworkElement.class,0L);
340+
(update?"Update":"Create"), createIsoAnswer.getDetails()), ConfigDriveNetworkElement.class, 0L);
334341
}
335342
configureConfigDriveDisk(profile, secondaryStore);
336343

@@ -363,7 +370,7 @@ private void configureConfigDriveDisk(VirtualMachineProfile profile, DataStore s
363370
}
364371
}
365372

366-
private boolean updateConfigDrive(VirtualMachineProfile profile, String publicKey) {
373+
private boolean updateConfigDrive(VirtualMachineProfile profile, String publicKey, NicProfile nic) {
367374
UserVmVO vm = _userVmDao.findById(profile.getId());
368375
if (vm.getType() != VirtualMachine.Type.User) {
369376
return false;
@@ -372,11 +379,10 @@ private boolean updateConfigDrive(VirtualMachineProfile profile, String publicKe
372379
Nic defaultNic = _networkModel.getDefaultNic(vm.getId());
373380
if (defaultNic != null) {
374381
final String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText();
375-
final String zoneName = _dcDao.findById(vm.getDataCenterId()).getName();
376382
boolean isWindows = _guestOSCategoryDao.findById(_guestOSDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
377383

378-
List<String[]> vmData = _networkModel.generateVmData(vm.getUserData(), serviceOffering, zoneName, vm.getInstanceName(), vm.getId(),
379-
publicKey, (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
384+
List<String[]> vmData = _networkModel.generateVmData(vm.getUserData(), serviceOffering, vm.getDataCenterId(), vm.getInstanceName(), vm.getId(),
385+
vm.getUuid(), nic.getIPv4Address(), publicKey, (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
380386
profile.setVmData(vmData);
381387
profile.setConfigDriveLabel(VirtualMachineManager.VmConfigDriveLabel.value());
382388
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4124,11 +4124,10 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl
41244124
Network network = _networkModel.getNetwork(defaultNic.getNetworkId());
41254125
if (_networkModel.isSharedNetworkWithoutServices(network.getId())) {
41264126
final String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText();
4127-
final String zoneName = _dcDao.findById(vm.getDataCenterId()).getName();
41284127
boolean isWindows = _guestOSCategoryDao.findById(_guestOSDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
41294128

4130-
List<String[]> vmData = _networkModel.generateVmData(vm.getUserData(), serviceOffering, zoneName, vm.getInstanceName(), vm.getId(),
4131-
(String) profile.getParameter(VirtualMachineProfile.Param.VmSshPubKey), (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
4129+
List<String[]> vmData = _networkModel.generateVmData(vm.getUserData(), serviceOffering, vm.getDataCenterId(), vm.getInstanceName(), vm.getId(),
4130+
vm.getUuid(), defaultNic.getIPv4Address(), vm.getDetail("SSH.PublicKey"), (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
41324131
String vmName = vm.getInstanceName();
41334132
String configDriveIsoRootFolder = "/tmp";
41344133
String isoFile = configDriveIsoRootFolder + "/" + vmName + "/configDrive/" + vmName + ".iso";

server/test/com/cloud/network/MockNetworkModelImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,7 @@ public boolean getNetworkEgressDefaultPolicy(Long networkId) {
898898
}
899899

900900
@Override
901-
public List<String[]> generateVmData(String userData, String serviceOffering, String zoneName, String vmName, long vmId, String publicKey, String password, Boolean isWindows) {
901+
public List<String[]> generateVmData(String userData, String serviceOffering, long datacenterId, String vmName, long vmId, String vmUuid, String guestIpAddress, String publicKey, String password, Boolean isWindows) {
902902
return null;
903903
}
904904

0 commit comments

Comments
 (0)