OSDN Git Service

Change validate
[karesansui/karesansui.git] / karesansui / lib / virt / virt.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # This file is part of Karesansui Core.
5 #
6 # Copyright (C) 2009-2010 HDE, Inc.
7 #
8 # This program is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12 #
13
14 """ 
15 <comment-ja>
16 仮想化全般のライブラリ群
17 </comment-ja>
18 <comment-en>
19 </comment-en>
20
21 @file:   virt.py
22
23 @author: Taizo ITO <taizo@karesansui-project.info>
24
25 @copyright:    
26
27 """
28
29 import sys
30 import string
31 import os, os.path
32 import time
33 import tempfile
34 import re
35 import libvirt
36 import libvirtmod
37 import logging
38 import glob
39
40 # define
41 from libvirt import VIR_DOMAIN_NOSTATE,VIR_DOMAIN_RUNNING,\
42      VIR_DOMAIN_BLOCKED,VIR_DOMAIN_PAUSED,VIR_DOMAIN_SHUTDOWN,\
43      VIR_DOMAIN_SHUTOFF,VIR_DOMAIN_CRASHED,\
44      VIR_STORAGE_POOL_DELETE_NORMAL,\
45      VIR_STORAGE_POOL_DELETE_ZEROED, \
46      VIR_STORAGE_VOL_DELETE_NORMAL, \
47      VIR_STORAGE_VOL_DELETE_ZEROED
48
49 if __name__ == '__main__':
50     for y in [os.path.abspath(os.path.dirname(os.path.abspath(__file__))+"/../../.."),"/opt/hde/lib/python"]:
51         if (y in sys.path) is False: sys.path.insert(0, y)
52
53 import karesansui
54 import karesansui.lib.locale
55
56 from karesansui.lib.const import VIRT_LIBVIRT_DATA_DIR, VIRT_DOMAINS_DIR, \
57      VIRT_XML_CONFIG_DIR, VIRT_NETWORK_CONFIG_DIR, VIRT_SNAPSHOT_DIR, \
58      VIRT_XENDOMAINS_AUTO_DIR, VIRT_AUTOSTART_CONFIG_DIR, \
59      KARESANSUI_GROUP, VNC_PORT_MIN_NUMBER, PORT_MAX_NUMBER, \
60      DEFAULT_KEYMAP, VIRT_STORAGE_CONFIG_DIR, \
61      DEFAULT_KVM_DISK_FORMAT, DEFAULT_XEN_DISK_FORMAT, \
62      DISK_USES, GUEST_EXPORT_FILE, KVM_BUS_TYPES, XEN_BUS_TYPES, \
63      VENDOR_DATA_ISCSI_DOMAINS_DIR, ISCSI_DEVICE_DIR
64
65 from karesansui.lib.const import XEN_VIRT_CONFIG_DIR, \
66      XEN_VIRTUAL_DISK_PREFIX, \
67      XEN_VIRT_URI_RW, XEN_VIRT_URI_RO, \
68      XEN_KARESANSUI_TMP_DIR, \
69      XEN_KEYMAP_DIR
70
71 from karesansui.lib.const import KVM_VIRT_CONFIG_DIR, \
72      KVM_VIRTUAL_DISK_PREFIX, \
73      KVM_VIRT_URI_RW, KVM_VIRT_URI_RO, \
74      KVM_KARESANSUI_TMP_DIR, \
75      KVM_KEYMAP_DIR
76
77 from karesansui.lib.virt.config import ConfigParam, \
78      XMLConfigGenerator, sync_config_generator, KaresansuiConfigParamException
79
80 from karesansui.lib.virt.config_network import NetworkConfigParam
81 from karesansui.lib.virt.config_network import NetworkXMLConfigGenerator
82
83 from karesansui.lib.virt.config_storage import StorageVolumeConfigParam, \
84      StorageVolumeXMLConfigGenerator, StoragePoolConfigParam, \
85      StoragePoolXMLConfigGenerator
86
87 from karesansui.lib.virt.config_export import ExportConfigParam, ExportXMLGenerator
88
89 from karesansui.lib.virt.config_capabilities import CapabilitiesConfigParam
90
91 from karesansui.lib.utils import uniq_sort            as UniqSort
92 from karesansui.lib.utils import generate_mac_address as GenMAC
93 from karesansui.lib.utils import execute_command      as ExecCmd
94 from karesansui.lib.utils import string_from_uuid     as StrFromUUID
95 from karesansui.lib.utils import generate_uuid        as GenUUID
96 from karesansui.lib.utils import next_number          as NextNumber
97 from karesansui.lib.utils import create_disk_img      as MakeDiskImage
98 from karesansui.lib.utils import copy_file            as CopyFile
99 from karesansui.lib.net.http import wget              as DownloadFile
100 from karesansui.lib.utils import is_uuid, get_ifconfig_info, r_chgrp, r_chmod, \
101   getfilesize_str, get_filesize_MB, get_disk_img_info, available_virt_uris, \
102   is_iso9660_filesystem_format, is_windows_bootable_iso, is_darwin_bootable_iso, \
103   file_contents_replace
104
105 from karesansui.lib.utils import get_inspect_stack
106
107 from karesansui.lib.file.configfile import ConfigFile
108
109
110 os.environ['LIBVIRT_XM_CONFIG_DIR'] = XEN_VIRT_CONFIG_DIR
111
112 class KaresansuiVirtException(karesansui.KaresansuiLibException):
113     pass
114
115 class KaresansuiVirtConnection:
116
117     def __init__(self,uri=None,readonly=True):
118         self.__prep()
119         self.logger.debug(get_inspect_stack())
120         try:
121             self.open(uri,readonly)
122         except:
123             raise KaresansuiVirtException(_("Cannot open '%s'") % uri)
124
125         self.__prep2()
126
127     def __prep(self):
128         """
129         <comment-ja>
130         デフォルトのストレージを作成します。
131         </comment-ja>
132         <comment-en>
133         </comment-en>
134         """
135         if not os.path.exists(VIRT_DOMAINS_DIR):
136           os.makedirs(VIRT_DOMAINS_DIR)
137         if not os.path.exists(VIRT_XML_CONFIG_DIR):
138           os.makedirs(VIRT_XML_CONFIG_DIR)
139         self.logger = logging.getLogger('karesansui.virt')
140         if os.getuid() == 0:
141             r_chgrp(VIRT_LIBVIRT_DATA_DIR,KARESANSUI_GROUP)
142             r_chmod(VIRT_DOMAINS_DIR,"o-rwx")
143
144     def __prep2(self):
145         if not os.path.exists(self.config_dir):
146           os.makedirs(self.config_dir)
147         self.logger = logging.getLogger('karesansui.virt')
148         if os.getuid() == 0:
149             r_chgrp(self.config_dir,KARESANSUI_GROUP)
150
151     def open(self, uri,readonly=True):
152         """
153         <comment-ja>
154         libvirtのコネクションをOpenします。またそれに伴う初期化も行います。
155         </comment-ja>
156         <comment-en>
157         </comment-en>
158         """
159         if uri == None:
160             uris = available_virt_uris()
161             try:
162                 uri = uris["KVM"]
163             except:
164                 try:
165                     uri = uris["XEN"]
166                 except:
167                     raise 'error: you must specify connect uri'
168
169         if uri.lower()[0:3] == "xen":
170             self.disk_prefix = XEN_VIRTUAL_DISK_PREFIX
171             self.config_dir  = XEN_VIRT_CONFIG_DIR
172             self.bus_types   = XEN_BUS_TYPES
173
174             if not os.access("/proc/xen", os.R_OK):
175                 raise 'System is not running a Xen kernel'
176
177         if uri.lower()[0:4] == "qemu":
178             self.disk_prefix = KVM_VIRTUAL_DISK_PREFIX
179             self.config_dir  = KVM_VIRT_CONFIG_DIR
180             self.bus_types   = KVM_BUS_TYPES
181
182             if False == True:
183                 raise 'System is not running a kvm module'
184
185         if uri != None:
186             self.uri = uri
187
188         self.logger.debug('uid=%d' % os.getuid())
189         self.logger.debug('gid=%d' % os.getgid())
190         
191         try:
192             """
193             if readonly == True:
194                 self.logger.info('libvirt.openReadOnly - %s' % self.uri)
195                 self._conn = libvirt.openReadOnly(self.uri)
196             else:
197                 self.logger.info('libvirt.open - %s' % self.uri)
198                 self._conn = libvirt.open(self.uri)
199             """
200             self.logger.debug('libvirt.open - %s' % self.uri)
201             self._conn = libvirt.open(self.uri)
202         except:
203             self.logger.error('failed to libvirt open - %s' % self.uri)
204
205         self.logger.debug('succeed to libvirt open - %s' % self.uri)
206         self.logger.debug('hypervisor_type - %s' % self.get_hypervisor_type())
207
208         self.guest = KaresansuiVirtGuest(self)
209         self.network = KaresansuiVirtNetwork(self)
210         self.storage_volume = KaresansuiVirtStorageVolume(self)
211         self.storage_pool = KaresansuiVirtStoragePool(self)
212         return self._conn
213
214     def close(self, conn=None):
215         """
216         <comment-ja>
217         libvirtなどの仮想化コネクションをCloseします。
218         </comment-ja>
219         <comment-en>
220         </comment-en>
221         """
222         self.logger.debug(get_inspect_stack())
223         if conn == None:
224             try:
225                 conn = self._conn
226             except NameError:
227                 pass
228         if conn != None:
229             conn.__del__()
230             self.logger.debug('succeed to libvirt close - %s' % self.uri)
231
232     def get_hypervisor_type(self):
233         """<comment-ja>
234         使用中のハイパーバイザーの種類を取得する。
235         @param void
236         @return: hypervisor type
237                  Xen or QEMU is available now (depend on libvirt API)
238                  e.g. Xen QEMU Test LXC phyp OpenVZ VBox UML ONE ESX
239                       XenAPI Remote
240         @rtype: string (see examples in previous field '@return')
241         </comment-ja>
242         <comment-en>
243         </comment-en>
244         """
245         return self._conn.getType()
246
247     def get_capabilities(self):
248         retval = {}
249         param = CapabilitiesConfigParam()
250         try:
251             param.load_xml_config(self._conn.getCapabilities())
252             retval = {
253                "host" :param.host,
254                "guest":param.guest,
255              }
256         except:
257             pass
258         return retval
259
260     def get_version(self):
261         """
262         <comment-ja>
263         libvirtのバージョン情報を取得します。
264         </comment-ja>
265         <comment-en>
266         </comment-en>
267         """
268         hypervisior = self.get_hypervisior_type()
269         ret = libvirtmod.virGetVersion(hypervisior)
270         libVersion = ret[0]
271         apiVersion = ret[1]
272
273         libVersion_major = libVersion / 1000000
274         libVersion %= 1000000
275         libVersion_minor = libVersion / 1000
276         libVersion_rel = libVersion % 1000
277         #print "Using library: libvir %d.%d.%d" %(libVersion_major, libVersion_minor, libVersion_rel)
278
279         apiVersion_major = apiVersion / 1000000
280         apiVersion %= 1000000
281         apiVersion_minor = apiVersion / 1000
282         apiVersion_rel = apiVersion % 1000
283         #print "Using API: %s %d.%d.%d" %(hypervisior, apiVersion_major, apiVersion_minor, apiVersion_rel)
284
285         return { "libVersion"  : "%d.%d.%d" %(libVersion_major, libVersion_minor, libVersion_rel),
286                  "apiVersion"  : "%s %d.%d.%d" %(hypervisior, apiVersion_major, apiVersion_minor, apiVersion_rel)
287                }
288
289     def get_nodeinfo(self):
290         info = dict()
291         data = self._conn.getInfo()
292         info = {
293             "model"        : data[0],
294             "memory"       : data[1],
295             "cpus"         : data[2],
296             "mhz"          : data[3],
297             "nodes"        : data[4],
298             "sockets"      : data[5],
299             "cores"        : data[6],
300             "threads"      : data[7]
301         }
302         return info
303
304     def get_mem_info(self):
305         """<comment-ja>
306         メモリの情報を取得する。
307          - guest_alloc_mem: ゲストOSに割り当てているメモリサイズ,
308          - host_max_mem: ホストOSのメモリサイズ,
309          - host_free_mem: ホストOSの未割り当てメモリサイズ
310          - 単位はMB
311         @rtype: dict
312         </comment-ja>
313         <comment-en>
314         </comment-en>
315         """
316         active_guests = self.list_active_guest()
317         inactive_guests = self.list_inactive_guest()
318         info = self.get_nodeinfo()
319         host_max_mem = info['memory']
320
321         guest_alloc_mem = 0
322         
323         for domname in active_guests + inactive_guests:
324             if not domname == "Domain-0":
325                 virt = self.search_kvg_guests(domname)[0]
326                 info = virt.get_info()
327                 guest_alloc_mem += int(info["maxMem"])
328                 
329         guest_alloc_mem /= 1000  # a unit 'MB'
330
331         host_free_mem = host_max_mem - guest_alloc_mem
332         if host_free_mem < 0: host_free_mem = 0
333
334         info = {
335             'guest_alloc_mem' : guest_alloc_mem,
336             'host_max_mem' : host_max_mem,
337             'host_free_mem' : host_free_mem,
338         }
339         return info
340
341     def is_max_vcpus(self, type=None):
342         """<comment-ja>
343         ゲストに割り当て可能な仮想CPU数の最大値を取得できるか。
344
345         @param type: ハイパーバイザー
346         @return: the maximum number of virtual CPUs supported for a
347           guest VM of a specific type.
348         @rtype: bool
349         </comment-ja>
350         <comment-en>
351         Get the maximum number of vcpu supported for guest.
352
353         @param type: type of hypervisor
354         @return: the maximum number of vcpus
355         @rtype: bool
356         </comment-en>
357         """
358         if type is None:
359             type = self.get_hypervisor_type()
360         try:
361             max = self._conn.getMaxVcpus(type.lower())
362             return True
363         except libvirt.libvirtError:
364             return False
365
366     def get_max_vcpus(self, type=None):
367         """<comment-ja>
368         ゲストに割り当て可能な仮想CPU数の最大値を取得する
369
370         @param type: ハイパーバイザー
371         @return: the maximum number of virtual CPUs supported for a
372           guest VM of a specific type.
373         @rtype: integer
374         </comment-ja>
375         <comment-en>
376         Get the maximum number of vcpu supported for guest.
377
378         @param type: type of hypervisor
379         @return: the maximum number of vcpus
380         @rtype: integer
381         </comment-en>
382         """
383         if type is None:
384             type = self.get_hypervisor_type()
385         try:
386             max = self._conn.getMaxVcpus(type.lower())
387         except libvirt.libvirtError:
388             max = 32
389         return max
390
391     def get_physical_cpus(self):
392         """<comment-ja>
393         物理CPU数を取得する
394
395         @return: 物理CPU数
396         @rtype: integer
397         </comment-ja>
398         <comment-en>
399         Get the number of phisical CPUs.
400
401         @return: the number of physical CPUs
402         @rtype: integer
403         </comment-en>
404         """
405         info = self.get_nodeinfo()
406         return info['nodes'] * info['sockets'] * info['cores'] * info['threads']
407
408     """
409     Domain-U
410     """
411     def set_domain_name(self,name=None):
412         self.guest.set_domain_name(name)
413     def get_domain_name(self):
414         return self.guest.get_domain_name()
415
416     def uuid_to_domname(self, uuid):
417         """
418         <comment-ja>
419         ゲストOSのUUIDからドメイン名を取得します。
420         </comment-ja>
421         <comment-en>
422         </comment-en>
423         """
424         try:
425             #guest = self._conn.lookupByUUIDString(uuid)
426             #return guest.name()
427             for guests in self.search_guests():
428                 if uuid == guests.UUIDString():
429                     return guests.name()
430         except:
431             return ''
432
433     def domname_to_uuid(self, domname):
434         """
435         <comment-ja>
436         ドメイン名からゲストOSのUUIDを取得します。
437         </comment-ja>
438         <comment-en>
439         </comment-en>
440         """
441         try:
442             return self.search_guests(domname)[0].UUIDString()
443         except:
444             return ''
445
446
447     def list_inactive_guest(self):
448         """
449         <comment-ja>
450         現在起動していないゲストOSを取得します。
451         </comment-ja>
452         <comment-en>
453         </comment-en>
454         """
455         return self._conn.listDefinedDomains()
456
457     def list_active_guest(self):
458         """
459         <comment-ja>
460         現在起動しているゲストOSを取得します。
461         </comment-ja>
462         <comment-en>
463         </comment-en>
464         """
465         names = []
466         for id in self._conn.listDomainsID():
467             dom = self._conn.lookupByID(id);
468             names.append(dom.name())
469         return names
470
471     def search_guests(self, name=None):
472         """
473         <comment-ja>
474         ドメイン名からゲストOSを検索します。
475         </comment-ja>
476         <comment-en>
477         </comment-en>
478         """
479         guests = []
480
481         if is_uuid(name):
482             name = self.uuid_to_domname(name)
483
484         ids = self._conn.listDomainsID()
485         for id in ids:
486             if self._conn.lookupByID(id).name() == "Domain-0" and self.get_hypervisor_type() == 'Xen':
487                 continue
488             guests.append(self._conn.lookupByID(id))
489         names = self.list_inactive_guest()
490         for _name in names:
491             guests.append(self._conn.lookupByName(_name))
492
493         if name == None:
494             return guests
495
496         for guest in guests:
497             if guest.name() == name:
498                 return [guest]
499
500         #return []
501         raise KaresansuiVirtException("guest %s not found" % name)
502
503     def search_kvg_guests(self, name=None):
504         """<comment-ja>
505         指定されたゲストOSオブジェクトをKaresansuiVirtGuestオブジェクトのlistにして返却する。
506         </comment-ja>
507         <comment-en>
508         TODO: English Comment
509         </comment-en>
510         """
511
512         if is_uuid(name):
513             name = self.uuid_to_domname(name)
514
515         guests = []
516         for guest in self.search_guests(name):
517             guests.append(
518                 KaresansuiVirtGuest(conn=self, name=guest.name()))
519
520         return guests
521
522     def list_used_vnc_port(self):
523         """
524         <comment-ja>
525         すでにシステムで利用しているVNCポート番号を取得します。
526         </comment-ja>
527         <comment-en>
528         TODO:
529         </comment-en>
530         """
531         ports = []
532         for guest in self.search_guests(None):
533
534             param = ConfigParam(guest.name())
535             xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, guest.name())
536             if not os.path.exists(xml_file):
537                 dom = self._conn.lookupByName(guest.name())
538                 ConfigFile(xml_file).write(dom.XMLDesc(0))
539                 if os.getuid() == 0 and os.path.exists(xml_file):
540                     r_chgrp(xml_file,KARESANSUI_GROUP)
541             param.load_xml_config(xml_file)
542
543             vnc_port = param.vnc_port
544             if vnc_port and int(vnc_port) > 0:
545                 ports.append(int(vnc_port))
546
547         return UniqSort(ports)
548
549     def list_used_mac_addr(self):
550         """
551         <comment-ja>
552         すでにシステムで利用しているMAC Addressを取得します。
553         </comment-ja>
554         <comment-en>
555         TODO:
556         </comment-en>
557         """
558         addrs = []
559         for guest in self.search_guests(None):
560
561             param = ConfigParam(guest.name())
562             xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, guest.name())
563             if not os.path.exists(xml_file):
564                 dom = self._conn.lookupByName(guest.name())
565                 ConfigFile(xml_file).write(dom.XMLDesc(0))
566                 if os.getuid() == 0 and os.path.exists(xml_file):
567                     r_chgrp(xml_file,KARESANSUI_GROUP)
568             param.load_xml_config(xml_file)
569
570             for info in param.interfaces:
571                 mac_addr = info['mac']
572                 addrs.append(mac_addr.lower())
573
574         return addrs
575
576     def set_interface_format(self, format=None):
577         """
578         <comment-ja>
579         TODO:
580         </comment-ja>
581         <comment-en>
582         TODO:
583         </comment-en>
584         """
585
586         if format is None:
587             format = "b:xenbr0"
588
589         self.interface_format = []
590         for _format in format.split(','):
591             (type, name) = _format.split(':')
592             if type[0] == 'n':
593                 try:
594                     netinfo = self.search_kvn_networks(name)[0].get_info()
595                     self.interface_format.append( {"type": "bridge", "name":netinfo['bridge']['name']} )
596                 except:
597                     raise
598             else:
599                 self.interface_format.append( {"type": "bridge", "name":name} )
600
601     def make_domain_dir(self, dir, name):
602         """
603         <comment-ja>
604         'dir'(Storage Pool)で構成されたゲスト用ディレクトリ構成を作成します。
605         </comment-ja>
606         <comment-en>
607         TODO:
608         </comment-en>
609         """
610         # domain dir
611         domain_dir = "%s/%s" % (dir, name,)
612         domain_images_dir   = "%s/images"   % (domain_dir,)
613         domain_boot_dir     = "%s/boot"     % (domain_dir,)
614         domain_disk_dir     = "%s/disk"     % (domain_dir,)
615         # < 2.0.0
616         #domain_snapshot_dir = "%s/snapshot" % (domain_dir,)
617
618         if not os.path.exists(domain_dir):
619             os.makedirs(domain_dir)
620         if not os.path.exists(domain_images_dir):
621             os.makedirs(domain_images_dir)
622         if not os.path.exists(domain_boot_dir):
623             os.makedirs(domain_boot_dir)
624         if not os.path.exists(domain_disk_dir):
625             os.makedirs(domain_disk_dir)
626         #if not os.path.exists(domain_snapshot_dir):
627         #    os.makedirs(domain_snapshot_dir)
628         if os.getuid() == 0:
629             r_chgrp(domain_dir,KARESANSUI_GROUP)
630             r_chmod(domain_dir,"o-rwx")
631
632         return domain_dir
633
634     def create_guest(self, name=None, type="xen", ram=256, disk=None, disksize=1024*16, 
635                      mac=None, uuid=None, kernel=None, initrd=None, iso=None, vnc=None,
636                      vcpus=None, extra=None, keymap=DEFAULT_KEYMAP,
637                      bus=None, disk_format=None,
638                      storage_pool=None, storage_volume=None):
639         """
640         <comment-ja>
641         ゲストOSの作成を行います。
642         </comment-ja>
643         <comment-en>
644         TODO:
645         </comment-en>
646         """
647         param = ConfigParam(name)
648
649         # Disk
650         if type == "kvm" and iso is not None:
651             param.add_disk(iso, "hdc", "cdrom") # install iso image
652
653         if bus is not None:
654             bus = bus.lower()
655
656         # Pool
657         pool_objs = self.search_kvn_storage_pools(storage_pool)
658         if not pool_objs:
659             raise KaresansuiVirtException(_("Storage pool could not be found. pool=%s") % \
660                                               storage_pool)
661
662         pool_type = pool_objs[0].get_info()['type']
663
664         if pool_type == 'iscsi':
665             domains_dir = VENDOR_DATA_ISCSI_DOMAINS_DIR
666             domain_dir = self.make_domain_dir(VENDOR_DATA_ISCSI_DOMAINS_DIR, name)
667         else:
668             domains_dir = pool_objs[0].get_info()["target"]["path"]
669             domain_dir = self.make_domain_dir(domains_dir, name)
670
671
672         if pool_type == "iscsi":
673             disk_type = "block"
674             disk = self.get_storage_volume_path(storage_pool, storage_volume)
675         else:
676             disk_type = "file"
677             #disk = "%s/images/%s.img" % (domain_dir, storage_volume)
678             disk = "%s/images/%s.img" % (domain_dir, name)
679
680         if disk is None:
681             raise KaresansuiVirtException("%s pool=%s,volume=%s" % \
682                                           (_("Storage path could not be retrieved."),
683                                            storage_pool,
684                                            storage_volume
685                                            ))
686
687         driver_type = None
688         driver_name = None
689         try:
690             file_format = get_disk_img_info(disk)['file_format']
691             if file_format == "qcow2":
692                 driver_type = "qcow2"
693                 if type == "kvm":
694                     driver_name = "qemu"
695             if type == "kvm":
696                 driver_type = file_format
697         except:
698             pass
699
700         if bus == "virtio":
701             target_dev_prefix = "vd"
702         elif bus == "scsi":
703             target_dev_prefix = "sd"
704         else:
705             target_dev_prefix = self.disk_prefix
706
707         param.add_disk(disk,
708                        target_dev_prefix + "a",
709                        bus=bus,
710                        disk_type=disk_type,
711                        driver_name=driver_name,
712                        driver_type=driver_type)
713
714         if mac is None:
715             mac = GenMAC()
716
717         if uuid is None:
718             uuid = StrFromUUID(GenUUID())
719
720         if vcpus is None:
721             vcpus = 1
722
723         if vnc is None:
724             used_ports = self.list_used_vnc_port()
725             vnc = NextNumber(VNC_PORT_MIN_NUMBER,PORT_MAX_NUMBER,used_ports)
726
727 #        if os.path.exists(disk):
728 #            os.unlink(disk)
729
730         param.set_domain_type(type)
731         param.set_uuid(uuid)
732         if type == "kvm":
733             acpi_info_file = "/proc/acpi/info"
734             if os.path.exists(acpi_info_file):
735                 param.set_features_acpi(True)
736             if iso is not None:
737                 param.set_boot_dev("cdrom")
738                 if is_windows_bootable_iso(iso) is not False:
739                     param.set_features_apic(True)
740                 elif is_darwin_bootable_iso(iso) is not False:
741                     param.set_features_apic(True)
742             else:
743                 param.set_kernel(kernel)
744                 param.set_initrd(initrd)
745         else:
746             param.set_kernel(kernel)
747             param.set_initrd(initrd)
748
749         param.set_max_vcpus(vcpus)
750         param.set_memory(str(ram) + 'm')
751         param.set_vnc_keymap(keymap)
752
753
754
755         for _format in self.interface_format:
756             if _format['name'][0:5] == 'xenbr':
757                 script = "vif-bridge"
758             else:
759                 script = None
760
761             if mac is None:
762                 mac = GenMAC()
763                 param.add_interface(mac,"bridge",_format['name'],script)
764             else:
765                 param.add_interface(mac.lower(),"bridge",_format['name'],script)
766                 mac = None
767
768         param.set_vnc_port(vnc)
769         if extra != None:
770             param.append_commandline(extra)
771         param.set_behavior("on_shutoff","destroy")
772         param.set_behavior("on_reboot","destroy")
773         param.set_behavior("on_crash","destroy")
774
775         r = re.compile(r"""(?:ftp|http)s?://""")
776
777         domain_boot_dir = "%s/boot" % (domain_dir,)
778         if kernel is not None:
779             (kfd, kfn) = tempfile.mkstemp(prefix="vmlinuz.", dir=domain_boot_dir)
780             m = r.match(param.get_kernel())
781             if m:
782               os.close(kfd)
783               DownloadFile(param.get_kernel(),kfn)
784             else:
785               kernel = open(param.get_kernel(),"r")
786               os.write(kfd, kernel.read())
787               os.close(kfd)
788               kernel.close()
789             param.set_kernel(kfn)
790
791         if initrd is not None:
792             (ifd, ifn) = tempfile.mkstemp(prefix="initrd.img.", dir=domain_boot_dir)
793             m = r.match(param.get_initrd())
794             if m:
795               os.close(ifd)
796               DownloadFile(param.get_initrd(),ifn)
797             else:
798               initrd = open(param.get_initrd(),"r")
799               os.write(ifd, initrd.read())
800               os.close(ifd)
801               initrd.close()
802             param.set_initrd(ifn)
803
804         sync_config_generator(param)
805
806         if self._conn is None:
807             self._conn = self.open(None)
808
809         generator = XMLConfigGenerator()
810         try:
811             cfgxml = generator.generate(param)
812         except:
813             raise
814
815         dom = self._conn.createLinux(cfgxml, 0)
816         time.sleep(2)
817         self._conn.defineXML(cfgxml)
818         time.sleep(1)
819         try:
820             self._conn.lookupByID(dom.ID())
821         except libvirt.libvirtError:
822             raise "create_guest() error. name:%s" % (name)
823
824         if initrd is not None:
825             os.unlink(param.get_initrd())
826
827         if kernel is not None:
828             os.unlink(param.get_kernel())
829
830         param.set_kernel(None)
831         param.set_initrd(None)
832         param.cmdline = []
833         if type == "xen":
834             param.set_bootloader("/usr/bin/pygrub")
835         elif type == "kvm":
836             param.set_boot_dev("hd")
837
838         if type == "kvm" and iso is not None:
839             param.delete_disk("hdc")
840         param.set_behavior("on_reboot","restart")
841         param.set_behavior("on_crash","restart")
842
843         sync_config_generator(param)
844
845         config = "%s/%s.xml" %(VIRT_XML_CONFIG_DIR,name,)
846         if os.path.exists(config):
847             f = open(config, "r")
848             cfgxml= f.read()
849             f.close()
850             self._conn.defineXML(cfgxml)
851
852         try:
853             self.search_storage_pools(storage_pool)[0].refresh(True)
854         except:
855             pass
856
857     def start_guest(self,name=None):
858         """
859         <comment-ja>
860         ゲストOSの起動を行います。
861         </comment-ja>
862         <comment-en>
863         TODO:
864         </comment-en>
865         """
866         if not (name is None):
867             self.guest.set_domain_name(name)
868
869         name = self.guest.get_domain_name()
870         config = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR,name,)
871         if os.path.exists(config):
872             f = open(config, "r")
873             cfgxml= f.read()
874             f.close()
875             self._conn.defineXML(cfgxml)
876
877         self.guest.create()
878
879     def shutdown_guest(self,name=None):
880         """
881         <comment-ja>
882         ゲストOSの停止を行います。
883         </comment-ja>
884         <comment-en>
885         TODO:
886         </comment-en>
887         """
888         if not (name is None):
889             self.guest.set_domain_name(name)
890         self.guest.shutdown()
891
892     def reboot_guest(self,name=None):
893         """
894         <comment-ja>
895         ゲストOSを再起動します。
896         </comment-ja>
897         <comment-en>
898         TODO:
899         </comment-en>
900         """
901         if not (name is None):
902             self.guest.set_domain_name(name)
903         self.guest.reboot()
904
905     def destroy_guest(self,name=None):
906         """
907         <comment-ja>
908         ゲストOSを削除します。(設定ファイルやゲストOS定義は削除されません。)
909         </comment-ja>
910         <comment-en>
911         TODO:
912         </comment-en>
913         """
914         if not (name is None):
915             self.guest.set_domain_name(name)
916         self.guest.destroy()
917
918     def delete_guest(self, name, pool, volume):
919         """
920         <comment-ja>
921         ゲストOSを完全に削除します。
922         </comment-ja>
923         <comment-en>
924         TODO:
925         </comment-en>
926         """
927         name = self.guest.get_domain_name()
928         tmp_pool = self.get_storage_pool_name_bydomain(name, 'os')
929         if tmp_pool:
930             pool_objs = self.search_kvn_storage_pools(tmp_pool[0])
931         else:
932             pool_objs = self.search_kvn_storage_pools(pool)
933
934         pool_type = pool_objs[0].get_info()['type']
935         if pool_type == 'iscsi':
936             domains_dir = VENDOR_DATA_ISCSI_DOMAINS_DIR
937             domain_dir = "%s/%s" % (VENDOR_DATA_ISCSI_DOMAINS_DIR, name)
938         else:
939             domains_dir = self.get_storage_pool_targetpath(pool)
940             domain_dir = "%s/%s" % (domains_dir, name)
941
942         vols = self.get_storage_volume_bydomain(name, 'os')
943         if vols:
944             vol_path = "%s/%s" % (domains_dir, vols.keys()[0])
945         else:
946             vol_path = "%s/%s" % (domains_dir, volume)
947
948         self.destroy_guest(name)
949         try:
950             self.guest.undefine()
951         except:
952             pass
953
954         import shutil
955         if os.path.islink(vol_path):
956             os.unlink(vol_path)
957
958         if os.path.exists(domain_dir):
959             #os.removedirs(domain_dir)
960             shutil.rmtree(domain_dir)
961
962         # delete qemu snapshot
963         domain_snapshot_dir = "%s/%s" % (VIRT_SNAPSHOT_DIR,name,)
964         if os.path.exists(domain_snapshot_dir):
965             #os.removedirs(domain_snapshot_dir)
966             shutil.rmtree(domain_snapshot_dir)
967
968         if tmp_pool:
969             try:
970                 self.search_storage_pools(tmp_pool[0])[0].refresh(True)
971             except:
972                 pass
973         else:
974             try:
975                 self.search_storage_pools(pool)[0].refresh(True)
976             except:
977                 pass
978
979     def suspend_guest(self,name=None):
980         """
981         <comment-ja>
982         起動しているゲストOSを一時停止します。
983         </comment-ja>
984         <comment-en>
985         TODO:
986         </comment-en>
987         """
988         if not (name is None):
989             self.guest.set_domain_name(name)
990         self.guest.suspend()
991
992     def resume_guest(self,name=None):
993         """
994         <comment-ja>
995         suspendしているゲストOSを復帰させます。
996         </comment-ja>
997         <comment-en>
998         TODO:
999         </comment-en>
1000         """
1001         if not (name is None):
1002             self.guest.set_domain_name(name)
1003         self.guest.resume()
1004
1005     def autostart_guest(self,flag=None,name=None):
1006         """
1007         <comment-ja>
1008         ゲストOSの自動起動設定を行います。
1009         </comment-ja>
1010         <comment-en>
1011         TODO:
1012         </comment-en>
1013         """
1014         if not (name is None):
1015             self.guest.set_domain_name(name)
1016         guests = self.search_guests(self.guest.get_domain_name())
1017         if len(guests):
1018             return self.guest.autostart(flag)
1019         else:
1020             return False
1021
1022     def replicate_storage_volume(self, orig_domname, orig_pool, orig_volume,
1023                                  dest_domname, dest_pool, dest_volume,
1024                                  progresscb=None):
1025         """<comment-ja>
1026         ストレージボリュームをコピーします。
1027         @param orig_domname: コピー元ドメイン名
1028         @param orig_pool: コピー元ストレージプール名
1029         @param orig_volume: コピー元ストレージボリューム名
1030         @param dest_domname: コピー先ドメイン名
1031         @param dest_pool: コピー先ストレージプール名
1032         @param dest_volume: コピー先ストレージボリューム名
1033         @param progresscb: コピー方式
1034         @return: 実行結果
1035         </comment-ja>
1036         <comment-en>
1037         TODO: English Documents(en)
1038         </comment-en>
1039         """
1040         orig_symlink_path = self.get_storage_volume_iscsi_rpath_bystorage(orig_pool, orig_volume)
1041         orig_rpath = os.path.realpath(orig_symlink_path)
1042         if not orig_rpath:
1043             return False
1044
1045         # orig
1046         orig_domains_dir = self.get_storage_pool_targetpath(orig_pool)
1047         orig_domain_dir = "%s/%s" % (orig_domains_dir, orig_domname)
1048
1049         # dest
1050         dest_domains_dir = self.get_storage_pool_targetpath(dest_pool)
1051         dest_domain_dir = self.make_domain_dir(dest_domains_dir, dest_domname)
1052
1053         orig_files = [orig_rpath,]
1054         dest_files = ["%s/disk/%s.img" % (dest_domain_dir, dest_volume),]
1055         if os.path.isfile(dest_files[0]) is True:
1056             raise KaresansuiVirtException("Already exists in the destination storage volume.")
1057
1058         if progresscb is not None:
1059             from karesansui.lib.utils import copy_file_cb
1060             copy_file_cb(orig_files, dest_files, progresscb, each=False)
1061         else:
1062             CopyFile(orig_files, dest_files)
1063
1064         # symlink
1065         os.symlink(dest_files[0], "%s/%s" % (dest_domains_dir, dest_volume))
1066
1067         # Storage Pool refresh
1068         try:
1069             self.search_storage_pools(orig_pool)[0].refresh(True)
1070             self.search_storage_pools(dest_pool)[0].refresh(True)
1071         except:
1072             pass
1073
1074         return True
1075
1076     def replicate_guest(self, name, source_name, pool, mac=None, uuid=None, vnc=None):
1077         """<comment-ja>
1078         ゲストOSのコピーを行います。
1079         すべてのディスクがfile形式のみ実行可能です。
1080         </comment-ja>
1081         <comment-en>
1082         TODO:
1083         </comment-en>
1084         """
1085         param = ConfigParam(name)
1086
1087         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, source_name)
1088         if not os.path.exists(xml_file):
1089             dom = self._conn.lookupByName(source_name)
1090             ConfigFile(xml_file).write(dom.XMLDesc(0))
1091             if os.getuid() == 0 and os.path.exists(xml_file):
1092                 r_chgrp(xml_file,KARESANSUI_GROUP)
1093         param.load_xml_config(xml_file)
1094
1095         autostart = False
1096         try:
1097             guest_obj = self.search_kvg_guests(source_name)[0]
1098             if not guest_obj:
1099                 raise KaresansuiVirtException(_("Domain could not be found. name=%s") % source_name)
1100             autostart = guest_obj.autostart()
1101         except:
1102             pass
1103
1104         # Source storage pool dir
1105         src_pool = self.get_storage_pool_name_bydomain(source_name, "os")[0]
1106         src_target_path = self.get_storage_pool_targetpath(src_pool)
1107         source_disk = "%s/%s/images/%s.img" \
1108                       % (src_target_path, source_name,source_name)
1109
1110         pool_dir = self.get_storage_pool_targetpath(pool)
1111         disk = "%s/%s/images/%s.img" % (pool_dir, name, name)
1112
1113         src_interfaces = param.interfaces
1114         param.interfaces = []
1115         for ifs in src_interfaces:
1116             script = ifs['script']
1117             if mac is None:
1118                 mac = GenMAC()
1119                 param.add_interface(mac,"bridge",ifs['bridge'],script)
1120             else:
1121                 param.add_interface(mac.lower(),"bridge",ifs['bridge'],script)
1122                 mac = None
1123
1124         if uuid is None:
1125             uuid = StrFromUUID(GenUUID())
1126
1127         if vnc is None:
1128             used_ports = self.list_used_vnc_port()
1129             vnc = NextNumber(VNC_PORT_MIN_NUMBER,PORT_MAX_NUMBER,used_ports)
1130
1131         old_disks = param.disks
1132
1133         # get further informations of disk used by os.
1134         bus = None
1135         driver_name = None
1136         driver_type = None
1137         for disk_info in old_disks:
1138             if disk_info['path'] == source_disk:
1139                 try:
1140                     bus = disk_info['bus']
1141                 except:
1142                     bus = None
1143                 try:
1144                     driver_name = disk_info['driver_name']
1145                 except:
1146                     driver_name = None
1147                 try:
1148                     driver_type = disk_info['driver_type']
1149                 except:
1150                     driver_type = None
1151                 break
1152
1153         param.disks = []
1154         param.set_uuid(uuid)
1155         param.set_vnc_port(vnc)
1156         param.add_disk(disk,
1157                        self.disk_prefix + "a",
1158                        bus=bus,
1159                        driver_name=driver_name,
1160                        driver_type=driver_type)
1161
1162         # dest make dirs
1163         self.make_domain_dir(pool_dir, name)
1164
1165         # TODO : boot dir
1166
1167         # 追加ディスクのコピー
1168         for _disk in old_disks:
1169             try:
1170                 s_disk_path   = _disk['path']
1171                 s_disk_target = _disk['target']
1172                 s_disk_bus    = _disk['bus']
1173                 try:
1174                     s_driver_name = _disk['driver_name']
1175                 except:
1176                     s_driver_name = None
1177                 try:
1178                     s_driver_type = _disk['driver_type']
1179                 except:
1180                     s_driver_type = None
1181
1182                 m = re.search("/domains/%s/disk/(?P<disk_name>[0-9\.]+\.img)$" % source_name ,s_disk_path)
1183                 if m:
1184                     new_disk_path = "%s/%s/disk/%s" % (pool_dir,name,m.group("disk_name"),)
1185
1186                     param.add_disk(new_disk_path,
1187                                    s_disk_target,
1188                                    "disk",
1189                                    bus=s_disk_bus,
1190                                    driver_name=s_driver_name,
1191                                    driver_type=s_driver_type)
1192
1193                     if not os.path.exists(new_disk_path):
1194                         CopyFile(s_disk_path,new_disk_path)
1195             except:
1196                 pass
1197
1198         # スナップショットのコピー
1199         # libvirtdの再起動後に認識される。(qemuDomainSnapshotLoad)
1200         s_domain_snapshot_dir = "%s/%s" % (VIRT_SNAPSHOT_DIR,source_name,)
1201         if os.path.exists(s_domain_snapshot_dir):
1202             domain_snapshot_dir = "%s/%s" % (VIRT_SNAPSHOT_DIR,name,)
1203             for snapshot_xml in glob.glob("%s/*.xml" % s_domain_snapshot_dir):
1204                 snapshot_xml_name = os.path.basename(snapshot_xml)
1205                 new_snapshot_xml = "%s/%s" % (domain_snapshot_dir,snapshot_xml_name,)
1206                 if not os.path.exists(domain_snapshot_dir):
1207                     os.makedirs(domain_snapshot_dir)
1208
1209                 old_pattern = "<uuid>.{36}</uuid>"
1210                 new_string  = "<uuid>%s</uuid>" % uuid
1211                 file_contents_replace(snapshot_xml,new_snapshot_xml,old_pattern,new_string)
1212             if os.getuid() == 0:
1213                 if os.path.exists(domain_snapshot_dir):
1214                     r_chmod(domain_snapshot_dir,"o-rwx")
1215                     r_chgrp(domain_snapshot_dir,KARESANSUI_GROUP)
1216
1217                 # This is commented out.
1218                 # cos guests that set to autostart flag will be started without intention.
1219                 #from karesansui.lib.virt.snapshot import KaresansuiVirtSnapshot
1220                 #kvs = KaresansuiVirtSnapshot()
1221                 #kvs.refreshSnapshot()
1222
1223         try:
1224             # ゲストOSイメージのコピー
1225             CopyFile(source_disk,disk)
1226
1227             # Storage pool directory, OS image set symlink
1228             os.symlink(disk,
1229                        "%s/%s" % (pool_dir, uuid))
1230
1231             xml_generator = XMLConfigGenerator()
1232             cfgxml = xml_generator.generate(param)
1233             self._conn.defineXML(cfgxml)
1234         except:
1235             raise
1236
1237         sync_config_generator(param, name)
1238
1239         # set autostart flag
1240         if autostart is True:
1241             try:
1242                 guest_obj = self.search_kvg_guests(name)[0]
1243                 if not guest_obj:
1244                     raise KaresansuiVirtException(_("Domain could not be found. name=%s") % name)
1245                 guest_obj.autostart(flag=autostart)
1246             except:
1247                 raise KaresansuiVirtException(_("Failed to set autostart flag. - dom=%s flag=%s") % (name,autostart))
1248
1249         # Storage Pool refresh
1250         for p in [src_pool, pool]:
1251             try:
1252                 self.search_storage_pools(p)[0].refresh(True)
1253             except:
1254                 pass
1255
1256         return True
1257
1258     def export_guest(self, uuid, name, directory, database, realicon, title="", snapshots=None, progresscb=None):
1259         """<comment-ja>
1260         ゲストOSののエクスポートを行います。
1261         </comment-ja>
1262         <comment-en>
1263         TODO:
1264         </comment-en>
1265         """
1266         #inactive_pools = self.list_inactive_storage_pool()
1267         inactive_pools = []
1268         active_pools   = self.list_active_storage_pool()
1269
1270         pool_name = None
1271         for _pool in inactive_pools + active_pools:
1272             path = self.search_kvn_storage_pools(_pool)[0].get_info()["target"]["path"]
1273             if directory == path:
1274                 pool_name = _pool
1275
1276         if not os.path.exists(directory):
1277             raise KaresansuiVirtException(_("Directory '%s' not found.") % directory)
1278
1279         if not (name is None):
1280             self.guest.set_domain_name(name)
1281
1282         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, name)
1283         config_file = "%s/%s" % (self.config_dir, name)
1284
1285         src_pool = self.get_storage_pool_name_bydomain(name, "os")[0]
1286         src_path = self.get_storage_pool_targetpath(src_pool)
1287
1288         domain_dir = "%s/%s" % (src_path,name,)
1289         image_file = "%s/images/%s.img" % (domain_dir,name)
1290         domain_snapshot_dir = "%s/%s" % (VIRT_SNAPSHOT_DIR,name,)
1291
1292         export_dir = "%s/%s" % (directory,uuid)
1293         #export_domain_dir = "%s/%s" % (export_dir,name)
1294         export_domain_dir = "%s/domain/%s" % (export_dir,name)
1295         #export_disk_dir = "%s/%s" % (export_dir,name)
1296         export_disk_dir = "%s/disk" % (export_dir)
1297
1298         if os.path.exists(export_domain_dir):
1299             raise KaresansuiVirtException(_("Directory '%s' found.") % export_domain_dir)
1300
1301         try:
1302             if not os.path.exists(export_domain_dir):
1303                 os.makedirs(export_domain_dir)
1304                 if os.getuid() == 0:
1305                     r_chgrp(export_dir,KARESANSUI_GROUP)
1306                     r_chmod(export_dir,"o-rwx")
1307
1308             if not os.path.exists(export_disk_dir):
1309                 os.makedirs(export_disk_dir)
1310                 if os.getuid() == 0:
1311                     r_chgrp(export_dir,KARESANSUI_GROUP)
1312                     r_chmod(export_dir,"o-rwx")
1313
1314             # -----------------------
1315             # Export information to disk to retrieve.
1316             disk_keys = self.get_storage_volume_bydomain(
1317                 self.guest.get_domain_name(), 'disk', 'key')
1318
1319             disks_info = []
1320             for key in disk_keys.keys():
1321                 _volume = key
1322                 _path = disk_keys[key]
1323                 _pool_name = self.get_storage_pool_name_byimage(_path)
1324
1325                 if not _pool_name:
1326                     raise KaresansuiVirtException("'%s' disk storage pool can not be found." % _volume)
1327                 else:
1328                     _pool_name = _pool_name[0]
1329
1330                 _pool = self.search_kvn_storage_pools(_pool_name)
1331                 if not _pool:
1332                     raise KaresansuiVirtException("'%s' disk storage pool(path) can not be found." % _volume)
1333                 else:
1334                     _pool = _pool[0]
1335
1336                 _pool_path = _pool.get_info()['target']['path']
1337                 pool_uuid = _pool.get_info()['uuid']
1338
1339                 disks_info.append({"volume" : _volume,
1340                                    "volume_path" : _path,
1341                                    "pool_name" : _pool_name,
1342                                    "domname" : self.guest.get_domain_name(),
1343                                    "pool_path" : _pool_path,
1344                                    "pool_uuid" : pool_uuid
1345                                    })
1346
1347             # Disk export
1348             for disk_info in disks_info:
1349                 disk_dir = "%s/%s" % (disk_info["pool_path"], disk_info["domname"])
1350                 if progresscb is not None:
1351                     from karesansui.lib.utils import copy_file_cb
1352
1353                     src_files = []
1354                     dst_files = []
1355                     for _sub in glob.glob("%s/disk/*" % disk_dir):
1356                         if os.path.isfile(_sub):
1357                             # {export uuid}/disk/{pool name}/{domname}/[images|boot|disk]
1358                             #dst_file = "%s/%s" % (export_disk_dir, os.path.basename(_sub),)
1359                             dst_file = "%s/%s/%s/disk/%s" % (export_disk_dir,
1360                                                        disk_info["pool_name"],
1361                                                        disk_info["domname"],
1362                                                        os.path.basename(_sub),
1363                                                        )
1364                             src_file = _sub
1365                             src_files.append(src_file)
1366                             dst_files.append(dst_file)
1367                     copy_file_cb(src_files,dst_files,progresscb,each=False)
1368                 else:
1369                     CopyFile(disk_dir, export_disk_dir)
1370
1371             # -----------------------
1372
1373             # copy domain image data
1374             if progresscb is not None:
1375                 from karesansui.lib.utils import copy_file_cb
1376
1377                 src_files = []
1378                 dst_files = []
1379                 # os image
1380                 src_files.append("%s/images/%s.img" % (domain_dir, name))
1381                 dst_files.append("%s/images/%s.img" % (export_domain_dir, name))
1382                 copy_file_cb(src_files,dst_files,progresscb,each=False)
1383
1384                 # boot
1385                 src_files = []
1386                 dst_files = []
1387                 for _sub in glob.glob("%s/boot/*" % domain_dir):
1388                     if os.path.isfile(_sub) is True:
1389                         dst_file = "%s/boot/%s" % (export_domain_dir,os.path.basename(_sub),)
1390                         src_files.append(_sub)
1391                         dst_files.append(dst_file)
1392
1393                 copy_file_cb(src_files,dst_files,progresscb,each=False)
1394             else:
1395                 CopyFile(domain_dir,export_domain_dir)
1396
1397             # copy domain configuration
1398             export_xml_file    = "%s/%s.xml"  % (export_dir,name,)
1399             CopyFile(xml_file,   export_xml_file)
1400             export_config_file = "%s/%s.conf" % (export_dir,name,)
1401             CopyFile(config_file,export_config_file)
1402
1403             # copy snapshot xmls
1404             if os.path.exists(domain_snapshot_dir):
1405                 export_snapshot_dir = "%s/snapshot" % (export_domain_dir,)
1406
1407                 try:
1408                     os.makedirs(export_snapshot_dir)
1409                 except:
1410                     pass
1411
1412                 for snapshot_xml in glob.glob("%s/*.xml" % domain_snapshot_dir):
1413                     snapshot_xml_name = os.path.basename(snapshot_xml)
1414                     export_snapshot_xml = "%s/%s" % (export_snapshot_dir,snapshot_xml_name,)
1415                     CopyFile(snapshot_xml,export_snapshot_xml)
1416
1417             # symlink to recognize as libvirt pool
1418             export_image_file = "%s/images/%s.img" % (export_domain_dir,name)
1419             link_file = "%s/%s-%s.img" % (directory,uuid,name,)
1420             if os.path.exists(link_file) is False:
1421                 os.symlink(export_image_file,link_file)
1422
1423             # web icon image
1424             if database['icon']:
1425                 CopyFile(realicon, "%s/%s" % (export_dir, database['icon']))
1426
1427             # info.dat
1428             param = ExportConfigParam()
1429
1430             param.set_path("%s/%s" % (export_dir, GUEST_EXPORT_FILE))
1431             param.set_uuid(uuid)
1432             param.set_domain(name)
1433             param.set_title(title)
1434             param.set_created(str(int(time.time())))
1435             param.set_database(database)
1436             param.set_pool(src_pool)
1437             param.set_snapshots(snapshots)
1438
1439             # add_disk
1440             for disk_info in disks_info:
1441                 param.add_disk(disk_info['volume'],
1442                                disk_info['pool_name'],
1443                                disk_info['pool_path'],
1444                                )
1445
1446             generator = ExportXMLGenerator(param.get_path())
1447             try:
1448                 cfgxml = generator.generate(param)
1449             except:
1450                 raise
1451             generator.writecfg(cfgxml)
1452
1453             if os.getuid() == 0:
1454                 r_chgrp(export_dir,KARESANSUI_GROUP)
1455                 r_chmod(export_dir,"o-rwx")
1456
1457             if pool_name is not None:
1458                 try:
1459                     self.search_storage_pools(pool_name)[0].refresh(True)
1460                 except:
1461                     pass
1462
1463         except:
1464             raise
1465
1466     def import_guest(self, directory, uuid, progresscb):
1467         """
1468         <comment-ja>
1469         ゲストOSのインポートを行います。
1470         </comment-ja>
1471         <comment-en>
1472         TODO:
1473         </comment-en>
1474         """
1475         if not os.path.exists(directory):
1476             raise KaresansuiVirtException(_("Directory '%s' not found.") % directory)
1477
1478         export_dir = directory
1479
1480         # read info.dat
1481         param = ExportConfigParam()
1482         info_file = "%s/info.dat" % (export_dir,)
1483         if os.path.exists(info_file):
1484             try:
1485                 param.load_xml_config(info_file)
1486             except:
1487                 raise KaresansuiVirtException(_("'%s' is invalid format.") % info_file)
1488         else:
1489             raise KaresansuiVirtException(_("'%s' not found.") % info_file)
1490
1491         id    = param.get_uuid()
1492         name  = param.get_domain()
1493         title = param.get_title()
1494         created = param.get_created()
1495
1496         domains_dir = self.get_storage_pool_targetpath(param.get_pool())
1497         xml_file    = "%s/%s.xml"        % (VIRT_XML_CONFIG_DIR, name)
1498         config_file = "%s/%s"            % (self.config_dir, name)
1499         domain_dir  = "%s/%s"            % (domains_dir,name,)
1500         image_file  = "%s/images/%s.img" % (domain_dir,name)
1501         domain_snapshot_dir = "%s/%s"    % (VIRT_SNAPSHOT_DIR,name,)
1502
1503         export_domain_dir   = "%s/domain/%s"       % (export_dir,name,)
1504         #export_snapshot_dir = "%s/snapshot" % (export_domain_dir,)
1505         export_snapshot_dir = "%s/snapshot" % (export_domain_dir)
1506
1507         if not os.path.exists(export_domain_dir):
1508             raise KaresansuiVirtException(_("Directory '%s' not found.") % export_domain_dir)
1509
1510         if os.path.exists(domain_dir):
1511             raise KaresansuiVirtException(_("guest '%s' already exists.") % name)
1512
1513         try:
1514             from karesansui.lib.utils import copy_file_cb
1515             # copy disks {export dir}/{export uuid}/disk/{pool}/{domname}/disk/{disk uuid}.img
1516             export_disk_dir = "%s/disk" % (export_dir)
1517             export_disks = param.get_disks()
1518             src_files = []
1519             dst_files = []
1520             dst_symlinks = []
1521             for disk in export_disks:
1522                 volume = disk['uuid']
1523                 pool_name = disk['name']
1524                 pool_path = disk['path']
1525                 pool = self.search_kvn_storage_pools(pool_name)
1526                 if not pool:
1527                     raise KaresansuiVirtException(_("Disk storage pools were found to import. - pool=%s") \
1528                                             % pool_name)
1529                 else:
1530                     pool = pool[0]
1531
1532                 # check
1533                 if pool_path != pool.get_json()['target']['path']:
1534                     raise KaresansuiVirtException(_("When exporting, there are differences in the storage pool information. (Storage pool path) = export=%s, import=%s") \
1535                                             % (pool_path, pool.get_json()['target']['path']))
1536
1537                 src_file = "%s/%s/%s/disk/%s.img" % (export_disk_dir, pool_name, name, volume)
1538                 if os.path.isfile(src_file) is False:
1539                     raise KaresansuiVirtException(_("Exporting the disk image can not be found."))
1540
1541                 dst_file = "%s/%s/disk/%s.img" % (pool.get_json()['target']['path'], name, volume)
1542
1543                 src_files.append(src_file)
1544                 dst_files.append(dst_file)
1545                 dst_symlinks.append("%s/%s" % (pool.get_json()['target']['path'], volume))
1546
1547             copy_file_cb(src_files,dst_files,progresscb,each=False)
1548             for i in xrange(len(dst_symlinks)):
1549                 os.symlink(dst_files[i], dst_symlinks[i])
1550
1551
1552             # copy domain image data
1553             src_files = []
1554             dst_files = []
1555             for _sub in glob.glob("%s/*" % export_domain_dir):
1556                 if os.path.isdir(_sub):
1557                     dst_dir = "%s/%s" % (domain_dir,os.path.basename(_sub),)
1558                     for _sub2 in glob.glob("%s/*" % _sub):
1559                         if os.path.isfile(_sub2):
1560                             src_file = _sub2
1561                             dst_file = "%s/%s" % (dst_dir,os.path.basename(_sub2),)
1562                             src_files.append(src_file)
1563                             dst_files.append(dst_file)
1564             copy_file_cb(src_files,dst_files,progresscb,each=False)
1565
1566             export_xml_file    = "%s/%s.xml"  % (export_dir,name,)
1567             # os image symlink
1568             g_param = ConfigParam(name)
1569             if os.path.isfile(export_xml_file) is False:
1570                 raise KaresansuiVirtException(
1571                     _("Export corrupt data. (file not found) - path=%s" % export_xml_file))
1572             g_param.load_xml_config(export_xml_file)
1573
1574             os_image_path = "%s/%s/images/%s.img" % (domains_dir, name, name)
1575             if os.path.isfile(os_image_path) is False:
1576                 raise KaresansuiVirtException(_("Import failed guest OS image. - path=%s") \
1577                                               % os_image_path)
1578             os.symlink(os_image_path, "%s/%s" % (domains_dir, g_param.uuid))
1579
1580             # copy domain configuration
1581             export_config_file = "%s/%s.conf" % (export_dir,name,)
1582             if uuid is None:
1583                 CopyFile(export_xml_file    ,xml_file)
1584                 CopyFile(export_config_file ,config_file)
1585             else:
1586                 old_pattern = "<uuid>.{36}</uuid>"
1587                 new_string  = "<uuid>%s</uuid>" % uuid
1588                 file_contents_replace(export_xml_file,xml_file,old_pattern,new_string)
1589                 old_pattern = "^uuid = .*"
1590                 new_string  = "uuid = '%s'" % str(uuid)
1591                 file_contents_replace(export_config_file ,config_file,old_pattern,new_string)
1592
1593             if os.path.exists(xml_file):
1594                 self._conn.defineXML("".join(ConfigFile(xml_file).read()))
1595
1596             # copy snapshot xmls
1597             # libvirtdの再起動後に認識される。(qemuDomainSnapshotLoad)
1598             if os.path.exists(export_snapshot_dir):
1599
1600                 if not os.path.exists(domain_snapshot_dir):
1601                     os.makedirs(domain_snapshot_dir)
1602
1603                 for snapshot_xml in glob.glob("%s/*.xml" % export_snapshot_dir):
1604                     snapshot_xml_name = os.path.basename(snapshot_xml)
1605                     new_snapshot_xml = "%s/%s" % (domain_snapshot_dir,snapshot_xml_name,)
1606                     CopyFile(snapshot_xml,new_snapshot_xml)
1607
1608
1609             if os.getuid() == 0:
1610                 r_chgrp(domain_dir,KARESANSUI_GROUP)
1611                 r_chmod(domain_dir,"o-rwx")
1612                 r_chgrp(xml_file,    KARESANSUI_GROUP)
1613                 r_chgrp(config_file, KARESANSUI_GROUP)
1614                 if os.path.exists(domain_snapshot_dir):
1615                     r_chmod(domain_snapshot_dir,"o-rwx")
1616                     r_chgrp(domain_snapshot_dir,KARESANSUI_GROUP)
1617
1618                 # This is commented out.
1619                 # cos guests that set to autostart flag will be started without intention.
1620                 #from karesansui.lib.virt.snapshot import KaresansuiVirtSnapshot
1621                 #kvs = KaresansuiVirtSnapshot()
1622                 #kvs.refreshSnapshot()
1623
1624             # Storage Pool refresh
1625             try:
1626                 self.search_storage_pools(param.get_pool())[0].refresh(True)
1627                 for disk in param.get_disks():
1628                     self.search_storage_pools(disk["name"])[0].refresh(True)
1629             except:
1630                 pass
1631
1632         except:
1633             raise
1634
1635     def get_hypervisor_type_bydomain(self,name=None):
1636         """<comment-ja>
1637         指定ドメインのハイパーバイザーの種類を取得する。
1638         @param void
1639         @return: hypervisor type
1640                  xen or kvm is available now (but depend on domain.xml)
1641                  e.g. xen kvm hyperv kqemu ldom lxc one openvz phyp qemu test
1642                       uml vbox vmware vserver
1643         @rtype: string (lower case only)
1644         </comment-ja>
1645         <comment-en>
1646         TODO:
1647         </comment-en>
1648         """
1649         retval = None
1650
1651         if not (name is None):
1652             self.guest.set_domain_name(name)
1653
1654         try:
1655             retval = self.guest.get_info()['VMType']
1656         except libvirt.libvirtError, e:
1657             pass
1658
1659         return retval
1660
1661     """
1662     Network
1663     """
1664     def list_inactive_network(self):
1665         """
1666         <comment-ja>
1667         現在起動していない仮想ネットワークのリストを取得します。
1668         </comment-ja>
1669         <comment-en>
1670         TODO:
1671         </comment-en>
1672         """
1673         return self._conn.listDefinedNetworks()
1674
1675     def list_active_network(self):
1676         """
1677         <comment-ja>
1678         現在起動している仮想ネットワークのリストを取得します。
1679         </comment-ja>
1680         <comment-en>
1681         TODO:
1682         </comment-en>
1683         """
1684         names = []
1685         for name in self._conn.listNetworks():
1686             names.append(name)
1687         return names
1688
1689     def search_networks(self, name=None):
1690         """
1691         <comment-ja>
1692         仮想ネットワークの検索を行います。
1693         </comment-ja>
1694         <comment-en>
1695         TODO:
1696         </comment-en>
1697         """
1698         networks = []
1699
1700         names = self._conn.listNetworks()
1701         for __name in names:
1702             networks.append(self._conn.networkLookupByName(__name))
1703         names = self.list_inactive_network()
1704         for __name in names:
1705             networks.append(self._conn.networkLookupByName(__name))
1706
1707         if name == None:
1708             return networks
1709
1710         regex_regex = re.compile(r"""^regex:(?P<regex>.*)""")
1711         m = regex_regex.match(name)
1712
1713         n_networks = []
1714         for network in networks:
1715             network_name = network.name()
1716             if m == None:
1717                 if network_name == name:
1718                     return [network]
1719             else:
1720                 regex = m.group('regex')
1721                 query_regex = re.compile(r""+regex+"")
1722                 n = query_regex.search(network_name)
1723                 if n != None:
1724                     n_networks.append(network)
1725         if len(n_networks):
1726             return n_networks
1727
1728         #return []
1729         raise KaresansuiVirtException("network %s not found" % name)
1730
1731     def search_kvn_networks(self, name=None):
1732         """<comment-ja>
1733         指定された仮想ネットワークオブジェクトをKaresansuiVirtNetworkオブジェクトのlistにして返却する。
1734         </comment-ja>
1735         <comment-en>
1736         TODO: English Comment
1737         </comment-en>
1738         """
1739
1740         if is_uuid(name):
1741             name = self.uuid_to_domname(name)
1742
1743         networks = []
1744         for network in self.search_networks(name):
1745             networks.append(
1746                 KaresansuiVirtNetwork(conn=self, name=network.name()))
1747
1748         return networks
1749
1750     def create_network(self, name, cidr, dhcp_start=None, dhcp_end=None, forward=None, bridge=None, autostart=None):
1751         """
1752         <comment-ja>
1753         仮想ネットワークを作成します。
1754         </comment-ja>
1755         <comment-en>
1756         TODO:
1757         </comment-en>
1758         """
1759         param = NetworkConfigParam(name)
1760         param.set_default_networks(cidr,dhcp_start,dhcp_end)
1761         param.set_ipaddr_and_netmask(cidr)
1762         if forward:
1763             if 'dev' in forward.keys():
1764                 param.set_forward_dev(forward['dev'])
1765             if 'mode' in forward.keys():
1766                 param.set_forward_mode(forward['mode'])
1767         if bridge:
1768             param.set_bridge(bridge)
1769         uuid = StrFromUUID(GenUUID())
1770         param.set_uuid(uuid)
1771
1772         generator = NetworkXMLConfigGenerator()
1773         try:
1774             cfgxml = generator.generate(param)
1775         except:
1776             raise
1777         generator.writecfg(cfgxml)
1778
1779         ret = libvirtmod.virNetworkCreateXML(self._conn._o,cfgxml)
1780         time.sleep(2)
1781         self._conn.networkDefineXML(cfgxml)
1782
1783         if autostart is not None:
1784             self.network.set_network_name(name)
1785             self.network.autostart(autostart)
1786
1787         return ret
1788
1789     def update_network(self, name, cidr=None, dhcp_start=None, dhcp_end=None, forward=None, bridge=None, autostart=None):
1790         """
1791         <comment-ja>
1792         仮想ネットワークを更新します。
1793         </comment-ja>
1794         <comment-en>
1795         TODO:
1796         </comment-en>
1797         """
1798         # パラメータをリセットする場合と引数が無い場合の区別 => リセットの場合は、空文字列を渡す。
1799
1800         if not ( cidr or
1801                  dhcp_start or
1802                  dhcp_end or
1803                  forward or
1804                  bridge ):
1805             # Not changed, do nothing
1806             # 更新成功時と同じ返り値(0)を返す
1807             return 0
1808
1809         try:
1810             param  = self.search_kvn_networks(name)[0].get_network_config_param()
1811         except:
1812             raise KaresansuiVirtException("Can't get parameters of network '%s'." % name)
1813
1814         if cidr:
1815             param.set_ipaddr_and_netmask(cidr)
1816         if dhcp_start:
1817             param.set_dhcp_start(dhcp_start)
1818         if dhcp_end:
1819             param.set_dhcp_end(dhcp_end)
1820         if forward:
1821             if 'dev' in forward.keys():
1822                 if forward['dev'] == '':
1823                     param.set_forward_dev(None)
1824                 else:
1825                     param.set_forward_dev(forward['dev'])
1826             if 'mode' in forward.keys():
1827                 if forward['mode'] == '':
1828                     param.set_forward_mode(None)
1829                 else:
1830                     param.set_forward_mode(forward['mode'])
1831         if bridge:
1832             param.set_bridge(bridge)
1833
1834         generator = NetworkXMLConfigGenerator()
1835         try:
1836             cfgxml = generator.generate(param)
1837         except:
1838             raise
1839
1840         self.stop_network(name)
1841
1842         generator.writecfg(cfgxml)
1843
1844         ret = libvirtmod.virNetworkCreateXML(self._conn._o,cfgxml)
1845         time.sleep(2)
1846         self._conn.networkDefineXML(cfgxml)
1847
1848         if autostart is not None:
1849             self.network.autostart(autostart)
1850
1851         return ret
1852
1853     def start_network(self,name=None):
1854         """
1855         <comment-ja>
1856         仮想ネットワークを起動します。
1857         </comment-ja>
1858         <comment-en>
1859         TODO:
1860         </comment-en>
1861         """
1862         if not (name is None):
1863             self.network.set_network_name(name)
1864         self.network.start()
1865
1866     def stop_network(self,name=None):
1867         """
1868         <comment-ja>
1869         仮想ネットワークを停止します。
1870         </comment-ja>
1871         <comment-en>
1872         TODO:
1873         </comment-en>
1874         """
1875         if not (name is None):
1876             self.network.set_network_name(name)
1877         self.network.stop()
1878
1879     def delete_network(self,name=None):
1880         """
1881         <comment-ja>
1882         仮想ネットワークを削除します。
1883         </comment-ja>
1884         <comment-en>
1885         TODO:
1886         </comment-en>
1887         """
1888         self.stop_network(name)
1889         if len(self.search_networks(name)) > 0:
1890             self.network.undefine()
1891
1892         config = "%s/%s.xml" %(VIRT_NETWORK_CONFIG_DIR, self.network.get_network_name())
1893         if os.path.exists(config):
1894             os.unlink(config)
1895
1896         config = "%s/autostart/%s.xml" %(VIRT_NETWORK_CONFIG_DIR, self.network.get_network_name())
1897         if os.path.exists(config):
1898             os.unlink(config)
1899
1900     def autostart_network(self,flag=None,name=None):
1901         """
1902         <comment-ja>
1903         仮想ネットワークの自動起動を設定します。
1904         </comment-ja>
1905         <comment-en>
1906         TODO:
1907         </comment-en>
1908         """
1909         if not (name is None):
1910             self.guest.set_domain_name(name)
1911         networks = self.search_networks(self.network.get_network_name())
1912         if len(networks):
1913             return self.network.autostart(flag)
1914         else:
1915             return False
1916
1917
1918     """
1919     Storage Pool
1920     """
1921     def refresh_pools(self):
1922         """
1923         <comment-ja>
1924         現在のストレージプール情報をリフレッシュします。
1925         </comment-ja>
1926         <comment-en>
1927         TODO:
1928         </comment-en>
1929         """
1930         # refresh pool.
1931         active_pools =  self.list_active_storage_pool()
1932         #inactive_pools =  self.list_inactive_storage_pool()
1933         inactive_pools = []
1934         for pool_name in active_pools + inactive_pools:
1935             try:
1936                 pool =  self.search_kvn_storage_pools(pool_name)
1937                 path = pool[0].get_info()["target"]["path"]
1938                 self.search_storage_pools(pool_name)[0].refresh(True)
1939             except:
1940                 pass
1941     
1942     def list_inactive_storage_pool(self):
1943         """
1944         <comment-ja>
1945         現在起動していないストレージプールのリストを取得します。
1946         </comment-ja>
1947         <comment-en>
1948         TODO:
1949         </comment-en>
1950         """
1951         pools = self._conn.listDefinedStoragePools()
1952         ret = []
1953         for i in xrange(len(pools)):
1954             path = "%s/%s.xml" % (VIRT_STORAGE_CONFIG_DIR, pools[i])
1955             if os.path.isfile(path) is False:
1956                 continue
1957             ret.append(pools[i])
1958         return ret
1959
1960     def list_active_storage_pool(self):
1961         """
1962         <comment-ja>
1963         現在起動しているストレージプールのリストを取得します。
1964         </comment-ja>
1965         <comment-en>
1966         TODO:
1967         </comment-en>
1968         """
1969         names = []
1970         for name in self._conn.listStoragePools():
1971             names.append(name)
1972         return names
1973
1974     def search_storage_pools(self, name=None, active_only=False):
1975         """
1976         <comment-ja>
1977         ストレージプールの検索を行います。
1978         </comment-ja>
1979         <comment-en>
1980         TODO:
1981         </comment-en>
1982         """
1983         pools = []
1984
1985         names = self._conn.listStoragePools()
1986         for __name in names:
1987             pools.append(self._conn.storagePoolLookupByName(__name))
1988
1989         if active_only is False:
1990             names = self.list_inactive_storage_pool()
1991             for __name in names:
1992                 pools.append(self._conn.storagePoolLookupByName(__name))
1993
1994         if name == None:
1995             return pools
1996
1997         regex_regex = re.compile(r"""^regex:(?P<regex>.*)""")
1998         m = regex_regex.match(name)
1999
2000         n_pools = []
2001         for pool in pools:
2002             pool_name = pool.name()
2003             if m == None:
2004                 if pool_name == name:
2005                     return [pool]
2006             else:
2007                 regex = m.group('regex')
2008                 query_regex = re.compile(r""+regex+"")
2009                 n = query_regex.search(storage_name)
2010                 if n != None:
2011                     n_pools.append(pool)
2012         if len(n_pools):
2013             return n_pools
2014
2015         #return []
2016         raise KaresansuiVirtException("Storage pool %s not found" % name)
2017
2018     def search_kvn_storage_pools(self, name=None, active_only=False):
2019         """<comment-ja>
2020         指定されたStorage Pool をKaresansuiVirtStoragePoolオブジェクトのlistにして返却する。
2021         </comment-ja>
2022         <comment-en>
2023         TODO: English Comment
2024         </comment-en>
2025         """
2026
2027         if is_uuid(name):
2028             name = self.uuid_to_domname(name)
2029
2030         pools = []
2031         for pool in self.search_storage_pools(name, active_only):
2032             pools.append(
2033                 KaresansuiVirtStoragePool(conn=self, name=pool.name()))
2034
2035         return pools
2036
2037     def start_storage_pool(self, name):
2038         """
2039         <comment-ja>
2040         ストレージプールの起動します。
2041         </comment-ja>
2042         <comment-en>
2043         TODO:
2044         </comment-en>
2045         """
2046         return self.storage_pool.create(name)
2047         
2048     def create_storage_pool(self, name, type,
2049                             target_path=None,
2050                             allocation=0, available=0, capacity=0,
2051                             source_f_type=None, source_dev_path=None, source_a_name=None,
2052                             source_dir_path=None, source_h_name=None,
2053                             target_p_group=None, target_p_label=None,
2054                             target_p_mode=None, target_p_owner=None,
2055                             target_e_format=None, target_encryption_s_type=None,
2056                             #target_encryption_s_uuid=None,
2057                             ):
2058         """
2059         <comment-ja>
2060         ストレージプールの作成を行います。
2061         </comment-ja>
2062         <comment-en>
2063         TODO:
2064         </comment-en>
2065         """
2066
2067         param = StoragePoolConfigParam(name)
2068         
2069         uuid = StrFromUUID(GenUUID())
2070         param.set_uuid(uuid)
2071
2072         if type is not None:
2073             param.set_pool_type(type)
2074
2075         if target_path is not None:
2076             param.set_target_path(target_path)
2077
2078         param.set_allocation(allocation)
2079         param.set_available(available)
2080         param.set_capacity(capacity)
2081         
2082         if source_f_type is not None:
2083             param.set_source_f_type(source_f_type)
2084
2085         if source_dev_path is not None:
2086             param.set_source_dev_path(source_dev_path)
2087
2088         if source_dir_path is not None:
2089             param.set_source_dir_path(source_dir_path)
2090
2091         if source_f_type is not None:
2092             param.set_source_f_type(source_f_type)
2093
2094         if source_h_name is not None:
2095             param.set_source_h_name(source_h_name)
2096
2097         if target_e_format is not None and \
2098                target_encryption_s_type is not None:
2099             param.set_target_e_format(target_e_format)
2100             param.set_target_encryption_s_type(target_encryption_s_type)
2101             target_encryption_s_uuid = StrFromUUID(GenUUID())
2102             param.set_target_encryption_s_uuid(target_encryption_s_uuid)
2103
2104         if target_p_group is not None:
2105             param.set_target_permissions_group(target_p_group)
2106
2107         if target_p_label is not None:
2108             param.set_target_permissions_label(target_p_label)
2109
2110         if target_p_mode is not None:
2111             param.set_target_permissions_mode(target_p_mode)
2112
2113         if target_p_owner is not None:
2114             param.set_target_permissions_owner(target_p_owner)
2115
2116         generator = StoragePoolXMLConfigGenerator()
2117         try:
2118             cfgxml = generator.generate(param)
2119         except:
2120             raise
2121         generator.writecfg(cfgxml)
2122
2123         if self.storage_pool.start(cfgxml, 0, name) == 0:
2124             return True
2125         else:
2126             return False
2127
2128     def is_autostart_storage_pool(self, name=None):
2129         """
2130         <comment-ja>
2131         指定されたストレージプールが自動起動するか。
2132         </comment-ja>
2133         <comment-en>
2134         TODO:
2135         </comment-en>
2136         """
2137         if not (name is None):
2138             self.storage_pool.set_storage_name(name)
2139
2140         pools = self.search_storage_pools(self.storage_pool.get_storage_name())
2141         if len(pools):
2142             ret = self.storage_pool.autostart()
2143             if ret == 0:
2144                 return False # OFF
2145             elif ret == 1:
2146                 return True # ON
2147             else:
2148                 return None # ERR
2149         else:
2150             return None # ERR
2151         
2152     def autostart_storage_pool(self, flag=None, name=None):
2153         """
2154         <comment-ja>
2155         ストレージプールの自動起動設定を行います。
2156         </comment-ja>
2157         <comment-en>
2158         TODO:
2159         </comment-en>
2160         """
2161         if not (name is None):
2162             self.storage_pool.set_storage_name(name)
2163
2164         pools = self.search_storage_pools(self.storage_pool.get_storage_name())
2165         if len(pools):
2166             if self.storage_pool.set_autostart(flag) == 0:
2167                 return True
2168             else:
2169                 return False
2170         else:
2171             return False
2172
2173     def destroy_storage_pool(self,name=None):
2174         """
2175         <comment-ja>
2176         ストレージプールの削除を行います。(設定ファイルなどの情報は削除されません)
2177         </comment-ja>
2178         <comment-en>
2179         TODO:
2180         </comment-en>
2181         """
2182         if name is not None:
2183             self.storage_pool.set_storage_name(name)
2184         if self.storage_pool.destroy() == 0:
2185             return True
2186         else:
2187             return False
2188
2189     def delete_storage_pool(self,name=None, flags=False):
2190         """
2191         <comment-ja>
2192         ストレージプールを完全に削除します。
2193         </comment-ja>
2194         <comment-en>
2195         TODO:
2196         </comment-en>
2197         """
2198         if name is not None:
2199             self.storage_pool.set_storage_name(name)
2200
2201         # autostart off
2202         self.autostart_storage_pool(False)
2203
2204         path = "%s/%s.xml" % (VIRT_STORAGE_CONFIG_DIR, self.storage_pool.get_storage_name())
2205         if os.path.isfile(path) is True:
2206             os.unlink(path)
2207
2208         mode = VIR_STORAGE_POOL_DELETE_NORMAL
2209         if flags is True:
2210             mode = VIR_STORAGE_POOL_DELETE_ZEROED
2211             
2212         if self.storage_pool.delete(mode) == 0:
2213             return True
2214         else:
2215             return False
2216
2217     def is_storage_volume(self, path):
2218         """<comment-ja>
2219         指定したパスがストレージボリュームに含まれているか。
2220         </comment-ja>
2221         <comment-en>
2222         Storage volume that contains the specified path.
2223         </comment-en>
2224         """
2225         if os.path.isfile(path) is False:
2226             return False
2227
2228         try:
2229             vir_storage_vol = self.storage_volume._conn.storageVolLookupByPath(path)
2230             return True
2231         except libvirt.libvirtError, e:
2232             # _("The specified path is not registered in the storage volume. '%s' (%s)")
2233             return False
2234
2235     def get_storage_volume(self, pool_name, vol_name):
2236         """
2237         <comment-ja>
2238         ストレージボリュームを取得します。
2239         </comment-ja>
2240         <comment-en>
2241         TODO:
2242         </comment-en>
2243         """
2244         try:
2245             pools = self.search_storage_pools(pool_name)
2246             if len(pools) <= 0:
2247                 return None
2248             vol = pools[0].storageVolLookupByName(vol_name)
2249             return vol
2250         except libvirt.libvirtError, e:
2251             return None
2252
2253     def get_storage_volume_path(self, pool_name, vol_name):
2254         """
2255         <comment-ja>
2256         ストレージボリュームのパスを取得します。
2257         </comment-ja>
2258         <comment-en>
2259         TODO:
2260         </comment-en>
2261         """
2262         try:
2263             vol = self.get_storage_volume(pool_name, vol_name)
2264             if vol is None:
2265                 return None
2266             vol_path = vol.path()
2267             return vol_path
2268         except libvirt.libvirtError, e:
2269             return None
2270
2271     def get_storage_pool_UUIDString2kvn_storage_pool(self, uuidstr):
2272         """
2273         <comment-ja>
2274         ストレージプールのUUIDをもとに、ストレージプール情報を取得します。
2275         </comment-ja>
2276         <comment-en>
2277         TODO:
2278         </comment-en>
2279         """
2280         pool_obj = self._conn.storagePoolLookupByUUIDString(uuidstr)
2281         return self.search_kvn_storage_pools(pool_obj.name())
2282         
2283     def create_storage_volume(self,
2284                               name,
2285                               pool_name,
2286                               t_f_type,
2287                               use,
2288                               volume_name=None,
2289                               #t_path=None,
2290                               key=None, allocation=0, capacity=0, c_unit=None,
2291                               source=None,
2292                               t_p_owner=None,t_p_group=None,t_p_mode=None, t_p_label=None,
2293                               b_path=None,
2294                               b_format=None,
2295                               b_p_owner=None, b_p_group=None, b_p_mode=None, b_p_label=None):
2296         """
2297         <comment-ja>
2298         ストレージプールを作成します。
2299         </comment-ja>
2300         <comment-en>
2301         TODO:
2302         </comment-en>
2303         """
2304         param = StorageVolumeConfigParam(name)
2305
2306         if volume_name is None:
2307             uuid = StrFromUUID(GenUUID())
2308         else:
2309             uuid = volume_name
2310         param.set_uuid(uuid)
2311         param.set_storage_name(uuid)
2312
2313         self.storage_pool.set_storage_name(pool_name)
2314         self.storage_volume.set_storage_volume_name(uuid)
2315
2316         #if t_path is not None:
2317         #   param.set_target_path(t_path)
2318
2319         param.set_target_f_type(t_f_type)
2320
2321         if key is not None:
2322             set_key(key)
2323
2324         param.set_allocation(allocation)
2325         param.set_capacity(capacity)
2326
2327         if c_unit is not None and (capacity != 0 or allocation != 0):
2328             param.set_c_unit(c_unit)
2329
2330         if source is not None:
2331             param.set_source(source)
2332                 
2333         if t_p_owner is not None:
2334             param.set_target_permissions_owner(t_p_owner)
2335
2336         if t_p_group is not None:
2337             param.set_target_permissions_group(t_p_group)
2338
2339         if t_p_mode is not None:
2340             param.set_target_permissions_mode(t_p_mode)
2341
2342         if t_p_label is not None:
2343             param.set_target_permissions_label(t_p_label)
2344
2345         if b_path is not None:
2346             param.set_backingStore_path(b_path)
2347             if b_format is not None:
2348                 param.set_backingStore_format(b_format)
2349
2350             if b_p_owner is not None:
2351                 param.set_backingStore_permissions_owner(b_p_owner)
2352
2353             if b_p_group is not None:
2354                 param.set_backingStore_permissions_group(b_p_group)
2355
2356             if b_p_mode is not None:
2357                 param.set_backingStore_permissions_mode(b_p_mode)
2358
2359             if b_p_label is not None:
2360                 param.set_backingStore_permissions_label(b_p_label)
2361
2362         generator = StorageVolumeXMLConfigGenerator()
2363         try:
2364             cfgxml = generator.generate(param)
2365         except:
2366             raise
2367
2368         # comment out
2369         #generator.writecfg(cfgxml)
2370
2371         vir_storage_vol = self.storage_pool.vol_createXML(cfgxml, 0)
2372
2373         if not isinstance(vir_storage_vol, libvirt.virStorageVol):
2374             return False
2375         # storage dir
2376         pool_objs = self.search_kvn_storage_pools(pool_name)
2377         if not pool_objs:
2378             raise KaresansuiVirtException(_("Storage pool could not be found. pool=%s") % \
2379                                           pool_name)
2380
2381         # TODO iscsi block device
2382         domains_dir = pool_objs[0].get_info()["target"]["path"]
2383         domain_dir = self.make_domain_dir(domains_dir, name)
2384
2385         import shutil
2386         if use == DISK_USES["IMAGES"]:
2387             disk = "%s/%s/%s.img" % (domain_dir, DISK_USES["IMAGES"], name)
2388             shutil.move("%s/%s" % (domains_dir, param.get_storage_name()),
2389                         disk)
2390
2391             os.symlink(disk,
2392                        "%s/%s" % (domains_dir, param.get_storage_name()))
2393         else:
2394             disk = "%s/%s/%s.img" % (domain_dir, DISK_USES["DISK"], uuid)
2395             shutil.move("%s/%s" % (domains_dir, uuid),
2396                         disk)
2397
2398             os.symlink(disk,
2399                        "%s/%s" % (domains_dir, uuid))
2400
2401         # Storage Pool refresh
2402         try:
2403             self.search_storage_pools(pool_name)[0].refresh(True)
2404         except:
2405             pass
2406
2407         return True
2408
2409     def delete_storage_volume(self,pool_name, vol_name, use, flags=False):
2410         """
2411         <comment-ja>
2412         ストレージボリュームを完全に削除します。
2413         </comment-ja>
2414         <comment-en>
2415         TODO:
2416         </comment-en>
2417         """
2418         self.storage_volume.set_storage_name(pool_name)
2419         self.storage_volume.set_storage_volume_name(vol_name)
2420
2421         # delete storage dir
2422         pool_objs = self.search_kvn_storage_pools(pool_name)
2423         if not pool_objs:
2424             raise KaresansuiVirtException(_("Storage pool could not be found. pool=%s") % \
2425                                               pool_name)
2426
2427         domains_dir = pool_objs[0].get_info()["target"]["path"]
2428         target_path = "%s/%s" % (domains_dir, vol_name)
2429         taget_real_path = os.path.realpath(target_path)
2430
2431         # delete process
2432         mode = VIR_STORAGE_VOL_DELETE_NORMAL
2433         if flags is True:
2434             mode = VIR_STORAGE_VOL_DELETE_ZEROED
2435
2436         if self.storage_volume.delete(mode) != 0:
2437             return False
2438
2439         # physical process
2440         if use == DISK_USES["IMAGES"]:
2441             os.remove(taget_real_path)
2442             if os.path.exists(target_path) is True:
2443                 os.remove(target_path)
2444         elif use == DISK_USES["DISK"]:
2445             os.remove(taget_real_path)
2446             if os.path.exists(target_path) is True:
2447                 os.remove(target_path)
2448         else:
2449             pass
2450
2451     def get_storage_pool_type(self, pool_name):
2452         """<comment-ja>
2453         ストレージプールのタイプを取得する
2454         @param pool_name: ストレージプール名
2455         @return: ストレージプールの種別
2456         @rtype: string
2457         </comment-ja>
2458         <comment-en>
2459         Get the type of storage pool.
2460         @param pool_name: name of storage pool
2461         @return: type of storage pool
2462         @rtype: string
2463         </comment-en>
2464         """
2465         retval = None
2466
2467         try:
2468             pool_objs = self.search_kvn_storage_pools(pool_name)
2469             if not pool_objs:
2470                 raise KaresansuiVirtException(_("Storage pool could not be found. pool=%s") % \
2471                                           pool_name)
2472             retval = pool_objs[0].get_info()['type']
2473         except:
2474             pass
2475
2476         return retval
2477
2478     def get_storage_pool_targetpath(self, pool_name):
2479         """<comment-ja>
2480         ストレージプールのターゲットパスを取得します。(dir)
2481         @param pool_name: ストレージプール名
2482         @return: ターゲットパス
2483         @rtype: string
2484         </comment-ja>
2485         <comment-en>
2486         Get the target path of storage pool.
2487         @param pool_name: name of storage pool
2488         @return: target path
2489         @rtype: string
2490         </comment-en>
2491         """
2492         retval = None
2493
2494         try:
2495             pool_objs = self.search_kvn_storage_pools(pool_name)
2496             if not pool_objs:
2497                 raise KaresansuiVirtException(_("Storage pool could not be found. pool=%s") % \
2498                                           pool_name)
2499             retval = pool_objs[0].get_info()['target']['path']
2500         except:
2501             pass
2502
2503         return retval
2504
2505     def get_storage_pool_sourcedevicepath(self, pool_name):
2506         """<comment-ja>
2507         ストレージプールのソースデバイスパスを取得します。(iscsi)
2508         @param pool_name: ストレージプール名
2509         @return: ソースデバイスパス
2510         @rtype: string
2511         </comment-ja>
2512         <comment-en>
2513         Get the source device path of storage pool.
2514         @param pool_name: name of storage pool
2515         @return: source device path
2516         @rtype: string
2517         </comment-en>
2518         """
2519         retval = None
2520
2521         try:
2522             pool_objs = self.search_kvn_storage_pools(pool_name)
2523             if not pool_objs:
2524                 raise KaresansuiVirtException(_("Storage pool could not be found. pool=%s") % \
2525                                           pool_name)
2526             retval = pool_objs[0].get_info()['source']['dev_path']
2527         except:
2528             pass
2529
2530         return retval
2531
2532     def get_storage_pool_name_byimage(self, path):
2533         """<comment-ja>
2534         ディスクイメージのパスからストレージプールの名前を取得する
2535         @param path: ディスクイメージのパス
2536         @return: ストレージプールの名前
2537         @rtype: list
2538         </comment-ja>
2539         <comment-en>
2540         Get name of storage pool where the specified disk image belongs to.
2541         @param path: path of disk image
2542         @return: list of storage pool name
2543         @rtype: list
2544         </comment-en>
2545         """
2546         retval = []
2547
2548         paths = [path]
2549         realpath = os.path.realpath(path)
2550
2551         # Includes realpath as detecting target if it is symbolic link.
2552         if realpath != path:
2553             paths.append(realpath)
2554
2555         try:
2556             pool_objs = self.search_kvn_storage_pools()
2557             if not pool_objs:
2558                 raise KaresansuiVirtException(_("No storage pools could be found."))
2559
2560             for pool_obj in pool_objs:
2561                 pool_info = pool_obj.get_info()
2562                 name        = pool_info['name']
2563
2564                 for vol_name,vol_path in self.get_storage_volume_bypool(name, attr="path").iteritems():
2565                     for _path in paths:
2566                         if ( vol_path == _path or os.path.realpath(vol_path) == _path ) and not name in retval:
2567                             retval.append(name)
2568
2569         except:
2570             pass
2571
2572         return retval
2573
2574     def get_storage_pool_name_bydomain(self, domain, image_type=None):
2575         """<comment-ja>
2576         ドメインの名前からストレージプールの名前を取得する
2577         * iscsi is returning the [].
2578         @param domain: ドメイン名
2579         @param image_type: イメージの種別 
2580                      "os"                :ゲストOS本体のイメージファイル
2581                      "disk"              :拡張ディスクのイメージファイル
2582                      未指定またはそれ以外:ドメインに属する全てのイメージファイル
2583         @return: ストレージプールの名前
2584         @rtype: list
2585         </comment-ja>
2586         <comment-en>
2587         Get name of storage pool where image files that the specified domain uses belong to.
2588
2589         @param domain: domain name
2590         @return: list of storage pool name
2591         @rtype: list
2592         </comment-en>
2593         """
2594         retval = []
2595
2596         regex = []
2597         if image_type == "os":
2598             regex.append("%s/images/%s\.img$" % (domain,domain,))
2599         if image_type == "disk":
2600             regex.append("%s/disk/[0-9\.]+\.img$" % (domain,))
2601         regex_str = "|".join(regex)
2602
2603         try:
2604             guest_obj = self.search_kvg_guests(domain)[0]
2605             if not guest_obj:
2606                 raise KaresansuiVirtException(_("Domain could not be found. name=%s") % \
2607                                           domain)
2608
2609             os_root = guest_obj.get_info()['os_root']
2610
2611             for info in guest_obj.get_disk_info():
2612                 try:
2613                     target = info['target']['dev']
2614                 except:
2615                     target = None
2616
2617                 try:
2618                     source = info['source']['file']
2619                 except:
2620                     try:
2621                         source = info['source']['dev']
2622                     except:
2623                         source = None
2624
2625                 pools = []
2626                 if image_type == "os":
2627                    if os_root is not None and target == os.path.basename(os_root):
2628                        pools = self.get_storage_pool_name_byimage(source)
2629                 elif image_type == "disk":
2630                    if os_root is not None and target != os.path.basename(os_root):
2631                        pools = self.get_storage_pool_name_byimage(source)
2632                 else:
2633                     pools = self.get_storage_pool_name_byimage(source)
2634
2635                 if len(pools) > 0:
2636                     for pool_name in pools:
2637                         if not pool_name in retval:
2638                             retval.append(pool_name)
2639
2640             # in case that os_root is not specified.
2641             if len(retval) == 0:
2642                 for info in guest_obj.get_disk_info():
2643                     if re.search(regex_str,info['source']['file']):
2644                         for pool_name in self.get_storage_pool_name_byimage(info['source']['file']):
2645                             if not pool_name in retval:
2646                                 retval.append(pool_name)
2647
2648         except:
2649             pass
2650
2651         return retval
2652
2653
2654     def get_storage_volume_bypool(self, pool, attr="name"):
2655         """<comment-ja>
2656         ストレージプールの名前からボリュームの一覧を取得する
2657         @param pool: プール名
2658         @param attr: 取得する属性
2659                      "name"  :ボリュームの名前(UUID形式)
2660                      "key"   :ボリュームのキー
2661                      "path"  :ボリュームのパス
2662                      "info"  :ボリュームの情報
2663                      未指定  :nameが指定されたものとする
2664
2665                      attr 'info' depends on virStorageVolInfo structure.
2666                        int type;                      virStorageVolType flags
2667                                                       0 :Regular file
2668                                                       1 :Block
2669                        unsigned long long capacity;   Logical size bytes
2670                        unsigned long long allocation; Current allocation bytes
2671         @return: ストレージボリューム名と対応するデータの辞書配列
2672         @rtype: dict
2673         </comment-ja>
2674         <comment-en>
2675         Get name of storage volume in the specified pool.
2676         
2677         @param pool: name of pool
2678         @param attr: volume attribute that you want to get
2679                      "name"  :name of volume (UUID style)
2680                      "key"   :key of volume
2681                      "path"  :path of volume
2682                      "info"  :volume information
2683                      none    :same as 'name' is specified
2684
2685         @return: dict of storage volume
2686         @rtype: dict
2687         </comment-en>
2688         """
2689         retval = {}
2690
2691         try:
2692             pool_obj = self.search_kvn_storage_pools(pool)[0]
2693             if not pool_obj:
2694                 raise KaresansuiVirtException(_("No storage pool '%s' could be found.") % pool)
2695
2696             vols = pool_obj.vol_listVolumes()
2697             for vol in vols:
2698                 vol_obj = pool_obj.vol_storageVolLookupByName(vol)
2699                 try:
2700                     exec("value = vol_obj.%s()" % attr)
2701                     retval[vol] = value
2702                 except:
2703                     pass
2704         except:
2705             pass
2706
2707         return retval
2708
2709     def get_storage_volume_iscsi_rpath_bystorage(self, pool, volume):
2710         """<comment-ja>
2711         ストレージプール名とストレージボリューム名から、ストレージのREAL PATHを取得します。
2712         </comment-ja>
2713         <comment-en>
2714         TODO: To include comments in English
2715         </comment-en>
2716         """
2717         ret = None
2718         try:
2719             pool_obj = self.search_kvn_storage_pools(pool)[0]
2720             if not pool_obj:
2721                 raise KaresansuiVirtException(_("No storage pool '%s' could be found.") % pool)
2722
2723             vol_obj = pool_obj.vol_storageVolLookupByName(volume)
2724             ret = vol_obj.key()
2725         except:
2726             pass
2727
2728         return ret
2729
2730     def get_storage_volume_bydomain(self, domain, image_type=None, attr="name"):
2731         """<comment-ja>
2732         ドメインの名前からボリュームの一覧を取得する
2733         @param domain: ドメイン名
2734         @param image_type: イメージの種別
2735                      "os"    :ゲストOS本体のイメージファイル
2736                      "disk"  :拡張ディスクのイメージファイル
2737                      未指定  :ドメインに属する全てのイメージファイル
2738         @param attr: 取得する属性
2739                      "name"  :ボリュームの名前(UUID形式)
2740                      "key"   :ボリュームのキー
2741                      "path"  :ボリュームのパス
2742                      "info"  :ボリュームの情報
2743                      未指定  :nameが指定されたものとする
2744
2745                      attr 'info' depends on virStorageVolInfo structure.
2746                        int type;                      virStorageVolType flags
2747                                                       0 :Regular file
2748                                                       1 :Block
2749                        unsigned long long capacity;   Logical size bytes
2750                        unsigned long long allocation; Current allocation bytes
2751         @return: ストレージボリューム名と対応するデータの辞書配列
2752         @rtype: dict
2753         </comment-ja>
2754         <comment-en>
2755         Get name of storage volume in the specified domain.
2756
2757         @param domain: domain name
2758         @param image_type: type of image file
2759                      "os"    :os image only
2760                      "disk"  :extended disk image only
2761                      none    :all images that domain uses
2762         @param attr: volume attribute that you want to get
2763                      "name"  :name of volume (UUID style)
2764                      "key"   :key of volume
2765                      "path"  :path of volume
2766                      "info"  :volume information
2767                      none    :same as 'name' is specified
2768
2769         @return: dict of storage volume
2770         @rtype: dict
2771         </comment-en>
2772         """
2773         retval = {}
2774
2775         regex = []
2776         if image_type == "os":
2777             regex.append("%s/images/%s\.img$" % (domain,domain,))
2778         if image_type == "disk":
2779             regex.append("%s/disk/[0-9\.]+\.img$" % (domain,))
2780         regex_str = "|".join(regex)
2781
2782         try:
2783             guest_obj = self.search_kvg_guests(domain)[0]
2784             if not guest_obj:
2785                 raise KaresansuiVirtException(_("Domain could not be found. name=%s") % \
2786                                           domain)
2787
2788             os_root = guest_obj.get_info()['os_root']
2789
2790             for info in guest_obj.get_disk_info():
2791                 try:
2792                     target = info['target']['dev']
2793                 except:
2794                     target = None
2795
2796                 try:
2797                     source = info['source']['file']
2798                 except:
2799                     try:
2800                         source = info['source']['dev']
2801                     except:
2802                         source = None
2803
2804                 pools = []
2805                 if image_type == "os":
2806                    if os_root is not None and target == os.path.basename(os_root):
2807                        pools = self.get_storage_pool_name_byimage(source)
2808                 elif image_type == "disk":
2809                    if os_root is not None and target != os.path.basename(os_root):
2810                        pools = self.get_storage_pool_name_byimage(source)
2811                 else:
2812                     pools = self.get_storage_pool_name_byimage(source)
2813
2814                 if len(pools) > 0:
2815                     for _pool in pools:
2816                         vols = self.get_storage_volume_bypool(_pool, attr=attr)
2817                         for vol,value in vols.iteritems():
2818                             path = self.get_storage_volume_iscsi_rpath_bystorage(_pool,vol)
2819                             if path[0:5] != "/dev/":
2820                                 path = os.path.realpath(path)
2821                             if source == path and not vol in retval.keys():
2822                                 retval[vol] = value
2823
2824         except:
2825             pass
2826
2827         return retval
2828
2829
2830     def get_storage_volume_symlink(self, path):
2831         """<comment-ja>
2832         ディスクイメージのパスからストレージボリューム(symlink)の名前を取得します。
2833         </comment-ja>
2834         <comment-en>
2835         TODO: English Comment
2836         </comment-en>
2837         """
2838         ret = []
2839
2840         paths = [path]
2841         realpath = os.path.realpath(path)
2842
2843         # Includes realpath as detecting target if it is symbolic link.
2844         if realpath != path:
2845             paths.append(realpath)
2846
2847         try:
2848             pool_objs = self.search_kvn_storage_pools()
2849             if not pool_objs:
2850                 raise KaresansuiVirtException(_("No storage pools could be found."))
2851
2852             for pool_obj in pool_objs:
2853                 pool_info = pool_obj.get_info()
2854                 if pool_info['type'] != 'dir' or pool_info['is_active'] is False:
2855                     continue
2856
2857                 vols = pool_obj.vol_listVolumes()
2858                 for vol in vols:
2859                     vol_path = "%s/%s" % (pool_info['target']['path'], vol)
2860                     vol_real_path = os.path.realpath(vol_path)
2861                     if path == vol_real_path:
2862                         #ret.append(vol_real_path)
2863                         ret.append(vol)
2864         except:
2865             pass
2866         return ret
2867
2868     def get_storage_volume_iscsi_bysymlink(self, symlink):
2869         """<comment-ja>
2870         example形式のiscsiパスからlibvirtのストレージボリューム情報を取得します。
2871         
2872         @param symlink: example) 'ip-192.168.100.100:3260-iscsi-iqn.2010-01.info.karesansui-project:iscsi-123-lun-1'
2873         @return: {pool: プール名,volume: ボリューム名,rpath:iscsiのby-path}
2874         </comment-ja>
2875         <comment-en>
2876         TODO: To include comments in English
2877         </comment-en>
2878         """
2879         pools = self.search_kvn_storage_pools()
2880         rpath = "%s/%s" % (ISCSI_DEVICE_DIR, symlink)
2881         ret = None
2882         for pool in pools:
2883             name = pool.get_storage_name()
2884             if self.get_storage_pool_type(name) == 'iscsi':
2885                 volumes = self.get_storage_volume_bypool(name, 'key')
2886                 for vkey in volumes.keys():
2887                     if rpath == volumes[vkey]:
2888                         ret = {"pool" : name,
2889                                "volume" : vkey,
2890                                "rpath" : volumes[vkey],
2891                                }
2892                         break
2893         return ret
2894
2895
2896 class KaresansuiVirtGuest:
2897
2898     def __init__(self, conn, name=None):
2899         self.connection = conn
2900         self._conn = self.connection._conn
2901         self.set_domain_name(name)
2902
2903     def get_json(self):
2904         """<comment-ja>
2905         JSON形式でKaresansuiVirtGuest情報を返却する。
2906         </comment-ja>
2907         <comment-en>
2908         TODO: English Comment
2909         </comment-en>
2910         """
2911         
2912         ret = {}
2913         ret['name'] = self.get_domain_name()
2914         ret.update(self.get_info())
2915         return ret
2916
2917     def set_domain_name(self,name=None):
2918         if is_uuid(name):
2919             self.domain = conn.uuid_to_domname(name)
2920         else:
2921             self.domain = name
2922
2923     def get_domain_name(self):
2924         return self.domain
2925
2926     def get_info(self):
2927         dom = self._conn.lookupByName(self.get_domain_name())
2928         data = dom.info()
2929         try:
2930             os_type = dom.OSType()
2931         except:
2932             os_type = None
2933
2934         param = ConfigParam(dom.name())
2935         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, dom.name())
2936         if not os.path.exists(xml_file):
2937             ConfigFile(xml_file).write(dom.XMLDesc(0))
2938             if os.getuid() == 0 and os.path.exists(xml_file):
2939                 r_chgrp(xml_file,KARESANSUI_GROUP)
2940         param.load_xml_config(xml_file)
2941
2942         vm_type = param.domain_type
2943         os_root = param.os_root
2944         hypervisor = self.connection.get_hypervisor_type()
2945         try:
2946           hvVersion = libvirtmod.virConnectGetVersion(self._conn._o)
2947           hvVersion_major = hvVersion / 1000000
2948           hvVersion %= 1000000
2949           hvVersion_minor = hvVersion / 1000
2950           hvVersion_rel = hvVersion % 1000
2951           hv_version = "%s %d.%d.%d" %(hypervisor, hvVersion_major, hvVersion_minor, hvVersion_rel)
2952         except:
2953           hv_version = None
2954         return {
2955                 "state"     : data[0],
2956                 "maxMem"    : data[1],
2957                 "memory"    : data[2],
2958                 "nrVirtCpu" : data[3],
2959                 "cpuTime"   : data[4],
2960                 "OSType"    : os_type,
2961                 "VMType"    : vm_type,
2962                 "hypervisor": hypervisor,
2963                 "hv_version": hv_version,
2964                 "os_root"   : os_root,
2965         }
2966
2967     def get_netinfo(self):
2968         info = {}
2969         dom = self._conn.lookupByName(self.get_domain_name())
2970         dom_id = dom.ID()
2971         if self.get_info()["VMType"] == "kvm":
2972             eth_info = get_ifconfig_info("regex:^eth")
2973             for dev,value in eth_info.iteritems():
2974                 info[dev] = value
2975         else:
2976             vif_info = get_ifconfig_info("regex:^vif%d\.[0-9]" % dom_id)
2977             for dev,value in vif_info.iteritems():
2978                 dev = dev.replace("vif%d." % (dom_id,), "eth")
2979                 info[dev] = value
2980         return info
2981
2982     def get_disk_info(self):
2983         infos = []
2984         dom = self._conn.lookupByName(self.get_domain_name())
2985
2986         param = ConfigParam(dom.name())
2987         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, dom.name())
2988         if not os.path.exists(xml_file):
2989             ConfigFile(xml_file).write(dom.XMLDesc(0))
2990             if os.getuid() == 0 and os.path.exists(xml_file):
2991                 r_chgrp(xml_file,KARESANSUI_GROUP)
2992         param.load_xml_config(xml_file)
2993
2994         for info in param.disks:
2995             driver = {}
2996             source = {}
2997             target = {}
2998             type   = info['disk_type']
2999             device = info['device']
3000
3001             try:
3002                 driver['name'] = info["driver_name"]
3003             except:
3004                 driver['name'] = None
3005             try:
3006                 driver['type'] = info["driver_type"]
3007             except:
3008                 driver['type'] = None
3009
3010             if type == 'block':
3011                 source['dev'] = info['path']
3012                 source_path = source['dev']
3013             else:
3014                 source['file'] = info['path']
3015                 source_path = source['file']
3016
3017             target['dev'] = info['target']
3018             target['bus'] = info['bus']
3019
3020             if os.path.exists(source_path):
3021                 img_info = get_disk_img_info(source_path)
3022                 try:
3023                     img_size = img_info['virtual_size']
3024                 except:
3025                     img_size = img_info['real_size']
3026                 source['size'] = get_filesize_MB(img_size)
3027             else:
3028                 source['size'] = 0
3029             info = {
3030                    "type":type,
3031                    "device":device,
3032                    "driver":driver,
3033                    "source":source,
3034                    "target":target,
3035                    }
3036             infos.append(info)
3037         return infos
3038
3039     def get_vcpus_info(self):
3040         dom = self._conn.lookupByName(self.get_domain_name())
3041
3042         param = ConfigParam(dom.name())
3043         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, dom.name())
3044         if not os.path.exists(xml_file):
3045             ConfigFile(xml_file).write(dom.XMLDesc(1))
3046             if os.getuid() == 0 and os.path.exists(xml_file):
3047                 r_chgrp(xml_file,KARESANSUI_GROUP)
3048         param.load_xml_config(xml_file)
3049
3050         try:
3051             max_vcpus = int(param.max_vcpus)
3052         except:
3053             max_vcpus = None
3054         try:
3055             if self.status() != VIR_DOMAIN_SHUTOFF:
3056                 vcpus = self.get_info()['nrVirtCpu']
3057             else:
3058                 vcpus = None
3059         except:
3060             vcpus = None
3061         try:
3062             bootup_vcpus = int(param.vcpus)
3063         except:
3064             bootup_vcpus = None
3065
3066         return {
3067                 "max_vcpus"    :max_vcpus,
3068                 "vcpus"        :vcpus,
3069                 "bootup_vcpus" :bootup_vcpus,
3070                }
3071
3072     def get_interface_info(self):
3073         infos = []
3074         dom = self._conn.lookupByName(self.get_domain_name())
3075
3076         param = ConfigParam(dom.name())
3077         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, dom.name())
3078         if not os.path.exists(xml_file):
3079             ConfigFile(xml_file).write(dom.XMLDesc(0))
3080             if os.getuid() == 0 and os.path.exists(xml_file):
3081                 r_chgrp(xml_file,KARESANSUI_GROUP)
3082         #param.load_xml_config(xml_file)
3083         param.load_xml_config(dom.XMLDesc(0))
3084
3085         for info in param.interfaces:
3086             mac = {}
3087             source = {}
3088             script = {}
3089             target = {}
3090             type           = info['type']
3091             mac['address'] = info['mac']
3092             script['path'] = info['script']
3093             target['dev']  = info['target']
3094             if str(type) == "network":
3095                 try:
3096                     source['network'] = info['network']
3097                 except:
3098                     source['network'] = None
3099             else:
3100                 try:
3101                     source['bridge']  = info['bridge']
3102                 except:
3103                     source['bridge']  = None
3104
3105             if_info = {
3106                    "type":type,
3107                    "mac":mac,
3108                    "source":source,
3109                    "script":script,
3110                    "target":target,
3111                    }
3112             infos.append(if_info)
3113
3114         return infos
3115
3116     def get_graphics_info(self):
3117         dom = self._conn.lookupByName(self.get_domain_name())
3118
3119         """ current info """
3120         param = ConfigParam(dom.name())
3121         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, dom.name())
3122         if not os.path.exists(xml_file):
3123             ConfigFile(xml_file).write(dom.XMLDesc(0))
3124             if os.getuid() == 0 and os.path.exists(xml_file):
3125                 r_chgrp(xml_file,KARESANSUI_GROUP)
3126         param.load_xml_config(xml_file)
3127
3128         type     = param.get_graphic_type()
3129         port     = param.get_vnc_port()
3130         autoport = param.get_vnc_autoport()
3131         listen   = param.get_vnc_listen()
3132         keymap   = param.get_vnc_keymap()
3133         current_info = {
3134                        "type"    :type,
3135                        "port"    :port,
3136                        "autoport":autoport,
3137                        "listen"  :listen,
3138                        "keymap"  :keymap,
3139                        }
3140
3141         """ current setting """
3142         param = ConfigParam(self.get_domain_name())
3143         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, self.get_domain_name())
3144         if not os.path.exists(xml_file):
3145             dom = self._conn.lookupByName(self.get_domain_name())
3146             ConfigFile(xml_file).write(dom.XMLDesc(0))
3147             if os.getuid() == 0 and os.path.exists(xml_file):
3148                 r_chgrp(xml_file,KARESANSUI_GROUP)
3149         param.load_xml_config(xml_file)
3150         port     = param.get_vnc_port()
3151         autoport = param.get_vnc_autoport()
3152         listen   = param.get_vnc_listen()
3153         keymap   = param.get_vnc_keymap()
3154         passwd   = param.get_vnc_passwd()
3155         current_setting = {
3156                        "port"    :port,
3157                        "autoport":autoport,
3158                        "listen"  :listen,
3159                        "keymap"  :keymap,
3160                        "passwd"  :passwd,
3161                        }
3162
3163         return {"info":current_info,"setting":current_setting}
3164
3165     def create(self):
3166         if self.is_creatable() is True:
3167             time.sleep(1)
3168             dom = self._conn.lookupByName(self.get_domain_name())
3169             dom.create()
3170             for x in range(0,5):
3171                 time.sleep(1)
3172                 if self.status() != VIR_DOMAIN_SHUTOFF:
3173                     break
3174
3175     def shutdown(self):
3176         if self.is_shutdownable() is True:
3177             time.sleep(1)
3178             dom = self._conn.lookupByName(self.get_domain_name())
3179             dom.shutdown()
3180             for x in range(0,120):
3181                 time.sleep(1)
3182                 if self.status() == VIR_DOMAIN_SHUTOFF:
3183                     break
3184
3185     def reboot(self):
3186         if self.is_shutdownable() is True:
3187             time.sleep(1)
3188             dom = self._conn.lookupByName(self.get_domain_name())
3189
3190             """
3191             dom.reboot(0)
3192             """
3193             dom.shutdown()
3194             for x in range(0,480):
3195                 time.sleep(1)
3196                 if self.status() == VIR_DOMAIN_SHUTOFF:
3197                     break
3198             dom.create()
3199
3200             for x in range(0,30):
3201                 time.sleep(1)
3202                 if self.status() != VIR_DOMAIN_SHUTOFF:
3203                     break
3204
3205     def destroy(self):
3206         if self.is_destroyable() is True:
3207             time.sleep(1)
3208             dom = self._conn.lookupByName(self.get_domain_name())
3209             dom.destroy()
3210             for x in range(0,120):
3211                 time.sleep(1)
3212                 if self.status() == VIR_DOMAIN_SHUTOFF:
3213                     break
3214
3215     def suspend(self):
3216         if self.is_suspendable() is True:
3217             time.sleep(1)
3218             dom = self._conn.lookupByName(self.get_domain_name())
3219             dom.suspend()
3220             for x in range(0,5):
3221                 time.sleep(1)
3222                 if self.status() == VIR_DOMAIN_PAUSED:
3223                     break
3224
3225     def resume(self):
3226         if self.is_resumable() is True:
3227             time.sleep(1)
3228             dom = self._conn.lookupByName(self.get_domain_name())
3229             dom.resume()
3230             for x in range(0,5):
3231                 time.sleep(1)
3232                 if self.status() != VIR_DOMAIN_PAUSED:
3233                     break
3234
3235     def undefine(self):
3236         dom = self._conn.lookupByName(self.get_domain_name())
3237         dom.undefine()
3238
3239     def status(self):
3240         return self.get_info()["state"]
3241
3242     def save(self,file):
3243         dom = self._conn.lookupByName(self.get_domain_name())
3244         dom.save(file)
3245         for x in range(0,120):
3246             time.sleep(1)
3247             if self.status() == VIR_DOMAIN_SHUTOFF:
3248                 break
3249
3250
3251     def set_current_snapshot(self,id=None):
3252
3253         from karesansui.lib.virt.config import ConfigParam
3254         param = ConfigParam(self.get_domain_name())
3255
3256         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, self.get_domain_name())
3257         if not os.path.exists(xml_file):
3258             dom = self._conn.lookupByName(self.get_domain_name())
3259             ConfigFile(xml_file).write(dom.XMLDesc(0))
3260             if os.getuid() == 0 and os.path.exists(xml_file):
3261                 r_chgrp(xml_file,KARESANSUI_GROUP)
3262         param.load_xml_config(xml_file)
3263
3264         param.set_current_snapshot(id)
3265
3266         xml_generator = XMLConfigGenerator()
3267         cfgxml = xml_generator.generate(param)
3268         self._conn.defineXML(cfgxml)
3269
3270         sync_config_generator(param, self.get_domain_name())
3271
3272
3273     def autostart(self, flag=None):
3274         if self.connection.get_hypervisor_type() == "Xen":
3275             autostart_file = "%s/%s" %(VIRT_XENDOMAINS_AUTO_DIR,self.get_domain_name())
3276
3277             if flag == True:
3278                 if not os.path.exists(autostart_file):
3279                     command_args = [
3280                         "/bin/ln", "-s",
3281                         "%s/%s" %(self.connection.config_dir,self.get_domain_name()),
3282                         "%s" % VIRT_XENDOMAINS_AUTO_DIR
3283                     ]
3284                     ret = ExecCmd(command_args)
3285             elif flag == False:
3286                 if os.path.exists(autostart_file):
3287                     os.unlink(autostart_file)
3288             else:
3289                 return os.path.lexists(autostart_file)
3290
3291         if self.connection.get_hypervisor_type() == "QEMU":
3292             autostart_file = "%s/%s.xml" %(VIRT_AUTOSTART_CONFIG_DIR,self.get_domain_name())
3293             dom = self._conn.lookupByName(self.get_domain_name())
3294             if flag == True:
3295                 return dom.setAutostart(flag)
3296             elif flag == False:
3297                 return dom.setAutostart(flag)
3298             else:
3299                 return os.path.exists(autostart_file)
3300
3301     def next_disk_target(self,bus=None):
3302         dom = self._conn.lookupByName(self.get_domain_name())
3303         serials = []
3304
3305         param = ConfigParam(dom.name())
3306         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, dom.name())
3307         if not os.path.exists(xml_file):
3308             ConfigFile(xml_file).write(dom.XMLDesc(0))
3309             if os.getuid() == 0 and os.path.exists(xml_file):
3310                 r_chgrp(xml_file,KARESANSUI_GROUP)
3311         param.load_xml_config(xml_file)
3312
3313         if bus is None:
3314             bus = self.connection.bus_types[0]
3315
3316         if bus == "virtio":
3317             prefix_regex = "vd"
3318         elif bus == "scsi":
3319             prefix_regex = "sd"
3320         else:
3321             prefix_regex = "hd|xvd"
3322
3323         prefix = None
3324         for info in param.disks:
3325             block_name = info['target']
3326             p = re.compile(r"""^(?P<prefix>%s)(?P<serial>[a-z])$""" % prefix_regex)
3327             m = p.match(block_name)
3328             if m is not None:
3329                 prefix = m.group("prefix")
3330                 serials.append(m.group("serial"))
3331
3332         if prefix is None:
3333             prefix = prefix_regex
3334
3335         for i,_x in enumerate('abcdefghijklmnopqrstuvwxyz'):
3336           if not _x in serials:
3337             next_serial = _x
3338             break
3339
3340         return "%s%s" %(prefix, next_serial)
3341
3342     """This is unused method
3343     def add_disk(self, path, target, size, is_sparse=True, bus=None,
3344                  driver_name=None, driver_type=None):
3345         name = self.get_domain_name()
3346
3347         # TODO VIRT_DOMAINS_DIR
3348         domain_disk_dir = "%s/%s/disk" % (VIRT_DOMAINS_DIR,name,)
3349         if not os.path.exists(domain_disk_dir):
3350             os.makedirs(domain_disk_dir)
3351
3352         if bus is None:
3353             bus = self.connection.bus_types[0]
3354
3355         if driver_type is None:
3356             if driver_name == "qemu":
3357                 driver_type = "qcow2"
3358             else:
3359                 driver_type = "raw"
3360
3361         try:
3362             MakeDiskImage(path,int(size),driver_type, is_sparse)
3363             return self.append_disk(path, target, bus,
3364                                     driver_name=driver_name, driver_type=driver_type)
3365         except:
3366             if os.path.exists(path) is True:
3367                 os.remove(path)
3368             raise
3369     """
3370
3371     def append_disk(self, path, target, bus=None, disk_type=None, driver_name=None, driver_type=None):
3372
3373         from karesansui.lib.virt.config import ConfigParam
3374         param = ConfigParam(self.get_domain_name())
3375         dom = self._conn.lookupByName(self.get_domain_name())
3376
3377         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, self.get_domain_name())
3378         if not os.path.exists(xml_file):
3379             ConfigFile(xml_file).write(dom.XMLDesc(0))
3380             if os.getuid() == 0 and os.path.exists(xml_file):
3381                 r_chgrp(xml_file,KARESANSUI_GROUP)
3382         param.load_xml_config(xml_file)
3383
3384         if bus is None:
3385             bus = self.connection.bus_types[0]
3386
3387         if disk_type != 'block':
3388             if driver_name is None:
3389                 if self.connection.get_hypervisor_type() == "QEMU":
3390                     driver_name = "qemu"
3391             if driver_type is None:
3392                 if driver_name == "qemu":
3393                     driver_type = "qcow2"
3394
3395         param.add_disk(path,
3396                        target,
3397                        "disk",
3398                        bus,
3399                        disk_type=disk_type,
3400                        driver_name=driver_name,
3401                        driver_type=driver_type)
3402
3403         try:
3404             from karesansui.lib.virt.config import XMLDiskConfigGenerator
3405             generator = XMLDiskConfigGenerator()
3406             generator.set_path(path)
3407             generator.set_target(target)
3408             cfg = generator.generate(None)
3409
3410             # qemu: cannot attach device on inactive domain
3411             if self.connection.get_hypervisor_type() == "QEMU" and dom.isActive() == 0:
3412                 True
3413             # qemu: disk bus 'ide' cannot be hotplugged.
3414             elif self.connection.get_hypervisor_type() == "QEMU" and bus is not None and bus == "ide":
3415                 True
3416             """Do not attach device whatever domain is active or not.
3417             else:
3418                 dom.attachDevice(cfg)
3419             """
3420
3421             xml_generator = XMLConfigGenerator()
3422             cfgxml = xml_generator.generate(param)
3423             self._conn.defineXML(cfgxml)
3424         except:
3425             raise
3426
3427         sync_config_generator(param, self.get_domain_name())
3428
3429     def delete_disk(self, target):
3430         status = self.status()
3431         if status == VIR_DOMAIN_PAUSED:
3432             self.resume()
3433             time.sleep(2)
3434             #raise KaresansuiVirtException("Domain %s is suspended." % self.get_domain_name())
3435
3436         from karesansui.lib.virt.config import ConfigParam
3437         param = ConfigParam(self.get_domain_name())
3438         dom = self._conn.lookupByName(self.get_domain_name())
3439
3440         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, self.get_domain_name())
3441         if not os.path.exists(xml_file):
3442             ConfigFile(xml_file).write(dom.XMLDesc(0))
3443             if os.getuid() == 0 and os.path.exists(xml_file):
3444                 r_chgrp(xml_file,KARESANSUI_GROUP)
3445         param.load_xml_config(xml_file)
3446
3447         path = param.get_disk_path(target)
3448
3449         # physical disk remove
3450         if path is not None and os.path.exists(path) is True:
3451             try:
3452                 os.remove(path)
3453             except:
3454                 self.logger.info("You do not have a disk file. - %s" % path)
3455                 raise
3456         param.delete_disk(target)
3457
3458         try:
3459             from karesansui.lib.virt.config import XMLDiskConfigGenerator
3460             generator = XMLDiskConfigGenerator()
3461             generator.set_target(target)
3462             generator.set_path(path)
3463             cfg = generator.generate(None)
3464
3465             """Do not detach device whatever domain is active or not.
3466             try:
3467                 dom.detachDevice(cfg)
3468             except:
3469                 xml_generator = XMLConfigGenerator()
3470                 cfgxml = xml_generator.generate(param)
3471                 self._conn.defineXML(cfgxml)
3472             """
3473             xml_generator = XMLConfigGenerator()
3474             cfgxml = xml_generator.generate(param)
3475             self._conn.defineXML(cfgxml)
3476
3477             if status == VIR_DOMAIN_PAUSED:
3478                 self.suspend()
3479         except KaresansuiConfigParamException, e:
3480             raise e
3481         except Exception, e:
3482             raise e
3483
3484         sync_config_generator(param, self.get_domain_name())
3485
3486     def append_interface(self,mac,bridge=None,network=None):
3487
3488         from karesansui.lib.virt.config import ConfigParam
3489         param = ConfigParam(self.get_domain_name())
3490         dom = self._conn.lookupByName(self.get_domain_name())
3491
3492         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, self.get_domain_name())
3493         if not os.path.exists(xml_file):
3494             ConfigFile(xml_file).write(dom.XMLDesc(0))
3495             if os.getuid() == 0 and os.path.exists(xml_file):
3496                 r_chgrp(xml_file,KARESANSUI_GROUP)
3497         param.load_xml_config(xml_file)
3498
3499         if network is not None:
3500             netinfo = self.connection.search_kvn_networks(network)[0].get_info()
3501             bridge = netinfo['bridge']['name']
3502
3503         if bridge[0:5] == 'xenbr':
3504             script = "vif-bridge"
3505         else:
3506             script = None
3507         mac = mac.lower()
3508         param.add_interface(mac,"bridge",bridge,script)
3509
3510         try:
3511             from karesansui.lib.virt.config import XMLInterfaceConfigGenerator
3512             generator = XMLInterfaceConfigGenerator()
3513             generator.set_mac(mac)
3514             generator.set_bridge(bridge)
3515             if script is not None:
3516                 generator.set_script(script)
3517             cfg = generator.generate(None)
3518
3519             # qemu: cannot attach device on inactive domain
3520             if self.connection.get_hypervisor_type() == "QEMU" and dom.isActive() == 0:
3521                 True
3522             else:
3523                 dom.attachDevice(cfg)
3524
3525             xml_generator = XMLConfigGenerator()
3526             cfgxml = xml_generator.generate(param)
3527             self._conn.defineXML(cfgxml)
3528
3529         except:
3530             raise
3531
3532         sync_config_generator(param, self.get_domain_name())
3533
3534     def delete_interface(self,mac,force=False):
3535
3536         status = self.status()
3537         if status == VIR_DOMAIN_PAUSED:
3538             self.resume()
3539             time.sleep(2)
3540             #raise KaresansuiVirtException("Domain %s is suspended." % self.get_domain_name())
3541
3542         from karesansui.lib.virt.config import ConfigParam
3543         param = ConfigParam(self.get_domain_name())
3544         dom = self._conn.lookupByName(self.get_domain_name())
3545
3546         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, self.get_domain_name())
3547         if not os.path.exists(xml_file):
3548             ConfigFile(xml_file).write(dom.XMLDesc(0))
3549             if os.getuid() == 0 and os.path.exists(xml_file):
3550                 r_chgrp(xml_file,KARESANSUI_GROUP)
3551         param.load_xml_config(xml_file)
3552
3553         current_snapshot = param.get_current_snapshot()
3554         if force is True:
3555             param.load_xml_config(dom.XMLDesc(0))
3556             if current_snapshot is not None:
3557                 param.set_current_snapshot(current_snapshot)
3558
3559         bridge = None
3560         for info in param.interfaces:
3561             if info["mac"] == mac:
3562                 bridge = info['bridge']
3563
3564         bridge = None
3565         if bridge is None:
3566             param.load_xml_config(dom.XMLDesc(0))
3567             for info in param.interfaces:
3568                 if info["mac"] == mac:
3569                     bridge = info['bridge']
3570
3571         mac = mac.lower()
3572         param.delete_interface(mac)
3573
3574         try:
3575             from karesansui.lib.virt.config import XMLInterfaceConfigGenerator
3576             generator = XMLInterfaceConfigGenerator()
3577             generator.set_mac(mac)
3578             if bridge is not None:
3579                 generator.set_bridge(bridge)
3580             cfg = generator.generate(None)
3581
3582             if self.connection.get_hypervisor_type() == "Xen":
3583                 try:
3584                     dom.detachDevice(cfg)
3585                 except:
3586                     pass
3587
3588             xml_generator = XMLConfigGenerator()
3589             cfgxml = xml_generator.generate(param)
3590             self._conn.defineXML(cfgxml)
3591
3592             if status == VIR_DOMAIN_PAUSED:
3593                 self.suspend()
3594         except:
3595             raise
3596
3597         sync_config_generator(param, self.get_domain_name())
3598
3599     def modify_mac_address(self,old,new):
3600
3601         status = self.status()
3602         if status == VIR_DOMAIN_PAUSED:
3603             self.resume()
3604             time.sleep(2)
3605             #raise KaresansuiVirtException("Domain %s is suspended." % self.get_domain_name())
3606
3607         from karesansui.lib.virt.config import ConfigParam
3608         param = ConfigParam(self.get_domain_name())
3609         dom = self._conn.lookupByName(self.get_domain_name())
3610
3611         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, self.get_domain_name())
3612         if not os.path.exists(xml_file):
3613             ConfigFile(xml_file).write(dom.XMLDesc(0))
3614             if os.getuid() == 0 and os.path.exists(xml_file):
3615                 r_chgrp(xml_file,KARESANSUI_GROUP)
3616         param.load_xml_config(xml_file)
3617
3618         new_interfaces = []
3619
3620         old = old.lower()
3621         new = new.lower()
3622         for info in param.interfaces:
3623             if info["mac"] == old:
3624                 bridge = info['bridge']
3625                 info["mac"] = new
3626             new_interfaces.append(info)
3627         param.interfaces = new_interfaces
3628
3629         try:
3630             """
3631             try:
3632                 self.delete_interface(old,True)
3633                 self.append_interface(new,bridge)
3634             except:
3635                 xml_generator = XMLConfigGenerator()
3636                 cfgxml = xml_generator.generate(param)
3637                 self._conn.defineXML(cfgxml)
3638             """
3639             xml_generator = XMLConfigGenerator()
3640             cfgxml = xml_generator.generate(param)
3641             self._conn.defineXML(cfgxml)
3642
3643             if status == VIR_DOMAIN_PAUSED:
3644                 self.suspend()
3645         except:
3646             raise
3647
3648         sync_config_generator(param, self.get_domain_name())
3649
3650     def set_memory(self,maxmem=None,memory=None):
3651
3652         from karesansui.lib.virt.config import ConfigParam
3653         param = ConfigParam(self.get_domain_name())
3654         dom = self._conn.lookupByName(self.get_domain_name())
3655
3656         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, self.get_domain_name())
3657         if not os.path.exists(xml_file):
3658             ConfigFile(xml_file).write(dom.XMLDesc(0))
3659             if os.getuid() == 0 and os.path.exists(xml_file):
3660                 r_chgrp(xml_file,KARESANSUI_GROUP)
3661         param.load_xml_config(xml_file)
3662
3663         if maxmem:
3664             param.set_max_memory(maxmem)
3665         if memory:
3666             param.set_memory(memory)
3667
3668         try:
3669             dom.setMaxMemory(param.get_max_memory("k"))
3670             dom.setMemory(param.get_memory("k"))
3671
3672             xml_generator = XMLConfigGenerator()
3673             cfgxml = xml_generator.generate(param)
3674             self._conn.defineXML(cfgxml)
3675         except:
3676             raise
3677
3678         sync_config_generator(param, self.get_domain_name())
3679
3680     def set_vcpus(self,max_vcpus=None,vcpus=None):
3681
3682         from karesansui.lib.virt.config import ConfigParam
3683         param = ConfigParam(self.get_domain_name())
3684         dom = self._conn.lookupByName(self.get_domain_name())
3685
3686         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, self.get_domain_name())
3687         if not os.path.exists(xml_file):
3688             ConfigFile(xml_file).write(dom.XMLDesc(0))
3689             if os.getuid() == 0 and os.path.exists(xml_file):
3690                 r_chgrp(xml_file,KARESANSUI_GROUP)
3691         param.load_xml_config(xml_file)
3692
3693         if max_vcpus is not None:
3694             param.set_max_vcpus(int(max_vcpus))
3695
3696         if vcpus is not None:
3697             param.set_vcpus(int(vcpus))
3698
3699         param.set_max_vcpus_limit(int(self.connection.get_max_vcpus()))
3700         param.set_vcpus_limit(int(self.get_vcpus_info()['max_vcpus']))
3701
3702         try:
3703             # qemu: cannot change vcpu count of an active domain
3704             if self.connection.get_hypervisor_type() == "QEMU" and dom.isActive() == 1:
3705                 True
3706             else:
3707                 dom.setVcpus(param.get_vcpus())
3708
3709             xml_generator = XMLConfigGenerator()
3710             cfgxml = xml_generator.generate(param)
3711             self._conn.defineXML(cfgxml)
3712         except:
3713             raise
3714
3715         sync_config_generator(param, self.get_domain_name())
3716
3717     def set_vnc(self,port=None,listen=None,passwd=None,keymap=None):
3718
3719         from karesansui.lib.virt.config import ConfigParam
3720         param = ConfigParam(self.get_domain_name())
3721         dom = self._conn.lookupByName(self.get_domain_name())
3722
3723         xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, self.get_domain_name())
3724         if not os.path.exists(xml_file):
3725             ConfigFile(xml_file).write(dom.XMLDesc(0))
3726             if os.getuid() == 0 and os.path.exists(xml_file):
3727                 r_chgrp(xml_file,KARESANSUI_GROUP)
3728         param.load_xml_config(xml_file)
3729
3730         if port is not None:
3731             param.set_vnc_port(port)
3732
3733         if listen is not None:
3734             param.set_vnc_listen(listen)
3735
3736         if passwd is not None:
3737             param.set_vnc_passwd(passwd)
3738
3739         if keymap is not None:
3740             param.set_vnc_keymap(keymap)
3741
3742         xml_generator = XMLConfigGenerator()
3743         cfgxml = xml_generator.generate(param)
3744         self._conn.defineXML(cfgxml)
3745
3746         sync_config_generator(param, self.get_domain_name())
3747
3748     def is_creatable(self):
3749         """<comment-ja>
3750         ゲストOS(ドメイン)を起動することができるか。
3751         </comment-ja>
3752         <comment-en>
3753         TODO: English Comment
3754         </comment-en>
3755         """
3756         if self.status() == VIR_DOMAIN_SHUTOFF:
3757             return True
3758         else:
3759             return False
3760
3761     def is_shutdownable(self):
3762         """<comment-ja>
3763         ゲストOS(ドメイン)をシャットダウンすることができるか。
3764         </comment-ja>
3765         <comment-en>
3766         TODO: English Comment
3767         </comment-en>
3768         """
3769         
3770         status = self.status()
3771         if status == VIR_DOMAIN_RUNNING \
3772                or status == VIR_DOMAIN_BLOCKED \
3773                or status == VIR_DOMAIN_PAUSED:
3774             return True
3775         else:
3776             return False
3777
3778     def is_destroyable(self):
3779         """<comment-ja>
3780         ゲストOS(ドメイン)を強制停止することができるか。
3781         </comment-ja>
3782         <comment-en>
3783         TODO: English Comment
3784         </comment-en>
3785         """
3786         status = self.status()
3787         if status == VIR_DOMAIN_RUNNING \
3788                or status == VIR_DOMAIN_BLOCKED \
3789                or status == VIR_DOMAIN_PAUSED:
3790             return True
3791         else:
3792             return False
3793
3794     def is_suspendable(self):
3795         """<comment-ja>
3796         ゲストOS(ドメイン)の一時停止することができるか。
3797         </comment-ja>
3798         <comment-en>
3799         TODO: English Comment
3800         </comment-en>
3801         """
3802         status = self.status()
3803         if status == VIR_DOMAIN_NOSTATE \
3804                or status ==VIR_DOMAIN_RUNNING \
3805                or status == VIR_DOMAIN_BLOCKED:
3806             return True
3807         else:
3808             return False
3809
3810     def is_resumable(self):
3811         """<comment-ja>
3812         ゲストOS(ドメイン)再開することができるか。
3813         </comment-ja>
3814         <comment-en>
3815         TODO: English Comment
3816         </comment-en>
3817         """
3818         if self.status() == VIR_DOMAIN_PAUSED:
3819             return True
3820         else:
3821             return False
3822
3823     def is_active(self):
3824         """<comment-ja>
3825         ゲストOSの状態がactiveか。
3826         </comment-ja>
3827         <comment-en>
3828         TODO: English Comment
3829         </comment-en>
3830         """
3831         return (self.get_domain_name() in self.connection.list_active_guest())
3832
3833     def is_inactive(self):
3834         """<comment-ja>
3835         ゲストOSの状態がinactiveか。
3836         </comment-ja>
3837         <comment-en>
3838         TODO: English Comment
3839         </comment-en>
3840         """
3841         return (self.get_domain_name() in self.connection.list_inactive_guest())
3842
3843     def is_takable_snapshot(self):
3844         """<comment-ja>
3845         スナップショットを作成できる状態か。
3846         </comment-ja>
3847         <comment-en>
3848         TODO: English Comment
3849         </comment-en>
3850         """
3851         if self.status() == VIR_DOMAIN_SHUTOFF:
3852             return False
3853         else:
3854             return True
3855
3856     
3857 class KaresansuiVirtNetwork:
3858
3859     def __init__(self, conn, name=None):
3860         self.connection = conn
3861         self._conn = self.connection._conn
3862         self.set_network_name(name)
3863
3864     def set_network_name(self,name=None):
3865         self.network_name = name
3866     def get_network_name(self):
3867         return self.network_name
3868
3869     def load(self):
3870         param = NetworkConfigParam(self.get_network_name())
3871         param.load_xml_config("%s/%s.xml" % (VIRT_NETWORK_CONFIG_DIR, self.get_network_name()))
3872
3873     def start(self):
3874         net = self._conn.networkLookupByName(self.get_network_name())
3875         try:
3876             net.create()
3877         except libvirt.libvirtError, e:
3878             raise KaresansuiVirtException(_("Could not start network '%s' (%s)") % (self.network_name, e))
3879
3880     def stop(self):
3881         net = self._conn.networkLookupByName(self.get_network_name())
3882         try:
3883             if net.isActive() != 0:
3884                 net.destroy()
3885         except libvirt.libvirtError, e:
3886             raise KaresansuiVirtException(_("Could not stop network '%s' (%s)") % (self.network_name, e))
3887
3888     def undefine(self):
3889         net = self._conn.networkLookupByName(self.get_network_name())
3890         net.undefine()
3891
3892     def autostart(self, flag=None):
3893         net = self._conn.networkLookupByName(self.get_network_name())
3894         if flag is None:
3895             return net.autostart()
3896         else:
3897             return net.setAutostart(flag)
3898
3899     def get_json(self):
3900         """<comment-ja>
3901         JSON形式でKaresansuiVirtNetwork情報を返却する。
3902         </comment-ja>
3903         <comment-en>
3904         TODO: English Comment
3905         </comment-en>
3906         """
3907         
3908         ret = {}
3909         ret['name'] = self.get_network_name()
3910         ret.update(self.get_info())
3911         return ret
3912
3913     def get_info(self):
3914         try:
3915             net = self._conn.networkLookupByName(self.get_network_name())
3916             autostart = net.autostart()
3917         except Exception, e:
3918             raise KaresansuiVirtException("Could not get network: %s"
3919                                             % str(e))
3920
3921         param = NetworkConfigParam(self.get_network_name())
3922         xml_file = "%s/%s.xml" % (VIRT_NETWORK_CONFIG_DIR, self.get_network_name())
3923         if not os.path.exists(xml_file):
3924             ConfigFile(xml_file).write(net.XMLDesc(0))
3925             if os.getuid() == 0 and os.path.exists(xml_file):
3926                 r_chgrp(xml_file,KARESANSUI_GROUP)
3927         param.load_xml_config(xml_file)
3928
3929
3930         name        = param.get_network_name()
3931         uuid        = param.get_uuid()
3932         bridge_name = param.get_bridge()
3933         bridge_stp  = param.get_bridge_stp()
3934         bridge_forwardDelay = param.get_bridge_forwardDelay()
3935         bridge = {
3936                    "name"        :bridge_name,
3937                    "stp"         :bridge_stp,
3938                    "forwardDelay":bridge_forwardDelay,
3939                  }
3940
3941         dhcp_start = param.get_dhcp_start()
3942         dhcp_end   = param.get_dhcp_end()
3943         dhcp = {
3944                    "start":dhcp_start,
3945                    "end"  :dhcp_end,
3946                }
3947
3948         ip_address = param.get_ipaddr()
3949         ip_netmask = param.get_netmask()
3950         ip = {
3951                    "address":ip_address,
3952                    "netmask":ip_netmask,
3953                    "dhcp"   :dhcp,
3954              }
3955
3956         forward_dev  = param.get_forward_dev()
3957         forward_mode = param.get_forward_mode()
3958         forward = {
3959                    "mode":forward_mode,
3960                    "dev" :forward_dev,
3961              }
3962
3963         is_active = self.is_active()
3964
3965         return {
3966                 "name"     :name,
3967                 "uuid"     :uuid,
3968                 "bridge"   :bridge,
3969                 "dhcp"     :dhcp,
3970                 "ip"       :ip,
3971                 "forward"  :forward,
3972                 "autostart":autostart,
3973                 "is_active":is_active,
3974         }
3975
3976     def get_network_config_param(self):
3977         return NetworkConfigParam(self.get_info())
3978
3979     def is_active(self):
3980         return (self.network_name in self._conn.listNetworks())
3981
3982     def is_inactive(self):
3983         return (self.network_name in self._conn.listDefinedNetworks())
3984
3985 class KaresansuiVirtStorage:
3986
3987     def __init__(self, conn, name=None):
3988         self.connection = conn
3989         self._conn = self.connection._conn
3990         self.set_storage_name(name)
3991
3992     def set_storage_name(self,name=None):
3993         self.storage_name = name
3994
3995     def get_storage_name(self):
3996         return self.storage_name
3997
3998 class KaresansuiVirtStoragePool(KaresansuiVirtStorage):
3999
4000     def build(self):
4001         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4002         try:
4003             return pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW)
4004         except Exception, e:
4005             raise KaresansuiVirtException("Could not build storage pool: %s"
4006                                             % str(e))
4007
4008     def create(self, name=None, flags=0):
4009         if name is not None:
4010             self.set_storage_name(name)
4011         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4012         try:
4013             ret = pool.create(flags)
4014             pool.refresh(0)
4015             return ret
4016         except Exception, e:
4017             raise KaresansuiVirtException("Could not create storage pool: %s"
4018                                             % str(e))
4019
4020     def start(self, cfgxml, flags, name=None):
4021         if name:
4022             self.set_storage_name(name)
4023             
4024         # define
4025         try:
4026             ret = self._conn.storagePoolDefineXML(cfgxml, flags) # virStoragePoolDefineXML
4027             #ret = libvirtmod.virStoragePoolCreateXML(self._conn._o,cfgxml, 0)
4028         except libvirt.libvirtError, e:
4029             raise KaresansuiVirtException("Could not start pool '%s' (%s)" \
4030                                           % (self.get_storage_name, e))
4031         ret1 = self.build()
4032         ret2 = self.create()
4033         return ret2
4034
4035     def load(self):
4036         param = StoragePoolConfigParam(self.get_storage_name())
4037         param.load_xml_config("%s/%s.xml" \
4038                               % (VIRT_STORAGE_CONFIG_DIR, self.get_storage_name()))
4039
4040
4041     def destroy(self):
4042         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4043         try:
4044             return pool.destroy()
4045         except Exception, e:
4046             raise KaresansuiVirtException("Could not destroy storage pool: %s" \
4047                                             % str(e))
4048
4049     def delete(self, flags):
4050         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4051         try:
4052             return pool.delete(flags)
4053         except Exception, e:
4054             raise KaresansuiVirtException("Could not delete storage pool: %s" \
4055                                             % str(e))
4056
4057     def autostart(self):
4058         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4059         return pool.autostart()
4060
4061     def is_autostart(self):
4062         ret = self.autostart()
4063         if ret == 0:
4064             return False # OFF
4065         elif ret == 1:
4066             return True # ON
4067         else:
4068             return None # ERR
4069
4070     def set_autostart(self, flag=None):
4071         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4072         return pool.setAutostart(flag)
4073
4074     def get_json(self):
4075         """<comment-ja>
4076         JSON形式でKaresansuiVirtNetwork情報を返却する。
4077         </comment-ja>
4078         <comment-en>
4079         TODO: English Comment
4080         </comment-en>
4081         """
4082         ret = {}
4083         ret['name'] = self.get_storage_name()
4084         ret.update(self.get_info())
4085         return ret
4086
4087     def get_info(self):
4088         try:
4089             pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4090         except Exception, e:
4091             raise KaresansuiVirtException("Could not get the storage pool: %s" \
4092                                             % str(e))
4093
4094         param = StoragePoolConfigParam(self.get_storage_name())
4095         param.load_xml_config(pool.XMLDesc(0))
4096         return {"name" : param.get_storage_name(),
4097                 "uuid" : param.get_uuid(),
4098                 "type" : param.get_pool_type(),
4099                 "allocation" : param.get_allocation(),
4100                 "capacity" : param.get_capacity(),
4101                 "available" : param.get_available(),
4102                 "source" : {"dev_path" : param.get_source_dev_path(),
4103                             "dir_path" : param.get_source_dir_path(),
4104                             "h_name" : param.get_source_h_name(),
4105                             "f_type" : param.get_source_f_type(),
4106                             },
4107                 "target" : {"path" : param.get_target_path(),
4108                             "p_owner" : param.get_target_permissions_owner(),
4109                             "p_group" : param.get_target_permissions_group(),
4110                             "p_mode" : param.get_target_permissions_mode(),
4111                             "p_label" : param.get_target_permissions_label(),
4112                             "e_format" : param.get_target_e_format(),
4113                             "e_s_type" : param.get_target_encryption_s_type(),
4114                             "e_s_uuid" : param.get_target_encryption_s_uuid(),
4115                             },
4116                 "is_active"    : self.is_active(),
4117                 "is_autostart" : self.is_autostart(),
4118             }
4119
4120     def is_active(self):
4121         return (self.storage_name in self._conn.listStoragePools())
4122
4123     def is_inactive(self):
4124         return (self.storage_name in self._conn.listdefinedStoragePools())
4125
4126     def vol_createXML(self, xmldesc, flags):
4127         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4128         try:
4129             return pool.createXML(xmldesc, flags)
4130         except Exception, e:
4131             raise KaresansuiVirtException("Could not create storage volume: %s" % str(e))
4132
4133     def vol_numOfVolumes(self):
4134         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4135         return pool.numOfVolumes()
4136         
4137     def vol_storageVolLookupByName(self, name):
4138         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4139         return pool.storageVolLookupByName(name)
4140         
4141     def vol_listVolumes(self):
4142         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4143         return pool.listVolumes()
4144
4145     def search_kvn_storage_volumes(self, conn):
4146         vols_obj = []
4147         for vol in self.vol_listVolumes():
4148             vol_obj = KaresansuiVirtStorageVolume(conn)
4149             vol_obj.set_storage_name(self.get_storage_name())
4150             vol_obj.set_storage_volume_name(vol)
4151             
4152             vols_obj.append(vol_obj)
4153         return vols_obj
4154
4155 class KaresansuiVirtStorageVolume(KaresansuiVirtStorage):
4156
4157     storage_volume_name = None
4158
4159     def set_storage_volume_name(self,name=None):
4160         self.storage_volume_name = name
4161
4162     def get_storage_volume_name(self):
4163         return self.storage_volume_name
4164
4165     def load(self):
4166         param = StorageVolumeConfigParam(self.get_storage_volume_name())
4167         param.load_xml_config("%s/%s.xml" \
4168                               % (VIRT_STORAGE_CONFIG_DIR, self.get_storage_volume_name()))
4169
4170     def delete(self, flags):
4171         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4172         try:
4173             vol = pool.storageVolLookupByName(self.get_storage_volume_name())
4174             return vol.delete(flags)
4175         except Exception, e:
4176             raise KaresansuiVirtException("Could not delete storage volume: %s"
4177                                             % str(e))
4178
4179     def get_json(self):
4180         """<comment-ja>
4181         JSON形式でKaresansuiVirtNetwork情報を返却する。
4182         </comment-ja>
4183         <comment-en>
4184         TODO: English Comment
4185         </comment-en>
4186         """
4187         pass
4188         #ret = {}
4189         #ret['name'] = self.get_network_name()
4190         #ret.update(self.get_info())
4191         #return ret
4192
4193     def get_info(self):
4194         pool = self._conn.storagePoolLookupByName(self.get_storage_name())
4195         try:
4196             vol = pool.storageVolLookupByName(self.get_storage_volume_name())
4197         except Exception, e:
4198             raise KaresansuiVirtException("Could not get the storage volume: %s"
4199                                             % str(e))
4200
4201         param = StorageVolumeConfigParam(self.get_storage_name())
4202         try:
4203             param.load_xml_config(vol.XMLDesc(0))
4204         except libvirt.libvirtError, le:
4205             # TODO test!!
4206             self.connection.refresh_pools()
4207             param.load_xml_config(vol.XMLDesc(0))
4208
4209         real = param.get_symlink2real()
4210         return {"name" : param.get_storage_name(),
4211                 "uuid" : param.get_uuid(),
4212                 "key" : param.get_key(),
4213                 "allocation" : param.get_allocation(),
4214                 "capacity" : param.get_capacity(),
4215                 "c_unit" : param.get_c_unit(),
4216                 "source" : param.get_source(),
4217                 "target" : {"path" : param.get_target_path(),
4218                             "f_type" : param.get_target_f_type(),
4219                             "p_owner" : param.get_target_permissions_owner(),
4220                             "p_group" : param.get_target_permissions_group(),
4221                             "p_mode" : param.get_target_permissions_mode(),
4222                             "p_label" : param.get_target_permissions_label(),
4223                             "b_path" : param.get_backingStore_path(),
4224                             "b_format" : param.get_backingStore_format(),
4225                             "b_p_owner" : param.get_backingStore_permissions_owner(),
4226                             "b_p_group" : param.get_backingStore_permissions_group(),
4227                             "b_p_mode" : param.get_backingStore_permissions_mode(),
4228                             "b_p_label" : param.get_backingStore_permissions_label(),
4229                             },
4230                 "real" : {"dir" : real[0],
4231                           "name" : real[1],
4232                           "extension" : real[2],
4233                           },
4234                 }
4235
4236
4237 if __name__ == '__main__':
4238     from karesansui.lib.utils import preprint_r
4239
4240     conn = KaresansuiVirtConnection(readonly=False)
4241     try:
4242         pass
4243         #print conn.get_storage_pool_type("default")
4244         #preprint_r(conn.get_capabilities())
4245         #print conn.get_storage_pool_name_bydomain("guest1",image_type='os')
4246         #print conn.get_storage_pool_name_bydomain("guest1",image_type='')
4247         #print conn.get_storage_pool_name_bydomain("centos55",image_type='')
4248         #print conn.get_storage_volume_bypool("default",attr="info")
4249         #print conn.get_storage_volume_bypool("default",attr="name")
4250         #print conn.get_storage_volume_bydomain("centos55",image_type=None, attr="name")
4251         #print conn.get_storage_volume_bydomain("centos55",image_type=None, attr="path")
4252         #print conn.get_storage_volume_bydomain("centos55",image_type="os", attr="info")
4253         #print conn.get_storage_volume_bydomain("centos55",image_type="os", attr="name")
4254         print conn.get_storage_volume_bydomain("centos55",image_type="disk", attr="name")
4255         #print conn.get_storage_pool_name_byimage("/var/opt/hde/libvirt/domains/guest1/images/guest1.img")
4256         #print conn.list_used_vnc_port()
4257         #print conn.list_used_mac_addr()
4258
4259         #kvg = conn.search_kvg_guests("centos55")[0]
4260         #preprint_r(kvg.get_info())
4261         #preprint_r(kvg.get_disk_info())
4262         #conn.import_guest("/var/opt/hde/libvirt/domains/527109d0-cb91-7308-ad39-7738c1893dc9", uuid=None, progresscb=None)
4263         #preprint_r(kvg.get_vcpus_info())
4264         #preprint_r(kvg.get_interface_info())
4265         #preprint_r(kvg.get_graphics_info())
4266         #print kvg.next_disk_target()
4267         #print kvg.delete_interface("52:54:00:0f:cb:6a")
4268
4269         #kvn = conn.search_kvn_networks("default")[0]
4270         #preprint_r(kvn.get_info())
4271
4272         #print conn.get_hypervisor_type()
4273         #print conn.get_hypervisor_type_bydomain("guest1")
4274
4275     except:
4276         raise
4277