=begin __ ___ _ _ _____ ____ __ __ \ \ / / |__ (_) |_ ___| ___| _ ___ ___ / ___| \/ | \ \ /\ / /| '_ \| | __/ _ \ |_ | | | / __|/ _ \ | | |\/| | \ V V / | | | | | || __/ _|| |_| \__ \ __/ |___| | | | \_/\_/ |_| |_|_|\__\___|_| \__,_|___/\___|\____|_| |_| Container Manager Copyright (C) 2015 David Prandzioch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. =end module Api class NodeApi < Grape::API format :json version 'v1' =begin @apiDefine NotFoundError @apiError (Not Found 404) error Object was not found @apiErrorExample 404 Not Found HTTP/1.1 404 Not Found { "error": "Not Found" } =end =begin @apiDefine ArgumentError @apiError (Bad Request 400) error Invalid arguments supplied @apiErrorExample 400 Bad Request HTTP/1.1 400 Bad Request { "error": "The supplied container name is invalid" } =end =begin @apiDefine UnauthorizedError @apiError (Unauthorized 401) error No valid API token was supplied @apiErrorExample 401 Unauthorized HTTP/1.1 401 Unauthorized { "error": "Unauthorized" } =end before do error!('Unauthorized', 401) unless headers['X-Api-Token'] == $api_token @man = ContainerManager.new($container_type) @resman = ResourceManager.new('linux') end =begin @apiDefine InternalError @apiError (Internal Server Error 500) error The process could not be requested due to an internal error @apiErrorExample 500 Internal Server Error HTTP/1.1 500 Internal Server Error { "error": "Unknown error occured" } =end rescue_from :all do |e| error_response(message: e.message, status: 500) end get '/' do {} end =begin @api {get} /info Request node information @apiVersion 1.0.0 @apiName NodeInfo @apiGroup Node @apiDescription Returns an array containing useful information about the node itself and the resources available on it. @apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf) @apiSuccess {String} container_type The configured container type (lxc or vserver) @apiSuccess {String} hostname The hostname of the system @apiSuccess {String} api_version The version number of the node api @apiSuccess {Integer} total_cpu_cores The number of cpu cores available totally @apiSuccess {Integer} free_cpu_cores The number of free cpu cores @apiUse UnauthorizedError @apiUse InternalError =end get '/info' do info = {} info['container_type'] = $container_type info['hostname'] = `#{$cmd_hostname}`.strip info['api_version'] = WfNodeApi::VERSION info['total_cpu_cores'] = @resman.total_cpu_cores info['free_cpu_cores'] = @man.free_cpu_core_count(@resman) info end =begin @api {get} /containers Request container list @apiVersion 1.0.0 @apiName GetContainers @apiGroup Container @apiDescription Returns an array of containers which are available on the node. @apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf) @apiSuccess {Object[]} containers List of available containers @apiSuccess {String} containers.name Name of the container @apiSuccess {String} containers.state State of the container (either 'RUNNING' or 'STOPPED') @apiSuccess {String} containers.ip_address IP address assigned to the container @apiSuccess {Integer} containers.cpu_cores Number of Vcores @apiSuccess {Integer} containers.memory_limit_bytes Memory limit in bytes @apiSuccess {Integer} containers.memory_usage_bytes Current amount of memory usage in bytes @apiSuccess {Integer} containers.disk_space_gb Available disk space in GB @apiSuccess {Integer} containers.disk_usage_gb Current amount of disk usage in GB @apiSuccess {String} containers.container_type Container type, could be either 'lxc' or 'vserver' @apiUse UnauthorizedError @apiUse InternalError =end get '/containers' do @man.containers end =begin @api {post} /containers Create a container @apiVersion 1.0.0 @apiName CreateContainer @apiGroup Container @apiDescription Creates a container. Returns 201 on success! @apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf) @apiParam {String} name Name of the container (must be unique per node) @apiParam {String} ip_address Valid IPv4 address @apiParam {Integer} disk_size_gb Container disk size in GB @apiParam {Integer} memory_limit_mb Memory limt in MB @apiParam {Integer} cpu_core_count Amount of Vcores assigned to the container @apiSuccess {String} success Success message @apiSuccess {String} output STDOUT from container creation @apiUse UnauthorizedError @apiUse ArgumentError @apiUse InternalError =end params do requires :name, type: String requires :ip_address, type: String requires :disk_size_gb, type: Integer requires :memory_limit_mb, type: Integer requires :cpu_core_count, type: Integer end post '/containers' do begin res = @man.create_container(params[:name], params[:ip_address], params[:disk_size_gb], params[:memory_limit_mb], params[:cpu_core_count] ) return { success: 'container was created', output: res } rescue ArgumentError => e error!(e.message, 400) rescue ::NotFoundError => e error!('Not Found', 404) end end =begin @api {get} /containers/:name Request container by its name @apiVersion 1.0.0 @apiName GetContainer @apiGroup Container @apiDescription Returns information on a specific container @apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf) @apiParam {String} name Unique name of the container @apiSuccess {String} name Name of the container @apiSuccess {String} state State of the container (either 'RUNNING' or 'STOPPED') @apiSuccess {String} ip_address IP address assigned to the container @apiSuccess {Integer} cpu_cores Number of Vcores @apiSuccess {Integer} memory_limit_bytes Memory limit in bytes @apiSuccess {Integer} memory_usage_bytes Current amount of memory usage in bytes @apiSuccess {Integer} disk_space_gb Available disk space in GB @apiSuccess {Integer} disk_usage_gb Current amount of disk usage in GB @apiSuccess {String} container_type Container type, could be either 'lxc' or 'vserver' @apiUse UnauthorizedError @apiUse InternalError @apiUse NotFoundError =end params do requires :name, type: String end get '/containers/:name' do begin return @man.container(params[:name]) rescue ::NotFoundError => e error!('Not Found', 404) end end =begin @api {put} /containers/:name/start Start a container @apiVersion 1.0.0 @apiName StartContainer @apiGroup Container @apiDescription Starts a container if it exists @apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf) @apiParam {String} name Unique name of the container @apiSuccess {String} success Success message @apiSuccess {String} output STDOUT from container start @apiUse UnauthorizedError @apiUse NotFoundError @apiUse InternalError =end params do requires :name, type: String end put '/containers/:name/start' do begin res = @man.start(params[:name]) return { success: 'container has been started', output: res } rescue ::NotFoundError => e error!('Not Found', 404) end end =begin @api {put} /containers/:name/stop Stop a container @apiVersion 1.0.0 @apiName StopContainer @apiGroup Container @apiDescription Stops a container if it exists @apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf) @apiParam {String} name Unique name of the container @apiSuccess {String} success Success message @apiSuccess {String} output STDOUT from container stop @apiUse UnauthorizedError @apiUse NotFoundError @apiUse InternalError =end params do requires :name, type: String end put '/containers/:name/stop' do begin res = @man.stop(params[:name]) return { success: 'container has been stopped', output: res } rescue ::NotFoundError => e error!('Not Found', 404) end end =begin @api {put} /containers/:name/kill Kill a container @apiVersion 1.0.0 @apiName KillContainer @apiGroup Container @apiDescription Kills a container if it exists. Does essentially the same as StopContainer but forces the container to shut down and does not care about processes running on it. @apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf) @apiParam {String} name Unique name of the container @apiSuccess {String} success Success message @apiSuccess {String} output STDOUT from container kill @apiUse UnauthorizedError @apiUse NotFoundError @apiUse InternalError =end params do requires :name, type: String end put '/containers/:name/kill' do begin res = @man.kill(params[:name]) return { success: 'container has been killed', output: res } rescue ::NotFoundError => e error('Not Found', 404) end end =begin @api {delete} /containers/:name Delete a container @apiVersion 1.0.0 @apiName DeleteContainer @apiGroup Container @apiDescription Deletes a container if it exists. @apiHeader {String} X-Api-Token API token (from /etc/wf_node_api.conf) @apiParam {String} name Unique name of the container @apiSuccess {String} success Success message @apiSuccess {String} output STDOUT from container deletion @apiUse UnauthorizedError @apiUse NotFoundError @apiUse InternalError =end params do requires :name, type: String end delete '/containers/:name' do begin res = @man.delete(params[:name]) return { success: 'container has been deleted', output: res } rescue ::NotFoundError => e error!('Not Found', 404) end end end end