2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-05 04:27:55 +00:00
Commit Graph

7014 Commits

Author SHA1 Message Date
Vinícius Ferrão 4824e836ce fix(rinv): report pending UEFI build separately
The IMM pending_build_id property is not guaranteed to identify the primary UEFI bank. Keep it out of the active version value and expose it as a separate firmware inventory record.

Recovered from original commit b79c005061 by Jarrod Johnson.

Co-authored-by: Jarrod Johnson <jarrod.b.johnson@gmail.com>
2026-08-30 22:22:39 -03:00
Vinícius Ferrão b7aa8eaa0f refactor(xcatd): keep command response state in CmdLog
Own collection, sensitivity, finalization, and reset as one request-scoped state object so xcatd only forwards callbacks and appends the finalized text.
2026-08-29 17:41:03 -03:00
Vinícius Ferrão 916091bfec refactor(xcatd): expose command log response handling 2026-08-29 17:15:23 -03:00
Vinícius Ferrão c878dbf808 Merge pull request #7747 from VersatusHPC/fix/template-default-httpport
fix(template): omit the default HTTP port from installer URLs
2026-08-29 16:45:16 -03:00
Daniel Hilst 1ba53dc7f8 Merge pull request #7754 from VersatusHPC/fix/centos8-minor-version-detection
fix(anaconda): read the CentOS Linux minor version from the release package
2026-08-28 17:38:16 -03:00
Vinícius Ferrão 999f18eacd Merge pull request #7737 from VersatusHPC/fix/cmdlog-response-classifier
fix(xcatd): classify secret responses by the shared secret set
2026-08-28 17:34:56 -03:00
Daniel Hilst a9a2c1f74e Merge pull request #7732 from VersatusHPC/fix/noderange-preauth
fix(xcatd): refuse the noderange ^file operator on unauthenticated requests
2026-08-28 17:32:33 -03:00
Vinícius Ferrão ae06a1edcb fix(anaconda): read the CentOS Linux minor version from the release package
Every CentOS Linux 8 medium gives the same description, "CentOS Linux 8".
The description gives no minor version. The .treeinfo file on the medium
gives no minor version. Thus copycds gave the name centos8 to all of these
media. Two CentOS Linux 8 media then wrote into the same /install/centos8
directory and made osimage definitions with the same names.

The discinfo identifier table gives the minor version, but it contains
only 8.1 and 8.5. The identifiers of an expanded tree are also different
from the identifiers of the DVD. The release package in BaseOS/Packages is
the only other record of the minor version on the medium.

Read the version from the name of that package. CentOS changed the name of
the package to centos-linux-release in 8.3, thus accept the two names.
Accept only a major.minor version, because other packages start with the
same centos-release prefix. Accept only the major version that the
description gives, because a package for a different major version does not
describe this medium. Accept the minor version only when the medium names
one, because a medium that names more than one does not pin a minor version.

Keep the version from the description in the other conditions. A medium that
names no minor version keeps the name centos8, which is the behaviour before
this change and the correct name for media that do not pin a minor version.

CentOS Stream, Rocky Linux, AlmaLinux and Red Hat Enterprise Linux keep
their own branches. CentOS Linux 7 gives a different description and has
no BaseOS directory, thus it does not use this path.

Recovered from the lenovobuild branch. Reimplemented against master: the
original reads only centos-release, which CentOS renamed in 8.3, and its
expression is not anchored.
2026-08-26 12:15:59 -03:00
Vinícius Ferrão 866302c88a fix(template): omit the default HTTP port from installer URLs
The template renderer writes the HTTP port into the URLs of a kickstart
file, an autoyast profile and a preseed file. It writes the port always, so
a URL gets the text ":80" when the site keeps the default port.

A URL that gives no port already goes to port 80. Write the port only when
the site sets a port that is not 80. The netboot plugins xnba, dhcp and mknb
already do this.

The module gave the port in three different ways. One place wrote the port
always. One place wrote the port only when the port was not 80. One place
wrote the port always from the environment. Put the rule in one routine and
let the four places use that routine.

