Skip to content

Commit

Permalink
Feature/remove bollard (#2396)
Browse files Browse the repository at this point in the history
* wip

* remove bollard, add podman feature

* fix error message parsing

* fix subcommand

* fix typo

* use com.docker.network.bridge.name for podman

* fix parse error

* handle podman network interface nuance

* add libyajl2

* use podman repos

* manually add criu

* do not manually require criu

* remove docker images during cleanup stage

* force removal

* increase img size

* Update startos-iso.yaml

* don't remove docker
  • Loading branch information
dr-bonez authored Aug 25, 2023
1 parent d6eaf8d commit e378659
Show file tree
Hide file tree
Showing 19 changed files with 400 additions and 273 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/startos-iso.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ on:
- dev
- unstable
- dev-unstable
- podman
- dev-podman
- dev-unstable-podman
runner:
type: choice
description: Runner
Expand Down Expand Up @@ -39,7 +42,7 @@ on:

env:
NODEJS_VERSION: "18.15.0"
ENVIRONMENT: '${{ fromJson(format(''["{0}", ""]'', github.event.inputs.environment || ''dev''))[github.event.inputs.environment == ''NONE''] }}'
ENVIRONMENT: '${{ fromJson(format(''["{0}", ""]'', github.event.inputs.environment || ''dev-podman''))[github.event.inputs.environment == ''NONE''] }}'

jobs:
all:
Expand Down Expand Up @@ -139,6 +142,7 @@ jobs:
with:
repository: Start9Labs/startos-image-recipes
path: startos-image-recipes
ref: feature/podman

- name: Install dependencies
run: |
Expand Down Expand Up @@ -166,7 +170,7 @@ jobs:

- run: "mv embassy-os-deb/embassyos_0.3.x-1_*.deb startos-image-recipes/overlays/deb/"

- run: "rm -rf embassy-os-deb ${{ steps.npm-cache-dir.outputs.dir }} $HOME/.cargo"
- run: "sudo rm -rf embassy-os-deb ${{ steps.npm-cache-dir.outputs.dir }} $HOME/.cargo"

- name: Run iso build
working-directory: startos-image-recipes
Expand Down
1 change: 0 additions & 1 deletion backend/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ avahi-alias = ["avahi"]
cli = []
sdk = []
daemon = []
podman = []

[dependencies]
aes = { version = "0.7.5", features = ["ctr"] }
Expand All @@ -50,7 +51,6 @@ base32 = "0.4.0"
base64 = "0.13.0"
base64ct = "1.5.1"
basic-cookies = "0.1.4"
bollard = "0.13.0"
bytes = "1"
chrono = { version = "0.4.19", features = ["serde"] }
clap = "3.2.8"
Expand Down
5 changes: 4 additions & 1 deletion backend/build-prod.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ alias 'rust-musl-builder'='docker run $USE_TTY --rm -e "OS_ARCH=$OS_ARCH" -v "$H

cd ..
FLAGS=""
if [[ "$ENVIRONMENT" =~ (^|-)podman($|-) ]]; then
FLAGS="podman,$FLAGS"
fi
if [[ "$ENVIRONMENT" =~ (^|-)unstable($|-) ]]; then
FLAGS="unstable,$FLAGS"
fi
Expand Down Expand Up @@ -56,7 +59,7 @@ else
fi
for ARCH in x86_64 aarch64
do
rust-musl-builder sh -c "(cd libs && cargo build --release --features $FLAGS --locked --bin embassy_container_init)"
rust-musl-builder sh -c "(cd libs && cargo build --release --locked --bin embassy_container_init)"
if test $? -ne 0; then
fail=true
fi
Expand Down
7 changes: 0 additions & 7 deletions backend/src/context/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;

use bollard::Docker;
use helpers::to_tmp_path;
use josekit::jwk::Jwk;
use patch_db::json_ptr::JsonPointer;
Expand Down Expand Up @@ -111,7 +109,6 @@ pub struct RpcContextSeed {
pub db: PatchDb,
pub secret_store: PgPool,
pub account: RwLock<AccountInfo>,
pub docker: Docker,
pub net_controller: Arc<NetController>,
pub managers: ManagerMap,
pub metrics_cache: RwLock<Option<crate::system::Metrics>>,
Expand Down Expand Up @@ -189,9 +186,6 @@ impl RpcContext {
let account = AccountInfo::load(&secret_store).await?;
let db = base.db(&account).await?;
tracing::info!("Opened PatchDB");
let mut docker = Docker::connect_with_unix_defaults()?;
docker.set_timeout(Duration::from_secs(600));
tracing::info!("Connected to Docker");
let net_controller = Arc::new(
NetController::init(
base.tor_control
Expand Down Expand Up @@ -225,7 +219,6 @@ impl RpcContext {
db,
secret_store,
account: RwLock::new(account),
docker,
net_controller,
managers,
metrics_cache,
Expand Down
84 changes: 45 additions & 39 deletions backend/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::install::PKG_ARCHIVE_DIR;
use crate::middleware::auth::LOCAL_AUTH_COOKIE_PATH;
use crate::sound::BEP;
use crate::system::time;
use crate::util::docker::{create_bridge_network, CONTAINER_DATADIR, CONTAINER_TOOL};
use crate::util::Invoke;
use crate::{Error, ARCH};

Expand Down Expand Up @@ -289,51 +290,56 @@ pub async fn init(cfg: &RpcContextConfig) -> Result<InitResult, Error> {
if tokio::fs::metadata(&tmp_dir).await.is_err() {
tokio::fs::create_dir_all(&tmp_dir).await?;
}
let tmp_docker = cfg.datadir().join("package-data/tmp/docker");
let tmp_docker = cfg
.datadir()
.join(format!("package-data/tmp/{CONTAINER_TOOL}"));
let tmp_docker_exists = tokio::fs::metadata(&tmp_docker).await.is_ok();
if should_rebuild && tmp_docker_exists {
tokio::fs::remove_dir_all(&tmp_docker).await?;
}
Command::new("systemctl")
.arg("stop")
.arg("docker")
.invoke(crate::ErrorKind::Docker)
.await?;
crate::disk::mount::util::bind(&tmp_docker, "/var/lib/docker", false).await?;
Command::new("systemctl")
.arg("reset-failed")
.arg("docker")
.invoke(crate::ErrorKind::Docker)
.await?;
Command::new("systemctl")
.arg("start")
.arg("docker")
.invoke(crate::ErrorKind::Docker)
.await?;
if CONTAINER_TOOL == "docker" {
Command::new("systemctl")
.arg("stop")
.arg("docker")
.invoke(crate::ErrorKind::Docker)
.await?;
}
crate::disk::mount::util::bind(&tmp_docker, CONTAINER_DATADIR, false).await?;

if CONTAINER_TOOL == "docker" {
Command::new("systemctl")
.arg("reset-failed")
.arg("docker")
.invoke(crate::ErrorKind::Docker)
.await?;
Command::new("systemctl")
.arg("start")
.arg("docker")
.invoke(crate::ErrorKind::Docker)
.await?;
}
tracing::info!("Mounted Docker Data");

if should_rebuild || !tmp_docker_exists {
tracing::info!("Creating Docker Network");
bollard::Docker::connect_with_unix_defaults()?
.create_network(bollard::network::CreateNetworkOptions {
name: "start9",
driver: "bridge",
ipam: bollard::models::Ipam {
config: Some(vec![bollard::models::IpamConfig {
subnet: Some("172.18.0.1/24".into()),
..Default::default()
}]),
..Default::default()
},
options: {
let mut m = HashMap::new();
m.insert("com.docker.network.bridge.name", "br-start9");
m
},
..Default::default()
})
if CONTAINER_TOOL == "podman" {
Command::new("podman")
.arg("run")
.arg("-d")
.arg("--rm")
.arg("--network=start9")
.arg("--name=netdummy")
.arg("start9/x_system/utils:latest")
.arg("sleep")
.arg("infinity")
.invoke(crate::ErrorKind::Docker)
.await?;
tracing::info!("Created Docker Network");
}

if should_rebuild || !tmp_docker_exists {
if CONTAINER_TOOL == "docker" {
tracing::info!("Creating Docker Network");
create_bridge_network("start9", "172.18.0.1/24", "br-start9").await?;
tracing::info!("Created Docker Network");
}

tracing::info!("Loading System Docker Images");
crate::install::load_images("/usr/lib/embassy/system-images").await?;
Expand All @@ -345,7 +351,7 @@ pub async fn init(cfg: &RpcContextConfig) -> Result<InitResult, Error> {
}

tracing::info!("Enabling Docker QEMU Emulation");
Command::new("docker")
Command::new(CONTAINER_TOOL)
.arg("run")
.arg("--privileged")
.arg("--rm")
Expand Down
46 changes: 5 additions & 41 deletions backend/src/install/cleanup.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;

use bollard::image::{ListImagesOptions, RemoveImageOptions};
use patch_db::{DbHandle, LockReceipt, LockTargetId, LockType, PatchDbHandle, Verifier};
use sqlx::{Executor, Postgres};
use tracing::instrument;
Expand Down Expand Up @@ -104,46 +102,12 @@ pub async fn cleanup(ctx: &RpcContext, id: &PackageId, version: &Version) -> Res
let mut errors = ErrorCollection::new();
ctx.managers.remove(&(id.clone(), version.clone())).await;
// docker images start9/$APP_ID/*:$VERSION -q | xargs docker rmi
let images = ctx
.docker
.list_images(Some(ListImagesOptions {
all: false,
filters: {
let mut f = HashMap::new();
f.insert(
"reference".to_owned(),
vec![format!("start9/{}/*:{}", id, version)],
);
f
},
digests: false,
}))
.await
.apply(|res| errors.handle(res));
let images = crate::util::docker::images_for(id, version).await?;
errors.extend(
futures::future::join_all(
images
.into_iter()
.flatten()
.flat_map(|image| image.repo_tags)
.filter(|tag| {
tag.starts_with(&format!("start9/{}/", id))
&& tag.ends_with(&format!(":{}", version))
})
.map(|tag| async {
let tag = tag; // move into future
ctx.docker
.remove_image(
&tag,
Some(RemoveImageOptions {
force: true,
noprune: false,
}),
None,
)
.await
}),
)
futures::future::join_all(images.into_iter().map(|sha| async {
let sha = sha; // move into future
crate::util::docker::remove_image(&sha).await
}))
.await,
);
let pkg_archive_dir = ctx
Expand Down
5 changes: 3 additions & 2 deletions backend/src/install/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use crate::notifications::NotificationLevel;
use crate::s9pk::manifest::{Manifest, PackageId};
use crate::s9pk::reader::S9pkReader;
use crate::status::{MainStatus, Status};
use crate::util::docker::CONTAINER_TOOL;
use crate::util::io::{copy_and_shutdown, response_to_reader};
use crate::util::serde::{display_serializable, Port};
use crate::util::{display_none, AsyncFileExt, Version};
Expand Down Expand Up @@ -1087,7 +1088,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin + Send + Sync>(
tracing::info!("Install {}@{}: Unpacking Docker Images", pkg_id, version);
progress
.track_read_during(progress_model.clone(), &ctx.db, || async {
let mut load = Command::new("docker")
let mut load = Command::new(CONTAINER_TOOL)
.arg("load")
.stdin(Stdio::piped())
.stderr(Stdio::piped())
Expand Down Expand Up @@ -1467,7 +1468,7 @@ pub fn load_images<'a, P: AsRef<Path> + 'a + Send + Sync>(
let path = entry.path();
let ext = path.extension().and_then(|ext| ext.to_str());
if ext == Some("tar") || ext == Some("s9pk") {
let mut load = Command::new("docker")
let mut load = Command::new(CONTAINER_TOOL)
.arg("load")
.stdin(Stdio::piped())
.stderr(Stdio::piped())
Expand Down
55 changes: 13 additions & 42 deletions backend/src/manager/manager_seed.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use bollard::container::{StopContainerOptions, WaitContainerOptions};
use models::ErrorKind;
use tokio_stream::StreamExt;

use crate::context::RpcContext;
use crate::s9pk::manifest::Manifest;
use crate::util::docker::stop_container;
use crate::Error;

/// This is helper structure for a service, the seed of the data that is needed for the manager_container
Expand All @@ -14,50 +15,20 @@ pub struct ManagerSeed {

impl ManagerSeed {
pub async fn stop_container(&self) -> Result<(), Error> {
match self
.ctx
.docker
.stop_container(
&self.container_name,
Some(StopContainerOptions {
t: self
.manifest
.containers
.as_ref()
.and_then(|c| c.main.sigterm_timeout)
.map(|d| d.as_secs())
.unwrap_or(30) as i64,
}),
)
.await
match stop_container(
&self.container_name,
self.manifest
.containers
.as_ref()
.and_then(|c| c.main.sigterm_timeout)
.map(|d| *d),
None,
)
.await
{
Err(bollard::errors::Error::DockerResponseServerError {
status_code: 404, // NOT FOUND
..
})
| Err(bollard::errors::Error::DockerResponseServerError {
status_code: 409, // CONFLICT
..
})
| Err(bollard::errors::Error::DockerResponseServerError {
status_code: 304, // NOT MODIFIED
..
}) => (), // Already stopped
Err(e) if e.kind == ErrorKind::NotFound => (), // Already stopped
a => a?,
}

// Wait for the container to stop
{
let mut waiting = self.ctx.docker.wait_container(
&self.container_name,
Some(WaitContainerOptions {
condition: "not-running",
}),
);
while let Some(_) = waiting.next().await {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
}
}
Ok(())
}
}
Loading

0 comments on commit e378659

Please sign in to comment.