ctao-bdms-clients 0.2.0rc1__tar.gz → 0.2.1__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.
Files changed (75) hide show
  1. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/.gitignore +3 -0
  2. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/.gitlab-ci.yml +2 -2
  3. ctao_bdms_clients-0.2.1/CHANGES.rst +80 -0
  4. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/Dockerfile +1 -1
  5. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/PKG-INFO +4 -2
  6. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/aiv-config.yml +2 -0
  7. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/Chart.yaml +2 -2
  8. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/README.md +5 -2
  9. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/scripts/certificates/install_ca.sh +0 -1
  10. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/templates/bootstrap_jobs.yaml +7 -1
  11. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/templates/test_storages.yaml +4 -2
  12. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/templates/tests/test_jobs.yaml +2 -1
  13. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/values.yaml +6 -0
  14. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/changelog.rst +1 -0
  15. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/pyproject.toml +3 -1
  16. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/sonar-project.properties +2 -2
  17. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/_version.py +2 -2
  18. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/acada_ingestion.py +48 -4
  19. ctao_bdms_clients-0.2.1/src/bdms/extract_fits_metadata.py +134 -0
  20. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/tests/conftest.py +25 -2
  21. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/tests/test_acada_ingestion.py +81 -56
  22. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/tests/test_basic_rucio_functionality.py +0 -1
  23. ctao_bdms_clients-0.2.1/src/bdms/tests/test_extract_fits_metadata.py +97 -0
  24. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/tests/test_onsite_storage.py +16 -35
  25. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/tests/utils.py +18 -0
  26. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/ctao_bdms_clients.egg-info/PKG-INFO +4 -2
  27. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/ctao_bdms_clients.egg-info/SOURCES.txt +2 -0
  28. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/ctao_bdms_clients.egg-info/requires.txt +2 -0
  29. ctao_bdms_clients-0.2.0rc1/CHANGES.rst +0 -8
  30. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/.codespell-ignores +0 -0
  31. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/.dockerignore +0 -0
  32. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/.flake8 +0 -0
  33. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/.gitmodules +0 -0
  34. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/.pre-commit-config.yaml +0 -0
  35. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/LICENSE +0 -0
  36. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/MANIFEST.in +0 -0
  37. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/Makefile +0 -0
  38. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/README.md +0 -0
  39. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/aiv-config-dependencies.yml +0 -0
  40. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/Makefile +0 -0
  41. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/scripts/bootstrap_rucio/setup_rucio.sh +0 -0
  42. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/scripts/bootstrap_rucio/wait_for_rucio.sh +0 -0
  43. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/templates/_helpers.tpl +0 -0
  44. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/templates/_helpers_cert.tpl +0 -0
  45. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/templates/configmap.yaml +0 -0
  46. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/chart/templates/prepuller.yaml +0 -0
  47. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/Makefile +0 -0
  48. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/changes/template.rst +0 -0
  49. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/chart.rst +0 -0
  50. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/conf.py +0 -0
  51. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/data_ingestion_acada.rst +0 -0
  52. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/data_transfers.rst +0 -0
  53. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/getting_started.rst +0 -0
  54. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/index.rst +0 -0
  55. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/reference/acada_ingestion.rst +0 -0
  56. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/reference/index.rst +0 -0
  57. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/server_setup/bdms_repos_interaction.rst +0 -0
  58. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/server_setup/certificates.rst +0 -0
  59. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/server_setup/fts.rst +0 -0
  60. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/server_setup/index.rst +0 -0
  61. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/server_setup/rucio_configuration.rst +0 -0
  62. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/docs/server_setup/storage_elements.rst +0 -0
  63. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/env_template +0 -0
  64. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/report/inspection.tex +0 -0
  65. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/report/performance_verification.tex +0 -0
  66. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/report/preamble.tex +0 -0
  67. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/setup.cfg +0 -0
  68. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/__init__.py +0 -0
  69. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/tests/__init__.py +0 -0
  70. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/tests/test_dpps_rel_0_0.py +0 -0
  71. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/tests/test_file_replicas.py +0 -0
  72. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/tests/test_metadata.py +0 -0
  73. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/bdms/version.py +0 -0
  74. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/ctao_bdms_clients.egg-info/dependency_links.txt +0 -0
  75. {ctao_bdms_clients-0.2.0rc1 → ctao_bdms_clients-0.2.1}/src/ctao_bdms_clients.egg-info/top_level.txt +0 -0
