The container-met.py script now supports registering containers for multiple architectures (x86_64 and ARM64) by accepting an optional ARM64 tarball parameter. This enables HySDS workers to automatically download and load the correct container image based on their architecture.
✅ Default behavior unchanged: If ARM64 tarball is not provided, registers x86_64 only (existing behavior)
✅ Existing invocations work: No changes needed to existing CI/CD pipelines
✅ Legacy url field preserved: Single URL field maintained for backward compatibility
./container-met.py \
container-name:tag \
1.0.0 \
container-name-tag.tar.gz \
s3://bucket \
sha256:digest \
http://mozart-rest-urlWhat This Does:
- Uploads x86_64 tarball to storage (S3/local)
- Registers container metadata with Mozart
- Sets
urlfield to x86_64 tarball URL - Sets
urlsfield with x86_64 mappings only
./container-met.py \
container-name:tag \
1.0.0 \
container-name-tag.tar.gz \
s3://bucket \
sha256:digest \
http://mozart-rest-url \
container-name-tag-arm64.tar.gzWhat This Does:
- Uploads both x86_64 and ARM64 tarballs to storage
- Registers container metadata with Mozart
- Sets
urlfield to x86_64 tarball URL (backward compatibility) - Sets
urlsfield with architecture-specific mappings:x86_64/amd64→ x86_64 tarball URLarm64/aarch64→ ARM64 tarball URL
container-met.py <ident> <version> <product> <repo> <digest> <mozart_url> [product_arm64]| Argument | Required | Description | Example |
|---|---|---|---|
ident |
Yes | Container name and tag | container-name:tag |
version |
Yes | Container version | 1.0.0 |
product |
Yes | x86_64 tarball filename | container-name-tag.tar.gz |
repo |
Yes | Storage URL (S3 or local) | s3://bucket or /path/to/storage |
digest |
Yes | Container image digest | sha256:abc123... |
mozart_url |
Yes | Mozart REST API URL | http://mozart:8888/api/v0.2 |
product_arm64 |
Optional | ARM64 tarball filename | container-name-tag-arm64.tar.gz |
Single Architecture (x86_64 only):
{
"name": "container-name:tag",
"version": "1.0.0",
"url": "s3://bucket/container-name-tag.tar.gz",
"urls": "{
\"x86_64\": \"s3://bucket/container-name-tag.tar.gz\",
\"amd64\": \"s3://bucket/container-name-tag.tar.gz\"
}",
"digest": "sha256:...",
"resource": "container"
}Multi-Architecture (x86_64 + ARM64):
{
"name": "container-name:tag",
"version": "1.0.0",
"url": "s3://bucket/container-name-tag.tar.gz",
"urls": "{
\"x86_64\": \"s3://bucket/container-name-tag.tar.gz\",
\"amd64\": \"s3://bucket/container-name-tag.tar.gz\",
\"arm64\": \"s3://bucket/container-name-tag-arm64.tar.gz\",
\"aarch64\": \"s3://bucket/container-name-tag-arm64.tar.gz\"
}",
"digest": "sha256:...",
"resource": "container"
}Key Points:
urlfield: Single URL for backward compatibility (always x86_64)urlsfield: JSON string containing architecture-specific URL mappings- Both
x86_64andamd64map to the same x86_64 tarball - Both
arm64andaarch64map to the same ARM64 tarball
// Existing code - no changes needed
sh """
IMAGE="container-\${REPO}:${TAG}"
TARBALL="\${IMAGE//:\//_}.tar.gz"
DIGEST=\$(docker inspect --format='{{.Id}}' \${IMAGE})
~/verdi/ops/container-builder/container-met.py \\
\${IMAGE} \\
${TAG} \\
\${TARBALL} \\
\${STORAGE_URL} \\
\${DIGEST} \\
\${MOZART_REST_URL}
"""sh """
IMAGE="container-\${REPO}:${TAG}"
TARBALL_X86="\${IMAGE//:\//_}.tar.gz"
TARBALL_ARM64="\${IMAGE//:\//_}-arm64.tar.gz"
DIGEST=\$(docker inspect --format='{{.Id}}' \${IMAGE})
# Register both architectures
~/verdi/ops/container-builder/container-met.py \\
\${IMAGE} \\
${TAG} \\
\${TARBALL_X86} \\
\${STORAGE_URL} \\
\${DIGEST} \\
\${MOZART_REST_URL} \\
\${TARBALL_ARM64}
"""stage('Build and Register Multi-Arch Container') {
steps {
sh """
IMAGE="container-\${REPO}:${TAG}"
TARBALL_X86="\${IMAGE//:\//_}.tar.gz"
TARBALL_ARM64="\${IMAGE//:\//_}-arm64.tar.gz"
# Build x86_64 image
docker buildx build --platform linux/amd64 -t \${IMAGE} --load .
docker save \${IMAGE} | gzip > \${TARBALL_X86}
# Build ARM64 image
docker buildx build --platform linux/arm64 -t \${IMAGE} --load .
docker save \${IMAGE} | gzip > \${TARBALL_ARM64}
# Get digest from x86_64 image
DIGEST=\$(docker inspect --format='{{.Id}}' \${IMAGE})
# Register both architectures
~/verdi/ops/container-builder/container-met.py \\
\${IMAGE} \\
${TAG} \\
\${TARBALL_X86} \\
\${STORAGE_URL} \\
\${DIGEST} \\
\${MOZART_REST_URL} \\
\${TARBALL_ARM64}
"""
}
}- x86_64 tarball: Always uploaded to storage (required)
- ARM64 tarball: Uploaded only if provided (optional)
- Storage: Uses
osaka.main.put()to upload to S3 or local storage
- Constructs metadata dict with name, version, url, digest, resource
- Adds
urlsfield as JSON string with architecture mappings - POSTs to Mozart API at
/container/addendpoint - Mozart stores in Elasticsearch containers index
When a HySDS worker needs to load a container:
- Worker reads
container_image_urlsfrom job metadata - Detects current architecture using
platform.machine() - Selects appropriate URL from
urlsmapping - Downloads and loads architecture-specific tarball
- Falls back to
urlfield ifurlsnot available (backward compatibility)
x86_64 tarball (no suffix for backward compatibility):
container-name-tag.tar.gz
ARM64 tarball (with -arm64 suffix):
container-name-tag-arm64.tar.gz
- Python 3.x
requestslibraryosakalibrary (for S3/storage uploads)- Mozart REST API accessible
- Mozart: Updated API endpoints to accept
urlsparameter - HySDS: Updated container loading logic to use architecture-specific URLs
- hysds_commons: Updated job resolution to pass
container_image_urls - Workers: Must be running updated HySDS code
Cause: Missing required arguments.
Solution: Provide all 6 required arguments. The 7th (ARM64 tarball) is optional.
Cause: Invalid S3 credentials or permissions.
Solution: Ensure AWS credentials are configured and have write access to the bucket.
Cause: Mozart REST API is unreachable or returns error.
Solution:
- Verify Mozart URL is correct and accessible
- Check Mozart logs for API errors
- Ensure Mozart API endpoints are updated to accept
urlsparameter
Cause: Worker is running old HySDS code without multi-arch support.
Solution: Update HySDS on workers and restart celery workers:
cd /home/ops/verdi/ops/hysds
git pull
pip install -e .
supervisorctl restart allCause: Mozart API not updated to handle urls parameter.
Solution: Deploy updated Mozart code with multi-architecture support.
No changes required! The script is fully backward compatible. Existing 6-argument invocations continue to work.
- Build ARM64 tarball (using Docker Buildx or native ARM64 host)
- Add ARM64 tarball as 7th argument to
container-met.py - Script automatically uploads both tarballs and registers with architecture mappings
Phase 1: Update Core Components
- Deploy updated
container-builder(this repo) - Deploy updated
mozartwithurlsparameter support - Deploy updated
hysdswith architecture-aware container loading - Deploy updated
hysds_commonswithcontainer_image_urlssupport
Phase 2: Update Workers
- Update HySDS code on all workers
- Restart celery workers to load new code
- Verify workers can read architecture from
platform.machine()
Phase 3: Register Multi-Arch Containers
- Build both x86_64 and ARM64 tarballs
- Register using updated
container-met.pywith both tarballs - Workers automatically select correct architecture
Check that multi-arch metadata is registered correctly:
curl -X GET "http://mozart:9200/containers/_doc/container-name:tag?pretty"Should show both url and urls fields in the response.