summaryrefslogtreecommitdiff
path: root/pyipmi/commands
diff options
context:
space:
mode:
Diffstat (limited to 'pyipmi/commands')
-rw-r--r--pyipmi/commands/__init__.py89
-rw-r--r--pyipmi/commands/bmc.py152
-rw-r--r--pyipmi/commands/bootdev.py80
-rw-r--r--pyipmi/commands/bootparam.py66
-rw-r--r--pyipmi/commands/channel.py201
-rw-r--r--pyipmi/commands/chassis.py80
-rw-r--r--pyipmi/commands/data.py125
-rw-r--r--pyipmi/commands/dcmi.py337
-rw-r--r--pyipmi/commands/event.py79
-rw-r--r--pyipmi/commands/fabric.py306
-rw-r--r--pyipmi/commands/fabric_config.py288
-rw-r--r--pyipmi/commands/freeipmi_pef.py211
-rw-r--r--pyipmi/commands/fru.py132
-rw-r--r--pyipmi/commands/fw.py400
-rw-r--r--pyipmi/commands/info.py92
-rw-r--r--pyipmi/commands/lan.py127
-rw-r--r--pyipmi/commands/mc.py69
-rw-r--r--pyipmi/commands/payload.py65
-rw-r--r--pyipmi/commands/pef.py130
-rw-r--r--pyipmi/commands/pet.py55
-rw-r--r--pyipmi/commands/sdr.py110
-rw-r--r--pyipmi/commands/sel.py229
-rw-r--r--pyipmi/commands/sol.py207
-rw-r--r--pyipmi/commands/user.py163
-rw-r--r--pyipmi/commands/watchdog.py92
25 files changed, 3885 insertions, 0 deletions
diff --git a/pyipmi/commands/__init__.py b/pyipmi/commands/__init__.py
new file mode 100644
index 0000000..380aaf6
--- /dev/null
+++ b/pyipmi/commands/__init__.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""IPMI commands that are implemented
+
+These don't always map directly to IPMI requests, although sometimes
+they do. Sometimes, they map to higher level commands provided by
+ipmitool. It's more convenient (and closer to real world use) to use
+these higher level commands than to break stuff down.
+"""
+from chassis import chassis_commands
+from bmc import bmc_commands
+from sdr import sdr_commands
+from fw import fw_commands
+from sel import sel_commands
+from sol import sol_commands
+from payload import payload_commands
+from dcmi import dcmi_commands
+from pef import pef_commands
+from freeipmi_pef import freeipmi_pef_commands
+from pet import pet_commands
+from event import event_commands
+from watchdog import watchdog_commands
+from fru import fru_commands
+from lan import lan_commands
+from channel import channel_commands
+from user import user_commands
+from fabric import fabric_commands
+from fabric_config import fabric_config_commands
+from bootdev import bootdev_commands
+from bootparam import bootparam_commands
+from mc import mc_commands
+from data import data_commands
+from info import info_commands
+
+ipmi_commands = {}
+
+ipmi_commands.update(bmc_commands)
+ipmi_commands.update(chassis_commands)
+ipmi_commands.update(sdr_commands)
+ipmi_commands.update(fw_commands)
+ipmi_commands.update(sel_commands)
+ipmi_commands.update(sol_commands)
+ipmi_commands.update(payload_commands)
+ipmi_commands.update(dcmi_commands)
+ipmi_commands.update(pef_commands)
+ipmi_commands.update(freeipmi_pef_commands)
+ipmi_commands.update(pet_commands)
+ipmi_commands.update(event_commands)
+ipmi_commands.update(watchdog_commands)
+ipmi_commands.update(fru_commands)
+ipmi_commands.update(lan_commands)
+ipmi_commands.update(channel_commands)
+ipmi_commands.update(user_commands)
+ipmi_commands.update(fabric_commands)
+ipmi_commands.update(fabric_config_commands)
+ipmi_commands.update(bootdev_commands)
+ipmi_commands.update(bootparam_commands)
+ipmi_commands.update(mc_commands)
+ipmi_commands.update(data_commands)
+ipmi_commands.update(info_commands)
diff --git a/pyipmi/commands/bmc.py b/pyipmi/commands/bmc.py
new file mode 100644
index 0000000..3a91569
--- /dev/null
+++ b/pyipmi/commands/bmc.py
@@ -0,0 +1,152 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""BMC related commands"""
+
+from .. import Command
+from .. bmc import BMCInfo, BMCGuid, BMCEnables, BMCResult, BMCResetResult
+from pyipmi.tools.responseparser import ResponseParserMixIn, str2bool
+
+class GetDeviceIdCommand(Command, ResponseParserMixIn):
+ """Describes the get_device_id IPMI command
+
+ This is "bmc info" to ipmitool
+ """
+ name = "Get Device ID"
+ result_type = BMCInfo
+
+ response_fields = {
+ "Device ID" : {},
+ "Device Revision" : {},
+ "Firmware Revision" : {},
+ "IPMI Version" : {},
+ "Manufacturer ID" : {},
+ "Product ID" : { "parser" : lambda s: s.split(' ')[0] },
+ "Device Available" : { "parser" : str2bool }
+ }
+
+ ipmitool_args = ["bmc", "info"]
+
+
+class BMCSelfTestCommand(Command, ResponseParserMixIn):
+ """Describes the get self test results IPMI command
+
+ This is "bmc selftest" to ipmitool
+ """
+ name = "BMC Self Test"
+ result_type = BMCResult
+
+ response_fields = {
+ "Selftest" : { }
+ }
+
+ ipmitool_args = ["bmc", "selftest"]
+
+
+class GetSystemGuidCommand(Command, ResponseParserMixIn):
+ """Describes the get_system_guid IPMI command
+
+ This is "bmc guid" to ipmitool
+ """
+ name = "Get System GUID"
+ result_type = BMCGuid
+
+ response_fields = {
+ "System GUID" : {}
+ }
+
+ ipmitool_args = ["bmc", "guid"]
+
+class GetCommandEnables(Command, ResponseParserMixIn):
+ """The Get Command Enables command
+
+ In ipmitool world, this is "bmc getenables"
+ """
+ name = 'Get Command Enables'
+ result_type = BMCEnables
+
+ response_fields = {
+ 'Receive Message Queue Interrupt' : {
+ 'attr' : 'recv_msg_intr',
+ 'parser' : str2bool
+ },
+ 'Event Message Buffer Full Interrupt' : {
+ 'attr' : 'event_msg_intr',
+ 'parser' : str2bool
+ },
+ 'Event Message Buffer' : {
+ 'attr' : 'event_msg',
+ 'parser' : str2bool
+ },
+ 'System Event Logging' : {
+ 'attr' : 'system_event_log',
+ 'parser' : str2bool
+ },
+ 'OEM 0' : {
+ 'attr' : 'oem0',
+ 'parser' : str2bool
+ },
+ 'OEM 1' : {
+ 'attr' : 'oem1',
+ 'parser' : str2bool
+ },
+ 'OEM 2' : {
+ 'attr' : 'oem2',
+ 'parser' : str2bool
+ }
+ }
+
+ ipmitool_args = ['bmc', 'getenables']
+
+
+class BMCResetCommand(Command, ResponseParserMixIn):
+ """The Get Command Enables command
+
+ In ipmitool world, this is "bmc reset [warm|cold]"
+ """
+ name = 'BMC Reset'
+ result_type = BMCResetResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ['bmc', 'reset', self._params['type']]
+
+
+bmc_commands = {
+ 'get_device_id' : GetDeviceIdCommand,
+ 'get_system_guid' : GetSystemGuidCommand,
+ 'get_command_enables' : GetCommandEnables,
+ 'selftest' : BMCSelfTestCommand,
+ 'bmc_reset' : BMCResetCommand
+}
diff --git a/pyipmi/commands/bootdev.py b/pyipmi/commands/bootdev.py
new file mode 100644
index 0000000..3be6b45
--- /dev/null
+++ b/pyipmi/commands/bootdev.py
@@ -0,0 +1,80 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+from .. import Command
+from pyipmi.tools.responseparser import ResponseParserMixIn
+from pyipmi.bootdev import *
+from pyipmi.commands.bootparam import *
+
+class BootDevSetCommand(Command, ResponseParserMixIn):
+ """ Set Boot Device using ipmitool chassis bootdev """
+
+ name = "Set Boot Device"
+ result_type = BootDevSetResult
+
+ response_fields = {
+ 'Boot Device' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ if self._params['options'] != None:
+ options = "options=" + str(self._params['options'])
+ return ["chassis", "bootdev", self._params['device'],options]
+ return ["chassis", "bootdev", self._params['device']]
+
+class BootDevGetCommand(Command, ResponseParserMixIn):
+ """ Get Boot Device using ipmitool chassis bootdev """
+
+ name = "Get Boot Device"
+ result_type = BootDevGetResult
+ """ parse the output into a nice harsh"""
+
+ def parse_response(self, out, err):
+ """ Use bootParam parse method to do the job of parsing output into a nice harsh """
+ boot_param = BootParamGetCommand(self._tool)
+ all_info = boot_param.parse_response(out=out,err=err)
+ bool2str = {True:'Yes',False:'No'}
+
+ """ Only interested in Device and Persistent (Y/N)"""
+ device = all_info['Boot Device Selector']
+ persistent = (all_info['Options apply'] == 'all future boots')
+ return {'device':device, 'persistent':bool2str[persistent]}
+
+ """Get 5 from bootparam provides the status of bootdev"""
+ @property
+ def ipmitool_args(self):
+ return ["chassis", "bootparam", "get", "5"]
+
+bootdev_commands = {
+ "bootdev_get" : BootDevGetCommand,
+ "bootdev_set" : BootDevSetCommand
+}
diff --git a/pyipmi/commands/bootparam.py b/pyipmi/commands/bootparam.py
new file mode 100644
index 0000000..08612c6
--- /dev/null
+++ b/pyipmi/commands/bootparam.py
@@ -0,0 +1,66 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+from .. import Command
+from pyipmi.tools.responseparser import ResponseParserMixIn
+from pyipmi.bootparam import *
+
+class BootParamGetCommand(Command, ResponseParserMixIn):
+ """ Get Boot Parameters using ipmitool chassis bootparam # """
+
+ name = "Get Boot Device"
+ result_type = BootParamGetResult
+
+ def parse_response(self, out, err):
+ """ Output is a number of lines with some info
+ """
+ result = {}
+ delimiter = [':','is','to']
+ for line in out.strip().split('\n'):
+ key, value = line, ""
+ for x in delimiter:
+ if x in line:
+ info = line.split(x)
+ key, value = info[0], info[1]
+ break
+ key = key.strip(' -')
+ value = value.strip(' -')
+ result[key] = value
+ return result
+
+ """ get #param from bootparam """
+ @property
+ def ipmitool_args(self):
+ return ["chassis", "bootparam", "get",self._params['param']]
+
+bootparam_commands = {
+ "bootparam_get" : BootParamGetCommand
+}
diff --git a/pyipmi/commands/channel.py b/pyipmi/commands/channel.py
new file mode 100644
index 0000000..200e193
--- /dev/null
+++ b/pyipmi/commands/channel.py
@@ -0,0 +1,201 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""channel related commands"""
+
+from .. import Command
+from pyipmi.channel import *
+from pyipmi.tools.responseparser import ResponseParserMixIn
+import re
+
+
+class ChannelInfoCommand(Command, ResponseParserMixIn):
+ """Describes the get channel info IPMI command
+
+ This is "channel info" to ipmitool
+ """
+
+ def parse_response(self, out, err):
+ """ Strip out extraneous colons to allow more generic parsing
+ """
+ out_list = map(lambda x: x.strip(), out.split('\n'))
+ new_out_list = []
+
+ setting_prefix = 'Active'
+ for line in out_list:
+ m = re.match("Channel 0x([0-9a-fA-F]+) info:", line)
+ if m:
+ line = "Channel : %s" % m.group(1)
+
+ m = re.match("(Alerting|Per-message Auth|User Level Auth|Access Mode)\s+:\s+(\S+)", line)
+ if m:
+ line = "%s %s : %s" % (setting_prefix, m.group(1), m.group(2))
+
+ m = re.match("Volatile\(active\) Settings", line)
+ if m:
+ setting_prefix = 'Active'
+ continue
+
+ m = re.match("Non-Volatile Settings", line)
+ if m:
+ setting_prefix = 'NV'
+ continue
+
+ new_out_list.append(line)
+
+ new_out = '\n'.join(new_out_list)
+ return self.response_parser(new_out, err)
+
+ name = "Channel Info"
+ result_type = ChannelInfoResult
+
+ response_fields = {
+ 'Channel' : {},
+ 'Channel Medium Type' : {},
+ 'Channel Protocol Type' : {},
+ 'Session Support' : {},
+ 'Active Session Count' : {},
+ 'Protocol Vendor ID' : {},
+ 'Active Alerting' : {},
+ 'Active Per-message Auth' : {},
+ 'Active User Level Auth' : {},
+ 'Active Access Mode' : {},
+ 'NV Alerting' : {},
+ 'NV Per-message Auth' : {},
+ 'NV User Level Auth' : {},
+ 'NV Access Mode' : {}
+ }
+
+ ipmitool_args = ["channel", "info"]
+
+
+class ChannelGetAccessCommand(Command, ResponseParserMixIn):
+ """Describes the get channel access IPMI command
+
+ This is "channel getaccess" to ipmitool
+ """
+
+ response_parser = ResponseParserMixIn.parse_colon_record_list
+
+ name = "Channel Get Access"
+ result_type = ChannelGetAccessResult
+
+ response_fields = {
+ 'Maximum User IDs' : {},
+ 'Enabled User IDs' : {},
+ 'User ID' : {},
+ 'User Name' : {},
+ 'Fixed Name' : {},
+ 'Access Available' : {},
+ 'Link Authentication' : {},
+ 'IPMI Messaging' : {},
+ 'Privilege Level' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["channel", "getaccess", self._params['channel'],
+ self._params['userid']]
+
+
+class ChannelSetAccessCommand(Command, ResponseParserMixIn):
+ """Describes the set channel access IPMI command
+
+ This is "channel setaccess" to ipmitool
+ """
+
+ name = "Channel Set Access"
+ result_type = ChannelSetAccessResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ callin = ipmi = link = priv_level = ""
+
+ if self._params.get('callin'):
+ callin = "callin=%s" % self._params.get('callin')
+ if self._params.get('ipmi'):
+ ipmi = "ipmi=%s" % self._params.get('ipmi')
+ if self._params.get('link'):
+ link = "link=%s" % self._params.get('link')
+ if self._params.get('priv_level'):
+ priv_level = "privilege=%s" % self._params.get('priv_level')
+
+ return ["channel", "setaccess", self._params['channel'],
+ self._params['userid'], callin, ipmi, link, priv_level]
+
+
+class ChannelGetCiphersCommand(Command, ResponseParserMixIn):
+ """Describes the get channel cipher suites IPMI command
+
+ This is "channel getciphers <ipmi | sol>" to ipmitool
+ """
+
+ def parse_response(self, out, err):
+ """ Strip out extraneous colons to allow more generic parsing
+ """
+ out.strip()
+ output_list = map(lambda x: x.strip(), out.split('\n'))
+ result = {}
+
+ for line in output_list:
+ if line == '':
+ continue
+ line_list = map(lambda x: x.strip(), line.split())
+ if line_list[0] == 'ID':
+ continue
+ suite = line_list[0]
+ result[suite] = ChannelGetCiphersResult()
+ result[suite].iana = line_list[1]
+ result[suite].auth_alg = line_list[2]
+ result[suite].integrity_alg = line_list[3]
+ result[suite].confidentiality_alg = line_list[4]
+
+ return result
+
+ name = "Channel Get Cipher Suites"
+ result_type = ChannelGetCiphersResult
+
+ @property
+ def ipmitool_args(self):
+ return ["channel", "getciphers", self._params['mode']]
+
+
+channel_commands = {
+ 'channel_info' : ChannelInfoCommand,
+ 'channel_get_access' : ChannelGetAccessCommand,
+ 'channel_set_access' : ChannelSetAccessCommand,
+ 'channel_get_ciphers' : ChannelGetCiphersCommand
+}
diff --git a/pyipmi/commands/chassis.py b/pyipmi/commands/chassis.py
new file mode 100644
index 0000000..1845902
--- /dev/null
+++ b/pyipmi/commands/chassis.py
@@ -0,0 +1,80 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""Chassis related IPMI commands"""
+from .. import Command
+from .. chassis import ChassisStatus
+from pyipmi.tools.responseparser import ResponseParserMixIn, str2bool
+
+class ChassisStatusCommand(Command, ResponseParserMixIn):
+ """Describes the chassis status IPMI command"""
+
+ name = 'Chassis Status'
+
+ ipmitool_args = ['chassis', 'status']
+ result_type = ChassisStatus
+
+ response_fields = {
+ 'System Power' : {'attr' : 'power_on', 'parser' : lambda v: v == 'on'},
+ 'Power Overload' : {'parser' : str2bool},
+ 'Power Interlock' : {},
+ 'Main Power Fault' : {'parser' : str2bool},
+ 'Power Control Fault' : {'parser' : str2bool},
+ 'Power Restore Policy' : {}
+ }
+
+class ChassisControlCommand(Command, ResponseParserMixIn):
+ """Describes the IPMI chassis control command
+
+ ipmitool calls this "chassis power"
+ """
+
+ @property
+ def ipmitool_args(self):
+ """The chassis control command takes a 'mode' parameter
+
+ Look at ipmitool's manpage for more info.
+ """
+ return ['chassis', 'power', self._params['mode']]
+
+class ChassisPolicyCommand(Command, ResponseParserMixIn):
+ """Describes the IPMI chassis policy command"""
+
+ @property
+ def ipmitool_args(self):
+ """The chassis policy command takes a 'state' parameter"""
+ return ['chassis', 'policy', self._params['state']]
+
+chassis_commands = {
+ 'chassis_status' : ChassisStatusCommand,
+ 'chassis_control' : ChassisControlCommand,
+ 'chassis_policy' : ChassisPolicyCommand
+}
diff --git a/pyipmi/commands/data.py b/pyipmi/commands/data.py
new file mode 100644
index 0000000..5fe5b1b
--- /dev/null
+++ b/pyipmi/commands/data.py
@@ -0,0 +1,125 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+from .. import Command
+from pyipmi.tools.responseparser import ResponseParserMixIn
+from pyipmi.data import *
+
+class DataMemReadCommand(Command, ResponseParserMixIn):
+ """ Describes the cxoem data mem read command
+ """
+
+ name = "Read value from memory"
+ result_type = DataMemReadResult
+
+ response_fields = {
+ 'Length' : {},
+ 'Addr' : {},
+ 'Value' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ args = ["cxoem", "data", "mem", "read",
+ self._params['length'], self._params['addr']]
+ if self._params['fmt']:
+ args.append(self._params['fmt'])
+ return args
+
+
+class DataMemWriteCommand(Command, ResponseParserMixIn):
+ """ Describes the cxoem data mem write command
+ """
+
+ name = "Write value to memory"
+ result_type = DataMemWriteResult
+
+ response_fields = {
+ 'Length' : {},
+ 'Addr' : {},
+ 'Value' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["cxoem", "data", "mem", "write", self._params['length'],
+ self._params['addr'], self._params['value']]
+
+
+class DataCDBReadCommand(Command, ResponseParserMixIn):
+ """ Describes the cxoem data cdb read command
+ """
+
+ name = "Read value from CDB"
+ result_type = DataCDBReadResult
+
+ response_fields = {
+ 'Length' : {},
+ 'Cid' : {},
+ 'Data size' : {},
+ 'CID size' : {},
+ 'Value' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ args = ["cxoem", "data", "cdb", "read",
+ self._params['length'], self._params['cid']]
+ if self._params['fmt']:
+ args.append(self._params['fmt'])
+ return args
+
+
+class DataCDBWriteCommand(Command, ResponseParserMixIn):
+ """ Describes the cxoem data cdb write command
+ """
+
+ name = "Write value to CDB"
+ result_type = DataCDBWriteResult
+
+ response_fields = {
+ 'Length' : {},
+ 'Cid' : {},
+ 'Value' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["cxoem", "data", "cdb", "write", self._params['length'],
+ self._params['cid'], self._params['value']]
+
+
+data_commands = {
+ "data_memread" : DataMemReadCommand,
+ "data_memwrite" : DataMemWriteCommand,
+ "data_cdbread" : DataCDBReadCommand,
+ "data_cdbwrite" : DataCDBWriteCommand
+}
diff --git a/pyipmi/commands/dcmi.py b/pyipmi/commands/dcmi.py
new file mode 100644
index 0000000..31c8a8f
--- /dev/null
+++ b/pyipmi/commands/dcmi.py
@@ -0,0 +1,337 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+from .. import Command
+from pyipmi.tools.responseparser import *
+from pyipmi.dcmi import *
+
+class DCMICommandWithErrors(Command, ResponseParserMixIn):
+
+ # TODO: Generalize this to base class? Better way to include
+ # error output in parsing?
+ def parse_response(self, out, err):
+ """Parse the response to a command
+
+ The 'response_format' attribute is used to determine
+ what parser to use to for interpreting the results.
+
+ Arguments:
+ out -- the text response of a command from stdout
+ err -- the text response of a command from stderr
+ """
+
+ out = out + err
+ return self.response_parser(out, err)
+
+class DCMIGetCapabilitiesCommand(DCMICommandWithErrors):
+ """Describes the DCMI get capabilities command
+
+ """
+
+ name = "Get DCMI Capabilities"
+ result_type = DCMIGetCapabilitiesResult
+
+ response_fields = {
+ 'DCMI Specification Conformance' : {},
+ 'Identification Support' : {},
+ 'SEL logging' : {},
+ 'Chassis Power' : {},
+ 'Temperature Monitor' : {},
+ 'Power Management / Monitoring Support' : {},
+ 'In-band System Interface Channel' : {},
+ 'Serial TMODE' : {},
+ 'Out-Of-Band Secondary LAN Channel' : {},
+ 'Out-Of-Band Primary LAN Channel' : {},
+ 'SOL' : {},
+ 'VLAN' : {},
+ 'Number of SEL entries' : {},
+ 'SEL automatic rollover' : {},
+ 'GUID' : {},
+ 'DHCP Host Name' : {},
+ 'Asset Tag' : {},
+ 'Inlet temperature' : {},
+ 'Processors temperature' : {},
+ 'Baseboard temperature' : {},
+ 'Power Management Device Slave Address' : {},
+ 'Power Management Controller Device Revision' : {},
+ 'Power Management Controller Channel Number' : {},
+ 'Primary LAN Out-of-band Channel Number' : {},
+ 'Secondary LAN Out-of-band Channel Number' : {},
+ 'Serial Out-of-band TMODE Capability Channel Number' : {}
+ }
+
+ ipmidcmi_args = ["--get-dcmi-capability-info"]
+
+class DCMISetAssetTagCommand(DCMICommandWithErrors):
+ """Describes the DCMI set asset tag command
+
+ """
+
+ name = "Set DCMI Asset Tag"
+ result_type = DCMISetAssetTagResult
+
+ # No response -- Have to do a get to confirm
+ response_fields = {
+ }
+
+ @property
+ def ipmidcmi_args(self):
+ """
+ """
+ return ["--set-asset-tag", self._params['tag']]
+
+class DCMIGetAssetTagCommand(DCMICommandWithErrors):
+ """Describes the dcmi get asset tag command
+
+ """
+
+ response_parser = ResponseParserMixIn.parse_single_line
+
+ name = "Get DCMI Asset Tag"
+ result_type = DCMIGetAssetTagResult
+
+ response_fields = {
+ 'attr' : 'tag'
+ }
+
+ ipmidcmi_args = ["--get-asset-tag"]
+
+
+class DCMIGetManagementControllerID(DCMICommandWithErrors):
+ """Describes the DCMI get management controller ID string command
+
+ """
+
+ response_parser = ResponseParserMixIn.parse_single_line
+
+ name = "Get Management Controller ID String"
+ result_type = DCMIGetManagementControllerIDResult
+
+ response_fields = {
+ 'attr' : 'DCMI'
+ }
+
+ ipmidcmi_args = ["--get-management-controller-identifier-string"]
+
+class DCMISetManagementControllerID(DCMICommandWithErrors):
+ """Describes the DCMI get management controller ID string command
+
+ """
+ response_parser = ResponseParserMixIn.parse_single_line
+
+ name = "Set Management Controller ID String"
+ result_type = DCMISetManagementControllerIDResult
+
+ response_fields = {
+ 'attr' : 'DCMI'
+ }
+
+ @property
+ def ipmidcmi_args(self):
+ """
+ """
+ return ["--set-management-controller-identifier-string", self._params['controller']]
+class DCMIGetSensorInfo(DCMICommandWithErrors):
+ """Describes the DCMI get sensor info command
+
+ """
+ def parse_response(self, out, err):
+ """ Output is a number of lines with some info
+ """
+ new_out_list = []
+ expected_fields = ['Inlet Temperature','CPU Temperature','Baseboard temperature']
+ for line in out.strip().split('\n'):
+ for field in expected_fields:
+ if field in line:
+ value = line.lstrip(field)
+ new_line = field + " : " + value
+ new_out_list.append(new_line)
+ new_output= "\n".join(new_out_list)
+ return self.response_parser(new_output, err)
+
+ name = "Get DCMI Sensor Info"
+ result_type = DCMIGetSensorInfoResult
+ response_fields = {
+ 'Inlet Temperature':{},
+ 'CPU Temperature' : {},
+ 'Baseboard temperature' :{}
+ }
+
+
+ ipmidcmi_args = ["--get-dcmi-sensor-info"]
+
+
+class DCMIGetPowerStatistics(DCMICommandWithErrors):
+ """Describes the DCMI get system power statistics command
+
+ """
+
+ name = "Get Power Statistics"
+ result_type = DCMIGetPowerStatisticsResult
+
+ response_fields = {
+ 'Current Power' : {},
+ 'Minimum Power over sampling duration' : {},
+ 'Maximum Power over sampling duration' : {},
+ 'Average Power over sampling duration' : {},
+ 'Time Stamp' : {},
+ 'Statistics reporting time period' : {},
+ 'Power Measurement' : {}
+ }
+
+ ipmidcmi_args = ["--get-system-power-statistics"]
+
+
+class DCMIGetPowerLimit(DCMICommandWithErrors):
+ """Describes the DCMI get power limit command
+
+ """
+ name = "Get Power Limit"
+ result_type = DCMIGetPowerLimitResult
+
+ response_fields = {
+ 'Exception Actions' : {} ,
+ 'Power Limit Requested' : {},
+ 'Correction time limit' : {},
+ 'Management application Statistics Sampling period' :{}
+ }
+
+ ipmidcmi_args = ["--get-power-limit"]
+
+
+class DCMISetPowerLimit(DCMICommandWithErrors):
+ """Describes the DCMI set power limit command
+
+ """
+
+ name = "Set Power Limit"
+ result_type = DCMISetPowerLimitResult
+
+ response_fields = {
+ }
+
+ ipmidcmi_args = ["--set-power-limit"]
+
+class DCMIPowerLimitRequested(DCMICommandWithErrors):
+ """Describes the DCMI power limit requested command
+
+ """
+
+ name = "Power Limit Requested (Watts)"
+ result_type = DCMIPowerLimitRequestedResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmidcmi_args(self):
+ """ """
+ if self._params['exception'] is None:
+ return ["--set-power-limit","--power-limit-requested", self._params['limit']]
+ else:
+ return ["--set-power-limit","--power-limit-requested", self._params['limit'],
+ "--exception-actions", self._params['exception']]
+
+class DCMICorrectionTimeLimit(DCMICommandWithErrors):
+ """Describes the DCMI correction time limit command
+
+ """
+
+ name = "Power Correction Time Limit (Milliseconds)"
+ result_type = DCMICorrectionTimeLimitResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmidcmi_args(self):
+ """
+ """
+ if self._params['exception'] is None:
+ return ["--set-power-limit","--correction-time-limit", self._params['time_limit']]
+ else:
+ return ["--set-power-limit","--correction-time-limit", self._params['time_limit'],
+ "--exception-actions", self._params['exception']]
+
+class DCMIStatisticsSamplingPeriod(DCMICommandWithErrors):
+ """Describes the DCMI statistics sampling period command
+
+ """
+ name = "Power Statistics Sampling Period ( seconds)"
+ result_type = DCMIStatisticsSamplingPeriodResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmidcmi_args(self):
+ """ """
+ if self._params['exception'] is None:
+ return ["--set-power-limit","--statistics-sampling-period", self._params['period']]
+ else:
+ return ["--set-power-limit","--statistics-sampling-period", self._params['period'],
+ "--exception-actions", self._params['exception']]
+
+
+class DCMIActivatePowerLimit(DCMICommandWithErrors):
+ """Describes the DCMI activate/deactivate power limit command
+
+ """
+
+ response_parser = ResponseParserMixIn.parse_single_line
+
+ name = "Activate Or Deactivate Power Limit"
+ result_type = DCMIActivatePowerLimitResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmidcmi_args(self):
+ """
+ """
+ return ["--activate-deactivate-power-limit", self._params['action']]
+
+dcmi_commands = {
+ "dcmi_get_capabilities" : DCMIGetCapabilitiesCommand,
+ "dcmi_set_asset_tag" : DCMISetAssetTagCommand,
+ "dcmi_get_asset_tag" : DCMIGetAssetTagCommand,
+ "dcmi_get_controller_id" : DCMIGetManagementControllerID,
+ "dcmi_set_controller_id" : DCMISetManagementControllerID,
+ "dcmi_get_sensor_info" : DCMIGetSensorInfo,
+ "dcmi_get_power_statistics" : DCMIGetPowerStatistics,
+ "dcmi_get_power_limit" : DCMIGetPowerLimit,
+ "dcmi_set_power_limit" : DCMISetPowerLimit,
+ "dcmi_power_limit_requested": DCMIPowerLimitRequested,
+ "dcmi_activate_power_limit" : DCMIActivatePowerLimit,
+ "dcmi_correction_time_limit" : DCMICorrectionTimeLimit,
+ "dcmi_statistics_sampling_period": DCMIStatisticsSamplingPeriod
+}
diff --git a/pyipmi/commands/event.py b/pyipmi/commands/event.py
new file mode 100644
index 0000000..2aca6dc
--- /dev/null
+++ b/pyipmi/commands/event.py
@@ -0,0 +1,79 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""event related commands -- for generating test events"""
+
+from .. import Command
+from pyipmi.event import *
+from pyipmi.tools.responseparser import ResponseParserMixIn
+
+
+class GenerateGenericEvent(Command, ResponseParserMixIn):
+ """Describes the generic event IPMI command
+
+ This is "event <event_type>" to ipmitool
+ """
+ name = "Generate Generic Event"
+ result_type = GenericEventResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["event", self._params['event_type']]
+
+
+class AssertSensorEvent(Command, ResponseParserMixIn):
+ """Describes the generic event IPMI command
+
+ This is "event <sensorid> <state> assert" to ipmitool
+ """
+ name = "Assert Sensor Event"
+ result_type = AssertSensorEventResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["event", self._params['sensor_id'],
+ self._params['state'], 'assert']
+
+
+event_commands = {
+ 'generic_event' : GenerateGenericEvent,
+ 'assert_sensor_event' : AssertSensorEvent
+}
diff --git a/pyipmi/commands/fabric.py b/pyipmi/commands/fabric.py
new file mode 100644
index 0000000..c28a6fb
--- /dev/null
+++ b/pyipmi/commands/fabric.py
@@ -0,0 +1,306 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+"""
+This module holdes cxoem "fabric" commands other than "fabric config"
+commands.
+"""
+
+from .. import Command
+from pyipmi.tools.responseparser import ResponseParserMixIn
+from pyipmi.fabric import *
+from pyipmi import IpmiError
+
+class CommandWithErrors(Command, ResponseParserMixIn):
+
+ def parse_response(self, out, err):
+ """Parse the response to a command
+
+ The 'ipmitool_response_format' attribute is used to determine
+ what parser to use to for interpreting the results.
+
+ Arguments:
+ out -- the text response of an command from stdout
+ err -- the text response of an command from stderr
+ """
+
+ out = out + err
+ return self.response_parser(out, err)
+
+class UpdateConfigCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric update config command"""
+ name = "Update Config"
+ result_type = FabricUpdateConfigResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["cxoem", "fabric", "update_config"]
+
+class GetNodeIDCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric get nodeid command"""
+ name = "Get NodeID command"
+ result_type = int
+
+ def parse_response(self, out, err):
+ if err:
+ raise IpmiError(err)
+ return int(out)
+
+ response_fields = {
+ }
+
+ ipmitool_args = ["cxoem", "fabric", "get", "nodeid"]
+
+class GetIPAddrCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric get ipaddr command"""
+ name = "Get ipaddr command"
+ result_type = str
+
+ def parse_response(self, out, err):
+ return out.strip()
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ result = ["cxoem", "fabric", "get", "ipaddr"]
+ if self._params.get('nodeid', None):
+ result.extend(['node', self._params['nodeid']])
+ if self._params.get('iface', None):
+ result.extend(['interface', self._params['iface']])
+ return result
+
+class GetMacAddrCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric get macaddr command"""
+ name = "Get macaddr command"
+ result_type = str
+
+ def parse_response(self, out, err):
+ if err:
+ raise IpmiError(err)
+ return out.strip()
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ result = ["cxoem", "fabric", "get", "macaddr", "interface",
+ self._params['iface']]
+ if self._params.get('nodeid', None):
+ result.extend(['node', self._params['nodeid']])
+ return result
+
+class AddMacAddrCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric add macaddr command"""
+ name = "Add macaddr command"
+
+ @property
+ def ipmitool_args(self):
+ result = ['cxoem', 'fabric', 'add',
+ 'macaddr', self._params['macaddr'],
+ 'interface', self._params['iface']]
+ if self._params['nodeid']:
+ result += ['node', self._params['nodeid']]
+ return result
+
+
+class RmMacAddrCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric rm macaddr command"""
+ name = "Remove macaddr command"
+
+ @property
+ def ipmitool_args(self):
+ result = ['cxoem', 'fabric', 'rm',
+ 'macaddr', self._params['macaddr'],
+ 'interface', self._params['iface']]
+ if self._params['nodeid']:
+ result += ['node', self._params['nodeid']]
+ return result
+
+class GetLinkspeedCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric get linkspeed command"""
+ name = "Get linkspeed command"
+ result_type = float
+
+ def parse_response(self, out, err):
+ if err:
+ raise IpmiError(err)
+ return float(out)
+
+ @property
+ def ipmitool_args(self):
+ result = ['cxoem', 'fabric', 'get', 'linkspeed']
+ if self._params.get('link', None):
+ result.extend(['link', self._params['link']])
+ if self._params.get('actual', None):
+ result.extend(['actual'])
+ return result
+
+class GetLinkStatsCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric info link_stats command"""
+ name = "Get link_stats command"
+ result_type = FabricGetLinkStatsResult
+ response_fields = {
+ 'File Name' : {},
+ 'Error' : {}
+ }
+
+ def parse_response(self, out, err):
+ return out.strip()
+
+ @property
+ def ipmitool_args(self):
+ if self._params['tftp_addr'] != None:
+ tftp_args = self._params['tftp_addr'].split(":")
+ if len(tftp_args) == 1:
+ return [
+ 'cxoem', 'fabric', 'info', 'link_stats',
+ 'link', self._params['link'],
+ 'tftp', tftp_args[0],
+ 'file', self._params['filename']
+ ]
+ else:
+ return [
+ 'cxoem', 'fabric', 'info', 'link_stats',
+ 'link', self._params['link'],
+ 'tftp', tftp_args[0],
+ 'port', tftp_args[1],
+ 'file', self._params['filename']
+ ]
+ else:
+ return [
+ 'cxoem', 'fabric', 'info', 'link_stats',
+ 'link', self._params['link'],
+ 'file', self._params['filename']
+ ]
+
+class GetLinkMapCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric info linkmap command"""
+ name = "Get linkmap command"
+ result_type = FabricGetLinkMapResult
+ response_fields = {
+ 'File Name' : {},
+ 'Error' : {}
+ }
+
+ def parse_response(self, out, err):
+ return out.strip()
+
+ @property
+ def ipmitool_args(self):
+ if self._params['tftp_addr'] != None:
+ tftp_args = self._params['tftp_addr'].split(":")
+ if len(tftp_args) == 1:
+ return ["cxoem", "fabric", "info", "linkmap", "tftp",
+ tftp_args[0], "file", self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "info", "linkmap", "tftp",
+ tftp_args[0], "port", tftp_args[1], "file",
+ self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "info", "linkmap", "file",
+ self._params['filename']]
+
+class GetRoutingTableCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric info routing_table command"""
+ name = "Get routing_table command"
+ result_type = FabricGetRoutingTableResult
+ response_fields = {
+ 'File Name' : {},
+ 'Error' : {}
+ }
+
+ def parse_response(self, out, err):
+ return out.strip()
+
+ @property
+ def ipmitool_args(self):
+ if self._params['tftp_addr'] != None:
+ tftp_args = self._params['tftp_addr'].split(":")
+ if len(tftp_args) == 1:
+ return ["cxoem", "fabric", "info", "routing_table", "tftp",
+ tftp_args[0], "file", self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "info", "routing_table", "tftp",
+ tftp_args[0], "port", tftp_args[1], "file",
+ self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "info", "routing_table", "file",
+ self._params['filename']]
+
+class GetDepthChartCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric info depth_chart command"""
+ name = "Get depth_chart command"
+ result_type = FabricGetDepthChartResult
+ response_fields = {
+ 'File Name' : {},
+ 'Error' : {}
+ }
+
+ def parse_response(self, out, err):
+ return out.strip()
+
+ @property
+ def ipmitool_args(self):
+ if self._params['tftp_addr'] != None:
+ tftp_args = self._params['tftp_addr'].split(":")
+ if len(tftp_args) == 1:
+ return ["cxoem", "fabric", "info", "depth_chart", "tftp",
+ tftp_args[0], "file", self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "info", "depth_chart", "tftp",
+ tftp_args[0], "port", tftp_args[1], "file",
+ self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "info", "depth_chart", "file",
+ self._params['filename']]
+
+fabric_commands = {
+ "fabric_updateconfig" :UpdateConfigCommand,
+ "fabric_getnodeid" : GetNodeIDCommand,
+ "fabric_getipaddr" : GetIPAddrCommand,
+ "fabric_getmacaddr" : GetMacAddrCommand,
+ "fabric_getlinkspeed" : GetLinkspeedCommand,
+ "fabric_getlinkstats" : GetLinkStatsCommand,
+ "fabric_getlinkmap" : GetLinkMapCommand,
+ "fabric_getdepthchart" : GetDepthChartCommand,
+ "fabric_getroutingtable" : GetRoutingTableCommand,
+ "fabric_addmacaddr" : AddMacAddrCommand,
+ "fabric_rmmacaddr" : RmMacAddrCommand,
+
+ "fabric_info_getroutingtable" : GetRoutingTableCommand,
+ "fabric_info_getlinkmap" : GetLinkMapCommand,
+ "fabric_info_getdepthchart" : GetDepthChartCommand,
+}
diff --git a/pyipmi/commands/fabric_config.py b/pyipmi/commands/fabric_config.py
new file mode 100644
index 0000000..fe6b92f
--- /dev/null
+++ b/pyipmi/commands/fabric_config.py
@@ -0,0 +1,288 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+from .. import Command
+from pyipmi.tools.responseparser import ResponseParserMixIn
+from pyipmi.fabric import *
+from pyipmi import IpmiError
+
+class CommandWithErrors(Command, ResponseParserMixIn):
+
+ def parse_response(self, out, err):
+ """Parse the response to a command
+
+ The 'ipmitool_response_format' attribute is used to determine
+ what parser to use to for interpreting the results.
+
+ Arguments:
+ out -- the text response of an command from stdout
+ err -- the text response of an command from stderr
+ """
+
+ out = out + err
+ return self.response_parser(out, err)
+
+class GetIPInfoCommand(CommandWithErrors):
+ """ Describes the cxoem fabric list_ip_addrs IPMI command
+ """
+
+ name = "Retrieve fabric IP info"
+ result_type = FabricGetIPInfoResult
+
+ response_fields = {
+ 'File Name' : {},
+ 'Error' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ if self._params['tftp_addr'] != None:
+ tftp_args = self._params['tftp_addr'].split(":")
+ if len(tftp_args) == 1:
+ return ["cxoem", "fabric", "config", "get", "ipinfo", "tftp",
+ tftp_args[0], "file", self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "config", "get", "ipinfo", "tftp",
+ tftp_args[0], "port", tftp_args[1], "file",
+ self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "config", "get", "ipinfo", "file",
+ self._params['filename']]
+
+class GetUplinkInfoCommand(CommandWithErrors):
+ """ Describes the cxoem fabric list_ip_addrs IPMI command
+ """
+
+ name = "Retrieve fabric Uplink info"
+ result_type = FabricGetUplinkInfoResult
+
+ response_fields = {
+ 'File Name' : {},
+ 'Error' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ if self._params['tftp_addr'] != None:
+ tftp_args = self._params['tftp_addr'].split(":")
+ if len(tftp_args) == 1:
+ return ["cxoem", "fabric", "config", "get", "uplink_info",
+ "tftp", tftp_args[0], "file", self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "config", "get", "uplink_info",
+ "tftp", tftp_args[0], "port", tftp_args[1], "file",
+ self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "config", "get", "uplink_info", "file",
+ self._params['filename']]
+
+class GetMACAddressesCommand(CommandWithErrors):
+ """ Describes the cxoem fabric list_macs IPMI command
+ """
+
+ name = "Retrieve fabric MAC addresses"
+ result_type = FabricGetMACAddressesResult
+
+ response_fields = {
+ 'File Name' : {},
+ 'Error' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ if self._params['tftp_addr'] != None:
+ tftp_args = self._params['tftp_addr'].split(":")
+ if len(tftp_args) == 1:
+ return ["cxoem", "fabric", "config", "get", "macaddrs", "tftp",
+ tftp_args[0], "file", self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "config", "get", "macaddrs", "tftp",
+ tftp_args[0], "port", tftp_args[1], "file",
+ self._params['filename']]
+ else:
+ return ["cxoem", "fabric", "config", "get", "macaddrs", "file",
+ self._params['filename']]
+
+class UpdateConfigCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric config update config command"""
+ name = "Update Config"
+
+ ipmitool_args = ['cxoem', 'fabric', 'config', 'update_config']
+
+class GetIPSrcCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric get ipsrc command"""
+ name = "Get ipsrc command"
+ result_type = int
+
+ def parse_response(self, out, err):
+ return int(out)
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["cxoem", "fabric", "config", "get", "ipsrc"]
+
+class SetIPSrcCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric set ipsrc command"""
+ name = "Set ipsrc command"
+
+ @property
+ def ipmitool_args(self):
+ return ['cxoem',
+ 'fabric',
+ 'config',
+ 'set',
+ 'ipsrc',
+ self._params['ipsrc_mode']]
+
+class FactoryDefaultCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric config factory_default command"""
+ name = "Fabric config factory_default command"
+
+ ipmitool_args = ['cxoem', 'fabric', 'config', 'factory_default']
+
+class GetIPAddrBase(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric config get ipaddr_base command"""
+ name = "Get fabric config ipaddr_base command"
+ result_type = str
+
+ ipmitool_args = ['cxoem', 'fabric', 'config', 'get', 'ipaddr_base']
+
+ def parse_response(self, out, err):
+ return out.strip()
+
+class GetLinkspeedCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric config get linkspeed command"""
+ name = "Get global linkspeed command"
+ result_type = float
+
+ def parse_response(self, out, err):
+ if err:
+ raise IpmiError(err)
+ return float(out)
+
+ ipmitool_args = ['cxoem', 'fabric', 'config', 'get', 'linkspeed']
+
+class SetLinkspeedCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric config set linkspeed command"""
+ name = "Set linkspeed command"
+
+ @property
+ def ipmitool_args(self):
+ return ['cxoem', 'fabric', 'config', 'set', 'linkspeed',
+ self._params['linkspeed']]
+
+class GetLinkspeedPolicyCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric config get ls_policy command"""
+ name = "Get global ls_policy command"
+ result_type = int
+
+ def parse_response(self, out, err):
+ if err:
+ raise IpmiError(err)
+ return int(out)
+
+ ipmitool_args = ['cxoem', 'fabric', 'config', 'get', 'ls_policy']
+
+class SetLinkspeedPolicyCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric config set ls_policy command"""
+ name = "Set linkspeed command"
+
+ @property
+ def ipmitool_args(self):
+ return ['cxoem', 'fabric', 'config', 'set', 'ls_policy',
+ self._params['ls_policy']]
+
+class GetUplinkCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric config get uplink command"""
+ name = "Get uplink command"
+ result_type = int
+
+ def parse_response(self, out, err):
+ if err:
+ raise IpmiError(err)
+ return int(out)
+
+ @property
+ def ipmitool_args(self):
+ return ['cxoem', 'fabric', 'config', 'get', 'uplink', 'interface',
+ self._params['iface']]
+
+class SetUplinkCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric config set uplink command"""
+ name = "Set uplink command"
+
+ @property
+ def ipmitool_args(self):
+ return ['cxoem', 'fabric', 'config', 'set', 'uplink',
+ self._params['uplink'], 'interface', self._params['iface']]
+
+class GetLinkUsersFactorCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric config get lu_factor command"""
+ name = "Get global link users factor command"
+ result_type = int
+
+ def parse_response(self, out, err):
+ if err:
+ raise IpmiError(err)
+ return int(out)
+
+ ipmitool_args = ['cxoem', 'fabric', 'config', 'get', 'lu_factor']
+
+class SetLinkUsersFactorCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool fabric config set lu_factor command"""
+ name = "Set global link users factor command"
+
+ @property
+ def ipmitool_args(self):
+ return ['cxoem', 'fabric', 'config', 'set', 'lu_factor',
+ self._params['lu_factor']]
+
+fabric_config_commands = {
+ "fabric_config_getipinfo" : GetIPInfoCommand,
+ "fabric_config_getmacaddresses" : GetMACAddressesCommand,
+ "fabric_config_updateconfig" : UpdateConfigCommand,
+ "fabric_config_getipsrc" : GetIPSrcCommand,
+ "fabric_config_setipsrc" : SetIPSrcCommand,
+ "fabric_config_factory_default" : FactoryDefaultCommand,
+ "fabric_config_get_ipaddr_base" : GetIPAddrBase,
+ "fabric_config_getlinkspeed" : GetLinkspeedCommand,
+ "fabric_config_setlinkspeed" : SetLinkspeedCommand,
+ "fabric_config_getlinkspeedpolicy" : GetLinkspeedPolicyCommand,
+ "fabric_config_setlinkspeedpolicy" : SetLinkspeedPolicyCommand,
+ "fabric_config_getuplinkinfo" : GetUplinkInfoCommand,
+ "fabric_config_getuplink" : GetUplinkCommand,
+ "fabric_config_setuplink" : SetUplinkCommand,
+ "fabric_config_getlinkusersfactor" : GetLinkUsersFactorCommand,
+ "fabric_config_setlinkusersfactor" : SetLinkUsersFactorCommand
+}
diff --git a/pyipmi/commands/freeipmi_pef.py b/pyipmi/commands/freeipmi_pef.py
new file mode 100644
index 0000000..a551d65
--- /dev/null
+++ b/pyipmi/commands/freeipmi_pef.py
@@ -0,0 +1,211 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""PEF related commands"""
+
+from .. import Command
+from pyipmi.freeipmi_pef import *
+from pyipmi.tools.responseparser import ResponseParserMixIn
+
+
+class FreeIPMIPEFInfoCommand(Command, ResponseParserMixIn):
+ """Describes the get PEF info IPMI command
+
+ This is "--info" to ipmi-pef-config
+ """
+ name = "Get PEF Info and Capabilities"
+ result_type = FreeIPMIPEFInfoResult
+
+ response_fields = {
+ 'PEF version' : {},
+ 'Alert action' : {},
+ 'Power down action' : {},
+ 'Power reset action' : {},
+ 'Power cycle action' : {},
+ 'OEM action' : {},
+ 'Diagnostic interrupt action' : {},
+ 'OEM event record filtering' : {},
+ 'Number of Event Filter Table entries' : {},
+ 'Number of Event Filters' : {},
+ 'Number of Alert Policy entries' : {},
+ 'Number of Alert Strings' : {}
+ }
+
+ ipmi_pef_config_args = ['--info']
+
+
+class FreeIPMIPEFCheckout(Command, ResponseParserMixIn):
+ """Retrieve platform event filtering configuration
+
+ """
+ name = "Checkout PEF Configuration"
+
+ def get_next_line(self, text):
+ line, c, rest = text.partition('\n')
+ line = line.strip()
+ return line, rest
+
+ def parse_section(self, rest):
+ config_dict = {}
+ line, rest = self.get_next_line(rest)
+ while line != "EndSection":
+ if line[0] == '#':
+ line, rest = self.get_next_line(rest)
+ continue
+ keyname, c, value = line.partition(" ")
+ config_dict[keyname.strip()] = value.strip()
+ line, rest = self.get_next_line(rest)
+ return config_dict, rest
+
+ def parse_results(self, response, err):
+ """Parse the output from "pef checkout." If a filename was given,
+ there will be no response
+ """
+
+ section_list = {}
+ line, rest = self.get_next_line(response)
+ while line != "":
+ if line[0] == '#':
+ line, rest = self.get_next_line(rest)
+ continue
+ keyword, c, value = line.partition(' ')
+ if keyword.strip() == "Section":
+ param_list, rest = self.parse_section(rest)
+ section_list[value.strip()] = param_list
+ line, rest = self.get_next_line(rest)
+ return section_list
+
+ @property
+ def ipmi_pef_config_args(self):
+ """
+ """
+ section = self._params.get("section")
+ filename = self._params.get('filename')
+ key = self._params.get('key')
+
+ if filename:
+ if section:
+ section = "--section=%s" % section
+ else:
+ section = ""
+ return ["--checkout", "--filename=" + filename, section]
+
+ if key and section:
+ return ["--checkout", "--key-pair=" + section + ":" + key]
+
+ if section:
+ return ["--checkout", "--section=" + section]
+
+ return ["--checkout"]
+
+
+class FreeIPMIPEFCommit(Command, ResponseParserMixIn):
+
+ """Update PEF configuration from file or key-value pair
+
+ """
+ name = "Update PEF Configuration"
+ result_type = FreeIPMIPEFCommitResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmi_pef_config_args(self):
+ """
+ """
+ filename = self._params.get('filename')
+
+ if filename:
+ return ["--commit", "--filename=" + filename]
+
+ key_value_pair = self._params.get('key_value_pair')
+ section = self._params.get('section')
+ if key_value_pair and section:
+ return ["--commit", "--key-pair=" + section + ":" + key_value_pair]
+
+ raise Exception("Command pef-config --commit requires either filename or key-value pair")
+
+
+class FreeIPMIPEFDiff(Command, ResponseParserMixIn):
+ """ Command to diff current PEF configuration against a file or key-value pair
+
+ """
+ name = "PEF Diff"
+ result_type = FreeIPMIDiffResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmi_pef_config_args(self):
+ """
+ """
+ filename = self._params.get('filename')
+ section = self._params.get('section')
+ key = self._params.get('key')
+
+ if filename:
+ if section:
+ section = "--section=%s" % section
+ else:
+ section = ""
+ return ["--diff", "--filename=" + filename, section]
+
+ if key and section:
+ return ["--diff", "--key-pair=" + section + ":" + key]
+
+ raise Exception("Command pef-config --diff requires either filename or key")
+
+
+class FreeIPMIPEFListSections(Command, ResponseParserMixIn):
+ """Describes the get PEF list sections command
+
+ """
+ name = "List PEF Table Sections"
+
+ def parse_results(self, response, err):
+ """Parse the output from "--listsections," which is a list
+ of section names separated by a single line break
+ """
+ result = map(lambda x: x.strip(), response.splitlines())
+ return result
+
+ ipmi_pef_config_args = ["--listsections"]
+
+
+freeipmi_pef_commands = {
+ 'pef_config_info' : FreeIPMIPEFInfoCommand,
+ 'pef_checkout' : FreeIPMIPEFCheckout,
+ 'pef_commit' : FreeIPMIPEFCommit,
+ 'pef_diff' : FreeIPMIPEFDiff,
+ 'pef_list_sections' : FreeIPMIPEFListSections
+}
diff --git a/pyipmi/commands/fru.py b/pyipmi/commands/fru.py
new file mode 100644
index 0000000..3eb3f87
--- /dev/null
+++ b/pyipmi/commands/fru.py
@@ -0,0 +1,132 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""FRU related commands"""
+
+from .. import Command
+from pyipmi.fru import *
+from pyipmi.tools.responseparser import ResponseParserMixIn
+
+
+class FRUPrintCommand(Command, ResponseParserMixIn):
+ """Describes the FRU get inventory area info IPMI command
+
+ This is "fru print" to ipmitool
+ """
+ name = "FRU Print"
+ result_type = FRUPrintResult
+
+ response_fields = {
+ 'FRU Device Description' : {},
+ 'Board Mfg Date' : {},
+ 'Board Mfg' : {},
+ 'Board Product' : {},
+ 'Board Serial' : {},
+ 'Board Part Number' : {},
+ 'Product Manufacturer' : {},
+ 'Product Name' : {},
+ 'Product Part Number' : {},
+ 'Product Serial' : {}
+ }
+
+ ipmitool_args = ["fru", "print"]
+
+
+class FRUReadCommand(Command, ResponseParserMixIn):
+ """Describes the FRU read IPMI command
+
+ This is "fru read" to ipmitool
+ """
+ name = "FRU Read"
+ result_type = FRUReadResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["fru", "read", self._params['fru_id'],
+ self._params['filename']]
+
+
+class FRUWriteCommand(Command, ResponseParserMixIn):
+ """Describes the FRU write IPMI command
+
+ This is "fru write" to ipmitool
+ """
+ name = "FRU Write"
+ result_type = FRUWriteResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["fru", "read", self._params['fru_id'],
+ self._params['filename']]
+
+
+class FRUUpgEKeyCommand(Command, ResponseParserMixIn):
+ """Describes the FRU upgEKey ipmitool command
+ """
+ name = "FRU UpgEkey"
+ result_type = FRUUpgEKeyResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["fru", "upgEkey", self._params['fru_id'],
+ self._params['filename']]
+
+
+class FRUShowCommand(Command, ResponseParserMixIn):
+ """Describes the ekanalyzer frushow ipmitool command
+ """
+ name = "FRU Show"
+ result_type = FRUShowResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["ekanalyzer", 'frushow',
+ 'oc=%s' % self._params['filename']]
+
+
+fru_commands = {
+ 'fru_print' : FRUPrintCommand,
+ 'fru_read' : FRUReadCommand,
+ 'fru_write' : FRUWriteCommand,
+ 'fru_upg_e_key' : FRUUpgEKeyCommand
+}
diff --git a/pyipmi/commands/fw.py b/pyipmi/commands/fw.py
new file mode 100644
index 0000000..0a70a8e
--- /dev/null
+++ b/pyipmi/commands/fw.py
@@ -0,0 +1,400 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+from .. import Command, IpmiError
+from pyipmi.tools.responseparser import ResponseParserMixIn
+from pyipmi.fw import *
+
+class CommandWithErrors(Command, ResponseParserMixIn):
+
+ # TODO: Generalize this to base class? Better way to include
+ # error output in parsing?
+ def parse_response(self, out, err):
+ """Parse the response to a command
+
+ The 'ipmitool_response_format' attribute is used to determine
+ what parser to use to for interpreting the results.
+
+ Arguments:
+ out -- the text response of an command from stdout
+ err -- the text response of an command from stderr
+ """
+
+ out = out + err
+ return self.response_parser(out, err)
+
+class FWDownloadCommand(CommandWithErrors):
+ """Describes the cxoem fw download IPMI command
+
+ """
+
+ name = "Update a Firmware Image"
+ result_type = FWDownloadResult
+
+ response_fields = {
+ 'File Name' : {},
+ 'Partition' : {},
+ 'Slot' : {'attr': 'partition'},
+ 'Type' : {},
+ 'IP' : {},
+ 'TFTP Handle ID' : {},
+ 'Start FW download failed' : {'attr': 'fw_error'}
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["cxoem", "fw", "download", self._params['filename'],
+ self._params['partition'], self._params['image_type'],
+ "tftp", self._params['tftp_addr']]
+
+
+class FWUploadCommand(CommandWithErrors):
+ """Describes the cxoem fw upload IPMI command
+
+ """
+
+ name = "Retrieve Firmware From Device"
+ result_type = FWUploadResult
+
+ response_fields = {
+ 'File Name' : {},
+ 'Partition' : {},
+ 'Slot' : {'attr': 'partition'},
+ 'Type' : {},
+ 'IP' : {},
+ 'TFTP Handle ID' : {},
+ 'Start FW download failed' : {'attr': 'fw_error'}
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["cxoem", "fw", "upload", self._params['partition'],
+ self._params['filename'], self._params['image_type'],
+ "tftp", self._params['tftp_addr']]
+
+
+class FWRegisterReadCommand(CommandWithErrors):
+ """ cxoem fw register read command """
+ name = "Register Firmware Read"
+ result_type = FWRegisterReadResult
+
+ response_fields = {
+ 'File Name' : {},
+ 'Partition' : {},
+ 'Type' : {},
+ 'Error' : {}
+ }
+
+ def parse_response(self, out, err):
+ result = super(FWRegisterReadCommand, self).parse_response(out, err)
+ if hasattr(result, "error"):
+ raise IpmiError(result.error)
+
+ @property
+ def ipmitool_args(self):
+ return ["cxoem", "fw", "register", "read", self._params['partition'],
+ self._params['filename'], self._params['image_type']]
+
+
+class FWRegisterWriteCommand(CommandWithErrors):
+ """ cxoem fw register write command """
+ name = "Register Firmware Write"
+ result_type = FWRegisterWriteResult
+
+ response_fields = {
+ 'File Name' : {},
+ 'Partition' : {},
+ 'Type' : {},
+ 'Error' : {}
+ }
+
+ def parse_response(self, out, err):
+ result = super(FWRegisterWriteCommand, self).parse_response(out, err)
+ if hasattr(result, "error"):
+ raise IpmiError(result.error)
+
+ @property
+ def ipmitool_args(self):
+ return ["cxoem", "fw", "register", "write", self._params['partition'],
+ self._params['filename'], self._params['image_type']]
+
+
+class FWActivateCommand(CommandWithErrors):
+ """Describes the cxoem fw activate IPMI command
+
+ """
+
+ name = "Mark A Firmware Image As Active"
+ result_type = FWActivateResult
+
+ response_fields = {
+ "" : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["cxoem", "fw", "activate", self._params['partition']]
+
+
+class FWInvalidateCommand(CommandWithErrors):
+ """Describes the cxoem fw deactivate IPMI command
+
+ """
+
+ name = "Mark A Firmware Image As Inactive"
+ result_type = FWDeactivateResult
+
+ response_fields = {
+ "" : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["cxoem", "fw", "invalidate", self._params['partition']]
+
+
+class FWFlagsCommand(CommandWithErrors):
+ """Describes the cxoem fw flags IPMI command
+
+ """
+
+ name = "Set Flags For a Firmware Image"
+ result_type = FWFlagsResult
+
+ response_fields = {
+ "" : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["cxoem", "fw", "flags", self._params['partition'],
+ self._params['flags']]
+
+
+class FWStatusCommand(CommandWithErrors):
+ """Describes the cxoem fw status IPMI command
+
+ """
+
+ name = "Check Status of Most Recent Upload or Download"
+ result_type = FWStatus
+
+ response_fields = {
+ 'Status' : {},
+ 'Error' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["cxoem", "fw", "status", self._params['tftp_handle']]
+
+
+class FWCheckCommand(CommandWithErrors):
+ """Describes the cxoem fw check IPMI command
+
+ """
+
+ name = "Perform CRC of a Firmware Image"
+ result_type = FWCheckResult
+
+ response_fields = {
+ 'Partition' : {},
+ 'Slot' : {'attr': 'partition'},
+ 'CRC32' : {},
+ 'Error' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["cxoem", "fw", "check", self._params['partition']]
+
+
+class FWCancelCommand(CommandWithErrors):
+ """Describes the cxoem fw cancel IPMI command
+
+ """
+
+ name = "Cancel an In-Progress Upload or Download"
+ result_type = FWCancelResult
+
+ response_fields = {
+ "" : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["cxoem", "fw", "cancel", self._params['job_id']]
+
+
+class FWInfoCommand(CommandWithErrors):
+ """Describes the cxoem fw info IPMI command
+
+ """
+
+ name = "Request Firmware Information"
+ result_type = FWInfo
+ response_parser = ResponseParserMixIn.parse_colon_record_list
+
+ response_fields = {
+ "Partition" : {},
+ "Slot" : {"attr": "partition"},
+ "Type" : {},
+ "Offset" : {},
+ "Size" : {},
+ "Priority" : {},
+ "Daddr" : {},
+ "Flags" : {},
+ "In Use" : {},
+ "Version" : {},
+ "Error" : {}
+ }
+
+ ipmitool_args = ["cxoem", "fw", "info"]
+
+
+class FWGetCommand(CommandWithErrors):
+ """Describes the cxoem fw get IPMI command
+
+ """
+
+ name = "Retrieve Raw Firmware From Device"
+ result_type = FWGetResult
+
+ response_fields = {
+ 'File Name' : {},
+ 'Address' : {},
+ 'Size' : {},
+ 'IP' : {},
+ 'TFTP Handle ID' : {},
+ 'Start raw transfer failed' : {'attr': 'fw_error'}
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["cxoem", "fw", "get", self._params['filename'],
+ self._params['offset'], self._params['size'],
+ "tftp", self._params['tftp_addr']]
+
+
+class FWPutCommand(CommandWithErrors):
+ """Describes the cxoem fw put IPMI command
+
+ """
+
+ name = "Update Raw Firmware To Device"
+ result_type = FWPutResult
+
+ response_fields = {
+ 'File Name' : {},
+ 'Address' : {},
+ 'TSize' : {},
+ 'IP' : {},
+ 'TFTP Handle ID' : {},
+ 'Start raw transfer failed' : {'attr': 'fw_error'}
+ }
+
+ @property
+ def ipmitool_args(self):
+ """
+ """
+ return ["cxoem", "fw", "put", self._params['filename'],
+ self._params['offset'], self._params['size'],
+ "tftp", self._params['tftp_addr']]
+
+
+class FWResetCommand(CommandWithErrors):
+ """Describes the cxoem fw reset IPMI command
+
+ """
+
+ name = "Reset to factory default"
+ result_type = FWResetResult
+
+ response_fields = {
+ "Error" : {}
+ }
+
+ ipmitool_args = ["cxoem", "fw", "reset"]
+
+
+
+class FWVersionCommand(CommandWithErrors):
+ """Describes the cxoem fw version IPMI command
+
+ """
+
+ name = "Set the firmware version"
+ result_type = FWVersionResult
+
+ response_fields = {
+ "Error" : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["cxoem", "fw", "version", self._params['version']]
+
+
+fw_commands = {
+ "fw_download" : FWDownloadCommand,
+ "fw_upload" : FWUploadCommand,
+ "fw_register_read" : FWRegisterReadCommand,
+ "fw_register_write" : FWRegisterWriteCommand,
+ "fw_activate" : FWActivateCommand,
+ "fw_invalidate" : FWInvalidateCommand,
+ "fw_flags" : FWFlagsCommand,
+ "fw_status" : FWStatusCommand,
+ "fw_check" : FWCheckCommand,
+ "fw_cancel" : FWCancelCommand,
+ "fw_info" : FWInfoCommand,
+ "fw_get" : FWGetCommand,
+ "fw_put" : FWPutCommand,
+ "fw_reset" : FWResetCommand,
+ "fw_version" : FWVersionCommand
+}
diff --git a/pyipmi/commands/info.py b/pyipmi/commands/info.py
new file mode 100644
index 0000000..650e951
--- /dev/null
+++ b/pyipmi/commands/info.py
@@ -0,0 +1,92 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+from .. import Command
+from pyipmi.info import *
+from pyipmi.tools.responseparser import ResponseParserMixIn
+from pyipmi import IpmiError
+
+class InfoBasicCommand(Command, ResponseParserMixIn):
+ """ Describes the cxoem info basic IPMI command
+ """
+
+ name = "Retrieve basic SoC info"
+
+ ipmitool_args = ["cxoem", "info", "basic"]
+
+ def parse_results(self, out, err):
+ """ Parse ipmitool output
+ """
+ result = InfoBasicResult()
+
+ if out.startswith("Calxeda SoC"):
+ for line in out.splitlines():
+ if line.lstrip().startswith("Calxeda SoC"):
+ result.iana = int(line.split()[2].strip("()"), 16)
+ elif line.lstrip().startswith("Firmware Version"):
+ result.firmware_version = line.partition(":")[2].strip()
+ elif line.lstrip().startswith("SoC Version"):
+ result.ecme_version = line.partition(":")[2].strip()
+ elif line.lstrip().startswith("Build Number"):
+ result.ecme_build_number = line.partition(":")[2].strip()
+ elif line.lstrip().startswith("Timestamp"):
+ result.ecme_timestamp = int(line.split()[1].strip(":()"))
+ elif err.startswith("Error: "):
+ raise IpmiError(err.splitlines()[0][7:])
+ else:
+ raise IpmiError("Unknown Error")
+
+ return result
+
+class InfoCardCommand(Command, ResponseParserMixIn):
+ """ Describes the cxoem info card IPMI command
+ """
+
+ name = "Retrieve card info"
+
+ ipmitool_args = ["cxoem", "info", "card"]
+
+ result_type = InfoCardResult
+ response_fields = {
+ 'Board Type' : {'attr' : 'type'},
+ 'Board Revision' : {'attr' : 'revision'}
+ }
+
+ def parse_results(self, out, err):
+ result = ResponseParserMixIn.parse_results(self, out, err)
+ if not (hasattr(result, 'type') and hasattr(result, 'revision')):
+ raise IpmiError(out.strip())
+ return result
+
+info_commands = {
+ "info_basic" : InfoBasicCommand,
+ "info_card" : InfoCardCommand
+}
diff --git a/pyipmi/commands/lan.py b/pyipmi/commands/lan.py
new file mode 100644
index 0000000..4316700
--- /dev/null
+++ b/pyipmi/commands/lan.py
@@ -0,0 +1,127 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""lan config related commands"""
+
+from .. import Command
+from pyipmi.lan import *
+from pyipmi.tools.responseparser import (ResponseParserMixIn,
+ str_to_list,
+ str_to_dict)
+
+
+class LANPrintCommand(Command, ResponseParserMixIn):
+ """Describes the lan print ipmitool command
+ """
+ name = "LAN Print"
+ result_type = LANPrintResults
+
+ def parse_response(self, out, err):
+ """ Strip out extraneous colons to allow more generic parsing
+ """
+ new_out_list = map(lambda x: x.lstrip(' \t\n:'), out.split('\n'))
+ new_out = reduce(lambda x, y: x + '\n' + y, new_out_list)
+
+ return self.response_parser(new_out, err)
+
+ def first_word_only(line):
+ y = line.split(' ')
+ return y[0]
+
+ response_fields = {
+ 'Set in Progress' : {},
+ 'Auth Type Support' : {'parser' : str_to_list},
+ 'Auth Type Enable' : {'lines' : 5,
+ 'parser' : str_to_dict,
+ 'operator' : ':',
+ 'delimiter' : '\n',
+ 'value_parser' : str_to_list},
+ 'IP Address Source' : {},
+ 'IP Address' : {},
+ 'Subnet Mask' : {},
+ 'MAC Address' : {},
+ 'SNMP Community String' : {},
+ 'IP Header' : {'parser' : str_to_dict,
+ 'operator' : '=',
+ 'delimiter' : ' '},
+ 'BMC ARP Control' : {'parser' : str_to_list,
+ 'delimiter' : ','},
+ 'Gratituous ARP Intrvl' : {'parser' : first_word_only},
+ 'Default Gateway IP' : {},
+ 'Default Gateway MAC' : {},
+ 'TFTP Server IP' : {},
+ 'NTP Server IP' : {},
+ 'NTP UDP port' : {},
+ 'OEM MAC0' : {},
+ 'OEM MAC1' : {},
+ 'OEM MAC2' : {},
+ 'OEM OUID' : {},
+ 'Supercluster OUID' : {},
+ 'Supercluster mode' : {},
+ 'Supercluster FID' : {},
+ '802.1q VLAN ID' : {},
+ '802.1q VLAN Priority' : {},
+ 'RMCP+ Cipher Suites' : {'parser' : str_to_list,
+ 'delimiter' : ','},
+ 'Cipher Suite Priv Max' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ channel = self._params.get('channel', '')
+ return ["lan", "print", channel]
+
+
+class LANSetCommand(Command, ResponseParserMixIn):
+ """Describes the ipmitool lan set command
+ """
+ name = "LAN Set"
+ result_type = LANSetResult
+
+ response_fields = {
+ }
+
+ @property
+ def ipmitool_args(self):
+ command = "lan set %s %s" % (self._params['channel'], self._params['command'])
+ command_array = command.split(' ')
+ params = self._params['param']
+ param_array = [params]
+ if self._params['command'] == 'auth':
+ param_array = params.split(' ')
+ command_array.extend(param_array)
+ return command_array
+
+
+lan_commands = {
+ 'lan_print' : LANPrintCommand,
+ 'lan_set' : LANSetCommand
+}
diff --git a/pyipmi/commands/mc.py b/pyipmi/commands/mc.py
new file mode 100644
index 0000000..b94c23b
--- /dev/null
+++ b/pyipmi/commands/mc.py
@@ -0,0 +1,69 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+from .. import Command
+from pyipmi.tools.responseparser import ResponseParserMixIn
+from pyipmi.mc import *
+
+class CommandWithErrors(Command, ResponseParserMixIn):
+
+ def parse_response(self, out, err):
+ """Parse the response to a command
+
+ The 'ipmitool_response_format' attribute is used to determine
+ what parser to use to for interpreting the results.
+
+ Arguments:
+ out -- the text response of an command from stdout
+ err -- the text response of an command from stderr
+ """
+
+ out = out + err
+ return self.response_parser(out, err)
+
+class MCResetCommand(CommandWithErrors):
+ """ Describes the cxoem MC reset IPMI command
+ """
+
+ name = "Reset the MC"
+ result_type = MCResetResult
+
+ response_fields = {
+ "Error" : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["mc", "reset", self._params['mode']]
+
+mc_commands = {
+ "mc_reset" : MCResetCommand,
+}
diff --git a/pyipmi/commands/payload.py b/pyipmi/commands/payload.py
new file mode 100644
index 0000000..5d8df53
--- /dev/null
+++ b/pyipmi/commands/payload.py
@@ -0,0 +1,65 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""A series of wrappers around RMCP+ Payload commands"""
+
+from pyipmi import Command, InteractiveCommand, IpmiError
+from pyipmi.tools.responseparser import ResponseParserMixIn
+
+
+class ActivatePayloadCommand(InteractiveCommand, ResponseParserMixIn):
+ """Describes the Activate Payload command"""
+
+ #TODO: there could be other payload types
+
+ name = "Activate Payload"
+ ipmitool_args = ["-I", "lanplus", "-C", "0", "sol", "activate"]
+
+
+class DeactivatePayloadCommand(Command, ResponseParserMixIn):
+ """Describes the Deactivate Payload command"""
+
+ #TODO: there could be other payload types
+
+ def handle_command_error(self, out, err):
+ if err.find('Info: SOL payload already de-activated') > -1:
+ return
+
+ raise IpmiError(err)
+
+ name = "Deactivate Payload"
+ ipmitool_args = ["-I", "lanplus", "sol", "deactivate"]
+
+
+payload_commands = {
+ "activate_payload" : ActivatePayloadCommand,
+ "deactivate_payload" : DeactivatePayloadCommand
+}
diff --git a/pyipmi/commands/pef.py b/pyipmi/commands/pef.py
new file mode 100644
index 0000000..6221d1a
--- /dev/null
+++ b/pyipmi/commands/pef.py
@@ -0,0 +1,130 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""PEF related commands"""
+
+from .. import Command
+from pyipmi.pef import *
+from pyipmi.tools.responseparser import ResponseParserMixIn
+
+
+class PEFGetInfoCommand(Command, ResponseParserMixIn):
+ """Describes the get PEF info IPMI command
+
+ This is "pef info" to ipmitool
+ """
+ name = "Get PEF Capabilities"
+ result_type = PEFInfoResult
+
+ response_fields = {
+ 'Version' : {},
+ 'PEF table size' : {},
+ 'Alert policy table size' : {},
+ 'System GUID' : {},
+ 'Alert' : {},
+ 'Power-off' : {},
+ 'Reset' : {},
+ 'Power-cycle' : {},
+ 'OEM-defined' : {},
+ 'Diagnostic-interrupt' : {}
+ }
+
+ ipmitool_args = ["-v", "pef", "info"]
+
+
+class PEFGetPolicyCommand(Command, ResponseParserMixIn):
+ """Describes the get PEF policies ipmitool command
+
+ This is "pef policy" to ipmitool
+ """
+
+ name = "Get PEF Policy"
+ result_type = PEFPolicyResult
+
+ response_fields = {
+ }
+
+ ipmitool_args = ["pef", "policy"]
+
+
+class PEFGetStatusCommand(Command, ResponseParserMixIn):
+ """Describes the get PEF status ipmitool command
+
+ This is "pef status" to ipmitool
+ """
+ name = "Get PEF Status"
+ result_type = PEFStatusResult
+
+ response_fields = {
+ 'Last SEL addition' : {},
+ 'Last SEL record ID' : {},
+ 'Last S/W processed ID' : {},
+ 'Last BMC processed ID' : {},
+ 'PEF' : {},
+ 'PEF event messages' : {},
+ 'PEF startup delay' : {},
+ 'Alert startup delay' : {},
+ 'Alert' : {},
+ 'Power-off' : {},
+ 'Reset' : {},
+ 'Power-cycle' : {},
+ 'OEM-defined' : {},
+ 'Diagnostic-interrupt' : {}
+ }
+
+ ipmitool_args = ["pef", "status"]
+
+
+class PEFListEntriesCommand(Command, ResponseParserMixIn):
+ """Describes the get PEF list entries ipmitool command
+
+ This is "pef list" to ipmitool
+ """
+ name = "List PEF Entries"
+
+ response_parser = ResponseParserMixIn.parse_colon_record_list
+
+ result_type = PEFListResult
+
+ response_fields = {
+ 'PEF table entry' : {},
+ 'Status' : {}
+ }
+
+ ipmitool_args = ["-v", "pef", "list"]
+
+
+pef_commands = {
+ 'pef_get_info' : PEFGetInfoCommand,
+ 'pef_get_status' : PEFGetStatusCommand,
+ 'pef_get_policies' : PEFGetPolicyCommand,
+ 'pef_list_entries' : PEFListEntriesCommand
+}
diff --git a/pyipmi/commands/pet.py b/pyipmi/commands/pet.py
new file mode 100644
index 0000000..178a4e7
--- /dev/null
+++ b/pyipmi/commands/pet.py
@@ -0,0 +1,55 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""PEF related commands"""
+
+from .. import Command
+from pyipmi.pet import *
+from pyipmi.tools.responseparser import ResponseParserMixIn
+
+
+class PETAcknowledgeCommand(Command, ResponseParserMixIn):
+ """Describes the PET Acknowledge command
+
+ This is "--pet-acknowledge" to ipmi-pet
+ """
+ name = "Send a PET Acknowledge"
+ result_type = PETAcknowledgeResult
+
+ response_fields = {
+ }
+
+ ipmi_pet_args = ['--pet-acknowledge']
+
+
+pet_commands = {
+ 'pet_acknowledge' : PETAcknowledgeCommand
+}
diff --git a/pyipmi/commands/sdr.py b/pyipmi/commands/sdr.py
new file mode 100644
index 0000000..41e8f69
--- /dev/null
+++ b/pyipmi/commands/sdr.py
@@ -0,0 +1,110 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""SDR related commands"""
+import re
+
+from .. import Command
+from .. sdr import Sdr, AnalogSdr
+from pyipmi.tools.responseparser import ResponseParserMixIn
+
+class SdrListCommand(Command, ResponseParserMixIn):
+ """Describes the sdr list command
+
+ This is not a single IPMI request type - it's an ipmitool
+ command that's composed of multiple IPMI requests.
+ """
+
+ name = 'SDR List'
+ result_type = Sdr
+
+ response_parser = ResponseParserMixIn.parse_colon_record_list
+ ipmitool_args = ['-v', 'sdr', 'list', 'all']
+
+ def sensor_name_parser(string):
+ return string.split('(')[0].strip()
+
+ def entity_id_parser(string):
+ m = re.search('(\d.\d{1,2})', string)
+ return m.groups()[0]
+
+ def get_response_types(self, record):
+ """Only matches Analog sensors right now.
+
+ There are several more types of records to match, if they
+ are needed.
+ """
+ if re.search('Sensor Type \(Analog\)', record):
+ return AnalogSdr, self.analog_response_fields
+ else:
+ return None, None
+
+ """
+ Unparsed fields for analog sensors:
+
+ Readable Thresholds : lnr lcr lnc unc ucr unr
+ Settable Thresholds : lnr lcr lnc unc ucr unr
+ Threshold Read Mask : lnr lcr lnc unc ucr unr
+ Assertion Events :
+ Assertions Enabled : unc+ ucr+ unr+
+ Deassertions Enabled : unc+ ucr+ unr+
+ """
+ analog_response_fields = {
+ 'Sensor ID' : {
+ 'attr' : 'sensor_name',
+ 'parser' : sensor_name_parser
+ },
+ 'Entity ID' : {
+ 'attr' : 'entity_id',
+ 'parser' : entity_id_parser
+ },
+ 'Sensor Type (Analog)' : { 'attr' : 'sensor_type' },
+ 'Sensor Reading' : {},
+ 'Status' : {},
+ 'Nominal Reading' : {},
+ 'Normal Minimum' : {},
+ 'Normal Maximum' : {},
+ 'Upper non-recoverable' : {},
+ 'Upper critical' : {},
+ 'Upper non-critical' : {},
+ 'Lower non-recoverable' : {},
+ 'Lower critical' : {},
+ 'Lower non-critical' : {},
+ 'Positive Hysteresis' : {},
+ 'Negative Hysteresis' : {},
+ 'Minimum sensor range' : {},
+ 'Maximum sensor range' : {},
+ 'Event Message Control' : {},
+ }
+
+sdr_commands = {
+ "get_sdr_list" : SdrListCommand
+}
diff --git a/pyipmi/commands/sel.py b/pyipmi/commands/sel.py
new file mode 100644
index 0000000..847468d
--- /dev/null
+++ b/pyipmi/commands/sel.py
@@ -0,0 +1,229 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""This module contains a series of wrappers
+ around SEL commands for ipmitool
+"""
+
+import os
+import re
+import tempfile
+import string
+from pyipmi import Command, IpmiError
+from pyipmi.tools.responseparser import ResponseParserMixIn, str2bool
+from pyipmi.sel import (SELTimestamp, SELInfo, SELAllocInfo, SELRecord,
+ SELOverflowError, SELTimestampError)
+
+
+class SELTimeSetCommand(Command, ResponseParserMixIn):
+ """Describes the Set SEL Time command"""
+
+ name = "Set SEL Time"
+ # TODO: get response data from ipmitool
+
+ @property
+ def ipmitool_args(self):
+ """return args for ipmitool command"""
+ return ["sel", "time", "set", self._params["time"].timestamp]
+
+ def handle_command_error(self, resp, err):
+ raise SELTimestampError(err)
+
+
+class SELTimeGetCommand(Command, ResponseParserMixIn):
+ """Describes the Get SEL Time command"""
+
+ def response_parser(self, resp, err):
+ """A helper function to parse a timestamp returned from
+ an 'sel time get' command
+ """
+
+ return SELTimestamp(resp.strip())
+
+ name = "Get SEL Time"
+ result_type = SELTimestamp
+ ipmitool_args = ["sel", "time", "get"]
+
+
+class SELInfoCommand(Command, ResponseParserMixIn):
+ """Describes the Get SEL Info command"""
+
+ def version_parser(string):
+ vdict = {}
+ vregex = '(?P<number>[12]\.[05]) \((?P<compliant>.+) compliant\)'
+ match = re.match(vregex, string)
+ vdict['number'] = match.group('number')
+ vdict['compliant'] = match.group('compliant').split(', ')
+ return vdict
+
+ name = "SEL Info"
+ ipmitool_args = ["sel", "info"]
+ result_type = SELInfo
+
+ response_fields = {
+ 'Version' : {'parser': version_parser},
+ 'Entries' : {'parser': lambda s: int(s)},
+ 'Free Space' : {'parser': lambda s: int(s[:-6])}, #removes ' bytes'
+ 'Last Add Time' : {'parser': lambda ts: SELTimestamp(ts)},
+ 'Last Del Time' : {'parser': lambda ts: SELTimestamp(ts)},
+ 'Overflow' : {'parser': str2bool},
+ 'Supported Cmds' : {'parser': lambda s: re.findall("\w[ \w]+", s)}
+ }
+
+
+class SELAllocInfoCommand(Command, ResponseParserMixIn):
+ """Describes the sel alloc info command"""
+
+ name = "SEL Alloc Info"
+ ipmitool_args = ["sel", "info"]
+ result_type = SELAllocInfo
+
+ response_fields = {
+ '# of Alloc Units' : {'attr': 'num_alloc_units', 'parser': lambda s: int(s)},
+ 'Alloc Unit Size' : {'parser': lambda s: int(s)},
+ '# Free Units' : {'attr': 'num_free_units', 'parser': lambda s: int(s)},
+ 'Largest Free Blk' : {'parser': lambda s: int(s)},
+ 'Max Record Size' : {'parser': lambda s: int(s)}
+ }
+
+
+class SELAddCommand(Command, ResponseParserMixIn):
+ """Describes the sel add command"""
+
+ #TODO: get response data from ipmitool
+
+ name = "SEL Add"
+
+ def __init__(self, *args, **kwargs):
+ super(SELAddCommand, self).__init__(*args, **kwargs)
+ self._tmpfile = tempfile.NamedTemporaryFile(delete=False)
+
+ for e in self._params['records']:
+ # TODO: handle other types of SEL Records
+ # TODO: allow for malformed SEL entries
+ entry = ('%s %s %s %s %s %s %s' %
+ (hex(e.evm_rev), hex(e.sensor_type), hex(e.sensor_number),
+ hex((e.event_direction << 7) | e.event_type),
+ hex(e.event_data[0]), hex(e.event_data[1]), hex(e.event_data[2])))
+ self._tmpfile.write(str(entry) + '\n')
+ self._tmpfile.flush()
+
+ def __del__(self):
+ os.remove(self._tmpfile.name)
+
+ @property
+ def ipmitool_args(self):
+ """return args for ipmitool command"""
+ return ["sel", "add", self._tmpfile.name]
+
+ def handle_command_error(self, resp, err):
+ if err.find('Out of space') > 0:
+ raise SELOverflowError(err)
+
+ raise IpmiError(err)
+
+
+class SELGetCommand(Command, ResponseParserMixIn):
+ """Describes the sel get command"""
+
+ def event_data_parser(string):
+ data = int(string, 16)
+ return (data >> 16, (data >> 8) & 0xff, data & 0xff)
+
+ def response_parser(self, response, err):
+ if err.find("command failed") > 0:
+ return None
+
+ entry = self.parse_colon_record(response, err)
+ entry.normalize()
+ return entry
+
+
+ direction_parser = lambda d: 0 if d == 'Assertion Event' else 1
+ hex_parser = lambda x: int(x, 16)
+
+ name = "SEL Get"
+ result_type = SELRecord
+
+ @property
+ def ipmitool_args(self):
+ """return args for ipmitool command"""
+ return ["sel", "get"] + list(self._params['record_ids'])
+
+ # TODO: add support for oem records
+ response_fields = {
+ 'SEL Record ID': {'parser': hex_parser, 'attr': 'record_id'},
+ 'Record Type' : {'parser': hex_parser},
+ 'Timestamp': {},
+ 'Generator ID': {'parser': hex_parser},
+ 'EvM Revision': {'parser': hex_parser},
+ 'Sensor Type': {}, #TODO: covert to hex code
+ 'Sensor Number': {'parser': hex_parser},
+ 'Event Type': {}, #TODO: convert to hex code
+ 'Event Direction': {'parser': direction_parser},
+ 'Event Data': {'parser': event_data_parser},
+ 'Description': {}
+ }
+
+
+class SELClearCommand(Command, ResponseParserMixIn):
+ """Describes the Clear SEL command"""
+
+ name = "Clear SEL"
+ ipmitool_args = ["sel", "clear"]
+ # TODO: get response data from ipmitool
+
+
+class SELListCommand(Command, ResponseParserMixIn):
+ """Describes SEL List command
+ note: this command is non-standard
+ """
+
+ def response_parser(self, resp, err):
+ sel_list = resp.strip().split('\n')
+ sel_list = map(string.strip, sel_list)
+ return filter(lambda s: s != '', sel_list) # remove blank entries
+
+ name = "List SEL"
+ ipmitool_args = ["sel", "list"]
+ result_type = list
+
+
+sel_commands = {
+ "set_sel_time" : SELTimeSetCommand,
+ "get_sel_time" : SELTimeGetCommand,
+ "sel_info" : SELInfoCommand,
+ "sel_alloc_info" : SELAllocInfoCommand,
+ "sel_add" : SELAddCommand,
+ "sel_get" : SELGetCommand,
+ "sel_clear" : SELClearCommand,
+ "sel_list" : SELListCommand
+}
diff --git a/pyipmi/commands/sol.py b/pyipmi/commands/sol.py
new file mode 100644
index 0000000..98fdfd8
--- /dev/null
+++ b/pyipmi/commands/sol.py
@@ -0,0 +1,207 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""A series of wrappers around SOL commands"""
+
+from pyipmi import Command, IpmiError
+from pyipmi.tools.responseparser import ResponseParserMixIn, str2bool
+
+
+def bit_rate_parser(bit_rate):
+ """Parse a bit rate returned from ipmitool's "sol info" command"""
+ assert bit_rate in ('IPMI-Over-Serial-Setting', '9.6', '19.2',
+ '38.4', '57.6', '115.2')
+
+ if bit_rate != 'IPMI-Over-Serial-Setting':
+ bit_rate = float(bit_rate)
+ #TODO: maybe find the IPMI-Over-Serial-Setting?
+
+ return bit_rate
+
+def channel_parser(channel):
+ """Parse a channel returned from ipmitool's "sol info" command.
+ Channel format is: "%d (%x)" % (channel, channel)
+ """
+
+ chan, xchan = channel.split(' (')
+ return int(chan)
+
+def bool2str(boolval):
+ """Map True to 'true', False to 'false'"""
+ return str(boolval).lower()
+
+def priv_level_formatter(level):
+ """Format privilege level"""
+ level = level.lower()
+ if level == "administrator":
+ level = "admin"
+ return level
+
+# need to know four ipmitool-specific things about each configuration parameter
+# set_name: name used in ipmitool's "sol set" command
+# get_name: name printed from ipmitool's "sol info" command
+# parser: a function to parse the value printed by ipmitool's "sol info" command
+# formatter: formatter tool-independant values into formats required by tool
+IPMITOOL_SOL_PARAMETERS = {
+ 'set_in_progress': {
+ 'set_name' : 'set-in-progress',
+ 'get_name' : 'Set in progress',
+ 'parser' : lambda s: s.replace('-', '_'),
+ 'formatter' : lambda s: s.replace('_', '-'),
+ },
+ 'enable' : {
+ 'set_name' : 'enabled',
+ 'get_name' : 'Enabled',
+ 'parser' : str2bool,
+ 'formatter' : bool2str,
+ },
+ 'force_encryption' : {
+ 'set_name' : 'force-encryption',
+ 'get_name' : 'Force Encryption',
+ 'parser' : str2bool,
+ 'formatter' : bool2str,
+ },
+ 'force_authentication' : {
+ 'set_name' : 'force-authentication',
+ 'get_name' : 'Force Authentication',
+ 'parser' : str2bool,
+ 'formatter' : bool2str,
+ },
+ 'privilege_level' : {
+ 'set_name' : 'privilege-level',
+ 'get_name' : 'Privilege Level',
+ 'parser' : str,
+ 'formatter' : priv_level_formatter,
+ },
+ 'character_accumulate_interval' : {
+ 'set_name' : 'character-accumulate-level',
+ 'get_name' : 'Character Accumulate Level (ms)',
+ 'parser' : lambda s: int(s) / 5,
+ 'formatter' : str,
+ },
+ 'character_send_threshold' : {
+ 'set_name' : 'character-send-threshold',
+ 'get_name' : 'Character Send Threshold',
+ 'parser' : int,
+ 'formatter' : str,
+ },
+ 'retry_count' : {
+ 'set_name' : 'retry-count',
+ 'get_name' : 'Retry Count',
+ 'parser' : int,
+ 'formatter' : str,
+ },
+ 'retry_interval' : {
+ 'set_name' : 'retry-interval',
+ 'get_name' : 'Retry Interval (ms)',
+ 'parser' : lambda s: int(s) / 10,
+ 'formatter' : str,
+ },
+ 'volatile_bit_rate' : {
+ 'set_name' : 'volatile-bit-rate',
+ 'get_name' : 'Volatile Bit Rate (kbps)',
+ 'parser' : bit_rate_parser,
+ 'formatter' : str,
+ },
+ 'non_volatile_bit_rate' : {
+ 'set_name' : 'non-volatile-bit-rate',
+ 'get_name' : 'Non-Volatile Bit Rate (kbps)',
+ 'parser' : bit_rate_parser,
+ 'formatter' : str,
+ },
+ 'payload_channel' : {
+ 'set_name' : None,
+ 'get_name' : 'Payload Channel',
+ 'parser' : channel_parser,
+ 'formatter' : None,
+ },
+ 'payload_port_number' : {
+ 'set_name' : None,
+ 'get_name' : 'Payload Port',
+ 'parser' : int,
+ 'formatter' : None,
+ }
+}
+
+# TODO: why does atom only work with lanplus, but qemu works on the lan iface?
+# TODO: enable/disable encryption
+IPMITOOL_SOL_ARGS = ["-I", "lanplus", "-C", "0", "sol"]
+
+class SetSOLConfigurationParametersCommand(Command, ResponseParserMixIn):
+ """Describes the Set SOL Configuration Parameters command"""
+
+ # ipmitool handles setting set-in-progress/set-complete for us
+ # however, other tools might not. this is where that'd be handled
+
+ name = "Set SOL Configuration Parameters"
+
+ @property
+ def ipmitool_args(self):
+ param = self._params['param']
+ ipmitool_param = IPMITOOL_SOL_PARAMETERS[param]['set_name']
+ formatter = IPMITOOL_SOL_PARAMETERS[param]['formatter']
+ val = formatter(self._params['value'])
+
+ if param is None:
+ raise IpmiError('ipmitool does not support "sol set %s" ' % param)
+
+ return IPMITOOL_SOL_ARGS + ["set", ipmitool_param, val, 'noguard']
+
+
+class GetSOLConfigurationParametersCommand(Command, ResponseParserMixIn):
+ """Describes the Get SOL Configuration Parameters command"""
+
+ name = "Get SOL Configuration Parameters"
+ ipmitool_args = IPMITOOL_SOL_ARGS + ["info"]
+
+ def parse_results(self, response, err):
+ """Parse the output from "sol info" for the desired parameters,
+ format the result, and return it.
+ """
+ response = response.split('\n')
+ result = {}
+
+ params = self._params['params']
+ for param in params:
+ field = IPMITOOL_SOL_PARAMETERS[param]['get_name']
+ parse = IPMITOOL_SOL_PARAMETERS[param]['parser']
+
+ field_value, = filter(lambda s: s.find(field) == 0, response)
+ field, value = field_value.split(': ')
+ result[param] = parse(value)
+
+ return result
+
+
+sol_commands = {
+ "set_sol_config_params" : SetSOLConfigurationParametersCommand,
+ "get_sol_config_params" : GetSOLConfigurationParametersCommand
+}
diff --git a/pyipmi/commands/user.py b/pyipmi/commands/user.py
new file mode 100644
index 0000000..6ecdbe1
--- /dev/null
+++ b/pyipmi/commands/user.py
@@ -0,0 +1,163 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""user management IPMI commands"""
+
+from .. import Command
+from pyipmi.user import *
+from pyipmi.tools.responseparser import (ResponseParserMixIn,
+ str_to_list,
+ str_to_dict)
+
+
+class UserListCommand(Command, ResponseParserMixIn):
+ """Describes the user list ipmitool command
+ """
+ name = "User List"
+ result_type = UserListResults
+
+ def parse_response(self, out, err):
+ """ Output is a table with a header row:
+ ID Name Callin Link Auth IPMI Msg Channel Priv Limit
+ 1 anonymous true false false NO ACCESS
+ """
+ result = {}
+ for line in out.strip().split('\n')[1:]:
+ user_info = self.result_type()
+
+ user_info_list = line.strip().split()
+ if len(user_info_list) < 5:
+ continue
+
+ key = line[0:3].strip()
+ user_info.name = line[4:20].strip()
+ user_info.callin = line[22:28].strip()
+ user_info.link_auth = line[29:39].strip()
+ user_info.ipmi_msg = line[40:48].strip()
+ user_info.channel_priv_limit = line[51:].strip()
+
+ result[key] = user_info
+
+ return result
+
+ @property
+ def ipmitool_args(self):
+ channel = self._params.get('channel', '')
+ return ["user", "list", channel]
+
+
+class UserSetNameCommand(Command, ResponseParserMixIn):
+ """Describes the user set name ipmitool command
+ """
+ name = "User Set Name"
+ result_type = UserSetNameResults
+
+ response_fields = {
+ 'Field Name' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["user", "set", "name", self._params['userid'],
+ self._params['name']]
+
+
+class UserSetPasswordCommand(Command, ResponseParserMixIn):
+ """Describes the user set password ipmitool command
+ """
+ name = "User Set Password"
+ result_type = UserSetPasswordResults
+
+ response_fields = {
+ 'Field Name' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ password = self._params.get('password', '')
+ return ["user", "set", "password", self._params['userid'], password]
+
+
+class UserDisableCommand(Command, ResponseParserMixIn):
+ """Describes the user disable ipmitool command
+ """
+ name = "User Disable"
+ result_type = UserDisableResults
+
+ response_fields = {
+ 'Field Name' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["user", "disable", self._params['userid']]
+
+
+class UserEnableCommand(Command, ResponseParserMixIn):
+ """Describes the user enable ipmitool command
+ """
+ name = "User Enable"
+ result_type = UserEnableResults
+
+ response_fields = {
+ 'Field Name' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ return ["user", "enable", self._params['userid']]
+
+
+class UserPrivCommand(Command, ResponseParserMixIn):
+ """Describes the user priv ipmitool command
+ """
+ name = "User Set Privileges"
+ result_type = UserPrivResults
+
+ response_fields = {
+ 'Field Name' : {}
+ }
+
+ @property
+ def ipmitool_args(self):
+ channel = self._params.get('channel', '')
+ return ["user", "priv", self._params['userid'],
+ self._params['priv_level'], channel]
+
+
+user_commands = {
+ 'user_list' : UserListCommand,
+ 'user_set_name' : UserSetNameCommand,
+ 'user_set_password' : UserSetPasswordCommand,
+ 'user_enable' : UserEnableCommand,
+ 'user_disable' : UserDisableCommand,
+ 'user_priv' : UserPrivCommand
+}
diff --git a/pyipmi/commands/watchdog.py b/pyipmi/commands/watchdog.py
new file mode 100644
index 0000000..1f3c5c0
--- /dev/null
+++ b/pyipmi/commands/watchdog.py
@@ -0,0 +1,92 @@
+# Copyright (c) 2012, Calxeda Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Calxeda Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+
+
+"""watchdog related commands"""
+
+from .. import Command
+from pyipmi.watchdog import *
+from pyipmi.tools.responseparser import ResponseParserMixIn
+
+
+class WatchdogGetCommand(Command, ResponseParserMixIn):
+ """Describes the watchdog get IPMI command
+
+ This is "mc watchdog get" to ipmitool
+ """
+ name = "Watchdog Get"
+ result_type = WatchdogGetResult
+
+ response_fields = {
+ 'Watchdog Timer Use' : {},
+ 'Watchdog Timer Is' : {},
+ 'Watchdog Timer Actions' : {},
+ 'Pre-timeout interval' : {},
+ 'Timer Expiration Flags' : {},
+ 'Initial Countdown' : {},
+ 'Present Countdown' : {}
+ }
+
+ ipmitool_args = ["mc", "watchdog", "get"]
+
+
+class WatchdogResetCommand(Command, ResponseParserMixIn):
+ """Describes the watchdog rest IPMI command
+
+ This is "mc watchdog reset" to ipmitool
+ """
+ name = "Watchdog Reset"
+ result_type = WatchdogResetResult
+
+ response_fields = {
+ }
+
+ ipmitool_args = ["mc", "watchdog", "reset"]
+
+
+class WatchdogOffCommand(Command, ResponseParserMixIn):
+ """Describes the watchdog off IPMI command
+
+ This is "mc watchdog off" to ipmitool
+ """
+ name = "Watchdog Off"
+ result_type = WatchdogOffResult
+
+ response_fields = {
+ }
+
+ ipmitool_args = ["mc", "watchdog", "off"]
+
+
+watchdog_commands = {
+ 'watchdog_get' : WatchdogGetCommand,
+ 'watchdog_reset' : WatchdogResetCommand,
+ 'watchdog_off' : WatchdogOffCommand
+}