@@ -145,3 +145,6 @@ dmypy.json
145
145
 
146
146
  # Pyre type checker
147
147
  .pyre/
148
+
149
+ # Test folder for Fits files
150
+ test_data/
@@ -1,6 +1,6 @@
1
1
  include:
2
2
  - project: 'cta-computing/dpps/aiv/dpps-aiv-toolkit'
3
- ref: 23eafda64340b8036cbed5ce196784a03666cad8
3
+ ref: 7ebf44c2b02bfd72f596e7ea27ea0e9a1f925903
4
4
  file: 'ci-functions.yml'
5
5
  - "aiv-config.yml"
6
6
 
@@ -9,7 +9,6 @@ variables:
9
9
  CHART_LOCATION: chart
10
10
  CHART_NAME: bdms
11
11
  CHART_EXTRA_VALUES: "--set dev.client_image_tag=${DOCKER_TAG}"
12
- DPPS_AIV_TOOLKIT_DIR: dpps-aiv-toolkit
13
12
  DOCKER_IMAGE_CONTEXT: '${CI_PROJECT_DIR}'
14
13
  RUCIO_VERSION: "35.4.1"
15
14
  RUCIO_TAG: "release-${RUCIO_VERSION}"
@@ -23,6 +22,7 @@ stages:
23
22
  - sonarqube
24
23
  - publish
25
24
  - report
25
+ - changelog
26
26
 
27
27
  k8s-integration-tests:
28
28
  # override from toolkit
@@ -0,0 +1,80 @@
1
+ BDMS v0.2.1 (2025-06-03)
2
+ ------------------------
3
+
4
+ Bugfix release to allow (pre-)production deployment without test storages.
5
+
6
+ Bug Fixes
7
+ ~~~~~~~~~
8
+
9
+ - Allow to further configure first test RSE: set storageclass and make optional. [`!112 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/112>`__]
10
+
11
+
12
+ BDMS 0.2.0 (2025-05-07)
13
+ -----------------------
14
+
15
+
16
+ API Changes
17
+ ~~~~~~~~~~~
18
+
19
+ - Add basic ingestion of ACADA files (UC-110-1.1.1) [`!76 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/76>`__]
20
+
21
+ - Replicate Data Products (UC-110-1.6) with test case for copies=2 [`!83 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/83>`__]
22
+
23
+ - Extraction of metadata from ACADA-LST DL0 FITS files and adding metadata to ingested file (UC-110-1.1.1) [`!85 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/85>`__]
24
+
25
+ - Add test case for copies=1 for the replication (UC-110-1.6) [`!87 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/87>`__]
26
+
27
+
28
+ Bug Fixes
29
+ ~~~~~~~~~
30
+
31
+ - Add missing permissions to fix onsite storage permissions [`!103 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/103>`__]
32
+
33
+
34
+ New Features
35
+ ~~~~~~~~~~~~
36
+
37
+ - Adapt one RSE as onsite and exposing its diskspace to client test pod [`!69 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/69>`__]
38
+
39
+ - Add dcache and its dependencies in the BDMS helm chart (UC-170-1.6) [`!80 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/80>`__]
40
+
41
+ - Add FITS checksum verification [`!94 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/94>`__]
42
+
43
+ - Make storage configurable by providing additional config for RSE and also make xrootd image configurable [`!96 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/96>`__]
44
+
45
+
46
+ Maintenance
47
+ ~~~~~~~~~~~
48
+
49
+ - Fix rucio server not using correct lfn2pfn algorithm [`!72 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/72>`__]
50
+
51
+ - Use test_vo fixture for ingestion tests [`!81 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/81>`__]
52
+
53
+ - Update dpps release for test report and signature matrix [`!82 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/82>`__]
54
+
55
+ - Update BDMS docs for Rel 0.1 [`!89 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/89>`__]
56
+
57
+ - Update fts image and toolkit [`!90 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/90>`__]
58
+
59
+ - Added download_test_file in utils.py to download a FITS file from MinIO server [`!93 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/93>`__]
60
+
61
+ - Update rucio to 35.7.0 [`!97 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/97>`__]
62
+
63
+ - Update FTS subchart version [`!99 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/99>`__]
64
+
65
+ - Resolve Test container build fails due to missing -y in autoremove [`!101 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/101>`__]
66
+
67
+
68
+ Refactoring and Optimization
69
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
70
+
71
+ - Update FTS chart to 0.3 to reduce integration test time [`!100 <https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/merge_requests/100>`__]
72
+
73
+ BDMS v0.1.0 (2025-02-21)
74
+ ---------------------------
75
+
76
+ First release of the Bulk Data Management System (BDMS).
77
+
78
+ * Deployment of Rucio 35.4 using helm.
79
+ * Client package pinning the correct rucio and rucio policy package versions.
80
+ * Integration tests for DPPS release 0.0 use cases.
@@ -22,7 +22,7 @@ USER root
22
22
  COPY --from=builder /tmp/dist/ /tmp/dist/
