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
6 changes: 3 additions & 3 deletions .github/workflows/mvsce.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ jobs:
docker run -d --rm --name mvs -p 8080:8080 -p 2121:2121 "$IMAGE"
start=$(date +%s)
for i in $(seq 1 180); do
v=$(curl -s -u IBMUSER:SYS1 'http://localhost:8080/zosmf/test?fn=version' || true)
case "$v" in *'"version"'*) break ;; esac
v=$(curl -s -u IBMUSER:SYS1 'http://localhost:8080/zosmf/info' || true)
case "$v" in *'"zosmf_full_version"'*) break ;; esac
if [ "$(docker inspect -f '{{.State.Status}}' mvs 2>/dev/null)" != running ]; then
echo "container stopped"; exit 1
fi
Expand All @@ -117,7 +117,7 @@ jobs:
docker exec mvs grep -E 'UFSD000I|HTTPD000I|FTPD000I' /logs/hercules.log | head -n 3
sha=$(echo "$banner" | sed -n 's/.*-g\([0-9a-f]\{7,\}\).*/\1/p')
case "$ref" in "$sha"*) [ -n "$sha" ] ;; *) echo "Hercules g$sha, label $ref"; exit 1 ;; esac
case "$v" in *"\"version\": \"$mvsmf\""*) ;; *) echo "mvsMF does not report $mvsmf"; exit 1 ;; esac
case "$v" in *"\"zosmf_full_version\":\"$mvsmf\""*) ;; *) echo "mvsMF does not report $mvsmf"; exit 1 ;; esac
# SHUTFAST, the servers still up, has to end MVS and the container
t0=$(date +%s)
curl -s -u IBMUSER:SYS1 -X PUT -H 'Content-Type: text/plain' -H 'X-IBM-Intrdr-Mode: TEXT' \
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ test-mvsce:
$(REGISTRY)/mvsce:$(TAG)
@echo "Waiting for MVS IPL and HTTPD..."
@rc=1; for i in $$(seq 1 60); do \
if curl -sf -u IBMUSER:SYS1 'http://localhost:8080/zosmf/test?fn=version'; then rc=0; break; fi; \
if curl -sf -u IBMUSER:SYS1 'http://localhost:8080/zosmf/info'; then rc=0; break; fi; \
sleep 5; \
done; \
[ $$rc -eq 0 ] || docker logs --tail 50 mvsce-test; \
Expand Down
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ docker run -d --rm --name mvs --network mvs-net \
ghcr.io/mvslovers/mvsce

