Active Cluster Support, Pod Quota Fixes,Token Cache and CI Improvements (#81)

feat: add Active Cluster support and improve plugin stability

## Major Features

### Active Cluster Support (Experimental) (#42)
- Add support for multiple PureStorage arrays in Active Cluster configuration
- Automatic volume connection on all arrays for high availability
- Configure via comma-separated addresses and tokens

### Pod Quota Limit Support (#69)
- Add proper handling of pod quota_limit parameter
- Use quota_limit when set, fall back to array capacity when unlimited
- Fix capacity reporting for pods with quotas

### Session Token Caching
- Implement session token caching in /etc/pve/priv/purestorage/
- Automatic token refresh at 80% of TTL to prevent expiration
- In-memory and file-based caching with jitter to prevent thundering herd

### Debug Logging
- Add configurable debug logging with 4 levels (0-3)
- Support both config parameter and PURESTORAGE_DEBUG environment variable

## Bug Fixes
- Fix volume deletion when connected to multiple hosts
- Query all connections before destroy
- Disconnect from all hosts on all arrays
- Prevents "Cannot destroy volume because it is currently connected" error

## CI/CD Improvements
- Add workflow_dispatch trigger to checks workflow
- Add option to check all files or only changed files
- Add comprehensive markdown linting with markdownlint-cli2

## Testing
- Add token caching tests (tests/token_cache_test.pl)
- Test token validation, expiration, and race conditions
- Test cleanup of expired cache files

## Refactoring (#72)
- Refactor volume removal logic to handle multiple host connections
- Improve device cleanup sequence (LVM, partitions, multipath)
- Extract connection querying logic before volume destruction
- Refactor CI/CD workflows for better maintainability and flexibility
- Improve error handling and logging throughout the plugin
- Enhance Active Cluster support with proper multi-array operations

## Code Formatting
- Format all Perl files with perltidy using .perltidyrc configuration
- Ensure consistent code style across the codebase
- Fix formatting issues in PureStoragePlugin.pm and test files

## Documentation
- Update README with new functionality
This commit is contained in:
Timur Kumakbayev
2026-01-17 17:20:28 +05:00
committed by GitHub
parent c693d189df
commit f9f8eed94b
13 changed files with 1986 additions and 136 deletions
+112
View File
@@ -0,0 +1,112 @@
name: Checks
run-name: Checks on ${{ github.ref_name }} by ${{ github.actor }}
on:
pull_request:
types:
- opened
- synchronize
- reopened
workflow_dispatch:
inputs:
check_all_files:
description: 'Check all files (not just changed)'
required: false
type: boolean
default: true
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check-changes:
name: Check changed files
runs-on: ubuntu-22.04
outputs:
check-all: ${{ steps.set-check-all.outputs.check-all }}
perl-changed: ${{ steps.changed-files-perl.outputs.any_changed }}
markdown-changed: ${{ steps.changed-files-markdown.outputs.any_changed }}
test-changed: ${{ steps.changed-files-test.outputs.any_changed }}
perl-files: ${{ steps.set-perl-files.outputs.files }}
markdown-files: ${{ steps.set-markdown-files.outputs.files }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine if we should check all files
id: set-check-all
run: |
# Check all files only for manual workflow dispatch with check_all_files=true
# For PRs, check only changed files
if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ "${{ inputs.check_all_files }}" == "true" ]; then
echo "check-all=true" >> $GITHUB_OUTPUT
else
echo "check-all=false" >> $GITHUB_OUTPUT
fi
- name: Check changed Perl files
id: changed-files-perl
uses: tj-actions/changed-files@v44
with:
files: |
**/*.pm
**/*.pl
- name: Check changed Markdown files
id: changed-files-markdown
uses: tj-actions/changed-files@v44
with:
files: |
**/*.md
- name: Check changed test files
id: changed-files-test
uses: tj-actions/changed-files@v44
with:
files: |
tests/**/*.t
tests/**/*.pl
- name: Set Perl files to check
id: set-perl-files
run: |
if [ "${{ steps.set-check-all.outputs.check-all }}" == "true" ]; then
files=$(find . -type f \( -name "*.pm" -o -name "*.pl" \) ! -path "*/node_modules/*" ! -path "*/.git/*" | tr '\n' ' ')
echo "files=$files" >> $GITHUB_OUTPUT
else
echo "files=${{ steps.changed-files-perl.outputs.all_changed_files }}" >> $GITHUB_OUTPUT
fi
- name: Set Markdown files to check
id: set-markdown-files
run: |
if [ "${{ steps.set-check-all.outputs.check-all }}" == "true" ]; then
files=$(find . -type f -name "*.md" ! -path "*/node_modules/*" ! -path "*/.git/*" | tr '\n' ' ')
echo "files=$files" >> $GITHUB_OUTPUT
else
echo "files=${{ steps.changed-files-markdown.outputs.all_changed_files }}" >> $GITHUB_OUTPUT
fi
lint:
name: Lint
needs: check-changes
if: |
(needs.check-changes.outputs.check-all == 'true') ||
(needs.check-changes.outputs.perl-changed == 'true' || needs.check-changes.outputs.markdown-changed == 'true')
uses: ./.github/workflows/lint.yml
with:
enable-perl-lint: ${{ needs.check-changes.outputs.check-all == 'true' || needs.check-changes.outputs.perl-changed == 'true' }}
enable-markdown-lint: ${{ needs.check-changes.outputs.check-all == 'true' || needs.check-changes.outputs.markdown-changed == 'true' }}
perl-files: ${{ needs.check-changes.outputs.perl-files }}
markdown-files: ${{ needs.check-changes.outputs.markdown-files }}
test:
name: Tests
needs: check-changes
if: |
(needs.check-changes.outputs.check-all == 'true') ||
(needs.check-changes.outputs.perl-changed == 'true' || needs.check-changes.outputs.test-changed == 'true')
uses: ./.github/workflows/tests.yml
+166
View File
@@ -0,0 +1,166 @@
name: Lint
run-name: Lint ${{ inputs.enable-perl-lint && 'Perl' || '' }} ${{ inputs.enable-markdown-lint && 'Markdown' || '' }}
on:
workflow_call:
inputs:
enable-perl-lint:
description: 'Enable Perl linting'
required: false
type: boolean
default: false
enable-markdown-lint:
description: 'Enable Markdown linting'
required: false
type: boolean
default: false
perl-files:
description: 'List of changed Perl files'
required: false
type: string
default: ''
markdown-files:
description: 'List of changed Markdown files'
required: false
type: string
default: ''
jobs:
perl-lint:
name: Perl Lint
if: ${{ inputs.enable-perl-lint == true }}
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Perl
uses: shogo82148/actions-setup-perl@v1
with:
perl-version: '5.34'
- name: Install cpanm
run: |
curl -L https://cpanmin.us | perl - App::cpanminus
- name: Install linting tools
run: |
cpanm --notest Perl::Critic
sudo apt-get update
sudo apt-get install -y perltidy || true
- name: Check code formatting with perltidy
if: inputs.perl-files != ''
run: |
echo "Checking code formatting..."
changed_files="${{ inputs.perl-files }}"
if [ -z "$changed_files" ] || [ "$changed_files" == " " ]; then
echo "No Perl files to check"
exit 0
fi
if [ ! -f ".perltidyrc" ]; then
echo "Warning: .perltidyrc not found, using default perltidy settings"
fi
for file in $changed_files; do
if [[ -n "$file" ]] && ([[ "$file" == *.pm ]] || [[ "$file" == *.pl ]]); then
echo "Checking formatting: $file"
if command -v perltidy >/dev/null 2>&1; then
formatted_file="${file}.formatted"
if [ -f ".perltidyrc" ]; then
perltidy -pro=.perltidyrc "$file" -o "$formatted_file" 2>&1 || true
else
perltidy "$file" -o "$formatted_file" 2>&1 || true
fi
if [ -f "$formatted_file" ]; then
if ! diff -q "$file" "$formatted_file" >/dev/null 2>&1; then
echo "::error file=$file::File is not properly formatted. Run 'perltidy -pro=.perltidyrc $file' to fix."
echo "Differences:"
diff "$file" "$formatted_file" | head -20 || true
rm -f "$formatted_file"
exit 1
fi
rm -f "$formatted_file"
else
echo "Warning: perltidy failed to create formatted file for $file"
fi
else
echo "Warning: perltidy not found, skipping formatting check"
fi
fi
done
find . -name '*.formatted' -delete 2>/dev/null || true
- name: Run Perl::Critic (optional)
if: inputs.perl-files != ''
continue-on-error: true
run: |
echo "Running Perl::Critic static analysis..."
if command -v perlcritic >/dev/null 2>&1; then
changed_files="${{ inputs.perl-files }}"
if [ -z "$changed_files" ] || [ "$changed_files" == " " ]; then
echo "No Perl files to analyze"
exit 0
fi
for file in $changed_files; do
if [[ -n "$file" ]] && [[ "$file" == *.pm ]]; then
echo "Analyzing: $file"
perlcritic --quiet "$file" || true
fi
done
else
echo "Perl::Critic not available, skipping..."
fi
markdown-lint:
name: Markdown Lint
if: ${{ inputs.enable-markdown-lint == true }}
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install markdownlint
run: |
npm install -g markdownlint-cli2 || true
- name: Lint Markdown files
if: inputs.markdown-files != ''
run: |
echo "Linting Markdown files..."
changed_files="${{ inputs.markdown-files }}"
if [ -z "$changed_files" ] || [ "$changed_files" == " " ]; then
echo "No Markdown files to lint"
exit 0
fi
if command -v markdownlint-cli2 >/dev/null 2>&1; then
for file in $changed_files; do
if [[ -n "$file" ]] && [[ "$file" == *.md ]]; then
echo "Linting: $file"
markdownlint-cli2 "$file" "#node_modules" "#.git" || {
echo "::error file=$file::Markdown linting failed"
exit 1
}
fi
done
elif command -v markdownlint >/dev/null 2>&1; then
for file in $changed_files; do
if [[ -n "$file" ]] && [[ "$file" == *.md ]]; then
echo "Linting: $file"
markdownlint "$file" || {
echo "::error file=$file::Markdown linting failed"
exit 1
}
fi
done
else
echo "Markdown linter not available, skipping..."
fi
+33
View File
@@ -0,0 +1,33 @@
name: Tests
run-name: Tests - ${{ github.ref_name }}
on:
workflow_call:
jobs:
test:
name: Run tests
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Perl
uses: shogo82148/actions-setup-perl@v1
with:
perl-version: '5.34'
- name: Install cpanm
run: |
curl -L https://cpanmin.us | perl - App::cpanminus
- name: Install Perl dependencies
run: |
cpanm --notest Test::More JSON JSON::XS
- name: Run tests
run: |
chmod +x tests/run_tests.sh
./tests/run_tests.sh