23
23
  RUN dnf install -y --setopt=install_weak_deps=False git \
24
24
  && python3 -m pip install --no-cache-dir /tmp/dist/ctao_bdms* \
25
- && dnf autoremove \
25
+ && dnf autoremove -y \
26
26
  && dnf clean all
27
27
 
28
28
  USER user
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ctao-bdms-clients
3
- Version: 0.2.0rc1
3
+ Version: 0.2.1
4
4
  Summary: Client module for the CTAO DPPS Bulk Data Management System
5
5
  Author-email: Georgios Zacharis <georgios.zacharis@inaf.it>, Stefano Gallozzi <Stefano.gallozzi@inaf.it>, Michele Mastropietro <michele.mastropietro@inaf.it>, Syed Anwar Ul Hasan <syedanwarul.hasan@cta-consortium.org>, Maximilian Linhoff <maximilian.linhoff@cta-observatory.org>, Volodymyr Savchenko <Volodymyr.Savchenko@epfl.ch>
6
- License: BSD-3-Clause
6
+ License-Expression: BSD-3-Clause
7
7
  Project-URL: repository, https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms
8
8
  Project-URL: documentation, http://cta-computing.gitlab-pages.cta-observatory.org/dpps/bdms/bdms
9
9
  Requires-Python: >=3.9
@@ -12,12 +12,14 @@ License-File: LICENSE
12
12
  Requires-Dist: astropy<8.0.0a0,>=6.0.1
13
13
  Requires-Dist: ctao-bdms-rucio-policy~=0.1.0
14
14
  Requires-Dist: rucio-clients~=35.7.0
15
+ Requires-Dist: protozfits>=2.7.2
15
16
  Provides-Extra: test
16
17
  Requires-Dist: pytest; extra == "test"
17
18
  Requires-Dist: pytest-cov; extra == "test"
18
19
  Requires-Dist: pytest-requirements; extra == "test"
19
20
  Requires-Dist: python-dotenv; extra == "test"
20
21
  Requires-Dist: minio; extra == "test"
22
+ Requires-Dist: pytest-xdist; extra == "test"
21
23
  Provides-Extra: doc
22
24
  Requires-Dist: sphinx; extra == "doc"
23
25
  Requires-Dist: numpydoc; extra == "doc"
@@ -15,3 +15,5 @@ variables:
15
15
  APPLICATION_AUTHOR_ORGANIZATION: CTAO
16
16
 
17
17
  EXTRA_CONFIG_FILES: aiv-config-dependencies.yml
18
+
19
+ DEFAULT_HELM_TEST: name=bdms-pytest
@@ -12,7 +12,7 @@ keywords:
12
12
 
13
13
  maintainers:
14
14
  - name: The BDMS Authors
15
- email: ""
15
+ email: ''
16
16
 
17
17
  dependencies:
18
18
  - name: postgresql
@@ -30,7 +30,7 @@ dependencies:
30
30
 
31
31
  - name: cert-generator-grid
32
32
  condition: cert-generator-grid.enabled
33
- version: v0.2.2
33
+ version: v2.0.0
34
34
  repository: oci://harbor.cta-observatory.org/dpps
35
35
 
36
36
  - name: fts
@@ -14,7 +14,7 @@ A Helm chart for the bdms project
14
14
 
15
15
  | Repository | Name | Version |
16
16
  |------------|------|---------|
17
- | oci://harbor.cta-observatory.org/dpps | cert-generator-grid | v0.2.2 |
17
+ | oci://harbor.cta-observatory.org/dpps | cert-generator-grid | v2.0.0 |
18
18
  | oci://harbor.cta-observatory.org/dpps | fts | v0.3.0 |
19
19
  | oci://harbor.cta-observatory.org/dpps | rucio-daemons | 35.0.0 |
