Search code examples
linuxdebianvirtualizationbootopenvz

How OpenVZ boot OS?


I bought VPS on OpenVZ virtualization and enabled Debian guest OS.

Guest /boot dir is empty. /etc/inittab is empty.

How is the OS initialization process performed?

What is the meaning of reboot for OpenVZ container?


Solution

  • After research I clone vzctl tool as main job about starting/stopping done here:

    git clone https://github.com/OpenVZ/vzctl.git
    git clone https://github.com/OpenVZ/libvzctl.git
    

    vzctl uses libvzctl where you can find https://github.com/OpenVZ/libvzctl/blob/master/lib/env.c#L783:

    int exec_init(struct start_param *param)
    {
       char cid[STR_SIZE];
       char *argv[] = {"init", "-z", "      ", NULL};
       char *envp[] = {"HOME=/", "TERM=linux", cid, NULL};
       char **env;
       int errcode = 0;
       logger(1, 0, "Starting init");
    
       if (stat_file("/sbin/init") == 0 &&
                       stat_file("/ertc/init") == 0  &&
                       stat_file("/bin/init") == 0)
               errcode = VZCTL_E_BAD_TMPL;
    
       if (write(param->err_p[1], &errcode, sizeof(errcode)) == -1)
               logger(-1, errno, "exec_init: write(param->err_p[1]");
    
       snprintf(cid, sizeof(cid), "container="SYSTEMD_CTID_FMT, EID(param->h));
       env = makeenv(envp, &param->h->env_param->misc->ve_env);
       if (env == NULL)
               return VZCTL_E_NOMEM;
    
       execve("/sbin/init", argv, env);
       execve("/etc/init", argv, env);
       execve("/bin/init", argv, env);
       free_ar_str(env);
       free(env);
    
       return VZCTL_E_BAD_TMPL;
    }
    

    Stop done by https://github.com/OpenVZ/libvzctl/blob/master/lib/env.c#L103:

    int real_env_stop(int stop_mode)
    {
      logger(10, 0, "* stop mode %d", stop_mode);
      close_fds(1, -1);
      /* Disable fsync. The fsync will be done by umount() */
      configure_sysctl("/proc/sys/fs/fsync-enable", "0");
      switch (stop_mode) {
      case M_HALT: {
              char *argv[] = {"halt", NULL};
              char *argv_init[] = {"init", "0", NULL};
              execvep(argv[0], argv, NULL);
              execvep(argv_init[0], argv_init, NULL);
              break;
      }
      case M_REBOOT: {
              char *argv[] = {"reboot", NULL};
              execvep(argv[0], argv, NULL);
              break;
      }
      case M_KILL:
              return syscall(__NR_reboot, LINUX_REBOOT_MAGIC1,
                      LINUX_REBOOT_MAGIC2,
                      LINUX_REBOOT_CMD_POWER_OFF, NULL);
      }
      return -1;
    }
    

    Before calling /sbin/init vzctl make some checks (like is system already run or mounted, some file present, etc), halt if required, mount fs, make some isolated analog of chroot and do /sbin/init.

    CONCLUSION OpenVZ doesn't use grub/linux-image/initrd from guest OS and do direct call to first that find among:

    "/sbin/init"
    "/etc/init"
    "/bin/init"
    

    in guest OS. In order to stop it uses one of

    halt
    init 0
    reboot
    

    from guest OS. Container inicialization (security, isolation, mounts, etc) isn't interested from user point view for guest OS booting process.