Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,18 @@ if(BUILD_TESTS)
set_tests_properties(show_device_rows_negctl PROPERTIES
LABELS "integration;authenticity" TIMEOUT 300)

# SHOW CLUSTER reflects the SCS daemon's LIVE membership (rd vms-8d4,
# INV-DCL). cmd_show_cluster() used to hardcode %SYSTEM-I-NOTMEMBER, so a
# genuinely-clustered node lied. This RUNS DCL against a membership file
# written in SCSD's own publication format (scs_membership.h -- the real
# boundary between the daemon and the DCL process) and requires the member
# set to be shown when present and NOTMEMBER only when genuinely absent.
add_test(NAME show_cluster_membership_gate
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tests/integration/test_show_cluster_membership.sh
$<TARGET_FILE:vmsdcl>)
set_tests_properties(show_cluster_membership_gate PROPERTIES
LABELS "integration;authenticity;cluster" TIMEOUT 60)

# SHOW SYMBOL renders an integer's Hex and Octal columns as a LONGWORD
# (rd vms-c71), pinned to a side-by-side measurement against OpenVMS VAX
# V7.3. Two defects lived on one line: a negative sign-extended to 16 hex
Expand Down
2 changes: 1 addition & 1 deletion src/imgact/test/run_dcl_native.sh
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ CFLAGS="-fPIC -O2 -ffreestanding -fno-builtin -fno-stack-protector -U_FORTIFY_SO
DEFS="-D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE"
# -I$LIBVMSSYS_DIR (vms-8019): dcl_cmd_show.c includes "vms_kif.h" — SHOW SYSTEM
# reads the executive's process table through vms_kif_procscan().
INCS="-I$DCL_DIR/include -I$LIBVMS_INC -I$VMSFS_INC -I$LNM_INC -I$RMS_INC -I$VMSPROC_DIR/include -I$SRC/vmsqueue -I$LIBVMSSYS_DIR"
INCS="-I$DCL_DIR/include -I$LIBVMS_INC -I$VMSFS_INC -I$LNM_INC -I$RMS_INC -I$VMSPROC_DIR/include -I$SRC/vmsqueue -I$LIBVMSSYS_DIR -I$SRC/vmsscs/include"
TUS="dcl_main dcl_lexer dcl_parser dcl_exec dcl_backup dcl_builtin dcl_cmd_show \
dcl_cmd_set dcl_cmd_file dcl_cmd_process dcl_cmd_io dcl_cmd_misc dcl_disk_logical \
dcl_editor dcl_terminal dcl_symbol dcl_lexical dcl_filespec dcl_io dcl_script \
Expand Down
3 changes: 3 additions & 0 deletions src/libvms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ target_include_directories(vms PUBLIC include ${VMS_RMS_INCLUDE_DIR} ${VMS_FS_IN
# (ovmx_image.h / ovmx_symvec.h) -- the same single-source-of-truth headers
# LINK.EXE and IMGACT.EXE share (vms-db2). PRIVATE: only these TUs need them.
target_include_directories(vms PRIVATE ${CMAKE_SOURCE_DIR}/src/vmslink/include)
# F$GETSYI CLUSTER_MEMBER/CLUSTER_NODES read SCSD's live membership publication
# (vms-8d4): src/vmsscs/include/scs_membership.h -- header-only, no link dep.
target_include_directories(vms PRIVATE ${CMAKE_SOURCE_DIR}/src/vmsscs/include)
# vmssys provides vms_kif_* (the /dev/vms ioctl wrappers used by sys_lock.c
# to reach the kernel lock manager).
target_link_libraries(vms PUBLIC vmsprocess vmsfs vmssys pthread m)
Expand Down
24 changes: 18 additions & 6 deletions src/libvms/syssvc/sys_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "sysgen_params.h"
#include "ovmx_identity.h"
#include "vms_kif.h" /* the executive OWNS privilege state (vms-pv1) */
#include "scs_membership.h" /* vms-8d4: live cluster membership from SCSD */

/*
* sys$setprv - Set or clear process privileges.
Expand Down Expand Up @@ -214,19 +215,30 @@ uint32_t sys$getsyi(uint32_t efn, const uint32_t *csidadr,
}

case SYI$_CLUSTER_MEMBER: {
uint32_t vaxcluster = 0; /* OVMX default: not cluster-enabled */
(void)sysgen_read_param("VAXCLUSTER", &vaxcluster);
uint32_t member = (vaxcluster != 0) ? 1 : 0;
/* vms-8d4: the LIVE fact, read from SCSD's published member set
* (scs_membership.h) — not the static SYSGEN VAXCLUSTER config
* flag, which said "member" whenever clustering was enabled even
* with no cluster formed. A node is a member iff the connection
* manager has admitted it into a cluster (>=1 published member).
* This keeps F$GETSYI consistent with DCL SHOW CLUSTER. */
struct scs_cluster_view view;
uint32_t member =
(scs_membership_read(&view) > 0 && view.n_members >= 1)
? 1 : 0;
if (item->bufaddr && item->buflen >= sizeof(uint32_t))
*(uint32_t *)item->bufaddr = member;
if (item->retlen) *item->retlen = sizeof(uint32_t);
break;
}

case SYI$_CLUSTER_NODES: {
/* OVMX has no live cluster wire yet (vms-ci.3) — report
* this node only. */
uint32_t nodes = 1;
/* vms-8d4: live cluster node count from SCSD's published member
* set; 1 (this node only) when not a member. Was hardcoded to
* 1 unconditionally (vms-ci.3), which lied on a real cluster. */
struct scs_cluster_view view;
uint32_t nodes =
(scs_membership_read(&view) > 0 && view.n_members >= 1)
? (uint32_t)view.n_members : 1;
if (item->bufaddr && item->buflen >= sizeof(uint32_t))
*(uint32_t *)item->bufaddr = nodes;
if (item->retlen) *item->retlen = sizeof(uint32_t);
Expand Down
4 changes: 4 additions & 0 deletions src/vmsdcl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ target_include_directories(vmsdcl PRIVATE
# kernel-interface client (vms-fb9): src/libvmssys/vms_kif.h, which
# pulls src/kernel/vms_ioctl.h for the shared ioctl structures.
${CMAKE_SOURCE_DIR}/src/libvmssys
# SHOW CLUSTER reads the SCS daemon's live membership publication
# (vms-8d4): src/vmsscs/include/scs_membership.h -- a header-only IPC,
# so no vmsscs link dependency is added.
${CMAKE_SOURCE_DIR}/src/vmsscs/include
)

# We need POSIX APIs (fork, sigaction, strncasecmp, realpath, etc.)
Expand Down
70 changes: 69 additions & 1 deletion src/vmsdcl/dcl_cmd_show.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "vms/pcb.h"
#include "ovmx_identity.h"
#include "ovmx_accounting.h"
#include "scs_membership.h" /* vms-8d4: read SCSD's live cluster membership */
#include "vmsqueue.h"
#include "descrip.h"
#include "jpidef.h"
Expand Down Expand Up @@ -2379,11 +2380,78 @@ static int cmd_show_license(struct dcl_command *cmd)

/*
* SHOW CLUSTER - Display VMScluster membership.
*
* vms-8d4 (INV-DCL facade-kill): this used to hardcode "%SYSTEM-I-NOTMEMBER"
* unconditionally, so a genuinely-clustered node lied about being standalone.
* It now reads the connection manager's LIVE member set, published by the SCS
* daemon (src/vmsscs/scsd.c -> scs_membership.h). When the daemon has admitted
* this node into a cluster it renders the real member list; when this node is
* not a member -- daemon not running, or not (yet) joined -- there is no
* published membership and NOTMEMBER is the honest answer, exactly as a real
* non-member VMS node reports.
*
* The display fields (the "View of Cluster from system ID N node: X" banner and
* the NODE / SOFTWARE / STATUS columns) are modeled on the public OpenVMS SHOW
* CLUSTER utility default report (Rule 8: matched to documented output, not to
* any VMS binary). The line art is an OVMX rendering.
*/
static int cmd_show_cluster(struct dcl_command *cmd)
{
(void)cmd;
printf("%%SYSTEM-I-NOTMEMBER, this system is not a member of a VMScluster\n");

struct scs_cluster_view view;
int rc = scs_membership_read(&view);

if (rc <= 0 || view.n_members < 1) {
/* Not a member: no live membership published. This is the truth for a
* standalone node and for a node whose connection manager is not up. */
printf("%%SYSTEM-I-NOTMEMBER, this system is not a member of a "
"VMScluster\n");
return SS$_NORMAL;
}

/* members[0] is the local node, as published by SCSD. */
const struct scs_cluster_member *local = &view.members[0];
const char *local_node =
(local->node[0] != '\0' && strcmp(local->node, "?") != 0)
? local->node : "OVMX";

char tbuf[64];
time_t now = time(NULL);
struct tm tmv;
localtime_r(&now, &tmv);
/* VMS date form: dd-MON-yyyy hh:mm:ss (month letters uppercased). */
strftime(tbuf, sizeof(tbuf), "%d-%b-%Y %H:%M:%S", &tmv);
for (char *p = tbuf; *p; p++) *p = (char)toupper((unsigned char)*p);

/* We know only THIS node's software version; the membership publication
* carries no per-peer software, so peer rows show the family ("VMS")
* without a version we cannot vouch for (Rule 8 / INV-DCL: never state a
* fact we did not observe). */
char local_software[24];
snprintf(local_software, sizeof(local_software), "VMS %s",
ovmx_compat_version());

printf("View of Cluster from system ID %u node: %-6s %s\n\n",
(unsigned)local->sysid, local_node, tbuf);
printf("+-------------------------------------------------+\n");
printf("| SYSTEMS | MEMBERS |\n");
printf("|--------------------------+----------------------|\n");
printf("| NODE | SOFTWARE | STATUS |\n");
printf("|--------+-----------------+----------------------|\n");
for (int i = 0; i < view.n_members; i++) {
const struct scs_cluster_member *m = &view.members[i];
char nodecol[SCS_MEMBERSHIP_NODE_LEN];
if (m->node[0] != '\0' && strcmp(m->node, "?") != 0) {
snprintf(nodecol, sizeof(nodecol), "%s", m->node);
} else {
/* Peer SCSNODE name not learned: identify it by SCSSYSTEMID. */
snprintf(nodecol, sizeof(nodecol), "%u", (unsigned)m->sysid);
}
const char *software = (i == 0) ? local_software : "VMS";
printf("| %-6s | %-15s | %-20s |\n", nodecol, software, m->state);
}
printf("+-------------------------------------------------+\n");
return SS$_NORMAL;
}

Expand Down
3 changes: 2 additions & 1 deletion src/vmslink/mk_dcl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ CFLAGS="${CFLAGS:--fPIC -O2 -ffreestanding -fno-builtin -fno-stack-protector -mn
DEFS="-D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE"
INCS="-I$DCL/include -I$REPO_SRC/libvms/include -I$REPO_SRC/vmsfs/include \
-I$REPO_SRC/vmslnm/include -I$REPO_SRC/vmsrms/include \
-I$REPO_SRC/vmsprocess/include -I$REPO_SRC/vmsqueue -I$REPO_SRC/libvmssys"
-I$REPO_SRC/vmsprocess/include -I$REPO_SRC/vmsqueue -I$REPO_SRC/libvmssys \
-I$REPO_SRC/vmsscs/include" # scs_membership.h for SHOW CLUSTER (vms-8d4)

# The 22 vmsdcl TUs (== src/vmsdcl/CMakeLists.txt, minus readline convenience).
TUS="dcl_main dcl_lexer dcl_parser dcl_exec dcl_backup dcl_builtin dcl_cmd_show \
Expand Down
1 change: 1 addition & 0 deletions src/vmslink/mk_decc_shr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ inet_ntop=PROCEDURE,inet_pton=PROCEDURE,ioctl=PROCEDURE,isatty=PROCEDURE,\
isxdigit=PROCEDURE,mktime=PROCEDURE,ntohl=PROCEDURE,pipe=PROCEDURE,\
readlink=PROCEDURE,rewind=PROCEDURE,setrlimit=PROCEDURE,settimeofday=PROCEDURE,\
sleep=PROCEDURE,socket=PROCEDURE,strerror=PROCEDURE,strptime=PROCEDURE,\
strftime=PROCEDURE,\
system=PROCEDURE,tcgetattr=PROCEDURE,tcsetattr=PROCEDURE,utimes=PROCEDURE,\
\
__addtf3=PROCEDURE,__divtf3=PROCEDURE,__eqtf2=PROCEDURE,__extenddftf2=PROCEDURE,\
Expand Down
2 changes: 2 additions & 0 deletions src/vmslink/mk_libvms_shr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ CFLAGS="${CFLAGS:--fPIC -O2 -ffreestanding -fno-builtin -fno-stack-protector -mn
INCS="-I$SRC/include -I$HERE/../libvmssys \
-I$HERE/../vmsprocess/include -I$HERE/../vmslnm/include \
-I$HERE/../vmsfs/include -I$HERE/../vmsrms/include \
-I$HERE/../vmsscs/include \
-I$HERE/include" # ovmx_image.h/ovmx_symvec.h for sys_imgact + imgact_prodreg (vms-db2)
# vmsscs/include: scs_membership.h for F$GETSYI CLUSTER_* (vms-8d4)

echo "mk_libvms_shr: LINK.EXE=$LINK_EXE CC=$CC GSMATCH=$GSMATCH"
echo "mk_libvms_shr: src=$SRC"
Expand Down
Loading
Loading