20
20
  | oci://harbor.cta-observatory.org/dpps | rucio-server | 35.0.0 |
@@ -43,6 +43,7 @@ A Helm chart for the bdms project
43
43
  | database.default | string | `"postgresql://rucio:XcL0xT9FgFgJEc4i3OcQf2DMVKpjIWDGezqcIPmXlM@bdms-postgresql:5432/rucio"` | The Rucio database connection URI |
44
44
  | dev.client_image_tag | string | `nil` | |
45
45
  | dev.mount_repo | bool | `true` | |
46
+ | dev.n_test_jobs | int | `4` | number of jobs to use for pytest |
46
47
  | dev.run_tests | bool | `true` | |
47
48
  | dev.sleep | bool | `false` | sleep after test to allow interactive development |
48
49
  | fts.enabled | bool | `true` | Specifies the configuration for FTS test step (FTS server, FTS database, and ActiveMQ broker containers). Enables or disables the deployment of a FTS instance for testing. This is set to 'False' if an external FTS is used |
@@ -145,7 +146,9 @@ A Helm chart for the bdms project
145
146
  | server.certificate.letsencrypt.enabled | bool | `false` | Enables SSL/TLS certificate provisioning using Let's encrypt |
146
147
  | server.rucioHost | string | `"rucio-server-manual-tc.local"` | The hostname of the Rucio server. It is used by clients and services to communicate with Rucio |
147
148
  | suffix_namespace | string | `"default"` | Specifies the Namespace suffix used for managing deployments in kubernetes |
148
- | test_storages | object | `{"xrootd":{"image":{"repository":"harbor.cta-observatory.org/proxy_cache/rucio/test-xrootd","tag":"37.1.0"},"instances":["rucio-storage-1","rucio-storage-2","rucio-storage-3"]}}` | - A list of test storages, deployed in the test setup |
149
+ | test_storages | object | `{"enabled":true,"xrootd":{"image":{"repository":"harbor.cta-observatory.org/proxy_cache/rucio/test-xrootd","tag":"37.1.0"},"instances":["rucio-storage-1","rucio-storage-2","rucio-storage-3"],"rucio_storage_1_storage_class":"standard"}}` | - A list of test storages, deployed in the test setup |
150
+ | test_storages.enabled | bool | `true` | If true, deploys test storages for testing purposes. This is set to 'False' if an external storage is used as in the production setup |
149
151
  | test_storages.xrootd.image.repository | string | `"harbor.cta-observatory.org/proxy_cache/rucio/test-xrootd"` | The container image repository for the XRootD storage deployment |
150
152
  | test_storages.xrootd.image.tag | string | `"37.1.0"` | Defines the specific version of the XRootD image to use |
153
+ | test_storages.xrootd.rucio_storage_1_storage_class | string | `"standard"` | The storage class name for the PVC used by rucio-storage-1 |
151
154
 
@@ -1,7 +1,6 @@
1
1
  hash=$(openssl x509 -noout -hash -in /etc/grid-security/ca.pem)
2
2
 
3
3
  mkdir -pv /etc/grid-security/certificates
4
- update-ca-trust force-enable
5
4
 
6
5
  cp -fv /etc/grid-security/ca.pem /etc/pki/ca-trust/source/anchors/rucio-ca.pem
7
6
  update-ca-trust extract
@@ -47,7 +47,7 @@ spec:
47
47
  - /bin/sh
48
48
  - -c
49
49
  - |
50
- set -x
50
+ set -ex
51
51
 
52
52
  {{ .Files.Get "scripts/certificates/install_ca.sh" | indent 10 }}
53
53
  {{ .Files.Get "scripts/bootstrap_rucio/wait_for_rucio.sh" | indent 10 }}
@@ -56,6 +56,12 @@ spec:
56
56
 
57
57
  python3 /usr/local/rucio/tools/reset_database.py
58
58
 
59
+ curl -LO https://dl.k8s.io/release/v1.33.0/bin/linux/amd64/kubectl -o ./kubectl
60
+ chmod +x ./kubectl
61
+
62
+ # could be also in post-upgrade hook but only if bootstrap was performed
63
+ ./kubectl rollout restart deployment {{ .Release.Name }}-rucio-server
64
+
59
65
  volumeMounts:
60
66
  {{ include "volume_mounts_rucio_config" . | indent 8 }}
61
67
  {{ include "volume_mounts_cert" . | indent 8 }}
