Package haizea :: Package core :: Package scheduler :: Package preparation_schedulers :: Module imagetransfer
[hide private]
[frames] | no frames]

Source Code for Module haizea.core.scheduler.preparation_schedulers.imagetransfer

  1  # -------------------------------------------------------------------------- # 
  2  # Copyright 2006-2009, University of Chicago                                 # 
  3  # Copyright 2008-2009, Distributed Systems Architecture Group, Universidad   # 
  4  # Complutense de Madrid (dsa-research.org)                                   # 
  5  #                                                                            # 
  6  # Licensed under the Apache License, Version 2.0 (the "License"); you may    # 
  7  # not use this file except in compliance with the License. You may obtain    # 
  8  # a copy of the License at                                                   # 
  9  #                                                                            # 
 10  # http://www.apache.org/licenses/LICENSE-2.0                                 # 
 11  #                                                                            # 
 12  # Unless required by applicable law or agreed to in writing, software        # 
 13  # distributed under the License is distributed on an "AS IS" BASIS,          # 
 14  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   # 
 15  # See the License for the specific language governing permissions and        # 
 16  # limitations under the License.                                             # 
 17  # -------------------------------------------------------------------------- # 
 18   
 19  import haizea.common.constants as constants 
 20  from haizea.core.scheduler.preparation_schedulers import PreparationScheduler 
 21  from haizea.core.scheduler.slottable import ResourceReservation 
 22  from haizea.core.scheduler import MigrationResourceReservation, InconsistentLeaseStateError 
 23  from haizea.core.leases import Lease, Capacity, UnmanagedSoftwareEnvironment 
 24  from haizea.core.scheduler import ReservationEventHandler, NotSchedulableException, EarliestStartingTime 
 25  from haizea.common.utils import estimate_transfer_time, get_config 
 26  from mx.DateTime import TimeDelta 
 27   
 28  import bisect 
 29  import logging 
