Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace WMIC with powershell cmd #4034

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion virttest/utils_disk.py
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,7 @@ def get_disk_size_windows(session, did):
e.g. 0, 1
:return: disk size.
"""
cmd = "wmic diskdrive get size, index"
cmd = 'powershell -command "Get-CimInstance Win32_DiskDrive | Select-Object Index, Size"'
return int(re.findall(r"%s\s+(\d+)" % did, session.cmd_output(cmd))[0])


Expand Down
19 changes: 14 additions & 5 deletions virttest/utils_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2351,8 +2351,10 @@ def get_free_disk(session, mount):
:return string: freespace M-bytes
"""
if re.match(r"[a-zA-Z]:", mount):
cmd = "wmic logicaldisk where \"DeviceID='%s'\" " % mount
cmd += "get FreeSpace"
cmd = (
"powershell -command \"Get-CimInstance Win32_LogicalDisk | Where-Object {$_.DeviceID -eq '%s'}"
' | Select-Object FreeSpace"'
) % mount
output = session.cmd_output(cmd)
free = "%sK" % re.findall(r"\d+", output)[0]
else:
Expand All @@ -2375,7 +2377,10 @@ def get_free_mem(session, os_type):
if os_type != "windows":
free = "%s kB" % get_mem_info(session, "MemFree")
else:
output = session.cmd_output("wmic OS get FreePhysicalMemory")
output = session.cmd_output(
'powershell -command "Get-CimInstance Win32_OperatingSystem | '
'Select-Object FreePhysicalMemory"'
)
free = "%sK" % re.findall("\d+", output)[0]
free = float(normalize_data_size(free, order_magnitude="M"))
return int(free)
Expand Down Expand Up @@ -2475,11 +2480,15 @@ def get_win_disk_vol(session, condition="VolumeName='WIN_UTILS'"):
Getting logicaldisk drive letter in windows guest.

:param session: session Object.
:param condition: supported condition via cmd "wmic logicaldisk list".
:param condition: supported condition via powershell cmd "Get-CimInstance Win32_LogicalDisk".

:return: volume ID.
"""
cmd = "wmic logicaldisk where (%s) get DeviceID" % condition
c_name, c_value = condition.split("=")
cmd = (
'powershell -command "Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object {$_.%s -like %s}'
' | Select-Object DeviceID"'
) % (c_name, c_value)
output = session.cmd(cmd, timeout=120)
device = re.search(r"(\w):", output, re.M)
if not device:
Expand Down
50 changes: 40 additions & 10 deletions virttest/utils_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -1654,9 +1654,15 @@ def set_guest_ip_addr(session, mac, ip_addr, netmask="255.255.255.0", os_type="l
session.cmd(cmd, timeout=360)
elif os_type == "windows":
info_cmd = "ipconfig /all"
get_nic_cmd = (
'powershell -command "$Adapter=Get-CimInstance Win32_NetworkAdapterConfiguration | '
"Where-Object {$_.MACAddress -eq '%s'}; $Adapter.InterfaceIndex\""
) % mac
nic_index = session.cmd_output(get_nic_cmd, timeout=120)
prefix_length = subnet_mask_to_prefix_length(netmask)
cmd = (
"wmic nicconfig where MACAddress='%s' call "
"enablestatic '%s','%s'" % (mac, ip_addr, netmask)
"powershell -command \"New-NetIPAddress -InterfaceIndex %s -IPAddress '%s' -PrefixLength %s\""
% (nic_index, ip_addr, prefix_length)
)
session.cmd(cmd, timeout=360)
else:
Expand All @@ -1667,6 +1673,24 @@ def set_guest_ip_addr(session, mac, ip_addr, netmask="255.255.255.0", os_type="l
raise IPAddrSetError(mac, ip_addr, err)


def subnet_mask_to_prefix_length(subnet_mask):
"""
Convert subnet_mask from 255.*** to prefix length

