1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('anate.vm')
import os
import devices
class VirtualDisk(devices.DMDevice):
_LOOP_DEV_MAJOR = 7
_AVAILABLE_MINORS = [0, 1, 2, 3, 4, 5, 6, 7]
def getAvailableMinor(self):
return self._AVAILABLE_MINORS[0]
def useMinor(self, minor):
self._AVAILABLE_MINORS.remove(minor)
def freeMinor(self, minor):
self._AVAILABLE_MINORS.append(minor)
self._AVAILABLE_MINORS.sort()
def __init__(self, name, size, usable_size=None):
if not usable_size:
usable_size = size
elif usable_size > size:
logger.error('usable_size cannot be greater than size')
return
self._remove_node = False
self._loop_node = self._createLoopNode(name)
if not self._loop_node:
raise OSError, 'node error'
self._loop_dev = self._createLoopDev(name, self._loop_node, usable_size)
devices.DMDevice.__init__(self, name, self._loop_dev, size)
def _createLoopNode(self, name):
loop_node = devices.BlockDeviceNode(os.path.join('/dev/', name), major=None, minor=None)
if loop_node.available:
logger.info('using existing node %s', loop_node.path)
loop_node.major, loop_node.minor = devices.getDeviceNumbers(loop_node.path)
if loop_node.major != self._LOOP_DEV_MAJOR:
logger.error('not a loop device node')
return
if loop_node.minor not in self._AVAILABLE_MINORS:
logger.error('node not available')
return
else:
logger.info('creating new node %s', loop_node.path)
loop_node.major = self._LOOP_DEV_MAJOR
loop_node.minor = self.getAvailableMinor()
loop_node.create()
self._remove_node = True
self.useMinor(loop_node.minor)
logger.info('using minor %d', loop_node.minor)
logger.info('available minors: %s', self._AVAILABLE_MINORS)
if not loop_node.available:
raise OSError, 'node error'
return loop_node
def _createLoopDev(self, name, loop_node, size):
loop_dev = devices.LoopDevice(name, loop_node, os.path.join('/tmp/', name), size)
loop_dev.initialize()
if not loop_dev.active:
raise OSError, 'loop device error'
return loop_dev
def create(self):
self.initialize()
if not self.active:
raise OSError, 'dm device error'
def remove(self):
self.destroy()
if self.active:
raise OSError, 'dm device error'
self._loop_dev.destroy()
if self._loop_dev.active:
raise OSError, 'loop device error'
if self._remove_node:
logger.info('removing node %s', self._loop_node.path)
self._loop_node.unlink()
if self._loop_node.available:
raise OSError, 'node error'
self.freeMinor(self._loop_node.minor)
logger.info('freeing minor %d', self._loop_node.minor)
logger.info('available minors: %s', self._AVAILABLE_MINORS)
class VM(object):
def __init__(self):
self._disks = {}
def addDisk(self, name, size, usable_size=None):
if name in self.disks:
logger.error('disk %s already exists', name)
return
disk = VirtualDisk(name, size=size, usable_size=usable_size)
disk.create()
self._disks[name] = disk
def removeDisk(self, name):
if name not in self.disks:
logger.error('disk %s does not exist', name)
return
disk = self.getDisk(name)
if disk.active:
disk.remove()
del self._disks[name]
def halt(self):
for disk in self.disks.values():
if disk.active:
disk.remove()
self._disks = {}
@property
def disks(self):
return self._disks
def getDisk(self, name):
return self.disks.get(name, None)
|