def _compute_storage_score(self, disks): best_effort = False if not disks: return self.MAX_SCORE, [] selector = DatastoreSelector.init_datastore_selector( self._datastore_manager, self._placeable_datastores()) disks_placement = DisksPlacement(disks, selector) # Place constraint disks first place_result = self._constrainted_placement.place(disks_placement) if place_result.result == PlaceResultCode.NO_SUCH_RESOURCE: raise NoSuchResourceException( ResourceType.DISK, "Disk placement failed.") elif place_result.result == \ PlaceResultCode.NOT_ENOUGH_DATASTORE_CAPACITY: raise NotEnoughDatastoreCapacityException() # Try optimal for unconstrainted disks first place_result = self._optimal_placement.place( place_result.disks_placement) if place_result.result == \ PlaceResultCode.NOT_ENOUGH_DATASTORE_CAPACITY: # If it doesn't work then try best effort place_result = self._best_effort_placement.place( place_result.disks_placement) best_effort = True # Still NOT_ENOUGH_SYSTEM_RESOURCE then have to give up. if place_result.result == \ PlaceResultCode.NOT_ENOUGH_DATASTORE_CAPACITY: raise NotEnoughDatastoreCapacityException() # Congrat! Successful placement. # Count reserved storage free = place_result.disks_placement.selector.total_free_space() total = place_result.disks_placement.selector.total_space() ratio = float(total-free+self._storage_reserved()) / total # If we find an optimal data store (that contains the image needed) # and the the data stores will not cross the free space threshold, # on admitting the VM, return a high score, so data store score will # not be used, if at all. if (ratio < self.FREESPACE_THRESHOLD and not best_effort): return self.MAX_SCORE, place_result.disks_placement.placement_list # Compute score score = self._score(ratio, True, ResourceType.DATASTORE) # If an optimal placement could not be achieved reduce the score for # this host if best_effort: score /= self.NOT_OPTIMAL_DIVIDE_FACTOR return score, place_result.disks_placement.placement_list
def test_constraint_place_engine_constraint_violated(self): # Create constraint place engine image_datastore = "ds1" image_datastores = [{"name": image_datastore, "used_for_vms": True}] option = PlacementOption(1, 1, image_datastores) ds_map = {image_datastore: DatastoreInfo(5, 0)} ds_mgr = self.create_datastore_manager(ds_map, image_datastores) engine = ConstraintDiskPlaceEngine(ds_mgr, option) ds = engine.placeable_datastores() selector = DatastoreSelector.init_datastore_selector(ds_mgr, ds) # Try place disks = [ Disk(disk_id="ds1", capacity_gb=1, constraints=[ ResourceConstraint(ResourceConstraintType.DATASTORE, ["ds2"]) ]), ] place_result = engine.place(DisksPlacement(disks, selector)) # Verify place result assert_that(place_result.result, equal_to(PlaceResultCode.NO_SUCH_RESOURCE))
def test_optimal_place_engine(self, result, ratio, disk_sizes, use_image_ds): # Create optimal place engine image_datastore = "datastore_id_1" image_datastores = [{"name": image_datastore, "used_for_vms": use_image_ds}] option = PlacementOption(1, 1, image_datastores) ds_map = {"datastore_id_1": DatastoreInfo(1 * 1024, 0), "datastore_id_2": DatastoreInfo(2 * 1024, 0), "datastore_id_3": DatastoreInfo(3 * 1024, 0)} ds_mgr = self.create_datastore_manager(ds_map, image_datastore) engine = OptimalPlaceEngine(ds_mgr, option) ds = engine.placeable_datastores() selector = DatastoreSelector.init_datastore_selector(ds_mgr, ds) disks_placement = DisksPlacement(self.create_disks(disk_sizes), selector) # Verify place result place_result = engine.place(disks_placement) assert_that(place_result.result, equal_to(result)) assert_that(place_result.disks_placement.selector.ratio(), equal_to(ratio)) # Verify placements if disk_sizes and place_result.result == PlaceResultCode.OK: placement_list = place_result.disks_placement.placement_list assert_that(placement_list, has_length(1)) assert_that(placement_list[0].type, equal_to(AgentResourcePlacement.DISK)) assert_that(placement_list[0].container_id, equal_to("datastore_id_3"))
def test_best_effort_place_engine(self, result, ratio, disk_sizes, places, use_image_ds): # Create best effort place engine image_datastore = "ds1" image_datastores = [{"name": image_datastore, "used_for_vms": use_image_ds}] option = PlacementOption(1, 1, image_datastores) ds_map = {image_datastore: DatastoreInfo(10, 0), "ds2": DatastoreInfo(20, 0), "ds3": DatastoreInfo(30, 0)} ds_mgr = self.create_datastore_manager(ds_map, image_datastore) engine = BestEffortPlaceEngine(ds_mgr, option) ds = engine.placeable_datastores() selector = DatastoreSelector.init_datastore_selector(ds_mgr, ds) disks_placement = DisksPlacement(self.create_disks(disk_sizes), selector) # Try place place_result = engine.place(disks_placement) # Verify place result assert_that(place_result.result, equal_to(result)) # Verify placements if disk_sizes and place_result.result == PlaceResultCode.OK: assert_that(place_result.disks_placement.selector.ratio(), equal_to(ratio)) for i, place in enumerate(places): placement_list = place_result.disks_placement.placement_list assert_that(placement_list[0].type, equal_to(AgentResourcePlacement.DISK)) assert_that(placement_list[i].container_id, equal_to(place))
def _compute_storage_score(self, disks): best_effort = False if not disks: return self.MAX_SCORE, [] selector = DatastoreSelector.init_datastore_selector( self._datastore_manager, self._placeable_datastores()) disks_placement = DisksPlacement(disks, selector) # Place constraint disks first place_result = self._constrainted_placement.place(disks_placement) if place_result.result == PlaceResultCode.NO_SUCH_RESOURCE: raise NoSuchResourceException(ResourceType.DISK, "Disk placement failed.") elif place_result.result == \ PlaceResultCode.NOT_ENOUGH_DATASTORE_CAPACITY: raise NotEnoughDatastoreCapacityException() # Try optimal for unconstrainted disks first place_result = self._optimal_placement.place( place_result.disks_placement) if place_result.result == \ PlaceResultCode.NOT_ENOUGH_DATASTORE_CAPACITY: # If it doesn't work then try best effort place_result = self._best_effort_placement.place( place_result.disks_placement) best_effort = True # Still NOT_ENOUGH_SYSTEM_RESOURCE then have to give up. if place_result.result == \ PlaceResultCode.NOT_ENOUGH_DATASTORE_CAPACITY: raise NotEnoughDatastoreCapacityException() # Congrat! Successful placement. # Count reserved storage free = place_result.disks_placement.selector.total_free_space() total = place_result.disks_placement.selector.total_space() ratio = float(total - free + self._storage_reserved()) / total # If we find an optimal data store (that contains the image needed) # and the the data stores will not cross the free space threshold, # on admitting the VM, return a high score, so data store score will # not be used, if at all. if (ratio < self.FREESPACE_THRESHOLD and not best_effort): return self.MAX_SCORE, place_result.disks_placement.placement_list # Compute score score = self._score(ratio, True, ResourceType.DATASTORE) # If an optimal placement could not be achieved reduce the score for # this host if best_effort: score /= self.NOT_OPTIMAL_DIVIDE_FACTOR return score, place_result.disks_placement.placement_list
def test_constraint_place_engine(self): # Create constraint place engine image_datastore = "ds1" image_datastores = [{"name": image_datastore, "used_for_vms": True}] option = PlacementOption(1, 1, image_datastores) ds_map = { image_datastore: DatastoreInfo(10, 0), "ds2": DatastoreInfo(20, 0), "ds3": DatastoreInfo(30, 0) } ds_mgr = self.create_datastore_manager(ds_map, image_datastore) engine = ConstraintDiskPlaceEngine(ds_mgr, option) ds = engine.placeable_datastores() selector = DatastoreSelector.init_datastore_selector(ds_mgr, ds) # Try place disks = [ Disk(disk_id="disk", capacity_gb=5, constraints=[]), Disk(disk_id="disk-in-ds1", capacity_gb=5, constraints=[ ResourceConstraint(ResourceConstraintType.DATASTORE, ["ds1"]) ]), Disk(disk_id="disk-in-ds2", capacity_gb=5, constraints=[ ResourceConstraint(ResourceConstraintType.DATASTORE, ["ds2"]) ]), Disk(disk_id="disk-in-ds3", capacity_gb=5, constraints=[ ResourceConstraint(ResourceConstraintType.DATASTORE, ["ds3"]) ]), Disk(capacity_gb=5, constraints=[]), ] disks_placement = DisksPlacement(disks, selector) place_result = engine.place(disks_placement) # Verify place result assert_that(place_result.result, equal_to(PlaceResultCode.OK)) # Verify placement list and unplaced list disks_placement = place_result.disks_placement assert_that(disks_placement.placement_list, has_length(3)) assert_that(disks_placement.disks, has_length(2)) assert_that([d.resource_id for d in disks_placement.placement_list], contains_inanyorder("disk-in-ds1", "disk-in-ds2", "disk-in-ds3")) for placement in disks_placement.placement_list: assert_that(placement.type, equal_to(AgentResourcePlacement.DISK)) assert_that("disk-in-" + placement.container_id, equal_to(placement.resource_id))
def test_constraint_place_engine(self): # Create constraint place engine image_datastore = "ds1" image_datastores = [{"name": image_datastore, "used_for_vms": True}] option = PlacementOption(1, 1, image_datastores) ds_map = {image_datastore: DatastoreInfo(10, 0), "ds2": DatastoreInfo(20, 0), "ds3": DatastoreInfo(30, 0)} ds_mgr = self.create_datastore_manager(ds_map, image_datastore) engine = ConstraintDiskPlaceEngine(ds_mgr, option) ds = engine.placeable_datastores() selector = DatastoreSelector.init_datastore_selector(ds_mgr, ds) # Try place disks = [ Disk(disk_id="disk", capacity_gb=5, constraints=[]), Disk(disk_id="disk-in-ds1", capacity_gb=5, constraints=[ ResourceConstraint( ResourceConstraintType.DATASTORE, ["ds1"])]), Disk(disk_id="disk-in-ds2", capacity_gb=5, constraints=[ ResourceConstraint( ResourceConstraintType.DATASTORE, ["ds2"])]), Disk(disk_id="disk-in-ds3", capacity_gb=5, constraints=[ ResourceConstraint( ResourceConstraintType.DATASTORE, ["ds3"])]), Disk(capacity_gb=5, constraints=[]), ] disks_placement = DisksPlacement(disks, selector) place_result = engine.place(disks_placement) # Verify place result assert_that(place_result.result, equal_to(PlaceResultCode.OK)) # Verify placement list and unplaced list disks_placement = place_result.disks_placement assert_that(disks_placement.placement_list, has_length(3)) assert_that(disks_placement.disks, has_length(2)) assert_that([d.resource_id for d in disks_placement.placement_list], contains_inanyorder("disk-in-ds1", "disk-in-ds2", "disk-in-ds3")) for placement in disks_placement.placement_list: assert_that(placement.type, equal_to(AgentResourcePlacement.DISK)) assert_that("disk-in-" + placement.container_id, equal_to(placement.resource_id))
def test_constraint_place_engine_constraint_violated(self): # Create constraint place engine image_datastore = "ds1" image_datastores = [{"name": image_datastore, "used_for_vms": True}] option = PlacementOption(1, 1, image_datastores) ds_map = {image_datastore: DatastoreInfo(5, 0)} ds_mgr = self.create_datastore_manager(ds_map, image_datastores) engine = ConstraintDiskPlaceEngine(ds_mgr, option) ds = engine.placeable_datastores() selector = DatastoreSelector.init_datastore_selector(ds_mgr, ds) # Try place disks = [ Disk(disk_id="ds1", capacity_gb=1, constraints=[ResourceConstraint( ResourceConstraintType.DATASTORE, ["ds2"])]), ] place_result = engine.place(DisksPlacement(disks, selector)) # Verify place result assert_that(place_result.result, equal_to(PlaceResultCode.NO_SUCH_RESOURCE))
def test_optimal_place_engine(self, result, ratio, disk_sizes, use_image_ds): # Create optimal place engine image_datastore = "datastore_id_1" image_datastores = [{ "name": image_datastore, "used_for_vms": use_image_ds }] option = PlacementOption(1, 1, image_datastores) ds_map = { "datastore_id_1": DatastoreInfo(1 * 1024, 0), "datastore_id_2": DatastoreInfo(2 * 1024, 0), "datastore_id_3": DatastoreInfo(3 * 1024, 0) } ds_mgr = self.create_datastore_manager(ds_map, image_datastore) engine = OptimalPlaceEngine(ds_mgr, option) ds = engine.placeable_datastores() selector = DatastoreSelector.init_datastore_selector(ds_mgr, ds) disks_placement = DisksPlacement(self.create_disks(disk_sizes), selector) # Verify place result place_result = engine.place(disks_placement) assert_that(place_result.result, equal_to(result)) assert_that(place_result.disks_placement.selector.ratio(), equal_to(ratio)) # Verify placements if disk_sizes and place_result.result == PlaceResultCode.OK: placement_list = place_result.disks_placement.placement_list assert_that(placement_list, has_length(1)) assert_that(placement_list[0].type, equal_to(AgentResourcePlacement.DISK)) assert_that(placement_list[0].container_id, equal_to("datastore_id_3"))
def test_best_effort_place_engine(self, result, ratio, disk_sizes, places, use_image_ds): # Create best effort place engine image_datastore = "ds1" image_datastores = [{ "name": image_datastore, "used_for_vms": use_image_ds }] option = PlacementOption(1, 1, image_datastores) ds_map = { image_datastore: DatastoreInfo(10, 0), "ds2": DatastoreInfo(20, 0), "ds3": DatastoreInfo(30, 0) } ds_mgr = self.create_datastore_manager(ds_map, image_datastore) engine = BestEffortPlaceEngine(ds_mgr, option) ds = engine.placeable_datastores() selector = DatastoreSelector.init_datastore_selector(ds_mgr, ds) disks_placement = DisksPlacement(self.create_disks(disk_sizes), selector) # Try place place_result = engine.place(disks_placement) # Verify place result assert_that(place_result.result, equal_to(result)) # Verify placements if disk_sizes and place_result.result == PlaceResultCode.OK: assert_that(place_result.disks_placement.selector.ratio(), equal_to(ratio)) for i, place in enumerate(places): placement_list = place_result.disks_placement.placement_list assert_that(placement_list[0].type, equal_to(AgentResourcePlacement.DISK)) assert_that(placement_list[i].container_id, equal_to(place))