@@ -1,3 +1,4 @@
1
+ {{ if .Values.test_storages.enabled }}
1
2
  {{- $suffix_namespace := .Values.suffix_namespace -}}
2
3
  {{ $values := .Values -}}
3
4
  {{- range $name := .Values.test_storages.xrootd.instances }}
@@ -44,7 +45,7 @@ spec:
44
45
  {{- if eq $name "rucio-storage-1" }}
45
46
  initContainers: #Initialize the PersistentVolumeClaim volume
46
47
  - name: bdms-storage-1-init #Name
47
- image: busybox:latest #You can use another image, like alpine/BusyBox, but must provide sh and chmod
48
+ image: harbor.cta-observatory.org/proxy_cache/busybox:latest #You can use another image, like alpine/BusyBox, but must provide sh and chmod
48
49
  command: ["/bin/sh", "-c", "mkdir -p /rucio/data && chmod -R 777 /rucio/data"] #This make the folder and sets all permissions correct
49
50
  volumeMounts:
50
51
  - name: bdms-storage-1-data
@@ -156,4 +157,5 @@ spec:
156
157
  resources:
157
158
  requests:
158
159
  storage: 2Gi # Adjust size as needed
159
- storageClassName: standard
160
+ storageClassName: {{ .Values.test_storages.xrootd.rucio_storage_1_storage_class }}
161
+ {{ end }}
@@ -76,7 +76,8 @@ spec:
76
76
  --junitxml=/tmp/report.xml \
77
77
  --color=yes \
78
78
  --log-cli-level=INFO \
79
- --durations=10 --durations-min=30
79
+ --durations=10 --durations-min=30 \
80
+ -n {{ .Values.dev.n_test_jobs }}
80
81
 
81
82
  curl -T /tmp/coverage.xml http://testkit:8000/coverage.xml
82
83
  curl -T /tmp/report.xml http://testkit:8000/report.xml
@@ -176,6 +176,8 @@ configure:
176
176
 
177
177
  # --- A list of test storages, deployed in the test setup
178
178
  test_storages:
179
+ # -- If true, deploys test storages for testing purposes. This is set to 'False' if an external storage is used as in the production setup
180
+ enabled: true
179
181
  xrootd:
180
182
  image:
181
183
  # -- The container image repository for the XRootD storage deployment
@@ -187,6 +189,8 @@ test_storages:
187
189
  - "rucio-storage-1"
188
190
  - "rucio-storage-2"
189
191
  - "rucio-storage-3"
192
+ # -- The storage class name for the PVC used by rucio-storage-1
193
+ rucio_storage_1_storage_class: standard
190
194
 
191
195
  rucio_db:
192
196
  # -- The database connection URI for Rucio. It is of the format: `postgresql://<user>:<password>@<host>:<port>/<database>`, this field in use only if 'existingSecret.enabled' is set to 'false', otherwise ignored
@@ -452,6 +456,8 @@ dev:
452
456
  run_tests: true
453
457
  mount_repo: true
454
458
  client_image_tag:
459
+ # -- number of jobs to use for pytest
460
+ n_test_jobs: 4
455
461
 
456
462
  cert-generator-grid:
457
463
  enabled: true
@@ -3,4 +3,5 @@ Change Log
3
3
 
4
4
  .. changelog::
5
5
  :towncrier: ../
6
+ :towncrier-skip-if-empty:
6
7
  :changelog_file: ../CHANGES.rst
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
  name = "ctao-bdms-clients"
7
7
  description = "Client module for the CTAO DPPS Bulk Data Management System"
8
8
  readme = "README.md"
