diff --git a/perl-xCAT-2.0/xCAT/Schema.pm b/perl-xCAT-2.0/xCAT/Schema.pm index 7cd5ec911..04e0203c1 100644 --- a/perl-xCAT-2.0/xCAT/Schema.pm +++ b/perl-xCAT-2.0/xCAT/Schema.pm @@ -13,7 +13,7 @@ package xCAT::Schema; cols => [qw(node hcp id profile parent comments disable)], keys => [qw(node)], }, - ppcdirect => { + ppcDirect => { cols => [qw(hcp username password comments disable)], keys => [qw(hcp)], }, @@ -26,8 +26,8 @@ package xCAT::Schema; keys => [qw(node)], }, iscsi => { - cols => [qw(node server target userid passwd comments disable)], - keys => [qw(node)], + cols => [qw(node server target userid passwd comments disable)], + keys => [qw(node)], }, vpd => { cols => [qw(node serial mtm comments disable)], @@ -65,6 +65,14 @@ package xCAT::Schema; cols => [qw(netname net mask gateway dhcpserver tftpserver nameservers dynamicrange comments disable)], keys => [qw(net mask)] }, + osimage => { + cols => [qw(imagename osname osvers osdistro osarch comments disable)], + keys => [qw(imagename)] + }, + nodegroup => { + cols => [qw(groupname grouptype members wherevals comments disable)], + keys => [qw(groupname)] + }, switch => { cols => [qw(node switch vlan port comments disable)], keys => [qw(node switch port)] @@ -77,6 +85,10 @@ package xCAT::Schema; cols => [qw(key value comments disable)], keys => [qw(key)] }, +# site => { +# cols => [qw(sitename domain master rsh rcp xcatdport installdir comments disable)], +# keys => [qw(sitename)] +# }, passwd => { cols => [qw(key username password comments disable)], keys => [qw(key)] @@ -138,226 +150,442 @@ package xCAT::Schema; node => { attrs => [], attrhash => {}, objkey => 'node' }, osimage => { attrs => [], attrhash => {}, objkey => 'imagename' }, network => { attrs => [], attrhash => {}, objkey => 'netname' }, - site => { attrs => [], attrhash => {}, objkey => 'master' } + group => { attrs => [], attrhash => {}, objkey => 'groupname' }, + site => { attrs => [], attrhash => {}, objkey => 'master' }, +#site => { attrs => [], attrhash => {}, objkey => 'sitename' }, + policy => { attrs => [], attrhash => {}, objkey => 'priority' }, + notification => { attrs => [], attrhash => {}, objkey => 'filename' } ); -############# -# TODO: Need to figure out how to map the following to data objects: -# nodetype table (does this get moved to the osimage table?) -# --> do we need an arch attr per node that is stored in nodehm? -# mac table (are we going to have an interface object definition?) -# switch table (each interface on a node can have its own switch -# table entry, part of interface object, too?) -# username/password from password, hmc, ivm, mpa, and ipmi tables -# (do we need special encryption and display masking for passwords?) -# chain table (I think this is internal use only, do not abstract?) -# noderes entries for kernel, initrd, kcmdline -# ppc table (waiting on Scot to add to tabspec) -# policy table - ? do we need a data abstraction for this? -# notification - is this handled by Ling's commands? -# site - need to figure out what entries we will have in the -# site table since they are not listed individually in the -# tabspec -# nodelist.groups -# new group table and object -# new osimage table and object -############### -# TODO: need to fill out all the "description" fields -# These will be used for verbose usage with the def* cmds -############## @{$defspec{node}->{'attrs'}} = ( - {attr_name => 'node', + {attr_name => 'node', tabentry => 'nodelist.node', - access_tabentry => 'objkeyvalue'}, -############ -# TODO: The attr name for nodelist.nodetype is in conflict with the existing -# nodetype table. With the osimage table, the nodetype table should go -# away. Will reuse of this name cause confusion for xcat users? -############ - {attr_name => 'nodetype', + access_tabentry => 'nodelist.node=attr:node', + description => 'The name of this node definition.'}, + {attr_name => 'nodetype', tabentry => 'nodelist.nodetype', access_tabentry => 'nodelist.node=attr:node', - description => 'Type of node: osi,hmc,fsp,mpa,???'}, - {attr_name => 'xcatmaster', + description => 'Specifies a comma-separated list of node type values. (Valid values: osi, hmc, fsp, blade, vm, lpar, ivm, bpa, mm, rsa, switch)'}, + {attr_name => 'groups', + tabentry => 'nodelist.groups', + access_tabentry => 'nodelist.node=attr:node', + description => 'Comma separated list of groups this node belongs to.'}, + {attr_name => 'xcatmaster', tabentry => 'noderes.xcatmaster', - access_tabentry => 'noderes.node=attr:node'}, - {attr_name => 'servicenode', + access_tabentry => 'noderes.node=attr:node', + description => 'The hostname of the xCAT management node.'}, +# {attr_name => 'mgtnet', +# tabentry => 'noderes.mgtnet', +# access_tabentry => 'noderes.node=attr:node', +# description => 'The name of the xCAT network definition for this node.'}, + {attr_name => 'servicenode', tabentry => 'noderes.servicenode', - access_tabentry => 'noderes.node=attr:node'}, - {attr_name => 'mgt', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'kernel', + tabentry => 'noderes.kernel', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'initrd', + tabentry => 'noderes.initrd', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'kcmdline', + tabentry => 'noderes.kcmdline', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'mgt', tabentry => 'nodehm.mgt', - access_tabentry => 'nodehm.node=attr:node'}, - {attr_name => 'power', + access_tabentry => 'nodehm.node=attr:node', + description => 'Specifies the hardware management method.'}, + {attr_name => 'power', tabentry => 'nodehm.power', - access_tabentry => 'nodehm.node=attr:node'}, - {attr_name => 'cons', + access_tabentry => 'nodehm.node=attr:node', + description => 'Specifies the power method.'}, + {attr_name => 'cons', tabentry => 'nodehm.cons', - access_tabentry => 'nodehm.node=attr:node'}, - {attr_name => 'termserver', + access_tabentry => 'nodehm.node=attr:node', + description => 'Specifies the console method.'}, + {attr_name => 'termserver', tabentry => 'nodehm.termserver', - access_tabentry => 'nodehm.node=attr:node'}, - {attr_name => 'termport', + access_tabentry => 'nodehm.node=attr:node', + description => 'The name of the terminal server.'}, + {attr_name => 'termport', tabentry => 'nodehm.termport', - access_tabentry => 'nodehm.node=attr:node'}, - {attr_name => 'conserver', + access_tabentry => 'nodehm.node=attr:node', + description => '??????.'}, + {attr_name => 'conserver', tabentry => 'nodehm.conserver', - access_tabentry => 'nodehm.node=attr:node'}, - {attr_name => 'getmac', + access_tabentry => 'nodehm.node=attr:node', + description => '??????.'}, + {attr_name => 'getmac', tabentry => 'nodehm.getmac', - access_tabentry => 'nodehm.node=attr:node'}, - {attr_name => 'serialport', + access_tabentry => 'nodehm.node=attr:node', + description => '??????.'}, + {attr_name => 'serialport', tabentry => 'noderes.serialport', - access_tabentry => 'noderes.node=attr:node'}, - {attr_name => 'serialspeed', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'serialspeed', tabentry => 'nodehm.serialspeed', - access_tabentry => 'nodehm.node=attr:node'}, - {attr_name => 'serialflow', + access_tabentry => 'nodehm.node=attr:node', + description => '??????.'}, + {attr_name => 'serialflow', tabentry => 'nodehm.serialflow', - access_tabentry => 'nodehm.node=attr:node'}, - {attr_name => 'ip', + access_tabentry => 'nodehm.node=attr:node', + description => '??????.'}, + {attr_name => 'ip', tabentry => 'hosts.ip', - access_tabentry => 'hosts.node=attr:node'}, - {attr_name => 'hostnames', + access_tabentry => 'hosts.node=attr:node', + description => '??????.'}, + {attr_name => 'hostnames', tabentry => 'hosts.hostnames', - access_tabentry => 'hosts.node=attr:node'}, - {attr_name => 'serialnumber', + access_tabentry => 'hosts.node=attr:node', + description => '??????.'}, + {attr_name => 'serialnumber', tabentry => 'vpd.serial', - access_tabentry => 'vpd.node=attr:node'}, - {attr_name => 'mtm', + access_tabentry => 'vpd.node=attr:node', + description => '??????.'}, + {attr_name => 'mtm', tabentry => 'vpd.mtm', - access_tabentry => 'vpd.node=attr:node'}, - {attr_name => 'rackloc', + access_tabentry => 'vpd.node=attr:node', + description => '??????.'}, + {attr_name => 'rackloc', tabentry => 'nodepos.rack', - access_tabentry => 'nodepos.node=attr:node'}, - {attr_name => 'unitloc', + access_tabentry => 'nodepos.node=attr:node', + description => '??????.'}, + {attr_name => 'unitloc', tabentry => 'nodepos.u', - access_tabentry => 'nodepos.node=attr:node'}, - {attr_name => 'chassisloc', + access_tabentry => 'nodepos.node=attr:node', + description => '??????.'}, + {attr_name => 'chassisloc', tabentry => 'nodepos.chassis', - access_tabentry => 'nodepos.node=attr:node'}, - {attr_name => 'slotloc', + access_tabentry => 'nodepos.node=attr:node', + description => '??????.'}, + {attr_name => 'slotloc', tabentry => 'nodepos.slot', - access_tabentry => 'nodepos.node=attr:node'}, - {attr_name => 'roomloc', + access_tabentry => 'nodepos.node=attr:node', + description => '??????.'}, + {attr_name => 'roomloc', tabentry => 'nodepos.room', - access_tabentry => 'nodepos.node=attr:node'}, + access_tabentry => 'nodepos.node=attr:node', + description => '??????.'}, + {attr_name => 'usercomment', + tabentry => 'nodelist.comments', + access_tabentry => 'nodelist.node=attr:node', + description => 'User comment.'}, + {attr_name => 'interface', + tabentry => 'mac.interface', + access_tabentry => 'mac.node=attr:node', + description => 'The Ethernet adapter interface name that will be used to install and manage the node. (For example, eth0 or en0.)'}, + {attr_name => 'mac', + tabentry => 'mac.mac', + access_tabentry => 'mac.node=attr:node', + description => 'The machine address of the network adapter used for deployment.'}, + {attr_name => 'currstate', + tabentry => 'chain.currstate', + access_tabentry => 'chain.node=attr:node', + description => '?????'}, + {attr_name => 'currchain', + tabentry => 'chain.currchain', + access_tabentry => 'chain.node=attr:node', + description => '?????'}, + {attr_name => 'chain', + tabentry => 'chain.chain', + access_tabentry => 'chain.node=attr:node', + description => '?????'}, + {attr_name => 'ondiscover', + tabentry => 'chain.ondiscover', + access_tabentry => 'chain.node=attr:node', + description => '?????'}, # Conditional attributes: # OSI node attributes: - {attr_name => 'tftpserver', + + {attr_name => 'tftpserver', only_if => 'nodetype=osi', tabentry => 'noderes.tftpserver', - access_tabentry => 'noderes.node=attr:node'}, - {attr_name => 'nfsserver', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'nfsserver', only_if => 'nodetype=osi', tabentry => 'noderes.nfsserver', - access_tabentry => 'noderes.node=attr:node'}, - {attr_name => 'nfsdir', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'nfsdir', only_if => 'nodetype=osi', tabentry => 'noderes.nfsdir', - access_tabentry => 'noderes.node=attr:node'}, - {attr_name => 'primarynic', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'primarynic', only_if => 'nodetype=osi', tabentry => 'noderes.primarynic', - access_tabentry => 'noderes.node=attr:node'}, - {attr_name => 'installnic', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'installnic', only_if => 'nodetype=osi', tabentry => 'noderes.installnic', - access_tabentry => 'noderes.node=attr:node'}, - {attr_name => 'netboot', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'netboot', only_if => 'nodetype=osi', tabentry => 'noderes.netboot', - access_tabentry => 'noderes.node=attr:node'}, - {attr_name => 'current_osimage', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'current_osimage', only_if => 'nodetype=osi', tabentry => 'noderes.current_osimage', - access_tabentry => 'noderes.node=attr:node'}, - {attr_name => 'next_osimage', + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, + {attr_name => 'next_osimage', only_if => 'nodetype=osi', tabentry => 'noderes.next_osimage', - access_tabentry => 'noderes.node=attr:node'}, + access_tabentry => 'noderes.node=attr:node', + description => '??????.'}, # Hardware Control node attributes: - {attr_name => hdwctrlpoint, - only_if => 'mgtmethod=mp', - tabentry => 'mp.mpa', - access_tabentry => 'mp.node=attr:node'}, -# {attr_name => hdwctrlpoint, + +# add hcp username password id profile mgt + + {attr_name => hcp, + only_if => 'mgt=hmc', + tabentry => 'ppc.hcp', + access_tabentry => 'ppc.node=attr:node', + description => 'The host name or IP address of the network interface for the hardware control point.'}, + {attr_name => id, + only_if => 'mgt=hmc', + tabentry => 'ppc.id', + access_tabentry => 'ppc.node=attr:node', + description => '?????'}, + {attr_name => profile, + only_if => 'mgt=hmc', + tabentry => 'ppc.profile', + access_tabentry => 'ppc.node=attr:node', + description => '?????'}, + {attr_name => id, + only_if => 'mgt=hmc', + tabentry => 'ppc.id', + access_tabentry => 'ppc.node=attr:node', + description => '?????'}, + + +# {attr_name => hdwctrlpoint, # only_if => 'mgtmethod=hmc', # tabentry => 'ppc.hcp', # access_tabentry => 'ppc.node=attr:node'}, - {attr_name => hdwctrlpoint, + {attr_name => hdwctrlpoint, only_if => 'mgtmethod=ipmi', tabentry => 'ipmi.bmc', access_tabentry => 'ipmi.node=attr:node'}, - {attr_name => hdwctrlnodeid, + {attr_name => hdwctrlnodeid, only_if => 'mgtmethod=mp', tabentry => 'mp.id', - access_tabentry => 'mp.node=attr:node'}, -# {attr_name => hdwctrlnodeid, + access_tabentry => 'mp.node=attr:node', + description => '??????.'}, +# {attr_name => hdwctrlnodeid, # only_if => 'mgtmethod=hmc', # tabentry => 'ppc.id', # access_tabentry => 'ppc.node=attr:node'} ); @{$defspec{osimage}->{'attrs'}} = ( - {attr_name => 'imagename', + {attr_name => 'imagename', tabentry => 'osimage.imagename', - access_tabentry => 'objkeyvalue', - description => 'Name of OS image'}, - {attr_name => 'osdistro', + access_tabentry => 'osimage.imagename=attr:imagename', + description => 'The name of this operating system image.'}, + {attr_name => 'osdistro', tabentry => 'osimage.osdistro', - access_tabentry => 'osimage.objname=attr:imagename'}, + access_tabentry => 'osimage.imagename=attr:imagename', + description => 'The Linux distribution name to be deployed. The valid values are RedHat, and SLES.'}, + {attr_name => 'osname', + tabentry => 'osimage.osname', + access_tabentry => 'osimage.imagename=attr:imagename', + description => 'The name of the operating system to be deployed. The expected values are AIX or Linux.'}, + {attr_name => 'osvers', + tabentry => 'osimage.osvers', + access_tabentry => 'osimage.imagename=attr:imagename', + description => 'The operating system version to be deployed. The formats for the values are "version.release.mod" for AIX and "version" for Linux. (ex. AIX: "5.3.0", Linux: "5").'}, + {attr_name => 'osarch', + tabentry => 'osimage.osarch', + access_tabentry => 'osimage.imagename=attr:imagename', + description => 'The node machine architecture.'}, + {attr_name => 'usercomment', + tabentry => 'osimage.comments', + access_tabentry => 'osimage.imagename=attr:imagename', + description => 'User comment.'}, ); @{$defspec{network}->{'attrs'}} = ( - {attr_name => 'netname', + {attr_name => 'netname', tabentry => 'networks.netname', - access_tabentry => 'objkeyvalue', - description => 'Name to identify the network'}, - {attr_name => 'net', + access_tabentry => 'networks.netname=attr:netname', + description => 'Name used to identify this network definition.'}, + {attr_name => 'net', tabentry => 'networks.net', - access_tabentry => 'networks.netname=attr:netname'}, - {attr_name => 'mask', + access_tabentry => 'networks.netname=attr:netname', + description => '??????.'}, + {attr_name => 'mask', tabentry => 'networks.mask', - access_tabentry => 'networks.netname=attr:netname'}, - {attr_name => 'gateway', + access_tabentry => 'networks.netname=attr:netname', + description => 'The network mask.'}, + {attr_name => 'gateway', tabentry => 'networks.gateway', - access_tabentry => 'networks.netname=attr:netname'}, - {attr_name => 'dhcpserver', + access_tabentry => 'networks.netname=attr:netname', + description => 'Specifies the hostname or IP address of the network gateway.'}, + {attr_name => 'dhcpserver', tabentry => 'networks.dhcpserver', - access_tabentry => 'networks.netname=attr:netname'}, - {attr_name => 'tftpserver', + access_tabentry => 'networks.netname=attr:netname', + description => '??????.'}, + {attr_name => 'tftpserver', tabentry => 'networks.tftpserver', - access_tabentry => 'networks.netname=attr:netname'}, - {attr_name => 'nameservers', + access_tabentry => 'networks.netname=attr:netname', + description => '??????.'}, + {attr_name => 'nameservers', tabentry => 'networks.nameservers', - access_tabentry => 'networks.netname=attr:netname'}, - {attr_name => 'dynamicrange', + access_tabentry => 'networks.netname=attr:netname', + description => '??????.'}, + {attr_name => 'dynamicrange', tabentry => 'networks.dynamicrange', - access_tabentry => 'networks.netname=attr:netname'}, + access_tabentry => 'networks.netname=attr:netname', + description => '??????.'}, + {attr_name => 'usercomment', + tabentry => 'networks.comments', + access_tabentry => 'networks.netname=attr:netname', + description => 'User comment.'}, ); -############## -# TODO: need to figure out how to handle a key for the site table. -# since this is really implemented differently than all the other -# data objects, it doesn't map as cleanly. -# change format of site table so each column is an attr and there -# is only a single row in the table keyed by xcatmaster name? -############# @{$defspec{site}->{'attrs'}} = ( - {attr_name => 'master', + {attr_name => 'key', + tabentry => 'site.key', + access_tabentry => 'site.key=attr:key', + description => 'The name of the attribute.'}, + {attr_name => 'value', tabentry => 'site.value', - access_tabentry => 'site.key=str:master', - description => 'The management node'}, - {attr_name => 'installdir', - tabentry => 'site.value', - access_tabentry => 'site.key=str:installdir', - description => 'The installation directory'}, - {attr_name => 'xcatdport', - tabentry => 'site.value', - access_tabentry => 'site.key=str:xcatdport', - description => 'Port used by xcatd daemon on master'}, + access_tabentry => 'site.key=attr:key', + description => 'The value of the attribute.'}, + {attr_name => 'comments', + tabentry => 'site.comments', + access_tabentry => 'site.key=attr:key', + description => 'User comments.'}, +); + +#@{$defspec{site}->{'attrs'}} = ( +# {attr_name => 'sitename', +# tabentry => 'site.sitename', +# access_tabentry => 'site.sitename=attr:sitename', +# description => 'Name of this xCAT cluster site definition.'}, +# {attr_name => 'master', +# tabentry => 'site.master', +# access_tabentry => 'site.sitename=attr:sitename', +# description => 'The name of the xCAT management node.'}, +# {attr_name => 'domain', +# tabentry => 'site.domain', +# access_tabentry => 'site.sitename=attr:sitename', +# description => 'The DNS domain name for this cluster.'}, +# {attr_name => 'installdir', +# tabentry => 'site.installdir', +# access_tabentry => 'site.sitename=attr:sitename', +# description => 'The installation directory.'}, +# {attr_name => 'rsh', +# tabentry => 'site.rsh', +# access_tabentry => 'site.sitename=attr:sitename', +# description => 'Specifies the path of the remote shell command to use.'}, +# {attr_name => 'rcp', +# tabentry => 'site.rcp', +# access_tabentry => 'site.sitename=attr:sitename', +# description => 'Specifies the path of the remote copy command to use.'}, +# {attr_name => 'xcatdport', +# tabentry => 'site.xcatdport', +# access_tabentry => 'site.sitename=attr:sitename', +# description => 'The port used by xcatd daemon running on the xCAT management node.'}, +# {attr_name => 'usercomment', +# tabentry => 'site.comments', +# access_tabentry => 'site.sitename=attr:sitename', +# description => 'User comment.'}, +# ); + + +@{$defspec{group}->{'attrs'}} = ( + {attr_name => 'groupname', + tabentry => 'nodegroup.groupname', + access_tabentry => 'nodegroup.groupname=attr:groupname', + description => 'The name of this xCAT group object definition.'}, + {attr_name => 'grouptype', + tabentry => 'nodegroup.grouptype', + access_tabentry => 'nodegroup.groupname=attr:groupname', + description => 'The type of xCAT group - either "static" or "dynamic".'}, + {attr_name => 'members', + tabentry => 'nodegroup.members', + access_tabentry => 'nodegroup.groupname=attr:groupname', + description => 'The list of members for this group.'}, + {attr_name => 'wherevals', + tabentry => 'nodegroup.wherevals', + access_tabentry => 'nodegroup.groupname=attr:groupname', + description => 'A list of comma-separated "attr=val" pairs that can be used to determine the members of a dynamic group.'}, + {attr_name => 'usercomment', + tabentry => 'nodegroup.comments', + access_tabentry => 'nodegroup.groupname=attr:groupname', + description => 'User comment.'}, + +# +# Node attrs that can be used with static groups - from above!!!! +# + ); + +@{$defspec{policy}->{'attrs'}} = ( + {attr_name => 'priority', + tabentry => 'policy.priority', + access_tabentry => 'policy.priority=attr:priority', + description => '??????.'}, + {attr_name => 'name', + tabentry => 'policy.name', + access_tabentry => 'policy.priority=attr:priority', + description => '??????.'}, + {attr_name => 'host', + tabentry => 'policy.host', + access_tabentry => 'policy.priority=attr:priority', + description => '??????.'}, + {attr_name => 'commands', + tabentry => 'policy.commands', + access_tabentry => 'policy.priority=attr:priority', + description => '??????.'}, + {attr_name => 'noderange', + tabentry => 'policy.noderange', + access_tabentry => 'policy.priority=attr:priority', + description => '??????.'}, + {attr_name => 'parameters', + tabentry => 'policy.parameters', + access_tabentry => 'policy.priority=attr:priority', + description => '??????.'}, + {attr_name => 'time', + tabentry => 'policy.time', + access_tabentry => 'policy.priority=attr:priority', + description => '??????.'}, + {attr_name => 'rule', + tabentry => 'policy.rule', + access_tabentry => 'policy.priority=attr:priority', + description => '??????.'}, + {attr_name => 'usercomment', + tabentry => 'policy.comments', + access_tabentry => 'policy.priority=attr:priority', + description => 'User comment.'}, ); - +@{$defspec{notification}->{'attrs'}} = ( + {attr_name => 'filename', + tabentry => 'notification.filename', + access_tabentry => 'notification.filename=attr:filename', + description => 'Specifies a file that implements the callback routine when the monitored table changes.'}, + {attr_name => 'tables', + tabentry => 'notification.tables', + access_tabentry => 'notification.filename=attr:filename', + description => 'The name of the xCAT database table to monitor.'}, + {attr_name => 'tableops', + tabentry => 'notification.tableops', + access_tabentry => 'notification.filename=attr:filename', + description => 'Specifies the table operation to monitor. It can be "d" for rows deleted, "a" for rows added or "u" for rows updated.'}, + {attr_name => 'comments', + tabentry => 'notification.comments', + access_tabentry => 'notification.filename=attr:filename', + description => 'User comment.'}, + );