Skip to content

Commit eac19fb

Browse files
committed
krun: parse annotations for krun.{cpus, ram_mib}
Support the use of OCI annotations as a way for the container engine to configure the microVM's CPU count and RAM amount via `krun.cpus` and `krun.ram_mib` respectively. Signed-off-by: Jake Correnti <[email protected]>
1 parent 8388a7d commit eac19fb

File tree

1 file changed

+63
-22
lines changed

1 file changed

+63
-22
lines changed

src/libcrun/handlers/krun.c

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -184,42 +184,83 @@ libkrun_read_vm_config (yajl_val *config_tree, libcrun_error_t *err)
184184
return 0;
185185
}
186186

187+
/*
188+
* Default to parsing the OCI annotations to find the specified resource
189+
* metadata. If the provided value not a non-negative integer, then fallback to
190+
* the provided default value. If the annotation is not provided, parse the
191+
* krun_vm.json file. If the value provided in the krun_vm.json file is not a
192+
* non-negative integer, or if the krun_vm.json file also doesn't contain the
193+
* metadata, then fallback to the default value provided.
194+
*/
195+
static int
196+
libkrun_parse_resource_configuration (yajl_val *config_tree, libcrun_container_t *container, const char *annotation, const char *path[], int default_val)
197+
{
198+
char *annotation_val;
199+
char *endptr;
200+
int resource_val = default_val;
201+
yajl_val krun_file_val = NULL;
202+
203+
annotation_val = (char *) find_annotation (container, annotation);
204+
if (annotation_val != NULL)
205+
{
206+
errno = 0;
207+
resource_val = (int) strtol (annotation_val, &endptr, 10);
208+
if (errno != 0 || endptr == annotation_val || *endptr != '\0')
209+
{
210+
// annotations input is not an integer
211+
return default_val;
212+
}
213+
}
214+
else if (*config_tree != NULL)
215+
{
216+
krun_file_val = yajl_tree_get (*config_tree, path, yajl_t_number);
217+
if (! YAJL_IS_INTEGER (krun_file_val))
218+
{
219+
return default_val;
220+
}
221+
222+
if (krun_file_val != NULL)
223+
resource_val = (int) YAJL_GET_INTEGER (krun_file_val);
224+
}
225+
226+
if (resource_val < 1)
227+
// parsed value is non-positive
228+
return default_val;
229+
230+
return resource_val;
231+
}
232+
187233
static int
188-
libkrun_configure_vm (uint32_t ctx_id, void *handle, bool *configured, yajl_val *config_tree, libcrun_error_t *err)
234+
libkrun_configure_vm (uint32_t ctx_id, void *handle, bool *configured, yajl_val *config_tree, libcrun_container_t *container, libcrun_error_t *err)
189235
{
190236
int32_t (*krun_set_vm_config) (uint32_t ctx_id, uint8_t num_vcpus, uint32_t ram_mib);
191-
yajl_val cpus = NULL;
192-
yajl_val ram_mib = NULL;
237+
int cpus, ram_mib, ret;
193238
const char *path_cpus[] = { "cpus", (const char *) 0 };
194239
const char *path_ram_mib[] = { "ram_mib", (const char *) 0 };
195-
int ret;
196240

197-
if (*config_tree == NULL)
198-
return 0;
199-
200-
/* Try to configure an external kernel. If the configuration file doesn't
201-
* specify a kernel, libkrun automatically fall back to using libkrunfw,
202-
* if the library is present and was loaded while creating the context.
203-
*/
204-
ret = libkrun_configure_kernel (ctx_id, handle, config_tree, err);
205-
if (UNLIKELY (ret))
206-
return ret;
207-
208-
cpus = yajl_tree_get (*config_tree, path_cpus, yajl_t_number);
209-
ram_mib = yajl_tree_get (*config_tree, path_ram_mib, yajl_t_number);
210-
/* Both cpus and ram_mib must be present at the same time */
211-
if (cpus == NULL || ram_mib == NULL || ! YAJL_IS_INTEGER (cpus) || ! YAJL_IS_INTEGER (ram_mib))
212-
return 0;
241+
cpus = libkrun_parse_resource_configuration (config_tree, container, "krun.cpus", path_cpus, 1);
242+
ram_mib = libkrun_parse_resource_configuration (config_tree, container, "krun.ram_mib", path_ram_mib, 1024);
213243

214244
krun_set_vm_config = dlsym (handle, "krun_set_vm_config");
215245

216246
if (krun_set_vm_config == NULL)
217247
return crun_make_error (err, 0, "could not find symbol in the krun library");
218248

219-
ret = krun_set_vm_config (ctx_id, YAJL_GET_INTEGER (cpus), YAJL_GET_INTEGER (ram_mib));
249+
ret = krun_set_vm_config (ctx_id, cpus, ram_mib);
220250
if (UNLIKELY (ret < 0))
221251
return crun_make_error (err, -ret, "could not set krun vm configuration");
222252

253+
if (*config_tree != NULL)
254+
{
255+
/* Try to configure an external kernel. If the configuration file doesn't
256+
* specify a kernel, libkrun automatically fall back to using libkrunfw,
257+
* if the library is present and was loaded while creating the context.
258+
*/
259+
ret = libkrun_configure_kernel (ctx_id, handle, config_tree, err);
260+
if (UNLIKELY (ret))
261+
return ret;
262+
}
263+
223264
*configured = true;
224265

225266
return 0;
@@ -395,7 +436,7 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname
395436
error (EXIT_FAILURE, -ret, "could not set enclave execution arguments");
396437
}
397438

398-
ret = libkrun_configure_vm (ctx_id, handle, &configured, &config_tree, &err);
439+
ret = libkrun_configure_vm (ctx_id, handle, &configured, &config_tree, container, &err);
399440
if (UNLIKELY (ret))
400441
{
401442
libcrun_error_t *tmp_err = &err;

0 commit comments

Comments
 (0)