|
1 | 1 | use crate::config::AppConfig; |
2 | | -use crate::parser::{Vendor, XmlParser}; |
| 2 | +use crate::parser::{Vendor, VcsaPackage, XmlParser}; |
3 | 3 | use crate::process::{FileType, ProcessManager, Source}; |
4 | 4 | use crate::verify::VerificationManager; |
5 | 5 | use anyhow::Result; |
@@ -454,6 +454,24 @@ impl Downloader { |
454 | 454 | Err(e) => warn!("Error reading manifest file: {}", e), |
455 | 455 | } |
456 | 456 | } |
| 457 | + |
| 458 | + // rpm-manifest.json lists additional files that are NOT referenced in |
| 459 | + // manifest-latest.xml - notably container image blobs (.blob) and |
| 460 | + // container manifests (.manifest). Without these, `software-packages |
| 461 | + // stage --iso` fails on the VCSA because the stage step can't find |
| 462 | + // the container layers referenced by the patch metadata. |
| 463 | + if file.ends_with("rpm-manifest.json") { |
| 464 | + match tokio::fs::read_to_string(&target_path).await { |
| 465 | + Ok(json_content) => { |
| 466 | + if let Err(e) = this.process_vcsa_rpm_manifest_json(&json_content, &version, &processed_base_url).await { |
| 467 | + warn!("Error processing rpm-manifest.json: {}", e); |
| 468 | + } else { |
| 469 | + info!("Successfully processed VCSA rpm-manifest.json"); |
| 470 | + } |
| 471 | + } |
| 472 | + Err(e) => warn!("Error reading rpm-manifest.json file: {}", e), |
| 473 | + } |
| 474 | + } |
457 | 475 | } |
458 | 476 | } else { |
459 | 477 | warn!("VCSA source missing version or files: {}", url); |
@@ -1482,21 +1500,45 @@ impl Downloader { |
1482 | 1500 | } |
1483 | 1501 |
|
1484 | 1502 | async fn process_vcsa_manifest(&self, content: &str, version: &str, base_url: &str) -> Result<()> { |
1485 | | - let start_time = std::time::Instant::now(); |
1486 | 1503 | let packages = self.xml_parser.parse_vcsa_packages(content)?; |
1487 | | - info!("Found {} packages in VCSA manifest for version {}", packages.len(), version); |
| 1504 | + info!("Found {} packages in VCSA manifest-latest.xml for version {}", packages.len(), version); |
| 1505 | + self.queue_vcsa_packages(packages, version, base_url, "manifest-latest.xml").await |
| 1506 | + } |
| 1507 | + |
| 1508 | + /// Parse VCSA rpm-manifest.json and queue any files it lists that aren't |
| 1509 | + /// already covered by manifest-latest.xml (blobs, container manifests, and |
| 1510 | + /// any extra RPMs listed only in the JSON). |
| 1511 | + async fn process_vcsa_rpm_manifest_json(&self, content: &str, version: &str, base_url: &str) -> Result<()> { |
| 1512 | + let packages = self.xml_parser.parse_vcsa_rpm_manifest_json(content)?; |
| 1513 | + info!("Found {} packages in VCSA rpm-manifest.json for version {}", packages.len(), version); |
| 1514 | + self.queue_vcsa_packages(packages, version, base_url, "rpm-manifest.json").await |
| 1515 | + } |
| 1516 | + |
| 1517 | + /// Shared back-end for processing a list of VcsaPackage entries: builds URLs, |
| 1518 | + /// skips already-processed / already-valid files, and spawns concurrent |
| 1519 | + /// download tasks. |
| 1520 | + async fn queue_vcsa_packages( |
| 1521 | + &self, |
| 1522 | + packages: Vec<VcsaPackage>, |
| 1523 | + version: &str, |
| 1524 | + base_url: &str, |
| 1525 | + source_label: &str, |
| 1526 | + ) -> Result<()> { |
| 1527 | + let start_time = std::time::Instant::now(); |
1488 | 1528 |
|
1489 | 1529 | let mut tasks = Vec::new(); |
1490 | 1530 | let max_concurrent = self.verifier.config.verification.max_concurrent_files(); |
1491 | 1531 | let file_semaphore = Arc::new(Semaphore::new(max_concurrent)); |
1492 | 1532 |
|
1493 | 1533 | for package in packages { |
1494 | 1534 | let location = package.location.clone(); |
| 1535 | + // pkg_info is only used for log output - use the filename with the |
| 1536 | + // package-pool/ prefix stripped, keeping the file extension so that |
| 1537 | + // non-RPM entries (like .blob / .manifest) are still readable in logs. |
1495 | 1538 | let pkg_info = location |
1496 | 1539 | .strip_prefix("package-pool/") |
1497 | | - .and_then(|s| s.strip_suffix(".rpm")) |
1498 | 1540 | .unwrap_or(&location); |
1499 | | - |
| 1541 | + |
1500 | 1542 | let url = format!( |
1501 | 1543 | "{}/{}/{}", |
1502 | 1544 | base_url, |
@@ -1598,8 +1640,8 @@ impl Downloader { |
1598 | 1640 | } |
1599 | 1641 |
|
1600 | 1642 | let duration = start_time.elapsed(); |
1601 | | - info!("VCSA manifest processing completed in {:?}: {}/{} packages successful, {} errors", |
1602 | | - duration, completed, total_tasks, errors); |
| 1643 | + info!("VCSA {} processing completed in {:?}: {}/{} packages successful, {} errors", |
| 1644 | + source_label, duration, completed, total_tasks, errors); |
1603 | 1645 |
|
1604 | 1646 | Ok(()) |
1605 | 1647 | } |
|
0 commit comments