30 31 -class ImageTransferPreparationScheduler(PreparationScheduler):
32 - def __init__(self, slottable, resourcepool, deployment_enact):
33 PreparationScheduler.__init__(self, slottable, resourcepool, deployment_enact) 34 35 self.imagenode = self.deployment_enact.get_imagenode() 36 37 self.transfers = [] 38 self.completed_transfers = [] 39 40 self.imagenode_bandwidth = self.deployment_enact.get_bandwidth() 41 42 self.handlers ={} 43 self.handlers[FileTransferResourceReservation] = ReservationEventHandler( 44 sched = self, 45 on_start = ImageTransferPreparationScheduler._handle_start_filetransfer, 46 on_end = ImageTransferPreparationScheduler._handle_end_filetransfer) 47 48 self.handlers[DiskImageMigrationResourceReservation] = ReservationEventHandler( 49 sched = self, 50 on_start = ImageTransferPreparationScheduler._handle_start_migrate, 51 on_end = ImageTransferPreparationScheduler._handle_end_migrate)
52
53 - def schedule(self, lease, vmrr, earliest):
54 if type(lease.software) == UnmanagedSoftwareEnvironment: 55 return [], True 56 if lease.get_type() == Lease.ADVANCE_RESERVATION: 57 return self.__schedule_deadline(lease, vmrr, earliest) 58 elif lease.get_type() in (Lease.BEST_EFFORT, Lease.IMMEDIATE): 59 return self.__schedule_asap(lease, vmrr, earliest)
60
61 - def schedule_migration(self, lease, vmrr, nexttime):
62 if type(lease.software) == UnmanagedSoftwareEnvironment: 63 return [] 64 65 # This code is the same as the one in vm_scheduler 66 # Should be factored out 67 last_vmrr = lease.get_last_vmrr() 68 vnode_migrations = dict([(vnode, (last_vmrr.nodes[vnode], vmrr.nodes[vnode])) for vnode in vmrr.nodes]) 69 70 mustmigrate = False 71 for vnode in vnode_migrations: 72 if vnode_migrations[vnode][0] != vnode_migrations[vnode][1]: 73 mustmigrate = True 74 break 75 76 if not mustmigrate: 77 return [] 78 79 if get_config().get("migration") == constants.MIGRATE_YES_NOTRANSFER: 80 start = nexttime 81 end = nexttime 82 res = {} 83 migr_rr = DiskImageMigrationResourceReservation(lease, start, end, res, vmrr, vnode_migrations) 84 migr_rr.state = ResourceReservation.STATE_SCHEDULED 85 return [migr_rr] 86 87 # Figure out what migrations can be done simultaneously 88 migrations = [] 89 while len(vnode_migrations) > 0: 90 pnodes = set() 91 migration = {} 92 for vnode in vnode_migrations: 93 origin = vnode_migrations[vnode][0] 94 dest = vnode_migrations[vnode][1] 95 if not origin in pnodes and not dest in pnodes: 96 migration[vnode] = vnode_migrations[vnode] 97 pnodes.add(origin) 98 pnodes.add(dest) 99 for vnode in migration: 100 del vnode_migrations[vnode] 101 migrations.append(migration) 102 103 # Create migration RRs 104 start = max(last_vmrr.post_rrs[-1].end, nexttime) 105 bandwidth = self.resourcepool.info.get_migration_bandwidth() 106 migr_rrs = [] 107 for m in migrations: 108 mb_to_migrate = lease.software.image_size * len(m.keys()) 109 migr_time = estimate_transfer_time(mb_to_migrate, bandwidth) 110 end = start + migr_time 111 res = {} 112 for (origin,dest) in m.values(): 113 resorigin = Capacity([constants.RES_NETOUT]) 114 resorigin.set_quantity(constants.RES_NETOUT, bandwidth) 115 resdest = Capacity([constants.RES_NETIN]) 116 resdest.set_quantity(constants.RES_NETIN, bandwidth) 117 res[origin] = self.slottable.create_resource_tuple_from_capacity(resorigin) 118 res[dest] = self.slottable.create_resource_tuple_from_capacity(resdest) 119 migr_rr = DiskImageMigrationResourceReservation(lease, start, start + migr_time, res, vmrr, m) 120 migr_rr.state = ResourceReservation.STATE_SCHEDULED 121 migr_rrs.append(migr_rr) 122 start = end 123 124 return migr_rrs
125
126 - def estimate_migration_time(self, lease):
127 migration = get_config().get("migration") 128 if migration == constants.MIGRATE_YES: 129 vmrr = lease.get_last_vmrr() 130 images_in_pnode = dict([(pnode,0) for pnode in set(vmrr.nodes.values())]) 131 for (vnode,pnode) in vmrr.nodes.items(): 132 images_in_pnode[pnode] += lease.software.image_size 133 max_to_transfer = max(images_in_pnode.values()) 134 bandwidth = self.resourcepool.info.get_migration_bandwidth() 135 return estimate_transfer_time(max_to_transfer, bandwidth) 136 elif migration == constants.MIGRATE_YES_NOTRANSFER: 137 return TimeDelta(seconds=0)
138
139 - def find_earliest_starting_times(self, lease, nexttime):
140 node_ids = [node.id for node in self.resourcepool.get_nodes()] 141 config = get_config() 142 mechanism = config.get("transfer-mechanism") 143 reusealg = config.get("diskimage-reuse") 144 avoidredundant = config.get("avoid-redundant-transfers") 145 146 if type(lease.software) == UnmanagedSoftwareEnvironment: 147 earliest = {} 148 for node in node_ids: 149 earliest[node] = EarliestStartingTime(nexttime, EarliestStartingTime.EARLIEST_NOPREPARATION) 150 return earliest 151 152 # Figure out earliest times assuming we have to transfer the images 153 transfer_duration = self.__estimate_image_transfer_time(lease, self.imagenode_bandwidth) 154 if mechanism == constants.TRANSFER_UNICAST: 155 transfer_duration *= lease.numnodes 156 start = self.__get_next_transfer_slot(nexttime, transfer_duration) 157 earliest = {} 158 for node in node_ids: 159 earliest[node] = ImageTransferEarliestStartingTime(start + transfer_duration, ImageTransferEarliestStartingTime.EARLIEST_IMAGETRANSFER) 160 earliest[node].transfer_start = start 161 162 # Check if we can reuse images 163 if reusealg == constants.REUSE_IMAGECACHES: 164 nodeswithimg = self.resourcepool.get_nodes_with_reusable_image(lease.software.image_id) 165 for node in nodeswithimg: 166 earliest[node].time = nexttime 167 earliest[node].type = ImageTransferEarliestStartingTime.EARLIEST_REUSE 168 169 170 # Check if we can avoid redundant transfers 171 if avoidredundant: 172 if mechanism == constants.TRANSFER_UNICAST: 173 # Piggybacking not supported if unicasting 174 # each individual image 175 pass 176 if mechanism == constants.TRANSFER_MULTICAST: 177 # We can only piggyback on transfers that haven't started yet 178 transfers = [t for t in self.transfers if t.state == ResourceReservation.STATE_SCHEDULED] 179 for t in transfers: 180 if t.file == lease.software.image_id: 181 start = t.end 182 if start > nexttime: 183 for n in earliest: 184 if start < earliest[n].time: 185 earliest[n].time = start 186 earliest[n].type = ImageTransferEarliestStartingTime.EARLIEST_PIGGYBACK 187 earliest[n].piggybacking_on = t 188 189 return earliest
190
191 - def cancel_preparation(self, lease):
192 toremove = self.__remove_transfers(lease) 193 for t in toremove: 194 t.lease.remove_preparationrr(t) 195 self.slottable.remove_reservation(t) 196 self.__remove_files(lease)
197
198 - def cleanup(self, lease):
199 self.__remove_files(lease)
200 201
202 - def __schedule_deadline(self, lease, vmrr, earliest):
203 config = get_config() 204 reusealg = config.get("diskimage-reuse") 205 avoidredundant = config.get("avoid-redundant-transfers") 206 is_ready = False 207 208 musttransfer = {} 209 mustpool = {} 210 nodeassignment = vmrr.nodes 211 start = lease.start.requested 212 end = lease.start.requested + lease.duration.requested 213 for (vnode, pnode) in nodeassignment.items(): 214 lease_id = lease.id 215 self.logger.debug("Scheduling image transfer of '%s' for vnode %i to physnode %i" % (lease.software.image_id, vnode, pnode)) 216 217 if reusealg == constants.REUSE_IMAGECACHES: 218 if self.resourcepool.exists_reusable_image(pnode, lease.software.image_id, start): 219 self.logger.debug("No need to schedule an image transfer (reusing an image in pool)") 220 mustpool[vnode] = pnode 221 else: 222 self.logger.debug("Need to schedule a transfer.") 223 musttransfer[vnode] = pnode 224 else: 225 self.logger.debug("Need to schedule a transfer.") 226 musttransfer[vnode] = pnode 227 228 if len(musttransfer) == 0: 229 is_ready = True 230 else: 231 try: 232 transfer_rrs = self.__schedule_imagetransfer_edf(lease, musttransfer, earliest) 233 except NotSchedulableException, exc: 234 raise 235 236 # No chance of scheduling exception at this point. It's safe 237 # to add entries to the pools 238 if reusealg == constants.REUSE_IMAGECACHES: 239 for (vnode, pnode) in mustpool.items(): 240 self.resourcepool.add_mapping_to_existing_reusable_image(pnode, lease.diskimage_id, lease.id, vnode, start) 241 self.resourcepool.add_diskimage(pnode, lease.diskimage_id, lease.diskimage_size, lease.id, vnode) 242 243 return transfer_rrs, is_ready
244 245
246 - def __schedule_asap(self, lease, vmrr, earliest):
247 config = get_config() 248 reusealg = config.get("diskimage-reuse") 249 avoidredundant = config.get("avoid-redundant-transfers") 250 251 is_ready = False 252 253 transfer_rrs = [] 254 musttransfer = {} 255 piggybacking = [] 256 for (vnode, pnode) in vmrr.nodes.items(): 257 earliest_type = earliest[pnode].type 258 if earliest_type == ImageTransferEarliestStartingTime.EARLIEST_REUSE: 259 # Add to pool 260 self.logger.debug("Reusing image for V%i->P%i." % (vnode, pnode)) 261 self.resourcepool.add_mapping_to_existing_reusable_image(pnode, lease.software.image_id, lease.id, vnode, vmrr.end) 262 self.resourcepool.add_diskimage(pnode, lease.software.image_id, lease.software.image_size, lease.id, vnode) 263 elif earliest_type == ImageTransferEarliestStartingTime.EARLIEST_PIGGYBACK: 264 # We can piggyback on an existing transfer 265 transfer_rr = earliest[pnode].piggybacking_on 266 transfer_rr.piggyback(lease.id, vnode, pnode) 267 self.logger.debug("Piggybacking transfer for V%i->P%i on existing transfer in lease %i." % (vnode, pnode, transfer_rr.lease.id)) 268 piggybacking.append(transfer_rr) 269 else: 270 # Transfer 271 musttransfer[vnode] = pnode 272 self.logger.debug("Must transfer V%i->P%i." % (vnode, pnode)) 273 274 if len(musttransfer)>0: 275 transfer_rrs = self.__schedule_imagetransfer_fifo(lease, musttransfer, earliest) 276 277 if len(musttransfer)==0 and len(piggybacking)==0: 278 is_ready = True 279 280 return transfer_rrs, is_ready
281 282
283 - def __schedule_imagetransfer_edf(self, lease, musttransfer, earliest):
284 # Estimate image transfer time 285 bandwidth = self.deployment_enact.get_bandwidth() 286 config = get_config() 287 mechanism = config.get("transfer-mechanism") 288 transfer_duration = self.__estimate_image_transfer_time(lease, bandwidth) 289 if mechanism == constants.TRANSFER_UNICAST: 290 transfer_duration *= len(musttransfer) 291 292 # Determine start time 293 start = self.__get_last_transfer_slot(lease.start.requested, transfer_duration) 294 295 res = {} 296 resimgnode = Capacity([constants.RES_NETOUT]) 297 resimgnode.set_quantity(constants.RES_NETOUT, bandwidth) 298 resnode = Capacity([constants.RES_NETIN]) 299 resnode.set_quantity(constants.RES_NETIN, bandwidth) 300 res[self.imagenode.id] = self.slottable.create_resource_tuple_from_capacity(resimgnode) 301 for pnode in musttransfer.values(): 302 res[pnode] = self.slottable.create_resource_tuple_from_capacity(resnode) 303 304 newtransfer = FileTransferResourceReservation(lease, res) 305 newtransfer.deadline = lease.start.requested 306 newtransfer.state = ResourceReservation.STATE_SCHEDULED 307 newtransfer.file = lease.software.image_id 308 newtransfer.start = start 309 newtransfer.end = start + transfer_duration 310 for vnode, pnode in musttransfer.items(): 311 newtransfer.piggyback(lease.id, vnode, pnode) 312 313 bisect.insort(self.transfers, newtransfer) 314 315 return [newtransfer]
316
317 - def __schedule_imagetransfer_fifo(self, lease, musttransfer, earliest):
318 # Estimate image transfer time 319 bandwidth = self.imagenode_bandwidth 320 config = get_config() 321 mechanism = config.get("transfer-mechanism") 322 323 # The starting time is the first available slot, which was 324 # included in the "earliest" dictionary. 325 pnodes = musttransfer.values() 326 start = earliest[pnodes[0]].transfer_start 327 transfer_duration = self.__estimate_image_transfer_time(lease, bandwidth) 328 329 res = {} 330 resimgnode = Capacity([constants.RES_NETOUT]) 331 resimgnode.set_quantity(constants.RES_NETOUT, bandwidth) 332 resnode = Capacity([constants.RES_NETIN]) 333 resnode.set_quantity(constants.RES_NETIN, bandwidth) 334 res[self.imagenode.id] = self.slottable.create_resource_tuple_from_capacity(resimgnode) 335 for n in musttransfer.values(): 336 res[n] = self.slottable.create_resource_tuple_from_capacity(resnode) 337 338 newtransfer = FileTransferResourceReservation(lease, res) 339 newtransfer.start = start 340 if mechanism == constants.TRANSFER_UNICAST: 341 newtransfer.end = start + (len(musttransfer) * transfer_duration) 342 if mechanism == constants.TRANSFER_MULTICAST: 343 newtransfer.end = start + transfer_duration 344 345 newtransfer.deadline = None 346 newtransfer.state = ResourceReservation.STATE_SCHEDULED 347 newtransfer.file = lease.software.image_id 348 for vnode, pnode in musttransfer.items(): 349 newtransfer.piggyback(lease.id, vnode, pnode) 350 351 bisect.insort(self.transfers, newtransfer) 352 353 return [newtransfer]
354 355
356 - def __estimate_image_transfer_time(self, lease, bandwidth):
357 config = get_config() 358 force_transfer_time = config.get("force-imagetransfer-time") 359 if force_transfer_time != None: 360 return force_transfer_time 361 else: 362 return estimate_transfer_time(lease.software.image_size, bandwidth)
363 364
365 - def __get_next_transfer_slot(self, nexttime, required_duration):
366 # This can probably be optimized by using one of the many 367 # "list of holes" algorithms out there 368 if len(self.transfers) == 0: 369 return nexttime 370 elif nexttime + required_duration <= self.transfers[0].start: 371 return nexttime 372 else: 373 for i in xrange(len(self.transfers) - 1): 374 if self.transfers[i].end != self.transfers[i+1].start: 375 hole_duration = self.transfers[i+1].start - self.transfers[i].end 376 if hole_duration >= required_duration: 377 return self.transfers[i].end 378 return self.transfers[-1].end
379 380
381 - def __get_last_transfer_slot(self, deadline, required_duration):
382 # This can probably be optimized by using one of the many 383 # "list of holes" algorithms out there 384 if len(self.transfers) == 0: 385 return deadline - required_duration 386 elif self.transfers[-1].end + required_duration <= deadline: 387 return deadline - required_duration 388 else: 389 for i in xrange(len(self.transfers) - 1, 0, -1): 390 if self.transfers[i].start != self.transfers[i-1].end: 391 hole_duration = self.transfers[i].start - self.transfers[i-1].end 392 if hole_duration >= required_duration: 393 return self.transfers[i].start - required_duration 394 return self.transfers[0].start - required_duration
395
396 - def __remove_transfers(self, lease):
397 toremove = [] 398 for t in self.transfers: 399 for pnode in t.transfers: 400 leases = [l for l, v in t.transfers[pnode]] 401 if lease in leases: 402 newtransfers = [(l, v) for l, v in t.transfers[pnode] if l!=lease] 403 t.transfers[pnode] = newtransfers 404 # Check if the transfer has to be cancelled 405 a = sum([len(l) for l in t.transfers.values()]) 406 if a == 0: 407 toremove.append(t) 408 for t in toremove: 409 self.transfers.remove(t) 410 411 return toremove
412
413 - def __remove_files(self, lease):
414 for vnode, pnode in lease.get_last_vmrr().nodes.items(): 415 self.resourcepool.remove_diskimage(pnode, lease.id, vnode)
416 417 @staticmethod
418 - def _handle_start_filetransfer(sched, lease, rr):
419 sched.logger.debug("LEASE-%i Start of handleStartFileTransfer" % lease.id) 420 lease.print_contents() 421 lease_state = lease.get_state() 422 if lease_state == Lease.STATE_SCHEDULED or lease_state == Lease.STATE_READY: 423 lease.set_state(Lease.STATE_PREPARING) 424 rr.state = ResourceReservation.STATE_ACTIVE 425 # TODO: Enactment 426 else: 427 raise InconsistentLeaseStateError(lease, doing = "starting a file transfer") 428 429 # TODO: Check for piggybacking 430 431 lease.print_contents() 432 sched.logger.debug("LEASE-%i End of handleStartFileTransfer" % lease.id) 433 sched.logger.info("Starting image transfer for lease %i" % (lease.id))
434 435 @staticmethod
436 - def _handle_end_filetransfer(sched, lease, rr):
437 sched.logger.debug("LEASE-%i Start of handleEndFileTransfer" % lease.id) 438 lease.print_contents() 439 lease_state = lease.get_state() 440 if lease_state == Lease.STATE_PREPARING: 441 lease.set_state(Lease.STATE_READY) 442 rr.state = ResourceReservation.STATE_DONE 443 for physnode in rr.transfers: 444 vnodes = rr.transfers[physnode] 445 446 # # Find out timeout of image. It will be the latest end time of all the 447 # # leases being used by that image. 448 # leases = [l for (l, v) in vnodes] 449 # maxend=None 450 # for lease_id in leases: 451 # l = sched.leases.get_lease(lease_id) 452 # end = lease.get_endtime() 453 # if maxend==None or end>maxend: 454 # maxend=end 455 maxend = None 456 # TODO: ENACTMENT: Verify the image was transferred correctly 457 sched._add_diskimages(physnode, rr.file, lease.software.image_size, vnodes, timeout=maxend) 458 else: 459 raise InconsistentLeaseStateError(lease, doing = "ending a file transfer") 460 461 sched.transfers.remove(rr) 462 lease.print_contents() 463 sched.logger.debug("LEASE-%i End of handleEndFileTransfer" % lease.id) 464 sched.logger.info("Completed image transfer for lease %i" % (lease.id))
465
466 - def _handle_start_migrate(self, l, rr):
467 self.logger.debug("LEASE-%i Start of handleStartMigrate" % l.id) 468 l.print_contents() 469 rr.state = ResourceReservation.STATE_ACTIVE 470 l.print_contents() 471 self.logger.debug("LEASE-%i End of handleStartMigrate" % l.id) 472 self.logger.info("Migrating lease %i..." % (l.id))
473
474 - def _handle_end_migrate(self, l, rr):
475 self.logger.debug("LEASE-%i Start of handleEndMigrate" % l.id) 476 l.print_contents() 477 478 for vnode in rr.transfers: 479 origin = rr.transfers[vnode][0] 480 dest = rr.transfers[vnode][1] 481 482 self.resourcepool.remove_diskimage(origin, l.id, vnode) 483 self.resourcepool.add_diskimage(dest, l.software.image_id, l.software.image_size, l.id, vnode) 484 485 rr.state = ResourceReservation.STATE_DONE 486 l.print_contents() 487 self.logger.debug("LEASE-%i End of handleEndMigrate" % l.id) 488 self.logger.info("Migrated lease %i..." % (l.id))
489
490 - def _add_diskimages(self, pnode_id, diskimage_id, diskimage_size, vnodes, timeout):
491 self.logger.debug("Adding image for leases=%s in nod_id=%i" % (vnodes, pnode_id)) 492 493 config = get_config() 494 reusealg = config.get("diskimage-reuse") 495 if reusealg == constants.REUSE_IMAGECACHES: 496 maxcachesize = config.get("diskimage-cache-size") 497 else: 498 maxcachesize = None 499 500 pnode = self.resourcepool.get_node(pnode_id) 501 502 if reusealg == constants.REUSE_NONE: 503 for (lease_id, vnode) in vnodes: 504 self.resourcepool.add_diskimage(pnode_id, diskimage_id, diskimage_size, lease_id, vnode) 505 elif reusealg == constants.REUSE_IMAGECACHES: 506 # Sometimes we might find that the image is already deployed 507 # (although unused). In that case, don't add another copy to 508 # the pool. Just "reactivate" it. 509 if pnode.exists_reusable_image(diskimage_id): 510 for (lease_id, vnode) in vnodes: 511 pnode.add_mapping_to_existing_reusable_image(diskimage_id, lease_id, vnode, timeout) 512 else: 513 if maxcachesize == constants.CACHESIZE_UNLIMITED: 514 can_add_to_cache = True 515 else: 516 # We may have to remove images from the cache 517 cachesize = pnode.get_reusable_images_size() 518 reqsize = cachesize + diskimage_size 519 if reqsize > maxcachesize: 520 # Have to shrink cache 521 desiredsize = maxcachesize - diskimage_size 522 self.logger.debug("Adding the image would make the size of pool in node %i = %iMB. Will try to bring it down to %i" % (pnode_id, reqsize, desiredsize)) 523 pnode.print_files() 524 success = pnode.purge_downto(maxcachesize) 525 if not success: 526 can_add_to_cache = False 527 else: 528 can_add_to_cache = True 529 else: 530 can_add_to_cache = True 531 532 if can_add_to_cache: 533 self.resourcepool.add_reusable_image(pnode_id, diskimage_id, diskimage_size, vnodes, timeout) 534 else: 535 # This just means we couldn't add the image 536 # to the pool. We will have to make do with just adding the tainted images. 537 self.logger.debug("Unable to add to pool. Must create individual disk images directly instead.") 538 539 # Besides adding the image to the cache, we need to create a separate image for 540 # this specific lease 541 for (lease_id, vnode) in vnodes: 542 self.resourcepool.add_diskimage(pnode_id, diskimage_id, diskimage_size, lease_id, vnode) 543 544 pnode.print_files()
545
546 -class FileTransferResourceReservation(ResourceReservation):
547 - def __init__(self, lease, res, start=None, end=None):
548 ResourceReservation.__init__(self, lease, start, end, res) 549 self.deadline = None 550 self.file = None 551 # Dictionary of physnode -> [ (lease_id, vnode)* ] 552 self.transfers = {}
553
554 - def print_contents(self, loglevel="VDEBUG"):
555 ResourceReservation.print_contents(self, loglevel) 556 logger = logging.getLogger("LEASES") 557 logger.log(loglevel, "Type : FILE TRANSFER") 558 logger.log(loglevel, "Deadline : %s" % self.deadline) 559 logger.log(loglevel, "File : %s" % self.file) 560 logger.log(loglevel, "Transfers : %s" % self.transfers)
561
562 - def piggyback(self, lease_id, vnode, physnode):
563 if self.transfers.has_key(physnode): 564 self.transfers[physnode].append((lease_id, vnode)) 565 else: 566 self.transfers[physnode] = [(lease_id, vnode)]
567
568 - def is_preemptible(self):
569 return False
570
571 - def __cmp__(self, rr):
572 return cmp(self.start, rr.start)
573
574 -class ImageTransferEarliestStartingTime(EarliestStartingTime):
575 EARLIEST_IMAGETRANSFER = 2 576 EARLIEST_REUSE = 3 577 EARLIEST_PIGGYBACK = 4 578
579 - def __init__(self, time, type):
580 EarliestStartingTime.__init__(self, time, type) 581 self.transfer_start = None 582 self.piggybacking_on = None
583
584 -class DiskImageMigrationResourceReservation(MigrationResourceReservation):
585 - def __init__(self, lease, start, end, res, vmrr, transfers):
586 MigrationResourceReservation.__init__(self, lease, start, end, res, vmrr, transfers)
587
588 - def print_contents(self, loglevel=constants.LOGLEVEL_VDEBUG):
589 logger = logging.getLogger("LEASES") 590 logger.log(loglevel, "Type : DISK IMAGE MIGRATION") 591 logger.log(loglevel, "Transfers : %s" % self.transfers) 592 ResourceReservation.print_contents(self, loglevel)
593