The routine also accepts a port that is set to nothing. Before, an empty
value made a URL that ends with a colon.
2026-08-26 12:15:26 -03:00
Vinícius Ferrão 031ad68a41 fix(xcatd): classify secret responses by the shared secret set
The commands.log response classifier used a "passw" text match on the
request arguments. A secret whose name has no such text passed the
check, so a read of an authentication key, a privacy key or the snmpc
site value logged its bare value in the response. A command that
expands an argument also passed the check: nodels with a table name
returns every column of the table, and lsdef returns attributes that
the request never names. The daemon also ran redact_password over the
whole connection log on each request, so the redactor split at the
first request of the connection and the change signal swept the text of
earlier requests and responses.

Add secret_in_request. The routine reports a request that names a
secret attribute, selects a secret site key, or dumps a table that owns
a secret column through tabdump or nodels, from the same secret set
that the argument redaction uses. The response classifier calls it, so
the response of such a request logs as redacted.

Add secret_in_response. The routine reports response text that holds
"passw" or a secret attribute name in assignment or column form. The
response finalizer calls it in place of the bare text match, so an
expanded listing that carries an authentication key or a product key
logs as redacted even when the request never names it. The lsvm
response is the directory entry, whose passwords are positional, so
the classifier marks the command itself.

Build each request segment alone, redact the segment, and then append
it to the connection log. The redactor now always sees the current
command, and the change signal covers only the current request.
2026-08-26 12:14:21 -03:00
Daniel Hilst b4c7936cc6 Merge pull request #7764 from VersatusHPC/refactor/dhcp-shared-os-version-parsing
refactor(dhcp): reuse shared OS version parsing
2026-08-26 11:09:02 -03:00
Daniel Hilst e8b0620345 Merge pull request #7757 from VersatusHPC/refactor/template-shared-ubuntu-version-comparison
refactor(template): use shared Ubuntu version comparison
2026-08-26 11:06:31 -03:00
Vinícius Ferrão 2dc4afd903 Merge pull request #7741 from stanford-rc/genpdu
feat: add `genpdu` pdutype for generic SNMP PDUs (PDU2-MIB)
2026-08-26 00:14:25 -03:00
Kilian Cavalotti 0b4695eef2 Accept MIB labels for genpdu enumerated values
With PDU2-MIB loaded, SNMP.pm returns an enumerated INTEGER as its label
rather than its number: a PX4 answers inletSensorUnits with "amp" rather
than "2". That failed the numeric test, fell back to none(-1) and
dropped the unit suffix from every rvitals reading.

Add pdu2_enum, which accepts the number, the label, or the label(value)
form Net-SNMP produces with quick printing off, and use it for the
sensor units and for outletSwitchingState.

Also stop requiring the switching probe to read on or off. An outlet can
be in any SensorStateEnumeration state, and pdu2_get has already ruled
out an absent instance, so any answer proves the outlet is switchable.

Signed-off-by: Kilian Cavalotti <kilian@stanford.edu>
2026-08-25 17:44:23 -07:00
Daniel Hilst ab7813e3e6 Merge pull request #7746 from VersatusHPC/fix/blade-findme-chassis-filter
fix(blade): let a discovery request reach the findme handler
2026-08-25 20:26:47 -03:00
Vinícius Ferrão b1ef0620de refactor(discovery): share blade findme decisions 2026-08-25 19:46:04 -03:00
Vinícius Ferrão e4a912db10 refactor(rspconfig): isolate per-BMC setting selection 2026-08-25 18:47:10 -03:00
Vinícius Ferrão d6eca6f052 refactor(blade): isolate findme decisions 2026-08-25 18:40:56 -03:00
Vinícius Ferrão 2d1f64f0fb fix(blade): let a discovery request reach the findme handler
A node that boots sends a findme request to say that it is there. That
request names no node, because the node is what the request asks xCAT to
find. The preprocessor of the blade plugin asks for a noderange for every
command, so it answers "Missing Noderange" with an error code and gives back
no request. The daemon then has nothing to give to the handler, and the
findme handler of the plugin does not run.

