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
This commit is contained in:
Frank Maximus 2018-04-26 15:10:23 +02:00 committed by Rafael Weingärtner
parent b6d420bec3
commit 85203248a4
14 changed files with 987 additions and 1034 deletions

View File

@ -59,6 +59,9 @@ public interface NetworkModel {
String SERVICE_OFFERING_FILE = "service-offering";
String AVAILABILITY_ZONE_FILE = "availability-zone";
String LOCAL_HOSTNAME_FILE = "local-hostname";
String LOCAL_IPV4_FILE = "local-ipv4";
String PUBLIC_HOSTNAME_FILE = "public-hostname";
String PUBLIC_IPV4_FILE = "public-ipv4";
String INSTANCE_ID_FILE = "instance-id";
String VM_ID_FILE = "vm-id";
String PUBLIC_KEYS_FILE = "public-keys";
@ -309,8 +312,8 @@ public interface NetworkModel {
boolean getNetworkEgressDefaultPolicy(Long networkId);
List<String[]> generateVmData(String userData, String serviceOffering, String zoneName,
String vmName, long vmId, String publicKey, String password, Boolean isWindows);
List<String[]> generateVmData(String userData, String serviceOffering, long datacenterId,
String vmName, long vmId, String vmUuid, String guestIpAddress, String publicKey, String password, Boolean isWindows);
String getValidNetworkCidr(Network guestNetwork);

View File

@ -2518,16 +2518,15 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
if (defaultNic != null) {
UserVmVO userVm = _userVmDao.findById(vm.getId());
Map<String, String> details = _vmDetailsDao.listDetailsKeyPairs(vm.getId());
vm.setDetails(details);
userVm.setDetails(details);
Network network = _networkModel.getNetwork(defaultNic.getNetworkId());
if (_networkModel.isSharedNetworkWithoutServices(network.getId())) {
final String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText();
final String zoneName = _dcDao.findById(vm.getDataCenterId()).getName();
boolean isWindows = _guestOSCategoryDao.findById(_guestOSDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
vmData = _networkModel.generateVmData(userVm.getUserData(), serviceOffering, zoneName, vm.getInstanceName(), vm.getId(),
(String) profile.getParameter(VirtualMachineProfile.Param.VmSshPubKey), (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
vmData = _networkModel.generateVmData(userVm.getUserData(), serviceOffering, vm.getDataCenterId(), vm.getInstanceName(), vm.getId(),
vm.getUuid(), defaultNic.getMacAddress(), userVm.getDetail("SSH.PublicKey"), (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
String vmName = vm.getInstanceName();
String configDriveIsoRootFolder = "/tmp";
String isoFile = configDriveIsoRootFolder + "/" + vmName + "/configDrive/" + vmName + ".iso";

View File

@ -22,6 +22,7 @@ import java.security.InvalidParameterException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -29,24 +30,24 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Collections;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
import com.cloud.api.ApiDBUtils;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
@ -2344,18 +2345,47 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
}
@Override
public List<String[]> generateVmData(String userData, String serviceOffering, String zoneName,
String vmName, long vmId, String publicKey, String password, Boolean isWindows) {
public List<String[]> generateVmData(String userData, String serviceOffering, long datacenterId,
String vmName, long vmId, String vmUuid,
String guestIpAddress, String publicKey, String password, Boolean isWindows) {
DataCenterVO dcVo = _dcDao.findById(datacenterId);
final String zoneName = dcVo.getName();
IPAddressVO publicIp = _ipAddressDao.findByAssociatedVmId(vmId);
final List<String[]> vmData = new ArrayList<String[]>();
if (userData != null) {
vmData.add(new String[]{USERDATA_DIR, USERDATA_FILE, new String(Base64.decodeBase64(userData),StringUtils.getPreferredCharset())});
vmData.add(new String[]{USERDATA_DIR, USERDATA_FILE, userData});
}
vmData.add(new String[]{METATDATA_DIR, SERVICE_OFFERING_FILE, StringUtils.unicodeEscape(serviceOffering)});
vmData.add(new String[]{METATDATA_DIR, AVAILABILITY_ZONE_FILE, StringUtils.unicodeEscape(zoneName)});
vmData.add(new String[]{METATDATA_DIR, LOCAL_HOSTNAME_FILE, StringUtils.unicodeEscape(vmName)});
vmData.add(new String[]{METATDATA_DIR, INSTANCE_ID_FILE, vmName});
vmData.add(new String[]{METATDATA_DIR, VM_ID_FILE, String.valueOf(vmId)});
vmData.add(new String[]{METATDATA_DIR, LOCAL_IPV4_FILE, guestIpAddress});
String publicIpAddress = guestIpAddress;
String publicHostName = StringUtils.unicodeEscape(vmName);
if (dcVo.getNetworkType() != DataCenter.NetworkType.Basic) {
if (publicIp != null) {
publicIpAddress = publicIp.getAddress().addr();
publicHostName = publicIp.getAddress().addr();
} else {
publicHostName = null;
}
}
vmData.add(new String[]{METATDATA_DIR, PUBLIC_IPV4_FILE, publicIpAddress});
vmData.add(new String[]{METATDATA_DIR, PUBLIC_HOSTNAME_FILE, publicHostName});
if (vmUuid == null) {
vmData.add(new String[]{METATDATA_DIR, INSTANCE_ID_FILE, vmName});
vmData.add(new String[]{METATDATA_DIR, VM_ID_FILE, String.valueOf(vmId)});
} else {
vmData.add(new String[]{METATDATA_DIR, INSTANCE_ID_FILE, vmUuid});
vmData.add(new String[]{METATDATA_DIR, VM_ID_FILE, vmUuid});
}
vmData.add(new String[]{METATDATA_DIR, PUBLIC_KEYS_FILE, publicKey});
String cloudIdentifier = _configDao.getValue("cloud.identifier");

View File

@ -206,30 +206,37 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle
return false;
}
private String getSshKey(VirtualMachineProfile profile) {
UserVmDetailVO vmDetailSshKey = _userVmDetailsDao.findDetail(profile.getId(), "SSH.PublicKey");
return (vmDetailSshKey!=null ? vmDetailSshKey.getValue() : null);
}
@Override
public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
UserVmDetailVO vmDetailSshKey = _userVmDetailsDao.findDetail(profile.getId(), "SSH.PublicKey");
return (canHandle(network.getTrafficType()) && updateConfigDrive(profile,
(vmDetailSshKey!=null?vmDetailSshKey.getValue():null)))
String sshPublicKey = getSshKey(profile);
return (canHandle(network.getTrafficType())
&& updateConfigDrive(profile, sshPublicKey, nic))
&& updateConfigDriveIso(network, profile, dest.getHost(), false);
}
@Override
public boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile profile) throws ResourceUnavailableException {
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(profile, (String) profile.getParameter(VirtualMachineProfile.Param.VmSshPubKey)))) return false;
String sshPublicKey = getSshKey(profile);
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(profile, sshPublicKey, nic))) return false;
return updateConfigDriveIso(network, profile, true);
}
@Override
public boolean saveSSHKey(Network network, NicProfile nic, VirtualMachineProfile vm, String sshPublicKey) throws ResourceUnavailableException {
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(vm, sshPublicKey))) return false;
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(vm, sshPublicKey, nic))) return false;
return updateConfigDriveIso(network, vm, true);
}
@Override
public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile profile) throws ResourceUnavailableException {
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(profile, (String) profile.getParameter(VirtualMachineProfile.Param.VmSshPubKey)))) return false;
String sshPublicKey = getSshKey(profile);
if (!(canHandle(network.getTrafficType()) && updateConfigDrive(profile, sshPublicKey, nic))) return false;
return updateConfigDriveIso(network, profile, true);
}
@ -330,7 +337,7 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle
Answer createIsoAnswer = endpoint.sendMessage(configDriveIsoCommand);
if (!createIsoAnswer.getResult()) {
throw new ResourceUnavailableException(String.format("%s ISO failed, details: %s",
(update?"Update":"Create"), createIsoAnswer.getDetails()),ConfigDriveNetworkElement.class,0L);
(update?"Update":"Create"), createIsoAnswer.getDetails()), ConfigDriveNetworkElement.class, 0L);
}
configureConfigDriveDisk(profile, secondaryStore);
@ -363,7 +370,7 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle
}
}
private boolean updateConfigDrive(VirtualMachineProfile profile, String publicKey) {
private boolean updateConfigDrive(VirtualMachineProfile profile, String publicKey, NicProfile nic) {
UserVmVO vm = _userVmDao.findById(profile.getId());
if (vm.getType() != VirtualMachine.Type.User) {
return false;
@ -372,11 +379,10 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle
Nic defaultNic = _networkModel.getDefaultNic(vm.getId());
if (defaultNic != null) {
final String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText();
final String zoneName = _dcDao.findById(vm.getDataCenterId()).getName();
boolean isWindows = _guestOSCategoryDao.findById(_guestOSDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
List<String[]> vmData = _networkModel.generateVmData(vm.getUserData(), serviceOffering, zoneName, vm.getInstanceName(), vm.getId(),
publicKey, (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
List<String[]> vmData = _networkModel.generateVmData(vm.getUserData(), serviceOffering, vm.getDataCenterId(), vm.getInstanceName(), vm.getId(),
vm.getUuid(), nic.getIPv4Address(), publicKey, (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
profile.setVmData(vmData);
profile.setConfigDriveLabel(VirtualMachineManager.VmConfigDriveLabel.value());
}

View File

@ -4124,11 +4124,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
Network network = _networkModel.getNetwork(defaultNic.getNetworkId());
if (_networkModel.isSharedNetworkWithoutServices(network.getId())) {
final String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText();
final String zoneName = _dcDao.findById(vm.getDataCenterId()).getName();
boolean isWindows = _guestOSCategoryDao.findById(_guestOSDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
List<String[]> vmData = _networkModel.generateVmData(vm.getUserData(), serviceOffering, zoneName, vm.getInstanceName(), vm.getId(),
(String) profile.getParameter(VirtualMachineProfile.Param.VmSshPubKey), (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
List<String[]> vmData = _networkModel.generateVmData(vm.getUserData(), serviceOffering, vm.getDataCenterId(), vm.getInstanceName(), vm.getId(),
vm.getUuid(), defaultNic.getIPv4Address(), vm.getDetail("SSH.PublicKey"), (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword), isWindows);
String vmName = vm.getInstanceName();
String configDriveIsoRootFolder = "/tmp";
String isoFile = configDriveIsoRootFolder + "/" + vmName + "/configDrive/" + vmName + ".iso";

View File

@ -898,7 +898,7 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel {
}
@Override
public List<String[]> generateVmData(String userData, String serviceOffering, String zoneName, String vmName, long vmId, String publicKey, String password, Boolean isWindows) {
public List<String[]> generateVmData(String userData, String serviceOffering, long datacenterId, String vmName, long vmId, String vmUuid, String guestIpAddress, String publicKey, String password, Boolean isWindows) {
return null;
}

View File

@ -36,7 +36,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.xerces.impl.dv.util.Base64;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
@ -64,6 +63,8 @@ import com.cloud.host.dao.HostDao;
import com.cloud.network.Network;
import com.cloud.network.NetworkModelImpl;
import com.cloud.network.Networks;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkServiceMapDao;
import com.cloud.network.dao.NetworkVO;
@ -77,6 +78,7 @@ import com.cloud.storage.dao.GuestOSDao;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateListener;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.utils.net.Ip;
import com.cloud.vm.Nic;
import com.cloud.vm.NicProfile;
import com.cloud.vm.UserVmDetailVO;
@ -99,7 +101,7 @@ public class ConfigDriveNetworkElementTest {
private final String VMINSTANCENAME = "vm_name";
private final String VMOFFERING = "custom_instance";
private final long VMID = 30L;
private final String VMUSERDATA = "userdata";
private final String VMUSERDATA = "H4sIABCvw1oAAystTi1KSSxJ5AIAUPllwQkAAAA=";
private final long SOID = 31L;
private final long HOSTID = NETWORK_ID;
private final String HOSTNAME = "host1";
@ -116,6 +118,7 @@ public class ConfigDriveNetworkElementTest {
@Mock private UserVmDetailsDao _userVmDetailsDao;
@Mock private NetworkDao _networkDao;
@Mock private NetworkServiceMapDao _ntwkSrvcDao;
@Mock private IPAddressDao _ipAddressDao;
@Mock private DataCenterVO dataCenterVO;
@Mock private DataStore dataStore;
@ -130,6 +133,7 @@ public class ConfigDriveNetworkElementTest {
@Mock private NicProfile nicp;
@Mock private ServiceOfferingVO serviceOfferingVO;
@Mock private UserVmVO virtualMachine;
@Mock private IPAddressVO publicIp;
@InjectMocks private final ConfigDriveNetworkElement _configDrivesNetworkElement = new ConfigDriveNetworkElement();
@InjectMocks @Spy private NetworkModelImpl _networkModel = new NetworkModelImpl();
@ -161,7 +165,7 @@ public class ConfigDriveNetworkElementTest {
when(virtualMachine.getServiceOfferingId()).thenReturn(SOID);
when(virtualMachine.getDataCenterId()).thenReturn(DATACENTERID);
when(virtualMachine.getInstanceName()).thenReturn(VMINSTANCENAME);
when(virtualMachine.getUserData()).thenReturn(Base64.encode(VMUSERDATA.getBytes()));
when(virtualMachine.getUserData()).thenReturn(VMUSERDATA);
when(deployDestination.getHost()).thenReturn(hostVO);
when(hostVO.getId()).thenReturn(HOSTID);
when(nic.isDefaultNic()).thenReturn(true);
@ -236,6 +240,71 @@ public class ConfigDriveNetworkElementTest {
@Test
public void testAddPasswordAndUserdata() throws InsufficientCapacityException, ResourceUnavailableException {
List<String[]> actualVmData = getVmData();
assertThat(actualVmData, containsInAnyOrder(
new String[]{"userdata", "user_data", VMUSERDATA},
new String[]{"metadata", "service-offering", VMOFFERING},
new String[]{"metadata", "availability-zone", ZONENAME},
new String[]{"metadata", "local-hostname", VMINSTANCENAME},
new String[]{"metadata", "local-ipv4", "192.168.111.111"},
new String[]{"metadata", "public-hostname", null},
new String[]{"metadata", "public-ipv4", "192.168.111.111"},
new String[]{"metadata", "vm-id", String.valueOf(VMID)},
new String[]{"metadata", "instance-id", VMINSTANCENAME},
new String[]{"metadata", "public-keys", PUBLIC_KEY},
new String[]{"metadata", "cloud-identifier", String.format("CloudStack-{%s}", CLOUD_ID)},
new String[]{PASSWORD, "vm_password", PASSWORD}
));
}
@Test
public void testAddPasswordAndUserdataStaticNat() throws InsufficientCapacityException, ResourceUnavailableException {
when(_ipAddressDao.findByAssociatedVmId(VMID)).thenReturn(publicIp);
when(publicIp.getAddress()).thenReturn(new Ip("7.7.7.7"));
List<String[]> actualVmData = getVmData();
assertThat(actualVmData, containsInAnyOrder(
new String[]{"userdata", "user_data", VMUSERDATA},
new String[]{"metadata", "service-offering", VMOFFERING},
new String[]{"metadata", "availability-zone", ZONENAME},
new String[]{"metadata", "local-hostname", VMINSTANCENAME},
new String[]{"metadata", "local-ipv4", "192.168.111.111"},
new String[]{"metadata", "public-hostname", "7.7.7.7"},
new String[]{"metadata", "public-ipv4", "7.7.7.7"},
new String[]{"metadata", "vm-id", String.valueOf(VMID)},
new String[]{"metadata", "instance-id", VMINSTANCENAME},
new String[]{"metadata", "public-keys", PUBLIC_KEY},
new String[]{"metadata", "cloud-identifier", String.format("CloudStack-{%s}", CLOUD_ID)},
new String[]{PASSWORD, "vm_password", PASSWORD}
));
}
@Test
public void testAddPasswordAndUserdataUuid() throws InsufficientCapacityException, ResourceUnavailableException {
when(virtualMachine.getUuid()).thenReturn("vm-uuid");
List<String[]> actualVmData = getVmData();
assertThat(actualVmData, containsInAnyOrder(
new String[]{"userdata", "user_data", VMUSERDATA},
new String[]{"metadata", "service-offering", VMOFFERING},
new String[]{"metadata", "availability-zone", ZONENAME},
new String[]{"metadata", "local-hostname", VMINSTANCENAME},
new String[]{"metadata", "local-ipv4", "192.168.111.111"},
new String[]{"metadata", "public-hostname", null},
new String[]{"metadata", "public-ipv4", "192.168.111.111"},
new String[]{"metadata", "vm-id", "vm-uuid"},
new String[]{"metadata", "instance-id", "vm-uuid"},
new String[]{"metadata", "public-keys", PUBLIC_KEY},
new String[]{"metadata", "cloud-identifier", String.format("CloudStack-{%s}", CLOUD_ID)},
new String[]{PASSWORD, "vm_password", PASSWORD}
));
}
private List<String[]> getVmData() throws InsufficientCapacityException, ResourceUnavailableException {
final Answer answer = mock(Answer.class);
final UserVmDetailVO userVmDetailVO = mock(UserVmDetailVO.class);
when(endpoint.sendMessage(any(HandleConfigDriveIsoCommand.class))).thenReturn(answer);
@ -243,6 +312,7 @@ public class ConfigDriveNetworkElementTest {
when(network.getTrafficType()).thenReturn(Networks.TrafficType.Guest);
when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Stopped);
when(userVmDetailVO.getValue()).thenReturn(PUBLIC_KEY);
when(nicp.getIPv4Address()).thenReturn("192.168.111.111");
when(_userVmDetailsDao.findDetail(anyLong(), anyString())).thenReturn(userVmDetailVO);
Map<VirtualMachineProfile.Param, Object> parms = Maps.newHashMap();
parms.put(VirtualMachineProfile.Param.VmPassword, PASSWORD);
@ -254,19 +324,6 @@ public class ConfigDriveNetworkElementTest {
ArgumentCaptor<HandleConfigDriveIsoCommand> commandCaptor = ArgumentCaptor.forClass(HandleConfigDriveIsoCommand.class);
verify(endpoint, times(1)).sendMessage(commandCaptor.capture());
HandleConfigDriveIsoCommand result = commandCaptor.getValue();
List<String[]> actualVmData = result.getVmData();
assertThat(actualVmData, containsInAnyOrder(
new String[]{"userdata", "user_data", VMUSERDATA},
new String[]{"metadata", "service-offering", VMOFFERING},
new String[]{"metadata", "availability-zone", ZONENAME},
new String[]{"metadata", "local-hostname", VMINSTANCENAME},
new String[]{"metadata", "vm-id", String.valueOf(VMID)},
new String[]{"metadata", "instance-id", String.valueOf(VMINSTANCENAME)},
new String[]{"metadata", "public-keys", PUBLIC_KEY},
new String[]{"metadata", "cloud-identifier", String.format("CloudStack-{%s}", CLOUD_ID)},
new String[]{PASSWORD, "vm_password", PASSWORD}
));
return result.getVmData();
}
}

View File

@ -913,7 +913,7 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel {
}
@Override
public List<String[]> generateVmData(String userData, String serviceOffering, String zoneName, String vmName, long vmId, String publicKey, String password, Boolean isWindows) {
public List<String[]> generateVmData(String userData, String serviceOffering, long datacenterId, String vmName, long vmId, String vmUuid, String guestIpAddress, String publicKey, String password, Boolean isWindows) {
return null;
}

View File

@ -40,6 +40,7 @@ import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URI;
@ -52,6 +53,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.naming.ConfigurationException;
import io.netty.bootstrap.ServerBootstrap;
@ -68,6 +70,7 @@ import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
@ -155,11 +158,11 @@ import com.cloud.agent.api.to.DatadiskTO;
import com.cloud.agent.api.to.NfsTO;
import com.cloud.agent.api.to.S3TO;
import com.cloud.agent.api.to.SwiftTO;
import com.cloud.configuration.Resource;
import com.cloud.exception.InternalErrorException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.configuration.Resource;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.NetworkModel;
import com.cloud.resource.ServerResourceBase;
@ -190,9 +193,6 @@ import com.cloud.utils.script.Script;
import com.cloud.utils.storage.S3.S3Utils;
import com.cloud.vm.SecondaryStorageVm;
import java.io.OutputStreamWriter;
public class NfsSecondaryStorageResource extends ServerResourceBase implements SecondaryStorageResource {
public static final Logger s_logger = Logger.getLogger(NfsSecondaryStorageResource.class);
@ -491,8 +491,13 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
if (typeFolder.exists() || typeFolder.mkdirs()) {
if (StringUtils.isNotEmpty(content)) {
File file = new File(typeFolder, fileName + ".txt");
try (FileWriter fw = new FileWriter(file); BufferedWriter bw = new BufferedWriter(fw)) {
bw.write(content);
try {
if (fileName.equals(USERDATA_FILE)) {
// User Data is passed as a base64 encoded string
FileUtils.writeByteArrayToFile(file, Base64.decodeBase64(content));
} else {
FileUtils.write(file, content, com.cloud.utils.StringUtils.getPreferredCharset());
}
} catch (IOException ex) {
s_logger.error("Failed to create file ", ex);
return new Answer(cmd, ex);

File diff suppressed because it is too large Load Diff

View File

@ -733,8 +733,12 @@ class nuageTestCase(cloudstackTestCase):
traffictype=traffic_type
)
# ssh_into_VM - Gets into the shell of the given VM using its public IP
def ssh_into_VM(self, vm, public_ip, reconnect=True, negative_test=False):
def ssh_into_VM(self, vm, public_ip, reconnect=True, negative_test=False, keypair=None):
"""Creates a SSH connection to the VM
:returns: the SSH connection
:rtype: marvin.sshClient.SshClient
"""
if self.isSimulator:
self.debug("Simulator Environment: Skipping ssh into VM")
return
@ -748,7 +752,8 @@ class nuageTestCase(cloudstackTestCase):
ssh_client = vm.get_ssh_client(
ipaddress=public_ip.ipaddress.ipaddress,
reconnect=reconnect,
retries=3 if negative_test else 30
retries=3 if negative_test else 30,
keyPairFileLocation=keypair.private_key_file if keypair else None
)
self.debug("Successful to SSH into VM with ID - %s on "
"public IP address - %s" %

View File

@ -0,0 +1,47 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from marvin.cloudstackAPI import createSSHKeyPair, deleteSSHKeyPair
class MySSHKeyPair:
"""Manage SSH Key pairs"""
def __init__(self, items):
self.__dict__.update(items)
@classmethod
def create(cls, apiclient, name=None, account=None,
domainid=None, projectid=None):
"""Creates SSH keypair"""
cmd = createSSHKeyPair.createSSHKeyPairCmd()
cmd.name = name
if account is not None:
cmd.account = account
if domainid is not None:
cmd.domainid = domainid
if projectid is not None:
cmd.projectid = projectid
return MySSHKeyPair(apiclient.createSSHKeyPair(cmd).__dict__)
def delete(self, apiclient):
"""Delete SSH key pair"""
cmd = deleteSSHKeyPair.deleteSSHKeyPairCmd()
cmd.name = self.name
cmd.account = self.account
cmd.domainid = self.domainid
apiclient.deleteSSHKeyPair(cmd)

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,12 @@ class jsonLoader(object):
else:
return None
def __getitem__(self, val):
if val in self.__dict__:
return self.__dict__[val]
else:
return None
def __repr__(self):
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v)
in self.__dict__.iteritems()))