OSDN Git Service

c9c92edb27a35e1761698c9abf72ce66e0e24bb9
[karesansui/karesansui.git] / karesansui / gadget / guest.py
1 # -*- coding: utf-8 -*-
2 #
3 # This file is part of Karesansui.
4 #
5 # Copyright (C) 2009-2010 HDE, Inc.
6 #
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
11 #
12
13 import re
14 import pwd
15 import os.path
16 import glob
17 import time
18
19 import web
20
21 import karesansui
22 from karesansui.lib.rest import Rest, auth
23 from karesansui.lib.const import ICON_DIR_TPL, \
24      VIRT_COMMAND_CREATE_GUEST, VIRT_COMMAND_REPLICATE_GUEST, \
25      VIRT_COMMAND_DELETE_GUEST, \
26      VNC_PORT_MIN_NUMBER, PORT_MAX_NUMBER, \
27      MEMORY_MIN_SIZE, DISK_MIN_SIZE, \
28      VIRT_DOMAINS_DIR, DEFAULT_KEYMAP
29
30 from karesansui.lib.const import XEN_KEYMAP_DIR, KVM_KEYMAP_DIR
31
32 from karesansui.lib.utils import comma_split, \
33      generate_mac_address, is_param, \
34      next_number, generate_uuid, string_from_uuid, uniq_sort, \
35      uni_force, get_partition_info, chk_create_disk, json_dumps, \
36      get_ifconfig_info, get_keymaps, available_virt_mechs, \
37      available_virt_uris, is_iso9660_filesystem_format, \
38      get_dom_list, get_dom_type, base64_encode
39
40 from karesansui.lib.utils import get_xml_parse as XMLParse
41 from karesansui.lib.utils import get_xml_xpath as XMLXpath
42 from karesansui.lib.utils import get_nums_xml_xpath as XMLXpathNum
43 from karesansui.lib.file.configfile import ConfigFile
44
45 from karesansui.lib.checker import Checker, \
46     CHECK_EMPTY, CHECK_VALID, CHECK_LENGTH, CHECK_ONLYSPACE, \
47     CHECK_MIN, CHECK_MAX, CHECK_EXIST
48
49 from karesansui.lib.const import \
50     NOTE_TITLE_MIN_LENGTH, NOTE_TITLE_MAX_LENGTH, \
51     MACHINE_NAME_MIN_LENGTH, MACHINE_NAME_MAX_LENGTH, \
52     TAG_MIN_LENGTH, TAG_MAX_LENGTH, \
53     VNC_PORT_MIN_NUMBER, VNC_PORT_MAX_NUMBER, \
54     HYPERVISOR_MIN_SIZE, HYPERVISOR_MAX_SIZE, \
55     MEMORY_MIN_SIZE, DISK_MIN_SIZE, \
56     DOMAIN_NAME_MIN_LENGTH, DOMAIN_NAME_MAX_LENGTH, \
57     MACHINE_HYPERVISOR, MACHINE_ATTRIBUTE, \
58     DISK_QEMU_FORMAT, DISK_NON_QEMU_FORMAT, \
59     VIRT_COMMAND_CREATE_STORAGE_VOLUME, \
60     VIRT_COMMAND_DELETE_STORAGE_VOLUME, STORAGE_VOLUME_PWD, \
61     DISK_USES
62
63 from karesansui.lib.virt.virt import KaresansuiVirtConnection
64 from karesansui.lib.virt.config_export import ExportConfigParam
65
66 from karesansui.lib.merge import  MergeGuest
67
68 from karesansui.db.access.machine import \
69      findbyhost1guestall, findbyhost1, \
70      findbyguest1, \
71      new as m_new, save as m_save, delete as m_delete
72
73 from karesansui.db.access.machine2jobgroup import new as m2j_new, save as m2j_save
74 from karesansui.db.access.notebook import new as n_new
75 #from karesansui.db.access.tag import new as t_new, samecount as t_count, findby1name as t_name
76 from karesansui.db.access.tag import new as t_new, samecount as t_count, findby1name as t_name
77 from karesansui.db.access._2pysilhouette import jg_save, jg_delete
78 from karesansui.db.model._2pysilhouette import Job, JobGroup
79
80 from pysilhouette.command import dict2command
81
82 def validates_guest_add(obj):
83     checker = Checker()
84     check = True
85
86     _ = obj._
87     checker.errors = []
88
89     if not is_param(obj.input, 'm_name'):
90         check = False
91         checker.add_error(_('Parameter m_name does not exist.'))
92     else:
93         check = checker.check_string(
94                     _('Machine Name'),
95                     obj.input.m_name,
96                     CHECK_EMPTY | CHECK_LENGTH | CHECK_ONLYSPACE,
97                     None,
98                     min = MACHINE_NAME_MIN_LENGTH,
99                     max = MACHINE_NAME_MAX_LENGTH,
100             ) and check
101
102     if is_param(obj.input, 'note_title'):
103         check = checker.check_string(
104                     _('Title'),
105                     obj.input.note_title,
106                     CHECK_LENGTH | CHECK_ONLYSPACE,
107                     None,
108                     min = NOTE_TITLE_MIN_LENGTH,
109                     max = NOTE_TITLE_MAX_LENGTH,
110                 ) and check
111
112     if is_param(obj.input, 'note_value'):
113         check = checker.check_string(
114                     _('Note'),
115                     obj.input.note_value,
116                     CHECK_ONLYSPACE,
117                     None,
118                     None,
119                     None,
120                 ) and check
121
122     if is_param(obj.input, 'tags'):
123         for tag in comma_split(obj.input.tags):
124             check = checker.check_string(
125                         _('Tag'),
126                         tag,
127                         CHECK_LENGTH | CHECK_ONLYSPACE,
128                         None,
129                         min = TAG_MIN_LENGTH,
130                         max = TAG_MAX_LENGTH,
131                     ) and check
132
133
134     if not is_param(obj.input, 'm_hypervisor'):
135         check = False
136         checker.add_error(_('Parameter m_hypervisor does not exist.'))
137     else:
138         check = checker.check_hypervisor(
139                 _('Hypervisor'),
140                 obj.input.m_hypervisor,
141                 CHECK_EMPTY | CHECK_VALID | CHECK_MIN | CHECK_MAX,
142                 HYPERVISOR_MIN_SIZE,
143                 HYPERVISOR_MAX_SIZE,
144             ) and check
145
146     if not is_param(obj.input, 'domain_name'):
147         check = False
148         checker.add_error(_('Parameter domain_name does not exist.'))
149     else:
150         check = checker.check_string(
151                 _('Domain Name'),
152                 obj.input.domain_name,
153                 CHECK_EMPTY | CHECK_VALID | CHECK_LENGTH | CHECK_ONLYSPACE,
154                 '[^-a-zA-Z0-9_\.]+',
155                 DOMAIN_NAME_MIN_LENGTH,
156                 DOMAIN_NAME_MAX_LENGTH,
157             ) and check
158
159         if obj.input.domain_name in get_dom_list():
160             dom_type = get_dom_type(obj.input.domain_name)
161             checker.add_error(_("The same domain name already exists for hypervisor '%s'.") % dom_type.upper())
162             check = False
163
164     if is_param(obj.input, 'vm_mem_size'):
165         check = checker.check_number(
166                 _('Memory Size (MB)'),
167                 obj.input.vm_mem_size,
168                 CHECK_VALID | CHECK_MIN | CHECK_EMPTY,
169                 MEMORY_MIN_SIZE,
170                 None,
171             ) and check
172
173     if is_param(obj.input, 'vm_disk_size'):
174         check = checker.check_number(
175                 _('Disk Size (MB)'),
176                 obj.input.vm_disk_size,
177                 CHECK_VALID | CHECK_MIN | CHECK_EMPTY,
178                 DISK_MIN_SIZE,
179                 None,
180             ) and check
181
182     if not is_param(obj.input, 'boot_image'):
183         check = False
184         checker.add_error(_('Parameter boot_image does not exist.'))
185     else:
186         if obj.input.boot_image == "kernel":
187             if not is_param(obj.input, 'vm_kernel'):
188                 check = False
189                 checker.add_error(_('Parameter vm_kernel does not exist.'))
190             else:
191                 check = checker.check_startfile(
192                         _('Kernel Image'),
193                         obj.input.vm_kernel,
194                         CHECK_EMPTY | CHECK_VALID | CHECK_EXIST,
195                     ) and check
196
197             if not is_param(obj.input, 'vm_initrd'):
198                 check = False
199                 checker.add_error(_('Parameter vm_initrd does not exist.'))
200             else:
201                 check = checker.check_startfile(
202                         _('Initrd Image'),
203                         obj.input.vm_initrd,
204                         CHECK_EMPTY | CHECK_VALID | CHECK_EXIST,
205                     ) and check
206
207         if obj.input.boot_image == "iso":
208             if not is_param(obj.input, 'vm_iso'):
209                 check = False
210                 checker.add_error(_('Parameter vm_iso does not exist.'))
211             else:
212                 check = checker.check_startfile(
213                         _('ISO Image'),
214                         obj.input.vm_iso,
215                         CHECK_EMPTY | CHECK_VALID | CHECK_EXIST,
216                     ) and check
217                 if check:
218                     check = is_iso9660_filesystem_format(obj.input.vm_iso)
219                     checker.add_error(_('"%s" is not valid ISO 9660 CD-ROM filesystem data.') % obj.input.vm_iso)
220
221     if not is_param(obj.input, 'keymap'):
222         check = False
223         checker.add_error(_('"%s" is required.') % _('VNC Keymap'))
224     else:
225         hypervisor = "KVM"
226         if int(obj.input.m_hypervisor) == MACHINE_HYPERVISOR['XEN']:
227             hypervisor = "XEN"
228         elif int(obj.input.m_hypervisor) == MACHINE_HYPERVISOR['KVM']:
229             hypervisor = "KVM"
230         check = checker.check_keymap(
231                 _('VNC Keymap'),
232                 obj.input.keymap,
233                 CHECK_EMPTY | CHECK_EXIST,
234                 hypervisor
235                 ) and check
236
237     if not is_param(obj.input, 'vm_vncport'):
238         check = False
239         checker.add_error(_('Parameter vm_vncport does not exist.'))
240     else:
241         check = checker.check_number(
242                 _('VNC Port Number'),
243                 obj.input.vm_vncport,
244                 CHECK_EMPTY | CHECK_VALID | CHECK_MIN | CHECK_MAX,
245                 VNC_PORT_MIN_NUMBER,
246                 VNC_PORT_MAX_NUMBER,
247             ) and check
248
249     if not is_param(obj.input, 'vm_mac'):
250         check = False
251         checker.add_error(_('Parameter vm_mac does not exist.'))
252     else:
253         check = checker.check_macaddr(
254                 _('MAC Address'),
255                 obj.input.vm_mac,
256                 CHECK_EMPTY | CHECK_VALID,
257             ) and check
258
259     obj.view.alert = checker.errors
260     return check
261
262
263 # public method
264 def make_storage_volume_job(uuid, name, pool_name, format,
265                             capacity, allocation, unit, order):
266     cmdname = u"Create Storage Volume"
267     cmd = VIRT_COMMAND_CREATE_STORAGE_VOLUME
268
269     options = {}
270     options['volume_name'] = uuid
271     options['name'] = name
272     options['pool_name'] = pool_name
273     options['format'] = format
274     options['capacity'] = capacity
275     options['allocation'] = allocation
276     options['unit'] = unit
277     options['permission_owner'] = pwd.getpwnam(STORAGE_VOLUME_PWD["OWNER"])[2]
278     options['permission_group'] = pwd.getpwnam(STORAGE_VOLUME_PWD["GROUP"])[2]
279     options['permission_mode'] = STORAGE_VOLUME_PWD["MODE"]
280     options['use'] = DISK_USES["IMAGES"]
281
282     _cmd = dict2command(
283         "%s/%s" % (karesansui.config['application.bin.dir'], cmd), options)
284
285     rollback_options = {}
286     #rollback_options["name"] = name
287     rollback_options["name"] = uuid
288     rollback_options["pool_name"] = pool_name
289     rollback_options["use"] = DISK_USES["IMAGES"]
290
291     rollback_cmd = dict2command(
292         "%s/%s" % (karesansui.config['application.bin.dir'], VIRT_COMMAND_DELETE_STORAGE_VOLUME),
293         rollback_options)
294
295     _job = Job('%s command' % cmdname, order, _cmd)
296     # delete_guestコマンドが削除まで担当してくれるので、ここではロールバックコマンドを設定しない。
297     #_job.rollback_command = rollback_cmd
298     return _job
299
300 def regist_guest(obj, _guest, icon_filename,
301                   cmd, options, cmdname, rollback_options, is_create=False):
302
303     if icon_filename:
304         _guest.icon = icon_filename
305
306     if (karesansui.sheconf.has_key('env.uniqkey') is False) \
307            or (karesansui.sheconf['env.uniqkey'].strip('') == ''):
308         raise 
309
310     action_cmd = dict2command(
311         "%s/%s" % (karesansui.config['application.bin.dir'], cmd),
312         options)
313
314     rollback_cmd = dict2command(
315         "%s/%s" % (karesansui.config['application.bin.dir'], VIRT_COMMAND_DELETE_GUEST),
316         rollback_options)
317
318     _jobgroup = JobGroup(cmdname[0], karesansui.sheconf['env.uniqkey'])
319
320     # create volume job
321     order = 0
322     if is_create is True:
323         _volume_job = make_storage_volume_job(options["uuid"],
324                                               options["storage-volume"],
325                                               options["storage-pool"],
326                                               options["disk-format"],
327                                               options["disk-size"],
328                                               options["disk-size"],
329                                               'M',
330                                               order
331                                               )
332
333         order += 1
334         _jobgroup.jobs.append(_volume_job)
335
336
337     _job = Job('%s command' % cmdname[1], order, action_cmd)
338     _job.rollback_command = rollback_cmd
339     _jobgroup.jobs.append(_job)
340
341     # GuestOS INSERT
342     try:
343         m_save(obj.orm, _guest)
344         obj.orm.commit()
345     except:
346         obj.logger.error('Failed to register the Guest OS. #1 - guest name=%s' \
347                           % _guest.name)
348         raise # throw
349
350     # JobGroup INSERT
351     try:
352         jg_save(obj.pysilhouette.orm, _jobgroup)
353         obj.pysilhouette.orm.commit()
354     except:
355         # rollback(machine)
356         obj.logger.error('Failed to register the JobGroup. #2 - jobgroup name=%s' \
357                           % _jobgroup.name)
358
359         try:
360             m_delete(obj.orm, _guest)
361             obj.orm.commit()
362             obj.logger.error('#3 Rollback successful. - guest id=%d' % _guest.id)
363         except:
364             obj.logger.critical('#4 Rollback failed. - guest id=%d' % _guest.id)
365             raise
366
367         raise # throw
368
369     # Machine2JobGroup INSERT
370     try:
371         _m2j = m2j_new(machine=_guest,
372                        jobgroup_id=_jobgroup.id,
373                        uniq_key=karesansui.sheconf['env.uniqkey'],
374                        created_user=obj.me,
375                        modified_user=obj.me,
376                        )
377         m2j_save(obj.orm, _m2j)
378         obj.orm.commit()
379     except:
380         # rollback(machine, jobgroup)
381         try:
382             m_delete(obj.orm, _guest)
383             obj.orm.commit()
384         except:
385             # rollback(machine)
386             obj.logger.critical('Failed to register the Machine. #5 - guest id=%d' \
387                               % _guest.id)
388         try:
389             jg_delete(obj.pysilhouette.orm, _jobgroup)
390             obj.pysilhouette.orm.commit()
391         except:
392             # rollback(jobgroup)
393             obj.logger.critical('Failed to register the JobGroup. #6 - jobgroup id=%d' \
394                               % _jobgroup.id)
395         raise # throw
396
397     return True
398
399 class Guest(Rest):
400
401     def _post(self, f):
402         ret = Rest._post(self, f)
403         if hasattr(self, "kvc") is True:
404             self.kvc.close()
405         return ret
406
407     @auth
408     def _GET(self, *param, **params):
409         host_id = self.chk_hostby1(param)
410         if host_id is None: return web.notfound()
411
412         model = findbyhost1(self.orm, host_id)
413         uris = available_virt_uris()
414
415         self.kvc = KaresansuiVirtConnection()
416         try: # libvirt connection scope -->
417             # Storage Pool
418             #inactive_pool = self.kvc.list_inactive_storage_pool()
419             inactive_pool = []
420             active_pool = self.kvc.list_active_storage_pool()
421             pools = inactive_pool + active_pool
422             pools.sort()
423
424             if not pools:
425                 return web.badrequest('One can not start a storage pool.')
426
427             self.view.pools = pools
428             pools_info = {}
429             pools_vols_info = {}
430
431             for pool in pools:
432                 pool_obj = self.kvc.search_kvn_storage_pools(pool)[0]
433                 if pool_obj.is_active() is True:
434                     vols_obj = pool_obj.search_kvn_storage_volumes(self.kvc)
435                     vols_info = {}
436                     for vol_obj in vols_obj:
437                         vol_name = vol_obj.get_storage_volume_name()
438                         vols_info[vol_name] = vol_obj.get_info()
439
440                     pools_vols_info[pool] = vols_info
441
442                 pools_info[pool] = pool_obj.get_info()
443
444             self.view.pools_info = pools_info
445             self.view.pools_vols_info = pools_vols_info
446
447             # Output .input
448             if self.is_mode_input() is True:
449                 bridge_prefix = {
450                     "XEN":"xenbr",
451                     "KVM":"(eth|bond)",
452                     }
453                 self.view.host_id = host_id
454                 self.view.DEFAULT_KEYMAP = DEFAULT_KEYMAP
455                 self.view.DISK_NON_QEMU_FORMAT = DISK_NON_QEMU_FORMAT
456                 self.view.DISK_QEMU_FORMAT = DISK_QEMU_FORMAT
457
458                 self.view.hypervisors = {}
459                 self.view.mac_address = {}
460                 self.view.keymaps = {}
461                 self.view.phydev = {}
462                 self.view.virnet = {}
463
464                 used_ports = {}
465
466                 for k,v in MACHINE_HYPERVISOR.iteritems():
467                     if k in available_virt_mechs():
468                         self.view.hypervisors[k] = v
469                         uri = uris[k]
470                         mem_info = self.kvc.get_mem_info()
471                         active_networks = self.kvc.list_active_network()
472                         used_vnc_ports = self.kvc.list_used_vnc_port()
473                         bus_types = self.kvc.bus_types
474                         self.view.bus_types = bus_types
475                         self.view.min_mem = MEMORY_MIN_SIZE
476                         self.view.max_mem = mem_info['host_max_mem']
477
478                         self.view.mac_address[k] = generate_mac_address(k)
479                         self.view.keymaps[k] = eval("get_keymaps(%s_KEYMAP_DIR)" % k)
480
481                         # Physical device
482                         phydev = []
483                         phydev_regex = re.compile(r"%s" % bridge_prefix[k])
484                         for dev,dev_info in get_ifconfig_info().iteritems():
485                             try:
486                                 if phydev_regex.match(dev):
487                                     phydev.append(dev)
488                             except:
489                                 pass
490                         if len(phydev) == 0:
491                             phydev.append("%s0" % bridge_prefix[k])
492                         phydev.sort()
493                         self.view.phydev[k] = phydev # Physical device
494
495                         # Virtual device
496                         self.view.virnet[k] = sorted(active_networks)
497                         used_ports[k] = used_vnc_ports
498
499
500                 exclude_ports = []
501                 for k, _used_port in used_ports.iteritems():
502                     exclude_ports = exclude_ports + _used_port
503                     exclude_ports = sorted(exclude_ports)
504                     exclude_ports = [p for p, q in zip(exclude_ports, exclude_ports[1:] + [None]) if p != q]
505                 self.view.vnc_port = next_number(VNC_PORT_MIN_NUMBER,
506                                                  PORT_MAX_NUMBER,
507                                                  exclude_ports)
508
509                 # TODO VIRT_DOMAINS_DIR
510                 # TODO max_disk, mix_diskはいらないので削除
511                 partition_info = get_partition_info(VIRT_DOMAINS_DIR)
512                 disk_info = {"host_max_disk":int(partition_info[1][0]),
513                              "guest_alloc_disk":int(partition_info[2][0]),
514                              "host_free_disk":int(partition_info[3][0]),
515                          }
516
517                 self.view.min_disk = DISK_MIN_SIZE
518                 self.view.max_disk = disk_info["host_max_disk"]
519
520             else: # .part
521                 models = findbyhost1guestall(self.orm, host_id)
522                 guests = []
523                 if models:
524                     # Physical Guest Info
525                     self.view.hypervisors = {}
526                     for model in models:
527                         for k,v in MACHINE_HYPERVISOR.iteritems():
528                             if k in available_virt_mechs():
529                                 self.view.hypervisors[k] = v
530                                 uri = uris[k]
531                                 if hasattr(self, "kvc") is not True:
532                                     self.kvc = KaresansuiVirtConnection(uri)
533                                 domname = self.kvc.uuid_to_domname(model.uniq_key)
534                                 #if not domname: return web.conflict(web.ctx.path)
535                                 _virt = self.kvc.search_kvg_guests(domname)
536                                 if 0 < len(_virt):
537                                     guests.append(MergeGuest(model, _virt[0]))
538                                 else:
539                                     guests.append(MergeGuest(model, None))
540
541                 # Exported Guest Info
542                 exports = {}
543                 for pool_name in pools:
544                     files = []
545
546                     pool = self.kvc.search_kvn_storage_pools(pool_name)
547                     path = pool[0].get_info()["target"]["path"]
548
549                     if os.path.exists(path):
550                         for _afile in glob.glob("%s/*/info.dat" % (path,)):
551                             param = ExportConfigParam()
552                             param.load_xml_config(_afile)
553
554                             _dir = os.path.dirname(_afile)
555
556                             uuid = param.get_uuid()
557                             name = param.get_domain()
558                             created = param.get_created()
559                             title = param.get_title()
560                             if title != "":
561                                 title = re.sub("[\r\n]","",title)
562                             if title == "":
563                                 title = _('untitled')
564
565                             if created != "":
566                                 created_str = time.strftime("%Y/%m/%d %H:%M:%S", \
567                                                             time.localtime(float(created)))
568                             else:
569                                 created_str = _("N/A")
570
571                             files.append({"dir": _dir,
572                                           "pool" : pool_name,
573                                           #"b64dir" : base64_encode(_dir),
574                                           "uuid" : uuid,
575                                           "name" : name,
576                                           "created" : int(created),
577                                           "created_str" : created_str,
578                                           "title" : title,
579                                           "icon" : param.get_database()["icon"],
580                                           })
581
582                     exports[pool_name] = files
583
584                 # .json
585                 if self.is_json() is True:
586                     guests_json = []
587                     for x in guests:
588                         guests_json.append(x.get_json(self.me.languages))
589                         
590                     self.view.guests = json_dumps(guests_json)
591                 else:
592                     self.view.exports = exports
593                     self.view.guests = guests
594
595             return True
596         finally:
597             #self.kvc.close()
598             pass # libvirt connection scope --> Guest#_post()
599
600     @auth
601     def _POST(self, *param, **params):
602         host_id = self.chk_hostby1(param)
603         if host_id is None: return web.notfound()
604
605         model = findbyhost1(self.orm, host_id)
606
607         uris = available_virt_uris()
608         if model.attribute == 0 and model.hypervisor == 1:
609             uri = uris["XEN"]
610         elif model.attribute == 0 and model.hypervisor == 2:
611             uri = uris["KVM"]
612         else:
613             uri = None
614
615         if not validates_guest_add(self):
616             return web.badrequest(self.view.alert)
617
618         try:
619             try:
620                 self.kvc = KaresansuiVirtConnection(uri)
621                 active_guests = self.kvc.list_active_guest()
622                 inactive_guests = self.kvc.list_inactive_guest()
623                 used_vnc_ports = self.kvc.list_used_vnc_port()
624                 used_mac_addrs = self.kvc.list_used_mac_addr()
625                 mem_info = self.kvc.get_mem_info()
626
627                 if is_param(self.input, "disk_layout") and \
628                        self.input.disk_layout == "create" and \
629                        is_param(self.input, "pool_dir"):
630                     target_path = self.kvc.get_storage_pool_targetpath(self.input.pool_dir)
631                     if target_path: # disk
632                         if not chk_create_disk(target_path, self.input.vm_disk_size):
633                             partition = get_partition_info(target_path, header=False)
634                             return web.badrequest(_("No space available to create disk image in '%s' partition.") % partition[5][0])
635             except:
636                 raise
637         finally:
638             del self.kvc
639
640         # Check on whether value has already been used
641         # Guest OS
642         if (self.input.domain_name in active_guests) \
643                or (self.input.domain_name in inactive_guests):
644             return web.conflict(web.ctx.path, "Guest OS is already there.")
645         # VNC port number
646         if(int(self.input.vm_vncport) in used_vnc_ports):
647             return web.conflict(web.ctx.path, "VNC Port is already there.")
648         # MAC addr
649         if(self.input.vm_mac in used_mac_addrs):
650             return web.conflict(web.ctx.path, "MAC Address is already there.")
651
652         uuid = string_from_uuid(generate_uuid())
653
654         options = {}
655         options['uuid'] = uuid
656
657         if is_param(self.input, "domain_name"):
658             options['name'] = self.input.domain_name
659         if is_param(self.input, "vm_mem_size"):
660             options['mem-size'] = self.input.vm_mem_size
661         if is_param(self.input, "vm_kernel"):
662             options['kernel'] = self.input.vm_kernel
663         if is_param(self.input, "vm_initrd"):
664             options['initrd'] = self.input.vm_initrd
665         if is_param(self.input, "vm_iso"):
666             options['iso'] = self.input.vm_iso
667         if is_param(self.input, "keymap"):
668             options['keymap'] = self.input.keymap
669
670         is_create = False
671         if is_param(self.input, "disk_layout"):
672             if is_param(self.input, "bus_type"):
673                 options['bus'] = self.input.bus_type
674
675             if self.input.disk_layout == "create": # create volume
676                 is_create = True
677                 options['disk-format'] = self.input.disk_format
678                 options["storage-pool"] = self.input.pool_dir
679                 options["storage-volume"] = options['name'] # default domain name
680                 options['disk-size'] = self.input.vm_disk_size
681
682             elif self.input.disk_layout == "iscsi": # iscsi volume TODO
683                 if is_param(self.input, "iscsi_pool") and is_param(self.input, "iscsi_volume"):
684                     options["storage-pool"] = self.input.iscsi_pool
685                     options["storage-volume"] = self.input.iscsi_volume
686                 else:
687                     return web.badrequest()
688             else:
689                 return web.badrequest()
690         else:
691             return web.badrequest()
692
693         if is_param(self.input, "vm_vncport"):
694             options['vnc-port'] = self.input.vm_vncport
695         if is_param(self.input, "vm_mac"):
696             options['mac'] = self.input.vm_mac
697         if is_param(self.input, "vm_extra"):
698             options['extra'] = self.input.vm_extra
699         if is_param(self.input, "nic_type"):
700             if self.input.nic_type == "phydev":
701                 options['interface-format'] = "b:" + self.input.phydev
702             elif self.input.nic_type == "virnet":
703                 options['interface-format'] = "n:" + self.input.virnet
704
705         if int(self.input.m_hypervisor) == MACHINE_HYPERVISOR['XEN']:
706             i_hypervisor = MACHINE_HYPERVISOR['XEN']
707             options['type'] = u"XEN"
708         elif int(self.input.m_hypervisor) == MACHINE_HYPERVISOR['KVM']:
709             i_hypervisor = MACHINE_HYPERVISOR['KVM']
710             options['type'] = u"KVM"
711         else:
712             return web.badrequest("This is not the hypervisor.")
713
714         host = findbyhost1(self.orm, host_id)
715
716         # notebook
717         note_title = None
718         if is_param(self.input, "note_title"):
719             note_title = self.input.note_title
720
721         note_value = None
722         if is_param(self.input, "note_value"):
723             note_value = self.input.note_value
724
725         _notebook = n_new(note_title, note_value)
726
727         # tags
728         _tags = None
729         if is_param(self.input, "tags"):
730             _tags = []
731             tag_array = comma_split(self.input.tags)
732             tag_array = uniq_sort(tag_array)
733             for x in tag_array:
734                 if t_count(self.orm, x) == 0:
735                     _tags.append(t_new(x))
736                 else:
737                     _tags.append(t_name(self.orm, x))
738
739         # Icon
740         icon_filename = None
741         if is_param(self.input, "icon_filename", empty=True):
742             icon_filename = self.input.icon_filename
743
744         _guest = m_new(created_user=self.me,
745                        modified_user=self.me,
746                        uniq_key=uni_force(uuid),
747                        name=self.input.m_name,
748                        attribute=MACHINE_ATTRIBUTE['GUEST'],
749                        hypervisor=i_hypervisor,
750                        notebook=_notebook,
751                        tags=_tags,
752                        icon=icon_filename,
753                        is_deleted=False,
754                        parent=host,
755                        )
756
757         ret =  regist_guest(self,
758                             _guest,
759                             icon_filename,
760                             VIRT_COMMAND_CREATE_GUEST,
761                             options,
762                             ('Create Guest', 'Create Guest'),
763                             {"name": options['name'],
764                              "pool" : options["storage-pool"],
765                              "volume" : options["uuid"],
766                              },
767                             is_create,
768                             )
769         if ret is True:
770             return web.accepted()
771         else:
772             return False
773
774 urls = (
775     '/host/(\d+)/guest/?(\.part|\.json)$', Guest,
776     )