X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=linux_usr%2Fv3_create.c;h=02bb87308f453cfc75a55e65103fe73a56af0576;hb=ae683f5cbd04c361a85861998749e9fc0faba822;hp=36057022bee8e93d0a17e8c03c993cac3dfa8229;hpb=ffd6d915b585a4a17a2d5b081313f0968885a105;p=palacios.git diff --git a/linux_usr/v3_create.c b/linux_usr/v3_create.c index 3605702..02bb873 100644 --- a/linux_usr/v3_create.c +++ b/linux_usr/v3_create.c @@ -3,7 +3,6 @@ * (c) Jack lange, 2010 */ - #include #include #include @@ -12,28 +11,80 @@ #include #include #include - +#include + + #include "v3_ctrl.h" +#include "ezxml.h" + +struct cfg_value { + char * tag; + char * value; +}; + +struct xml_option { + char * tag; + ezxml_t location; + struct xml_option * next; +}; + + +struct file_info { + int size; + char filename[2048]; + char id[256]; +}; + +#define MAX_FILES 256 +unsigned long long num_files = 0; +struct file_info files[MAX_FILES]; + int read_file(int fd, int size, unsigned char * buf); -int main(int argc, char* argv[]) { - char * filename = argv[1]; - char * name = argv[2]; - int guest_fd = 0; - int v3_fd = 0; + + +int create_vm(char * vm_name, void * img_data, unsigned int img_size) { struct v3_guest_img guest_img; - struct stat guest_stats; + int v3_fd = 0; int dev_idx = 0; memset(&guest_img, 0, sizeof(struct v3_guest_img)); - if (argc <= 2) { - printf("usage: v3_create \n"); + guest_img.size = img_size; + guest_img.guest_data = img_data; + strncpy(guest_img.name, vm_name, 127); + + + v3_fd = open(v3_dev, O_RDONLY); + + if (v3_fd == -1) { + printf("Error opening V3Vee control device\n"); return -1; } - printf("Creating guest: %s\n", filename); + dev_idx = ioctl(v3_fd, V3_CREATE_GUEST, &guest_img); + + + if (dev_idx < 0) { + printf("Error (%d) creating VM\n", dev_idx); + return -1; + } + + printf("VM (%s) created at /dev/v3-vm%d\n", vm_name, dev_idx); + + /* Close the file descriptor. */ + close(v3_fd); + + return 0; +} + + +int load_image(char * vm_name, char * filename) { + int guest_fd = 0; + struct stat guest_stats; + int img_size = 0; + void * img_data = NULL; guest_fd = open(filename, O_RDONLY); @@ -46,47 +97,342 @@ int main(int argc, char* argv[]) { printf("ERROR: Could not stat guest image file -- %s\n", filename); return -1; } + + img_size = guest_stats.st_size; + + // load guest image into user memory + img_data = malloc(img_size); + read_file(guest_fd, img_size, img_data); - guest_img.size = guest_stats.st_size; + close(guest_fd); + + printf("Guest image Loaded (size=%u)\n", img_size); + return create_vm(vm_name, img_data, img_size); + +} + + +ezxml_t open_xml_file(char * filename) { + + ezxml_t xml_input = ezxml_parse_file(filename); - // load guest image into user memory - guest_img.guest_data = malloc(guest_img.size); - if (!guest_img.guest_data) { - printf("ERROR: could not allocate memory for guest image\n"); - return -1; + if (xml_input == NULL) { + printf("Error: Could not open XML input file (%s)\n", filename); + return NULL; + } else if (strcmp("", ezxml_error(xml_input)) != 0) { + printf("%s\n", ezxml_error(xml_input)); + return NULL; } - read_file(guest_fd, guest_img.size, guest_img.guest_data); + return xml_input; +} + + +int find_xml_options(ezxml_t xml, struct xml_option ** opts) { + int num_opts = 0; + ezxml_t child = xml->child; + struct xml_option * next_opt = NULL; + + char * opt = (char *)ezxml_attr(xml, "opt_tag"); + + if (opt) { + next_opt = malloc(sizeof(struct xml_option)); + + memset(next_opt, 0, sizeof(struct xml_option)); + + next_opt->tag = opt; + next_opt->location = xml; + next_opt->next = NULL; + +// printf("Option found: %s\n", opt); + + *opts = next_opt; + num_opts++; + } + + + while (child) { + + fflush(stdout); + + if (next_opt != 0x0) { + num_opts += find_xml_options(child, &(next_opt->next)); + } else { + num_opts += find_xml_options(child, opts); + + if (*opts) { + next_opt = *opts; + } + } + + if (next_opt) { + while (next_opt->next) { + next_opt = next_opt->next; + } + } + + child = child->ordered; + } - close(guest_fd); + return num_opts; + +} + + +char * get_val(ezxml_t cfg, char * tag) { + char * attrib = (char *)ezxml_attr(cfg, tag); + ezxml_t txt = ezxml_child(cfg, tag); + + if ((txt != NULL) && (attrib != NULL)) { + printf("Invalid Cfg file: Duplicate value for %s (attr=%s, txt=%s)\n", + tag, attrib, ezxml_txt(txt)); + exit(-1); + } + + return (attrib == NULL) ? ezxml_txt(txt) : attrib; +} + + +int parse_aux_files(ezxml_t cfg_input) { + ezxml_t file_tags = NULL; + ezxml_t tmp_file_tag = NULL; + + // files are transformed into blobs that are slapped to the end of the file + + file_tags = ezxml_child(cfg_input, "files"); - printf("Loaded guest image. Creation begins.\n"); + tmp_file_tag = ezxml_child(file_tags, "file"); + + while (tmp_file_tag) { + char * filename = get_val(tmp_file_tag, "filename"); + struct stat file_stats; + char * id = get_val(tmp_file_tag, "id"); + char index_buf[256]; + + + if (stat(filename, &file_stats) != 0) { + perror(filename); + exit(-1); + } + + files[num_files].size = (unsigned int)file_stats.st_size; + strncpy(files[num_files].id, id, 256); + strncpy(files[num_files].filename, filename, 2048); + + snprintf(index_buf, 256, "%llu", num_files); + ezxml_set_attr_d(tmp_file_tag, "index", index_buf); + + num_files++; + tmp_file_tag = ezxml_next(tmp_file_tag); + } + + + return 0; +} + +int build_image(char * vm_name, char * filename, struct cfg_value * cfg_vals, int num_options) { + int i = 0; + ezxml_t xml = NULL; + struct xml_option * xml_opts = NULL; + int num_xml_opts = 0; + void * guest_img_data = NULL; + int guest_img_size = 0; + + + xml = open_xml_file(filename); + + // parse options + num_xml_opts = find_xml_options(xml, &xml_opts); - strncpy(guest_img.name, name, 127); + // printf("%d options\n", num_xml_opts); + // apply options + for (i = 0; i < num_options; i++) { + struct cfg_value * cfg_val = &cfg_vals[i]; + struct xml_option * xml_opt = xml_opts; - v3_fd = open(v3_dev, O_RDONLY); + while (xml_opt) { + if (strcasecmp(cfg_val->tag, xml_opt->tag) == 0) { + break; + } + + xml_opt = xml_opt->next; + } - if (v3_fd == -1) { - printf("Error opening V3Vee control device\n"); - return -1; + + if (!xml_opt) { + printf("Could not find Config option (%s) in XML file\n", cfg_val->tag); + return -1; + } + + ezxml_set_txt(xml_opt->location, cfg_val->value); } + - dev_idx = ioctl(v3_fd, V3_CREATE_GUEST, &guest_img); + // parse files + parse_aux_files(xml); + + // create image data blob + { + char * new_xml_str = ezxml_toxml(xml); + int file_data_size = 0; + int i = 0; + int offset = 0; + unsigned long long file_offset = 0; - if (dev_idx < 0) { - printf("Error (%d) creating VM\n", dev_idx); + /* Image size is: + 8 byte header + + 4 byte xml length + + xml strlen + + 8 bytes of zeros + + 8 bytes (number of files) + + num_files * 16 byte file header + + 8 bytes of zeroes + + file data + */ + for (i = 0; i < num_files; i++) { + file_data_size += files[i].size; + } + + guest_img_size = 8 + 4 + strlen(new_xml_str) + 8 + 8 + + (num_files * 16) + 8 + file_data_size; + + + guest_img_data = malloc(guest_img_size); + memset(guest_img_data, 0, guest_img_size); + + memcpy(guest_img_data, "v3vee\0\0\0", 8); + offset += 8; + + *(unsigned int *)(guest_img_data + offset) = strlen(new_xml_str); + offset += 4; + + memcpy(guest_img_data + offset, new_xml_str, strlen(new_xml_str)); + offset += strlen(new_xml_str); + + memset(guest_img_data + offset, 0, 8); + offset += 8; + + *(unsigned long long *)(guest_img_data + offset) = num_files; + offset += 8; + + + // The file offset starts at the end of the file list + file_offset = offset + (16 * num_files) + 8; + + for (i = 0; i < num_files; i++) { + *(unsigned int *)(guest_img_data + offset) = i; + offset += 4; + *(unsigned int *)(guest_img_data + offset) = files[i].size; + offset += 4; + *(unsigned long long *)(guest_img_data + offset) = file_offset; + offset += 8; + + file_offset += files[i].size; + + } + + memset(guest_img_data + offset, 0, 8); + offset += 8; + + + for (i = 0; i < num_files; i++) { + int fd = open(files[i].filename, O_RDONLY); + + if (fd == -1) { + printf("Error: Could not open aux file (%s)\n", files[i].filename); + return -1; + } + + read_file(fd, files[i].size, (unsigned char *)(guest_img_data + offset)); + + close(fd); + + offset += files[i].size; + + } + + free(new_xml_str); + + } + + printf("Guest Image Created (size=%u)\n", guest_img_size); + return create_vm(vm_name, guest_img_data, guest_img_size); +} + + + + + + +int main(int argc, char** argv) { + char * filename = NULL; + char * name = NULL; + int build_flag = 0; + int c = 0; + + opterr = 0; + + while (( c = getopt(argc, argv, "b")) != -1) { + switch (c) { + case 'b': + build_flag = 1; + break; + } + } + + if (argc - optind + 1 < 3) { + printf("usage: v3_create [-b] [cfg options]\n"); return -1; } - printf("VM (%s) created at /dev/v3-vm%d\n", name, dev_idx); + filename = argv[optind]; + name = argv[optind + 1]; - /* Close the file descriptor. */ - close(v3_fd); - + if (build_flag == 1) { + int cfg_idx = optind + 2; + int i = 0; + struct cfg_value * cfg_vals = NULL; + + printf("Building VM Image (cfg=%s) (name=%s) (%d config options)\n", filename, name, argc - cfg_idx); + + cfg_vals = malloc(sizeof(struct cfg_value) * argc - cfg_idx); + + + + while (i < argc - cfg_idx) { + char * tag = NULL; + char * value = NULL; + + value = argv[cfg_idx + i]; + + tag = strsep(&value, "="); + // parse + + if (value == NULL) { + printf("Invalid Option format: %s\n", argv[cfg_idx + i]); + return -1; + } + + cfg_vals[i].tag = tag; + cfg_vals[i].value = value; + + printf("Config option: %s: %s\n", tag, value); + + + i++; + } + + return build_image(name, filename, cfg_vals, argc - cfg_idx); + + + } else { + printf("Loading VM Image (img=%s) (name=%s)\n", filename, name); + return load_image(name, filename); + } return 0; }