# The mvsMF API is now reachable at http://mvs:8080 from within mvs-dev
curl -u IBMUSER:SYS1 'http://mvs:8080/zosmf/test?fn=version'
curl -u IBMUSER:SYS1 'http://mvs:8080/zosmf/info'
```

Set `MVSMF_HOST=mvs` and `MVSMF_PORT=8080` in your project's `.env` file.
Expand Down Expand Up @@ -289,7 +289,7 @@ image. The link `mvsce-builder/mvsce-target` is gone. Use
| [Hercules](https://github.com/SDL-Hercules-390/hyperion) (SDL-Hyperion, `develop`) | `a742398074` (4.10.0.11783) | `/home/hercules/herctest/herc4x`, replacing MVS/CE's |
| [UFSD](https://github.com/mvslovers/ufsd) | 1.4.0 | `MVSLOVER.UFSD.LOADLIB` |
| [HTTPD](https://github.com/mvslovers/httpd) | 4.5.1 | `HTTPD.LINKLIB` |
| [mvsMF](https://github.com/mvslovers/mvsmf) | 1.3.0 | `HTTPD.LINKLIB` |
| [mvsMF](https://github.com/mvslovers/mvsmf) | 1.4.1 | `HTTPD.LINKLIB` |
| [FTPD](https://github.com/mvslovers/ftpd) | 1.2.0 | `MVSLOVER.FTPD.LOADLIB` |
| [RAKF](https://github.com/MVS-sysgen/RAKF) | 2.0.0 (TK5 Update 6), replacing the older RAKF of the base image | `SYS1.LPALIB`, `SYS1.LINKLIB`, SMP4 FUNCTION `TRKF200` |

Expand Down Expand Up @@ -380,12 +380,19 @@ only:
other user's; it fails if either of the two is missing,
- adds `S UFSD` / `S HTTPD` / `S FTPD` to `SYS1.PARMLIB(COMMND00)`.

**No JESSPOOL profile is defined.** mvsMF 1.4.0 shows a user only its own
jobs unless a profile of the RAKF class `JESSPOOL` says otherwise, and the
image leaves the class empty. The FTPD and mvsMF suites that test the class
expect that: FTPD's test 18 stops on any `JESSPOOL` line in `PROFILES` and
creates its own profiles on a clean container.

It checks RAKF by content, not by return code, and **fails unless** the
installed `ICHSFR00` has the text `UNDEFINED CLASS` / `RAKF0012` and the
class descriptor table in `ICHSEC00` has the entry `JESSPOOL`, and the same
two are found in the storage of the CLPA-IPLed system. It then starts all
three servers and **fails unless** the `UFSD000I`/`HTTPD000I`/
`FTPD000I` banners and `/zosmf/test?fn=version` report the pinned versions,
`FTPD000I` banners and `/zosmf/info` (`zosmf_full_version`) report the pinned versions,
`/zosmf/restconsoles/v1/log` answers 401 without a login and 200 for `IBMUSER`,
neither server logs `RAKF0004`, `HTTPD004W`, `FTPD004W`, `HTTPD012E` or
`APF SETUP FAILED`, HTTPD logs `HTTPD002I AUTHORIZED BY`, FTPD
`FTPD004I STC IDENTITY SET TO FTPD/USER`, `FTPD001I READY` follows, an FTP
Expand Down Expand Up @@ -413,11 +420,11 @@ docker run -d --rm --name mvs-build \
ghcr.io/mvslovers/mvsce

# Wait for MVS to IPL and HTTPD to come up, then check the mvsMF level
curl -u IBMUSER:SYS1 'http://localhost:8080/zosmf/test?fn=version'
curl -u IBMUSER:SYS1 'http://localhost:8080/zosmf/info'
```

