OSDN Git Service

5604807c9ca3f0c5af24dc7038e744a5b171bb13
[karesansui/karesansui.git] / karesansui / gadget / guestby1device.py
1 # -*- coding: utf-8 -*-
2 #
3 # This file is part of Karesansui.
4 #
5 # Copyright (C) 2009-2010 HDE, Inc.
6 #
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
11 #
12
13 import re
14 import os
15 import pwd
16
17 import web
18
19 import karesansui
20 from karesansui.lib.rest import Rest, auth
21
22 from karesansui.lib.virt.virt import KaresansuiVirtException, \
23      KaresansuiVirtConnection
24 from karesansui.lib.merge import MergeGuest
25 from karesansui.lib.utils import get_ifconfig_info, generate_mac_address, is_param, \
26      generate_uuid, string_from_uuid
27
28 from karesansui.gadget.guestby1disk import create_disk_job, validates_disk, \
29      create_storage_volume_dir, exec_disk_job
30
31 from karesansui.gadget.guestby1nic import create_nic_job, validates_nic
32
33 from karesansui.gadget.hostby1networkstorage import get_iscsi_cmd
34
35 from karesansui.db.access.machine import findbyguest1
36 from karesansui.db.access._2pysilhouette import save_job_collaboration
37 from karesansui.db.access.machine2jobgroup import new as m2j_new
38 from karesansui.db.model._2pysilhouette import JobGroup, Job
39
40 from pysilhouette.command import dict2command
41
42 from karesansui.lib.const import DISK_QEMU_FORMAT, DISK_NON_QEMU_FORMAT, \
43      STORAGE_VOLUME_PWD, DISK_USES, \
44      VIRT_COMMAND_DELETE_STORAGE_VOLUME, VIRT_COMMAND_CREATE_STORAGE_VOLUME
45
46 from karesansui.lib.checker import Checker, \
47      CHECK_EMPTY, CHECK_VALID, CHECK_LENGTH, \
48      CHECK_STARTROOT, CHECK_EXIST, CHECK_ISDIR
49
50 class GuestBy1Device(Rest):
51
52     @auth
53     def _GET(self, *param, **params):
54         (host_id, guest_id) = self.chk_guestby1(param)
55         if guest_id is None: return web.notfound()
56
57         bridge_prefix = {
58                           "XEN":"xenbr",
59                           "KVM":"eth",
60                         }
61
62         model = findbyguest1(self.orm, guest_id)
63
64         # virt
65         self.kvc = KaresansuiVirtConnection()
66         try:
67             inactive_pool = []
68             active_pool = self.kvc.list_active_storage_pool()
69             pools = inactive_pool + active_pool
70             pools.sort()
71
72             if not pools:
73                 return web.badrequest('One can not start a storage pool.')
74
75             self.view.pools = pools
76
77             domname = self.kvc.uuid_to_domname(model.uniq_key)
78             if not domname: return web.notfound()
79
80             virt = self.kvc.search_kvg_guests(domname)[0]
81
82             guest = MergeGuest(model, virt)
83
84             try:
85                 VMType = guest.info["virt"].get_info()["VMType"].upper()
86             except:
87                 VMType = "KVM"
88
89             phydev = []
90             phydev_regex = re.compile(r"%s" % bridge_prefix[VMType])
91
92             for dev,dev_info in get_ifconfig_info().iteritems():
93                 try:
94                     if phydev_regex.match(dev):
95                         phydev.append(dev)
96                 except:
97                     pass
98             if len(phydev) == 0:
99                 phydev.append("%s0" % bridge_prefix[VMType])
100
101             phydev.sort()
102             self.view.phydev = phydev # Physical device
103             self.view.virnet = sorted(self.kvc.list_active_network()) # Virtual device
104             self.view.mac_address = generate_mac_address() # new mac address
105             self.view.ifinfo = virt.get_interface_info() # interface info
106             self.view.guest = guest # virt obj off
107             self.view.VMType = VMType
108             if VMType == "KVM":
109                 self.view.DISK_FORMATS = DISK_QEMU_FORMAT
110             else:
111                 self.view.DISK_FORMATS = DISK_NON_QEMU_FORMAT
112
113             self.view.bus_types = self.kvc.bus_types
114
115             # iscsi block device list
116             network_storages = get_iscsi_cmd(self, host_id)
117             if network_storages is False:
118                 self.logger.debug("Get iSCSI command failed. Return to timeout")
119                 return web.internalerror('Internal Server Error. (Timeout)')
120
121             self.view.network_storages = network_storages
122
123             #iscsi_pools = {}
124             #for pool in pools:
125             #    pool_obj = self.kvc.search_kvn_storage_pools(pool)[0]
126             #    pool_info = pool_obj.get_info()
127             #    if pool_obj.is_active() is True and pool_info['type'] == 'iscsi':
128             #        vols_obj = pool_obj.search_kvn_storage_volumes(self.kvc)
129             #        vols_info = []
130             #        for vol_obj in vols_obj:
131             #            vols_info.append(vol_obj.get_info())
132             #
133             #        iscsi_pools[pool] = {"info" : pool_obj.get_info(),
134             #                             "vols" : vols_info,
135             #                             }
136             #self.view.iscsi_pools = iscsi_pools
137
138             # os pool info
139             os_pool = self.kvc.get_storage_pool_name_bydomain(domname, "os")
140             if not os_pool:
141                 return web.badrequest(_("Was found that the guest are using storage pools."))
142             self.view.os_pool = os_pool[0]
143
144             #self.view.pool_info = self.kvc.search_kvn_storage_pools(os_pool[0])[0].get_info()
145             pools_info = []
146             for pool in self.kvc.search_kvn_storage_pools():
147                 pools_info.append(pool.get_info())
148             self.view.pools_info = pools_info
149
150             # disk
151             self.view.disk_info = virt.get_disk_info() # Disk info
152
153             #from karesansui.lib.utils import preprint_r
154             #preprint_r(self.view.pools_info)
155             #preprint_r(self.view.pools_vols_info)
156             #import pdb; pdb.set_trace()
157
158         finally:
159             self.kvc.close()
160
161         return True
162
163     @auth
164     def _POST(self, *param, **params):
165         (host_id, guest_id) = self.chk_guestby1(param)
166         if guest_id is None: return web.notfound()
167
168         model = findbyguest1(self.orm, guest_id)
169
170         # virt
171         kvc = KaresansuiVirtConnection()
172         try:
173             domname = kvc.uuid_to_domname(model.uniq_key)
174             if not domname: return web.conflict(web.ctx.path)
175             virt = kvc.search_kvg_guests(domname)[0]
176             nic_info = virt.get_interface_info()
177
178             # -- Nic
179             if self.input.device_type == "nic":
180                 if not validates_nic(self):
181                     return web.badrequest(self.view.alert)
182
183                 f_chk = True
184                 for x in nic_info:
185                     if x['mac']['address'] == self.input.mac_address:
186                         f_chk = False
187                         break
188                 if f_chk is False:
189                     return web.badrequest(_('Specified MAC address is already defined.'))
190
191                 mac = self.input.mac_address
192                 bridge = None
193                 network = None
194                 if self.input.nic_type == "phydev":
195                     bridge = self.input.phydev
196                 elif self.input.nic_type == "virnet":
197                     network = self.input.virnet
198
199                 self.logger.debug('spinning off create_nic_job dom=%s, mac=%s, bridge=%s, network=%s' \
200                                   % (domname, mac, bridge, network))
201
202                 create_nic_job(self,model,domname,mac,bridge,network)
203                 return web.accepted()
204
205             # -- Disk
206             elif self.input.device_type == "disk":
207                 if not validates_disk(self):
208                     return web.badrequest(self.view.alert)
209
210                 volume_job = None
211                 order = 0
212                 if self.input.disk_layout == "create": # create(dir)
213                     disk_type = 'file'
214                     volume_name = string_from_uuid(generate_uuid())
215                     volume_job = create_storage_volume_dir(self,
216                                                            model,
217                                                            domname,
218                                                            volume_name,
219                                                            self.input.pool_dir,
220                                                            self.input.disk_format,
221                                                            self.input.disk_size,
222                                                            self.input.disk_size,
223                                                            'M',
224                                                            order)
225                     order += 1
226
227                     pool_name = self.input.pool_dir
228                 elif self.input.disk_layout == "iscsi": # create(iscsi block)
229                     disk_type = 'iscsi'
230                     pool_name = self.input.pool_dir
231                     target_storage = kvc.get_storage_volume_iscsi_bysymlink(self.input.iscsi_block)
232                     pool_name = target_storage['pool']
233                     volume_name = target_storage['volume']
234                 else:
235                     return badrequest(_("No storage type specified."))
236
237                 # add disk
238                 disk_job = create_disk_job(self,
239                                            guest=model,
240                                            domain_name=domname,
241                                            pool=pool_name,
242                                            volume=volume_name,
243                                            bus=self.input.bus_type,
244                                            format=self.input.disk_format,
245                                            type=disk_type,
246                                            order=order)
247                 order += 1
248
249                 if exec_disk_job(obj=self,
250                                  guest=model,
251                                  disk_job=disk_job,
252                                  volume_job=volume_job,
253                                  order=order
254                                  ) is True:
255                     return web.accepted()
256                 else:
257                     return False
258
259             else: # Not Found
260                 return False
261         finally:
262             kvc.close()
263
264 urls = (
265     '/host/(\d+)/guest/(\d+)/device/?(\.part|\.html)?$', GuestBy1Device,
266     )