mirror of https://github.com/apache/cloudstack.git
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:
parent
b6d420bec3
commit
85203248a4
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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" %
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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()))
|
||||
|
|
|
|||
Loading…
Reference in New Issue