2018-03-14 20:46:54 +01:00
|
|
|
/*
|
|
|
|
|
*crun - OCI runtime written in C
|
|
|
|
|
*
|
2019-01-01 21:29:59 +01:00
|
|
|
*Copyright (C) 2018, 2019 Giuseppe Scrivano <giuseppe@scrivano.org>
|
2018-03-14 20:46:54 +01:00
|
|
|
*crun is free software; you can redistribute it and/or modify
|
|
|
|
|
*it under the terms of the GNU Lesser General Public License as published by
|
2020-02-25 22:05:09 +01:00
|
|
|
*the Free Software Foundation; either version 2.1 of the License, or
|
2018-03-14 20:46:54 +01:00
|
|
|
*(at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
*crun 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 Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
*You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
*along with crun. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
An example of using this module:
|
|
|
|
|
|
|
|
|
|
import python_crun
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
spec = json.loads(python_crun.spec())
|
|
|
|
|
spec['root']['path'] = '/path/to/the/rootfs'
|
|
|
|
|
spec['process']['args'] = ['/bin/echo', 'hello from a container']
|
|
|
|
|
|
|
|
|
|
ctr = python_crun.load_from_memory(json.dumps(spec))
|
|
|
|
|
ctx = python_crun.make_context("test-container")
|
|
|
|
|
python_crun.set_verbosity(python_crun.VERBOSITY_ERROR)
|
|
|
|
|
python_crun.run(ctx, ctr)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include <Python.h>
|
|
|
|
|
#include <libcrun/container.h>
|
|
|
|
|
#include <libcrun/status.h>
|
|
|
|
|
#include <libcrun/utils.h>
|
|
|
|
|
#include <libcrun/error.h>
|
|
|
|
|
|
|
|
|
|
#define CONTEXT_OBJ_TAG "crun-context"
|
|
|
|
|
#define CONTAINER_OBJ_TAG "crun-container"
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
set_error (libcrun_error_t *err)
|
|
|
|
|
{
|
|
|
|
|
if ((*err)->status == 0)
|
|
|
|
|
PyErr_SetString (PyExc_RuntimeError, (*err)->msg);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cleanup_free char *msg = NULL;
|
2020-07-30 22:29:20 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
ret = asprintf (&msg, "%s: %s", (*err)->msg, strerror ((*err)->status));
|
|
|
|
|
if (LIKELY (ret >= 0))
|
|
|
|
|
PyErr_SetString (PyExc_RuntimeError, msg);
|
2018-03-14 20:46:54 +01:00
|
|
|
}
|
|
|
|
|
|
2020-06-13 20:44:33 +02:00
|
|
|
libcrun_error_release (err);
|
2018-03-14 20:46:54 +01:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
free_container (PyObject *ptr)
|
|
|
|
|
{
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_container_t *ctr = PyCapsule_GetPointer (ptr, CONTAINER_OBJ_TAG);
|
2020-06-13 20:44:33 +02:00
|
|
|
free_runtime_spec_schema_config_schema (ctr->container_def);
|
2018-03-14 20:46:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
container_load_from_file (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
const char *path;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_container_t *ctr;
|
2018-03-14 20:46:54 +01:00
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple (args, "s", &path))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctr = libcrun_container_load_from_file (path, &err);
|
|
|
|
|
if (ctr == NULL)
|
|
|
|
|
return set_error (&err);
|
|
|
|
|
|
|
|
|
|
return PyCapsule_New (ctr, CONTAINER_OBJ_TAG, free_container);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
container_load_from_memory (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
const char *def;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_container_t *ctr;
|
2018-03-14 20:46:54 +01:00
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple (args, "s", &def))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctr = libcrun_container_load_from_memory (def, &err);
|
|
|
|
|
if (ctr == NULL)
|
|
|
|
|
return set_error (&err);
|
|
|
|
|
|
|
|
|
|
return PyCapsule_New (ctr, CONTAINER_OBJ_TAG, free_container);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
free_context (void *ptr)
|
|
|
|
|
{
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_context_t *ctx = ptr;
|
2018-03-14 20:46:54 +01:00
|
|
|
char *id = (char *) ctx->id;
|
|
|
|
|
free (ctx->state_root);
|
|
|
|
|
free (ctx->notify_socket);
|
|
|
|
|
free (id);
|
|
|
|
|
free (ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
make_context (PyObject *self arg_unused, PyObject *args, PyObject *kwargs)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
char *id = NULL;
|
|
|
|
|
char *bundle = NULL;
|
|
|
|
|
char *state_root = NULL;
|
|
|
|
|
char *notify_socket = NULL;
|
|
|
|
|
static char *kwlist[] =
|
2024-02-05 10:18:47 +01:00
|
|
|
{ "id", "bundle", "state_root", "systemd_cgroup", "notify_socket", "detach", "no_new_keyring", "force_no_cgroup", "no_pivot", NULL };
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_context_t *ctx = malloc (sizeof (*ctx));
|
2018-03-14 20:46:54 +01:00
|
|
|
if (ctx == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
memset (ctx, 0, sizeof (*ctx));
|
|
|
|
|
ctx->fifo_exec_wait_fd = -1;
|
|
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords
|
2024-02-05 10:18:47 +01:00
|
|
|
(args, kwargs, "s|ssbsbbbb", kwlist, &id, &bundle, &state_root,
|
|
|
|
|
&ctx->systemd_cgroup, ¬ify_socket, &ctx->detach, &ctx->no_new_keyring, &ctx->force_no_cgroup, &ctx->no_pivot))
|
2018-03-14 20:46:54 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctx->id = xstrdup (id);
|
|
|
|
|
ctx->bundle = xstrdup (bundle ? bundle : ".");
|
|
|
|
|
ctx->state_root = xstrdup (state_root);
|
|
|
|
|
ctx->notify_socket = xstrdup (notify_socket);
|
|
|
|
|
return PyCapsule_New (ctx, CONTEXT_OBJ_TAG, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
container_run (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
PyObject *ctx_obj = NULL;
|
|
|
|
|
PyObject *ctr_obj = NULL;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_container_t *ctr;
|
|
|
|
|
libcrun_context_t *ctx;
|
2018-03-15 18:46:22 +01:00
|
|
|
int ret;
|
2018-03-14 20:46:54 +01:00
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple (args, "OO", &ctx_obj, &ctr_obj))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctx = PyCapsule_GetPointer (ctx_obj, CONTEXT_OBJ_TAG);
|
|
|
|
|
if (ctx == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctr = PyCapsule_GetPointer (ctr_obj, CONTAINER_OBJ_TAG);
|
|
|
|
|
if (ctr == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_BEGIN_ALLOW_THREADS;
|
2022-07-11 20:30:13 +02:00
|
|
|
ret = libcrun_container_run (ctx, ctr, 0, &err);
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_END_ALLOW_THREADS;
|
|
|
|
|
if (ret < 0)
|
2018-03-14 20:46:54 +01:00
|
|
|
return set_error (&err);
|
|
|
|
|
|
2018-03-20 15:06:22 +01:00
|
|
|
return PyLong_FromLong (ret);
|
2018-03-14 20:46:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
container_create (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
PyObject *ctx_obj = NULL;
|
|
|
|
|
PyObject *ctr_obj = NULL;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_container_t *ctr;
|
|
|
|
|
libcrun_context_t *ctx;
|
2018-03-15 18:46:22 +01:00
|
|
|
int ret;
|
2018-03-14 20:46:54 +01:00
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple (args, "OO", &ctx_obj, &ctr_obj))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctx = PyCapsule_GetPointer (ctx_obj, CONTEXT_OBJ_TAG);
|
|
|
|
|
if (ctx == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctr = PyCapsule_GetPointer (ctr_obj, CONTAINER_OBJ_TAG);
|
|
|
|
|
if (ctr == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_BEGIN_ALLOW_THREADS;
|
2024-03-01 11:00:27 +01:00
|
|
|
ret = libcrun_container_create (ctx, ctr, LIBCRUN_CREATE_OPTIONS_PREFORK, &err);
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_END_ALLOW_THREADS;
|
|
|
|
|
if (ret < 0)
|
2018-03-14 20:46:54 +01:00
|
|
|
return set_error (&err);
|
|
|
|
|
|
2018-03-20 15:06:22 +01:00
|
|
|
return PyLong_FromLong (ret);
|
2018-03-14 20:46:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
container_delete (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
PyObject *ctx_obj = NULL;
|
|
|
|
|
char *id = NULL;
|
|
|
|
|
bool force;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_context_t *ctx;
|
2018-03-15 18:46:22 +01:00
|
|
|
int ret;
|
2018-03-14 20:46:54 +01:00
|
|
|
|
2022-10-07 11:09:54 -04:00
|
|
|
if (!PyArg_ParseTuple (args, "Osb", &ctx_obj, &id, &force))
|
2018-03-14 20:46:54 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctx = PyCapsule_GetPointer (ctx_obj, CONTEXT_OBJ_TAG);
|
|
|
|
|
if (ctx == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_BEGIN_ALLOW_THREADS;
|
|
|
|
|
ret = libcrun_container_delete (ctx, NULL, id, force, &err);
|
|
|
|
|
Py_END_ALLOW_THREADS;
|
|
|
|
|
if (ret < 0)
|
2018-03-14 20:46:54 +01:00
|
|
|
return set_error (&err);
|
|
|
|
|
|
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
container_kill (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
PyObject *ctx_obj = NULL;
|
|
|
|
|
char *id = NULL;
|
2022-01-18 17:13:31 +01:00
|
|
|
char *signal;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_context_t *ctx;
|
2018-03-15 18:46:22 +01:00
|
|
|
int ret;
|
2018-03-14 20:46:54 +01:00
|
|
|
|
2021-12-23 10:12:38 +01:00
|
|
|
if (!PyArg_ParseTuple (args, "Oss", &ctx_obj, &id, &signal))
|
2018-03-14 20:46:54 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctx = PyCapsule_GetPointer (ctx_obj, CONTEXT_OBJ_TAG);
|
|
|
|
|
if (ctx == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_BEGIN_ALLOW_THREADS;
|
|
|
|
|
ret = libcrun_container_kill (ctx, id, signal, &err);
|
|
|
|
|
Py_END_ALLOW_THREADS;
|
|
|
|
|
if (ret < 0)
|
2018-03-14 20:46:54 +01:00
|
|
|
return set_error (&err);
|
|
|
|
|
|
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
container_start (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
PyObject *ctx_obj = NULL;
|
|
|
|
|
char *id = NULL;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_context_t *ctx;
|
2018-03-15 18:46:22 +01:00
|
|
|
int ret;
|
2018-03-14 20:46:54 +01:00
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple (args, "Os", &ctx_obj, &id))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctx = PyCapsule_GetPointer (ctx_obj, CONTEXT_OBJ_TAG);
|
|
|
|
|
if (ctx == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_BEGIN_ALLOW_THREADS;
|
|
|
|
|
ret = libcrun_container_start (ctx, id, &err);
|
|
|
|
|
Py_END_ALLOW_THREADS;
|
|
|
|
|
if (ret < 0)
|
2018-03-14 20:46:54 +01:00
|
|
|
return set_error (&err);
|
|
|
|
|
|
2018-03-20 15:06:22 +01:00
|
|
|
return PyLong_FromLong (ret);
|
2018-03-14 20:46:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
containers_list (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
PyObject *ctx_obj = NULL;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_context_t *ctx;
|
2018-03-14 20:46:54 +01:00
|
|
|
libcrun_container_list_t *containers, *it;
|
2018-03-15 18:46:22 +01:00
|
|
|
PyObject *retobj;
|
2018-03-14 20:46:54 +01:00
|
|
|
Py_ssize_t i = 0;
|
2018-03-15 18:46:22 +01:00
|
|
|
int ret;
|
2018-03-14 20:46:54 +01:00
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple (args, "O", &ctx_obj))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctx = PyCapsule_GetPointer (ctx_obj, CONTEXT_OBJ_TAG);
|
|
|
|
|
if (ctx == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_BEGIN_ALLOW_THREADS;
|
|
|
|
|
ret = libcrun_get_containers_list (&containers, ctx->state_root, &err);
|
|
|
|
|
Py_END_ALLOW_THREADS;
|
|
|
|
|
if (ret < 0)
|
2018-03-14 20:46:54 +01:00
|
|
|
return set_error (&err);
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
for (it = containers; it; it = it->next)
|
|
|
|
|
i++;
|
2018-03-15 18:46:22 +01:00
|
|
|
|
|
|
|
|
retobj = PyList_New (i);
|
|
|
|
|
if (retobj == NULL)
|
2018-03-14 20:46:54 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
for (it = containers; it; it = it->next)
|
2018-03-15 18:46:22 +01:00
|
|
|
PyList_SetItem (retobj, i++, PyUnicode_FromString (it->name));
|
2018-03-14 20:46:54 +01:00
|
|
|
|
|
|
|
|
libcrun_free_containers_list (containers);
|
|
|
|
|
|
2018-03-15 18:46:22 +01:00
|
|
|
return retobj;
|
2018-03-14 20:46:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
container_status (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
PyObject *ctx_obj = NULL;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_context_t *ctx;
|
2018-03-14 20:46:54 +01:00
|
|
|
char *id = NULL;
|
|
|
|
|
libcrun_container_status_t status;
|
|
|
|
|
cleanup_free char *buffer = NULL;
|
|
|
|
|
FILE *memfile;
|
2018-03-15 18:46:22 +01:00
|
|
|
int ret;
|
2018-03-14 20:46:54 +01:00
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple (args, "Os", &ctx_obj, &id))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctx = PyCapsule_GetPointer (ctx_obj, CONTEXT_OBJ_TAG);
|
|
|
|
|
if (ctx == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
buffer = malloc (4096);
|
|
|
|
|
if (buffer == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
/* A bit silly (and expensive), libcrun_container_state needs a refactoring
|
|
|
|
|
to make this nicer. */
|
|
|
|
|
memset (buffer, 0, 4096);
|
|
|
|
|
|
|
|
|
|
memfile = fmemopen (buffer, 4095, "w");
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_BEGIN_ALLOW_THREADS;
|
|
|
|
|
ret = libcrun_container_state (ctx, id, memfile, &err);
|
|
|
|
|
Py_END_ALLOW_THREADS;
|
|
|
|
|
if (ret < 0)
|
2018-03-14 20:46:54 +01:00
|
|
|
return set_error (&err);
|
2018-03-15 18:46:22 +01:00
|
|
|
|
2018-03-14 20:46:54 +01:00
|
|
|
fclose (memfile);
|
|
|
|
|
|
|
|
|
|
return PyUnicode_FromString (buffer);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-13 20:44:33 +02:00
|
|
|
static int
|
|
|
|
|
load_json_file (yajl_val *out, const char *jsondata, struct parser_context *ctx arg_unused, libcrun_error_t *err)
|
|
|
|
|
{
|
|
|
|
|
char errbuf[1024];
|
|
|
|
|
|
|
|
|
|
*err = NULL;
|
|
|
|
|
|
|
|
|
|
*out = yajl_tree_parse (jsondata, errbuf, sizeof (errbuf));
|
|
|
|
|
if (*out == NULL)
|
|
|
|
|
return libcrun_make_error (err, 0, "cannot parse the data: `%s`", errbuf);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-14 20:46:54 +01:00
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
container_update (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
PyObject *ctx_obj = NULL;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_context_t *ctx;
|
2018-03-14 20:46:54 +01:00
|
|
|
char *id = NULL;
|
|
|
|
|
char *content = NULL;
|
|
|
|
|
yajl_val tree = NULL;
|
|
|
|
|
int ret;
|
|
|
|
|
parser_error parser_err = NULL;
|
2019-03-25 00:25:33 +01:00
|
|
|
struct parser_context parser_ctx = { 0, stderr };
|
2020-06-13 20:44:33 +02:00
|
|
|
runtime_spec_schema_config_schema_process *process = NULL;
|
2018-03-14 20:46:54 +01:00
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple (args, "Oss", &ctx_obj, &id, &content))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ctx = PyCapsule_GetPointer (ctx_obj, CONTEXT_OBJ_TAG);
|
|
|
|
|
if (ctx == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2020-06-13 20:44:33 +02:00
|
|
|
ret = load_json_file (&tree, content, &parser_ctx, &err);
|
2018-03-14 20:46:54 +01:00
|
|
|
if (UNLIKELY (ret < 0))
|
|
|
|
|
return set_error (&err);
|
|
|
|
|
|
2020-06-13 20:44:33 +02:00
|
|
|
process = make_runtime_spec_schema_config_schema_process (tree, &parser_ctx, &parser_err);
|
2018-03-14 20:46:54 +01:00
|
|
|
yajl_tree_free (tree);
|
|
|
|
|
if (process == NULL)
|
|
|
|
|
{
|
|
|
|
|
cleanup_free char *msg = NULL;
|
2020-07-30 22:29:20 +08:00
|
|
|
ret = asprintf (&msg, "cannot parse process: %s", parser_err);
|
|
|
|
|
if (LIKELY (ret >= 0))
|
|
|
|
|
PyErr_SetString (PyExc_RuntimeError, msg);
|
2018-03-14 20:46:54 +01:00
|
|
|
free (parser_err);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_BEGIN_ALLOW_THREADS;
|
2018-03-14 20:46:54 +01:00
|
|
|
ret = libcrun_container_exec (ctx, id, process, &err);
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_END_ALLOW_THREADS;
|
|
|
|
|
|
2020-06-13 20:44:33 +02:00
|
|
|
free_runtime_spec_schema_config_schema_process (process);
|
2018-03-14 20:46:54 +01:00
|
|
|
if (ret < 0)
|
|
|
|
|
return set_error (&err);
|
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
container_spec (PyObject *self arg_unused, PyObject *args arg_unused)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
PyObject *ctx_obj = NULL;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_context_t *ctx;
|
2018-03-14 20:46:54 +01:00
|
|
|
char *id = NULL;
|
|
|
|
|
libcrun_container_status_t status;
|
|
|
|
|
cleanup_free char *buffer = NULL;
|
|
|
|
|
FILE *memfile;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
buffer = malloc (4096);
|
|
|
|
|
if (buffer == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
memfile = fmemopen (buffer, 4095, "w");
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_BEGIN_ALLOW_THREADS;
|
2018-03-14 20:46:54 +01:00
|
|
|
ret = libcrun_container_spec (geteuid () == 0, memfile, &err);
|
2018-03-15 18:46:22 +01:00
|
|
|
Py_END_ALLOW_THREADS;
|
2018-03-14 20:46:54 +01:00
|
|
|
if (ret < 0)
|
|
|
|
|
return set_error (&err);
|
|
|
|
|
buffer[ret] = '\0';
|
|
|
|
|
fclose (memfile);
|
|
|
|
|
|
|
|
|
|
return PyUnicode_FromString (buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
get_verbosity (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
2025-05-07 18:26:22 +02:00
|
|
|
return PyLong_FromLong (libcrun_get_verbosity());
|
2018-03-14 20:46:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
2023-08-12 15:28:16 +02:00
|
|
|
set_verbosity (PyObject *self arg_unused, PyObject *args)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
|
|
|
|
libcrun_error_t err;
|
|
|
|
|
PyObject *ctx_obj = NULL;
|
2019-05-31 10:14:24 +02:00
|
|
|
libcrun_context_t *ctx;
|
2018-03-14 20:46:54 +01:00
|
|
|
int verbosity;
|
|
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple (args, "i", &verbosity))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
libcrun_set_verbosity (verbosity);
|
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyMethodDef CrunMethods[] = {
|
|
|
|
|
{"load_from_file", container_load_from_file, METH_VARARGS,
|
|
|
|
|
"Load an OCI container from file."},
|
|
|
|
|
{"load_from_memory", container_load_from_memory, METH_VARARGS,
|
|
|
|
|
"Load an OCI container from memory."},
|
|
|
|
|
{"run", container_run, METH_VARARGS, "Run a container."},
|
2023-03-08 19:41:42 +08:00
|
|
|
{"create", container_create, METH_VARARGS, "Create a container."},
|
2018-03-14 20:46:54 +01:00
|
|
|
{"delete", container_delete, METH_VARARGS, "Delete a container."},
|
|
|
|
|
{"kill", container_kill, METH_VARARGS, "Kill a container."},
|
|
|
|
|
{"list", containers_list, METH_VARARGS, "List the containers."},
|
|
|
|
|
{"status", container_status, METH_VARARGS,
|
|
|
|
|
"Get the status of a container."},
|
|
|
|
|
{"update", container_update, METH_VARARGS,
|
|
|
|
|
"Update the constraints of a container."},
|
|
|
|
|
{"spec", container_spec, METH_VARARGS,
|
|
|
|
|
"Generate a new configuration file."},
|
|
|
|
|
{"make_context", (PyCFunction) make_context, METH_VARARGS | METH_KEYWORDS,
|
|
|
|
|
"Create a context object."},
|
|
|
|
|
{"set_verbosity", set_verbosity, METH_VARARGS, "Set the logging verbosity."},
|
2025-05-07 18:26:22 +02:00
|
|
|
{"get_verbosity", get_verbosity, METH_NOARGS, "Get the logging verbosity."},
|
2018-03-14 20:46:54 +01:00
|
|
|
{"spec", container_spec, METH_VARARGS,
|
|
|
|
|
"Generate a new configuration file."},
|
|
|
|
|
{NULL, NULL, 0, NULL}
|
|
|
|
|
};
|
|
|
|
|
|
2020-06-13 20:44:33 +02:00
|
|
|
struct PyModuleDef crun_mod =
|
|
|
|
|
{
|
|
|
|
|
PyModuleDef_HEAD_INIT,
|
|
|
|
|
"python_crun",
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
CrunMethods,
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-14 20:46:54 +01:00
|
|
|
PyMODINIT_FUNC
|
2020-06-13 20:44:33 +02:00
|
|
|
PyInit_python_crun (void)
|
2018-03-14 20:46:54 +01:00
|
|
|
{
|
2020-06-13 20:44:33 +02:00
|
|
|
PyObject *ret;
|
|
|
|
|
ret = PyModule_Create (&crun_mod);
|
|
|
|
|
if (ret == NULL)
|
|
|
|
|
return ret;
|
|
|
|
|
(void) PyModule_AddIntConstant (ret, "VERBOSITY_ERROR", LIBCRUN_VERBOSITY_ERROR);
|
|
|
|
|
(void) PyModule_AddIntConstant (ret, "VERBOSITY_WARNING", LIBCRUN_VERBOSITY_WARNING);
|
2024-08-19 13:58:43 +02:00
|
|
|
(void) PyModule_AddIntConstant (ret, "VERBOSITY_DEBUG", LIBCRUN_VERBOSITY_DEBUG);
|
2020-06-13 20:44:33 +02:00
|
|
|
return ret;
|
2018-03-14 20:46:54 +01:00
|
|
|
}
|