:param subnet_mask: nic subnet_mask

:return: prefix length
"""

octets = subnet_mask.split(".")

prefix_length = 0
for octet in octets:
prefix_length += bin(int(octet)).count("1")

return prefix_length
Comment on lines +1685 to +1691
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
octets = subnet_mask.split(".")
prefix_length = 0
for octet in octets:
prefix_length += bin(int(octet)).count("1")
return prefix_length
return sum(bin(int(octet)).count("1") for octet in subnet_mask.split("."))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @PaulYuuu
Would you like to help to review it?
Thanks. CC @nickzhq

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note that the netmask in set_guest_ip_addr can be CIDR AND dot-decimal notation, only when users give a dot-decimal notation, we have to convert it to a bitmask.

However, the new function is a duplicate of convert_netmask in utils_net module, and set_guest_ip_addr also used it.

nic_ifname = get_linux_ifname(session, mac)
if session.cmd_status("which ip") != 0:
info_cmd = "ifconfig -a; ethtool -S %s" % nic_ifname
cmd = "ifconfig %s %s netmask %s" % (nic_ifname, ip_addr, netmask)
else:
if "." in netmask:
netmask = convert_netmask(netmask)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, the current convert_netmask can only handle dot-decimal notation, as we already import ipaddress, an enhancement here is to use it to handle all types of netmask.

>>> import ipaddress
>>> ip_addr = "192.168.1.1"
>>> netmask = "24" # or "255.255.255.0"
>>> ipaddr = ipaddress.IPv4Network(f"{ip_addr}/{netmask}", strict=False)
>>> ipaddr.netmask
IPv4Address('255.255.255.0')
>>> ipaddr.prefixlen
24

And then you can use it for linux/windows



def get_guest_nameserver(session):
"""
Get guest nameserver from serial session for linux guest
Expand Down Expand Up @@ -3788,7 +3812,10 @@ def str2ipaddr(str_ip):
return None

maps = {}
cmd = "wmic nicconfig where IPEnabled=True get ipaddress, macaddress"
cmd = (
'powershell -command "Get-CimInstance Win32_NetworkAdapterConfiguration | '
"Where-Object {$_.IPEnabled -eq 'True'} | Select-Object IPAddress, MACAddress\""
)
out = session.cmd_output(cmd)
regex = r".*\w{2}[:-]\w{2}[:-]\w{2}[:-]\w{2}[:-]\w{2}[:-]\w{2}\s*"
lines = [l.strip() for l in out.splitlines() if l.strip()]
Expand Down Expand Up @@ -3941,19 +3968,22 @@ def update_mac_ip_address(vm, timeout=240):


