_NETWORK_XML_TAG = "network"
_POOL_XML_TAG = "pool"
-_ETHTOOL_OTHERCONFIG_ATTRS = ['ethtool-%s' % x for x in 'autoneg', 'speed', 'duplex', 'rx', 'tx', 'sg', 'tso', 'ufo', 'gso' ]
+_ETHTOOL_OTHERCONFIG_ATTRS = ['ethtool-%s' % x for x in 'autoneg', 'speed', 'duplex', 'rx', 'tx', 'sg', 'tso', 'ufo', 'gso', 'gro', 'lro' ]
_PIF_OTHERCONFIG_ATTRS = [ 'domain', 'peerdns', 'defaultroute', 'mtu', 'static-routes' ] + \
[ 'bond-%s' % x for x in 'mode', 'miimon', 'downdelay',
continue
self.__pifs[p] = {}
for f in _PIF_ATTRS:
- if f in [ "tunnel_access_PIF_of", "tunnel_transport_PIF_of" ] and f not in rec:
- # XenServer 5.5 network records did not have
- # these fields, so allow them to be missing.
- pass
- else:
- self.__pifs[p][f] = rec[f]
+ self.__pifs[p][f] = rec[f]
self.__pifs[p]['other_config'] = {}
for f in _PIF_OTHERCONFIG_ATTRS:
if not rec['other_config'].has_key(f): continue
def __get_vlan_records_from_xapi(self, session):
self.__vlans = {}
- for v in session.xenapi.VLAN.get_all():
- rec = session.xenapi.VLAN.get_record(v)
+ for (v,rec) in session.xenapi.VLAN.get_all_records().items():
if not self.__pif_on_host(rec['untagged_PIF']):
continue
self.__vlans[v] = {}
def __get_bond_records_from_xapi(self, session):
self.__bonds = {}
- for b in session.xenapi.Bond.get_all():
- rec = session.xenapi.Bond.get_record(b)
+ for (b,rec) in session.xenapi.Bond.get_all_records().items():
if not self.__pif_on_host(rec['master']):
continue
self.__bonds[b] = {}
def __get_network_records_from_xapi(self, session):
self.__networks = {}
- for n in session.xenapi.network.get_all():
- rec = session.xenapi.network.get_record(n)
+ for (n,rec) in session.xenapi.network.get_all_records().items():
self.__networks[n] = {}
for f in _NETWORK_ATTRS:
if f == "PIFs":
self.__get_pif_records_from_xapi(session, host)
- try:
- self.__get_tunnel_records_from_xapi(session)
- except XenAPI.Failure, e:
- error,details = e.details
- if error == "MESSAGE_METHOD_UNKNOWN" and details == "tunnel.get_all":
- pass
-
+ self.__get_tunnel_records_from_xapi(session)
self.__get_pool_records_from_xapi(session)
self.__get_vlan_records_from_xapi(session)
self.__get_bond_records_from_xapi(session)
#
#
#
+PIF_OTHERCONFIG_DEFAULTS = {'gro': 'off', 'lro': 'off'}
-def ethtool_settings(oc):
+def ethtool_settings(oc, defaults = {}):
settings = []
if oc.has_key('ethtool-speed'):
val = oc['ethtool-speed']
log("Invalid value for ethtool-speed = %s. Must be 10|100|1000." % val)
if oc.has_key('ethtool-duplex'):
val = oc['ethtool-duplex']
- if val in ["10", "100", "1000"]:
- settings += ['duplex', 'val']
+ if val in ["half", "full"]:
+ settings += ['duplex', val]
else:
log("Invalid value for ethtool-duplex = %s. Must be half|full." % val)
if oc.has_key('ethtool-autoneg'):
else:
log("Invalid value for ethtool-autoneg = %s. Must be on|true|off|false." % val)
offload = []
- for opt in ("rx", "tx", "sg", "tso", "ufo", "gso"):
+ for opt in ("rx", "tx", "sg", "tso", "ufo", "gso", "gro", "lro"):
if oc.has_key("ethtool-" + opt):
val = oc["ethtool-" + opt]
if val in ["true", "on"]:
offload += [opt, 'off']
else:
log("Invalid value for ethtool-%s = %s. Must be on|true|off|false." % (opt, val))
+ elif opt in defaults:
+ offload += [opt, defaults[opt]]
return settings,offload
# By default the MTU is taken from the Network.MTU setting for VIF,
# Tunnel PIFs
#
def pif_is_tunnel(pif):
- rec = db().get_pif_record(pif)
- return rec.has_key('tunnel_access_PIF_of') and len(rec['tunnel_access_PIF_of']) > 0
+ return len(db().get_pif_record(pif)['tunnel_access_PIF_of']) > 0
#
# Datapath base class
PROC_MOUNTS = '/proc/mounts'
ISCSI_CONF = '/etc/iscsi/iscsid.conf'
ISCSI_INITIATOR = '/etc/iscsi/initiatorname.iscsi'
-LVM_CACHE = '/etc/lvm/.cache'
+LVM_CACHE = '/etc/lvm/cache/.cache'
+LVM_CONFIG = '/etc/lvm/lvm.conf'
PROC_CPUINFO = '/proc/cpuinfo'
PROC_MEMINFO = '/proc/meminfo'
PROC_IOPORTS = '/proc/ioports'
ROUTE_RE = re.compile(r'^.*/route-.*')
NETWORK_DBCACHE = '/var/xapi/network.dbcache'
RESOLV_CONF = '/etc/resolv.conf'
+MPP_CONF = '/etc/mpp.conf'
MULTIPATH_CONF = '/etc/multipath.conf'
NSSWITCH_CONF = '/etc/nsswitch.conf'
NTP_CONF = '/etc/ntp.conf'
PATCH_APPLIED_DIR = '/var/patch/applied'
XENSERVER_LOGS = \
[ VAR_LOG_DIR + x for x in
- ['xensource.log', 'audit.log', 'xenstored-access.log', 'SMlog', 'xen/xenstored-trace.log',
+ ['xensource.log', 'audit.log', 'xenstored-access.log', 'SMlog', 'VMPRlog', 'xen/xenstored-trace.log',
'xen/xen-hotplug.log', 'xen/domain-builder-ng.log', 'squeezed.log',
'openvswitch/ovs-brcompatd.log', 'openvswitch/ovs-vswitchd.log', 'openvswitch/ovsdb-server.log' ] +
[ f % n for n in range(1, 20) \
- for f in ['xensource.log.%d', 'xensource.log.%d.gz','SMlog.%d', 'SMlog.%d.gz',
+ for f in ['xensource.log.%d', 'xensource.log.%d.gz','SMlog.%d', 'SMlog.%d.gz', 'VMPRlog.%d', 'VMPRlog.%d.gz',
'audit.log.%d', 'audit.log.%d.gz', 'xenstored-access.log.%d', 'xenstored-access.log.%d.gz', \
'xen/xenstored-access.log.%d', 'xen/xenstored-access.log.%d.gz', 'squeezed.log.%d', \
'openvswitch/ovs-brcompatd.log.%d', 'openvswitch/ovs-brcompatd.log.%d.gz', \
LVDISPLAY = '/usr/sbin/lvdisplay'
MD5SUM = '/usr/bin/md5sum'
MODINFO = '/sbin/modinfo'
+MPPUTIL = '/usr/sbin/mppUtil'
MULTIPATHD = '/sbin/multipathd'
NETSTAT = '/bin/netstat'
OVS_DPCTL = '/usr/bin/ovs-dpctl'
def cap(key, pii=PII_MAYBE, min_size=-1, max_size=-1, min_time=-1,
max_time=-1, mime=MIME_TEXT, checked=True, hidden=False):
+ if os.getenv('XEN_RT') and max_time > 0:
+ max_time *= 5
caps[key] = (key, pii, min_size, max_size, min_time, max_time, mime,
checked, hidden)
cap_sizes[key] = 0
cap(CAP_BOOT_LOADER, PII_NO, max_size=3*KB,
max_time=5)
cap(CAP_CVSM, PII_NO, max_size=3*MB,
- max_time=60)
-cap(CAP_DISK_INFO, PII_MAYBE, max_size=25*KB,
+ max_time=120)
+cap(CAP_DISK_INFO, PII_MAYBE, max_size=50*KB,
max_time=20)
cap(CAP_FIRSTBOOT, PII_YES, min_size=60*KB, max_size=80*KB)
-cap(CAP_HARDWARE_INFO, PII_MAYBE, max_size=30*KB,
+cap(CAP_HARDWARE_INFO, PII_MAYBE, max_size=50*KB,
max_time=20)
cap(CAP_HDPARM_T, PII_NO, min_size=0, max_size=5*KB,
min_time=20, max_time=90, checked=False, hidden=True)
cap(CAP_KERNEL_INFO, PII_MAYBE, max_size=120*KB,
max_time=5)
cap(CAP_LOSETUP_A, PII_MAYBE, max_size=KB, max_time=5)
-cap(CAP_MULTIPATH, PII_MAYBE, max_size=10*KB,
+cap(CAP_MULTIPATH, PII_MAYBE, max_size=20*KB,
max_time=10)
cap(CAP_NETWORK_CONFIG, PII_IF_CUSTOMIZED,
- min_size=0, max_size=20*KB)
+ min_size=0, max_size=40*KB)
cap(CAP_NETWORK_STATUS, PII_YES, max_size=19*KB,
max_time=30)
-cap(CAP_PAM, PII_NO, max_size=30*KB)
+cap(CAP_PAM, PII_NO, max_size=50*KB)
cap(CAP_PERSISTENT_STATS, PII_MAYBE, max_size=50*MB,
max_time=60)
cap(CAP_PROCESS_LIST, PII_YES, max_size=30*KB,
cap(CAP_XAPI_DEBUG, PII_MAYBE, max_size=10*MB)
cap(CAP_XAPI_SUBPROCESS, PII_NO, max_size=5*KB,
max_time=10)
-cap(CAP_XENRT, PII_NO, min_size=0, max_size=5*KB,
+cap(CAP_XENRT, PII_NO, min_size=0, max_size=500*MB,
checked=False, hidden=True)
cap(CAP_XENSERVER_CONFIG, PII_MAYBE, max_size=80*KB,
max_time=5)
cmd_output(CAP_DISK_INFO, [PVS])
cmd_output(CAP_DISK_INFO, [VGS])
cmd_output(CAP_DISK_INFO, [LVS])
- file_output(CAP_DISK_INFO, [LVM_CACHE])
+ file_output(CAP_DISK_INFO, [LVM_CACHE, LVM_CONFIG])
cmd_output(CAP_DISK_INFO, [LS, '-R', '/sys/class/scsi_host'])
cmd_output(CAP_DISK_INFO, [LS, '-R', '/sys/class/scsi_disk'])
cmd_output(CAP_DISK_INFO, [LS, '-R', '/sys/class/fc_transport'])
cmd_output(CAP_LOSETUP_A, [LOSETUP, '-a'])
- file_output(CAP_MULTIPATH, [MULTIPATH_CONF])
- cmd_output(CAP_MULTIPATH, [DMSETUP, 'status'])
+ file_output(CAP_MULTIPATH, [MULTIPATH_CONF, MPP_CONF])
+ cmd_output(CAP_MULTIPATH, [DMSETUP, 'table'])
func_output(CAP_MULTIPATH, 'multipathd_topology', multipathd_topology)
+ cmd_output(CAP_MULTIPATH, [MPPUTIL, '-a'])
+ if CAP_MULTIPATH in entries:
+ dump_rdac_groups(CAP_MULTIPATH)
file_output(CAP_NETWORK_CONFIG, [NETWORK_CONF])
file_output(CAP_NETWORK_CONFIG, [NETWORK_DBCACHE])
tree_output(CAP_VNCTERM, VNCTERM_CORE_DIR)
+ cmd_output(CAP_WLB, [XE, 'pool-retrieve-wlb-configuration'])
cmd_output(CAP_WLB, [XE, 'pool-retrieve-wlb-diagnostics'])
tree_output(CAP_X11_LOGS, X11_LOGS_DIR, X11_LOGS_RE)
func_output(CAP_XAPI_SUBPROCESS, 'xapi_subprocesses', dump_xapi_subprocess_info)
tree_output(CAP_XENRT, '/tmp', FIST_RE)
+ # CA-45540: capture QEMU core files
+ tree_output(CAP_XENRT, '/var/xen/qemu')
+ tree_output(CAP_XENRT, '/tmp', re.compile(r'^.*xen\.qemu-dm\.'))
file_output(CAP_XENSERVER_CONFIG, [INITIAL_INVENTORY])
file_output(CAP_XENSERVER_CONFIG, [POOL_CONF, PTOKEN, XAPI_CONF, XAPI_SSL_CONF,
cmd_output(CAP_XENSERVER_CONFIG, [LS, '-lR', STATIC_VDIS])
func_output(CAP_XENSERVER_DATABASES, 'xapi-db.xml', dump_filtered_xapi_db)
- cmd_output(CAP_XENSERVER_DATABASES, [XENSTORE_LS])
+ cmd_output(CAP_XENSERVER_DATABASES, [XENSTORE_LS, '-f'])
file_output(CAP_XENSERVER_DATABASES, [DB_CONF, DB_CONF_RIO, DB_DEFAULT_FIELDS, DB_SCHEMA_SQL])
tree_output(CAP_XENSERVER_DATABASES, OEM_CONFIG_DIR, OEM_DB_FILES_RE)
file_output(CAP_XENSERVER_DATABASES, [XENSTORED_DB, XENSTORED_DB + '.bak'])
session.xenapi.session.logout()
return output
-def filter_db_pii(str, state):
- if 'in_secret_table' not in state:
- state['in_secret_table'] = False
+'''Filter a Xapi XML database.
+
+ There is one important assumption made in this class:
+ - the XML document does not contain any characters between the end of one
+ tag and the beginning of the next, ie every > is immediately followed by
+ a <
+'''
+class DBFilter:
+ def __init__(self):
+ self.result = ''
+ self.rest = ''
+ self.state = {}
+
+ def filter_secrets(self, s):
+ if 'in_secret_table' not in self.state:
+ self.state['in_secret_table'] = False
+
+ # this logic doesn't deal with <table name="secret" /> properly!!!
+ if s.startswith('<table ') and 'name="secret"' in s:
+ self.state['in_secret_table'] = True
+ elif s.startswith('</table>'):
+ self.state['in_secret_table'] = False
+
+ if self.state['in_secret_table'] and s.startswith("<row"): # match only on DB rows
+ s = re.sub(r'(value=")[^"]+(")', r'\1REMOVED\2', s)
+ return s
- if str.startswith('<table ') and 'name="secret"' in str:
- state['in_secret_table'] = True
- elif str.startswith('</table>'):
- state['in_secret_table'] = False
-
- if state['in_secret_table'] and str.startswith("<row"): # match only on DB rows
- str = re.sub(r'(value=")[^"]+(")', r'\1REMOVED\2', str)
- return str
+ def feed(self, s):
+ rem = self.rest + s
+ p = rem.find('>')
+ while p != -1:
+ s = rem[:p+1]
+ rem = rem[p+1:]
+ self.result += self.filter_secrets(s)
+ p = rem.find('>')
+ self.rest = rem
+
+ def output(self):
+ r = self.result + self.filter_secrets(self.rest)
+ self.result, self.rest = '', ''
+ self.state = {}
+ return r
+
+def filter_db_pii(s, state):
+ dbfilter = DBFilter()
+ dbfilter.feed(s)
+ return dbfilter.output()
def dump_filtered_xapi_db(cap):
db_file = None
if not ih:
return ''
- remain = ''
+ dbfilter = DBFilter()
rec = ih.read(2048)
while rec != '':
- remain += rec
- p = remain.find('>')
- while p != -1:
- str = remain[:p+1]
- remain = remain[p+1:]
- output += filter_db_pii(str, state)
- p = remain.find('>')
+ dbfilter.feed(rec)
rec = ih.read(2048)
- output += remain
+ output = dbfilter.output()
if pipe:
pipe.wait()
output = StringIO.StringIO()
procs = []
-
- def rotate_string(x, n):
- transtbl = ""
- for a in range(0, 256):
- transtbl = transtbl + chr(a)
- transtbl = transtbl[n:] + transtbl[0:n]
- return x.translate(transtbl)
-
- def _untransform_string(str, remove_trailing_nulls=False):
- """De-obfuscate string. To cope with an obfuscation bug in Rio, the argument
- remove_trailing_nulls should be set to True"""
- tmp = base64.decodestring(str)
- if remove_trailing_nulls:
- tmp = tmp.rstrip('\x00')
- return rotate_string(tmp, -13)
+ csl_targets_fetched = []
for pbd in session.xenapi.PBD.get_all_records().values():
if pbd.has_key('device_config') and pbd['device_config'].has_key('target'):
+ if pbd['device_config']['target'] in csl_targets_fetched:
+ continue
sr = session.xenapi.SR.get_record(pbd['SR'])
if sr.has_key('type') and sr['type'] == 'cslg':
if sr['shared'] and pbd['host'] != this_host and not i_am_master:
server += ':' + dev_cfg['port']
if dev_cfg.has_key('username'):
server += ',' + dev_cfg['username']
- if dev_cfg.has_key('password_transformed'):
- server += ',' + _untransform_string(dev_cfg['password_transformed'])
+ if dev_cfg.has_key('password_secret'):
+ sec_ref = session.xenapi.secret.get_by_uuid(dev_cfg['password_secret'])
+ server += ',' + session.xenapi.secret.get_value(sec_ref)
procs.append(ProcOutput([CSL, server, 'srv-log-get'], caps[cap][MAX_TIME], output))
+ csl_targets_fetched.append(dev_cfg['target'])
session.xenapi.session.logout()
output += "%s: %s\n" % (k, str(fd_dict[k]))
return output
+def dump_rdac_groups(cap):
+ output = StringIO.StringIO()
+ procs = [ProcOutput([MPPUTIL, '-a'], caps[cap][MAX_TIME], output)]
+
+ run_procs([procs])
+
+ if not procs[0].timed_out:
+ proc_line = 0
+ for line in output.getvalue().splitlines():
+ if line.startswith('ID'):
+ proc_line = 2
+ elif line.startswith('----'):
+ proc_line -= 1
+ elif proc_line > 0:
+ group, _ = line.split(None, 1)
+ cmd_output(cap, [MPPUTIL, '-g', group])
+
def load_plugins(just_capabilities = False):
def getText(nodelist):
rc = ""
if v.has_key('output'):
zf.writestr(dest, v['output'].getvalue())
- else:
+ elif v.has_key('filename'):
if os.stat(v['filename']).st_size < 50:
compress_type = zipfile.ZIP_STORED
else: