Instance: Test vlc installation #770
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
name: Create Instance | |
on: | |
issue_comment: | |
types: [created] | |
jobs: | |
create: | |
runs-on: self-hosted | |
if: | |
${{ !github.event.issue.pull_request && ( | |
contains(github.event.comment.body, '/create') ) }} | |
steps: | |
- name: create command | |
id: create_command | |
uses: github/[email protected] | |
with: | |
command: "/create" | |
reaction: "rocket" | |
allowed_contexts: "issue" | |
permissions: "write,maintain,admin" | |
allowlist: "${{ vars.MORPHOCLOUD_GITHUB_ADMINS }}" | |
- uses: actions/checkout@v4 | |
- name: Add "request:approved" label | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
github.rest.issues.addLabels({ | |
issue_number: context.payload.issue.number, | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
labels: ["request:approved"] | |
}) | |
- name: comment (progress) | |
id: couc_progress | |
uses: ./.github/actions/comment-progress | |
with: | |
create_ip: ⏳ | |
create_volume: "" | |
create_instance: "" | |
associate_ip: "" | |
setup_instance: "" | |
attach_volume: "" | |
send_email: "" | |
- name: Extract labels | |
id: labels | |
run: | | |
# If there are multiple "flavor:" labels, select the first one | |
instance_flavor=$( | |
gh issue view $ISSUE_NUMBER \ | |
--json labels \ | |
--jq '[.labels[].name | select(. | startswith("flavor:")) | split(":")[1]][0]' | |
) | |
echo "instance_flavor=$instance_flavor" >> $GITHUB_OUTPUT | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
GH_REPO: ${{ github.repository }} | |
ISSUE_NUMBER: ${{ github.event.issue.number }} | |
- name: Define instance name | |
id: define | |
uses: ./.github/actions/define-instance-name | |
with: | |
prefix: ${{ vars.INSTANCE_NAME_PREFIX }} | |
issue_number: ${{ github.event.issue.number }} | |
- name: Check instance exists | |
id: check_instance | |
uses: ./.github/actions/check-instance-exists | |
with: | |
os_cloud: ${{ vars.MORPHOCLOUD_OS_CLOUD }} | |
instance_name: ${{ steps.define.outputs.instance_name }} | |
- name: comment (Instance already created) | |
if: ${{ fromJSON(steps.check_instance.outputs.exists) }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Instance **${{ steps.define.outputs.instance_name }}** already created. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: instance already exists (failure) | |
if: ${{ fromJSON(steps.check_instance.outputs.exists) }} | |
run: | | |
echo "::error ::Instance $INSTANCE_NAME already created" | |
exit 1 | |
env: | |
INSTANCE_NAME: ${{ steps.define.outputs.instance_name }} | |
- name: Create floating IP | |
id: ip_create | |
run: | | |
source ~/venv/bin/activate | |
json_output=$(openstack floating ip create public -f json) | |
echo $json_output | |
floating_ip_uuid=$( | |
echo $json_output | | |
jq -r ".id" | |
) | |
echo "floating_ip_uuid [$floating_ip_uuid]" | |
echo "floating_ip_uuid=$floating_ip_uuid" >> $GITHUB_OUTPUT | |
floating_ip_address=$( | |
echo $json_output | | |
jq -r ".floating_ip_address" | |
) | |
echo "floating_ip_address [$floating_ip_address]" | |
echo "floating_ip_address=$floating_ip_address" >> $GITHUB_OUTPUT | |
env: | |
OS_CLOUD: ${{ vars.MORPHOCLOUD_OS_CLOUD }} | |
- name: comment (floating IP creation failed) | |
if: ${{ steps.ip_create.outcome == 'failure' && failure() }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Failed to create floating IP for **${{ steps.define.outputs.instance_name }}** instance. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: comment (progress) | |
uses: ./.github/actions/comment-progress | |
with: | |
comment-id: ${{ steps.couc_progress.outputs.comment-id }} | |
create_ip: ✅ | |
create_volume: ⏳ | |
create_instance: "" | |
associate_ip: "" | |
setup_instance: "" | |
attach_volume: "" | |
send_email: "" | |
- name: Define volume name | |
id: define_volume_name | |
uses: ./.github/actions/define-volume-name | |
with: | |
issue_number: ${{ github.event.issue.number }} | |
suffix: ${{ vars.VOLUME_NAME_SUFFIX }} | |
- name: Check volume exists | |
id: check_volume | |
uses: ./.github/actions/check-volume-exists | |
with: | |
os_cloud: ${{ vars.MORPHOCLOUD_OS_CLOUD }} | |
volume_name: ${{ steps.define_volume_name.outputs.volume_name }} | |
- name: comment (volume already exists) | |
if: ${{ fromJSON(steps.check_volume.outputs.exists) }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ⚠️ | |
Volume **${{ steps.define_volume_name.outputs.volume_name }}** already exists. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: Create Volume | |
if: ${{ ! fromJSON(steps.check_volume.outputs.exists) }} | |
id: create_volume | |
run: | | |
source ~/venv/bin/activate | |
openstack volume create --size 100 "${VOLUME_NAME}" | |
env: | |
OS_CLOUD: ${{ vars.MORPHOCLOUD_OS_CLOUD }} | |
VOLUME_NAME: ${{ steps.define_volume_name.outputs.volume_name }} | |
- name: comment (failed to create volume) | |
if: ${{ steps.create_volume.outcome == 'failure' && failure() }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Failed to create volume. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: comment (progress) | |
uses: ./.github/actions/comment-progress | |
with: | |
comment-id: ${{ steps.couc_progress.outputs.comment-id }} | |
create_ip: ✅ | |
create_volume: ✅ | |
create_instance: ⏳ | |
associate_ip: "" | |
setup_instance: "" | |
attach_volume: "" | |
send_email: "" | |
- name: Create instance | |
id: create_instance | |
run: | | |
source ~/venv/bin/activate | |
echo Creating instance "$INSTANCE_NAME" | |
# See https://jetstream2.exosphere.app/exosphere/helpabout | |
exoClientUuid=67296a2e-069b-49ca-9ca4-5dd296869ada | |
# See "currentExoServerVersion" in exosphere/src/Types/Server.elm | |
exoServerVersion=5 | |
openstack server create "$INSTANCE_NAME" \ | |
--nic net-id="auto_allocated_network" \ | |
--security-group "exosphere" \ | |
--flavor $INSTANCE_FLAVOR \ | |
--image "Featured-Ubuntu22" \ | |
--key-name "jcfr" \ | |
--property "exoGuac={\"v\":1,\"ssh\":true,\"vnc\":true}" \ | |
--property "exoClientUuid=$exoClientUuid" \ | |
--property "exoServerVersion=$exoServerVersion" \ | |
--property "[email protected]" \ | |
--property "exoFloatingIpOption=useFloatingIp" \ | |
--property "exoFloatingIpReuseOption=$FLOATING_IP_UUID" \ | |
--property "exoSetup={\"status\":\"waiting\",\"epoch\":null}" \ | |
--user-data ./cloud-config \ | |
--wait \ | |
--column created \ | |
--column flavor \ | |
--column image \ | |
--column name \ | |
--column status | |
env: | |
OS_CLOUD: ${{ vars.MORPHOCLOUD_OS_CLOUD }} | |
INSTANCE_NAME: ${{ steps.define.outputs.instance_name }} | |
INSTANCE_FLAVOR: ${{ steps.labels.outputs.instance_flavor }} | |
FLOATING_IP_UUID: ${{ steps.ip_create.outputs.floating_ip_uuid }} | |
- name: comment (instance creation failed) | |
if: ${{ steps.create_instance.outcome == 'failure' && failure() }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Failed to create instance **${{ steps.define.outputs.instance_name }}**. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: comment (progress) | |
uses: ./.github/actions/comment-progress | |
with: | |
comment-id: ${{ steps.couc_progress.outputs.comment-id }} | |
create_ip: ✅ | |
create_volume: ✅ | |
create_instance: ✅ | |
associate_ip: ⏳ | |
setup_instance: "" | |
attach_volume: "" | |
send_email: "" | |
- name: Associate floating IP with created instance | |
id: associated_ip | |
run: | | |
source ~/venv/bin/activate | |
has_ip=$( | |
openstack server show $INSTANCE_NAME -c addresses -f json | \ | |
jq -r '.addresses.auto_allocated_network[1] != null' | |
) | |
echo "has_ip [$has_ip]" | |
if [[ $has_ip != "true" ]]; then | |
openstack server add floating ip "$INSTANCE_NAME" $FLOATING_IP_ADDRESS | |
fi | |
env: | |
OS_CLOUD: ${{ vars.MORPHOCLOUD_OS_CLOUD }} | |
FLOATING_IP_ADDRESS: | |
${{ steps.ip_create.outputs.floating_ip_address }} | |
INSTANCE_NAME: ${{ steps.define.outputs.instance_name }} | |
- name: comment (failed to associate IP with instance) | |
if: ${{ steps.associated_ip.outcome == 'failure' && failure() }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Failed to associate IP with instance **${{ steps.define.outputs.instance_name }}**. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: comment (progress) | |
uses: ./.github/actions/comment-progress | |
with: | |
comment-id: ${{ steps.couc_progress.outputs.comment-id }} | |
create_ip: ✅ | |
create_volume: ✅ | |
create_instance: ✅ | |
associate_ip: ✅ | |
setup_instance: ⏳ | |
attach_volume: "" | |
send_email: "" | |
- name: Poll instance setup status | |
id: instance_poll | |
run: | | |
source ~/venv/bin/activate | |
echo Polling "$INSTANCE_NAME" setup status | |
max_wait_time=1200 # Maximum wait time in seconds (1200s -> 20mins) | |
wait_interval=5 # Interval between status checks in seconds | |
total_wait_time=0 | |
while [ $total_wait_time -lt $max_wait_time ]; do | |
status=$(openstack console log show $INSTANCE_NAME | \ | |
grep "^\{\"status\":\"" | \ | |
tail -1 | \ | |
jq -r '.status // "pending"') | |
echo -n "setup status [$status]. " | |
if [[ "$status" == "complete" ]]; then | |
echo "Exiting loop." | |
break | |
else | |
echo "Waiting for completion..." | |
sleep $wait_interval | |
total_wait_time=$((total_wait_time + wait_interval)) | |
fi | |
done | |
if [ $total_wait_time -ge $max_wait_time ]; then | |
echo "::error ::Maximum wait time ($max_wait_time seconds) exceeded." | |
exit 1 | |
fi | |
echo "status=$status" >> $GITHUB_OUTPUT | |
env: | |
OS_CLOUD: ${{ vars.MORPHOCLOUD_OS_CLOUD }} | |
INSTANCE_NAME: ${{ steps.define.outputs.instance_name }} | |
- name: comment (maximum wait time exceeded) | |
if: ${{ steps.instance_poll.outcome == 'failure' && failure() }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Maximum wait time for instance **${{ steps.define.outputs.instance_name }}** setup to complete exceeded. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: comment (progress) | |
uses: ./.github/actions/comment-progress | |
with: | |
comment-id: ${{ steps.couc_progress.outputs.comment-id }} | |
create_ip: ✅ | |
create_volume: ✅ | |
create_instance: ✅ | |
associate_ip: ✅ | |
setup_instance: ✅ | |
attach_volume: ⏳ | |
send_email: "" | |
- name: Rename MyData directory to MyData-tmp | |
id: rename_mydata | |
run: | | |
ssh \ | |
-o StrictHostKeyChecking=no \ | |
-o UserKnownHostsFile=/dev/null \ | |
-o LogLevel=ERROR \ | |
exouser@$INSTANCE_IP \ | |
'mv /media/volume/MyData /media/volume/MyData-tmp' | |
env: | |
INSTANCE_IP: ${{ steps.ip_create.outputs.floating_ip_address }} | |
- name: comment (failed to rename MyData) | |
if: ${{ steps.rename_mydata.outcome == 'failure' && failure() }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Failed to rename `/media/volume/MyData` to `/media/volume/MyData-tmp` for instance **${{ steps.define.outputs.instance_name }}**. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: Attach Volume | |
id: attach_volume | |
run: | | |
source ~/venv/bin/activate | |
instance_id=$(openstack server list -f json | \ | |
jq \ | |
--arg instance_name "$INSTANCE_NAME" \ | |
-c '.[] | select(.Name == $instance_name)' | \ | |
jq -r '.ID' | tail -1) | |
echo "instance_id [$instance_id]" | |
volume_id=$(openstack volume list -f json | \ | |
jq \ | |
--arg volume_name "$VOLUME_NAME" \ | |
-c '.[] | select(.Name == $volume_name)' | \ | |
jq -r '.ID' | tail -1) | |
echo "volume_id [$volume_id]" | |
openstack server set \ | |
--property "exoVolumes::$volume_id={\"name\":\"MyData\"}" \ | |
$instance_id | |
openstack server add volume \ | |
$instance_id \ | |
$volume_id | |
env: | |
OS_CLOUD: ${{ vars.MORPHOCLOUD_OS_CLOUD }} | |
INSTANCE_NAME: ${{ steps.define.outputs.instance_name }} | |
VOLUME_NAME: ${{ steps.define_volume_name.outputs.volume_name }} | |
- name: comment (failed to attach volume) | |
if: ${{ steps.attach_volume.outcome == 'failure' && failure() }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Failed to attach volume **${{ steps.define_volume_name.outputs.volume_name }}** to instance **${{ steps.define.outputs.instance_name }}**. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: Copy installed files into attached volume | |
id: copy_installed_files | |
run: | | |
function check_mountpoint_ready { | |
ssh \ | |
-o StrictHostKeyChecking=no \ | |
-o UserKnownHostsFile=/dev/null \ | |
-o LogLevel=ERROR \ | |
exouser@$INSTANCE_IP \ | |
'mountpoint -q /media/volume/MyData' | |
} | |
set +e | |
max_attempts=5 | |
for attempt in $(seq 1 $max_attempts); do | |
echo "Checking if mount point is ready ($attempt/$max_attempts)" | |
check_mountpoint_ready | |
if check_mountpoint_ready; then | |
echo "Mount point /media/volume/MyData is ready." | |
break | |
else | |
echo "Mount point not ready. Retrying in 5 seconds..." | |
sleep 5 | |
fi | |
done | |
if ! check_mountpoint_ready; then | |
echo "::error ::Mount point /media/volume/MyData not ready after $((max_attempts * 5)) seconds." | |
exit 1 | |
fi | |
set -e | |
ssh \ | |
-o StrictHostKeyChecking=no \ | |
-o UserKnownHostsFile=/dev/null \ | |
-o LogLevel=ERROR \ | |
exouser@$INSTANCE_IP \ | |
'[ ! -d /media/volume/MyData/Slicer ] && mv /media/volume/MyData-tmp/Slicer /media/volume/MyData/Slicer && rmdir /media/volume/MyData-tmp || rm -rf /media/volume/MyData-tmp' | |
env: | |
INSTANCE_IP: ${{ steps.ip_create.outputs.floating_ip_address }} | |
- name: comment (failed to copy installed files from MyData-tmp to MyData) | |
if: ${{ steps.copy_installed_files.outcome == 'failure' && failure() }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Failed to copy installed files from `/media/volume/MyData-tmp` to `/media/volume/MyData` for instance **${{ steps.define.outputs.instance_name }}**. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: Create Renviron file | |
id: create_renviron_file | |
run: | | |
ssh \ | |
-o StrictHostKeyChecking=no \ | |
-o UserKnownHostsFile=/dev/null \ | |
-o LogLevel=ERROR \ | |
exouser@$INSTANCE_IP \ | |
'echo -e "R_LIBS_SITE=/media/share/MorphoCloudCephShare/R/x86_64-pc-linux-gnu-library/4.4/\nR_LIBS_USER=/media/volume/MyData/R/x86_64-pc-linux-gnu-library/4.4/" > /home/exouser/.Renviron && mkdir -p /media/volume/MyData/R/x86_64-pc-linux-gnu-library/4.4/' | |
env: | |
INSTANCE_IP: ${{ steps.ip_create.outputs.floating_ip_address }} | |
- name: comment (failed to create /home/exouser/.Renviron) | |
if: ${{ steps.create_renviron_file.outcome == 'failure' && failure() }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Failed to create `/home/exouser/.Renviron` file for instance **${{ steps.define.outputs.instance_name }}**. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: Update Request Status Label | |
id: update-request-status-label | |
uses: ./.github/actions/update-request-status-label | |
with: | |
os_cloud: ${{ vars.MORPHOCLOUD_OS_CLOUD }} | |
token: ${{ secrets.GITHUB_TOKEN }} | |
instance_name: ${{ steps.define.outputs.instance_name }} | |
issue_number: ${{ github.event.issue.number }} | |
- name: comment (failed to update request status label) | |
if: | |
${{ steps.update-request-status-label.outcome == 'failure' && | |
failure() }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Failed to update request status label for instance **${{ steps.define.outputs.instance_name }}**. | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: comment (progress) | |
uses: ./.github/actions/comment-progress | |
with: | |
comment-id: ${{ steps.couc_progress.outputs.comment-id }} | |
create_ip: ✅ | |
create_volume: ✅ | |
create_instance: ✅ | |
associate_ip: ✅ | |
setup_instance: ✅ | |
attach_volume: ✅ | |
send_email: ⏳ | |
- name: Send mail | |
id: send_email | |
if: ${{ steps.instance_poll.outputs.status == 'complete' }} | |
uses: ./.github/actions/send-email | |
with: | |
os_cloud: ${{ vars.MORPHOCLOUD_OS_CLOUD }} | |
token: ${{ secrets.GITHUB_TOKEN }} | |
string_encryption_key: ${{ secrets.STRING_ENCRYPTION_KEY }} | |
mail_server_username: ${{secrets.MAIL_USERNAME}} | |
mail_server_password: ${{secrets.MAIL_PASSWORD}} | |
instance_name: ${{ steps.define.outputs.instance_name }} | |
instance_issue_number: ${{ github.event.issue.number }} | |
- name: comment (failed to send email) | |
if: ${{ steps.send_email.outcome == 'failure' && failure() }} | |
uses: peter-evans/[email protected] | |
with: | |
issue-number: ${{ github.event.issue.number }} | |
body: | | |
### Instance Creation Results ❌ | |
Failed to send connection email for instance **${{ steps.define.outputs.instance_name }}**. ${{ steps.send_email.outputs.error_message }} | |
See details at https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
- name: comment (progress) | |
uses: ./.github/actions/comment-progress | |
with: | |
comment-id: ${{ steps.couc_progress.outputs.comment-id }} | |
create_ip: ✅ | |
create_volume: ✅ | |
create_instance: ✅ | |
associate_ip: ✅ | |
setup_instance: ✅ | |
attach_volume: ✅ | |
send_email: ✅ |