Contents
There are multiple possible approaches to multi domain support. Here we will list various proposals until we figure out which to implement in OpenHPI. Please feel free to add your own by creating a subpage with your own username here.
Proposals
SeanDague's proposal
Problem Statement
The problem we are trying to solve is adding Multiple Domain support in OpenHPI. The will allow resources and events to exist in domains other than the default domain.
The reason this support is interesting is that a piece of hardware may want to represent it's component parts as seperate Domains. A good example piece of hardware would be a Bladed Chassis, where a single connection to the CMM provides management for a large number (> 10) blades. The hardware may wish to model this via simple resources, or via domains, however the decision on what is the *correct* system model should be left to the hardware itself.
Top Down Approach
Multiple domain support has been looked at since the beginning of OpenHPI. In most cases a Top Down approach was first considered. This is unworkable because:
- it adds yet another level of configuration hacking for the end user. Honestly, we need to make bring up easier, not more painful.
- it complete disregards the plugin author's ideas of how things should be modeled. This policy should be as close to the hardware as possible (in the hardware would be great.)
- it requires containers for domains be only as small as a handler. For the Bladed Chassis setup above, it completely gets rid of this concept.
While it is simpler to develop, this is the wrong approach. It is worth noting that OpenHPI 0.1 had this concept of oh_zone, which was domains as handlers. After spinning on that for 3 months it was thrown out, as we created a number of scenarios that were impossible to model with that approach.
Bottom Up Approach
If not top down, then bottom up is the other natural way to go with this. In this regard think of domain ids similar to device ids in the Linux Kernel. If you want to use hardware devices, and you aren't already allocated them (i.e. IDE), you need to request an id from the kernel. Once it gives you this back you are then free to use dev nodes with that major number for your device driver.
In OpenHPI this could be accomplished by 2 function calls implemented in the infrastructure that are exported to plugins:
SaHpiDomainIdT oh_request_domain_id(unsigned int handler_id, SaHpiDomainIdT parentid, SaHpiDomainIdT peerid); SaErrorT oh_release_domain_id(unsigned int handler_id, SaHpiDomainIdT did);
The first function is the requests a domain id to be allocated. If peerid is 0, it isn't a peer domain. If parentid is 0, it is a child of DEFAULT_DOMAIN. The domain id is returned to the handler, and it is allowed to then have events with that did set in them.
Infrastructure would keep the table of allowed did for each handler id, and when the event loop is processed it will reject any dids not allowed for each handler. This table will also alow calls like saHpiDiscover to only have to call the appropriate subset of handlers when a domain other than default is called for discovery. Due to the nature of the OpenHPI implementation, Discover called on the DEFAULT_DOMAIN will be equivalent to discover called on all domains.
This will allow arbitrarily complex domain structures, which will be entirely managed by the handlers. If you want that kind of complexity, you can do it yourself very nicely. For those that don't want that, they can just keep writing plugins like they are today.
VadimRevyakin's proposal
Here is example of openhpi.config file to create multiple domain structure.
Comments in this file describe how to write it.
## File format is outlined here and examples are given
## First section, declare global parameters like the following.
#OPENHPI_LOG_ON_SEV = "MINOR"
#OPENHPI_ON_EP = "{SYSTEM_CHASSIS,1}"
#OPENHPI_EVT_QUEUE_LIMIT = "0"
#OPENHPI_DEL_SIZE_LIMIT = "0"
#OPENHPI_DEL_SAVE = "NO"
#OPENHPI_DAT_SIZE_LIMIT = "0"
#OPENHPI_DAT_USER_LIMIT = "0"
#OPENHPI_THREADED = "NO"
#OPENHPI_PATH = "/usr/local/lib/openhpi:/usr/lib/openhpi"
#OPENHPI_VARPATH = "/usr/local/var/lib/openhpi"
## The default values for each have been selected in the example above (except
## for OPENHPI_PATH and OPENHPI_CONF. See below).
## No need to specify any one of them because the default will be used
## automatically. The library will also look for these as environment variables.
## Environment variables found that match a global parameter will override the
## corresponding parameter set in this configuration file.
##
## OPENHPI_LOG_SEV sets the lowest severity level an event must meet to be
## logged in the domain event log. Possible values are (highest to lowest):
## "CRITICAL", "MAJOR", "MINOR", "INFORMATIONAL", "OK", and "DEBUG".
## OPENHPI_ON_EP sets the entity path on wich the application is running. This
## entity path will be returned when SaHpiResourceIdGet() is called.
## OPENHPI_EVT_QUEUE_LIMIT sets the maximum number of events that are allowed
## in the session's event queue. "0" means unlimited.
## OPENHPI_DEL_SIZE_LIMIT sets the maximum size (in number of event log entries)
## for the domain event log. "0" means unlimited.
## OPENHPI_DEL_SAVE sets wether the domain event log will be persisted to disk or
## not. The event log is written to OPENHPI_VARPATH value.
## OPENHPI_DAT_SIZE_LIMIT sets the maximum size (in number of alarm entries) for
## the alarm table. "0" means unlimited.
## OPENHPI_DAT_USER_LIMIT sets the maximum number of user type alarm entries
## allowed in the alarm table.
## OPENHPI_THREADED sets whether a thread is used for handling the event loop.
## This thread will be looping around the plugin instances and fetching events.
## OPENHPI_PATH is a colon (:) delimited list of directories specifying
## the location of openhpi plugin libraries. The default is defined when the
## library is configured.
## OPENHPI_VARPATH is a directory to which certain openhpi data will be saved to.
## At this point, only the DEL is saved to this directory. The default is set at
## compile time through the ./configure options.
## Second section, declare plugin to use. For example:
## plugin plugin-name
plugin libdummy
## Depends on openipmi to be installed on this system:
#plugin libipmi
## Depends on net-snmp being installed on the system:
#plugin libsnmp_bc
## Depends openhpi being configured
## (e.g "configure --enable-dummy=static")
#plugin dummy
#plugin libipmidirect
## Third section is a domain declaration. Each domain has a unique name in
## config file. This name is used only in config file to assign plugin handlers
## to domain and describe domain tree structure. Domain declaration can have
## argument "tag". Domain can be created as a child of another domain by using
## "child_of" expression. So the syntax:
##
## domain <domain_name> [child_of <parent_domain_name>] {
## [tag = "Tag of new domain"]
## }
## Domain declaration can in any place of config file.
## if child_of is missed new domain will be a child of root (default) domain.
## if child_of is used domain <parent_domain_name> must be declared above.
## if tag is missed new domain will have tag = <domain_name>.
## Here are some examples of domain declaration
##
## These domains will be the children of root domain
##
## domain Servers {
## tag = "Production server room"
## }
##
## domain Labs {
## tag = "Developer labs"
## }
##
## The following domains will be the children of Labs domain
##
## domain Lab1 child_of Labs {
## tag = "Second floor lab"
## }
##
## domain Lab2 child_of Labs {
## tag = "Third floor lab"
## }
## Forth section is a handler (instance) declaration. It has the following syntax:
## handler <plugin_name> [new_domain | assigned_to <domain_name>] {
## [argument_name = argument_value]
## [argument_name = argument_value]
## .........
## }
##
## Arguments are understood by plugin. Strings are enclosed by "", numbers are not.
#############################################################################
##**WARNING** System administrators have to make sure that entity paths are
## unique in a domain. To avoid entity paths conflicting among handlers, make
## sure the "entity_root" is unique for each handler definition.
#############################################################################
## If new_domain and assigned_to are missed the plugin is assigned to the root domain.
## If new_domain is used the plugin is assigned to the new domain which is the child
## of the root domain.
## If assigned_to is used the plugin is assigned to domain <domain_name>.
## domain <domain_name> must be declared in config file below or above plugin
## declaration.
## Each plugin handler can create it's own domains. These domains are not described
## in config file. They can be created in run time. All these domains will be the
## children of domain the handler assigned to.
handler libdummy {
entity_root = "{SYSTEM_CHASSIS,1}"
name = "test"
addr = 0
}
## Dummy allows you open second virtual by addr 1
#handler libdummy {
# entity_root = "{SYSTEM_CHASSIS,2}"
# addr = 1
#}
## This handler will be assigned to described above domain Lab1
#handler libdummy assigned_to Lab1 {
# entity_root = "{SYSTEM_CHASSIS,3}"
# addr = 2
##}
## Section for ipmi plugin using SMI -- local interface
#handler libipmi {
# entity_root = "{SYSTEM_CHASSIS,2}"
# name = "smi"
# addr = 0
#}
## Section for ipmi plugin based on OpenIPMI:
#handler libipmi {
# entity_root = "{SYSTEM_CHASSIS,3}"
# name = "lan"
# addr = "x.x.x.x" #ipaddress
# port = 999
# auth_type = "straight"
# auth_level= "user"
# username = "joe"
# password = "blow"
#}
## Section for snmp_bc plugin:
## The root entry can be omitted in 'entity_root',
## but *not* the chassis entry.
#handler libsnmp_bc {
# entity_root = "{SYSTEM_CHASSIS,4}" # Required
# host = "bc.ibm.com" # Required
# community = "community" # Version 1 Required.
# version = "1" # Required. SNMP protocol version (1|3)
# security_name = "snmpv3_user" # Version 3 Required.
# passphrase = "opensesame" # Version 3. Required if security_level is authNoPriv or authPriv.
# auth_type = "MD5" # Version 3. Passphrase encoding (MD5|SHA)
# security_level = "noAuthNoPriv" # Version 3. (noAuthNoPriv|authNoPriv|authPriv)
#}
## Section for static dummy plugin:
## If openhpi configured with
## configure --enable-dummy=static
## the dummy plugin is compiled in.
## It is possible to use dummy and libdummy
## at the same time.
#handler dummy {
# entity_root = "{SYSTEM_CHASSIS,5}"
# name = "test"
# addr = 2
#}
## Section for ipmidirect plugin using SMI -- local interface
#handler libipmidirect {
# entity_root = "{SYSTEM_CHASSIS,6}"
# name = "smi"
# addr = 0
#}
## Section for ipmidirect plugin using RMCP:
#handler libipmidirect {
# entity_root = "{SYSTEM_CHASSIS,7}"
# name = "lan" # RMCP
# addr = "localhost" # ipaddress
# port = "623" # RMCP port
# auth_type = "none" # none, md2, md5 or straight
# auth_level = "admin" # none, callback, user, operator or admin
# username = "arthur"
# password = "pieman"
# logflags = "" # logging off
# # logflags = "file stdout"
# # infos goes to logfile and stdout
# # the logfile are log00.log, log01.log ...
# # if #logfile_max reached replace the oldest one
# logfile = "log"
# logfile_max = 10
#}