def get_windows_nic_attribute(
session, key, value, target, timeout=240, global_switch="nic"
session, key, value, target, timeout=240, global_switch="NetworkAdapter"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

):
"""
Get the windows nic attribute using wmic. All the support key you can
using wmic to have a check.
Get the windows nic attribute using powershell. All the support key you can
using powershell to have a check.

:param session: session to the virtual machine
:param key: the key supported by wmic
:param key: the key supported by Get-CimInstance
:param value: the value of the key
:param target: which nic attribute you want to get.

"""
cmd = 'wmic %s where %s="%s" get %s' % (global_switch, key, value, target)
cmd = (
"powershell -command \"Get-CimInstance Win32_%s | Where-Object {$_.%s -eq '%s'} | Select-Object %s\""
% (global_switch, key, value, target)
)
status, out = session.cmd_status_output(cmd, timeout=timeout)
if status != 0:
err_msg = "Execute guest shell command('%s') " "failed with error: '%s'" % (
Expand Down Expand Up @@ -3993,7 +4023,7 @@ def restart_windows_guest_network(session, connection_id, timeout=240, mode="net

:param session: session to virtual machine
:param connection_id: windows nic connectionid,it means connection name,
you Can get connection id string via wmic
you Can get connection id string via wmic or powershell
"""
if mode == "netsh":
disable_windows_guest_network(session, connection_id, timeout=timeout)
Expand All @@ -4011,7 +4041,7 @@ def restart_windows_guest_network_by_key(
using devcon mode must download devcon.exe and put it under c:\

:param session: session to virtual machine
:param key: the key supported by wmic nic
:param key: the key supported by Get-CimInstance nic
:param value: the value of the key
:param timeout: timeout
:param mode: command mode netsh or devcon
Expand Down
5 changes: 4 additions & 1 deletion virttest/utils_netperf.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,10 @@ def __init__(
def is_target_running(self, target):
list_cmd = "ps -C %s" % target
if self.client == "nc":
list_cmd = "wmic process where name='%s' list" % target
list_cmd = (
"powershell -command \"Get-CimInstance Win32_Process | Where-Object {$_.Name -eq '%s'}"
' | Format-List *"'
) % target
try:
output = self.session.cmd_output_safe(list_cmd, timeout=120)
check_reg = re.compile(r"%s" % target, re.I | re.M)
Expand Down
19 changes: 11 additions & 8 deletions virttest/utils_test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,18 +300,21 @@ def start_windows_service(session, service, timeout=120):

def get_windows_file_abs_path(session, filename, extension="exe", tmout=240):
"""
return file abs path "drive+path" by "wmic datafile"
"""
cmd_tmp = "wmic datafile where \"Filename='%s' and "
cmd_tmp += "extension='%s'\" get drive^,path"
cmd = cmd_tmp % (filename, extension)
return file abs path "drive+path" by Get-CimInstance
"""
full_name = filename + "." + extension
cmd = (
'powershell -command "Get-PSDrive -PSProvider FileSystem | ForEach-Object '
'{Get-ChildItem -Path $_.Root -Filter "%s" -Recurse -ErrorAction SilentlyContinue} |'
' Select-Object Fullname"'
) % full_name
info = session.cmd_output(cmd, timeout=tmout).strip()
drive_path = re.search(r"(\w):\s+(\S+)", info, re.M)
if not drive_path:
file_abs_path = re.search(r"^[A-Z]:\\.*\.*$", info, re.M)
if not file_abs_path:
raise exceptions.TestError(
"Not found file %s.%s in your guest" % (filename, extension)
)
return ":".join(drive_path.groups())
return file_abs_path.string


def get_windows_disk_drive(session, filename, extension="exe", tmout=240):
Expand Down
2 changes: 1 addition & 1 deletion virttest/utils_test/qemu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ def get_guest_total_mem(cls, vm):
:return: physical memory report by guest OS in MB
"""
if vm.params.get("os_type") == "windows":
cmd = "wmic ComputerSystem get TotalPhysicalMemory"
cmd = 'powershell -command "(Get-CimInstance -ClassName Win32_ComputerSystem).TotalPhysicalMemory"'
else:
cmd = "grep 'MemTotal:' /proc/meminfo"
return vm.get_memory_size(cmd)
Expand Down
58 changes: 38 additions & 20 deletions virttest/utils_windows/drive.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
"""
Windows drive utilities
"""

from virttest import utils_misc

from . import wmic
import re


def _logical_disks(session, cond=None, props=None):
cmd = wmic.make_query("LogicalDisk", cond, props, get_swch=wmic.FMT_TYPE_LIST)
out = utils_misc.wait_for(
lambda: wmic.parse_list(session.cmd(cmd, timeout=120)), 240
)
return out if out else []
c_name, c_value = cond.split("=")
cmd = (
'powershell -command "Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object {$_.%s -like %s}'
Copy link
Contributor

@mcasquer mcasquer Jan 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The disk needs to be under single quotes, same you've done in utils_netperf.py and replace the existing ones by double quotes

Suggested change
'powershell -command "Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object {$_.%s -like %s}'
"powershell -command \"Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object {$_.%s -like '%s'}"

' | Select-Object %s | Format-List *"'
) % (c_name, c_value, ",".join(props))
out = session.cmd(cmd, timeout=120)
results = []
for para in re.split("(?:\r?\n){2,}", out.strip()):
keys, vals = [], []
for line in para.splitlines():
key, val = line.split(":", 1)
keys.append(key.strip())
vals.append(val.strip())
if len(keys) == 1:
results.append(vals[0])
else:
results.append(dict(zip(keys, vals)))
return results if results else []


def get_hard_drive_letter(session, label):
Expand All @@ -24,7 +34,7 @@ def get_hard_drive_letter(session, label):

:return: Hard drive's letter if found, otherwise `None`.
"""
cond = "VolumeName like '%s'" % label
cond = "VolumeName='%s'" % label
try:
return _logical_disks(session, cond=cond, props=["DeviceID"])[0]
except IndexError:
Expand Down Expand Up @@ -103,13 +113,21 @@ def get_disk_props_by_serial_number(session, serial_number, props):
:return: The mapping between properties and values.
:rtype: dict
"""
cond = "SerialNumber like '%s'" % serial_number
cmd = wmic.make_query("diskdrive", cond, props=props, get_swch=wmic.FMT_TYPE_LIST)
out = wmic.parse_list(session.cmd(cmd, timeout=120))

if out:
mapping = out[-1]
if isinstance(mapping, str):
return {props[0]: mapping}
return mapping
return {}
cmd = (
'powershell -command "Get-CimInstance -ClassName Win32_Diskdrive | Where-Object {$_.SerialNumber -eq %s}'
Copy link
Contributor

@mcasquer mcasquer Jan 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

Suggested change
'powershell -command "Get-CimInstance -ClassName Win32_Diskdrive | Where-Object {$_.SerialNumber -eq %s}'
"powershell -command \"Get-CimInstance -ClassName Win32_Diskdrive | Where-Object {$_.SerialNumber -eq '%s'}"

' | Select-Object %s | Format-List *"'
) % (serial_number, ",".join(props))
out = session.cmd(cmd, timeout=120)
results = []
for para in re.split("(?:\r?\n){2,}", out.strip()):
print(para)
keys, vals = [], []
for line in para.splitlines():
key, val = line.split(":", 1)
keys.append(key.strip())
vals.append(val.strip())
if len(keys) == 1:
results.append(vals[0])
else:
results.append(dict(zip(keys, vals)))
return results if results else []
Copy link
Contributor

@mcasquer mcasquer Jan 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leidwang
Another comment here, this implementation seems to no longer return a map, so this will probably break all the calls to this function.

25 changes: 18 additions & 7 deletions virttest/utils_windows/system.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
"""
Windows system utilities
"""

from . import wmic
import re


def _osinfo(session, props=None):
cmd = wmic.make_query("os", props=props, get_swch=wmic.FMT_TYPE_LIST)
try:
return wmic.parse_list(session.cmd(cmd))[0]
except IndexError:
return None
cmd = (
'powershell -command "Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object %s | Format-List *"'
% (",".join(props))
)
out = session.cmd(cmd, timeout=120)
results = []
for para in re.split("(?:\r?\n){2,}", out.strip()):
keys, vals = [], []
for line in para.splitlines():
key, val = line.split(":", 1)
keys.append(key.strip())
vals.append(val.strip())
if len(keys) == 1:
results.append(vals[0])
else:
results.append(dict(zip(keys, vals)))
return results[0] if results else []


def product_name(session):
Expand Down
2 changes: 1 addition & 1 deletion virttest/utils_windows/virtio_win.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def drive_letter_iso(session):

:return: Drive letter.
"""
return drive.get_hard_drive_letter(session, "virtio-win%")
return drive.get_hard_drive_letter(session, "virtio-win*")


def drive_letter_vfd(session):
Expand Down