-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from klauer/testing
Add initial implementation to provision TwinCAT/BSD PLCs with ansible
- Loading branch information
Showing
16 changed files
with
1,154 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.DS_Store | ||
*_rsa | ||
*.pub | ||
# Only include the template: | ||
/host_inventory.yaml | ||
TCBSD*.vdi | ||
TCBSD*.iso |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
external-sources=true | ||
|
||
disable=SC1091 | ||
disable=SC1090 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# This is the IP address of the PLC. | ||
PLC_IP ?= | ||
PLC_HOSTNAME ?= my-plcname | ||
PLC_NET_ID ?= $(PLC_IP).1.1 | ||
PLC_USERNAME ?= Administrator | ||
SSH_KEY_FILENAME ?= $(shell pwd)/tcbsd_key_rsa | ||
|
||
# This auto-detects your local adapter's IP address. It may be completely wrong. | ||
# Change it in your environment (OUR_IP_ADDRESS=... make) or replace the value | ||
# after ?= with your IP. | ||
OUR_IP_ADDRESS ?= $(shell ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' | head -n 1) | ||
OUR_NET_ID ?= $(OUR_IP_ADDRESS).1.1 | ||
OUR_ROUTE_NAME ?= $(shell hostname -s) | ||
|
||
export PLC_HOSTNAME | ||
export PLC_IP | ||
export PLC_NET_ID | ||
export PLC_USERNAME | ||
export OUR_IP_ADDRESS | ||
export OUR_NET_ID | ||
export OUR_ROUTE_NAME | ||
export SSH_KEY_FILENAME | ||
|
||
ifndef PLC_IP | ||
$(error PLC_IP is not set. Set it to the PLC's IP address.) | ||
endif | ||
ifndef PLC_HOSTNAME | ||
$(error PLC_HOSTNAME is not set.) | ||
endif | ||
ifndef OUR_IP_ADDRESS | ||
$(warning OUR_IP_ADDRESS is not set. Will not be able to add route.) | ||
endif | ||
|
||
all: ssh-setup run-provision | ||
|
||
ssh-setup: | ||
if [ ! -f "$(SSH_KEY_FILENAME)" ]; then \ | ||
ssh-keygen -t rsa -f "$(SSH_KEY_FILENAME)"; \ | ||
fi | ||
ssh-copy-id -i "$(SSH_KEY_FILENAME)" "$(PLC_USERNAME)@$(PLC_IP)" | ||
$(MAKE) ssh SSH_ARGS='echo "Successfully logged in with the key to $(PLC_IP)"' | ||
|
||
ssh: | ||
ssh -i "$(SSH_KEY_FILENAME)" "$(PLC_USERNAME)@$(PLC_IP)" $(SSH_ARGS) | ||
|
||
host_inventory.yaml: Makefile host_inventory.yaml.template | ||
# This substitutes our local environment into ``host_inventory.yaml.template`` | ||
# and writes ``host_inventory.yaml`` | ||
envsubst < "host_inventory.yaml.template" > "$@" | ||
|
||
run-bootstrap: host_inventory.yaml tcbsd-bootstrap-playbook.yaml | ||
ansible-playbook tcbsd-bootstrap-playbook.yaml -i host_inventory.yaml | ||
|
||
run-provision: run-bootstrap host_inventory.yaml tcbsd-provision-playbook.yaml | ||
ansible-playbook tcbsd-provision-playbook.yaml -i host_inventory.yaml | ||
|
||
add-route: | ||
# NOTE: the add_route script lazily uses environment variables instead of | ||
# command-line arguments. | ||
bash add_route.sh | ||
|
||
.PHONY: all ssh-setup ssh run-provision run-bootstrap add-route |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#!/usr/bin/env bash | ||
|
||
if [ -z "$OUR_IP_ADDRESS" ]; then | ||
echo "This script is intended to be run from the Makefile as it expects a" 2>/dev/stderr | ||
echo "certain set of variables to be set in advance. Sorry!" 2>/dev/stderr | ||
exit 1 | ||
fi | ||
|
||
echo "Your local IP is set as: ${OUR_IP_ADDRESS} (**)" | ||
echo "PLC IP address: ${PLC_IP}" | ||
echo "Local AMS net ID: ${OUR_NET_ID}" | ||
echo "PLC username: ${PLC_USERNAME}" | ||
echo "PLC route name: ${OUR_ROUTE_NAME}" | ||
echo | ||
echo "** If using the auto-detection from the Makefile, it may be wrong." | ||
echo " Please set OUR_IP_ADDRESS specifically before running this." | ||
echo | ||
read -p "Enter password for adding PLC route: " -rs PLC_PASSWORD ; | ||
echo | ||
|
||
set -e | ||
|
||
if command -v adstool &> /dev/null; then | ||
echo "Found adstool, using it..." | ||
adstool "${PLC_IP}" --localams="${OUR_NET_ID}" --log-level=0 addroute \ | ||
--addr="${OUR_IP_ADDRESS}" --netid="${OUR_NET_ID}" \ | ||
--username="${PLC_USERNAME}" --password="${PLC_PASSWORD}" \ | ||
--routename="${OUR_ROUTE_NAME}"; | ||
elif command -v ads-async &> /dev/null; then | ||
echo "Found ads-async, using it..." | ||
echo "PLC information:" | ||
ads-async info "${PLC_IP}" | ||
ADS_ASYNC_LOCAL_IP="${OUR_IP_ADDRESS}" ADS_ASYNC_LOCAL_NET_ID="${OUR_NET_ID}" \ | ||
ads-async route --route-name "${OUR_ROUTE_NAME}" \ | ||
--username "${PLC_USERNAME}" --password "${PLC_PASSWORD}" \ | ||
"${PLC_IP}" "${OUR_NET_ID}" "${OUR_IP_ADDRESS}"; | ||
else | ||
echo "No ads tools found to get PLC info / add route" | ||
fi | ||
echo "Added a route to the PLC named ${OUR_ROUTE_NAME}:" | ||
echo " ${OUR_IP_ADDRESS} - ${OUR_NET_ID} <-> ${PLC_IP} ${PLC_NET_ID}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
#!/usr/bin/env bash | ||
# | ||
# by @klauer, loosely based on https://github.com/PTKu/TwinCAT-BSD-VM-creator | ||
|
||
set -e | ||
|
||
usage () { | ||
echo "Usage: $0 vm_name [tcbsd_iso_image]" >&2 | ||
exit 0 | ||
} | ||
|
||
die () { | ||
echo "$@" >&2 | ||
exit 1 | ||
} | ||
|
||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) | ||
VM_NAME=$1 | ||
TCBSD_ISO_IMAGE=$2 | ||
VM_HDD="$PWD/$VM_NAME/$1.vhd" | ||
|
||
if [[ $# -lt 1 || $# -gt 2 || -z "$VM_NAME" ]]; then | ||
usage | ||
fi | ||
|
||
if [ -z "$TCBSD_ISO_IMAGE" ]; then | ||
# shellcheck disable=SC2012 | ||
TCBSD_ISO_IMAGE=$(ls "${SCRIPT_DIR}/TCBSD"*.iso | head -n 1) | ||
fi | ||
|
||
echo "* VM name: ${VM_NAME}" | ||
echo "* TcBSD ISO: ${TCBSD_ISO_IMAGE}" | ||
echo "* Disk name: ${VM_NAME}" | ||
|
||
if [ ! -f "$TCBSD_ISO_IMAGE" ]; then | ||
die " | ||
* TcBsd ISO image not found. Download it here: | ||
-> https://www.beckhoff.com/en-en/products/ipc/software-and-tools/operating-systems/c9900-s60x-cxxxxx-0185.html | ||
" | ||
fi | ||
|
||
if ! command -v VBoxManage &>/dev/null; then | ||
die "VirtualBox installation not found." | ||
fi | ||
|
||
TCBSD_VDI_IMAGE="$SCRIPT_DIR/$(basename "${TCBSD_ISO_IMAGE%.*}").vdi" | ||
|
||
echo "* TcBSD VirtualBox-specific VDI: ${TCBSD_VDI_IMAGE}" | ||
|
||
vbox_manage() { | ||
echo "Running: VBoxManage $*" | ||
VBoxManage "$@" | ||
EXIT_CODE=$? | ||
if [ $EXIT_CODE -gt 0 ]; then | ||
echo "VBoxManage reported exit code $EXIT_CODE; exiting early." | ||
exit "$EXIT_CODE" | ||
fi | ||
echo "" | ||
} | ||
|
||
show_vm_info() { | ||
VBoxManage showvminfo "$1" | ||
} | ||
|
||
set +e | ||
|
||
if [ ! -f "$TCBSD_VDI_IMAGE" ]; then | ||
echo "* Converting ISO to TcBSD VirtualBox-specific VDI" | ||
vbox_manage convertfromraw --format VDI "$TCBSD_ISO_IMAGE" "$TCBSD_VDI_IMAGE" 2>&1 | ||
fi | ||
|
||
if show_vm_info "$VM_NAME" &> /dev/null; then | ||
echo "VBoxManage reports that the VM ${VM_NAME} already exists." | ||
read -rp "Delete it? [yN]" yn | ||
|
||
if [[ "$yn" != "y" ]]; then | ||
echo "VM already exists; cannot continue" >/dev/stderr | ||
exit 1 | ||
fi | ||
|
||
echo "Unregistering ${VM_NAME} from VirtualBox and moving files to a backup directory." | ||
set -x | ||
vbox_manage unregistervm "$VM_NAME" | ||
mv "$VM_NAME" "${VM_NAME}.old.$(date +%s)" | ||
set +x | ||
fi | ||
|
||
echo "* Creating the VM" | ||
vbox_manage createvm --name "$VM_NAME" --basefolder "$PWD" --ostype FreeBSD_64 --register | ||
|
||
echo "* Setting VM basic settings" | ||
vbox_manage modifyvm "$VM_NAME" --memory 1024 --vram 128 --acpi on --hpet on --graphicscontroller vmsvga --firmware efi64 | ||
|
||
echo "* Setting VM storage settings" | ||
vbox_manage storagectl "$VM_NAME" --name SATA --add sata --controller IntelAhci --hostiocache on --bootable on | ||
|
||
echo "* Attaching to installation HDD to SATA Port 1" | ||
vbox_manage storageattach "$VM_NAME" --storagectl "SATA" --device 0 --port 1 --type hdd --medium "$TCBSD_VDI_IMAGE" | ||
|
||
echo "* Creating an empty 8GB disk image for the TwinCAT BSD installation" | ||
vbox_manage createmedium --filename "$VM_HDD" --size 8192 --format VHD 2>&1 | ||
|
||
echo "* Attaching the empty disk image to SATA Port 0" | ||
vbox_manage storageattach "$VM_NAME" --storagectl "SATA" --device 0 --port 0 --type hdd --medium "$VM_HDD" | ||
|
||
if command -v xdg-open &>/dev/null; then | ||
OPEN="xdg-open" | ||
elif command -v open &>/dev/null; then | ||
OPEN="open" | ||
elif command -v start.exe &>/dev/null; then | ||
OPEN="start.exe" | ||
else | ||
echo "Created VM but unable to figure out how to show it to you. Look in $PWD/$VM_NAME" | ||
ls "$PWD/$VM_NAME" | ||
exit 0 | ||
fi | ||
|
||
"$OPEN" "$PWD/$VM_NAME" |
Oops, something went wrong.