0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen/* liblxcapi
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen *
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * Copyright © 2013 Oracle.
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen *
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * Authors:
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * Dwight Engen <dwight.engen@oracle.com>
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen *
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * This program is free software; you can redistribute it and/or modify
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * it under the terms of the GNU General Public License version 2, as
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * published by the Free Software Foundation.
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen *
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * This program is distributed in the hope that it will be useful,
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * but WITHOUT ANY WARRANTY; without even the implied warranty of
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * GNU General Public License for more details.
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen *
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * You should have received a copy of the GNU General Public License along
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * with this program; if not, write to the Free Software Foundation, Inc.,
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen */
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
948955a2d6f8e4e28bceada9666c5831de4a6bb8Stéphane Graber#include <lxc/lxccontainer.h>
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen#include <errno.h>
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen#include <unistd.h>
4012c89148c42dc7c15809bec348746681f96eddStéphane Graber#include <stdio.h>
95ee490bbdb97ab2b4f1dfa63a0a26e0dd1c2f17Stéphane Graber#include <string.h>
95ee490bbdb97ab2b4f1dfa63a0a26e0dd1c2f17Stéphane Graber#include <sys/stat.h>
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen#define TTYCNT 4
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen#define TTYCNT_STR "4"
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen#define TSTNAME "lxcconsoletest"
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen#define MAXCONSOLES 512
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen#define TSTERR(fmt, ...) do { \
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen fprintf(stderr, "%s:%d " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen} while (0)
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engenstatic void test_console_close_all(int ttyfd[MAXCONSOLES],
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen int masterfd[MAXCONSOLES])
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen{
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen int i;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen for (i = 0; i < MAXCONSOLES; i++) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (masterfd[i] != -1) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen close(masterfd[i]);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen masterfd[i] = -1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (ttyfd[i] != -1) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen close(ttyfd[i]);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen ttyfd[i] = -1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen}
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engenstatic int test_console_running_container(struct lxc_container *c)
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen{
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen int nrconsoles, i, ret = -1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen int ttynum [MAXCONSOLES];
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen int ttyfd [MAXCONSOLES];
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen int masterfd[MAXCONSOLES];
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen for (i = 0; i < MAXCONSOLES; i++)
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen ttynum[i] = ttyfd[i] = masterfd[i] = -1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen ttynum[0] = 1;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen ret = c->console_getfd(c, &ttynum[0], &masterfd[0]);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (ret < 0) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen TSTERR("console allocate failed");
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen goto err1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen ttyfd[0] = ret;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (ttynum[0] != 1) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen TSTERR("console allocate got bad ttynum %d", ttynum[0]);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen goto err2;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen /* attempt to alloc same ttynum */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen ret = c->console_getfd(c, &ttynum[0], &masterfd[1]);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (ret != -1) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen TSTERR("console allocate should fail for allocated ttynum %d", ttynum[0]);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen goto err2;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen close(masterfd[0]); masterfd[0] = -1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen close(ttyfd[0]); ttyfd[0] = -1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen /* ensure we can allocate all consoles, we do this a few times to
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * show that the closes are freeing up the allocated slots
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen */
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen for (i = 0; i < 10; i++) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen for (nrconsoles = 0; nrconsoles < MAXCONSOLES; nrconsoles++) {
b515981702133b9aaea1aff378493f054c14d46cDwight Engen ret = c->console_getfd(c, &ttynum[nrconsoles], &masterfd[nrconsoles]);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (ret < 0)
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen break;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen ttyfd[nrconsoles] = ret;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (nrconsoles != TTYCNT) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen TSTERR("didn't allocate all consoles %d != %d", nrconsoles, TTYCNT);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen goto err2;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen test_console_close_all(ttyfd, masterfd);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen ret = 0;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engenerr2:
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen test_console_close_all(ttyfd, masterfd);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engenerr1:
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen return ret;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen}
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen/* test_container: test console function
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen *
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * @lxcpath : the lxcpath in which to create the container
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * @group : name of the container group or NULL for default "lxc"
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * @name : name of the container
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen * @template : template to use when creating the container
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen */
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engenstatic int test_console(const char *lxcpath,
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen const char *group, const char *name,
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen const char *template)
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen{
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen int ret;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen struct lxc_container *c = NULL;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (lxcpath) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen ret = mkdir(lxcpath, 0755);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (ret < 0 && errno != EEXIST) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen TSTERR("failed to mkdir %s %s", lxcpath, strerror(errno));
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen goto out1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen ret = -1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if ((c = lxc_container_new(name, lxcpath)) == NULL) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen TSTERR("instantiating container %s", name);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen goto out1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (c->is_defined(c)) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen c->stop(c);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen c->destroy(c);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen c = lxc_container_new(name, lxcpath);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
dc23c1c817da5c13529432270e51d0f7f3b1e95eSerge Hallyn if (!c->createl(c, template, NULL, NULL, 0, NULL)) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen TSTERR("creating container %s", name);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen goto out2;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen c->load_config(c, NULL);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen c->set_config_item(c, "lxc.tty", TTYCNT_STR);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen c->save_config(c, NULL);
540f932aeb28274e8e7ea1e8f3a8e5889b88e1d6Stéphane Graber c->want_daemonize(c, true);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (!c->startl(c, 0, NULL)) {
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen TSTERR("starting container %s", name);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen goto out3;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen }
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen ret = test_console_running_container(c);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen c->stop(c);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engenout3:
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen c->destroy(c);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engenout2:
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen lxc_container_put(c);
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engenout1:
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen return ret;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen}
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engenint main(int argc, char *argv[])
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen{
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen int ret;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen ret = test_console(NULL, NULL, TSTNAME, "busybox");
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (ret < 0)
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen goto err1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen ret = test_console("/var/lib/lxctest2", NULL, TSTNAME, "busybox");
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen if (ret < 0)
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen goto err1;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen printf("All tests passed\n");
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engenerr1:
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen return ret;
0115f8fd27b1a31d367bb161a121694f92b45e62Dwight Engen}