Skip to content

Commit cf0f1fe

Browse files
configdrive: fix some failures in tests/component/test_configdrive.py (apache#5144)
* server: fix failed to apply userdata when enable static nat * server: fix cannot expunge vm as applyUserdata fails * configdrive: fix ISO is not recognized when plug a new nic * configdrive: detach and attach configdrive ISO as it is changed when plug a new nic or migrate vm * configdrive test: (1) password file does not exists in recreated ISO; (2) vm hostname should be changed after migration * configdrive: use centos55 template with sshkey and configdrive support * configdrive: disklabel is 'config-2' for configdrive ISO * configdrive: use copy for configdrive ISO and move for other template/volume/iso * configdrive: use public-keys.txt * configdrive test: fix (1) update_template ; (2) ssh into vm by keypair
1 parent 0406e27 commit cf0f1fe

7 files changed

Lines changed: 85 additions & 23 deletions

File tree

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
303303
protected String _agentHooksVmOnStopScript = "libvirt-vm-state-change.groovy";
304304
protected String _agentHooksVmOnStopMethod = "onStop";
305305

306+
private static final String CONFIG_DRIVE_ISO_DISK_LABEL = "hdd";
307+
private static final int CONFIG_DRIVE_ISO_DEVICE_ID = 4;
306308

307309
protected File _qemuSocketsPath;
308310
private final String _qemuGuestAgentSocketName = "org.qemu.guest_agent.0";
@@ -2756,6 +2758,32 @@ protected KVMStoragePoolManager getPoolManager() {
27562758
return _storagePoolMgr;
27572759
}
27582760

2761+
public void detachAndAttachConfigDriveISO(final Connect conn, final String vmName) {
2762+
// detach and re-attach configdrive ISO
2763+
List<DiskDef> disks = getDisks(conn, vmName);
2764+
DiskDef configdrive = null;
2765+
for (DiskDef disk : disks) {
2766+
if (disk.getDeviceType() == DiskDef.DeviceType.CDROM && disk.getDiskLabel() == CONFIG_DRIVE_ISO_DISK_LABEL) {
2767+
configdrive = disk;
2768+
}
2769+
}
2770+
if (configdrive != null) {
2771+
try {
2772+
String result = attachOrDetachISO(conn, vmName, configdrive.getDiskPath(), false, CONFIG_DRIVE_ISO_DEVICE_ID);
2773+
if (result != null) {
2774+
s_logger.warn("Detach ConfigDrive ISO with result: " + result);
2775+
}
2776+
result = attachOrDetachISO(conn, vmName, configdrive.getDiskPath(), true, CONFIG_DRIVE_ISO_DEVICE_ID);
2777+
if (result != null) {
2778+
s_logger.warn("Attach ConfigDrive ISO with result: " + result);
2779+
}
2780+
} catch (final LibvirtException | InternalErrorException | URISyntaxException e) {
2781+
final String msg = "Detach and attach ConfigDrive ISO failed due to " + e.toString();
2782+
s_logger.warn(msg, e);
2783+
}
2784+
}
2785+
}
2786+
27592787
public synchronized String attachOrDetachISO(final Connect conn, final String vmName, String isoPath, final boolean isAttach, final Integer diskSeq) throws LibvirtException, URISyntaxException,
27602788
InternalErrorException {
27612789
final DiskDef iso = new DiskDef();

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
import com.cloud.resource.ResourceWrapper;
7777
import com.cloud.utils.Ternary;
7878
import com.cloud.utils.exception.CloudRuntimeException;
79+
import com.cloud.vm.VirtualMachine;
7980
import com.google.common.base.Strings;
8081

8182
@ResourceWrapper(handles = MigrateCommand.class)
@@ -180,6 +181,10 @@ Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0.
180181

181182
dconn = libvirtUtilitiesHelper.retrieveQemuConnection(destinationUri);
182183

184+
if (to.getType() == VirtualMachine.Type.User) {
185+
libvirtComputingResource.detachAndAttachConfigDriveISO(conn, vmName);
186+
}
187+
183188
//run migration in thread so we can monitor it
184189
s_logger.info("Live migration of instance " + vmName + " initiated to destination host: " + dconn.getURI());
185190
final ExecutorService executor = Executors.newFixedThreadPool(1);

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtPlugNicCommandWrapper.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ public Answer execute(final PlugNicCommand command, final LibvirtComputingResour
7272
libvirtComputingResource.applyDefaultNetworkRulesOnNic(conn, vmName, vmId, nic, false, false);
7373
}
7474

75+
if (vmType == VirtualMachine.Type.User) {
76+
libvirtComputingResource.detachAndAttachConfigDriveISO(conn, vmName);
77+
}
78+
7579
return new PlugNicAnswer(command, true, "success");
7680
} catch (final LibvirtException e) {
7781
final String msg = " Plug Nic failed due to " + e.toString();

scripts/storage/secondary/createvolume.sh

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,16 @@ create_from_file() {
139139

140140
}
141141

142+
copy_from_file() {
143+
local tmpltfs=$1
144+
local tmpltimg=$2
145+
local tmpltname=$3
146+
147+
[ -n "$verbose" ] && echo "Copying to $tmpltfs/$tmpltname...could take a while" >&2
148+
cp -rf $tmpltimg /$tmpltfs/$tmpltname
149+
rm -rf $tmpltimg
150+
}
151+
142152
tflag=
143153
nflag=
144154
fflag=
@@ -228,7 +238,11 @@ fi
228238

229239
imgsize=$(ls -l $tmpltimg2| awk -F" " '{print $5}')
230240

231-
create_from_file $tmpltfs $tmpltimg2 $tmpltname
241+
if [ "$descr" = "configDrive" ] && [ "$Sflag" = "" ];then
242+
copy_from_file $tmpltfs $tmpltimg2 $tmpltname
243+
else
244+
create_from_file $tmpltfs $tmpltimg2 $tmpltname
245+
fi
232246

233247
touch /$tmpltfs/volume.properties
234248
rollback_if_needed $tmpltfs $? "Failed to create volume.properties file"

server/src/main/java/com/cloud/network/rules/RulesManagerImpl.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -630,20 +630,23 @@ private boolean enableStaticNat(long ipId, long vmId, long networkId, boolean is
630630
}
631631

632632
protected void applyUserData(long vmId, Network network, Nic guestNic) throws ResourceUnavailableException {
633-
UserVmVO vm = _vmDao.findById(vmId);
634-
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
635-
NicProfile nicProfile = new NicProfile(guestNic, network, null, null, null,
636-
_networkModel.isSecurityGroupSupportedInNetwork(network),
637-
_networkModel.getNetworkTag(template.getHypervisorType(), network));
638-
VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vm);
639633
UserDataServiceProvider element = _networkModel.getUserDataUpdateProvider(network);
640634
if (element == null) {
641635
s_logger.error("Can't find network element for " + Service.UserData.getName() + " provider needed for UserData update");
642636
} else {
643-
boolean result = element.saveUserData(network, nicProfile, vmProfile);
644-
if (!result) {
637+
UserVmVO vm = _vmDao.findById(vmId);
638+
try {
639+
VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId());
640+
NicProfile nicProfile = new NicProfile(guestNic, network, null, null, null,
641+
_networkModel.isSecurityGroupSupportedInNetwork(network),
642+
_networkModel.getNetworkTag(template.getHypervisorType(), network));
643+
VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vm);
644+
if (!element.saveUserData(network, nicProfile, vmProfile)) {
645645
s_logger.error("Failed to update userdata for vm " + vm + " and nic " + guestNic);
646646
}
647+
} catch (Exception e) {
648+
s_logger.error("Failed to update userdata for vm " + vm + " and nic " + guestNic + " due to " + e.getMessage(), e);
649+
}
647650
}
648651
}
649652

