view ie-virsh.c @ 35:f01dc83040a9

Change mount point and template xml
author atton
date Thu, 05 Nov 2015 18:28:03 +0900
parents ccac5d8090f6
children ebeeb6c20d0a
line wrap: on
line source


#include <stdlib.h>
#include <unistd.h>

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

#include <sys/types.h>
#include <regex.h>

/* Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License */

#define command "/usr/bin/virsh"
/* #define command "/usr/local/bin/virsh" */
#define list_command "/usr/bin/virsh list --all"
/* #define list_command "/usr/local/bin/virsh list --all" */
#define start_command "start"
#define stop_command "destroy"
#define define_command "define"
#define undefine_command "undefine"
#define dumpxml_command "dumpxml"
#define console_command "console"
#define debug_command "debug"


const char *guests[] = {};
const char *managers[] = {"atton"};
const char students_sym[] = "students";
const char managers_sym[] = "managers";
const char guests_sym[] = "guests";
const char delimiter[] = "_";

static char bad_name[] = "Bad vmname. Try 01 or 02 ... 04\n";

const char newvm_command[] = "/usr/local/bin/newvm.py -c /etc/libvirt/qemu/fedora23.xml -n ";

enum {
    NAME_LENGTH = 50,
    VM_NAME_LENGTH = 50
};

enum {
    STUDENTS,
    GUESTS,
    MANAGERS
};

#define VMNAME_MAX (512)

typedef struct vmlist {
    char name[VMNAME_MAX];
    struct vmlist *next;
} VMLIST, *VMLISTPTR;

#define NEW(type)  ((type*)malloc(sizeof(type)))

/* Define global variables */

VMLISTPTR
get_vmlist(regex_t *list_pattern)
{
    VMLISTPTR list = NEW(VMLIST);
    VMLISTPTR p = list ;
    p->name[0] = 0;
    p->next = 0;
    FILE *fp = popen(list_command,"r");
    while(fgets(p->name,VMNAME_MAX,fp)!=NULL) {
        if (regexec(list_pattern, p->name, (size_t) 0, NULL, 0)) continue;
        p->next = NEW(VMLIST);
        p = p->next;
    }
    p->name[0] = 0;
    pclose(fp);
    return list;
}

void 
print_vmlist(VMLISTPTR list) 
{
    for(;list && list->name[0]; list=list->next) {
        fprintf(stdout, "   %s\n",list->name);
    }
}

int
check_vmlist_name(VMLISTPTR list, char *arg)
{
    for(;list && list->name[0]; list=list->next) {
        if (strstr(list->name,arg)!=0) return 1;
    }
    return 0;
}

void
change_delimiter_to_slash(char *name)
{
    long size = sizeof(char) * VM_NAME_LENGTH;
    int i = 0;
    for (; i < size; i++) {
        if (name[i] == '_') {
            name[i] = '/';
        }
    }
}

int
check_name(const char *p)
{
    if (!p) return  1;
    for(;*p;p++) {
        char c = *p;
        if (c<=' ') return 1;
        if (('a'<=c && c<='z') ||
                ('0'<=c && c<='9') ||
                ('/'==c ) ||
                ('-'==c )) continue;
        return 1;
        printf("%c", c);
    }
    return 0;
}

void 
usage()
{
    printf("Usage: COMMAND [define|list|start|destroy|xmldump|undefine|console] [vm-name]\n");
    printf("   vm-name should be 01 - 04\n");
}

int
check_user_name(const char *account_name)
{
    const char *regex = "[ek]([0-9]{6})";
    
    regex_t *pattern = NEW(regex_t);
    int ret = 1;

    if (regcomp(pattern, regex, REG_EXTENDED|REG_NEWLINE) != 0) {
        exit(0);
    }

    ret = regexec(pattern, account_name, (size_t) 0, NULL, 0);
    regfree(pattern);

    if (!ret){
        return STUDENTS;
    }

    const int managers_num = sizeof(managers) / sizeof(managers[0]);
    int i = 0;
    for (; i < managers_num; i++) {
        if (strncmp(account_name, managers[i], NAME_LENGTH) == 0) {
            return MANAGERS;
        }
    }

    const int guests_num = sizeof(guests) / sizeof(guests[0]);
    int j = 0;
    for (; j < guests_num; j++) {
        if (strncmp(account_name, guests[j], NAME_LENGTH) == 0) {
            return GUESTS;
        }
    }

    return -1;
}

void
bind_name(char *name, const char *first,  const char *second)
{
    strncat(name, first, VM_NAME_LENGTH);
    strncat(name, delimiter, VM_NAME_LENGTH);
    strncat(name, second, VM_NAME_LENGTH);
    strncat(name, delimiter, VM_NAME_LENGTH);
    return;
}

void
make_vm_name(char *vm_name, const int account_type, const char *account_name, const char *vm_num)
{
    switch(account_type) {
        case STUDENTS:
            strncat(vm_name, students_sym, VM_NAME_LENGTH);
            strncat(vm_name, delimiter, VM_NAME_LENGTH);
            strncat(vm_name, account_name, 3);
            strncat(vm_name, delimiter, VM_NAME_LENGTH);
            strncat(vm_name, account_name, VM_NAME_LENGTH);
            strncat(vm_name, delimiter, VM_NAME_LENGTH);
            break;
        case GUESTS:
            bind_name(vm_name, guests_sym, account_name);
            break;
        case MANAGERS:
            bind_name(vm_name, managers_sym, account_name);
            break;
        default :
            fprintf(stderr, "Error: no registered type name.");
            return;
    }

    strncat(vm_name, vm_num, VM_NAME_LENGTH);
}

/* main(int argc, char **argv) - main process loop */

