mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-06-13 09:50:19 +00:00
Merge branch 'master' into rspconfig_gard_passwd
This commit is contained in:
@ -108,7 +108,7 @@ For system x machine, on sles10 set the crashkernelsize attribute like this: ::
|
||||
|
||||
chdef -t osimage <image name> crashkernelsize=<size>M@16M
|
||||
|
||||
On sles11 and rhels6 set the crashkernelsize attribute like this: ::
|
||||
On sles11, rhels6 and above set the crashkernelsize attribute like this: ::
|
||||
|
||||
chdef -t osimage <image name> crashkernelsize=<size>M
|
||||
|
||||
@ -118,13 +118,21 @@ Where <size> recommended value is 256. For more information about the size can r
|
||||
`<http://www.novell.com/support/kb/doc.php?id=3374462>`_.
|
||||
|
||||
`<https://access.redhat.com/knowledge/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/s2-kdump-configuration-cli.html>`_.
|
||||
|
||||
`<https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/kernel_crash_dump_guide/sect-kdump-config-cli>`_.
|
||||
|
||||
For system p machine, set the crashkernelsize attribute to this: ::
|
||||
|
||||
chdef -t osimage <image name> crashkernelsize=<size>@32M
|
||||
|
||||
For Power System AC922, set the crashkernelsize attribute to this: ::
|
||||
|
||||
chdef -t osimage <image name> crashkernelsize=<size>M
|
||||
|
||||
Where <size> recommended value is 256, more information can refer the kdump document for the system x.
|
||||
|
||||
**Notes**: The ``crashkernel=`` option can be defined in multiple ways. If it is hard to decide the specific crashkernelsize, auto value can be used, the auto value enables automatic configuration of reserved memory based on the total amount of memory in the system like ``crashkernel=auto``.
|
||||
|
||||
When your node starts, and you get a kdump start error like this: ::
|
||||
|
||||
Your running kernel is using more than 70% of the amount of space you reserved for kdump, you should consider increasing your crashkernel
|
||||
|
41
xCAT-openbmc-py/lib/python/agent/hwctl/eventlog.py
Normal file
41
xCAT-openbmc-py/lib/python/agent/hwctl/eventlog.py
Normal file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
###############################################################################
|
||||
# IBM(c) 2018 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
###############################################################################
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
class EventlogInterface(object):
|
||||
"""Interface for eventlog-related actions."""
|
||||
interface_type = 'eventlog'
|
||||
version = '1.0'
|
||||
|
||||
def get_eventlog_info(self, task, number_of_records="all"):
|
||||
"""Return the eventlog info of the task's nodes.
|
||||
|
||||
:param number_of_records: number of records to display.
|
||||
:param task: a Task instance containing the nodes to act on.
|
||||
:return eventlog list
|
||||
"""
|
||||
return task.run('get_ev_info', number_of_records)
|
||||
|
||||
def clear_all_eventlog_records(self, task):
|
||||
"""Clear all eventlog records.
|
||||
|
||||
:param task: a Task instance containing the nodes to act on.
|
||||
:return
|
||||
"""
|
||||
return task.run('clear_all_ev_records')
|
||||
|
||||
def resolve_eventlog_records(self, task, resolve_list="LED"):
|
||||
"""Return the eventlog info of the task's nodes.
|
||||
|
||||
:param resolve: list of eventlog ids to resolve or LED label.
|
||||
:param task: a Task instance containing the nodes to act on.
|
||||
:return eventlog list of resolved entries
|
||||
"""
|
||||
return task.run('resolve_ev_records', resolve_list)
|
||||
|
||||
class DefaultEventlogManager(EventlogInterface):
|
||||
"""Interface for eventlog-related actions."""
|
||||
pass
|
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python
|
||||
###############################################################################
|
||||
# IBM(c) 2018 EPL license http://www.eclipse.org/legal/epl-v10.html
|
||||
###############################################################################
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import gevent
|
||||
import time
|
||||
|
||||
from common.task import ParallelNodesCommand
|
||||
from common.exceptions import SelfClientException, SelfServerException
|
||||
from hwctl import openbmc_client as openbmc
|
||||
from common import utils
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger('xcatagent')
|
||||
|
||||
class OpenBMCEventlogTask(ParallelNodesCommand):
|
||||
"""Executor for eventlog-related actions."""
|
||||
|
||||
def get_ev_info(self, num_to_display, **kw):
|
||||
|
||||
node = kw['node']
|
||||
number_to_display = 0
|
||||
try:
|
||||
# Number of records to display from the end
|
||||
number_to_display = 0-int(num_to_display[0])
|
||||
except Exception:
|
||||
# All records to display
|
||||
number_to_display = 0
|
||||
|
||||
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback, debugmode=self.debugmode, verbose=self.verbose)
|
||||
eventlog_info = []
|
||||
try:
|
||||
obmc.login()
|
||||
|
||||
# Get all eventlog records
|
||||
eventlog_info_dict = obmc.get_eventlog_info()
|
||||
|
||||
keys = eventlog_info_dict.keys()
|
||||
# Sort thy keys in natural order
|
||||
keys.sort(key=lambda x : int(x[0:]))
|
||||
|
||||
# Display all, or specified number of records from the end
|
||||
for key in list(keys)[number_to_display:]:
|
||||
self.callback.info('%s: %s' % (node, eventlog_info_dict[key]))
|
||||
eventlog_info += eventlog_info_dict[key]
|
||||
|
||||
except (SelfServerException, SelfClientException) as e:
|
||||
self.callback.info('%s: %s' % (node, e.message))
|
||||
|
||||
return eventlog_info
|
||||
|
||||
def clear_all_ev_records(self, **kw):
|
||||
|
||||
node = kw['node']
|
||||
|
||||
def resolve_ev_records(self, resolve_list, **kw):
|
||||
|
||||
node = kw['node']
|
@ -5,6 +5,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
import os
|
||||
import requests
|
||||
import json
|
||||
import time
|
||||
@ -218,6 +219,11 @@ RSPCONFIG_APIS = {
|
||||
},
|
||||
}
|
||||
|
||||
EVENTLOG_URL = "/logging/enumerate"
|
||||
RAS_POLICY_TABLE = "/opt/ibm/ras/lib/policyTable.json"
|
||||
RAS_POLICY_MSG = "Install the OpenBMC RAS package to obtain more details logging messages."
|
||||
RAS_NOT_FOUND_MSG = " Not found in policy table: "
|
||||
|
||||
RESULT_OK = 'ok'
|
||||
RESULT_FAIL = 'fail'
|
||||
|
||||
@ -550,6 +556,99 @@ class OpenBMCRest(object):
|
||||
|
||||
return bool(func_list), fw_dict
|
||||
|
||||
# Extract all eventlog info and parse it
|
||||
def get_eventlog_info(self):
|
||||
|
||||
eventlog_data = self.request('GET', EVENTLOG_URL, cmd='get_eventlog_info')
|
||||
|
||||
return self.parse_eventlog_data(eventlog_data)
|
||||
|
||||
# Parse eventlog data and build a dictionary with eventid as a key
|
||||
def parse_eventlog_data(self, eventlog_data):
|
||||
|
||||
# Check if policy table file is there
|
||||
ras_event_mapping = {}
|
||||
if os.path.isfile(RAS_POLICY_TABLE):
|
||||
with open(RAS_POLICY_TABLE, "r") as data_file:
|
||||
policy_hash = json.load(data_file)
|
||||
if policy_hash:
|
||||
ras_event_mapping = policy_hash['events']
|
||||
else:
|
||||
self.messager.info(RAS_POLICY_MSG)
|
||||
data_file.close()
|
||||
else:
|
||||
self.messager.info(RAS_POLICY_MSG)
|
||||
try:
|
||||
eventlog_dict = {}
|
||||
for key, value in sorted(eventlog_data.items()):
|
||||
id, event_log_line = self.parse_eventlog_data_record(value, ras_event_mapping)
|
||||
if int(id) != 0:
|
||||
eventlog_dict[str(id)] = event_log_line
|
||||
return eventlog_dict
|
||||
except KeyError:
|
||||
error = 'Error: Received wrong format response: %s' % eventlog_data
|
||||
raise SelfServerException(error)
|
||||
|
||||
# Parse a single eventlog entry and return data in formatted string
|
||||
def parse_eventlog_data_record(self, event_log_entry, ras_event_mapping):
|
||||
formatted_line = ""
|
||||
callout_data = ""
|
||||
LED_tag = " [LED]"
|
||||
timestamp_str = ""
|
||||
message_str = ""
|
||||
pid_str = ""
|
||||
resolved_str = ""
|
||||
id_str = "0"
|
||||
callout = False
|
||||
for (sub_key, v) in event_log_entry.items():
|
||||
if sub_key == 'AdditionalData':
|
||||
for (data_key) in v:
|
||||
additional_data = data_key.split("=");
|
||||
if additional_data[0] == 'ESEL':
|
||||
esel = additional_data[1]
|
||||
# Placeholder, not currently used
|
||||
elif additional_data[0] == '_PID':
|
||||
pid_str = "PID: " + str(additional_data[1]) + "),"
|
||||
elif 'CALLOUT_DEVICE_PATH' in additional_data[0]:
|
||||
callout = True
|
||||
callout_data = "I2C"
|
||||
elif 'CALLOUT_INVENTORY_PATH' in additional_data[0]:
|
||||
callout = True
|
||||
callout_data = additional_data[1]
|
||||
elif 'CALLOUT' in additional_data[0]:
|
||||
callout = True
|
||||
elif 'GPU' in additional_data[0]:
|
||||
callout_data="/xyz/openbmc_project/inventory/system/chassis/motherboard/gpu"
|
||||
elif 'PROCEDURE' in additional_data[0]:
|
||||
callout_data = '{:x}'.format(int(additional_data[1])) #Convert to hext
|
||||
elif sub_key == 'Timestamp':
|
||||
timestamp = time.localtime(v / 1000)
|
||||
timestamp_str = time.strftime("%m/%d/%Y %T", timestamp)
|
||||
elif sub_key == 'Id':
|
||||
id_str = str(v)
|
||||
elif sub_key == 'Resolved':
|
||||
resolved_str = " Resolved: " + str(v)
|
||||
elif sub_key == 'Message':
|
||||
message_str = v
|
||||
if callout_data:
|
||||
message_str += "||" + callout_data
|
||||
|
||||
# If event data mapping was read in from RAS policy table, display a more detailed message
|
||||
if ras_event_mapping:
|
||||
if message_str in ras_event_mapping:
|
||||
event_type = ras_event_mapping[message_str]['EventType']
|
||||
event_message = ras_event_mapping[message_str]['Message']
|
||||
severity = ras_event_mapping[message_str]['Severity']
|
||||
affect = ras_event_mapping[message_str]['AffectedSubsystem']
|
||||
formatted_line = timestamp_str + " [" + id_str +"]" + ": " + event_type + ", " + "(" + severity + ") " + event_message + " (AffectedSubsystem: " + affect + ", " + pid_str + resolved_str
|
||||
else:
|
||||
formatted_line = timestamp_str + " [" + id_str +"]" + ":" + RAS_NOT_FOUND_MSG + message_str + " (" + pid_str + resolved_str
|
||||
else:
|
||||
formatted_line = timestamp_str + " [" + id_str +"]" + ": " + message_str + " (" + pid_str + resolved_str
|
||||
if callout:
|
||||
formatted_line += LED_tag
|
||||
return id_str, formatted_line
|
||||
|
||||
def set_apis_values(self, key, value):
|
||||
attr_info = RSPCONFIG_APIS[key]
|
||||
if 'set_url' not in attr_info:
|
||||
|
@ -20,12 +20,14 @@ from hwctl.executor.openbmc_inventory import OpenBMCInventoryTask
|
||||
from hwctl.executor.openbmc_power import OpenBMCPowerTask
|
||||
from hwctl.executor.openbmc_sensor import OpenBMCSensorTask
|
||||
from hwctl.executor.openbmc_bmcconfig import OpenBMCBmcConfigTask
|
||||
from hwctl.executor.openbmc_eventlog import OpenBMCEventlogTask
|
||||
from hwctl.beacon import DefaultBeaconManager
|
||||
from hwctl.setboot import DefaultBootManager
|
||||
from hwctl.inventory import DefaultInventoryManager
|
||||
from hwctl.power import DefaultPowerManager
|
||||
from hwctl.sensor import DefaultSensorManager
|
||||
from hwctl.bmcconfig import DefaultBmcConfigManager
|
||||
from hwctl.eventlog import DefaultEventlogManager
|
||||
|
||||
from xcatagent import base
|
||||
import openbmc_rest
|
||||
@ -146,6 +148,9 @@ SETBOOT_SET_OPTIONS = ('cd', 'def', 'default', 'hd', 'net')
|
||||
VITALS_OPTIONS = ('all', 'altitude', 'fanspeed', 'leds', 'power',
|
||||
'temp', 'voltage', 'wattage')
|
||||
|
||||
# global variables of reventlog
|
||||
EVENTLOG_OPTIONS = ('list', 'clear', 'resolved')
|
||||
|
||||
class OpenBMC(base.BaseDriver):
|
||||
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
@ -835,6 +840,50 @@ class OpenBMCManager(base.BaseManager):
|
||||
else:
|
||||
DefaultSensorManager().get_sensor_info(runner, action)
|
||||
|
||||
def reventlog(self, nodesinfo, args):
|
||||
|
||||
# 1, parse agrs
|
||||
if not args:
|
||||
args = ['all']
|
||||
|
||||
reventlog_usage = """
|
||||
Usage:
|
||||
reventlog [-V|--verbose] resolved <id_list>
|
||||
reventlog [-V|--verbose] clear
|
||||
reventlog [-V|--verbose] list <number_of_records>
|
||||
|
||||
Options:
|
||||
-V --verbose eventlog verbose mode.
|
||||
"""
|
||||
|
||||
try:
|
||||
opts = docopt(reventlog_usage, argv=args)
|
||||
|
||||
self.verbose = opts.pop('--verbose')
|
||||
action = [k for k,v in opts.items() if v][0]
|
||||
except Exception as e:
|
||||
self.messager.error("Failed to parse arguments for reventlog: %s" % args)
|
||||
return
|
||||
|
||||
# 2, validate the args
|
||||
if action not in EVENTLOG_OPTIONS:
|
||||
self.messager.error("Not supported subcommand for reventlog: %s" % action)
|
||||
return
|
||||
|
||||
# 3, run the subcommands
|
||||
runner = OpenBMCEventlogTask(nodesinfo, callback=self.messager, debugmode=self.debugmode, verbose=self.verbose)
|
||||
self.messager.info('revetlog.py processing action=%s args=%s' % (action, args))
|
||||
if action == 'clear':
|
||||
DefaultEventlogManager().clear_all_eventlog_records(runner)
|
||||
elif action == 'resolved':
|
||||
eventlog_id_list = opts.pop('<id_list>')
|
||||
DefaultEventlogManager().resolve_eventlog_records(runner, eventlog_id_list)
|
||||
elif action == 'list':
|
||||
eventlog_number_of_records = opts.pop('<number_of_records>')
|
||||
DefaultEventlogManager().get_eventlog_info(runner, eventlog_number_of_records)
|
||||
else:
|
||||
DefaultEventlogManager().get_eventlog_info(runner, "all")
|
||||
|
||||
def _get_full_path(self,file_path):
|
||||
if type(self.cwd) == 'unicode':
|
||||
dir_path = self.cwd
|
||||
|
@ -94,8 +94,9 @@ class Server(object):
|
||||
func = getattr(manager, req['command'])
|
||||
# translate unicode string to normal string to avoid docopt error
|
||||
new_args=[]
|
||||
for a in req['args']:
|
||||
new_args.append(a.encode('utf-8'))
|
||||
if req['args']:
|
||||
for a in req['args']:
|
||||
new_args.append(a.encode('utf-8'))
|
||||
# call the function in the specified manager
|
||||
func(req['nodeinfo'], new_args)
|
||||
# after the method returns, the request should be handled
|
||||
|
@ -59,6 +59,7 @@ my $dhcpconffile = $^O eq 'aix' ? '/etc/dhcpsd.cnf' : '/etc/dhcpd.conf';
|
||||
my %dynamicranges; #track dynamic ranges defined to see if a host that resolves is actually a dynamic address
|
||||
my %netcfgs;
|
||||
my $distro = xCAT::Utils->osver();
|
||||
my $checkdomain=0;
|
||||
|
||||
# dhcp 4.x will use /etc/dhcp/dhcpd.conf as the config file
|
||||
my $dhcp6conffile;
|
||||
@ -1931,6 +1932,14 @@ sub process_request
|
||||
addnet($line[0], $line[2]);
|
||||
}
|
||||
}
|
||||
if ($checkdomain)
|
||||
{
|
||||
$callback->({ error => [ "above error fail to generate new dhcp configuration file, restore dhcp configuration file $dhcpconffile" ], errorcode => [1] });
|
||||
my $backupfile = $dhcpconffile.".xcatbak";
|
||||
rename("$backupfile", $dhcpconffile);
|
||||
xCAT::MsgUtils->trace($verbose_on_off, "d", "dhcp: Restore dhcp configuration file to $dhcpconffile");
|
||||
exit 1;
|
||||
}
|
||||
foreach (@nrn6) { #do the ipv6 networks
|
||||
addnet6($_); #already did all the filtering before putting into nrn6
|
||||
}
|
||||
@ -2440,10 +2449,12 @@ sub addnet
|
||||
} else {
|
||||
$callback->(
|
||||
{
|
||||
warning => [
|
||||
"No $net specific entry for domain, and no domain defined in site table."
|
||||
]
|
||||
error => [
|
||||
"No domain defined for $net entry in networks table, and no domain defined in site table."
|
||||
],
|
||||
errorcode => [1]
|
||||
});
|
||||
$checkdomain=1;
|
||||
}
|
||||
|
||||
if ($ent and $ent->{nameservers})
|
||||
|
@ -38,9 +38,14 @@ sub handled_commands {
|
||||
rsetboot => 'nodehm:mgt=openbmc',
|
||||
rvitals => 'nodehm:mgt=openbmc',
|
||||
rspconfig => 'nodehm:mgt=openbmc',
|
||||
reventlog => 'nodehm:mgt=openbmc',
|
||||
};
|
||||
}
|
||||
|
||||
# Common logging messages:
|
||||
my $usage_errormsg = "Usage error.";
|
||||
my $reventlog_no_id_resolved_errormsg = "Provide a comma separated list of IDs to be resolved. Example: 'resolved=x,y,z'";
|
||||
|
||||
my %node_info = ();
|
||||
my $callback;
|
||||
|
||||
@ -255,6 +260,26 @@ sub parse_args {
|
||||
}
|
||||
} elsif ($command eq 'rspconfig') {
|
||||
xCAT_plugin::openbmc::parse_args('rspconfig', $extrargs, $noderange);
|
||||
} elsif ($command eq "reventlog") {
|
||||
$subcommand = "all" if (!defined($ARGV[0]));
|
||||
if ($subcommand =~ /^resolved=(.*)/) {
|
||||
my $value = $1;
|
||||
if (not $value) {
|
||||
return ([ 1, "$usage_errormsg $reventlog_no_id_resolved_errormsg" ]);
|
||||
}
|
||||
|
||||
my $nodes_num = @$noderange;
|
||||
if (@$noderange > 1) {
|
||||
return ([ 1, "Resolving faults over a xCAT noderange is not recommended." ]);
|
||||
}
|
||||
|
||||
xCAT::SvrUtils::sendmsg("Attempting to resolve the following log entries: $value...", $callback);
|
||||
} elsif ($subcommand !~ /^\d+$|^all$|^clear$/) {
|
||||
if ($subcommand =~ "resolved") {
|
||||
return ([ 1, "$usage_errormsg $reventlog_no_id_resolved_errormsg" ]);
|
||||
}
|
||||
return ([ 1, "Unsupported command: $command $subcommand" ]);
|
||||
}
|
||||
} else {
|
||||
return ([ 1, "Unsupported command: $command" ]);
|
||||
}
|
||||
@ -358,6 +383,24 @@ sub refactor_args {
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($command eq "reventlog") {
|
||||
if (!defined($extrargs->[0])) {
|
||||
# If no parameters are passed, default to list all records
|
||||
$request->{arg} = ["list","all"];
|
||||
}
|
||||
else {
|
||||
$subcommand = $extrargs->[0];
|
||||
}
|
||||
if ($subcommand =~ /^\d+$/) {
|
||||
unshift @$extrargs, "list";
|
||||
}
|
||||
elsif ($subcommand =~/^resolved=(.*)/) {
|
||||
unshift @$extrargs, "resolved";
|
||||
}
|
||||
elsif ($subcommand =~/^all$/) {
|
||||
unshift @$extrargs, "list";
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ end
|
||||
start:reventlog_all
|
||||
cmd:reventlog $$CN all
|
||||
check:rc==0
|
||||
check:output=~$$CN\s*:\s*.*\d\d/\d\d/\d\d\s*\S+
|
||||
check:output=~$$CN\s*:\s*.*\d\d/\d\d/\d\d\s*\S+|No attributes returned from the BMC
|
||||
end
|
||||
|
||||
start:reventlog_clear
|
||||
@ -19,7 +19,7 @@ end
|
||||
start:reventlog_numofentries
|
||||
cmd:reventlog $$CN 5
|
||||
check:rc==0
|
||||
check:output=~$$CN\s*:\s*.*\d\d/\d\d/\d\d\s*\S+|$$CN: no SEL entries|Entry
|
||||
check:output=~$$CN\s*:\s*.*\d\d/\d\d/\d\d\s*\S+|$$CN: no SEL entries|Entry|No attributes returned from the BMC
|
||||
end
|
||||
|
||||
start:reventlog_s_openbmc
|
||||
|
@ -269,7 +269,9 @@ cmd:mkdir -p /tmp/rspconfig_set_hostname_equal_star_with_bmc_is_hostname
|
||||
check:rc == 0
|
||||
cmd:lsdef $$CN -z > /tmp/rspconfig_set_hostname_equal_star_with_bmc_is_hostname/$$CN.stanza
|
||||
check:rc == 0
|
||||
cmd:chdef -t node -o bogus_bmc_hostname groups=bmc ip=10.6.17.100
|
||||
cmd:chdef -t node -o bogus_bmc_hostname groups=bmc ip=__GETNODEATTR($$CN,bmc)__
|
||||
check:rc == 0
|
||||
cmd:lsdef bogus_bmc_hostname
|
||||
check:rc == 0
|
||||
cmd:makehosts bogus_bmc_hostname
|
||||
check:rc == 0
|
||||
|
Reference in New Issue
Block a user