view src/main.rs @ 11:9fac2c578228

...
author AnaTofuZ <anatofuz@gmail.com>
date Thu, 29 Oct 2020 09:44:38 +0900
parents 188bf8ab3e81
children 0df4d067badb
line wrap: on
line source

use clap::Clap;
use nix;
use std::process::Command;

#[derive(Clap)]
#[clap(version = "1.0", author = "AnaTofuZ <anatofuz@cr.ie.u-ryukyu.ac.jp>")]
struct Opts {
    #[clap(subcommand)]
    subcmd: SubCommand,
}

#[derive(Clap)]
enum SubCommand {
    List(List),
    Undefine(UnDefine),
    Define(Define),
    Shutdown(Shutdown),
    Destroy(Destroy),
    Console(Console),
    Start(Start),
    Ttyconsole(TTyConsole),
    VNCDisplay(VNCDisplay)
    //todo define-gdb dumpxml 
}

/// define (but don't start) a domain from an template XML file
#[derive(Clap)]
struct Define {
    name: String,
}

// vncdisplay
#[derive(Clap)]
struct VNCDisplay {
    name_or_id: String,
}

/// undefine a domain
#[derive(Clap)]
struct UnDefine {
    name: String,
}

/// start a (previously defined) inactive domain
#[derive(Clap)]
struct Start {
    name: String,
}

/// tty console
#[derive(Clap)]
struct TTyConsole {
    name_or_id: String,
}

/// gracefully shutdown a domain
#[derive(Clap)]
struct Shutdown {
    name: String,
}

/// list domains
#[derive(Clap)]
struct List {}

/// destroy (stop) a domain
#[derive(Clap)]
struct Destroy {
    name: String,
}

/// connect to the guest console
#[derive(Clap)]
struct Console {
    name_or_id: String,
}

struct ListDumpMsg {
    info_msg: String,
    border_line: String,
}

struct VM {
    id: u32,
    name: String,
    is_vm_running: bool,
}

fn main() {
    let opts: Opts = Opts::parse();

    let uid = getuid();
    let gid = getgid();
    let user_name = getlogin(uid);
    println!("uid: {} gid: {} name: {}", uid, gid, user_name);

    match opts.subcmd {
        SubCommand::List(_) => {
            set_root_id();
            let (ldump_msg, vm_list_strs) = list_command(user_name);
            println!("{}\n{}", ldump_msg.info_msg, ldump_msg.border_line);
            for vm_info in vm_list_strs {
                println!("{}", vm_info);
            }
        }
        SubCommand::Define(name) => {}
        SubCommand::Shutdown(name) => {}
        SubCommand::Console(name) => {}

        SubCommand::Destroy(name_or_id) => {}
        _ => {}
    }

    //set_root_id();
    //list_command(user_name);
}

fn getlogin(uid: u32) -> &'static str {
    use std::ffi::CStr;
    let user_passwd = unsafe { nix::libc::getpwuid(uid) };
    let c_str = unsafe { CStr::from_ptr((*user_passwd).pw_name) };
    return c_str.to_str().unwrap();
}

fn getuid() -> u32 {
    let uid_struct = nix::unistd::getuid();
    return uid_struct.into();
}

fn getgid() -> u32 {
    let gid_struct = nix::unistd::getgid();
    return gid_struct.into();
}

fn list_command(user_name: &'static str) -> (ListDumpMsg, Vec<String>) {
    let output = Command::new("virsh")
        .arg("list")
        .arg("--all")
        .output()
        .expect("failed to virsh");
    let virsh_list = String::from_utf8_lossy(&output.stdout);
    let mut virsh_list = virsh_list.split("\n");

    let info_msg = virsh_list.next().unwrap();
    let border_line = virsh_list.next().unwrap();
    let ldump_msg = ListDumpMsg {
        info_msg: String::from(info_msg),
        border_line: String::from(border_line),
    };

    return (
        ldump_msg,
        virsh_list
            .filter(|&x| x.contains(user_name))
            .map(|x| x.to_string())
            .collect(),
    );
}

fn set_root_id() {
    let id = 0;
    match nix::unistd::seteuid(nix::unistd::Uid::from_raw(id)) {
        Err(err) => panic!("failed seteuid {}", err),
        Ok(_) => {}
    }
    match nix::unistd::setegid(nix::unistd::Gid::from_raw(id)) {
        Err(err) => panic!("failed setedid{}", err),
        Ok(_) => {}
    }

    match nix::unistd::setuid(nix::unistd::Uid::from_raw(id)) {
        Err(err) => panic!("failed setuid {}", err),
        Ok(_) => {}
    }

    match nix::unistd::setgid(nix::unistd::Gid::from_raw(id)) {
        Err(err) => panic!("failed setdid{}", err),
        Ok(_) => {}
    }
}

fn create_new_vm(user_name: &'static str, vm_name: &'static str, debug_kernel: bool) {}