The plugin therefore answers each discovery request with an error, and blade
discovery does not happen. The check that asks for a noderange is older than
the findme handler.

Hand a findme request to the handler, as the switch plugin does for the
commands that it does not preprocess. Every other command keeps the check.

The preprocessor also held a test that removed a node from a findme request
when the hardware type was not blade. A findme request now returns above that
test, and it named a noderange that a findme request never carries, so the
test could not run. Remove it.
2026-08-25 18:40:56 -03:00
Vinícius Ferrão f9ed90ec0b fix(rspconfig): accept one network value per BMC
A node can carry more than one BMC, and rspconfig already opens a
session per BMC for rinv, reventlog, rvitals and rspconfig. A setting
such as ip= carried a single value, so every BMC of the node received
the same one. Two BMCs cannot share an address, so a node like that
could not be configured through rspconfig at all.

Read a comma separated value as one setting per BMC, in the order the
sessions are numbered. Only the ip, netmask and gateway settings read a
list, because a comma belongs to the value itself in a free form SNMP
community string. A value without a comma still reaches every BMC, so
the existing single BMC use is unchanged.

An entry that is missing or empty reports the mismatch instead of
reaching the address encoders, which reject an empty string. The
session then holds the value of its own BMC, because the follow-up
callbacks read the subcommand again to decide whether the address came
from DHCP.

Recovered from the lenovobuild branch.
2026-08-25 18:40:55 -03:00
Vinícius Ferrão 097554ba34 fix(blade): ask only the blades of a chassis for a discovery inventory
The findme handler of the blade plugin makes an inventory request for each
node in the mp table. That table holds more than the blades of a chassis.
lsslp writes a row for a Power BMC, for an FSP, for a BPA, for an HMC and for
other hardware, and xCAT::PPCdb::add_systemX writes a row for a management
module. None of that hardware answers a blade inventory.

Keep a row that gives blade as its hardware type. Keep also a row that gives
no hardware type but names a different node as its mpa, when that other node
is a management module. The mp template in xCAT/templates/e1350 leaves the
hardware type of a blade empty, so a test of the hardware type alone loses
the blades of a chassis.

Return when the table holds no blades. The work below the filter reads the
arp table of the management node, and a site that has no chassis must not pay
for that on each discovery request.

Recovered from the lenovobuild branch, which tested the hardware type only.
2026-08-25 18:40:55 -03:00
Vinícius Ferrão 8e94cd157a fix(genesis): complete artifact cleanup
Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
2026-08-25 11:26:47 -03:00
Vinícius Ferrão a983faf736 fix(genesis): retire stale legacy initramfs
Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
2026-08-25 11:26:47 -03:00
Vinícius Ferrão 33124a1483 fix(genesis): preserve canonical ppc64 images 2026-08-25 11:26:46 -03:00
Vinícius Ferrão ca1b0cbd67 fix(genesis): protect Power architecture fallback 2026-08-25 11:26:46 -03:00
Vinícius Ferrão 719e5aecab fix(genesis): close consumer review gaps 2026-08-25 11:26:46 -03:00
Vinícius Ferrão ba2c1e75bc fix(genesis): finish consumer integration 2026-08-25 11:26:45 -03:00
Vinícius Ferrão f5d1bd8e73 fix(genesis): complete boot consumer wiring 2026-08-25 11:26:45 -03:00
Vinícius Ferrão 4457efbd1b feat(genesis): activate installed OpenEmbedded images 2026-08-25 11:26:44 -03:00
Kilian Cavalotti daef2d7bae Distinguish SNMP failures from absent objects in genpdu
A missing object is exception text under v2c/v3 and an error under v1,
and genpdu treated both the same. Add pdu2_get, returning a value and an
ok, absent or failed status. A failed signed minimum read now skips the
sensor, and rinv no longer prints "No Such Instance currently exists at
this OID" for a nameplate field the model does not populate.

Read the signed minimum per entity: the MIB indexes it that way, and it
decides which value column is read.