int main(int argc, char **argv)
{
    /* Set euid and egid to actual user */
    int uid    = getuid();
    int gid    = getgid();
    char *name = getlogin();

    printf("uid %d gid %d name %s\n", uid,gid,name);
    setegid(getgid());
    seteuid(getuid());

    int account_type = check_user_name(name);
    if (account_type < 0) {
        fprintf(stderr, "Parmission denied. :%s\n", name);
    }


    /* Confirm user is in GROUP(999) group */

    /*
       if ( gid != 999 ) {
       printf("User Not Authorized!  Exiting...\n");
       exit(1);
       }
     */

    if (argc<2) {
        usage();
        exit(0);
    }

    /* Set uid, gid, euid and egid to root */

    setegid(0);
    seteuid(0);
    setgid(0);
    setuid(0);

    char *vm_name = (char *)malloc(sizeof(char) * VM_NAME_LENGTH);
    vm_name[0] = '\0';
    if (!(strncmp(argv[1], "list", 4) == 0 || strncmp(argv[1], debug_command, 5) == 0)) {
        const char *regex = "0[1-4]";
        regex_t *num_pattern = NEW(regex_t);

        if (regcomp(num_pattern, regex, REG_EXTENDED|REG_NEWLINE) != 0) {
            exit(0);
        }

        int ret = regexec(num_pattern, argv[2], (size_t) 0, NULL, 0);
        regfree(num_pattern);

        if (ret){
            fprintf(stderr, "This name is not number: %s\n", argv[2]);
            exit(0);
        }

        make_vm_name(vm_name, account_type, name, argv[2]);
    }

    if (argc>=3) {
        if ( strncmp(argv[1], "define", 6) == 0 ) {
            if (check_name(argv[2])) {
                fprintf(stderr, bad_name);
                exit(0);
            }
            char *vm_path = (char *)malloc(sizeof(char) * VM_NAME_LENGTH);
            strncpy(vm_path, vm_name, VM_NAME_LENGTH);
            change_delimiter_to_slash(vm_path);
            char exec[1024];
            strncpy(exec, newvm_command ,900);
            strncat(exec, vm_path,1000);
            fprintf(stdout, "excuting %s\n",exec );
            system(exec);
            free(vm_path);
        }
    }

    regex_t *pattern = NEW(regex_t);
    if (regcomp(pattern, name, 0) != 0) {
        exit(0);
    }

    VMLISTPTR vmlist = get_vmlist(pattern);

    char name_xml[1024];
    name_xml[0] = 0;

    if (argc>=3) {
        if ( strncmp(argv[1], "define", 6) == 0 ) {
            char *vm_path = (char *)malloc(sizeof(char) * VM_NAME_LENGTH);
            vm_path[0] = '\0';
            strncpy(vm_path, vm_name, VM_NAME_LENGTH);
            change_delimiter_to_slash(vm_path);
            printf("%s\n", vm_path);
            strncpy(name_xml, vm_path,900);
            strncat(name_xml,".xml",1000);
            free(vm_path);
        } else if (check_vmlist_name(vmlist, argv[2])==0) {
            fprintf(stderr, bad_name);
            print_vmlist(vmlist);
            exit(0);
        }
    } 

    /* Check argv for proper arguments and run 
     * the corresponding script, if invoked.
     */

    if (argv[1]==0 || strncmp(argv[1], "list", 4) == 0 ) {
        print_vmlist(vmlist);
    } else if (strncmp(argv[1], start_command, 5) == 0) {
        if (execl(command, command, start_command, vm_name, NULL) < 0) {
            perror("Execl:");
        }
    } else if ( strncmp(argv[1], stop_command, 4) == 0 ) {
        if (execl(command, command, stop_command, vm_name, NULL) < 0) {
            perror("Execl:");
        }
    } else if ( strncmp(argv[1], dumpxml_command, 7) == 0 ) {
        if (execl(command, command, dumpxml_command, vm_name, NULL) < 0) {
            perror("Execl:");
        }
    } else if ( strncmp(argv[1], console_command, 8) == 0 ) {
        if (execl(command, command, console_command, vm_name, NULL) < 0) {
            perror("Execl:");
        }
    } else if (strncmp(argv[1], define_command, 6) == 0 ) {
        /* chdir("/usr/local/etc/libvirt/qemu"); */
        chdir("/etc/libvirt/qemu");
        if (execl(command, command, define_command, name_xml, NULL) < 0) {
            perror("Execl:");
        }
    } else if ( strncmp(argv[1], undefine_command, 8) == 0 ) {
        /* chdir("/usr/local/etc/libvirt/qemu"); */
        chdir("/etc/libvirt/qemu");
        if (execl(command, command, undefine_command, vm_name, NULL) < 0) {
            perror("Execl:");
        }
    } else if (strncmp(argv[1], debug_command, 5) == 0) {
        char *user_name = (char *)malloc(sizeof(char) * VM_NAME_LENGTH);
        strncpy(user_name,  "\0", 1);
        make_vm_name(user_name, account_type, name, debug_command);

        char str_uid[1024];
        sprintf(str_uid, "%d", uid);

        char debug_exec[1026];
        sprintf(debug_exec, "/usr/local/bin/debugvm.py --name %s --uid %s --config %s", user_name, str_uid, "/etc/libvirt/qemu/debugvm.xml");
        free(user_name);

        printf("debug_exec::%s \n", debug_exec);

        char gdb_exec[1024];
        strncpy(gdb_exec, "/usr/bin/gdb",900);
//      strncat(gdb_exec, " /usr/lib/debug/lib/modules/3.17.4-200.fc20.x86_64/vmlinux", 900);
//      system(gdb_exec);
    } else {
        usage();
        exit(1);
    }
    free(vm_name);
    exit(0);
}

/* end */