http: api: implement vmm.ping

vmm.ping will help to check if http API server is up and
running.

This also removes the vmm.info endpoint.

Signed-off-by: Jose Carlos Venegas Munoz <jose.carlos.venegas.munoz@intel.com>
This commit is contained in:
Jose Carlos Venegas Munoz 2019-11-04 18:06:45 +00:00 committed by Sebastien Boeuf
parent 348a1bc30e
commit a518651402
6 changed files with 81 additions and 7 deletions

View File

@ -2722,6 +2722,9 @@ mod tests {
thread::sleep(std::time::Duration::new(1, 0));
// Verify API server is running
curl_command(&api_socket, "GET", "http://localhost/api/v1/vmm.ping", None);
// Create the VM first
let cpu_count: u8 = 4;
let http_body = guest.api_create_body(cpu_count);
@ -2778,6 +2781,9 @@ mod tests {
thread::sleep(std::time::Duration::new(1, 0));
// Verify API server is running
curl_command(&api_socket, "GET", "http://localhost/api/v1/vmm.ping", None);
// Create the VM first
let cpu_count: u8 = 4;
let http_body = guest.api_create_body(cpu_count);

View File

@ -3,7 +3,7 @@
// SPDX-License-Identifier: Apache-2.0
//
use crate::api::http_endpoint::{VmActionHandler, VmCreate, VmInfo, VmmShutdown};
use crate::api::http_endpoint::{VmActionHandler, VmCreate, VmInfo, VmmPing, VmmShutdown};
use crate::api::{ApiRequest, VmAction};
use crate::{Error, Result};
use micro_http::{HttpServer, MediaType, Request, Response, StatusCode, Version};
@ -58,6 +58,7 @@ lazy_static! {
r.routes.insert(endpoint!("/vm.shutdown"), Box::new(VmActionHandler::new(VmAction::Shutdown)));
r.routes.insert(endpoint!("/vm.reboot"), Box::new(VmActionHandler::new(VmAction::Reboot)));
r.routes.insert(endpoint!("/vmm.shutdown"), Box::new(VmmShutdown {}));
r.routes.insert(endpoint!("/vmm.ping"), Box::new(VmmPing {}));
r
};

View File

@ -5,7 +5,7 @@
use crate::api::http::EndpointHandler;
use crate::api::{
vm_boot, vm_create, vm_delete, vm_info, vm_pause, vm_reboot, vm_resume, vm_shutdown,
vm_boot, vm_create, vm_delete, vm_info, vm_pause, vm_reboot, vm_resume, vm_shutdown, vmm_ping,
vmm_shutdown, ApiError, ApiRequest, ApiResult, VmAction, VmConfig,
};
use micro_http::{Body, Method, Request, Response, StatusCode, Version};
@ -46,6 +46,9 @@ pub enum HttpError {
/// Could not shut the VMM down
VmmShutdown(ApiError),
/// Could not handle VMM ping
VmmPing(ApiError),
}
fn error_response(error: HttpError, status: StatusCode) -> Response {
@ -169,6 +172,32 @@ impl EndpointHandler for VmInfo {
}
}
// /api/v1/vmm.info handler
pub struct VmmPing {}
impl EndpointHandler for VmmPing {
fn handle_request(
&self,
req: &Request,
api_notifier: EventFd,
api_sender: Sender<ApiRequest>,
) -> Response {
match req.method() {
Method::Get => match vmm_ping(api_notifier, api_sender).map_err(HttpError::VmmPing) {
Ok(pong) => {
let mut response = Response::new(Version::Http11, StatusCode::OK);
let info_serialized = serde_json::to_string(&pong).unwrap();
response.set_body(Body::new(info_serialized));
response
}
Err(e) => error_response(e, StatusCode::InternalServerError),
},
_ => Response::new(Version::Http11, StatusCode::BadRequest),
}
}
}
// /api/v1/vmm.shutdown handler
pub struct VmmShutdown {}

View File

@ -105,12 +105,20 @@ pub struct VmInfo {
pub state: VmState,
}
#[derive(Clone, Deserialize, Serialize)]
pub struct VmmPingResponse {
pub version: String,
}
pub enum ApiResponsePayload {
/// No data is sent on the channel.
Empty,
/// Virtual machine information
VmInfo(VmInfo),
/// Vmm ping response
VmmPing(VmmPingResponse),
}
/// This is the response sent by the VMM API server through the mpsc channel.
@ -138,6 +146,9 @@ pub enum ApiRequest {
/// Request the VM information.
VmInfo(Sender<ApiResponse>),
/// Request the VMM API server status
VmmPing(Sender<ApiResponse>),
/// Pause a VM.
VmPause(Sender<ApiResponse>),
@ -263,6 +274,22 @@ pub fn vm_info(api_evt: EventFd, api_sender: Sender<ApiRequest>) -> ApiResult<Vm
}
}
pub fn vmm_ping(api_evt: EventFd, api_sender: Sender<ApiRequest>) -> ApiResult<VmmPingResponse> {
let (response_sender, response_receiver) = channel();
api_sender
.send(ApiRequest::VmmPing(response_sender))
.map_err(ApiError::RequestSend)?;
api_evt.write(1).map_err(ApiError::EventFdWrite)?;
let vmm_pong = response_receiver.recv().map_err(ApiError::ResponseRecv)??;
match vmm_pong {
ApiResponsePayload::VmmPing(pong) => Ok(pong),
_ => Err(ApiError::ResponsePayloadType),
}
}
pub fn vmm_shutdown(api_evt: EventFd, api_sender: Sender<ApiRequest>) -> ApiResult<()> {
let (response_sender, response_receiver) = channel();

View File

@ -12,16 +12,16 @@ servers:
paths:
/vmm.info:
/vmm.ping:
get:
summary: Returns general information about the cloud-hypervisor Virtual Machine Monitor (VMM).
summary: Ping the VMM to check for API server availability
responses:
200:
description: The VMM information
content:
application/json:
schema:
$ref: '#/components/schemas/VmmInfo'
$ref: '#/components/schemas/VmmPingResponse'
/vmm.shutdown:
put:
@ -126,7 +126,7 @@ paths:
components:
schemas:
VmmInfo:
VmmPingResponse:
required:
- version
type: object

View File

@ -14,7 +14,7 @@ extern crate serde_derive;
extern crate serde_json;
extern crate vmm_sys_util;
use crate::api::{ApiError, ApiRequest, ApiResponse, ApiResponsePayload, VmInfo};
use crate::api::{ApiError, ApiRequest, ApiResponse, ApiResponsePayload, VmInfo, VmmPingResponse};
use crate::config::VmConfig;
use crate::vm::{Error as VmError, Vm, VmState};
use libc::EFD_NONBLOCK;
@ -302,6 +302,12 @@ impl Vmm {
}
}
fn vmm_ping(&self) -> result::Result<VmmPingResponse, ApiError> {
Ok(VmmPingResponse {
version: env!("CARGO_PKG_VERSION").to_string(),
})
}
fn vm_delete(&mut self) -> result::Result<(), VmError> {
if self.vm_config.is_none() {
return Ok(());
@ -433,6 +439,11 @@ impl Vmm {
sender.send(response).map_err(Error::ApiResponseSend)?;
}
ApiRequest::VmmPing(sender) => {
let response = self.vmm_ping().map(ApiResponsePayload::VmmPing);
sender.send(response).map_err(Error::ApiResponseSend)?;
}
ApiRequest::VmPause(sender) => {
let response = self
.vm_pause()