In the session probe, fall back to the PDU2 nameplate rather than
sysDescr, so a credential that cannot read PDU2 is rejected, return
early when the pduCount read fails at the transport level, and warn once
per PDU.

Signed-off-by: Kilian Cavalotti <kilian@stanford.edu>
2026-08-24 16:32:41 -07:00
Kilian Cavalotti 30dc723b6d Fix genpdu sensor value column and connection detection
genpdu read negative-capable sensors from the unsigned value column,
which the MIB leaves undefined for them: a PX4 answers it with 0 for
inlet reactive power and carries the reading in the signed column. Use
SensorSignedMinimum to pick the column, as the MIB specifies. The
unsigned column is still needed for active energy, whose range exceeds
Integer32 and reads 0 in the signed one.

An unreachable PDU or a wrong credential looked like a PDU without
switched outlets, since the switching probe was the first exchange with
the device. Probe pduCount first (implemented by every PDU2 agent,
verified on PX2, PX3 and PX4) and return no session when it fails, so
callers print "Couldn't connect to <pdu>". Warn when pduCount is not 1
rather than refusing: a linked primary still answers for its own
outlets.

Add unit tests for the genpdu sensor, session and inventory paths.

Signed-off-by: Kilian Cavalotti <kilian@stanford.edu>
2026-08-24 16:32:41 -07:00
Daniel Hilst 4844528860 fix(xcat-core): resolve the Subiquity install NIC in xCAT's own fallback order
Treating an empty noderes.installnic as "mac" skipped noderes.primarynic: a node
that configures only primarynic was installed with a netplan matching on mac.mac
that never renamed the interface, and a primarynic holding a MAC address was
ignored. The order xCAT uses everywhere else is installnic -> primarynic ->
mac.mac, with either attribute allowed to hold an interface name or a MAC
address, and xCAT::NetworkUtils::gen_net_boot_params already implements it for
the netboot kernel parameters.

Resolve it in Perl and hand the template the answer:

- xCAT::Template::subiquity_install_netcfg() delegates the order to
  gen_net_boot_params and returns the netplan set-name (empty when the device is
  matched by MAC alone) and the address to match on, with mac.mac parsed by
  xCAT::Utils::parseMacTabEntry so |-separated, !hostname-suffixed entries
  resolve to THIS node rather than to whichever entry came first.
- #SUBIQUITYINSTALLNIC# / #SUBIQUITYINSTALLMAC# render those two values.
  installnic and primarynic are read blank-okay -- a node that sets neither is
  normal, and is exactly what "match on mac.mac" means -- while mac.mac stays a
  required lookup, as it was when the template read it directly.
- compute.subiquity.tmpl consumes the resolved values. No part of the fallback,
  and no mac.mac parsing, is left in shell: it only chooses whether to emit
  set-name, based on whether a name was resolved.

ubuntu_subiquity_installnic.t now passes: the six resolution cases, multi-entry
mac.mac, and the netplan the template's own late-command writes for a resolved
name and for none. ubuntu_subiquity_template.t asserts the template no longer
reads installnic/primarynic or parses MACs itself.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-08-24 18:17:08 -03:00
Vinícius Ferrão 94531ecf79 refactor(dhcp): reuse shared OS version parsing 2026-08-24 16:21:19 -03:00
Vinícius Ferrão 6e5dac5176 refactor(template): use shared Ubuntu version comparison 2026-08-24 15:11:57 -03:00
Daniel Hilst f2f96b67fc Merge pull request #7728 from VersatusHPC/fix/xml-external-entity
fix(xcatd): block XML external entities on the legacy parser path
2026-08-24 14:23:48 -03:00
Daniel Hilst 5ca148889c Merge pull request #7749 from VersatusHPC/fix/nodestat-usefping-option
fix(nodestat): accept the fping option that the usage message gives
2026-08-24 12:42:21 -03:00
Daniel Hilst bcf6f9059a Merge pull request #7750 from VersatusHPC/fix/dbobjutils-exact-only-if-values
fix(dbobjutils): match exact only-if values
2026-08-24 12:39:34 -03:00
Daniel Hilst 14feebce2f Merge pull request #7753 from VersatusHPC/fix/genesis-lzma-via-xz
fix(mknb): compress the genesis image with xz when lzma is absent
2026-08-24 12:36:26 -03:00
Daniel Hilst a7f4c770b5 Merge pull request #7631 from VersatusHPC/refactor/ipmi-rmcp-response-identity
refactor(ipmi): centralize RMCP response identity check
2026-08-24 12:27:17 -03:00
Vinícius Ferrão d5f882291d fix(nodestat): accept the fping option that the usage message gives
The manual page and the usage message of nodestat give the option
-f|--usefping. The preprocessor of the request knows no option f, and the
handler of the request spells the long name useping, so --usefping does
nothing. An administrator who follows the manual page gets the nmap path, and
gets no message that says why.

