fix(openwrt): use full opkg path and pre-check availability
`channel.exec()` doesn't source the shell profile, so PATH may not
include /usr/bin on some routers. Using /usr/bin/opkg explicitly
avoids exit-127 surprises. Added opkg_check() to give a clear error
("firmware may not support package management") before attempting
opkg_update, rather than a confusing "command not found" exit code.
Also split the BusyBox-hostile `grep -v 'all\|noarch'` into two
separate greps for the arch-detection fallback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4c56e1bb96
commit
bc1ec9aa3e
@ -4,31 +4,43 @@ use tracing::info;
|
||||
use crate::Router;
|
||||
|
||||
impl Router {
|
||||
/// Verify opkg is available, returning a clear error if not.
|
||||
pub fn opkg_check(&self) -> Result<()> {
|
||||
let (_, code) = self.run("test -x /usr/bin/opkg")?;
|
||||
if code != 0 {
|
||||
anyhow::bail!(
|
||||
"opkg not found at /usr/bin/opkg — this router's firmware may not \
|
||||
support package management (TollGate requires a standard OpenWrt build)"
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `opkg update` — refresh package lists.
|
||||
pub fn opkg_update(&self) -> Result<()> {
|
||||
info!("[{}] opkg update", self.host);
|
||||
self.run_ok("opkg update")?;
|
||||
self.run_ok("/usr/bin/opkg update")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Install a package, skipping if already installed.
|
||||
pub fn opkg_install(&self, package: &str) -> Result<()> {
|
||||
// Check if already installed to avoid unnecessary network traffic.
|
||||
let (_, code) = self.run(&format!("opkg list-installed | grep -q '^{} '", package))?;
|
||||
let (_, code) = self.run(&format!("/usr/bin/opkg list-installed | grep -q '^{} '", package))?;
|
||||
if code == 0 {
|
||||
info!("[{}] {} already installed", self.host, package);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
info!("[{}] opkg install {}", self.host, package);
|
||||
self.run_ok(&format!("opkg install {}", package))?;
|
||||
self.run_ok(&format!("/usr/bin/opkg install {}", package))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove a package.
|
||||
pub fn opkg_remove(&self, package: &str) -> Result<()> {
|
||||
info!("[{}] opkg remove {}", self.host, package);
|
||||
self.run_ok(&format!("opkg remove {}", package))?;
|
||||
self.run_ok(&format!("/usr/bin/opkg remove {}", package))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ pub fn install_tollgate(router: &Router) -> Result<()> {
|
||||
|
||||
// Package not in any feed — download the .ipk directly.
|
||||
let arch = router
|
||||
.run_ok("opkg print-architecture | grep -v 'all\\|noarch' | tail -1 | awk '{print $2}'")?;
|
||||
.run_ok("/usr/bin/opkg print-architecture | grep -v all | grep -v noarch | tail -1 | awk '{print $2}'")?;
|
||||
let arch = arch.trim();
|
||||
|
||||
let url = ipk_url(arch).ok_or_else(|| {
|
||||
@ -50,7 +50,7 @@ pub fn install_tollgate(router: &Router) -> Result<()> {
|
||||
router.run_ok(&format!("wget -O /tmp/tollgate.ipk '{}'", url))?;
|
||||
|
||||
// Capture stderr too — BusyBox opkg exits 0 even on "Cannot install" failures.
|
||||
let (out, _code) = router.run("opkg install --force-depends /tmp/tollgate.ipk 2>&1")?;
|
||||
let (out, _code) = router.run("/usr/bin/opkg install --force-depends /tmp/tollgate.ipk 2>&1")?;
|
||||
router.run_ok("rm -f /tmp/tollgate.ipk")?;
|
||||
|
||||
if out.contains("Cannot install") || out.contains("errors encountered") {
|
||||
|
||||
@ -19,6 +19,7 @@ use crate::Router;
|
||||
pub async fn provision(router: &Router, config: &TollGateConfig) -> Result<()> {
|
||||
info!("[{}] Starting TollGate provisioning", router.host);
|
||||
|
||||
router.opkg_check()?;
|
||||
router.opkg_update()?;
|
||||
install_tollgate(router)?;
|
||||
config::apply(router, config)?;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user