palimpsest-client 0.2.3__py3-none-any.whl

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 (131) hide show
  1. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/defaults/main.yml +155 -0
  2. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/files/validate_image_ref.py +63 -0
  3. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/handlers/main.yml +1 -0
  4. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/meta/main.yml +8 -0
  5. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/bootstrap_service.yml +58 -0
  6. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/config.yml +20 -0
  7. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/deploy.yml +20 -0
  8. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/destroy.yml +8 -0
  9. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/image_precheck.yml +36 -0
  10. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/loadbalancer.yml +23 -0
  11. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/main.yml +10 -0
  12. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/precheck.yml +44 -0
  13. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/preconditions.yml +6 -0
  14. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/preconditions_db.yml +31 -0
  15. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/preconditions_keystone.yml +24 -0
  16. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/pull.yml +16 -0
  17. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/reconfigure.yml +9 -0
  18. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/source_build.yml +97 -0
  19. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/start.yml +31 -0
  20. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/tasks/upgrade.yml +9 -0
  21. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/templates/palimpsest.conf.j2 +26 -0
  22. palimpsest_client-0.2.3.data/data/share/kolla-ansible/ansible/roles/palimpsest/vars/main.yml +1 -0
  23. palimpsest_client-0.2.3.dist-info/METADATA +622 -0
  24. palimpsest_client-0.2.3.dist-info/RECORD +131 -0
  25. palimpsest_client-0.2.3.dist-info/WHEEL +4 -0
  26. palimpsest_client-0.2.3.dist-info/entry_points.txt +2 -0
  27. palimpsest_client-0.2.3.dist-info/licenses/LICENSE +21 -0
  28. palimpsest_local/__init__.py +42 -0
  29. palimpsest_local/_oci_stage1_kvm_proof.py +5845 -0
  30. palimpsest_local/artifact_store.py +1019 -0
  31. palimpsest_local/assets/oci-stage1-init.x86_64 +0 -0
  32. palimpsest_local/build.py +599 -0
  33. palimpsest_local/buildkit.py +2100 -0
  34. palimpsest_local/cli.py +2431 -0
  35. palimpsest_local/cloud_runtime.py +2011 -0
  36. palimpsest_local/cloudinit.py +600 -0
  37. palimpsest_local/completion.py +263 -0
  38. palimpsest_local/digest.py +46 -0
  39. palimpsest_local/errors.py +57 -0
  40. palimpsest_local/guest.py +174 -0
  41. palimpsest_local/host_journal.py +204 -0
  42. palimpsest_local/hub.py +557 -0
  43. palimpsest_local/hub_builder.py +212 -0
  44. palimpsest_local/inventory.py +697 -0
  45. palimpsest_local/kvm.py +717 -0
  46. palimpsest_local/lima.py +1428 -0
  47. palimpsest_local/linux_install.py +232 -0
  48. palimpsest_local/log_stream.py +180 -0
  49. palimpsest_local/metrics.py +967 -0
  50. palimpsest_local/oci_acl.py +290 -0
  51. palimpsest_local/oci_boot_access.py +412 -0
  52. palimpsest_local/oci_boot_exports.py +426 -0
  53. palimpsest_local/oci_boot_plan.py +274 -0
  54. palimpsest_local/oci_changeset.py +462 -0
  55. palimpsest_local/oci_control_protocol.py +521 -0
  56. palimpsest_local/oci_control_protocol_v2.py +1298 -0
  57. palimpsest_local/oci_convert.py +1279 -0
  58. palimpsest_local/oci_converter.py +1099 -0
  59. palimpsest_local/oci_exec_control.py +203 -0
  60. palimpsest_local/oci_exec_record.py +850 -0
  61. palimpsest_local/oci_exec_session.py +444 -0
  62. palimpsest_local/oci_exec_status.py +83 -0
  63. palimpsest_local/oci_guest_filesystems.py +245 -0
  64. palimpsest_local/oci_guest_stage1.py +613 -0
  65. palimpsest_local/oci_host.py +283 -0
  66. palimpsest_local/oci_image.py +494 -0
  67. palimpsest_local/oci_initramfs.py +820 -0
  68. palimpsest_local/oci_layout.py +722 -0
  69. palimpsest_local/oci_lifecycle_transport.py +603 -0
  70. palimpsest_local/oci_lower_access.py +401 -0
  71. palimpsest_local/oci_lower_exports.py +382 -0
  72. palimpsest_local/oci_materializer.py +676 -0
  73. palimpsest_local/oci_materializer_worker.py +249 -0
  74. palimpsest_local/oci_metrics.py +361 -0
  75. palimpsest_local/oci_monitor.py +802 -0
  76. palimpsest_local/oci_monitor_client.py +342 -0
  77. palimpsest_local/oci_monitor_control.py +73 -0
  78. palimpsest_local/oci_monitor_coordinator.py +311 -0
  79. palimpsest_local/oci_monitor_handoff.py +454 -0
  80. palimpsest_local/oci_monitor_ipc.py +2892 -0
  81. palimpsest_local/oci_monitor_launch.py +723 -0
  82. palimpsest_local/oci_monitor_recovery.py +540 -0
  83. palimpsest_local/oci_monitor_retention.py +336 -0
  84. palimpsest_local/oci_network.py +492 -0
  85. palimpsest_local/oci_network_status.py +72 -0
  86. palimpsest_local/oci_packer.py +1110 -0
  87. palimpsest_local/oci_process.py +386 -0
  88. palimpsest_local/oci_process_session.py +141 -0
  89. palimpsest_local/oci_provenance.py +836 -0
  90. palimpsest_local/oci_resource_status.py +213 -0
  91. palimpsest_local/oci_root_access.py +731 -0
  92. palimpsest_local/oci_root_kvm.py +1326 -0
  93. palimpsest_local/oci_root_prepare.py +742 -0
  94. palimpsest_local/oci_root_proof.py +319 -0
  95. palimpsest_local/oci_root_runtime.py +2530 -0
  96. palimpsest_local/oci_root_volume.py +1055 -0
  97. palimpsest_local/oci_root_volume_inventory.py +76 -0
  98. palimpsest_local/oci_run_adapter.py +271 -0
  99. palimpsest_local/oci_run_cleanup.py +249 -0
  100. palimpsest_local/oci_run_request.py +214 -0
  101. palimpsest_local/oci_runtime_access.py +737 -0
  102. palimpsest_local/oci_runtime_io.py +398 -0
  103. palimpsest_local/oci_shared_traversal.py +1116 -0
  104. palimpsest_local/oci_source.py +1426 -0
  105. palimpsest_local/oci_stage1.py +387 -0
  106. palimpsest_local/oci_stage1_access.py +605 -0
  107. palimpsest_local/oci_stage1_transport.py +348 -0
  108. palimpsest_local/oci_store.py +2618 -0
  109. palimpsest_local/oci_supervisor.py +1151 -0
  110. palimpsest_local/oci_tar_emitter.py +147 -0
  111. palimpsest_local/oci_worker_limits.py +5 -0
  112. palimpsest_local/oci_worker_protocol.py +436 -0
  113. palimpsest_local/pci_preflight.py +281 -0
  114. palimpsest_local/platforms.py +937 -0
  115. palimpsest_local/process_session.py +458 -0
  116. palimpsest_local/project.py +1821 -0
  117. palimpsest_local/project_adapter.py +1019 -0
  118. palimpsest_local/project_runtime.py +1310 -0
  119. palimpsest_local/project_volumes.py +1012 -0
  120. palimpsest_local/refs.py +180 -0
  121. palimpsest_local/registry.py +971 -0
  122. palimpsest_local/registry_intake.py +307 -0
  123. palimpsest_local/runtime.py +45 -0
  124. palimpsest_local/runtime_dispatch.py +1596 -0
  125. palimpsest_local/runtime_types.py +1723 -0
  126. palimpsest_local/sandbox_policy.py +865 -0
  127. palimpsest_local/state.py +3244 -0
  128. palimpsest_local/ui.py +448 -0
  129. palimpsest_local/webui/app.css +434 -0
  130. palimpsest_local/webui/app.js +654 -0
  131. palimpsest_local/webui/index.html +325 -0