The two places also read different specifications, so an option that one
place accepts can reach the other place and take a different meaning. Put the
specification in one routine, and let both places read that routine.

Give the name usefping to the option, and keep useping as a second name. That
spelling has worked since 2.14.2, so a site can have it in a script.

The long name of the fping option starts with the same letters as usemon, so
--use and --us become names that Getopt::Long cannot decide. Those two
abbreviations select usemon today. Keep them with usemon, or an administrator
who monitors with them loses the monitoring and gets no message.

The change has two other effects. The abbreviations --use and --us no longer
select fping as well, which they did only because the two places read
different specifications. The bundles -mf and -fm now select both options,
which they did not do before.

Recovered from the lenovobuild branch.
2026-08-23 22:38:41 -03:00
Vinícius Ferrão c390570e95 fix(mknb): compress the genesis image with xz when lzma is absent
The genesis image goes into a file whose name ends with .lzma. The plugin
writes that file only when /usr/bin/lzma is there, and it falls back to gzip
when it is not.

Red Hat ships no lzma binary. On AlmaLinux 9 and on AlmaLinux 10 that test
fails, the plugin falls back to gzip, and it gives no message that says why.
The image is larger on each run of mknb. Debian and Ubuntu ship lzma as a
second name for xz, so those systems still get the smaller image.

Ask xz for the same container when lzma is absent. The command
"xz --format=lzma" writes the same bytes as "lzma", so the file keeps its
name, its container and its size. Keep the gzip fallback for a system that
has neither program.

Recovered from the lenovobuild branch, which asked xz for the xz container.
That container is not the lzma container, and the name of the file says lzma.
2026-08-23 22:38:41 -03:00
Vinícius Ferrão b6d9bc6643 refactor(network): reuse shared netmask helpers 2026-08-23 13:50:00 -03:00
Vinícius Ferrão 6e43843712 refactor(utils): centralize comma-list membership 2026-08-23 11:08:24 -03:00
Kilian Cavalotti 657b17570a Add genpdu pdutype for generic SNMP PDUs (PDU2-MIB)
Add a new pdutype (genpdu) for PDUs implementing the Raritan PDU2-MIB.
A single MIB covers the Raritan PX2/PX3/PX4/PXC/SRC/PXO/BCM series, the
Server Technology PRO3X/PRO4X series, the Legrand intelligent PDUs, and
all PDUs following the PDU2-MIB.

Supports rpower (whole-PDU and per-outlet), rinv and rvitals over SNMP
v1, v2c or v3, with credentials read from the pdu table).

Unlike the existing types, sensor units and decimal precision are read
from the MIB per sensor rather than hardcoded, so readings are correct
across models that report differing precision for the same sensor.
Outlet switching capability is probed at connect time, so metered-only
models report a single "unsupported" message instead of a per-outlet error.

rspconfig is not supported for genpdu; PDU linking and BCM2/PMC power
meters are out of scope.

Tested on Raritan PX4-5851-E7V2 (fw 4.2.10.5-50400, switched),
PX3-1901U-N1 and PX3-1901U-N1A6 (fw 4.0.20.5-49038, metered), and
PX2-1901U-N1A6 (fw 4.0.20.5-49038, metered).

