diff --git a/scripts/crun_create b/scripts/crun_create index f938a49615dd984746989dfd9e78cb878136a9ba..edb6f8b5a7e92fad90440d22a12cf1ee138abdf3 100755 --- a/scripts/crun_create +++ b/scripts/crun_create @@ -4,6 +4,19 @@ BUSYBOX_EXE=$(command -v busybox) BUSYBOX_DEV_LIST="" BUSYBOX_LIB_MOUNT_LIST="" +# Make sure busybox is present +if [ ! -x "${BUSYBOX_EXE}" ]; then + echo "ERROR: Failed to find busybox binary (${BUSYBOX_EXE})" 1>&2 + exit 1 +fi + +BUNDLE_PATH=$(uci -q get swmodd.globals.oci_bundle_root) +if [ -z "${BUNDLE_PATH}" ]; then + BUNDLE_PATH="/srv/crun" # default location +fi + +mkdir -p "${BUNDLE_PATH}" + copy_configuration() { path="${1}" @@ -555,13 +568,107 @@ copy_prereq() return 0; } -usage() { +create_container() +{ + local name + + name="${1}" + + # Make sure container already not created + list=$(crun list 2>&1 | tail -n +2 | grep "${name}" | awk '{print $1}') + for cont in $list; do + if [ "$cont" = "$name" ]; then + echo "ERROR: Container already exists"$'\n'"$(crun list)" 1>&2 + exit 1; + fi + done + + bundle="$BUNDLE_PATH/$name" + # Make sure bundle path not already exists + if [ -d "${bundle}" ]; then + echo "ERROR: Bundle ${bundle} already exists, delete it first" 1>&2 + exit 1; + fi + + # Create bundle directory + mkdir "${bundle}" + + # Create rootfs + rootfs="$bundle/rootfs" + mkdir "${rootfs}" + + if ! install_busybox "${rootfs}" "${name}"; then + echo "ERROR: Failed to install rootfs" 1>&2 + exit 1 + fi + + if ! configure_busybox "${rootfs}"; then + echo "ERROR: Failed to configure busybox" 1>&2 + exit 1 + fi + + if ! copy_configuration "${bundle}" "${name}"; then + echo "ERROR: Failed to write config file" 1>&2 + exit 1 + fi + + if ! copy_prereq "${rootfs}"; then + echo "ERROR: Failed to copy required binaries" 1>&2 + exit 1 + fi +} + +generate_config() +{ + local name oci_bundle_root res cfg + + name="${1}" + if [ -z "${name}" ]; then + echo "ERROR: Please pass the name for the container" 1>&2 + exit 1 + fi + + oci_bundle_root=$(uci -q get swmodd.globals.oci_bundle_root) + if [ -z "${oci_bundle_root}" ]; then + echo "ERROR: Failed to get CRUN UCI path" + exit 1 + fi + + # Configure in crun uci for new container # + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}"=du_eu_assoc + + # Enable the container + uuid=$(uuidgen) + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".name="${name}" + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".autostart=1 + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".requested_state='Active' + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".du_status='Installed' + if [ -f "${oci_bundle_root}/$name/config" ]; then + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".type='lxc' + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".url='local://lxc_template' + else + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".type='crun' + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".url='local://crun_template' + fi + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".uuid="${uuid}" + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".ee_name='OpenWRT_Linux' + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".duid="${uuid}" + uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".eu_name="${name}" + uci -c "${oci_bundle_root}" commit ocicontainer + + # Reload crun service + ubus call uci commit '{"config":"crun"}' +} + +usage() +{ cat <<EOF CRUN iopsys image builder Special arguments: [ -h | --help ]: Print this help message and exit. + [ -c | --config ]: Generate config in swmodd for specified container Arguments: @@ -575,17 +682,19 @@ EOF return 0 } -if ! options=$(getopt -o hn: -l help,name:,busybox-path: -- "$@"); then +if ! options=$(getopt -o hcn: -l help,config,name:,busybox-path: -- "$@"); then usage exit 1 fi eval set -- "$options" +config=0 while true do case "$1" in -h|--help) usage && exit 0;; -n|--name) name=$2; shift 2;; + -c|--config) config=1 && shift 1;; --busybox-path) BUSYBOX_EXE=$2; shift 2;; --) shift 1; break ;; *) break ;; @@ -598,100 +707,9 @@ if [ -z "${name}" ]; then exit 1 fi -# Make sure busybox is present -if [ -z "${BUSYBOX_EXE}" ]; then - echo "ERROR: Please pass a pathname for busybox binary" 1>&2 - exit 1 -fi -if [ ! -x "${BUSYBOX_EXE}" ]; then - echo "ERROR: Failed to find busybox binary (${BUSYBOX_EXE})" 1>&2 - exit 1 -fi - -# Read the rootfs parent directory from swmodd uci -BUNDLE_PATH=$(uci -q get swmodd.globals.oci_bundle_root) -if [ -z "${BUNDLE_PATH}" ]; then - BUNDLE_PATH="/srv/crun" # default location -fi - -mkdir -p "${BUNDLE_PATH}" - -# Make sure container already not created -list=$(crun list 2>&1 | tail -n +2 | grep "${name}" | awk '{print $1}') -for cont in $list; do - if [ "$cont" = "$name" ]; then - echo "ERROR: Container already exists"$'\n'"$(crun list)" 1>&2 - exit 1; - fi -done - -bundle="$BUNDLE_PATH/$name" -# Make sure bundle path not already exists -if [ -d "${bundle}" ]; then - echo "ERROR: Bundle ${bundle} already exists, delete it first" 1>&2 - exit 1; -fi - -# Create bundle directory -mkdir "${bundle}" - -# Create rootfs -rootfs="$bundle/rootfs" -mkdir "${rootfs}" - -if ! install_busybox "${rootfs}" "${name}"; then - echo "ERROR: Failed to install rootfs" 1>&2 - exit 1 -fi - -if ! configure_busybox "${rootfs}"; then - echo "ERROR: Failed to configure busybox" 1>&2 - exit 1 -fi - -if ! copy_configuration "${bundle}" "${name}"; then - echo "ERROR: Failed to write config file" 1>&2 - exit 1 -fi - -if ! copy_prereq "${rootfs}"; then - echo "ERROR: Failed to copy required binaries" 1>&2 - exit 1 -fi - -oci_bundle_root=$(uci -q get swmodd.globals.oci_bundle_root) -if [ -z "${oci_bundle_root}" ]; then - echo "ERROR: Failed to get CRUN UCI path" - exit 1 -fi - -# Configure in crun uci for new container # -res=$(uci -q -c "${oci_bundle_root}" get ocicontainer."${name}") -if [ "${res}" != "du_eu_assoc" ]; then - # Add a new section - cfg=$(uci -q -c "${oci_bundle_root}" add ocicontainer du_eu_assoc) - if [ -z "${cfg}" ]; then - echo "ERROR: Failed to create a new section in CRUN UCI" - exit 1 - fi - - uci -q -c "${oci_bundle_root}" rename ocicontainer."${cfg}"="${name}" - uci -c "${oci_bundle_root}" commit ocicontainer +if [ "$config" -eq "1" ]; then + generate_config "$name" +else + create_container "$name" + generate_config "${name}" fi - -# Enable the container -uuid=$(uuidgen) -uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".name="${name}" -uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".autostart=1 -uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".requested_state='Active' -uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".du_status='Installed' -uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".type='crun' -uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".url='local://crun_template' -uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".uuid="${uuid}" -uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".ee_name='OpenWRT_Linux' -uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".duid="${uuid}" -uci -q -c "${oci_bundle_root}" set ocicontainer."${name}".eu_name="${name}" -uci -c "${oci_bundle_root}" commit ocicontainer - -# Reload crun service -ubus call uci commit '{"config":"crun"}' diff --git a/src/swmod.c b/src/swmod.c index b3e38d1132464f4ab5b917896eb6be89d28e48f5..7904ce98ef4671c30b5b779d4a739078068c9338 100644 --- a/src/swmod.c +++ b/src/swmod.c @@ -452,7 +452,14 @@ static void swmod_perform_package_install(PkgInfo *pkg) docker_image = true; // installation performed externally } else if (strstr(output, "Tar") != NULL) { sscanf(output, "Tar %63s installed", info.name); - snprintf(info.du_type, sizeof(info.du_type), "crun"); + char path[1024] = {0}; + + snprintf(path, sizeof(path), "%s/%s/config", swmod_config.oci_bundle_root, info.name); + if (file_exists(path)) { + snprintf(info.du_type, sizeof(info.du_type), "lxc"); + } else { + snprintf(info.du_type, sizeof(info.du_type), "crun"); + } snprintf(info.eu_name, sizeof(info.eu_name), "%.32s", info.name); } else { err = -1; @@ -483,9 +490,8 @@ static void swmod_perform_package_install(PkgInfo *pkg) swmod_uci_fini(uci_file); - if (strcmp(info.du_type, "crun") == 0) {// for crun containers - swmod_uci_commit("crun"); - } + PRINT_INFO("# Installed DU reload %s service #", info.du_type); + swmod_uci_commit("crun"); } else { PRINT_ERR("DU Installation failed"); swmod_uci_delete_by_section(s, NULL, NULL); diff --git a/src/swmod_crun.c b/src/swmod_crun.c index bb01720b98382900af4be6cefe651ae9eb50bb67..0a78fddc726cb9204f6a72b921d59cf48aa6067c 100644 --- a/src/swmod_crun.c +++ b/src/swmod_crun.c @@ -20,6 +20,38 @@ #include "swmod_crun.h" #include "swmod_common.h" +static char* get_lxc_status(const char *c_name) +{ + if (c_name == NULL) { + return "Error"; + } + + char cmd[MAX_BUFFER_LEN] = {0}; + char output[MAX_BUFFER_LEN] = {0}; + + snprintf(cmd, sizeof(cmd), "lxc-info -s -n %s", c_name); + + if (run_cmd(cmd, output, sizeof(output)) != 0) { + PRINT_ERR("Failed to read container status"); + return "Error"; + } + + if (strlen(output) == 0) { + PRINT_ERR("Container status not found"); + return "Error"; + } + + if (strstr(output, "RUNNING") != NULL) { + return "Up"; + } + + if (strstr(output, "STOPPED") != NULL) { + return "Disabled"; + } + + return "Error"; +} + static char* get_container_status(const char *c_name) { if (c_name == NULL) { @@ -56,6 +88,40 @@ static char* get_container_status(const char *c_name) return "Up"; } +static int get_lxc_pid(const char *c_name) +{ + if (c_name == NULL) { + return -1; + } + + char cmd[MAX_BUFFER_LEN] = {0}; + char output[MAX_BUFFER_LEN] = {0}; + + snprintf(cmd, sizeof(cmd), "lxc-info -p -n %s", c_name); + + if (run_cmd(cmd, output, sizeof(output)) != 0) { + PRINT_ERR("Failed to read container pid"); + return -1; + } + + if (strlen(output) == 0) { + PRINT_DEBUG("Container pid not found"); + return -1; + } + + if (strstr(output, "error opening") != NULL) { + return -1; + } + + int pid = -1; + char *tmp = strstr(output, "PID:"); + if (tmp != NULL) { + pid = atoi(output+4); + } + + return pid; +} + static int get_container_pid(const char *c_name) { if (c_name == NULL) { @@ -90,6 +156,23 @@ static int get_container_pid(const char *c_name) return pid; } +static int _lxc_run_cmd(const char *ct_name, char *sub_cmd, char *output, size_t len) +{ + if (ct_name == NULL || sub_cmd == NULL) { + return -1; + } + + char cmd[MAX_BUFFER_LEN] = {0}; + if ((strlen(ct_name) + strlen(sub_cmd) + 11) >= sizeof(cmd)) { + PRINT_ERR("Command length too large"); + return -1; + } + + snprintf(cmd, sizeof(cmd), "lxc-attach %s -- %s", ct_name, sub_cmd); + return run_cmd(cmd, output, len); +} + + static int crun_run_cmd(const char *ct_name, char *sub_cmd, char *output, size_t len) { if (ct_name == NULL || sub_cmd == NULL) { @@ -106,7 +189,17 @@ static int crun_run_cmd(const char *ct_name, char *sub_cmd, char *output, size_t return run_cmd(cmd, output, len); } -static void get_memory_info(const char *ct_name, int *avail_mem, int *alloc_mem) +static int __run_cmd(const char *type, const char *ct_name, char *sub_cmd, char *output, size_t len) +{ + if (strcmp(type, "crun") == 0) { + return crun_run_cmd(ct_name, sub_cmd, output, len); + } else { + return _lxc_run_cmd(ct_name, sub_cmd, output, len); + } + return -1; +} + +static void get_memory_info(const char *type, const char *ct_name, int *avail_mem, int *alloc_mem) { char cmd[1024] = {0}; char output[1024] = {0}; @@ -116,7 +209,7 @@ static void get_memory_info(const char *ct_name, int *avail_mem, int *alloc_mem) } snprintf(cmd, sizeof(cmd), "grep MemTotal /proc/meminfo"); - if (crun_run_cmd(ct_name, cmd, output, sizeof(output)) != 0) { + if (__run_cmd(type, ct_name, cmd, output, sizeof(output)) != 0) { return; } @@ -126,7 +219,7 @@ static void get_memory_info(const char *ct_name, int *avail_mem, int *alloc_mem) memset(output, 0, sizeof(output)); snprintf(cmd, sizeof(cmd), "grep MemFree /proc/meminfo"); - if (crun_run_cmd(ct_name, cmd, output, sizeof(output)) != 0) { + if (__run_cmd(type, ct_name, cmd, output, sizeof(output)) != 0) { return; } @@ -135,7 +228,7 @@ static void get_memory_info(const char *ct_name, int *avail_mem, int *alloc_mem) } } -static void get_disk_space_info(const char *ct_name, int *avail_disk, int *alloc_disk) +static void get_disk_space_info(const char *type, const char *ct_name, int *avail_disk, int *alloc_disk) { char cmd[1024] = {0}; char output[MAX_BUFFER_LEN] = {0}; @@ -145,7 +238,7 @@ static void get_disk_space_info(const char *ct_name, int *avail_disk, int *alloc } snprintf(cmd, sizeof(cmd), "df -P / | tail -n +2"); - if (crun_run_cmd(ct_name, cmd, output, sizeof(output)) != 0) { + if (__run_cmd(type, ct_name, cmd, output, sizeof(output)) != 0) { return; } @@ -157,7 +250,7 @@ static void get_disk_space_info(const char *ct_name, int *avail_disk, int *alloc sscanf(output, "%254s %d %d %d", filesystem, alloc_disk, &used_disk, avail_disk); } -static void get_host_info(const char *ct_name, char *vendor, int vend_len, char *ver, int ver_len) +static void get_host_info(const char *type, const char *ct_name, char *vendor, int vend_len, char *ver, int ver_len) { char cmd[1024] = {0}; char output[MAX_BUFFER_LEN] = {0}; @@ -167,7 +260,7 @@ static void get_host_info(const char *ct_name, char *vendor, int vend_len, char } snprintf(cmd, sizeof(cmd), "uname -n"); - if (crun_run_cmd(ct_name, cmd, output, sizeof(output)) != 0) { + if (__run_cmd(type, ct_name, cmd, output, sizeof(output)) != 0) { return; } @@ -178,7 +271,7 @@ static void get_host_info(const char *ct_name, char *vendor, int vend_len, char memset(output, 0, sizeof(output)); snprintf(cmd, sizeof(cmd), "uname -r"); - if (crun_run_cmd(ct_name, cmd, output, sizeof(output)) != 0) { + if (__run_cmd(type, ct_name, cmd, output, sizeof(output)) != 0) { return; } @@ -527,7 +620,8 @@ void populate_crun_eu(ExecEnv_t *ee, const char *oci_uci_path) swmod_uci_foreach_section_safe(SWMOD_OCI_DU_UCI, "du_eu_assoc", stmp, s) { const char *type = swmod_uci_get_value_by_section(s, "type"); const char *status = swmod_uci_get_value_by_section(s, "du_status"); - if (strcmp(type, "crun") == 0 && strcmp(status, "Installed") == 0) { + + if ((strcmp(type, "crun") == 0 || strcmp(type, "lxc") == 0) && strcmp(status, "Installed") == 0) { ExecUnit new; memset(&new, 0, sizeof(ExecUnit)); new.eu_exists = true; @@ -550,34 +644,46 @@ void populate_crun_eu(ExecEnv_t *ee, const char *oci_uci_path) const char *auto_start = swmod_uci_get_value_by_section(s, "autostart"); new.autostart = uci_str_to_bool(auto_start); - int pid = get_container_pid(name); + int pid = -1; + if (strcmp(type, "crun") == 0) { + pid = get_container_pid(name); + } else { + pid = get_lxc_pid(name); + } + if (pid == -1) { snprintf(new.euid, sizeof(new.euid), "Unknown"); } else { snprintf(new.euid, sizeof(new.euid), "%d", pid); } - char *ct_status = get_container_status(name); + char *ct_status = NULL; + if (strcmp(type, "crun") == 0) { + ct_status = get_container_status(name); + } else { + ct_status = get_lxc_status(name); + } + if (strcmp(ct_status, "Up") == 0) { swmod_strncpy(new.state, "Active", sizeof(new.state)); /* get memory space limits */ int avail_memory = 0, alloc_memory = 0; - get_memory_info(name, &avail_memory, &alloc_memory); + get_memory_info(type, name, &avail_memory, &alloc_memory); new.memory_space = alloc_memory; /* get disk space info */ int avail_disk = 0, alloc_disk = 0; - get_disk_space_info(name, &avail_disk, &alloc_disk); + get_disk_space_info(type, name, &avail_disk, &alloc_disk); new.disk_space = alloc_disk; /* get vendor and version info */ - get_host_info(name, new.vendor, sizeof(new.vendor), new.version, sizeof(new.version)); + get_host_info(type, name, new.vendor, sizeof(new.vendor), new.version, sizeof(new.version)); } else { swmod_strncpy(new.state, "Idle", sizeof(new.state)); } - swmod_strncpy(new.description, "This is a CRUN container", sizeof(new.description)); + snprintf(new.description, sizeof(new.description), "This is a %s container", type); get_crun_fault_code(name, new.fault_code, sizeof(new.fault_code)); swmod_add_eu_in_list(&ee->eu_list, &new); } diff --git a/templates/lxc-iopsys b/templates/lxc-iopsys index fe9c75d3d5e8e5d3b78602b6c132ac550b254252..95b414823d6a147372d8b2cb9d323f8476ea9dce 100755 --- a/templates/lxc-iopsys +++ b/templates/lxc-iopsys @@ -411,12 +411,6 @@ if ! copy_prereq "${rootfs}"; then exit 1 fi -uci_path=$(dirname "${path}") -cfg=$(uci -c "${uci_path}" -q add lxccontainer container) -if [ -n "${cfg}" ]; then - uci -c "${uci_path}" -q set lxccontainer."${cfg}".name="${name}" - uci -c "${uci_path}" -q set lxccontainer."${cfg}".type='lxc' - uci -c "${uci_path}" -q set lxccontainer."${cfg}".autostart='1' - uci -c "${uci_path}" -q set lxccontainer."${cfg}".timeout='300' - uci -c "${uci_path}" commit lxccontainer +if command -v crun_create; then + crun_create -c -n "$name" fi