Skip to content

Commit

Permalink
apiserver: new /actions/reboot endpoint
Browse files Browse the repository at this point in the history
Adds new API path: `/actions/reboot` for initiating reboots.
  • Loading branch information
etungsten committed Jun 2, 2020
1 parent b916fc3 commit 902bb55
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
7 changes: 7 additions & 0 deletions sources/api/apiserver/src/server/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use nix::unistd::Gid;
use snafu::Snafu;
use std::io;
use std::path::PathBuf;
use std::string::String;

// We want server (router/handler) and controller errors together so it's easy to define response
// error codes for all the high-level types of errors that could happen during a request.
Expand Down Expand Up @@ -115,6 +116,12 @@ pub enum Error {

#[snafu(display("Unable to send input to config applier: {}", source))]
ConfigApplierWrite { source: io::Error },

#[snafu(display("Unable to start shutdown: {}", source))]
Shutdown { source: io::Error },

#[snafu(display("Failed to reboot, exit code: {}, stderr: {}", exit_code, String::from_utf8_lossy(stderr)))]
Reboot { exit_code: i32, stderr: Vec<u8> },
}

pub type Result<T> = std::result::Result<T, Error>;
25 changes: 25 additions & 0 deletions sources/api/apiserver/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use std::env;
use std::fs::set_permissions;
use std::fs::Permissions;
use std::os::unix::fs::PermissionsExt;
use std::os::unix::process::ExitStatusExt;
use std::path::Path;
use std::process::Command;
use std::sync;
Expand Down Expand Up @@ -115,6 +116,7 @@ where
web::scope("/configuration-files")
.route("", web::get().to(get_configuration_files)),
)
.service(web::scope("/actions").route("/reboot", web::post().to(reboot)))
})
.workers(threads)
.bind_uds(socket_path.as_ref())
Expand Down Expand Up @@ -352,6 +354,27 @@ async fn get_configuration_files(
Ok(ConfigurationFilesResponse(resp))
}

/// Reboots the machine
async fn reboot() -> Result<HttpResponse> {
debug!("Rebooting now");
let output = Command::new("/sbin/shutdown")
.arg("-r")
.arg("now")
.output()
.context(error::Shutdown)?;
ensure!(
output.status.success(),
error::Reboot {
exit_code: match output.status.code() {
Some(code) => code,
None => output.status.signal().unwrap_or(1),
},
stderr: output.stderr
}
);
Ok(HttpResponse::NoContent().finish())
}

// =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^=

// Helpers for handler methods called by the router
Expand Down Expand Up @@ -408,6 +431,8 @@ impl ResponseError for error::Error {
SetPermissions { .. } => HttpResponse::InternalServerError(),
SetGroup { .. } => HttpResponse::InternalServerError(),
ReleaseData { .. } => HttpResponse::InternalServerError(),
Shutdown { .. } => HttpResponse::InternalServerError(),
Reboot { .. } => HttpResponse::InternalServerError(),
}
// Include the error message in the response, and for all error types. The Bottlerocket
// API is only exposed locally, and only on the host filesystem and to authorized
Expand Down
10 changes: 10 additions & 0 deletions sources/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,13 @@ paths:
$ref: "ConfigurationFiles"
500:
description: "Server error"

/actions/reboot:
post:
summary: "Reboot"
operationId: "reboot"
responses:
204:
description: "Reboot requested"
500:
description: "Server error"

0 comments on commit 902bb55

Please sign in to comment.