mvsMF answers before TSO is up: on an idle 4-CPU host the authenticated
`fn=version` returned 200 about 2 s after `docker run`, and `IKT005I TCAS IS
`/zosmf/info` returned 200 about 2 s after `docker run`, and `IKT005I TCAS IS
INITIALIZED` followed about 1.5 s later. Wait for each separately.
`/zosmf/info` answers 401 without credentials, so a readiness probe has to
authenticate.
Expand Down
2 changes: 1 addition & 1 deletion mvsce/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ ARG HERCULES_REF
ARG HERCULES_REPO
ARG UFSD_VERSION=1.4.0
ARG HTTPD_VERSION=4.5.1
ARG MVSMF_VERSION=1.3.0
ARG MVSMF_VERSION=1.4.1
ARG FTPD_VERSION=1.2.0
ARG RAKF_VERSION=2.0.0
# TK5INST.zip of the RAKF release: trkf200.xmi, the TK5 Update 6 install
Expand Down
4 changes: 2 additions & 2 deletions mvsce/mvsce-target
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#
# Every instance carries the label io.mvslovers.target=NAME and goes away
# completely when it stops (Docker: --rm with its anonymous volumes).
# `up` returns once the authenticated mvsMF fn=version answers; it does not
# `up` returns once the authenticated mvsMF /zosmf/info answers; it does not
# wait for TSO or FTP (see the README for when those are ready).
#
# Environment: MVSCE_TARGET_HOST (= --host), MVSCE_TARGET_RUNTIME,
Expand Down Expand Up @@ -501,7 +501,7 @@ start_once() {
if [ -n "$addr" ] && [ -n "$port" ]; then
code=$(curl -s -m 5 -o /dev/null -w '%{http_code}' \
-u "$MVS_USER:$MVS_PASS" \
"http://$addr:$port/zosmf/test?fn=version" || true)
"http://$addr:$port/zosmf/info" || true)
fi
[ "$code" = 200 ] && break
state=$(rt_state "$c")
Expand Down
42 changes: 35 additions & 7 deletions mvsce/setup_mvsce.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@
FTPD_VERSION, no RAKF0004 / HTTPD004W / FTPD004W for either server,
no HTTPD012E and no APF SETUP FAILED, FTPD004I,
FTPD001I READY, an FTP login, FTPAUTH refusing the FTPD user, and
/zosmf/test?fn=version against MVSMF_VERSION.
/zosmf/info zosmf_full_version against MVSMF_VERSION (a release has no
/zosmf/test), and the console route
/zosmf/restconsoles/v1/log (401 without a login, 200 for IBMUSER).
A build that installed nothing therefore fails instead of publishing
the previous level.
10. Adds P FTPD / P HTTPD / P UFSD to MVS/CE's SCRIPTS/SHUTDOWN.RC, purges
Expand All @@ -86,6 +88,7 @@
import subprocess
import sys
import time
import urllib.error
import urllib.request
import zipfile

Expand Down Expand Up @@ -1038,21 +1041,45 @@ def check_ftpd(herc, expected, since, ftpd_pw):


def check_mvsmf(herc, expected):
log('Checking the running mvsMF level (/zosmf/test?fn=version)...')
log('Checking the running mvsMF level (/zosmf/info)...')
if not wait_for_port(HTTP_PORT, timeout=60):
fail(herc, f'HTTPD is not listening on port {HTTP_PORT}')
req = urllib.request.Request(
f'http://127.0.0.1:{HTTP_PORT}/zosmf/test?fn=version')
req = urllib.request.Request(f'http://127.0.0.1:{HTTP_PORT}/zosmf/info')
cred = base64.b64encode(f'{USER}:{PASSWORD}'.encode()).decode()
req.add_header('Authorization', f'Basic {cred}')
try:
with urllib.request.urlopen(req, timeout=30) as resp:
info = json.loads(resp.read().decode())
except Exception as e: # noqa: BLE001 - any failure fails the build
fail(herc, f'mvsMF version probe failed: {e}')
log(f' mvsMF {info.get("version")} build {info.get("build")}')
if expected and info.get('version', '').upper() != expected.upper():
fail(herc, f'mvsMF reports {info.get("version")}, expected {expected}')
version = info.get('zosmf_full_version', '')
log(f' mvsMF {version}')
if version.endswith('-dev'):
fail(herc, f'mvsMF {version} is a development build, not a release')
if expected and version.upper() != expected.upper():
fail(herc, f'mvsMF reports {version}, expected {expected}')


def check_console_route(herc):
log('Checking the console route (/zosmf/restconsoles/v1/log)...')
url = f'http://127.0.0.1:{HTTP_PORT}/zosmf/restconsoles/v1/log'
try:
urllib.request.urlopen(url, timeout=30)
fail(herc, 'console route answers without a login')
except urllib.error.HTTPError as e:
if e.code != 401:
fail(herc, f'console route without a login answers {e.code}, expected 401')
req = urllib.request.Request(url)
cred = base64.b64encode(f'{USER}:{PASSWORD}'.encode()).decode()
req.add_header('Authorization', f'Basic {cred}')
try:
with urllib.request.urlopen(req, timeout=30) as resp:
code = resp.status
except urllib.error.HTTPError as e:
code = e.code
if code != 200:
fail(herc, f'console route with a login answers {code}, expected 200')
log(' 401 without a login, 200 for IBMUSER')


SHUTDOWN_RC = '/MVSCE/SCRIPTS/SHUTDOWN.RC'
Expand Down Expand Up @@ -1221,6 +1248,7 @@ def main():
start_stc(herc, 'HTTPD', 'HTTPD000I', os.environ.get('HTTPD_VERSION'))
check_identity(herc, 'HTTPD', since, 'HTTPD001I')
check_mvsmf(herc, os.environ.get('MVSMF_VERSION'))
check_console_route(herc)
since = len(read_log())
start_stc(herc, 'FTPD', 'FTPD000I', os.environ.get('FTPD_VERSION'))
check_ftpd(herc, os.environ.get('FTPD_VERSION'), since, ftpd_pw)
Expand Down
Loading