Revision 6b93ec9d lib/backend.py

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

  

Also available in: Unified diff