This patch adds node device test case to cover API: listAllDevice, listCaps,
numOfCaps, parent, name.
It lists all node devices by checking each uevent file of node in sysfs. If the
keywords are found in uevent, it will add this node to node device, and record
relationship with its parent node device.
Signed-off-by: jmiao <jmiao(a)redhat.com>
---
cases/basic_nodedevice.conf | 10 ++
repos/nodedevice/capabilities.py | 63 ++++++++
repos/nodedevice/list_nodedevices.py | 276 +++++++++++++++++++++++++++++++++++
repos/nodedevice/parent_name.py | 63 ++++++++
4 files changed, 412 insertions(+)
create mode 100644 repos/nodedevice/capabilities.py
create mode 100644 repos/nodedevice/list_nodedevices.py
create mode 100644 repos/nodedevice/parent_name.py
diff --git a/cases/basic_nodedevice.conf b/cases/basic_nodedevice.conf
index 85a68f7..1a19bde 100644
--- a/cases/basic_nodedevice.conf
+++ b/cases/basic_nodedevice.conf
@@ -1,3 +1,13 @@
+nodedevice:list_nodedevices
+
+nodedevice:parent_name
+ pciaddress
+ $testpci
+
+nodedevice:capabilities
+ pciaddress
+ $testpci
+
nodedevice:detach
pciaddress
$testpci
diff --git a/repos/nodedevice/capabilities.py b/repos/nodedevice/capabilities.py
new file mode 100644
index 0000000..9b94376
--- /dev/null
+++ b/repos/nodedevice/capabilities.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+import libvirt
+from libvirt import libvirtError
+
+from src import sharedmod
+
+required_params = ('pciaddress',)
+optional_params = {}
+
+def capabilities(params):
+ """check the capabilities of a given node device"""
+ global logger
+ logger = params['logger']
+
+ pciaddress = params['pciaddress']
+
+ nodedevice = None
+
+ node_capabilities = []
+
+ if not sharedmod.data.has_key('all_nodes'):
+ logger.error("Failed to get nodes.")
+ return 1
+
+
+ (bus, slot_func) = pciaddress.split(":")
+ (slot, func) = slot_func.split(".")
+ device_name = "pci_0000_%s_%s_%s" % (bus, slot, func)
+ logger.debug("the name of the pci device is: %s" % device_name)
+
+ nodes = sharedmod.data['all_nodes']
+
+ for entry in nodes:
+ if cmp(entry.name, device_name):
+ nodedevice = entry
+ else:
+ if nodedevice is None:
+ logger.error("parent_name cannot find %s" % device_name)
+ return 1
+
+ conn = sharedmod.libvirtobj['conn']
+
+ try:
+ node_obj = conn.nodeDeviceLookupByName(device_name)
+ node_capabilities = node_obj.listCaps()
+
+ logger.info("%s capabilities: %s" %(device_name, node_capabilities))
+
+ if len(node_capabilities) != node_obj.numOfCaps():
+ logger.error("The number of node capabilities error")
+ return 1
+
+ if not cmp(node_capabilities[0], nodedevice.capability):
+ logger.error("%s capabilities error: %s, should be %s."
+ % (device_name, node_capabilities[0], nodedevice.capability))
+ return 1
+ except libvirtError, e:
+ logger.error("API error message: %s, error code is %s"
+ % (e.message, e.get_error_code()))
+ return 1
+
+ return 0
diff --git a/repos/nodedevice/list_nodedevices.py b/repos/nodedevice/list_nodedevices.py
new file mode 100644
index 0000000..eb1f242
--- /dev/null
+++ b/repos/nodedevice/list_nodedevices.py
@@ -0,0 +1,276 @@
+#!/usr/bin/env python
+# list all node devices from host
+
+import commands
+
+import libvirt
+from libvirt import libvirtError
+
+from src import sharedmod
+
+required_params = ()
+optional_params = {}
+
+g_pci = []
+g_usb_device = []
+g_usb = []
+g_scsi_host = []
+g_scsi_target = []
+g_scsi = []
+g_net = []
+g_storage = []
+g_nodes = []
+
+options = { 'pci' : ['PCI_ID', g_pci, 'pci_'],
+ 'usb_device' : ['DEVTYPE=usb_device', g_usb_device,
'usb_'],
+ 'usb' : ['DEVTYPE=usb_interface', g_usb, 'usb_'],
+ 'scsi_host' : ['DEVTYPE=scsi_host', g_scsi_host,
'scsi_'],
+ 'scsi_target' : ['DEVTYPE=scsi_target', g_scsi_target,
'scsi_'],
+ 'scsi' : ['DEVTYPE=scsi_device', g_scsi, 'scsi_'],
+ }
+
+class NodeDevice(object):
+ """A NodeDevice class to record related
information."""
+ def __init__(self, name, path):
+ """init"""
+ self.name = name
+ self.path = path
+ self.parent = None
+ self.capability = None
+
+ def create_child(self, name, path, cap):
+ """create_child function"""
+ child = NodeDevice(name, path)
+ child.parent = self
+ child.capability = cap
+ return child
+
+def format_name(name):
+ """format name to libvirt style: pci_0000_00_00_0"""
+ name = name.replace('.', '_')
+ name = name.replace(':', '_')
+ name = name.replace('-', '_')
+ return name
+
+def extract_name(path):
+ """
+ extract name from a path. The argument must be a path which ending with
+ '/', and it will be parsed by this function.
+ """
+ pos2 = path.rfind('/')
+ path = path[0:pos2]
+ pos1 = path.rfind('/')
+ path = path[pos1+1:pos2]
+ return format_name(path)
+
+def list_net(root):
+ """list all net nodedevices"""
+ global g_net, g_pci
+ cmd = "ip link | awk {'print $2'}"
+ (status, ret) = commands.getstatusoutput(cmd)
+ if status != 0:
+ return 1
+
+ tmp = ret.split('\n')
+
+ # bubble sort to reduce the replicated mac
+ for i in reversed(range(0, len(tmp)/2)):
+ for j in reversed(range(i, len(tmp)/2)):
+ if i != j and tmp[i*2+1] == tmp[j*2+1]:
+ del tmp[i*2+1]
+ del tmp[i*2]
+
+ for i in range(0, len(tmp)/2):
+ cmd = "ethtool -i %s | grep driver" % tmp[i*2][0:len(tmp[i*2])-1]
+ (status, ret) = commands.getstatusoutput(cmd)
+ if status != 0:
+ g_net.append(root.create_child("net_" + format_name(tmp[i*2] +
+ tmp[i*2+1]), root.path, "net"))
+ continue
+
+ cmd = "echo %s | awk {'print $2'}" % ret
+ (status, ret) = commands.getstatusoutput(cmd)
+ driver = ret
+
+ cmd = "echo %s | egrep -v 'tun|bridge'" % driver
+ (status, ret) = commands.getstatusoutput(cmd)
+ if status == 0:
+ for entry in g_pci:
+ cmd = "cat %s/uevent | grep %s" % (entry.path, driver)
+ (status, ret) = commands.getstatusoutput(cmd)
+ if status == 0:
+ g_net.append(entry.create_child("net_" + format_name(
+ tmp[i*2] + tmp[i*2+1]), entry.path, "net"))
+ else:
+ g_net.append(root.create_child("net_" + format_name(tmp[i*2] +
+ tmp[i*2+1]), root.path, "net"))
+
+
+ return 0
+
+def list_scsi_host(node):
+ """list all scsi host nodedevices"""
+ cmd = "find %s -name host*" % node.path
+ (status, ret) = commands.getstatusoutput(cmd)
+ if status != 0:
+ return 1
+ if len(ret) == 0:
+ return 1
+
+ dir = ret.split('\n')
+
+ for entry in dir:
+ entry_path = entry + '/'
+ cmd = "cat %s/uevent | egrep -i '%s'" % (entry_path,
+ options['scsi_host'][0])
+ (status, ret) = commands.getstatusoutput(cmd)
+ if status == 0:
+ options['scsi_host'][1].append(node.create_child(
+ options['scsi_host'][2] + extract_name(entry_path),
+ entry_path, 'scsi_host'))
+
+
+def list_storage(root):
+ """list all storage nodedevices"""
+ global g_nodes, g_storage
+ cmd = "find %s -name block | sed -e 's/block//'" % root.path
+ (status, ret) = commands.getstatusoutput(cmd)
+ if status != 0:
+ return 1
+
+ if len(ret) == 0:
+ return 1
+
+ blk = ret.split('\n')
+
+ for blk_entry in blk:
+ for node_entry in g_nodes:
+ if cmp(blk_entry, node_entry.path) == 0:
+ cmd = "ls %s/block" % blk_entry
+ (status, ret) = commands.getstatusoutput(cmd)
+ if status != 0:
+ continue
+
+ g_storage.append(node_entry.create_child("block_" + ret,
+ blk_entry+"block/", "storage"))
+ return 0
+
+
+def list_node(node_device, path, cap, checktop):
+ """list a nodedevices though path."""
+ dirs = []
+ if checktop == True:
+ cmd = "cat %suevent | egrep -i '%s'" % (path, options[cap][0])
+ (status, ret) = commands.getstatusoutput(cmd)
+ if status != 0:
+ return 1
+ else:
+ options[cap][1].append(node_device.create_child(options[cap][2]
+ + extract_name(path), path, cap))
+
+ cmd = "ls %s" % path
+ (status, ret) = commands.getstatusoutput(cmd)
+ if status != 0:
+ return 1
+
+ cmd = "ls -l %s | grep '^d' | awk {'print $9'}" % path
+ (status, ret) = commands.getstatusoutput(cmd)
+
+ if len(ret) == 0:
+ return 1
+
+ dirs = ret.split('\n')
+
+ for entry in dirs:
+ list_node(node_device, path + entry + "/", cap, True)
+
+ return 0
+
+
+def list_nodedevices(params):
+ """list all nodedevices"""
+ global logger
+ global g_nodes, g_pci, g_usb_device, g_usb, g_net
+ global g_scsi_host, g_scsi_target, g_scsi, g_storage
+ ret = 0
+
+ logger = params['logger']
+
+ root = NodeDevice("computer", "/sys/devices/pci0000:00/")
+ g_nodes.append(root)
+
+ # find pci
+ list_node(root, root.path, 'pci', False)
+ g_nodes += g_pci
+
+ # find usb_device
+ for entry in g_pci:
+ list_node(entry, entry.path, 'usb_device', False)
+ g_nodes += g_usb_device
+
+ # find usb
+ for entry in g_usb_device:
+ list_node(entry, entry.path, 'usb', False)
+ g_nodes += g_usb
+
+ # find scsi_host
+ for entry in g_pci + g_usb:
+ list_scsi_host(entry)
+ g_nodes += g_scsi_host
+
+ # find scsi_target
+ for entry in g_scsi_host:
+ list_node(entry, entry.path, 'scsi_target', False)
+ g_nodes += g_scsi_target
+
+ # find scsi
+ for entry in g_scsi_target:
+ list_node(entry, entry.path, 'scsi', False)
+ g_nodes += g_scsi
+
+ # find net
+ list_net(root)
+ g_nodes += g_net
+
+ # find storage
+ list_storage(root)
+ g_nodes += g_storage
+
+ logger.debug("Traverse the node device list")
+
+ sharedmod.data['all_nodes'] = g_nodes
+
+ try:
+ conn = sharedmod.libvirtobj['conn']
+ retlist = conn.listAllDevices(0)
+
+ if len(retlist) > len(g_nodes):
+ for entry in g_nodes:
+ print entry.name
+ logger.error("list_all_node_devices miss some devices")
+ return 1
+ elif len(retlist) < len(g_nodes):
+ for entry in g_nodes:
+ print entry.name
+ logger.error("listAllDevices miss some devices")
+ return 1
+
+ for entry in retlist:
+ checked = 0
+ for node in g_nodes:
+ if entry.name().find(node.name) == 0:
+ logger.info("%s \033[32mchecked\033[0m" % entry.name())
+ checked = 1
+ ret = 0
+ else:
+ if checked == 0:
+ logger.error("%s \033[31mnot found\033[0m" % entry.name())
+ ret = 1
+
+
+ except libvirtError, e:
+ logger.error("API error message: %s, error code is %s"
+ % (e.message, e.get_error_code()))
+ return 1
+
+ return ret
diff --git a/repos/nodedevice/parent_name.py b/repos/nodedevice/parent_name.py
new file mode 100644
index 0000000..5ce27f5
--- /dev/null
+++ b/repos/nodedevice/parent_name.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+import os
+import sys
+
+import libvirt
+from libvirt import libvirtError
+
+from src import sharedmod
+from utils import utils
+
+required_params = ('pciaddress',)
+optional_params = {}
+
+def parent_name(params):
+ """check nodedevice parant and name API"""
+ global logger
+ logger = params['logger']
+
+ pciaddress = params['pciaddress']
+
+ nodedevice = None
+
+ if not sharedmod.data.has_key('all_nodes'):
+ logger.error("Failed to get nodes.")
+ return 1
+
+
+ (bus, slot_func) = pciaddress.split(":")
+ (slot, func) = slot_func.split(".")
+ device_name = "pci_0000_%s_%s_%s" % (bus, slot, func)
+ logger.debug("the name of the pci device is: %s" % device_name)
+
+ nodes = sharedmod.data['all_nodes']
+
+ for entry in nodes:
+ if cmp(entry.name, device_name):
+ nodedevice = entry
+ else:
+ if nodedevice is None:
+ logger.error("parent_name cannot find %s" % device_name)
+ return 1
+
+ parent_nodedevice = nodedevice.parent
+
+ conn = sharedmod.libvirtobj['conn']
+
+ try:
+ node_obj = conn.nodeDeviceLookupByName(device_name)
+ parent_node_name = node_obj.parent()
+
+ logger.info("%s's parent name is %s" %(device_name,
parent_node_name))
+
+ if not cmp(parent_node_name, parent_nodedevice.name):
+ logger.error("%s's parent device name error: %s, should be %s."
+ % (device_name, parent_node_name, parent_nodedevice.name))
+ return 1
+ except libvirtError, e:
+ logger.error("API error message: %s, error code is %s"
+ % (e.message, e.get_error_code()))
+ return 1
+
+ return 0
--
1.8.2.1