Revision 6b93ec9d
b/daemons/ganeti-noded | ||
---|---|---|
232 | 232 |
disks = [objects.Disk.FromDict(cf) for cf in params[1]] |
233 | 233 |
return backend.CloseBlockDevices(params[0], disks) |
234 | 234 |
|
235 |
# blockdev/drbd specific methods ---------- |
|
236 |
|
|
237 |
@staticmethod |
|
238 |
def perspective_drbd_disconnect_net(params): |
|
239 |
"""Disconnects the network connection of drbd disks. |
|
240 |
|
|
241 |
Note that this is only valid for drbd disks, so the members of the |
|
242 |
disk list must all be drbd devices. |
|
243 |
|
|
244 |
""" |
|
245 |
nodes_ip, disks = params |
|
246 |
disks = [objects.Disk.FromDict(cf) for cf in disks] |
|
247 |
return backend.DrbdDisconnectNet(nodes_ip, disks) |
|
248 |
|
|
249 |
@staticmethod |
|
250 |
def perspective_drbd_attach_net(params): |
|
251 |
"""Attaches the network connection of drbd disks. |
|
252 |
|
|
253 |
Note that this is only valid for drbd disks, so the members of the |
|
254 |
disk list must all be drbd devices. |
|
255 |
|
|
256 |
""" |
|
257 |
nodes_ip, disks, instance_name, multimaster = params |
|
258 |
disks = [objects.Disk.FromDict(cf) for cf in disks] |
|
259 |
return backend.DrbdAttachNet(nodes_ip, disks, instance_name, multimaster) |
|
260 |
|
|
261 |
@staticmethod |
|
262 |
def perspective_drbd_wait_sync(params): |
|
263 |
"""Wait until DRBD disks are synched. |
|
264 |
|
|
265 |
Note that this is only valid for drbd disks, so the members of the |
|
266 |
disk list must all be drbd devices. |
|
267 |
|
|
268 |
""" |
|
269 |
nodes_ip, disks = params |
|
270 |
disks = [objects.Disk.FromDict(cf) for cf in disks] |
|
271 |
return backend.DrbdWaitSync(nodes_ip, disks) |
|
272 |
|
|
235 | 273 |
# export/import -------------------------- |
236 | 274 |
|
237 | 275 |
@staticmethod |
b/lib/backend.py | ||
---|---|---|
2177 | 2177 |
return (True, "Done") |
2178 | 2178 |
|
2179 | 2179 |
|
2180 |
def _FindDisks(nodes_ip, disks): |
|
2181 |
"""Sets the physical ID on disks and returns the block devices. |
|
2182 |
|
|
2183 |
""" |
|
2184 |
# set the correct physical ID |
|
2185 |
my_name = utils.HostInfo().name |
|
2186 |
for cf in disks: |
|
2187 |
cf.SetPhysicalID(my_name, nodes_ip) |
|
2188 |
|
|
2189 |
bdevs = [] |
|
2190 |
|
|
2191 |
for cf in disks: |
|
2192 |
rd = _RecursiveFindBD(cf) |
|
2193 |
if rd is None: |
|
2194 |
return (False, "Can't find device %s" % cf) |
|
2195 |
bdevs.append(rd) |
|
2196 |
return (True, bdevs) |
|
2197 |
|
|
2198 |
|
|
2199 |
def DrbdDisconnectNet(nodes_ip, disks): |
|
2200 |
"""Disconnects the network on a list of drbd devices. |
|
2201 |
|
|
2202 |
""" |
|
2203 |
status, bdevs = _FindDisks(nodes_ip, disks) |
|
2204 |
if not status: |
|
2205 |
return status, bdevs |
|
2206 |
|
|
2207 |
# disconnect disks |
|
2208 |
for rd in bdevs: |
|
2209 |
try: |
|
2210 |
rd.DisconnectNet() |
|
2211 |
except errors.BlockDeviceError, err: |
|
2212 |
logging.exception("Failed to go into standalone mode") |
|
2213 |
return (False, "Can't change network configuration: %s" % str(err)) |
|
2214 |
return (True, "All disks are now disconnected") |
|
2215 |
|
|
2216 |
|
|
2217 |
def DrbdAttachNet(nodes_ip, disks, instance_name, multimaster): |
|
2218 |
"""Attaches the network on a list of drbd devices. |
|
2219 |
|
|
2220 |
""" |
|
2221 |
status, bdevs = _FindDisks(nodes_ip, disks) |
|
2222 |
if not status: |
|
2223 |
return status, bdevs |
|
2224 |
|
|
2225 |
if multimaster: |
|
2226 |
for cf, rd in zip(disks, bdevs): |
|
2227 |
try: |
|
2228 |
_SymlinkBlockDev(instance_name, rd.dev_path, cf.iv_name) |
|
2229 |
except EnvironmentError, err: |
|
2230 |
return (False, "Can't create symlink: %s" % str(err)) |
|
2231 |
# reconnect disks, switch to new master configuration and if |
|
2232 |
# needed primary mode |
|
2233 |
for rd in bdevs: |
|
2234 |
try: |
|
2235 |
rd.AttachNet(multimaster) |
|
2236 |
except errors.BlockDeviceError, err: |
|
2237 |
return (False, "Can't change network configuration: %s" % str(err)) |
|
2238 |
# wait until the disks are connected; we need to retry the re-attach |
|
2239 |
# if the device becomes standalone, as this might happen if the one |
|
2240 |
# node disconnects and reconnects in a different mode before the |
|
2241 |
# other node reconnects; in this case, one or both of the nodes will |
|
2242 |
# decide it has wrong configuration and switch to standalone |
|
2243 |
RECONNECT_TIMEOUT = 2 * 60 |
|
2244 |
sleep_time = 0.100 # start with 100 miliseconds |
|
2245 |
timeout_limit = time.time() + RECONNECT_TIMEOUT |
|
2246 |
while time.time() < timeout_limit: |
|
2247 |
all_connected = True |
|
2248 |
for rd in bdevs: |
|
2249 |
stats = rd.GetProcStatus() |
|
2250 |
if not (stats.is_connected or stats.is_in_resync): |
|
2251 |
all_connected = False |
|
2252 |
if stats.is_standalone: |
|
2253 |
# peer had different config info and this node became |
|
2254 |
# standalone, even though this should not happen with the |
|
2255 |
# new staged way of changing disk configs |
|
2256 |
try: |
|
2257 |
rd.ReAttachNet(multimaster) |
|
2258 |
except errors.BlockDeviceError, err: |
|
2259 |
return (False, "Can't change network configuration: %s" % str(err)) |
|
2260 |
if all_connected: |
|
2261 |
break |
|
2262 |
time.sleep(sleep_time) |
|
2263 |
sleep_time = min(5, sleep_time * 1.5) |
|
2264 |
if not all_connected: |
|
2265 |
return (False, "Timeout in disk reconnecting") |
|
2266 |
if multimaster: |
|
2267 |
# change to primary mode |
|
2268 |
for rd in bdevs: |
|
2269 |
rd.Open() |
|
2270 |
if multimaster: |
|
2271 |
msg = "multi-master and primary" |
|
2272 |
else: |
|
2273 |
msg = "single-master" |
|
2274 |
return (True, "Disks are now configured as %s" % msg) |
|
2275 |
|
|
2276 |
|
|
2277 |
def DrbdWaitSync(nodes_ip, disks): |
|
2278 |
"""Wait until DRBDs have synchronized. |
|
2279 |
|
|
2280 |
""" |
|
2281 |
status, bdevs = _FindDisks(nodes_ip, disks) |
|
2282 |
if not status: |
|
2283 |
return status, bdevs |
|
2284 |
|
|
2285 |
min_resync = 100 |
|
2286 |
alldone = True |
|
2287 |
failure = False |
|
2288 |
for rd in bdevs: |
|
2289 |
stats = rd.GetProcStatus() |
|
2290 |
if not (stats.is_connected or stats.is_in_resync): |
|
2291 |
failure = True |
|
2292 |
break |
|
2293 |
alldone = alldone and (not stats.is_in_resync) |
|
2294 |
if stats.sync_percent is not None: |
|
2295 |
min_resync = min(min_resync, stats.sync_percent) |
|
2296 |
return (not failure, (alldone, min_resync)) |
|
2297 |
|
|
2298 |
|
|
2180 | 2299 |
class HooksRunner(object): |
2181 | 2300 |
"""Hook runner. |
2182 | 2301 |
|
b/lib/bdev.py | ||
---|---|---|
567 | 567 |
self.is_diskless = self.ldisk == "Diskless" |
568 | 568 |
self.is_disk_uptodate = self.ldisk == "UpToDate" |
569 | 569 |
|
570 |
self.is_in_resync = self.cstatus in ('SyncSource', 'SyncTarget') |
|
571 |
|
|
570 | 572 |
m = self.SYNC_RE.match(procline) |
571 | 573 |
if m: |
572 | 574 |
self.sync_percent = float(m.group(1)) |
b/lib/rpc.py | ||
---|---|---|
736 | 736 |
params = [instance_name, [cf.ToDict() for cf in disks]] |
737 | 737 |
return self._SingleNodeCall(node, "blockdev_close", params) |
738 | 738 |
|
739 |
def call_drbd_disconnect_net(self, node_list, nodes_ip, disks): |
|
740 |
"""Disconnects the network of the given drbd devices. |
|
741 |
|
|
742 |
This is a multi-node call. |
|
743 |
|
|
744 |
""" |
|
745 |
return self._MultiNodeCall(node_list, "drbd_disconnect_net", |
|
746 |
[nodes_ip, [cf.ToDict() for cf in disks]]) |
|
747 |
|
|
748 |
def call_drbd_attach_net(self, node_list, nodes_ip, |
|
749 |
disks, instance_name, multimaster): |
|
750 |
"""Disconnects the given drbd devices. |
|
751 |
|
|
752 |
This is a multi-node call. |
|
753 |
|
|
754 |
""" |
|
755 |
return self._MultiNodeCall(node_list, "drbd_attach_net", |
|
756 |
[nodes_ip, [cf.ToDict() for cf in disks], |
|
757 |
instance_name, multimaster]) |
|
758 |
|
|
759 |
def call_drbd_wait_sync(self, node_list, nodes_ip, disks): |
|
760 |
"""Waits for the synchronization of drbd devices is complete. |
|
761 |
|
|
762 |
This is a multi-node call. |
|
763 |
|
|
764 |
""" |
|
765 |
return self._MultiNodeCall(node_list, "drbd_wait_sync", |
|
766 |
[nodes_ip, [cf.ToDict() for cf in disks]]) |
|
767 |
|
|
739 | 768 |
@classmethod |
740 | 769 |
def call_upload_file(cls, node_list, file_name, address_list=None): |
741 | 770 |
"""Upload a file. |
Also available in: Unified diff