Skip to content

Automatic Provisioning

The SLURM PowerAutomate system begins when applicants fill out a Microsoft Form requesting access. Power Automate sends an adaptive card to administrators for approval or denial. Upon approval, Power Automate updates a shared Excel file on OneDrive with the request details. The SLURM server periodically checks this Excel file for changes, automatically processing approved "new" requests by creating LDAP accounts with home directories and adding them to the proper advisor/student group, and "extension" requests by modifying account expiration dates. After successful processing, the server updates the Excel file with generated usernames and passwords, triggering Power Automate to send an email to the applicant with their credentials and access details. This end-to-end automation eliminates manual intervention while maintaining proper approval workflows and audit trails.

Power Automate Flow

The current Power Automate setup is not flexible enough, resulting in two separate flows for the new-user and extension scenarios. Each pair of flows is largely similar, with only minor differences, and there are also two separate flows dedicated to sending emails for these cases.

2 Flows Triggered by New Form Submission

Adaptive Card JSON
{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "text": "📝 New Resource Request Received",
      "weight": "Bolder",
      "size": "Large"
    },
    {
      "type": "TextBlock",
      "text": "📧 KFUPM Email: @{outputs('Get_response_details')?['body/responder']}",
      "wrap": true
    },
    {
      "type": "TextBlock",
      "text": "🏫 Academic Department: @{replace(replace(outputs('Get_response_details')?['body/ra7f68cb1b98841d7bbe8534dfa405e37'], '\', '\\'), '"', '\"')}",
      "wrap": true
    },
    {
      "type": "TextBlock",
      "text": "📚 Topic Description: @{replace(replace(outputs('Get_response_details')?['body/r49b61f1dfb7b464bbdaaf11899aa8c74'], '\', '\\'), '"', '\"')}",
      "wrap": true
    },
    {
      "type": "TextBlock",
      "text": "⏳ Period of Access: @{outputs('Get_response_details')?['body/r76be5d1721bf4706b7c0e999a77aa517']} Days",
      "wrap": true
    },
    {
      "type": "TextBlock",
      "text": "📢 Publication Acknowledgement: @{outputs('Get_response_details')?['body/r80a67ac6574e495bbbc43dd0054e71b4']}",
      "wrap": true
    },
    {
      "type": "TextBlock",
      "text": "🗒 Additional Comments: @{replace(replace(outputs('Get_response_details')?['body/rd1e2f20f721b4538a138760a850b7e97'], '\', '\\'), '"', '\"')}",
      "wrap": true
    }
  ],
  "actions": [
    {
      "type": "Action.ShowCard",
      "title": "✅ Approve",
      "card": {
        "type": "AdaptiveCard",
        "body": [
          {
            "type": "TextBlock",
            "text": "Are you sure you want to approve this request?"
          }
        ],
        "actions": [
          {
            "type": "Action.Submit",
            "title": "Confirm Approval",
            "data": {
              "approval": "Approve"
            }
          }
        ]
      }
    },
    {
      "type": "Action.ShowCard",
      "title": "❌ Reject",
      "card": {
        "type": "AdaptiveCard",
        "body": [
          {
            "type": "TextBlock",
            "text": "Please confirm rejection and optionally explain why."
          },
          {
            "type": "Input.Text",
            "id": "rejectionReason",
            "placeholder": "Enter reason (optional)",
            "isMultiline": true
          }
        ],
        "actions": [
          {
            "type": "Action.Submit",
            "title": "Confirm Rejection",
            "data": {
              "approval": "Reject"
            }
          }
        ]
      }
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.4"
}

New User Requests

Screenshot

New Extension Requests

Screenshot

Flow: Newly Created Users (Every 10 min)

Screenshot

Flow: Newly Extended Users (Every 10 min)

Screenshot

Excel Schema

The shared "Responses" Excel sheet on OneDrive. Each field and where it comes from:

  • ReqID — Form/Power Automate
  • Request Date — Form/Power Automate
  • Request Type — Form/Power Automate
  • KFUPM_Email — Form/Power Automate
  • Full Name — Form/Power Automate
  • Department — Form/Power Automate
  • Topic — Form/Power Automate
  • AccessDays — Form/Power Automate
  • Acknowledgement — Form/Power Automate
  • Comments — Form/Power Automate
  • ApprovalStatus — Approve/Deny on Teams / Power Automate
  • Created — Server Script
  • Username — Server Script
  • Password — Server Script
  • Notified — Power Automate
  • Extended — Server Script

See Server Scripts for what actually reads/writes these columns.

Server Scripts

Scripts path: /opt/slurm-powerautomate

The server runs Python scripts that handle the core user management operations. slurm_main.py serves as the main orchestrator, reading the Excel file once and processing both creation and extension requests efficiently. slurm_auto_create.py and slurm_auto_extend.py handle the specific logic for new accounts and expiration extensions respectively. Core functionality is provided by ldap_manager.py for LDAP operations, onedrive_manager.py for Excel integration, system_manager.py for Linux operations, slurm_manager.py for SLURM accounts and associations, and utils.py for common functions. All scripts integrate with LDAP for authentication, XFS quotas for storage limits, and SLURM account association, ensuring complete user provisioning in a single automated workflow.

slurm_main.py

Main orchestrator that reads the Excel file once and coordinates both creation and extension processing. Runs with configurable modes (--create, --extend, --both) for flexible operation. Invoked automatically by slurm-powerautomate.service.

slurm_main.py

utils.py

Common utility functions including logging setup, username generation from emails, and password creation. Contains Excel column mapping and helper functions used across all modules.

utils.py

slurm_auto_create.py

Processes "new" user requests by generating usernames/passwords and creating complete SLURM accounts. Updates Excel with generated credentials upon successful account creation.

slurm_auto_create.py

slurm_auto_extend.py

Handles "extension" requests by modifying LDAP shadowExpire attributes to extend account access. Updates Excel with extension confirmation once processing is complete.

slurm_auto_extend.py

onedrive_manager.py

Microsoft OneDrive integration for Excel file operations using OAuth authentication. Provides methods to read Excel data and update individual cells with processing results.

onedrive_manager.py

ldap_manager.py

Core LDAP operations including user creation, expiration management, and account deletion. Handles SSHA password hashing.

ldap_manager.py

system_manager.py

Handles home directory creation and (previously) XFS quota setting — see Disk Quotas (XFS, old).

system_manager.py

slurm_manager.py

Handles SLURM association.

slurm_manager.py

systemd Services

For this to automatically work and check for changes in the Excel sheet, it has to be linked with a systemd service and timer.

  • slurm-powerautomate.service runs slurm_main.py with --both.
  • slurm-powerautomate.timer makes it check every 3 minutes.

slurm-powerautomate.service

Path: /etc/systemd/system/slurm-powerautomate.service

[Unit]
Description=SLURM PowerAutomate Account Processor
After=network.target

[Service]
Type=oneshot
User=root
EnvironmentFile=/etc/slurm-powerautomate/credentials
WorkingDirectory=/opt/slurm-powerautomate
ExecStart=/opt/anaconda3/bin/python /opt/slurm-powerautomate/slurm_main.py --both
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

slurm-powerautomate.timer

Path: /etc/systemd/system/slurm-powerautomate.timer

[Unit]
Description=Run SLURM PowerAutomate processor every 3 minutes
Requires=slurm-powerautomate.service

[Timer]
OnCalendar=*:0/3:00
Persistent=true

[Install]
WantedBy=timers.target

If this fails

See Power Automate Auth Failure for the most common failure mode (an expired OAuth token cache).