Signed-off-by: Kilian Cavalotti <kilian@stanford.edu>
2026-08-20 18:51:02 -07:00
Vinícius Ferrão bae92ffc47 fix(credentials): audit delegated certificate signing 2026-08-20 17:37:19 -03:00
Vinícius Ferrão 109f587a7f fix(credentials): delegate node certificates through service nodes 2026-08-20 16:50:27 -03:00
Daniel Hilst c6549352b9 Merge pull request #7724 from VersatusHPC/feat/mknb-exported-genesis
feat(mknb): install exported Genesis images
2026-08-20 13:00:24 -03:00
Daniel Hilst d7d71b2c5e Merge pull request #7735 from VersatusHPC/fix/redact-command-log-arguments
fix(xcatd): redact command-log arguments per element
2026-08-19 15:44:02 -03:00
Vinícius Ferrão 7fa755719a fix(xcatd): redact command-log arguments per element
The daemon redacted secret attributes on the joined command string. The
match failed when a value held a space. The match also failed for a "+="
splice assignment. The validate() path did not quote the arguments, so a
multi-word secret value kept its later words in syslog and in the
auditlog table. A password that a command receives through an option or
a positional operand was not redacted at all. The debug dispatch trace
wrote the raw arguments to syslog when site.xcatdebugmode was set.

Redact the argument vector before the daemon joins it. Add
redact_password_args for this task. The routine masks the value of a
secret attribute in any argument, at the start or embedded after another
token. An embedded secret assignment masks to the end of the argument,
because a shell value may hold quotes and spaces. The routine allows
spaces around the operator. It accepts the "=", "+=", ",=", "^=", "!=",
"=~" and "!~" operators that chdef, nodech and node selection use. It
masks a password option value in each form that Getopt::Long accepts: a
separate argument, a compact short option, a bundle of short options
with the "?" help letter, a "+" option prefix, a single-letter option
with two dashes, a long option, a long option with an equals sign, and
an abbreviated long option. The long-name match runs first, so a long
option keeps its name and masks its value. A walk over each bundle then
finds the first secret letter, so the mask always starts at the option
and the result does not depend on hash order. The walk knows which
other letters of a command take a value, so a secret letter inside such
a value does not redact and the audit text stays correct. The walk also
knows which letters take an integer, because the z/VM cpu option
consumes only its signed digits and the parser then continues the
bundle into the password option. The value stops match letter case,
because a bundle keeps short options case sensitive and an unknown
capital letter does not absorb the rest. The mkvm secret match ignores
letter case, because the z/VM parser keeps the Getopt::Long default for
long names. The mkhwconn match keeps letter case, because -p
is the hardware control point and -P is the password. The routine knows
the password options of bmcdiscover, switchdiscover, mkhwconn, mkvm,
createvcluster, lsvcluster and rmvcluster, the rspconfig password
assignments, the mkvm clone pw= operand, and the positional password
operands of chvm. It masks the site.value argument of tabch and chtab
when a selector or a site.key assignment names snmpc. An exact short
option that takes a non-secret value stays visible, so the PPC mkvm -p
profile is not an abbreviation of --password. The dispatch trace builds
its text from the redacted vector.

Add snmpc, productkey, prodkey.key, tokenid and token.tokenid to the
secret list, with community and pdu.community. The secret list holds
only attributes that map to a secret column, so key and sshkeydir stay
visible.

redact_password keeps a second pass over the joined string. This pass
masks an embedded secret assignment to the end of the line, because the
argument boundaries are gone after the join.

The commands.log response classifier marks a response sensitive when the
request was redacted. The argument vector pass sets that signal, so a
secret whose name has no "passw" text still marks its response.
2026-08-19 13:43:23 -03:00
Daniel Hilst 73fbf10e6b Merge pull request #7716 from VersatusHPC/fix/syncfiles-explicit-root-identity
fix(syncfiles): name root explicitly on the xdcp subrequest
2026-08-19 07:19:11 -03:00