Note: The current version of this README is at http://www.fargos.net/packages/README_UbuntuOnHercules.html.
A tar file of the most current version of the scripts is available for download as http://www.fargos.net/packages/ubuntuOnHercules.tar.gz. The contents of the scripts have been reproduced below for educational purposes and these reproductions are not guaranteed to be the most current versions. The tar archive referenced above holds the current versions.
You will need the following:
Some variant of Hercules version 4 (hyperion) is required. The Software Development Lab version was the most up-to-date in 2019.
Obtain an ISO image for s390x Ubuntu. Start your search here.
Download the current scripts and configuration files from http://www.fargos.net/packages/ubuntuOnHercules.tar.gz.
Create a directory into which you want to place the scripts and untar the contents of http://www.fargos.net/packages/ubuntuOnHercules.tar.gz.
mkdir ubuntu-hercules cd ubuntu-hercules tar xvf ..../ubuntuOnHercules.tar.gz
Create a virtual DASD image to which the operating system will be installed. This can be done with makeNewUbuntuDisk, which is a convenience cover for the dasdinit command. By default, the makeNewUbuntuDisk script generates a 12000 cylinder (8 gigabyte) disk named as dasd/ubuntu-v18.disk. The Ubuntu version and the total number of cylinders can be set on the command line:
usage: ./makeNewUbuntuDisk [-c cylinders] [-v ubuntuVersion]
The hercules-ubuntu.cfg file currently assumes a single disk in the dasd subdirectory named ubuntu-v18.disk. If a different name was desired, it must be renamed in that configuration file.
# DASD
0120 3390 ./dasd/ubuntu-v18.disk
The ‑‑iso option of the boot_ubuntu.sh script will automatically mount an installation ISO image and boot it, filling out most of the configuration parameters that have to be entered via the system console. You will still need follow the instructions and login via ssh with the installation password to complete the installation process.
First, invoke ./boot_ubuntu.sh ‑‑help to see what defaults are programmatically obtained on your system. You only need specify arguments for entries you wish to change to alternate values.
usage: boot_ubuntu.sh [‑‑screen] [{‑‑iso isoFileName [‑‑dns DNSserver] [‑‑gw gatewayAddr] [‑‑host hostName] [‑‑domain domainName] [‑‑pw installPassword]}] --iso image = boot from CD image Image will be associated with a read-only loopback device and mounted, then IPLed using ubuntu.ins in the root directory Default gateway and DNS server: A.B.C.D Default hostname: ubuntu-z Default domain: your.domain.name Default install password: initialpw
Then invoke ./boot_ubuntu.sh ‑‑iso with any of the extra arguments needed to override the inferred default settings.
Wait patiently for a nontrivial amount of time... If all goes well, you will eventually be prompted to login using secure shell from a different window.
ssh installer@10.1.1.2
Login with the installation password ("initialpw" by default). Work your way through all of the installation questions and, after many hours, the installation should complete.
On subsequent startups of the guest, use sudo ./bootUnderScreen to run it under screen. This allows the invoking terminal to be detached and for different terminal sessions to attach and detach from the system console during the lifetime of the hercules process.
If you want access to the console, sudo ./connectToScreen will connect to the screen-affiliated terminal session.
As noted in the introduction, these configuration files and scripts are presented for convenient reading and are not guaranteed to be the most current versions.
A tar file of the most current version of the files is available for download as http://www.fargos.net/packages/ubuntuOnHercules.tar.gz.
The provided hercules-ubuntu.cfg configuration file defines a system with a maximum of 8 CPUs and about 6 gigabytes of memory. These can be changed to values more appropriate for the local environment.
# hercules-ubuntu.cfg - configuration file for Ubuntu with hercules ARCHLVL z/Arch ARCHLVL ENABLE BIT54 # Interlocked-access facility 2 ARCHLVL ENABLE BIT44 # PFPO Facility ARCHLVL ENABLE BIT37 # unknown ARCHLVL ENABLE BIT45 # FAST BCR SERIAL (on by default) ARCHLVL ENABLE BIT49 # MISC INST EXTN 1 (on by default) ARCHLVL ENABLE asn_lx_reuse # You can choose your own serial number CPUSERIAL 001482 CPUMODEL 2964 # z13 #ALRF ENABLE DIAG8CMD ENABLE ECPSVM YES # chosen hostname PANTITLE "ubuntu-z" # This 6 gigabyte size is usable MAINSIZE 6000 # 8 CPUs, use them all MAXCPU 8 NUMCPU 8 OSTAILOR LINUX PANRATE SLOW # Display Terminals 0700 3270 0701 3270 # DASD definitions # Disk prepared by makeNewUbuntuDisk 0120 3390 ./dasd/ubuntu-v18.disk # tape 0581 3420 # Tunnel will be configured on host by setupCTCnetwork script. # network s390x onHost 0A00,0A01 CTCI -n /dev/net/tun -t 1500 10.1.1.2 10.1.1.1
The makeNewUbuntuDisk script is a convenience cover script that invokes dasdinit to create a DASD image for use with hercules. It defaults to creating an 8 gigabyte drive image.
#!/bin/sh # makeNewUbuntuDisk - create DASD image for hercules version=18 cylinders=12000 while test $# -gt 0 do case "${1}" in -h | -help | --help) printf "usage: %s [-c cylinders] [-v ubuntuVersion]\n" "${0}" >&2 exit 1 ;; -c) cylinders=${2} shift ;; -v) version=${2} shift ;; -*) printf "%s: unrecognized option: \"%s\"\n" "${0}" "${1}" >&2 exit 1 ;; -*) printf "%s: unrecognized argument: \"%s\"\n" "${0}" "${1}" >&2 exit 1 ;; esac shift done diskName="dasd/ubuntu-v${version}.disk" if test -e ${diskName} then printf "%s: disk file %s already exists\n" "${0}" "${diskName}" exit 1 fi echo dasdinit -lfs -linux ${diskName} 3390-3 UBU120 ${cylinders} dasdinit -lfs -linux ${diskName} 3390-3 UBU120 ${cylinders}
The setupCTCnetwork script configures the Linux kernel using iptables or nftablesto setup Network Address Translation for the hercules guest. Fedora 32 moved to nftables, so this script has been updated to use nft if it is available and fallback to iptables.
Note: This script requires root privileges. The boot_ubuntu.sh script will use the sudo command to obtain the required elevated privileges if it was not invoked by the root user.
#!/bin/bash # setupCTCnetwork - setup network address translation for hercules networkToUse="10.1.1.0/24" userId=`id -u` if test "${userId}" -ne 0 then printf "%s: must be root to set iptables\n" "${0}" >&2 exit 1 fi defaultIf=`netstat -rn | awk '/^0.0.0.0/ { print $NF; exit }'` if test -z "${defaultIf}" then printf "%S: could not determine default interface\n" "${0}" >&2 exit 1 fi iptables -F INPUT iptables -F OUTPUT iptables -F FORWARD iptables -t nat -A POSTROUTING -o ${defaultIf} -s ${networkToUse} -j MASQUERADE iptables -A FORWARD -s ${networkToUse} -j ACCEPT iptables -A FORWARD -d ${networkToUse} -j ACCEPT echo 1 > /proc/sys/net/ipv4/ip_forward echo 1 > /proc/sys/net/ipv4/conf/all/proxy_arp exit 0
The setupSSHforwarding script configures the Linux kernel using iptables or nftables to setup Network Address Translation to forward an alias for the SSH port to the hercules guest. Fedora 32 moved to nftables, so this script has been updated to use nft if it is available and fallback to iptables.
By default, port 3270 is used for the alias port. Assuming the hercules process was running on a host named host and the initial account for Ubuntu was named loginName,
ssh -p 3270 -l loginName host
will connect to the hercules-hosted operating system.
Note: This script requires root privileges. The boot_ubuntu.sh script will use the sudo command to obtain the required elevated privileges if it was not invoked by the root user.
#!/bin/sh # setupSSHforwarding - forward to SSH port on local guest virtual machine image # The aliasPort on the hosting machine will be forwarded to the guestPort # listening at the end of the tunnel to guestAddr. aliasPort=3270 guestPort=22 guestAddr="10.1.1.2" userId=`id -u` if test ${userId} -ne 0 then printf "%s: must be root to set iptables\n" "${0}" >&2 exit 1 fi defaultInterface=`netstat -rn | awk '/^0.0.0.0 / { print $NF; exit; }'` while test $# -gt 0 do case "${1}" in -h | -help | --help) printf "usage: %s [--listen lPort] [--fwdport dPort] [--toaddr dAddr] [--if interface]\n" "${0}" >&2 printf " --listen = listen on port (default %d)\n" ${aliasPort} >&2 printf " --fwdport = forward to guest machine port (default %d)\n" ${guestPort} >&2 printf " --toaddr = forward to guest machine address (default %s)\n" "${guestAddr}" >&2 printf " --if = listen on interface (default %s)\n" "${defaultInterface}" >&2 exit 1 ;; --listen) aliasPort="${2}" shift ;; --fwdport) guestPort="${2}" shift ;; --toaddr) guestAddr="${2}" shift ;; --if) defaultInterface="${2}" shift ;; *) printf "%s: unrecognized argument \"%s\"\n" "${0}" "${1}" >&2 exit 1 ;; esac shift done set -x # incoming connections to ${aliasPort} get redirected to guest machine address iptables -I PREROUTING -p tcp -t nat -i "${defaultInterface}" --dport ${aliasPort} -j DNAT --to ${guestAddr}:${guestPort} # Allow connection to guest port to be permitted iptables -A FORWARD -p tcp -d ${guestAddr} --dport ${guestPort} -j ACCEPT # required to allow established connection to flow iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT exit 0
The boot_ubuntu.sh script is normally used to invoke hercules with the hercules-ubuntu.cfg configuration file. It does have a second mode, enabled with the ‑‑iso option, that can mount a CD-ROM image of a Ubuntu install disk and perform the Initial Program Load from that virtual CD device so that the initial installation can be performed.
It makes use of setupCTCnetwork and setupSSHforwarding to configure Network Address Translation and the forwarding of an aliased port to the SSH port on the hercules guest.
#!/bin/sh # boot_ubuntu.sh - boot Ubuntu s390x image using hercules originDir=`dirname $0` sudoCmd="" mountISO="" useScreen=0 rcBootFile="${originDir}/hercules-ipl.rc" defaultGateway=`netstat -rn | awk '/^0.0.0.0/ { print $2; exit; }'` defaultHostname="ubuntu-z" DNSserver="${defaultGateway}" initialPW="initialpw" defaultDomain=`dnsdomainname` while test $# -gt 0 do case "${1}" in -h | -help | --help) printf "usage: %s [--screen] [{--iso isoFileName [--dns DNSserver] [--gw gatewayAddr] [--host hostName] [--domain domainName] [--pw installPassword]}]\n" "${0}" >&2 printf " --iso image = boot from CD image\n" >&2 printf " Image will be associated with a read-only loopback device and mounted,\n" >&2 printf " then IPLed using ubuntu.ins in the root directory\n" >&2 printf " Default gateway and DNS server: %s\n" "${defaultGateway}" >&2 printf " Default hostname: %s\n" "${defaultHostname}" >&2 printf " Default domain: %s\n" "${defaultDomain}" >&2 printf " Default install password: %s\n" "${initialPW}" >&2 exit 1 ;; --screen) useScreen=1 ;; --iso) mountISO="${2}" shift ;; --dns) DNSserver="${2}" shift ;; --domain) defaultDomain="${2}" shift ;; --gw) defaultGateway="${2}" shift ;; --host) defaultHostname="${2}" shift ;; --pw) initialPW="${2}" shift ;; -*) printf "%s: unrecognized option: \"%s\"\n" "${0}" "${1}" >&2 exit 1 ;; *) printf "%s: unrecognized argument: \"%s\"\n" "${0}" "${1}" >&2 exit 1 ;; esac shift done userId=`id -u` if test ${userId} -ne 0 then # not root printf "%s: using sudo to gain root permission to configure network\n" "${0}" sudoCmd="sudo" fi # clear IP tables, setup NAT ${sudoCmd} ${originDir}/setupCTCnetwork rc=$? if test ${rc} -ne 0 then printf "%s: could not configure networking\n" "${0}" >&2 exit 1 fi ${sudoCmd} ${originDir}/setupSSHforwarding # start hercules if test -n "${mountISO}" then # boot from mounted ISO set -x mountPoint="/tmp/s390x.iso" useLoopDevice=`${sudoCmd} losetup -r --find --show ${mountISO}` ${sudoCmd} mkdir -p ${mountPoint} ${sudoCmd} mount -r ${useLoopDevice} ${mountPoint} iplInstructions=`ls ${mountPoint}/ubuntu.ins` if test -z "${iplInstructions}" then printf "%s: could not find IPL instructions, expected ubuntu.ins under %s\n" "${0}" "${mountPoint}" >&2 exit 1 fi rcBootFile="/tmp/iplFromISO.rc" # ipl instructions # 1 = use CTC # 1 = set read device # 2 = set write device # 2 = set protocol to Linux # 2 = set network configuration manually # 10.1.1.2 = local IP address # 255.255.255.0 = network mask # ${defaultGateway} = gateway # ${defaultDNS} = nameserver # ${defaultHostname} = hostname # ${defaultDomain} = domain name # initialpw = install password # initialpw = install password cat > ${rcBootFile} <<endIPL ipl ${iplInstructions} .1 .1 .2 .2 .2 .10.1.1.2 .255.255.255.0 .${defaultGateway} .${DNSserver} .${defaultHostname} .${defaultDomain} .${initialPW} .${initialPW} endIPL trap "rm -f ${rcBootFile}" EXIT fi if test ${useScreen} -eq 1 then screen -D -m -S 'hercules zSeries Ubuntu' -t 'zeries Ubuntu' \ hercules -f ${originDir}/hercules-ubuntu.cfg --rc ${rcBootFile} sleep 2 else hercules -f ${originDir}/hercules-ubuntu.cfg --rc ${rcBootFile} if test -n "${mountISO}" then echo umount ${mountPoint} umount ${mountPoint} echo losetup -d ${useLoopDevice} losetup -d ${useLoopDevice} fi fi
The bootUnderScreen script uses the screen command to launch an instance of boot_ubuntu.sh. The associated script connectToHerculesScreen is used to connect to the screen when desired.
#/bin/sh # bootUnderScreen - run boot_ubuntu.sh under screen originDir=`dirname $0` PATH=${PATH}:${originDir} export PATH screen -D -m -S 'hercules zSeries Ubuntu' -t 'zeries Ubuntu' boot_ubuntu.sh "$@"
The connectToHerculesScreen is a convenience cover script that uses the screen command to locate and attach to the virtual screen created by a previous invocation of bootUnderScreen.
#!/bin/sh # connectToHerculesScreen - connect to screen created by bootUnderScreen sudoCmd="" userId=`id -u` if test ${userId} -ne 0 then # not root printf "%s: using sudo to gain root permission to access screen\n" "${0}" sudoCmd="sudo" fi screenSession=`${sudoCmd} screen -list | fgrep zSeries | awk '{ print $1; }'` sessionTitle=`${sudoCmd} screen -list | fgrep zSeries | awk '{ s = $2; for(i=3;i<NF;i+=1) { s = s " " $i; } print s; }'` echo screen ${screenSession} title ${sessionTitle} set -x ${sudoCmd} screen -r "${screenSession}" -s "${sessionTitle}"
If you are lucky, the Ubuntu installer will correctly configure the network for you. If not, you will have to effect repairs manually. The current release of Ubuntu moved to using netplan and is biased towards using systemd-networkd for servers and NetworkManager for desktops.
It is tedious to use the system console terminal, so it is simplest to effect a temporary repair to enable networking and then login using a regular terminal session. Login on the console using the login name you created for yourself, remembering to prefix each line with a period ("."), and use ifconfig to setup the point-to-point link. Your session will look something like the following:
.loginName .password .sudo ifconfig dstaddr 10.1.1.1 slca00 .password
Once the point-to-point link is up, you can login via an SSH session. From the host running the hercules guest, you can use 10.1.1.2 as the destination address. From elsewhere, you can use the name of the host running hercules and port 3270. Thus:
ssh -l loginName 10.1.1.2or
ssh -l loginName -p 3270 hostName
The /etc/netplan/01-netcfg.yaml file should appear similar to:
# This file describes the network interfaces available on your system # For more information, see netplan(5). network: version: 2 renderer: networkd ethernets: slca00: dhcp4: no dhcp6: no addresses: [ 10.1.1.2/24 ] routes: - to: 0.0.0.0/0 via: 10.1.1.1 on-link: true gateway4: 10.1.1.1 nameservers: search: [ your.domain.name ] addresses: - d.n.s.ip
After updating the /etc/netplan/01-netcfg.yaml file, generate and apply the configuration:
netplan --debug apply
Ensure the systemd-networkd service is enabled:
systemctl enable --now systemd-networkd
Reboot to test that the configuration is applied correctly.
In some environments, the Linux-for-zSeries image will only be booted as needed by manually invoking bootUnderScreen. In others, it will be desireable to have the image automatically booted whenever the host system completes its startup. For those scenarios, a hercules.service systemd service description is provided that can be installed into a directory such as /etc/systemd/system. This service description is dependent upon a /etc/sysconfig/hercules.env configuration file that must be created locally. The file is intended to define the HERCULES-LINUX-DIR environment variable, which is expected to point at the directory into which this package was unpacked. It will appear similar to:
HERCULES-LINUX-DIR=/root/hercules-linuxTo enable the service:
# systemctl enable hercules.serviceand start it:
# systemctl start hercules.serviceVerify startup:
# systemctl status hercules.serviceShutdown:
# systemctl stop hercules.service