9
- license = {text = "BSD-3-Clause"}
9
+ license = "BSD-3-Clause"
10
10
  authors = [
11
11
  {name = "Georgios Zacharis", email = "georgios.zacharis@inaf.it"},
12
12
  {name = "Stefano Gallozzi", email = "Stefano.gallozzi@inaf.it"},
@@ -21,6 +21,7 @@ dependencies = [
21
21
  "astropy>=6.0.1,<8.0.0a0",
22
22
  "ctao-bdms-rucio-policy~=0.1.0",
23
23
  "rucio-clients~=35.7.0",
24
+ "protozfits>=2.7.2",
24
25
  ]
25
26
 
26
27
  # needed for setuptools_scm, we don"t define a static version
@@ -41,6 +42,7 @@ test = [
41
42
  "pytest-requirements",
42
43
  "python-dotenv",
43
44
  "minio",
45
+ "pytest-xdist",
44
46
  ]
45
47
  doc = [
46
48
  "sphinx",
@@ -8,5 +8,5 @@ sonar.language=python
8
8
  sonar.python.coverage.reportPaths=coverage.xml
9
9
  sonar.python.version=3
10
10
  # ignore submodule, is external
11
- sonar.exclusions=dpps-aiv-toolkit/**,test-report/**,dpps-release-plan/**,requirements-traceability/**,chart/charts/rucio-daemons/patches/request_patched.py
12
- sonar.coverage.exclusions=**/tests/**,**/conftest.py,**/test_*.py
11
+ sonar.exclusions=dpps-aiv-toolkit/**,test-report/**,dpps-release-plan/**,requirements-traceability/**,chart/charts/rucio-daemons/patches/request_patched.py,src/bdms/_version.py,src/bdms/_dev_version/__init__.py
12
+ sonar.coverage.exclusions=**/tests/**,**/conftest.py,**/test_*.py,docs/conf.py
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.2.0rc1'
21
- __version_tuple__ = version_tuple = (0, 2, 0, 'rc1')
20
+ __version__ = version = '0.2.1'
21
+ __version_tuple__ = version_tuple = (0, 2, 1)
@@ -4,16 +4,16 @@ This module provides the IngestionClient class to manage the ingestion of ACADA
4
4
  It includes functionality for constructing FITS file paths, converting ACADA paths to Logical File Names (LFNs),
5
5
  and registering replicas in Rucio.
6
6
  """
7
- # this is the latest working file (as on 6:40 pm) with judge repairer repairing the STUCK rule.
8
7
 
9
8
  import logging
10
9
  import os
10
+ from contextlib import ExitStack
11
11
  from pathlib import Path
12
12
  from typing import Optional, Union
13
13
 
14
14
  from astropy.io import fits
15
15
  from rucio.client.accountclient import AccountClient
16
- from rucio.client.client import Client
16
+ from rucio.client.client import Client, DIDClient
17
17
  from rucio.client.replicaclient import ReplicaClient
18
18
  from rucio.client.rseclient import RSEClient
19
19
  from rucio.client.ruleclient import RuleClient
@@ -21,6 +21,11 @@ from rucio.client.scopeclient import ScopeClient
21
21
  from rucio.common.exception import Duplicate, RucioException
22
22
  from rucio.common.utils import adler32
23
23
 
24
+ from bdms.extract_fits_metadata import (
25
+ extract_metadata_from_data,
26
+ extract_metadata_from_headers,
27
+ )
28
+
24
29
  LOGGER = logging.getLogger(__name__)
25
30
 
26
31
 
@@ -91,6 +96,7 @@ class IngestionClient:
91
96
  self.account_client = AccountClient()
92
97
  self.rse_client = RSEClient()
93
98
  self.rule_client = RuleClient()
99
+ self.did_client = DIDClient()
94
100
  except RucioException as e:
95
101
  self.logger.error("Failed to initialize Rucio clients: %s", str(e))
96
102
  raise
@@ -261,9 +267,10 @@ class IngestionClient:
261
267
  return lfn
262
268
 
263
269
  # Proceed with registering the replica if check_replica_exists returns False
270
+ valid, metadata = verify_and_extract_metadata(acada_path)
271
+ metadata["valid_fits_checksum"] = valid
264
272
 
265
- # Compute file metadata
266
- # TODO: use functions to identify file type, extract metadata, validate integrity, when this functionality is ready https://gitlab.cta-observatory.org/cta-computing/dpps/bdms/bdms/-/work_items/46
273
+ # Compute rucio file metadata
267
274
  file_size = acada_path.stat().st_size
268
275
  checksum = adler32(acada_path)
269
276
 
@@ -286,6 +293,10 @@ class IngestionClient:
286
293
  )
287
294
  self.logger.info("Successfully registered the replica for lfn '%s'", lfn)
288
295
 
296
+ if len(metadata) > 0:
297
+ self.did_client.set_metadata_bulk(scope=self.scope, name=lfn, meta=metadata)
298
+ self.logger.info("Set metadata of %r to %r", lfn, metadata)
299
+
289
300
  return lfn
290
301
 
291
302
  def add_offsite_replication_rules(
@@ -433,3 +444,36 @@ def verify_fits_checksum(hdul: fits.HDUList):
433
444
  raise FITSVerificationError(msg)
434
445
  elif checksum_result == 2 and pos != 0: # ignore primary for warning
435
446
  LOGGER.warning("No CHECKSUM in HDU %d with name %r", pos, name)
447
+
448
+
449
+ def verify_and_extract_metadata(fits_path):
450
+ """Verify checksums and extract metadata from FITS files.
451
+
452
+ This wrapper transforms exceptions into log errors and minimizes
453
+ the number of times the FITS file has to be opened.
454
+ """
455
+ # this context manager allows elegant handling
456
+ # of conditionally present context managers
457
+ # which allows better handling of exceptions below
458
+ context = ExitStack()
459
+ metadata = {}
460
+ with context:
461
+ try:
462
+ hdul = context.enter_context(fits.open(fits_path))
463
+ except Exception as e:
464
+ LOGGER.error("Failed to open FITS file %r: %s", fits_path, e)
465
+ return False, metadata
466
+
467
+ try:
468
+ verify_fits_checksum(hdul)
469
+ except FITSVerificationError as e:
470
+ LOGGER.error("File %r failed FITS checksum verification: %s", fits_path, e)
471
+ return False, metadata
472
+
473
+ try:
474
+ metadata = extract_metadata_from_headers(hdul)
475
+ metadata.update(extract_metadata_from_data(fits_path))
476
+ return True, metadata
477
+ except Exception as e:
478
+ LOGGER.error("Failed to extract metadata from %r: %s", fits_path, e)
479
+ return False, metadata
@@ -0,0 +1,134 @@
1
+ """Functions to extract metadata from input files."""
2
+
3
+ import logging
4
+
5
+ import numpy as np
6
+ from protozfits import File
7
+
8
+ # Configure logger
9
+ logger = logging.getLogger(__name__)
10
+
11
+ # COMMON HEADER
12
+ start_time = "DataStream.DATE"
13
+
14
+ # COMMON DATA
15
+ origin = "DataStream.ORIGIN"
16
+ sb_id = "DataStream.sb_id"
17
+ obs_id = "DataStream.obs_id"
18
+
19
+ # -- FOR TEL_TRIG
20
+ tel_ids = "DataStream.tel_ids"
21
+
22
+ # -- FOR TEL_SUB
23
+ subarray_id = "DataStream.subarray_id"
24
+
25
+ METADATA_TEL = {
26
+ "HEADER": {
27
+ "observatory": origin,
28
+ "start_time": start_time,
29
+ "end_time": "Events.DATEEND",
30
+ },
31
+ "PAYLOAD": {
32
+ "sb_id": sb_id,
33
+ "obs_id": obs_id,
34
+ },
35
+ }
36
+
37
+ METADATA_SUB = {
38
+ "HEADER": {
39
+ "observatory": origin,
40
+ "start_time": start_time,
41
+ "end_time": "SubarrayEvents.DATEEND",
42
+ },
43
+ "PAYLOAD": {
44
+ "subarray_id": subarray_id,
45
+ "sb_id": sb_id,
46
+ "obs_id": obs_id,
47
+ },
48
+ }
49
+
50
+ METADATA_TRIG = {
51
+ "HEADER": {
52
+ "observatory": origin,
53
+ "start_time": start_time,
54
+ "end_time": "Triggers.DATEEND",
55
+ },
56
+ "PAYLOAD": {
57
+ "tel_ids": tel_ids,
58
+ "sb_id": sb_id,
59
+ "obs_id": obs_id,
60
+ },
61
+ }
62
+
63
+ #: Mapping from DataStream.PBFHEAD to the metadata items we want to collect
64
+ METADATA_SCHEMAS = {
65
+ "DL0v1.Trigger.DataStream": METADATA_TRIG,
66
+ "DL0v1.Subarray.DataStream": METADATA_SUB,
67
+ "DL0v1.Telescope.DataStream": METADATA_TEL,
68
+ }
69
+
70
+
71
+ def extract_metadata_from_headers(hdul):
72
+ """Extract metadata from FITS headers of hdul."""
73
+ all_headers = {}
74
+ for hdu in hdul:
75
+ if hdu.is_image:
76
+ continue
77
+ all_headers[hdu.name] = dict(hdu.header)
78
+
79
+ try:
80
+ all_headers["DataStream"]
81
+ except KeyError:
82
+ logger.error("No DataStream HDU found in the FITS file.")
83
+ return {}
84
+
85
+ pbfhead = all_headers["DataStream"]["PBFHEAD"]
86
+ schema = METADATA_SCHEMAS.get(pbfhead)
87
+ if schema is None:
88
+ logger.error(
89
+ "The PBFHEAD %r does not correspond to any known FITS type.", pbfhead
90
+ )
91
+ return {}
92
+
93
+ logger.debug("Headers extracted: %s", all_headers.keys())
94
+
95
+ metadata = {}
96
+ for value_name, metadata_path in schema["HEADER"].items():
97
+ extname, header_key = metadata_path.split(".")
98
+ table = all_headers[extname][header_key]
99
+ metadata[value_name] = table
100
+
101
+ return metadata
102
+
103
+
104
+ def extract_metadata_from_data(path):
105
+ """Extract metadata from zFITS payload in path."""
106
+ with File(path) as f:
107
+ if not hasattr(f, "DataStream"):
108
+ return {}
109
+
110
+ pbfhead = f.DataStream.header["PBFHEAD"]
111
+ schema = METADATA_SCHEMAS.get(pbfhead)
112
+ if schema is None:
113
+ logger.error(
114
+ "The PBFHEAD %r does not correspond to any known FITS type.", pbfhead
115
+ )
116
+ return {}
117
+
118
+ metadata = {}
119
+ for value_name, metadata_path in schema["PAYLOAD"].items():
120
+ hdu, column = metadata_path.split(".")
121
+ row = getattr(f, hdu)[0]
122
+ metadata[value_name] = getattr(row, column)
123
+
124
+ if isinstance(metadata[value_name], np.ndarray):
125
+ # Convert numpy array to a Python list
126
+ metadata[value_name] = metadata[value_name].tolist()
127
+
128
+ logger.debug(
129
+ "Value '%s' from '%s' extracted. (renamed as '%s')",
130
+ column,
131
+ hdu,
132
+ value_name,
133
+ )
134
+ return metadata
@@ -8,7 +8,7 @@ from secrets import token_hex
8
8
  import pytest
9
9
  from rucio.client.scopeclient import ScopeClient
10
10
 
11
- from bdms.tests.utils import download_test_file
11
+ from bdms.tests.utils import download_test_file, reset_xrootd_permissions
12
12
 
13
13
  USER_CERT = os.getenv("RUCIO_CFG_CLIENT_CERT", "/opt/rucio/etc/usercert.pem")
14
14
  USER_KEY = os.getenv("RUCIO_CFG_CLIENT_KEY", "/opt/rucio/etc/userkey.pem")
@@ -90,5 +90,28 @@ def tel_trigger_test_file():
90
90
  @pytest.fixture(scope="session")
91
91
  def tel_events_test_file():
92
92
  """Fixture to download a telescope events test file"""
93
- path = "acada-small/DL0/LSTN-01/ctao-n-acada/acada-adh/events/2025/02/04/TEL001_SDH0000_20250204T213354_SBID0000000002000000066_OBSID0000000002000000200_CHUNK000.fits.fz"
93
+ path = "acada-small/DL0/LSTN-01/ctao-n-acada/acada-adh/events/2025/02/04/TEL001_SDH0000_20250204T213354_SBID0000000002000000066_OBSID0000000002000000200_CHUNK001.fits.fz"
94
94
  return download_test_file(path)
95
+
96
+
97
+ @pytest.fixture
98
+ def onsite_test_file(
99
+ storage_mount_path: Path, test_scope: str, test_vo: str
100
+ ) -> tuple[Path, str]:
101
+ """Create a dummy file in the shared storage for testing."""
102
+
103
+ unique_id = f"{datetime.now():%Y%m%d_%H%M%S}_{token_hex(8)}"
104
+ filename = f"testfile_{unique_id}.txt"
105
+
106
+ test_file_path = storage_mount_path / test_vo / test_scope / filename
107
+ test_file_path.parent.mkdir(parents=True, exist_ok=True)
108
+
109
+ # Write a small test content (simulating a .fits.fz file with minimal content for testing)
110
+ test_file_content = f"Test file with random content: {unique_id}"
111
+ test_file_path.write_text(test_file_content)
112
+
113
+ # need to change file permissions of created directories so that
114
+ # the xrootd still can read and write there
115
+ reset_xrootd_permissions(storage_mount_path)
116
+
117
+ return test_file_path, test_file_content