waldur-site-agent-cscs-dwdi 0.7.0__tar.gz → 0.7.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of waldur-site-agent-cscs-dwdi might be problematic. Click here for more details.
- waldur_site_agent_cscs_dwdi-0.7.3/PKG-INFO +284 -0
- waldur_site_agent_cscs_dwdi-0.7.3/README.md +274 -0
- {waldur_site_agent_cscs_dwdi-0.7.0 → waldur_site_agent_cscs_dwdi-0.7.3}/pyproject.toml +3 -2
- {waldur_site_agent_cscs_dwdi-0.7.0 → waldur_site_agent_cscs_dwdi-0.7.3}/tests/test_cscs_dwdi.py +46 -10
- {waldur_site_agent_cscs_dwdi-0.7.0 → waldur_site_agent_cscs_dwdi-0.7.3}/waldur_site_agent_cscs_dwdi/backend.py +307 -4
- {waldur_site_agent_cscs_dwdi-0.7.0 → waldur_site_agent_cscs_dwdi-0.7.3}/waldur_site_agent_cscs_dwdi/client.py +188 -12
- waldur_site_agent_cscs_dwdi-0.7.0/PKG-INFO +0 -240
- waldur_site_agent_cscs_dwdi-0.7.0/README.md +0 -230
- {waldur_site_agent_cscs_dwdi-0.7.0 → waldur_site_agent_cscs_dwdi-0.7.3}/.gitignore +0 -0
- {waldur_site_agent_cscs_dwdi-0.7.0 → waldur_site_agent_cscs_dwdi-0.7.3}/waldur_site_agent_cscs_dwdi/__init__.py +0 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: waldur-site-agent-cscs-dwdi
|
|
3
|
+
Version: 0.7.3
|
|
4
|
+
Summary: CSCS-DWDI reporting plugin for Waldur Site Agent
|
|
5
|
+
Author-email: OpenNode Team <info@opennodecloud.com>
|
|
6
|
+
Requires-Python: <4,>=3.9
|
|
7
|
+
Requires-Dist: httpx>=0.25.0
|
|
8
|
+
Requires-Dist: waldur-site-agent>=0.7.0
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# CSCS-DWDI Plugin for Waldur Site Agent
|
|
12
|
+
|
|
13
|
+
This plugin provides integration with the CSCS Data Warehouse Data Intelligence (DWDI) system to report both
|
|
14
|
+
computational and storage usage data to Waldur.
|
|
15
|
+
|
|
16
|
+
## Overview
|
|
17
|
+
|
|
18
|
+
The plugin implements two separate backends to handle different types of accounting data:
|
|
19
|
+
|
|
20
|
+
- **Compute Backend** (`cscs-dwdi-compute`): Reports CPU and node hour usage from HPC clusters
|
|
21
|
+
- **Storage Backend** (`cscs-dwdi-storage`): Reports storage space and inode usage from filesystems
|
|
22
|
+
|
|
23
|
+
## Backend Types
|
|
24
|
+
|
|
25
|
+
### Compute Backend
|
|
26
|
+
|
|
27
|
+
The compute backend queries the DWDI API for computational resource usage and reports:
|
|
28
|
+
|
|
29
|
+
- Node hours consumed by accounts and users
|
|
30
|
+
- CPU hours consumed by accounts and users
|
|
31
|
+
- Account-level and user-level usage aggregation
|
|
32
|
+
|
|
33
|
+
**API Endpoints Used:**
|
|
34
|
+
|
|
35
|
+
- `/api/v1/compute/usage-month/account` - Monthly usage data
|
|
36
|
+
- `/api/v1/compute/usage-day/account` - Daily usage data
|
|
37
|
+
|
|
38
|
+
### Storage Backend
|
|
39
|
+
|
|
40
|
+
The storage backend queries the DWDI API for storage resource usage and reports:
|
|
41
|
+
|
|
42
|
+
- Storage space used (converted from bytes to configured units)
|
|
43
|
+
- Inode (file count) usage
|
|
44
|
+
- Path-based resource identification
|
|
45
|
+
|
|
46
|
+
**API Endpoints Used:**
|
|
47
|
+
|
|
48
|
+
- `/api/v1/storage/usage-month/filesystem_name/data_type` - Monthly storage usage
|
|
49
|
+
- `/api/v1/storage/usage-day/filesystem_name/data_type` - Daily storage usage
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
### Compute Backend Configuration
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
backend_type: "cscs-dwdi-compute"
|
|
57
|
+
|
|
58
|
+
backend_settings:
|
|
59
|
+
cscs_dwdi_api_url: "https://dwdi.cscs.ch"
|
|
60
|
+
cscs_dwdi_client_id: "your_oidc_client_id"
|
|
61
|
+
cscs_dwdi_client_secret: "your_oidc_client_secret"
|
|
62
|
+
cscs_dwdi_oidc_token_url: "https://auth.cscs.ch/realms/cscs/protocol/openid-connect/token"
|
|
63
|
+
cscs_dwdi_oidc_scope: "openid" # Optional
|
|
64
|
+
|
|
65
|
+
backend_components:
|
|
66
|
+
nodeHours:
|
|
67
|
+
measured_unit: "node-hours"
|
|
68
|
+
unit_factor: 1
|
|
69
|
+
accounting_type: "usage"
|
|
70
|
+
label: "Node Hours"
|
|
71
|
+
|
|
72
|
+
cpuHours:
|
|
73
|
+
measured_unit: "cpu-hours"
|
|
74
|
+
unit_factor: 1
|
|
75
|
+
accounting_type: "usage"
|
|
76
|
+
label: "CPU Hours"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Storage Backend Configuration
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
backend_type: "cscs-dwdi-storage"
|
|
83
|
+
|
|
84
|
+
backend_settings:
|
|
85
|
+
cscs_dwdi_api_url: "https://dwdi.cscs.ch"
|
|
86
|
+
cscs_dwdi_client_id: "your_oidc_client_id"
|
|
87
|
+
cscs_dwdi_client_secret: "your_oidc_client_secret"
|
|
88
|
+
cscs_dwdi_oidc_token_url: "https://auth.cscs.ch/realms/cscs/protocol/openid-connect/token"
|
|
89
|
+
|
|
90
|
+
# Storage-specific settings
|
|
91
|
+
storage_filesystem: "lustre"
|
|
92
|
+
storage_data_type: "projects"
|
|
93
|
+
storage_tenant: "cscs" # Optional
|
|
94
|
+
|
|
95
|
+
# Map Waldur resource IDs to storage paths
|
|
96
|
+
storage_path_mapping:
|
|
97
|
+
"project_123": "/store/projects/proj123"
|
|
98
|
+
"project_456": "/store/projects/proj456"
|
|
99
|
+
|
|
100
|
+
backend_components:
|
|
101
|
+
storage_space:
|
|
102
|
+
measured_unit: "GB"
|
|
103
|
+
unit_factor: 0.000000001 # Convert bytes to GB
|
|
104
|
+
accounting_type: "usage"
|
|
105
|
+
label: "Storage Space (GB)"
|
|
106
|
+
|
|
107
|
+
storage_inodes:
|
|
108
|
+
measured_unit: "count"
|
|
109
|
+
unit_factor: 1
|
|
110
|
+
accounting_type: "usage"
|
|
111
|
+
label: "File Count"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Authentication
|
|
115
|
+
|
|
116
|
+
Both backends use OIDC client credentials flow for authentication with the DWDI API. You need:
|
|
117
|
+
|
|
118
|
+
- `cscs_dwdi_client_id`: OIDC client identifier
|
|
119
|
+
- `cscs_dwdi_client_secret`: OIDC client secret
|
|
120
|
+
- `cscs_dwdi_oidc_token_url`: OIDC token endpoint URL
|
|
121
|
+
- `cscs_dwdi_oidc_scope`: OIDC scope (optional, defaults to "openid")
|
|
122
|
+
|
|
123
|
+
## SOCKS Proxy Support
|
|
124
|
+
|
|
125
|
+
Both backends support SOCKS proxy for network connectivity. This is useful when the DWDI API is only accessible
|
|
126
|
+
through a proxy or jump host.
|
|
127
|
+
|
|
128
|
+
### SOCKS Proxy Configuration
|
|
129
|
+
|
|
130
|
+
Add the SOCKS proxy setting to your backend configuration:
|
|
131
|
+
|
|
132
|
+
```yaml
|
|
133
|
+
backend_settings:
|
|
134
|
+
# ... other settings ...
|
|
135
|
+
socks_proxy: "socks5://localhost:12345" # SOCKS5 proxy URL
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Supported Proxy Types
|
|
139
|
+
|
|
140
|
+
- **SOCKS5**: `socks5://hostname:port`
|
|
141
|
+
- **SOCKS4**: `socks4://hostname:port`
|
|
142
|
+
- **HTTP**: `http://hostname:port`
|
|
143
|
+
|
|
144
|
+
### Usage Examples
|
|
145
|
+
|
|
146
|
+
**SSH Tunnel with SOCKS5:**
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Create SSH tunnel to jump host
|
|
150
|
+
ssh -D 12345 -N user@jumphost.cscs.ch
|
|
151
|
+
|
|
152
|
+
# Configure backend to use tunnel
|
|
153
|
+
backend_settings:
|
|
154
|
+
socks_proxy: "socks5://localhost:12345"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**HTTP Proxy:**
|
|
158
|
+
|
|
159
|
+
```yaml
|
|
160
|
+
backend_settings:
|
|
161
|
+
socks_proxy: "http://proxy.cscs.ch:8080"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Resource Identification
|
|
165
|
+
|
|
166
|
+
### Compute Resources
|
|
167
|
+
|
|
168
|
+
For compute resources, the system uses account names as returned by the DWDI API. The Waldur resource
|
|
169
|
+
`backend_id` should match the account name in the cluster accounting system.
|
|
170
|
+
|
|
171
|
+
### Storage Resources
|
|
172
|
+
|
|
173
|
+
For storage resources, there are two options:
|
|
174
|
+
|
|
175
|
+
1. **Direct Path Usage**: Set the Waldur resource `backend_id` to the actual filesystem path
|
|
176
|
+
2. **Path Mapping**: Use the `storage_path_mapping` setting to map resource IDs to paths
|
|
177
|
+
|
|
178
|
+
## Usage Reporting
|
|
179
|
+
|
|
180
|
+
Both backends are read-only and designed for usage reporting. They implement the `_get_usage_report()` method
|
|
181
|
+
but do not support:
|
|
182
|
+
|
|
183
|
+
- Account creation/deletion
|
|
184
|
+
- Resource management
|
|
185
|
+
- User management
|
|
186
|
+
- Limit setting
|
|
187
|
+
|
|
188
|
+
## Example Configurations
|
|
189
|
+
|
|
190
|
+
See the `examples/` directory for complete configuration examples:
|
|
191
|
+
|
|
192
|
+
- `cscs-dwdi-compute-config.yaml` - Compute backend only
|
|
193
|
+
- `cscs-dwdi-storage-config.yaml` - Storage backend only
|
|
194
|
+
- `cscs-dwdi-combined-config.yaml` - Both backends in one configuration
|
|
195
|
+
|
|
196
|
+
## Installation
|
|
197
|
+
|
|
198
|
+
The plugin is automatically discovered when the waldur-site-agent-cscs-dwdi package is installed alongside waldur-site-agent.
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Install all workspace packages including cscs-dwdi plugin
|
|
202
|
+
uv sync --all-packages
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Testing
|
|
206
|
+
|
|
207
|
+
Run the test suite:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
uv run pytest plugins/cscs-dwdi/tests/
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## API Compatibility
|
|
214
|
+
|
|
215
|
+
This plugin is compatible with DWDI API version 1 (`/api/v1/`). It requires the following API endpoints to be available:
|
|
216
|
+
|
|
217
|
+
**Compute API:**
|
|
218
|
+
|
|
219
|
+
- `/api/v1/compute/usage-month/account`
|
|
220
|
+
- `/api/v1/compute/usage-day/account`
|
|
221
|
+
|
|
222
|
+
**Storage API:**
|
|
223
|
+
|
|
224
|
+
- `/api/v1/storage/usage-month/filesystem_name/data_type`
|
|
225
|
+
- `/api/v1/storage/usage-day/filesystem_name/data_type`
|
|
226
|
+
|
|
227
|
+
## Troubleshooting
|
|
228
|
+
|
|
229
|
+
### Authentication Issues
|
|
230
|
+
|
|
231
|
+
- Verify OIDC client credentials are correct
|
|
232
|
+
- Check that the token endpoint URL is accessible
|
|
233
|
+
- Ensure the client has appropriate scopes
|
|
234
|
+
|
|
235
|
+
### Storage Backend Issues
|
|
236
|
+
|
|
237
|
+
- Verify `storage_filesystem` and `storage_data_type` match available values in DWDI
|
|
238
|
+
- Check `storage_path_mapping` if using custom resource IDs
|
|
239
|
+
- Ensure storage paths exist in the DWDI system
|
|
240
|
+
|
|
241
|
+
### Connection Issues
|
|
242
|
+
|
|
243
|
+
- Use the `ping()` method to test API connectivity
|
|
244
|
+
- Check network connectivity to the DWDI API endpoint
|
|
245
|
+
- Verify SSL/TLS configuration
|
|
246
|
+
- If behind a firewall, configure SOCKS proxy (`socks_proxy` setting)
|
|
247
|
+
|
|
248
|
+
### Proxy Issues
|
|
249
|
+
|
|
250
|
+
- Verify proxy server is running and accessible
|
|
251
|
+
- Check proxy authentication if required
|
|
252
|
+
- Test proxy connectivity manually: `curl --proxy socks5://localhost:12345 https://dwdi.cscs.ch`
|
|
253
|
+
- Ensure proxy supports the required protocol (SOCKS4/5, HTTP)
|
|
254
|
+
|
|
255
|
+
## Development
|
|
256
|
+
|
|
257
|
+
### Project Structure
|
|
258
|
+
|
|
259
|
+
```text
|
|
260
|
+
plugins/cscs-dwdi/
|
|
261
|
+
├── pyproject.toml # Plugin configuration
|
|
262
|
+
├── README.md # This documentation
|
|
263
|
+
├── examples/ # Configuration examples
|
|
264
|
+
├── waldur_site_agent_cscs_dwdi/
|
|
265
|
+
│ ├── __init__.py # Package init
|
|
266
|
+
│ ├── backend.py # Backend implementations
|
|
267
|
+
│ └── client.py # CSCS-DWDI API client
|
|
268
|
+
└── tests/
|
|
269
|
+
└── test_cscs_dwdi.py # Plugin tests
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Key Classes
|
|
273
|
+
|
|
274
|
+
- **`CSCSDWDIComputeBackend`**: Compute usage reporting backend
|
|
275
|
+
- **`CSCSDWDIStorageBackend`**: Storage usage reporting backend
|
|
276
|
+
- **`CSCSDWDIClient`**: HTTP client for CSCS-DWDI API communication
|
|
277
|
+
|
|
278
|
+
### Extension Points
|
|
279
|
+
|
|
280
|
+
To extend the plugin:
|
|
281
|
+
|
|
282
|
+
1. **Additional Endpoints**: Modify `CSCSDWDIClient` to support more API endpoints
|
|
283
|
+
2. **Authentication Methods**: Update authentication logic in `client.py`
|
|
284
|
+
3. **Data Processing**: Enhance response processing methods for additional data formats
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# CSCS-DWDI Plugin for Waldur Site Agent
|
|
2
|
+
|
|
3
|
+
This plugin provides integration with the CSCS Data Warehouse Data Intelligence (DWDI) system to report both
|
|
4
|
+
computational and storage usage data to Waldur.
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
The plugin implements two separate backends to handle different types of accounting data:
|
|
9
|
+
|
|
10
|
+
- **Compute Backend** (`cscs-dwdi-compute`): Reports CPU and node hour usage from HPC clusters
|
|
11
|
+
- **Storage Backend** (`cscs-dwdi-storage`): Reports storage space and inode usage from filesystems
|
|
12
|
+
|
|
13
|
+
## Backend Types
|
|
14
|
+
|
|
15
|
+
### Compute Backend
|
|
16
|
+
|
|
17
|
+
The compute backend queries the DWDI API for computational resource usage and reports:
|
|
18
|
+
|
|
19
|
+
- Node hours consumed by accounts and users
|
|
20
|
+
- CPU hours consumed by accounts and users
|
|
21
|
+
- Account-level and user-level usage aggregation
|
|
22
|
+
|
|
23
|
+
**API Endpoints Used:**
|
|
24
|
+
|
|
25
|
+
- `/api/v1/compute/usage-month/account` - Monthly usage data
|
|
26
|
+
- `/api/v1/compute/usage-day/account` - Daily usage data
|
|
27
|
+
|
|
28
|
+
### Storage Backend
|
|
29
|
+
|
|
30
|
+
The storage backend queries the DWDI API for storage resource usage and reports:
|
|
31
|
+
|
|
32
|
+
- Storage space used (converted from bytes to configured units)
|
|
33
|
+
- Inode (file count) usage
|
|
34
|
+
- Path-based resource identification
|
|
35
|
+
|
|
36
|
+
**API Endpoints Used:**
|
|
37
|
+
|
|
38
|
+
- `/api/v1/storage/usage-month/filesystem_name/data_type` - Monthly storage usage
|
|
39
|
+
- `/api/v1/storage/usage-day/filesystem_name/data_type` - Daily storage usage
|
|
40
|
+
|
|
41
|
+
## Configuration
|
|
42
|
+
|
|
43
|
+
### Compute Backend Configuration
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
backend_type: "cscs-dwdi-compute"
|
|
47
|
+
|
|
48
|
+
backend_settings:
|
|
49
|
+
cscs_dwdi_api_url: "https://dwdi.cscs.ch"
|
|
50
|
+
cscs_dwdi_client_id: "your_oidc_client_id"
|
|
51
|
+
cscs_dwdi_client_secret: "your_oidc_client_secret"
|
|
52
|
+
cscs_dwdi_oidc_token_url: "https://auth.cscs.ch/realms/cscs/protocol/openid-connect/token"
|
|
53
|
+
cscs_dwdi_oidc_scope: "openid" # Optional
|
|
54
|
+
|
|
55
|
+
backend_components:
|
|
56
|
+
nodeHours:
|
|
57
|
+
measured_unit: "node-hours"
|
|
58
|
+
unit_factor: 1
|
|
59
|
+
accounting_type: "usage"
|
|
60
|
+
label: "Node Hours"
|
|
61
|
+
|
|
62
|
+
cpuHours:
|
|
63
|
+
measured_unit: "cpu-hours"
|
|
64
|
+
unit_factor: 1
|
|
65
|
+
accounting_type: "usage"
|
|
66
|
+
label: "CPU Hours"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Storage Backend Configuration
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
backend_type: "cscs-dwdi-storage"
|
|
73
|
+
|
|
74
|
+
backend_settings:
|
|
75
|
+
cscs_dwdi_api_url: "https://dwdi.cscs.ch"
|
|
76
|
+
cscs_dwdi_client_id: "your_oidc_client_id"
|
|
77
|
+
cscs_dwdi_client_secret: "your_oidc_client_secret"
|
|
78
|
+
cscs_dwdi_oidc_token_url: "https://auth.cscs.ch/realms/cscs/protocol/openid-connect/token"
|
|
79
|
+
|
|
80
|
+
# Storage-specific settings
|
|
81
|
+
storage_filesystem: "lustre"
|
|
82
|
+
storage_data_type: "projects"
|
|
83
|
+
storage_tenant: "cscs" # Optional
|
|
84
|
+
|
|
85
|
+
# Map Waldur resource IDs to storage paths
|
|
86
|
+
storage_path_mapping:
|
|
87
|
+
"project_123": "/store/projects/proj123"
|
|
88
|
+
"project_456": "/store/projects/proj456"
|
|
89
|
+
|
|
90
|
+
backend_components:
|
|
91
|
+
storage_space:
|
|
92
|
+
measured_unit: "GB"
|
|
93
|
+
unit_factor: 0.000000001 # Convert bytes to GB
|
|
94
|
+
accounting_type: "usage"
|
|
95
|
+
label: "Storage Space (GB)"
|
|
96
|
+
|
|
97
|
+
storage_inodes:
|
|
98
|
+
measured_unit: "count"
|
|
99
|
+
unit_factor: 1
|
|
100
|
+
accounting_type: "usage"
|
|
101
|
+
label: "File Count"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Authentication
|
|
105
|
+
|
|
106
|
+
Both backends use OIDC client credentials flow for authentication with the DWDI API. You need:
|
|
107
|
+
|
|
108
|
+
- `cscs_dwdi_client_id`: OIDC client identifier
|
|
109
|
+
- `cscs_dwdi_client_secret`: OIDC client secret
|
|
110
|
+
- `cscs_dwdi_oidc_token_url`: OIDC token endpoint URL
|
|
111
|
+
- `cscs_dwdi_oidc_scope`: OIDC scope (optional, defaults to "openid")
|
|
112
|
+
|
|
113
|
+
## SOCKS Proxy Support
|
|
114
|
+
|
|
115
|
+
Both backends support SOCKS proxy for network connectivity. This is useful when the DWDI API is only accessible
|
|
116
|
+
through a proxy or jump host.
|
|
117
|
+
|
|
118
|
+
### SOCKS Proxy Configuration
|
|
119
|
+
|
|
120
|
+
Add the SOCKS proxy setting to your backend configuration:
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
backend_settings:
|
|
124
|
+
# ... other settings ...
|
|
125
|
+
socks_proxy: "socks5://localhost:12345" # SOCKS5 proxy URL
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Supported Proxy Types
|
|
129
|
+
|
|
130
|
+
- **SOCKS5**: `socks5://hostname:port`
|
|
131
|
+
- **SOCKS4**: `socks4://hostname:port`
|
|
132
|
+
- **HTTP**: `http://hostname:port`
|
|
133
|
+
|
|
134
|
+
### Usage Examples
|
|
135
|
+
|
|
136
|
+
**SSH Tunnel with SOCKS5:**
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Create SSH tunnel to jump host
|
|
140
|
+
ssh -D 12345 -N user@jumphost.cscs.ch
|
|
141
|
+
|
|
142
|
+
# Configure backend to use tunnel
|
|
143
|
+
backend_settings:
|
|
144
|
+
socks_proxy: "socks5://localhost:12345"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**HTTP Proxy:**
|
|
148
|
+
|
|
149
|
+
```yaml
|
|
150
|
+
backend_settings:
|
|
151
|
+
socks_proxy: "http://proxy.cscs.ch:8080"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Resource Identification
|
|
155
|
+
|
|
156
|
+
### Compute Resources
|
|
157
|
+
|
|
158
|
+
For compute resources, the system uses account names as returned by the DWDI API. The Waldur resource
|
|
159
|
+
`backend_id` should match the account name in the cluster accounting system.
|
|
160
|
+
|
|
161
|
+
### Storage Resources
|
|
162
|
+
|
|
163
|
+
For storage resources, there are two options:
|
|
164
|
+
|
|
165
|
+
1. **Direct Path Usage**: Set the Waldur resource `backend_id` to the actual filesystem path
|
|
166
|
+
2. **Path Mapping**: Use the `storage_path_mapping` setting to map resource IDs to paths
|
|
167
|
+
|
|
168
|
+
## Usage Reporting
|
|
169
|
+
|
|
170
|
+
Both backends are read-only and designed for usage reporting. They implement the `_get_usage_report()` method
|
|
171
|
+
but do not support:
|
|
172
|
+
|
|
173
|
+
- Account creation/deletion
|
|
174
|
+
- Resource management
|
|
175
|
+
- User management
|
|
176
|
+
- Limit setting
|
|
177
|
+
|
|
178
|
+
## Example Configurations
|
|
179
|
+
|
|
180
|
+
See the `examples/` directory for complete configuration examples:
|
|
181
|
+
|
|
182
|
+
- `cscs-dwdi-compute-config.yaml` - Compute backend only
|
|
183
|
+
- `cscs-dwdi-storage-config.yaml` - Storage backend only
|
|
184
|
+
- `cscs-dwdi-combined-config.yaml` - Both backends in one configuration
|
|
185
|
+
|
|
186
|
+
## Installation
|
|
187
|
+
|
|
188
|
+
The plugin is automatically discovered when the waldur-site-agent-cscs-dwdi package is installed alongside waldur-site-agent.
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Install all workspace packages including cscs-dwdi plugin
|
|
192
|
+
uv sync --all-packages
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Testing
|
|
196
|
+
|
|
197
|
+
Run the test suite:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
uv run pytest plugins/cscs-dwdi/tests/
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## API Compatibility
|
|
204
|
+
|
|
205
|
+
This plugin is compatible with DWDI API version 1 (`/api/v1/`). It requires the following API endpoints to be available:
|
|
206
|
+
|
|
207
|
+
**Compute API:**
|
|
208
|
+
|
|
209
|
+
- `/api/v1/compute/usage-month/account`
|
|
210
|
+
- `/api/v1/compute/usage-day/account`
|
|
211
|
+
|
|
212
|
+
**Storage API:**
|
|
213
|
+
|
|
214
|
+
- `/api/v1/storage/usage-month/filesystem_name/data_type`
|
|
215
|
+
- `/api/v1/storage/usage-day/filesystem_name/data_type`
|
|
216
|
+
|
|
217
|
+
## Troubleshooting
|
|
218
|
+
|
|
219
|
+
### Authentication Issues
|
|
220
|
+
|
|
221
|
+
- Verify OIDC client credentials are correct
|
|
222
|
+
- Check that the token endpoint URL is accessible
|
|
223
|
+
- Ensure the client has appropriate scopes
|
|
224
|
+
|
|
225
|
+
### Storage Backend Issues
|
|
226
|
+
|
|
227
|
+
- Verify `storage_filesystem` and `storage_data_type` match available values in DWDI
|
|
228
|
+
- Check `storage_path_mapping` if using custom resource IDs
|
|
229
|
+
- Ensure storage paths exist in the DWDI system
|
|
230
|
+
|
|
231
|
+
### Connection Issues
|
|
232
|
+
|
|
233
|
+
- Use the `ping()` method to test API connectivity
|
|
234
|
+
- Check network connectivity to the DWDI API endpoint
|
|
235
|
+
- Verify SSL/TLS configuration
|
|
236
|
+
- If behind a firewall, configure SOCKS proxy (`socks_proxy` setting)
|
|
237
|
+
|
|
238
|
+
### Proxy Issues
|
|
239
|
+
|
|
240
|
+
- Verify proxy server is running and accessible
|
|
241
|
+
- Check proxy authentication if required
|
|
242
|
+
- Test proxy connectivity manually: `curl --proxy socks5://localhost:12345 https://dwdi.cscs.ch`
|
|
243
|
+
- Ensure proxy supports the required protocol (SOCKS4/5, HTTP)
|
|
244
|
+
|
|
245
|
+
## Development
|
|
246
|
+
|
|
247
|
+
### Project Structure
|
|
248
|
+
|
|
249
|
+
```text
|
|
250
|
+
plugins/cscs-dwdi/
|
|
251
|
+
├── pyproject.toml # Plugin configuration
|
|
252
|
+
├── README.md # This documentation
|
|
253
|
+
├── examples/ # Configuration examples
|
|
254
|
+
├── waldur_site_agent_cscs_dwdi/
|
|
255
|
+
│ ├── __init__.py # Package init
|
|
256
|
+
│ ├── backend.py # Backend implementations
|
|
257
|
+
│ └── client.py # CSCS-DWDI API client
|
|
258
|
+
└── tests/
|
|
259
|
+
└── test_cscs_dwdi.py # Plugin tests
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Key Classes
|
|
263
|
+
|
|
264
|
+
- **`CSCSDWDIComputeBackend`**: Compute usage reporting backend
|
|
265
|
+
- **`CSCSDWDIStorageBackend`**: Storage usage reporting backend
|
|
266
|
+
- **`CSCSDWDIClient`**: HTTP client for CSCS-DWDI API communication
|
|
267
|
+
|
|
268
|
+
### Extension Points
|
|
269
|
+
|
|
270
|
+
To extend the plugin:
|
|
271
|
+
|
|
272
|
+
1. **Additional Endpoints**: Modify `CSCSDWDIClient` to support more API endpoints
|
|
273
|
+
2. **Authentication Methods**: Update authentication logic in `client.py`
|
|
274
|
+
3. **Data Processing**: Enhance response processing methods for additional data formats
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "waldur-site-agent-cscs-dwdi"
|
|
3
|
-
version = "0.7.
|
|
3
|
+
version = "0.7.3"
|
|
4
4
|
description = "CSCS-DWDI reporting plugin for Waldur Site Agent"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [{ name = "OpenNode Team", email = "info@opennodecloud.com" }]
|
|
@@ -19,4 +19,5 @@ waldur-site-agent = { workspace = true }
|
|
|
19
19
|
|
|
20
20
|
# Entry points for exporting backends
|
|
21
21
|
[project.entry-points."waldur_site_agent.backends"]
|
|
22
|
-
cscs-dwdi = "waldur_site_agent_cscs_dwdi.backend:
|
|
22
|
+
cscs-dwdi-compute = "waldur_site_agent_cscs_dwdi.backend:CSCSDWDIComputeBackend"
|
|
23
|
+
cscs-dwdi-storage = "waldur_site_agent_cscs_dwdi.backend:CSCSDWDIStorageBackend"
|
{waldur_site_agent_cscs_dwdi-0.7.0 → waldur_site_agent_cscs_dwdi-0.7.3}/tests/test_cscs_dwdi.py
RENAMED
|
@@ -5,7 +5,7 @@ from typing import Any
|
|
|
5
5
|
from unittest.mock import MagicMock, patch
|
|
6
6
|
|
|
7
7
|
import pytest
|
|
8
|
-
from waldur_site_agent_cscs_dwdi.backend import
|
|
8
|
+
from waldur_site_agent_cscs_dwdi.backend import CSCSDWDIComputeBackend, CSCSDWDIStorageBackend
|
|
9
9
|
from waldur_site_agent_cscs_dwdi.client import CSCSDWDIClient
|
|
10
10
|
|
|
11
11
|
|
|
@@ -25,6 +25,18 @@ class TestCSCSDWDIClient:
|
|
|
25
25
|
assert client.client_secret == "test_secret"
|
|
26
26
|
assert client.oidc_token_url is None
|
|
27
27
|
assert client.oidc_scope == "openid"
|
|
28
|
+
assert client.socks_proxy is None
|
|
29
|
+
|
|
30
|
+
def test_client_initialization_with_proxy(self) -> None:
|
|
31
|
+
"""Test client initializes with SOCKS proxy."""
|
|
32
|
+
client = CSCSDWDIClient(
|
|
33
|
+
api_url="https://api.example.com",
|
|
34
|
+
client_id="test_client",
|
|
35
|
+
client_secret="test_secret",
|
|
36
|
+
socks_proxy="socks5://localhost:12345",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
assert client.socks_proxy == "socks5://localhost:12345"
|
|
28
40
|
|
|
29
41
|
def test_client_strips_trailing_slash(self) -> None:
|
|
30
42
|
"""Test client strips trailing slash from API URL."""
|
|
@@ -230,8 +242,8 @@ class TestCSCSDWDIClient:
|
|
|
230
242
|
assert token1 == token2
|
|
231
243
|
|
|
232
244
|
|
|
233
|
-
class
|
|
234
|
-
"""Tests for CSCS-DWDI backend."""
|
|
245
|
+
class TestCSCSDWDIComputeBackend:
|
|
246
|
+
"""Tests for CSCS-DWDI compute backend."""
|
|
235
247
|
|
|
236
248
|
def test_backend_initialization(self) -> None:
|
|
237
249
|
"""Test backend initializes with correct configuration."""
|
|
@@ -250,12 +262,36 @@ class TestCSCSDWDIBackend:
|
|
|
250
262
|
}
|
|
251
263
|
}
|
|
252
264
|
|
|
253
|
-
backend =
|
|
265
|
+
backend = CSCSDWDIComputeBackend(backend_settings, backend_components)
|
|
254
266
|
|
|
255
267
|
assert backend.api_url == "https://api.example.com"
|
|
256
268
|
assert backend.client_id == "test_client"
|
|
257
269
|
assert backend.client_secret == "test_secret"
|
|
258
270
|
assert isinstance(backend.cscs_client, CSCSDWDIClient)
|
|
271
|
+
assert backend.socks_proxy is None
|
|
272
|
+
|
|
273
|
+
def test_backend_initialization_with_proxy(self) -> None:
|
|
274
|
+
"""Test backend initializes with SOCKS proxy configuration."""
|
|
275
|
+
backend_settings = {
|
|
276
|
+
"cscs_dwdi_api_url": "https://api.example.com",
|
|
277
|
+
"cscs_dwdi_client_id": "test_client",
|
|
278
|
+
"cscs_dwdi_client_secret": "test_secret",
|
|
279
|
+
"cscs_dwdi_oidc_token_url": "https://oidc.example.com/token",
|
|
280
|
+
"socks_proxy": "socks5://localhost:12345",
|
|
281
|
+
}
|
|
282
|
+
backend_components = {
|
|
283
|
+
"nodeHours": {
|
|
284
|
+
"measured_unit": "node-hours",
|
|
285
|
+
"unit_factor": 1,
|
|
286
|
+
"accounting_type": "usage",
|
|
287
|
+
"label": "Node Hours",
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
backend = CSCSDWDIComputeBackend(backend_settings, backend_components)
|
|
292
|
+
|
|
293
|
+
assert backend.socks_proxy == "socks5://localhost:12345"
|
|
294
|
+
assert backend.cscs_client.socks_proxy == "socks5://localhost:12345"
|
|
259
295
|
|
|
260
296
|
def test_backend_initialization_missing_config(self) -> None:
|
|
261
297
|
"""Test backend raises error when configuration is missing."""
|
|
@@ -266,7 +302,7 @@ class TestCSCSDWDIBackend:
|
|
|
266
302
|
backend_components: dict[str, dict] = {}
|
|
267
303
|
|
|
268
304
|
with pytest.raises(ValueError) as exc_info:
|
|
269
|
-
|
|
305
|
+
CSCSDWDIComputeBackend(backend_settings, backend_components)
|
|
270
306
|
|
|
271
307
|
assert "cscs_dwdi_oidc_token_url" in str(exc_info.value)
|
|
272
308
|
|
|
@@ -286,7 +322,7 @@ class TestCSCSDWDIBackend:
|
|
|
286
322
|
"label": "Node Hours",
|
|
287
323
|
}
|
|
288
324
|
}
|
|
289
|
-
backend =
|
|
325
|
+
backend = CSCSDWDIComputeBackend(backend_settings, backend_components)
|
|
290
326
|
|
|
291
327
|
# Sample API response
|
|
292
328
|
api_response = {
|
|
@@ -347,7 +383,7 @@ class TestCSCSDWDIBackend:
|
|
|
347
383
|
"label": "Node Hours",
|
|
348
384
|
}
|
|
349
385
|
}
|
|
350
|
-
backend =
|
|
386
|
+
backend = CSCSDWDIComputeBackend(backend_settings, backend_components)
|
|
351
387
|
|
|
352
388
|
# API response with same user appearing multiple times
|
|
353
389
|
api_response = {
|
|
@@ -416,7 +452,7 @@ class TestCSCSDWDIBackend:
|
|
|
416
452
|
"label": "Node Hours",
|
|
417
453
|
}
|
|
418
454
|
}
|
|
419
|
-
backend =
|
|
455
|
+
backend = CSCSDWDIComputeBackend(backend_settings, backend_components)
|
|
420
456
|
|
|
421
457
|
# Test the method
|
|
422
458
|
result = backend._get_usage_report(["account1", "account2"])
|
|
@@ -448,7 +484,7 @@ class TestCSCSDWDIBackend:
|
|
|
448
484
|
"label": "Node Hours",
|
|
449
485
|
}
|
|
450
486
|
}
|
|
451
|
-
backend =
|
|
487
|
+
backend = CSCSDWDIComputeBackend(backend_settings, backend_components)
|
|
452
488
|
|
|
453
489
|
# Mock the client method
|
|
454
490
|
with patch.object(backend.cscs_client, "get_usage_for_month") as mock_get:
|
|
@@ -496,7 +532,7 @@ class TestCSCSDWDIBackend:
|
|
|
496
532
|
"label": "Node Hours",
|
|
497
533
|
}
|
|
498
534
|
}
|
|
499
|
-
backend =
|
|
535
|
+
backend = CSCSDWDIComputeBackend(backend_settings, backend_components)
|
|
500
536
|
|
|
501
537
|
with pytest.raises(NotImplementedError):
|
|
502
538
|
backend.create_account({})
|