Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


update palacios mempool status when onlining memory in userspace
[palacios.git] / linux_usr / v3_create.c
1 /* 
2  * V3 Control utility
3  * (c) Jack lange, 2010
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <fcntl.h> 
9 #include <sys/ioctl.h> 
10 #include <sys/stat.h> 
11 #include <sys/types.h> 
12 #include <unistd.h> 
13 #include <string.h>
14 #include <getopt.h> 
15
16
17 #include "v3_ctrl.h"
18 #include "ezxml.h"
19
20 struct cfg_value {
21     char * tag;
22     char * value;
23 };
24
25 struct xml_option {
26     char * tag;
27     ezxml_t location;
28     struct xml_option * next;
29 };
30
31
32 struct file_info {
33     int size;
34     char filename[2048];
35     char id[256];
36 };
37
38 #define MAX_FILES 256
39 unsigned long long num_files = 0;
40 struct file_info files[MAX_FILES];
41
42
43 int read_file(int fd, int size, unsigned char * buf);
44
45
46
47 int create_vm(char * vm_name, void * img_data, unsigned int img_size) {
48     struct v3_guest_img guest_img;
49     int v3_fd = 0;
50     int dev_idx = 0;
51
52     memset(&guest_img, 0, sizeof(struct v3_guest_img));
53
54     guest_img.size = img_size;
55     guest_img.guest_data = img_data;
56     strncpy(guest_img.name, vm_name, 127);
57
58
59     v3_fd = open(v3_dev, O_RDONLY);
60
61     if (v3_fd == -1) {
62         printf("Error opening V3Vee control device\n");
63         return -1;
64     }
65
66     dev_idx = ioctl(v3_fd, V3_CREATE_GUEST, &guest_img); 
67
68
69     if (dev_idx < 0) {
70         printf("Error (%d) creating VM\n", dev_idx);
71         return -1;
72     }
73
74     printf("VM (%s) created at /dev/v3-vm%d\n", vm_name, dev_idx);
75
76     /* Close the file descriptor.  */ 
77     close(v3_fd); 
78
79     return 0;
80 }
81
82
83 int load_image(char * vm_name, char * filename) {
84     int guest_fd = 0;
85     struct stat guest_stats;
86     int img_size = 0;
87     void * img_data = NULL;
88
89     guest_fd = open(filename, O_RDONLY); 
90
91     if (guest_fd == -1) {
92         printf("Error Opening guest image: %s\n", filename);
93         return -1;
94     }
95
96     if (fstat(guest_fd, &guest_stats) == -1) {
97         printf("ERROR: Could not stat guest image file -- %s\n", filename);
98         return -1;
99     }
100     
101     img_size = guest_stats.st_size;
102
103     // load guest image into user memory
104     img_data = malloc(img_size);
105
106     read_file(guest_fd, img_size, img_data);
107     
108     close(guest_fd);
109
110     printf("Guest image Loaded (size=%u)\n", img_size);
111     return create_vm(vm_name, img_data, img_size);
112
113 }
114
115
116 ezxml_t open_xml_file(char * filename) {
117
118     ezxml_t xml_input = ezxml_parse_file(filename);
119     
120     if (xml_input == NULL) {
121         printf("Error: Could not open XML input file (%s)\n", filename);
122         return NULL;
123     } else if (strcmp("", ezxml_error(xml_input)) != 0) {
124         printf("%s\n", ezxml_error(xml_input));
125         return NULL;
126     }
127
128     return xml_input;
129 }
130
131
132 int find_xml_options(ezxml_t xml,  struct xml_option ** opts) {
133     int num_opts = 0;
134     ezxml_t child = xml->child;
135     struct xml_option * next_opt = NULL;
136
137     char * opt = (char *)ezxml_attr(xml, "opt_tag");
138
139     if (opt) {
140         next_opt = malloc(sizeof(struct xml_option));
141
142         memset(next_opt, 0, sizeof(struct xml_option));
143
144         next_opt->tag = opt;
145         next_opt->location = xml;
146         next_opt->next = NULL;
147
148 //      printf("Option found: %s\n", opt);
149
150         *opts = next_opt;
151         num_opts++;
152     }
153
154
155     while (child) {
156
157         fflush(stdout);
158
159         if (next_opt != 0x0) {
160             num_opts += find_xml_options(child, &(next_opt->next));
161         } else {
162             num_opts += find_xml_options(child, opts);
163
164             if (*opts) {
165                 next_opt = *opts;
166             }
167         }
168
169         if (next_opt) {
170             while (next_opt->next) {
171                 next_opt = next_opt->next;
172             }
173         }
174
175         child = child->ordered;
176     }
177     
178     return num_opts;
179
180 }
181
182
183 char * get_val(ezxml_t cfg, char * tag) {
184     char * attrib = (char *)ezxml_attr(cfg, tag);
185     ezxml_t txt = ezxml_child(cfg, tag);
186
187     if ((txt != NULL) && (attrib != NULL)) {
188         printf("Invalid Cfg file: Duplicate value for %s (attr=%s, txt=%s)\n", 
189                tag, attrib, ezxml_txt(txt));
190         exit(-1);
191     }
192
193     return (attrib == NULL) ? ezxml_txt(txt) : attrib;
194 }
195
196
197 int parse_aux_files(ezxml_t cfg_input) {
198     ezxml_t file_tags = NULL;
199     ezxml_t tmp_file_tag = NULL;
200
201     // files are transformed into blobs that are slapped to the end of the file
202         
203     file_tags = ezxml_child(cfg_input, "files");
204
205     tmp_file_tag = ezxml_child(file_tags, "file");
206
207     while (tmp_file_tag) {
208         char * filename = get_val(tmp_file_tag, "filename");
209         struct stat file_stats;
210         char * id = get_val(tmp_file_tag, "id");
211         char index_buf[256];
212
213
214         if (stat(filename, &file_stats) != 0) {
215             perror(filename);
216             exit(-1);
217         }
218
219         files[num_files].size = (unsigned int)file_stats.st_size;
220         strncpy(files[num_files].id, id, 256);
221         strncpy(files[num_files].filename, filename, 2048);
222
223         snprintf(index_buf, 256, "%llu", num_files);
224         ezxml_set_attr_d(tmp_file_tag, "index", index_buf);
225
226         num_files++;
227         tmp_file_tag = ezxml_next(tmp_file_tag);
228     }
229
230
231     return 0;
232 }
233
234 int build_image(char * vm_name, char * filename, struct cfg_value * cfg_vals, int num_options) {
235     int i = 0;
236     ezxml_t xml = NULL;
237     struct xml_option * xml_opts = NULL;
238     int num_xml_opts = 0;
239     void * guest_img_data = NULL;
240     int guest_img_size = 0;
241
242
243     xml = open_xml_file(filename);
244     
245     // parse options
246     num_xml_opts = find_xml_options(xml, &xml_opts);
247     
248     //  printf("%d options\n", num_xml_opts);
249
250     // apply options
251     for (i = 0; i < num_options; i++) {
252         struct cfg_value * cfg_val = &cfg_vals[i];
253         struct xml_option * xml_opt = xml_opts;
254
255         while (xml_opt) {
256             if (strcasecmp(cfg_val->tag, xml_opt->tag) == 0) {
257                 break;
258             }
259             
260             xml_opt = xml_opt->next;
261         }
262
263
264         if (!xml_opt) {
265             printf("Could not find Config option (%s) in XML file\n", cfg_val->tag);
266             return -1;
267         }
268
269         ezxml_set_txt(xml_opt->location, cfg_val->value);
270     }
271     
272
273
274     // parse files
275     parse_aux_files(xml);
276     
277     // create image data blob
278     {
279         char * new_xml_str = ezxml_toxml(xml);
280         int file_data_size = 0;
281         int i = 0;
282         int offset = 0;
283         unsigned long long file_offset = 0;
284
285         /* Image size is: 
286            8 byte header + 
287            4 byte xml length + 
288            xml strlen + 
289            8 bytes of zeros + 
290            8 bytes (number of files) + 
291            num_files * 16 byte file header + 
292            8 bytes of zeroes + 
293            file data
294         */
295         for (i = 0; i < num_files; i++) {
296             file_data_size += files[i].size;
297         }
298
299         guest_img_size = 8 + 4 + strlen(new_xml_str) + 8 + 8 + 
300             (num_files * 16) + 8 + file_data_size;
301             
302
303         guest_img_data = malloc(guest_img_size);
304         memset(guest_img_data, 0, guest_img_size);
305
306         memcpy(guest_img_data, "v3vee\0\0\0", 8);
307         offset += 8;
308
309         *(unsigned int *)(guest_img_data + offset) = strlen(new_xml_str);
310         offset += 4;
311
312         memcpy(guest_img_data + offset, new_xml_str, strlen(new_xml_str));
313         offset += strlen(new_xml_str);
314
315         memset(guest_img_data + offset, 0, 8);
316         offset += 8;
317         
318         *(unsigned long long *)(guest_img_data + offset) = num_files;
319         offset += 8;
320
321         
322         // The file offset starts at the end of the file list
323         file_offset = offset + (16 * num_files) + 8;
324
325         for (i = 0; i < num_files; i++) {
326             *(unsigned int *)(guest_img_data + offset) = i;
327             offset += 4;
328             *(unsigned int *)(guest_img_data + offset) = files[i].size;
329             offset += 4;
330             *(unsigned long long *)(guest_img_data + offset) = file_offset;
331             offset += 8;
332
333             file_offset += files[i].size;
334
335         }
336
337         memset(guest_img_data + offset, 0, 8);
338         offset += 8;
339
340
341         for (i = 0; i < num_files; i++) {
342             int fd = open(files[i].filename, O_RDONLY);
343
344             if (fd == -1) {
345                 printf("Error: Could not open aux file (%s)\n", files[i].filename);
346                 return -1;
347             }
348
349             read_file(fd, files[i].size, (unsigned char *)(guest_img_data + offset));
350
351             close(fd);
352
353             offset += files[i].size;
354
355         }
356         
357         free(new_xml_str);
358
359     }
360
361     printf("Guest Image Created (size=%u)\n", guest_img_size);
362     return create_vm(vm_name, guest_img_data, guest_img_size);
363 }
364
365
366
367
368
369
370 int main(int argc, char** argv) {
371     char * filename = NULL;
372     char * name = NULL;
373     int build_flag  = 0;
374     int c = 0;
375
376     opterr = 0;
377
378     while (( c = getopt(argc, argv, "b")) != -1) {
379         switch (c) {
380         case 'b':
381             build_flag = 1;
382             break;
383         }
384     }
385
386     if (argc - optind + 1 < 3) {
387         printf("usage: v3_create [-b] <guest_img> <vm name> [cfg options]\n");
388         return -1;
389     }
390
391     filename = argv[optind];
392     name = argv[optind + 1];
393
394
395     if (build_flag == 1) {
396         int cfg_idx = optind + 2;
397         int i = 0;
398         struct cfg_value * cfg_vals = NULL;
399         
400         printf("Building VM Image (cfg=%s) (name=%s) (%d config options)\n", filename, name, argc - cfg_idx);
401
402         cfg_vals = malloc(sizeof(struct cfg_value) * argc - cfg_idx);
403         
404         
405
406         while (i < argc - cfg_idx) {
407             char * tag = NULL;
408             char * value = NULL;
409
410             value = argv[cfg_idx + i];
411
412             tag = strsep(&value, "=");
413             // parse
414
415             if (value == NULL) {
416                 printf("Invalid Option format: %s\n", argv[cfg_idx + i]);
417                 return -1;
418             }
419
420             cfg_vals[i].tag = tag;
421             cfg_vals[i].value = value;
422
423             printf("Config option: %s: %s\n", tag, value);
424
425
426             i++;
427         }
428
429         return build_image(name, filename, cfg_vals, argc - cfg_idx);
430
431
432     } else {
433         printf("Loading VM Image (img=%s) (name=%s)\n", filename, name);
434         return load_image(name, filename);
435     }
436
437     return 0; 
438
439
440
441
442 int read_file(int fd, int size, unsigned char * buf) {
443     int left_to_read = size;
444     int have_read = 0;
445
446     while (left_to_read != 0) {
447         int bytes_read = read(fd, buf + have_read, left_to_read);
448
449         if (bytes_read <= 0) {
450             break;
451         }
452
453         have_read += bytes_read;
454         left_to_read -= bytes_read;
455     }
456
457     if (left_to_read != 0) {
458         printf("Error could not finish reading file\n");
459         return -1;
460     }
461     
462     return 0;
463 }