@@ -0,0 +1,155 @@
1
+ ---
2
+ # Palimpsest kolla role defaults
3
+
4
+ palimpsest_image_tag: "0.2.0"
5
+ palimpsest_image_namespace: "ghcr.io/openstack-afterglow"
6
+ palimpsest_api_image: "{{ palimpsest_image_namespace }}/palimpsest-hub-api"
7
+ palimpsest_worker_image: "{{ palimpsest_image_namespace }}/palimpsest-hub-worker"
8
+
9
+ palimpsest_source_mode: "{{ enable_palimpsest_source_build | default(enable_source_build | default(palimpsest_dev_mode | default(false))) | bool }}"
10
+ palimpsest_source_repo: "https://github.com/openstack-afterglow/palimpsest.git"
11
+ palimpsest_source_version: "98f6dc920af43d0ce906750d918a60ca2f3eacd9"
12
+ palimpsest_source_dir: "{{ palimpsest_source_checkout_path | default('/opt/afterglow/src/palimpsest') }}"
13
+ palimpsest_api_image_ref: "{{ 'afterglow-local/palimpsest-hub-api:' ~ (palimpsest_source_version | truncate(12, True, '')) if (palimpsest_source_mode | bool) else (palimpsest_api_image ~ ':' ~ palimpsest_image_tag) }}"
14
+ palimpsest_worker_image_ref: "{{ 'afterglow-local/palimpsest-hub-worker:' ~ (palimpsest_source_version | truncate(12, True, '')) if (palimpsest_source_mode | bool) else (palimpsest_worker_image ~ ':' ~ palimpsest_image_tag) }}"
15
+
16
+ enable_palimpsest: "no"
17
+ enable_palimpsest_hub_api: "{{ enable_palimpsest }}"
18
+ enable_palimpsest_hub_worker: "{{ enable_palimpsest }}"
19
+ palimpsest_run_preconditions: true
20
+
21
+ palimpsest_api_port: 8020
22
+ palimpsest_api_listen_address: "{{ 'api' | kolla_address(inventory_hostname) }}"
23
+ palimpsest_api_listen_port: 18020
24
+ palimpsest_database_name: "palimpsest_kolla"
25
+ palimpsest_database_user: "palimpsest_kolla"
26
+ palimpsest_database_address: "{{ database_address }}"
27
+ palimpsest_database_port: "{{ database_port }}"
28
+ palimpsest_database_admin_user: "{{ database_user }}"
29
+ palimpsest_database_admin_password: "{{ database_password }}"
30
+ palimpsest_database_url: "mysql+asyncmy://{{ palimpsest_database_user }}:{{ palimpsest_database_password }}@{{ palimpsest_database_address }}:{{ palimpsest_database_port }}/{{ palimpsest_database_name }}"
31
+ palimpsest_valkey_host: "{{ 'api' | kolla_address(groups['valkey'][0]) }}"
32
+ palimpsest_valkey_port: "{{ valkey_server_port }}"
33
+ palimpsest_valkey_password: "{{ valkey_master_password }}"
34
+ palimpsest_redis_db_index: 9
35
+ palimpsest_redis_url: "redis://default:{{ palimpsest_valkey_password }}@{{ palimpsest_valkey_host }}:{{ palimpsest_valkey_port }}/{{ palimpsest_redis_db_index }}"
36
+
37
+ palimpsest_keystone_user: "palimpsest"
38
+ palimpsest_keystone_auth_url: "{{ keystone_internal_url }}"
39
+ palimpsest_keystone_project_domain_name: "{{ default_project_domain_name }}"
40
+ palimpsest_keystone_user_domain_name: "{{ default_user_domain_name }}"
41
+ palimpsest_keystone_region_name: "{{ openstack_region_name }}"
42
+ palimpsest_keystone_interface: "{{ openstack_interface | default('internal') }}"
43
+ palimpsest_service_project_name: "palimpsest-service"
44
+ palimpsest_external_url: "{{ public_protocol | default('https') }}://{{ kolla_external_fqdn | default('localhost') }}:{{ palimpsest_api_port }}"
45
+ palimpsest_public_endpoint_url: "{{ palimpsest_external_url }}"
46
+ palimpsest_internal_endpoint_url: "{{ internal_protocol | default('http') }}://{{ kolla_internal_fqdn | default(kolla_internal_vip_address) }}:{{ palimpsest_api_port }}"
47
+ palimpsest_admin_endpoint_url: "{{ palimpsest_internal_endpoint_url }}"
48
+
49
+ palimpsest_hub_volume: "palimpsest_hub"
50
+ palimpsest_hub_path: "/var/lib/palimpsest/hub"
51
+ palimpsest_config_dir: "{{ node_config_directory }}/palimpsest"
52
+ palimpsest_hub_max_blob_bytes: 107374182400
53
+ palimpsest_hub_max_bundle_expanded_bytes: 107374182400
54
+ palimpsest_hub_max_blocking_operations: 2
55
+
56
+ palimpsest_public_haproxy_enabled: false
57
+ palimpsest_public_haproxy_fqdn: ""
58
+
59
+ palimpsest_services:
60
+ palimpsest-hub-api:
61
+ container_name: palimpsest_hub_api
62
+ group: palimpsest
63
+ enabled: "{{ enable_palimpsest_hub_api | bool }}"
64
+ image: "{{ palimpsest_api_image_ref }}"
65
+ network_mode: host
66
+ command: ["uvicorn", "palimpsest_hub.main:app", "--host", "{{ palimpsest_api_listen_address }}", "--port", "{{ palimpsest_api_listen_port | string }}", "--proxy-headers"]
67
+ restart_policy: unless-stopped
68
+ volumes:
69
+ - "{{ palimpsest_config_dir }}/palimpsest.conf:/app/palimpsest.conf:ro"
70
+ - "{{ palimpsest_hub_volume }}:{{ palimpsest_hub_path }}"
71
+ - "kolla_logs:/var/log/kolla/"
72
+ environment:
73
+ DATABASE_URL: "{{ palimpsest_database_url }}"
74
+ REDIS_URL: "{{ palimpsest_redis_url }}"
75
+ OS_PASSWORD: "{{ palimpsest_keystone_password }}"
76
+ PALIMPSEST_HUB_LOCAL_PATH: "{{ palimpsest_hub_path }}"
77
+ PALIMPSEST_HUB_MAX_BLOB_BYTES: "{{ palimpsest_hub_max_blob_bytes | string }}"
78
+ PALIMPSEST_HUB_MAX_BUNDLE_EXPANDED_BYTES: "{{ palimpsest_hub_max_bundle_expanded_bytes | string }}"
79
+ PALIMPSEST_HUB_MAX_BLOCKING_OPERATIONS: "{{ palimpsest_hub_max_blocking_operations | string }}"
80
+ OS_AUTH_URL: "{{ palimpsest_keystone_auth_url }}"
81
+ OS_USERNAME: "{{ palimpsest_keystone_user }}"
82
+ OS_PROJECT_NAME: "{{ palimpsest_service_project_name }}"
83
+ OS_PROJECT_DOMAIN_NAME: "{{ palimpsest_keystone_project_domain_name }}"
84
+ OS_USER_DOMAIN_NAME: "{{ palimpsest_keystone_user_domain_name }}"
85
+ OS_REGION_NAME: "{{ palimpsest_keystone_region_name }}"
86
+ OS_INTERFACE: "{{ palimpsest_keystone_interface }}"
87
+ SSL_VERIFY: "{{ (not (openstack_insecure | default(false) | bool)) | string }}"
88
+ healthcheck:
89
+ test: ["CMD", "python", "-c", "from urllib.request import urlopen; response = urlopen('http://{{ palimpsest_api_listen_address }}:{{ palimpsest_api_listen_port }}/v1/health', timeout=5); assert response.status == 200"]
90
+ interval: 30s
91
+ timeout: 10s
92
+ retries: 3
93
+ start_period: 30s
94
+ haproxy:
95
+ palimpsest-hub-api:
96
+ enabled: "{{ enable_palimpsest_hub_api | bool }}"
97
+ external: false
98
+ port: "{{ palimpsest_api_port }}"
99
+ listen_port: "{{ palimpsest_api_listen_port }}"
100
+ host_group: palimpsest
101
+ frontend_http_extra:
102
+ - "option forwardfor"
103
+ backend_http_extra:
104
+ - "option httpchk GET /v1/health"
105
+ - "http-check expect status 200"
106
+
107
+ palimpsest-hub-worker:
108
+ container_name: palimpsest_hub_worker
109
+ group: palimpsest
110
+ enabled: "{{ enable_palimpsest_hub_worker | bool }}"
111
+ image: "{{ palimpsest_worker_image_ref }}"
112
+ command: ["palimpsest-hub-worker"]
113
+ network_mode: host
114
+ restart_policy: unless-stopped
115
+ volumes:
116
+ - "{{ palimpsest_config_dir }}/palimpsest.conf:/app/palimpsest.conf:ro"
117
+ - "{{ palimpsest_hub_volume }}:{{ palimpsest_hub_path }}"
118
+ - "kolla_logs:/var/log/kolla/"
119
+ environment:
120
+ DATABASE_URL: "{{ palimpsest_database_url }}"
121
+ REDIS_URL: "{{ palimpsest_redis_url }}"
122
+ OS_PASSWORD: "{{ palimpsest_keystone_password }}"
123
+ PALIMPSEST_HUB_LOCAL_PATH: "{{ palimpsest_hub_path }}"
124
+ PALIMPSEST_HUB_MAX_BLOB_BYTES: "{{ palimpsest_hub_max_blob_bytes | string }}"
125
+ OS_AUTH_URL: "{{ palimpsest_keystone_auth_url }}"
126
+ OS_USERNAME: "{{ palimpsest_keystone_user }}"
127
+ OS_PROJECT_NAME: "{{ palimpsest_service_project_name }}"
128
+ OS_PROJECT_DOMAIN_NAME: "{{ palimpsest_keystone_project_domain_name }}"
129
+ OS_USER_DOMAIN_NAME: "{{ palimpsest_keystone_user_domain_name }}"
130
+ OS_REGION_NAME: "{{ palimpsest_keystone_region_name }}"
131
+ OS_INTERFACE: "{{ palimpsest_keystone_interface }}"
132
+ SSL_VERIFY: "{{ (not (openstack_insecure | default(false) | bool)) | string }}"
133
+
134
+ palimpsest_public_haproxy_services:
135
+ palimpsest-public:
136
+ group: palimpsest
137
+ enabled: "{{ enable_palimpsest_hub_api | bool and palimpsest_public_haproxy_enabled | bool }}"
138
+ haproxy:
139
+ palimpsest-public:
140
+ enabled: "{{ enable_palimpsest_hub_api | bool and palimpsest_public_haproxy_enabled | bool }}"
141
+ external: true
142
+ external_fqdn: "{{ palimpsest_public_haproxy_fqdn }}"
143
+ mode: http
144
+ with_frontend: true
145
+ with_backend: true
146
+ host_group: palimpsest
147
+ port: "{{ palimpsest_api_port }}"
148
+ listen_port: "{{ palimpsest_api_listen_port }}"
149
+ frontend_http_extra:
150
+ - "option forwardfor"
151
+ backend_http_extra:
152
+ - "option httpchk GET /v1/health"
153
+ - "http-check expect status 200"
154
+
155
+ palimpsest_haproxy_services: "{{ palimpsest_services | combine(palimpsest_public_haproxy_services, recursive=True) }}"
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env python3
2
+ """Validate Palimpsest OCI image references before deployment mutation."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import re
7
+ import sys
8
+
9
+ _REMOTE_DIGEST_REF = re.compile(
10
+ r"^[a-z0-9]+(?:[._-][a-z0-9]+)*(?::[0-9]+)?/"
11
+ r"[a-z0-9]+(?:[._/-][a-z0-9]+)*@sha256:[0-9a-f]{64}$"
12
+ )
13
+ _REMOTE_TAG_REF = re.compile(
14
+ r"^[a-z0-9]+(?:[._-][a-z0-9]+)*(?::[0-9]+)?/"
15
+ r"[a-z0-9]+(?:[._/-][a-z0-9]+)*:([a-zA-Z0-9_][a-zA-Z0-9_.-]{0,127})$"
16
+ )
17
+ _LOCAL_SOURCE_REF = re.compile(r"^afterglow-local/palimpsest-hub-(?:api|worker):[0-9a-f]{12}$")
18
+
19
+
20
+ def validate_image_ref(reference: str, *, source_mode: bool) -> None:
21
+ if source_mode:
22
+ if not _LOCAL_SOURCE_REF.fullmatch(reference):
23
+ raise ValueError(
24
+ "invalid Palimpsest image reference; "
25
+ "expected afterglow-local/palimpsest-hub-{api|worker}:<12-hex-commit>"
26
+ )
27
+ return
28
+
29
+ if _REMOTE_DIGEST_REF.fullmatch(reference):
30
+ return
31
+
32
+ tag_match = _REMOTE_TAG_REF.fullmatch(reference)
33
+ if tag_match:
34
+ tag = tag_match.group(1)
35
+ if tag.lower() == "latest":
36
+ raise ValueError(
37
+ "invalid Palimpsest image reference; latest tag is prohibited, "
38
+ "expected registry/repository@sha256:<64-lowercase-hex> or "
39
+ "registry/repository:<version-tag>"
40
+ )
41
+ return
42
+
43
+ raise ValueError(
44
+ "invalid Palimpsest image reference; "
45
+ "expected registry/repository@sha256:<64-lowercase-hex> or "
46
+ "registry/repository:<version-tag>"
47
+ )
48
+
49
+
50
+ def main(reference: str, source_mode_arg: str) -> None:
51
+ normalized_mode = source_mode_arg.strip().lower()
52
+ if normalized_mode not in {"true", "false"}:
53
+ raise ValueError("source mode must be true or false")
54
+ validate_image_ref(reference, source_mode=normalized_mode == "true")
55
+
56
+
57
+ if __name__ == "__main__":
58
+ if len(sys.argv) != 3:
59
+ raise SystemExit("usage: validate_image_ref.py IMAGE_REF SOURCE_MODE")
60
+ try:
61
+ main(sys.argv[1], sys.argv[2])
62
+ except ValueError as exc:
63
+ raise SystemExit(str(exc)) from exc
@@ -0,0 +1,8 @@
1
+ ---
2
+ galaxy_info:
3
+ role_name: palimpsest
4
+ author: openstack-afterglow
5
+ description: Palimpsest Hub layer repository service deployment role for kolla-ansible
6
+ min_ansible_version: "2.14"
7
+
8
+ dependencies: []
@@ -0,0 +1,58 @@
1
+ ---
2
+ - name: Bootstrap | Pull Palimpsest API image for bootstrap
3
+ become: true
4
+ community.docker.docker_image:
5
+ name: "{{ palimpsest_api_image_ref }}"
6
+ source: pull
7
+ force_source: "{{ palimpsest_image_tag == 'latest' }}"
8
+ run_once: true
9
+ delegate_to: "{{ groups['palimpsest'] | first }}"
10
+ when: not (palimpsest_source_mode | default(false) | bool)
11
+
12
+ - name: Bootstrap | Set Hub volume owner to image runtime user
13
+ become: true
14
+ community.docker.docker_container:
15
+ name: palimpsest_hub_volume_owner
16
+ image: "{{ palimpsest_api_image_ref }}"
17
+ pull: never
18
+ command: ["chown", "palimpsest:palimpsest", "{{ palimpsest_hub_path }}"]
19
+ user: "0:0"
20
+ state: started
21
+ detach: false
22
+ cleanup: true
23
+ network_mode: none
24
+ volumes:
25
+ - "{{ palimpsest_hub_volume }}:{{ palimpsest_hub_path }}"
26
+ run_once: true
27
+ delegate_to: "{{ groups['palimpsest'] | first }}"
28
+
29
+ - name: Bootstrap | Run Palimpsest Hub bootstrap
30
+ become: true
31
+ community.docker.docker_container:
32
+ name: palimpsest_bootstrap
33
+ image: "{{ palimpsest_api_image_ref }}"
34
+ command: ["palimpsest-hub-bootstrap"]
35
+ state: started
36
+ detach: false
37
+ cleanup: true
38
+ network_mode: host
39
+ volumes:
40
+ - "{{ palimpsest_config_dir }}/palimpsest.conf:/app/palimpsest.conf:ro"
41
+ - "{{ palimpsest_hub_volume }}:{{ palimpsest_hub_path }}"
42
+ env:
43
+ DATABASE_URL: "{{ palimpsest_database_url }}"
44
+ REDIS_URL: "{{ palimpsest_redis_url }}"
45
+ PALIMPSEST_HUB_LOCAL_PATH: "{{ palimpsest_hub_path }}"
46
+ OS_AUTH_URL: "{{ palimpsest_keystone_auth_url }}"
47
+ OS_USERNAME: "{{ palimpsest_keystone_user }}"
48
+ OS_PASSWORD: "{{ palimpsest_keystone_password }}"
49
+ OS_PROJECT_NAME: "{{ palimpsest_service_project_name }}"
50
+ OS_PROJECT_DOMAIN_NAME: "{{ palimpsest_keystone_project_domain_name }}"
51
+ OS_USER_DOMAIN_NAME: "{{ palimpsest_keystone_user_domain_name }}"
52
+ OS_REGION_NAME: "{{ palimpsest_keystone_region_name }}"
53
+ OS_INTERFACE: "{{ palimpsest_keystone_interface }}"
54
+ SSL_VERIFY: "{{ (not (openstack_insecure | default(false) | bool)) | string }}"
55
+ no_log: true
56
+ register: palimpsest_bootstrap_result
57
+ run_once: true
58
+ delegate_to: "{{ groups['palimpsest'] | first }}"
@@ -0,0 +1,20 @@
1
+ ---
2
+ - name: Config | Ensure Palimpsest config directory exists
3
+ become: true
4
+ ansible.builtin.file:
5
+ path: "{{ palimpsest_config_dir }}"
6
+ state: directory
7
+ mode: "0750"
8
+ owner: root
9
+ group: root
10
+ when: inventory_hostname in groups['palimpsest']
11
+
12
+ - name: Config | Render palimpsest.conf
13
+ become: true
14
+ ansible.builtin.template:
15
+ src: palimpsest.conf.j2
16
+ dest: "{{ palimpsest_config_dir }}/palimpsest.conf"
17
+ mode: "0640"
18
+ owner: root
19
+ group: root
20
+ when: inventory_hostname in groups['palimpsest']
@@ -0,0 +1,20 @@
1
+ ---
2
+ - name: Include precheck tasks
3
+ ansible.builtin.include_tasks: precheck.yml
4
+
5
+ - name: Include source build tasks
6
+ ansible.builtin.include_tasks: source_build.yml
7
+ when: palimpsest_source_mode | default(false) | bool
8
+
9
+ - name: Include config tasks
10
+ ansible.builtin.include_tasks: config.yml
11
+
12
+ - name: Include precondition tasks
13
+ ansible.builtin.include_tasks: preconditions.yml
14
+ when: palimpsest_run_preconditions | default(true) | bool
15
+
16
+ - name: Include bootstrap service tasks
17
+ ansible.builtin.include_tasks: bootstrap_service.yml
18
+
19
+ - name: Include start tasks
20
+ ansible.builtin.include_tasks: start.yml
@@ -0,0 +1,8 @@
1
+ ---
2
+ - name: Destroy | Stop and remove Palimpsest containers
3
+ become: true
4
+ community.docker.docker_container:
5
+ name: "{{ item.value.container_name }}"
6
+ state: absent
7
+ loop: "{{ palimpsest_services | dict2items }}"
8
+ when: inventory_hostname in groups['palimpsest']
@@ -0,0 +1,36 @@
1
+ ---
2
+ - name: Image precheck | Validate enabled Palimpsest image references
3
+ ansible.builtin.command:
4
+ argv:
5
+ - "{{ ansible_playbook_python }}"
6
+ - "{{ role_path }}/files/validate_image_ref.py"
7
+ - "{{ item.value.image }}"
8
+ - "{{ palimpsest_source_mode | default(false) | bool | lower }}"
9
+ changed_when: false
10
+ loop: "{{ palimpsest_services | dict2items }}"
11
+ loop_control:
12
+ label: "{{ item.key }}"
13
+ run_once: true
14
+ delegate_to: "{{ groups['deployment'][0] }}"
15
+ when:
16
+ - enable_palimpsest | bool
17
+ - item.value.enabled | bool
18
+
19
+ - name: Image precheck | Inspect enabled remote Palimpsest image manifests
20
+ become: true
21
+ ansible.builtin.command:
22
+ argv:
23
+ - docker
24
+ - manifest
25
+ - inspect
26
+ - "{{ item.value.image }}"
27
+ changed_when: false
28
+ loop: "{{ palimpsest_services | dict2items }}"
29
+ loop_control:
30
+ label: "{{ item.key }}"
31
+ run_once: true
32
+ delegate_to: "{{ groups['palimpsest'] | first }}"
33
+ when:
34
+ - enable_palimpsest | bool
35
+ - item.value.enabled | bool
36
+ - not (palimpsest_source_mode | default(false) | bool)
@@ -0,0 +1,23 @@
1
+ ---
2
+ - name: HAProxy | Remove disabled Palimpsest public route destination
3
+ become: true
4
+ ansible.builtin.file:
5
+ path: "{{ node_config_directory }}/haproxy/services.d/palimpsest-public.cfg"
6
+ state: absent
7
+ when: not (palimpsest_public_haproxy_enabled | default(false) | bool)
8
+
9
+ - name: HAProxy | Remove disabled Palimpsest external frontend map
10
+ become: true
11
+ ansible.builtin.blockinfile:
12
+ path: "{{ node_config_directory }}/haproxy/external-frontend-map"
13
+ marker: "# {mark} palimpsest-public"
14
+ state: absent
15
+ when: not (palimpsest_public_haproxy_enabled | default(false) | bool)
16
+
17
+ - name: Configure loadbalancer for Palimpsest
18
+ ansible.builtin.import_role:
19
+ name: loadbalancer-config
20
+ vars:
21
+ project_name: palimpsest
22
+ project_services: "{{ palimpsest_haproxy_services }}"
23
+ tags: always
@@ -0,0 +1,10 @@
1
+ ---
2
+ - name: Validate requested Palimpsest lifecycle action
3
+ ansible.builtin.assert:
4
+ that:
5
+ - kolla_action | default('deploy') in ['precheck', 'pull', 'deploy', 'reconfigure', 'upgrade', 'destroy', 'config', 'config_validate', 'stop', 'deploy-containers', 'check']
6
+ fail_msg: "Unsupported kolla_action '{{ kolla_action | default('deploy') }}' for palimpsest"
7
+
8
+ - name: Run requested Palimpsest lifecycle action
9
+ ansible.builtin.include_tasks: "{{ kolla_action | default('deploy') }}.yml"
10
+ when: kolla_action | default('deploy') in ['precheck', 'pull', 'deploy', 'reconfigure', 'upgrade', 'destroy', 'config']
@@ -0,0 +1,44 @@
1
+ ---
2
+ - name: Precheck | Verify enable_palimpsest is set
3
+ ansible.builtin.assert:
4
+ that:
5
+ - enable_palimpsest is defined
6
+ fail_msg: "enable_palimpsest must be set in globals.yml"
7
+ run_once: true
8
+ tags: precheck
9
+
10
+ - name: Precheck | Verify stock Kolla Valkey dependency
11
+ ansible.builtin.assert:
12
+ that:
13
+ - enable_valkey | default(false) | bool
14
+ - groups.get('valkey', []) | length > 0
15
+ - valkey_master_password is defined and valkey_master_password | length > 0
16
+ fail_msg: "Deploy stock Kolla Valkey before enabling palimpsest; no plugin Redis fallback exists"
17
+ run_once: true
18
+ tags: precheck
19
+ when: enable_palimpsest | default(false) | bool
20
+
21
+ - name: Precheck | Check required Palimpsest secrets
22
+ ansible.builtin.assert:
23
+ that:
24
+ - palimpsest_database_password is defined and palimpsest_database_password | length > 0
25
+ - palimpsest_keystone_password is defined and palimpsest_keystone_password | length > 0
26
+ - palimpsest_redis_db_index == 9
27
+ fail_msg: "Palimpsest DB/Keystone secrets must be set, and palimpsest_redis_db_index must equal 9"
28
+ tags: precheck
29
+ when: enable_palimpsest | bool
30
+
31
+ - name: Precheck | Validate Palimpsest public route hostname
32
+ ansible.builtin.assert:
33
+ that:
34
+ - palimpsest_public_haproxy_fqdn is match('^[A-Za-z0-9][A-Za-z0-9.-]*[A-Za-z0-9]$')
35
+ - (palimpsest_public_endpoint_url | regex_replace('/$', '')) == ('https://' ~ palimpsest_public_haproxy_fqdn)
36
+ fail_msg: "palimpsest_public_endpoint_url must be the HTTPS origin for palimpsest_public_haproxy_fqdn"
37
+ run_once: true
38
+ tags: precheck
39
+ when:
40
+ - enable_palimpsest | bool
41
+ - palimpsest_public_haproxy_enabled | bool
42
+
43
+ - name: Include Palimpsest image precheck tasks
44
+ ansible.builtin.include_tasks: image_precheck.yml
@@ -0,0 +1,6 @@
1
+ ---
2
+ - name: Include database precondition tasks
3
+ ansible.builtin.import_tasks: preconditions_db.yml
4
+
5
+ - name: Include Keystone precondition tasks
6
+ ansible.builtin.import_tasks: preconditions_keystone.yml
@@ -0,0 +1,31 @@
1
+ ---
2
+ - name: DB | Create Palimpsest database
3
+ kolla_toolbox:
4
+ container_engine: "{{ kolla_container_engine }}"
5
+ module_name: mysql_db
6
+ module_args:
7
+ login_host: "{{ palimpsest_database_address }}"
8
+ login_port: "{{ palimpsest_database_port }}"
9
+ login_user: "{{ palimpsest_database_admin_user }}"
10
+ login_password: "{{ palimpsest_database_admin_password }}"
11
+ name: "{{ palimpsest_database_name }}"
12
+ run_once: true
13
+ delegate_to: "{{ groups['palimpsest'][0] }}"
14
+
15
+ - name: DB | Create Palimpsest database user
16
+ kolla_toolbox:
17
+ container_engine: "{{ kolla_container_engine }}"
18
+ module_name: mysql_user
19
+ module_args:
20
+ login_host: "{{ palimpsest_database_address }}"
21
+ login_port: "{{ palimpsest_database_port }}"
22
+ login_user: "{{ palimpsest_database_admin_user }}"
23
+ login_password: "{{ palimpsest_database_admin_password }}"
24
+ name: "{{ palimpsest_database_user }}"
25
+ password: "{{ palimpsest_database_password }}"
26
+ host: "%"
27
+ priv: "{{ palimpsest_database_name }}.*:ALL"
28
+ state: present
29
+ run_once: true
30
+ delegate_to: "{{ groups['palimpsest'][0] }}"
31
+ no_log: true
@@ -0,0 +1,24 @@
1
+ ---
2
+ - name: Keystone | Register Palimpsest service, project, and user
3
+ ansible.builtin.import_role:
4
+ name: service-ks-register
5
+ vars:
6
+ project_name: palimpsest
7
+ service_ks_register_auth: "{{ openstack_auth }}"
8
+ service_ks_register_services:
9
+ - name: palimpsest
10
+ type: palimpsest
11
+ description: "Palimpsest Hub layer repository service"
12
+ endpoints:
13
+ - interface: public
14
+ url: "{{ palimpsest_public_endpoint_url }}"
15
+ - interface: internal
16
+ url: "{{ palimpsest_internal_endpoint_url }}"
17
+ - interface: admin
18
+ url: "{{ palimpsest_admin_endpoint_url }}"
19
+ service_ks_register_users:
20
+ - project: "{{ palimpsest_service_project_name }}"
21
+ user: "{{ palimpsest_keystone_user }}"
22
+ password: "{{ palimpsest_keystone_password }}"
23
+ role: admin
24
+ no_log: true
@@ -0,0 +1,16 @@
1
+ ---
2
+ - name: Include Palimpsest image precheck tasks
3
+ ansible.builtin.include_tasks: image_precheck.yml
4
+
5
+ - name: Pull | Pull Palimpsest images
6
+ become: true
7
+ community.docker.docker_image:
8
+ name: "{{ item.value.image }}"
9
+ source: pull
10
+ force_source: true
11
+ no_log: true
12
+ loop: "{{ palimpsest_services | dict2items }}"
13
+ when:
14
+ - inventory_hostname in groups['palimpsest']
15
+ - item.value.enabled | bool
16
+ - not (palimpsest_source_mode | default(false) | bool)
@@ -0,0 +1,9 @@
1
+ ---
2
+ - name: Include precheck tasks
3
+ ansible.builtin.include_tasks: precheck.yml
4
+
5
+ - name: Include config tasks
6
+ ansible.builtin.include_tasks: config.yml
7
+
8
+ - name: Include start tasks
9
+ ansible.builtin.include_tasks: start.yml
@@ -0,0 +1,97 @@
1
+ ---
2
+ - name: Source Build | Ensure Palimpsest source checkout directory exists
3
+ become: true
4
+ ansible.builtin.file:
5
+ path: "{{ palimpsest_source_dir }}"
6
+ state: directory
7
+ mode: "0755"
8
+ when: inventory_hostname in groups['palimpsest']
9
+
10
+ - name: Source Build | Check if existing Git repository exists
11
+ become: true
12
+ ansible.builtin.stat:
13
+ path: "{{ palimpsest_source_dir }}/.git"
14
+ register: palimpsest_git_dir_stat
15
+ when: inventory_hostname in groups['palimpsest']
16
+
17
+ - name: Source Build | Check git status of existing checkout
18
+ become: true
19
+ ansible.builtin.command:
20
+ cmd: "git status --porcelain"
21
+ chdir: "{{ palimpsest_source_dir }}"
22
+ register: palimpsest_existing_git_status
23
+ changed_when: false
24
+ when:
25
+ - inventory_hostname in groups['palimpsest']
26
+ - palimpsest_git_dir_stat.stat.exists
27
+
28
+ - name: Source Build | Fail if existing Palimpsest checkout is dirty
29
+ ansible.builtin.assert:
30
+ that:
31
+ - palimpsest_existing_git_status.stdout | trim | length == 0
32
+ fail_msg: "Existing Palimpsest source checkout at {{ palimpsest_source_dir }} is dirty (uncommitted changes present)"
33
+ when:
34
+ - inventory_hostname in groups['palimpsest']
35
+ - palimpsest_git_dir_stat.stat.exists
36
+
37
+ - name: Source Build | Check HEAD SHA of existing checkout
38
+ become: true
39
+ ansible.builtin.command:
40
+ cmd: "git rev-parse HEAD"
41
+ chdir: "{{ palimpsest_source_dir }}"
42
+ register: palimpsest_existing_head_sha
43
+ changed_when: false
44
+ when:
45
+ - inventory_hostname in groups['palimpsest']
46
+ - palimpsest_git_dir_stat.stat.exists
47
+
48
+ - name: Source Build | Fail if existing Palimpsest checkout HEAD does not match palimpsest_source_version
49
+ ansible.builtin.assert:
50
+ that:
51
+ - palimpsest_existing_head_sha.stdout | trim == palimpsest_source_version
52
+ fail_msg: "Existing Palimpsest checkout HEAD ({{ palimpsest_existing_head_sha.stdout | default('') }}) does not match required version ({{ palimpsest_source_version }})"
53
+ when:
54
+ - inventory_hostname in groups['palimpsest']
55
+ - palimpsest_git_dir_stat.stat.exists
56
+
57
+ - name: Source Build | Checkout Palimpsest source repository when absent
58
+ become: true
59
+ ansible.builtin.git:
60
+ repo: "{{ palimpsest_source_repo }}"
61
+ dest: "{{ palimpsest_source_dir }}"
62
+ version: "{{ palimpsest_source_version }}"
63
+ force: false
64
+ when:
65
+ - inventory_hostname in groups['palimpsest']
66
+ - not palimpsest_git_dir_stat.stat.exists
67
+
68
+ - name: Source Build | Verify checked out HEAD SHA
69
+ become: true
70
+ ansible.builtin.command:
71
+ cmd: "git rev-parse HEAD"
72
+ chdir: "{{ palimpsest_source_dir }}"
73
+ register: palimpsest_head_sha
74
+ changed_when: false
75
+ when: inventory_hostname in groups['palimpsest']
76
+
77
+ - name: Source Build | Fail if checked out HEAD does not match palimpsest_source_version
78
+ ansible.builtin.assert:
79
+ that:
80
+ - palimpsest_head_sha.stdout | trim == palimpsest_source_version
81
+ fail_msg: "Palimpsest source checkout HEAD ({{ palimpsest_head_sha.stdout | default('') }}) does not match expected version ({{ palimpsest_source_version }})"
82
+ when: inventory_hostname in groups['palimpsest']
83
+
84
+ - name: Source Build | Build local Palimpsest images
85
+ become: true
86
+ community.docker.docker_image:
87
+ name: "afterglow-local/{{ item }}:{{ palimpsest_source_version | truncate(12, True, '') }}"
88
+ build:
89
+ path: "{{ palimpsest_source_dir }}"
90
+ dockerfile: "docker/hub/Dockerfile"
91
+ target: "{{ item }}"
92
+ source: build
93
+ force_source: false
94
+ loop:
95
+ - palimpsest-hub-api
96
+ - palimpsest-hub-worker
97
+ when: inventory_hostname in groups['palimpsest']