setup/bindir/cloud-set-guest-sshkey-configdrive.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ mountdir=$(mktemp -d)
3131
# If lable name is other than config, please change the below line as required
3232
DefaultDisk=/dev/disk/by-label/config-2
3333

34-
SSHKey_File=$mountdir/cloudstack/metadata/public_keys.txt
34+
SSHKey_File=$mountdir/cloudstack/metadata/public-keys.txt
3535
keys_received=0
3636

3737
function prepare_mount
@@ -44,7 +44,7 @@ function prepare_mount
4444
if [ -e $DefaultDisk ]; then
4545
Disk=$DefaultDisk
4646
else
47-
BLOCK_DEVICE=$(blkid -t LABEL='config' /dev/hd? /dev/sd? /dev/xvd? /dev/vd? -o device)
47+
BLOCK_DEVICE=$(blkid -t LABEL='config-2' /dev/hd? /dev/sd? /dev/xvd? /dev/vd? -o device)
4848
if [ -n $BLOCK_DEVICE ]; then
4949
Disk=$BLOCK_DEVICE
5050
else

test/integration/component/test_configdrive.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
Hypervisor, Template)
5454
from marvin.lib.common import (get_domain,
5555
get_template,
56-
get_zone, get_test_template,
56+
get_zone,
57+
get_test_template,
5758
is_config_suitable)
5859
from marvin.lib.utils import random_gen
5960
# Import System Modules
@@ -104,12 +105,12 @@ def __init__(self):
104105
self.services = {
105106
"test_templates": {
106107
"kvm": {
107-
"name": "Centos-5.5-configdrive",
108-
"displaytext": "ConfigDrive enabled CentOS",
108+
"name": "Centos-5.5-sshkey-and-configdrive",
109+
"displaytext": "SSHkey and ConfigDrive enabled CentOS",
109110
"format": "qcow2",
110111
"hypervisor": "kvm",
111112
"ostype": "CentOS 5.5 (64-bit)",
112-
"url": "http://people.apache.org/~fmaximus/centos55-extended.qcow2.bz2",
113+
"url": "http://people.apache.org/~weizhou/centos55-sshkey-configdrive.qcow2.bz2",
113114
"requireshvm": "False",
114115
"ispublic": "True",
115116
"isextractable": "True"
@@ -653,8 +654,7 @@ def given_template_password_enabled_is(self, new_state):
653654
orig_state = self.template.passwordenabled
654655
self.debug("Updating guest VM template to password enabled "
655656
"from %s to %s" % (orig_state, new_state))
656-
if orig_state != new_state:
657-
self.update_template(passwordenabled=new_state)
657+
self.update_template(passwordenabled=new_state)
658658
self.assertEqual(self.template.passwordenabled, new_state,
659659
"Guest VM template is not password enabled")
660660
return orig_state
@@ -850,7 +850,7 @@ def then_config_drive_is_as_expected(self, vm,
850850

851851
self.debug("SSHing into the VM %s" % vm.name)
852852

853-
ssh = self.ssh_into_VM(vm, public_ip, reconnect=reconnect)
853+
ssh = self.ssh_into_VM(vm, public_ip, reconnect=reconnect, keypair=vm.key_pair)
854854

855855
d = {x.name: x for x in ssh.logger.handlers}
856856
ssh.logger.handlers = list(d.values())
@@ -974,6 +974,7 @@ def plug_nic(self, vm, network):
974974
vm.add_nic(self.api_client, network.id)
975975
self.debug("Added NIC in VM with ID - %s and network with ID - %s"
976976
% (vm.id, network.id))
977+
vm.password_test = ConfigDriveUtils.PasswordTest(expect_pw=False)
977978

978979
def unplug_nic(self, vm, network):
979980
nic = self._find_nic(vm, network)
@@ -1530,12 +1531,14 @@ def ssh_into_VM(self, vm, public_ip, reconnect=True,
15301531
self.debug("SSH into VM with ID - %s on public IP address - %s" %
15311532
(vm.id, public_ip.ipaddress.ipaddress))
15321533
tries = 1 if negative_test else 3
1534+
private_key_file_location = keypair.private_key_file if keypair else None
15331535

15341536
@retry(tries=tries)
15351537
def retry_ssh():
15361538
ssh_client = vm.get_ssh_client(
15371539
ipaddress=public_ip.ipaddress.ipaddress,
15381540
reconnect=reconnect,
1541+
keyPairFileLocation=private_key_file_location,
15391542
retries=3 if negative_test else 30
15401543
)
15411544
self.debug("Successful to SSH into VM with ID - %s on "
@@ -1702,6 +1705,7 @@ def migrate_VM(self, vm):
17021705
"%s to Host: %s" % (vm.id, host.id))
17031706
try:
17041707
vm.migrate(self.api_client, hostid=host.id)
1708+
vm.password_test = ConfigDriveUtils.PasswordTest(expect_pw=False)
17051709
except Exception as e:
17061710
self.fail("Failed to migrate instance, %s" % e)
17071711
self.debug("Migrated VM with ID: "
@@ -1917,7 +1921,8 @@ def test_configdrive_isolated_network(self):
19171921
# =====================================================================
19181922
self.debug("+++ Scenario: "
19191923
"update userdata and reset password after migrate")
1920-
self.migrate_VM(vm1)
1924+
host = self.migrate_VM(vm1)
1925+
vm1.hostname = host.name
19211926
self.then_config_drive_is_as_expected(vm1, public_ip_1, metadata=True)
19221927
self.debug("Updating userdata after migrating VM - %s" % vm1.name)
19231928
self.update_and_validate_userdata(vm1, "hello after migrate",
@@ -1955,7 +1960,7 @@ def test_configdrive_isolated_network(self):
19551960
# =====================================================================
19561961
self.debug("+++ Scenario: "
19571962
"Update Userdata on a VM that is not password enabled")
1958-
self.update_template(passwordenabled=False)
1963+
self.given_template_password_enabled_is(False)
19591964
vm1 = self.when_I_deploy_a_vm_with_keypair_in(network1)
19601965

19611966
public_ip_1 = \
@@ -2112,7 +2117,8 @@ def test_configdrive_vpc_network(self):
21122117
# =====================================================================
21132118
self.debug("+++ Scenario: "
21142119
"update userdata and reset password after migrate")
2115-
self.migrate_VM(vm)
2120+
host = self.migrate_VM(vm)
2121+
vm.hostname = host.name
21162122
self.then_config_drive_is_as_expected(vm, public_ip_1, metadata=True)
21172123
self.update_and_validate_userdata(vm, "hello migrate", public_ip_1)
21182124

@@ -2150,7 +2156,7 @@ def test_configdrive_vpc_network(self):
21502156
self.debug("+++ Scenario: "
21512157
"Update Userdata on a VM that is not password enabled")
21522158

2153-
self.update_template(passwordenabled=False)
2159+
self.given_template_password_enabled_is(False)
21542160

21552161
vm = self.when_I_deploy_a_vm(network1,
21562162
keypair=self.keypair.name)
@@ -2285,7 +2291,7 @@ def test_configdrive_shared_network(self):
22852291
self.delete(vm1, expunge=True)
22862292

22872293
self.given_config_drive_provider_is("Enabled")
2288-
self.update_template(passwordenabled=False)
2294+
self.given_template_password_enabled_is(False)
22892295

22902296
vm1 = self.create_VM(
22912297
[shared_network.network],
@@ -2362,6 +2368,7 @@ def test_configdrive_isolated_network_hypervisor_hostname_exposed(self):
23622368
self.debug("+++Deploy VM in the created Isolated network "
23632369
"with user data provider as configdrive")
23642370

2371+
self.given_template_password_enabled_is(True)
23652372
vm1 = self.when_I_deploy_a_vm(network1)
23662373

23672374
public_ip_1 = self.when_I_create_a_static_nat_ip_to(vm1, network1)
@@ -2476,6 +2483,7 @@ def test_configdrive_vpc_network_verify_metadata(self):
24762483
# =====================================================================
24772484
self.debug("+++ Scenario: "
24782485
"Deploy VM in the Tier 1 with user data")
2486+
self.given_template_password_enabled_is(True)
24792487
vm = self.when_I_deploy_a_vm(network1)
24802488
public_ip_1 = self.when_I_create_a_static_nat_ip_to(vm, network1)
24812489

0 commit comments

Comments
 (0)