/** {@inheritDoc} */ @Override public synchronized void resourceOffers(SchedulerDriver schedulerDriver, List<Protos.Offer> offers) { log.log(Level.FINE, "Offers resources: {0}", offers.size()); for (Protos.Offer offer : offers) { IgniteTask igniteTask = checkOffer(offer); // Decline offer which doesn't match by mem or cpu. if (igniteTask == null) { schedulerDriver.declineOffer(offer.getId()); continue; } // Generate a unique task ID. Protos.TaskID taskId = Protos.TaskID.newBuilder() .setValue(Integer.toString(taskIdGenerator.incrementAndGet())).build(); log.log(Level.INFO, "Launching task: {0}", igniteTask); // Create task to run. Protos.TaskInfo task = createTask(offer, igniteTask, taskId); try { schedulerDriver.launchTasks(Collections.singletonList(offer.getId()), Collections.singletonList(task), Protos.Filters.newBuilder().setRefuseSeconds(1).build()); } catch (RuntimeException e) { log.log(Level.SEVERE, "Failed launch task. Task id: {0}. Task info: {1}", new Object[]{taskId, task, e}); throw e; } tasks.put(taskId.getValue(), igniteTask); } }
.addVariables(Protos.Environment.Variable.newBuilder() .setName("IGNITE_TCP_DISCOVERY_ADDRESSES") .setValue(getAddress(offer.getHostname()))) .addVariables(Protos.Environment.Variable.newBuilder() .setName("JVM_OPTS") .setName("Ignite node " + taskId.getValue()) .setTaskId(taskId) .setSlaveId(offer.getSlaveId()) .setCommand(builder) .addResources(Protos.Resource.newBuilder()
&& clusterProps.hostnameConstraint().matcher(offer.getHostname()).matches()) return null; for (Protos.Resource resource : offer.getResourcesList()) { if (resource.getName().equals(CPU)) { if (resource.getType().equals(Protos.Value.Type.SCALAR)) log.log(Level.FINE, "Offer not sufficient for slave request: {0}", offer.getResourcesList()); log.log(Level.FINE, "Offer not sufficient for slave request: {0}", offer.getResourcesList()); return new IgniteTask(offer.getHostname(), cpus, mem, disk); else { log.log(Level.FINE, "Offer not sufficient for slave request: {0}", offer.getResourcesList());
OfferResponse response = defaultScheduler.offers(Collections.singletonList(offer1)); Assert.assertEquals(9, response.recommendations.size()); Assert.assertEquals(offer1.getId(), response.recommendations.iterator().next().getOfferId()); Protos.Resource mem = ResourceTestUtils.getReservedMem(1.0, UUID.randomUUID().toString()); Protos.Offer offerA = Protos.Offer.newBuilder(getSufficientOfferForTaskA()) .addAllResources(response.recommendations.stream() .filter(rec -> rec.getOperation().isPresent()) .addResources(mem) .build(); Protos.Offer offerB = Protos.Offer.newBuilder(getSufficientOfferForTaskB()) .addAllResources(response.recommendations.stream() .filter(rec -> rec.getOperation().isPresent()) .addResources(mem) .build(); Protos.Offer offerC = Protos.Offer.newBuilder(getSufficientOfferForTaskB()) .addAllResources(response.recommendations.stream() .filter(rec -> rec.getOperation().isPresent()) Assert.assertEquals(new HashSet<>(Arrays.asList(offerA.getId(), offerB.getId())), response.recommendations.stream().map(r -> r.getOfferId()).distinct().collect(Collectors.toSet()));
List<Range> ports = null; for (Resource resource : offer.getResourcesList()) { String resourceRole = resource.getRole(); String expectedRole = mesosCloud.getRole(); offer.getResourcesList().toString() + "\n" + offer.getAttributesList().toString() + "\nRequested for Jenkins slave:\n" + " cpus: " + requestedCpus + "\n" +
Protos.Offer.Builder offerBuilder = Protos.Offer.newBuilder().setHostname(hostname); offerBuilder.getIdBuilder().setValue(UUID.randomUUID().toString()); offerBuilder.getFrameworkIdBuilder().setValue("test-framework-id");
Collection<Protos.Resource> goodResources = new ArrayList<>(); Collection<Protos.Resource> badResources = new ArrayList<>(); for (Protos.Resource resource : offer.getResourcesList()) { if (ResourceUtils.isProcessable(resource, frameworkRolesWhitelist)) { goodResources.add(resource); "Filtered {} resources from offer {}:", badResources.size(), offer.getId().getValue()); for (Protos.Resource badResource : badResources) { LOGGER.info(" {}", TextFormat.shortDebugString(badResource)); return offer.toBuilder() .clearResources() .addAllResources(goodResources)
double mem = -1; for (Resource resource : offer.getResourcesList()) { if (resource.getName().equals("cpus")) { if (resource.getType().equals(Value.Type.SCALAR)) { LOGGER.info( "Offer not sufficient for slave request:\n" + offer.getResourcesList().toString() + "\nRequested for Gitlab slave:\n" + " cpus: " + requestedCpus + "\n"
.setName("task " + taskId.getValue()) .setTaskId(taskId) .setSlaveId(offer.getSlaveId()) .setCommand(commandBuilder.build()); double diskNeeded = request.request.diskNeeded; for (Resource r : offer.getResourcesList()) { if (r.getName().equals("cpus") && cpusNeeded > 0) { double cpus = Math.min(r.getScalar().getValue(), cpusNeeded);
Assert.assertEquals(UnexpectedResourcesResponse.Result.PROCESSED, response.result); Assert.assertEquals(1, response.offerResources.size()); Assert.assertEquals(offer.getResourcesList(), response.offerResources.iterator().next().getResources());
public void add(Protos.Offer offer) { assert offer.getSlaveId().equals(slaveID) && offer.getHostname().equals(hostname); offerList.add(offer); for (Protos.Resource r : offer.getResourcesList()) { ResourceType resourceType = ResourceType.of(r.getName()); ReservationType reservationType = (r.getRole().equals("*")) ?
@Test public void testSetGetOfferAttributes() { Protos.Offer.Builder offerBuilder = Protos.Offer.newBuilder() .setId(TestConstants.OFFER_ID) .setFrameworkId(TestConstants.FRAMEWORK_ID) .setSlaveId(TestConstants.AGENT_ID) .setHostname(TestConstants.HOSTNAME); Protos.Attribute.Builder attrBuilder = offerBuilder.addAttributesBuilder().setName("1").setType(Protos.Value.Type.RANGES); attrBuilder.getRangesBuilder().addRangeBuilder().setBegin(5).setEnd(6); attrBuilder.getRangesBuilder().addRangeBuilder().setBegin(10).setEnd(12); attrBuilder = offerBuilder.addAttributesBuilder().setName("2").setType(Protos.Value.Type.SCALAR); attrBuilder.getScalarBuilder().setValue(123.4567); attrBuilder = offerBuilder.addAttributesBuilder().setName("3").setType(Protos.Value.Type.SET); attrBuilder.getSetBuilder().addItem("foo").addItem("bar").addItem("baz"); attrBuilder = offerBuilder.addAttributesBuilder().setName("4").setType(Protos.Value.Type.RANGES); attrBuilder.getRangesBuilder().addRangeBuilder().setBegin(7).setEnd(8); attrBuilder.getRangesBuilder().addRangeBuilder().setBegin(10).setEnd(12); Assert.assertTrue(new TaskLabelReader(getTestTaskInfo()).getOfferAttributeStrings().isEmpty()); Protos.TaskInfo.Builder tb = getTestTaskInfo().toBuilder(); tb.setLabels(new TaskLabelWriter(tb).setOfferAttributes(offerBuilder.build()).toProto()); List<String> expectedStrings = new ArrayList<>(); expectedStrings.add("1:[5-6,10-12]"); expectedStrings.add("2:123.457"); expectedStrings.add("3:{foo,bar,baz}"); expectedStrings.add("4:[7-8,10-12]"); Assert.assertEquals(expectedStrings, new TaskLabelReader(tb).getOfferAttributeStrings()); tb.setLabels(new TaskLabelWriter(tb).setOfferAttributes(offerBuilder.clearAttributes().build()).toProto()); Assert.assertTrue(new TaskLabelReader(tb.build()).getOfferAttributeStrings().isEmpty()); }
@Test public void testPlanCompletes() throws Exception { Protos.Offer offer = OfferTestUtils.getOffer(Arrays.asList( RESERVED_RESOURCE_1, RESERVED_RESOURCE_2, RESERVED_RESOURCE_3)); UninstallScheduler uninstallScheduler = getUninstallScheduler(); // Invoke getClientStatus so that plan status is correctly processed before offers are passed: Assert.assertEquals(ClientStatusResponse.launching(true), uninstallScheduler.getClientStatus()); uninstallScheduler.offers(Collections.singletonList(offer)); // Verify that scheduler doesn't expect _1/_2/_3. It then expects that they have been cleaned: UnexpectedResourcesResponse response = uninstallScheduler.getUnexpectedResources(Collections.singletonList(offer)); Assert.assertEquals(UnexpectedResourcesResponse.Result.PROCESSED, response.result); Assert.assertEquals(1, response.offerResources.size()); Assert.assertEquals(offer.getResourcesList(), response.offerResources.iterator().next().getResources()); Plan plan = getUninstallPlan(uninstallScheduler); List<Status> expected = Arrays.asList(Status.COMPLETE, Status.COMPLETE, Status.COMPLETE, Status.COMPLETE, Status.PENDING); Assert.assertEquals(plan.toString(), expected, getStepStatuses(plan)); // Turn the crank once to prepare the deregistration Step Assert.assertEquals(ClientStatusResponse.launching(true), uninstallScheduler.getClientStatus()); uninstallScheduler.offers(Collections.singleton(getOffer())); expected = Arrays.asList(Status.COMPLETE, Status.COMPLETE, Status.COMPLETE, Status.COMPLETE, Status.PREPARED); Assert.assertEquals(plan.toString(), expected, getStepStatuses(plan)); // Advertise an UNINSTALLED state so that upstream will clean us up and call unregistered(): Assert.assertEquals(ClientStatusResponse.readyToRemove(), uninstallScheduler.getClientStatus()); // Deregistration completes only after we've told the scheduler that it's unregistered uninstallScheduler.unregistered(); expected = Arrays.asList(Status.COMPLETE, Status.COMPLETE, Status.COMPLETE, Status.COMPLETE, Status.COMPLETE); Assert.assertEquals(plan.toString(), expected, getStepStatuses(plan)); Assert.assertTrue(plan.isComplete()); }
@Test public void testUninstallStepsComplete() throws Exception { Protos.Offer offer = OfferTestUtils.getOffer(Arrays.asList(RESERVED_RESOURCE_1, RESERVED_RESOURCE_2)); UninstallScheduler uninstallScheduler = getUninstallScheduler(); // Invoke getClientStatus so that plan status is correctly processed before offers are passed: Assert.assertEquals(ClientStatusResponse.launching(true), uninstallScheduler.getClientStatus()); uninstallScheduler.offers(Collections.singletonList(offer)); // Verify that scheduler doesn't expect _1 and _2. It then expects that they have been cleaned: UnexpectedResourcesResponse response = uninstallScheduler.getUnexpectedResources(Collections.singletonList(offer)); Assert.assertEquals(UnexpectedResourcesResponse.Result.PROCESSED, response.result); Assert.assertEquals(1, response.offerResources.size()); Assert.assertEquals(offer.getResourcesList(), response.offerResources.iterator().next().getResources()); // Check that _1 and _2 are now marked as complete, while _3 is still prepared: Plan plan = getUninstallPlan(uninstallScheduler); List<Status> expected = Arrays.asList(Status.COMPLETE, Status.COMPLETE, Status.COMPLETE, Status.PREPARED, Status.PENDING); Assert.assertEquals(plan.toString(), expected, getStepStatuses(plan)); // Invoke getClientStatus so that plan status is correctly processed before offers are passed. // Shouldn't see any new work since all the uninstall steps were considered candidates up-front. Assert.assertEquals(ClientStatusResponse.launching(false), uninstallScheduler.getClientStatus()); offer = OfferTestUtils.getOffer(Collections.singletonList(RESERVED_RESOURCE_3)); uninstallScheduler.offers(Collections.singletonList(offer)); // Verify that scheduler doesn't expect _3. It then expects that it has been cleaned: response = uninstallScheduler.getUnexpectedResources(Collections.singletonList(offer)); Assert.assertEquals(UnexpectedResourcesResponse.Result.PROCESSED, response.result); Assert.assertEquals(1, response.offerResources.size()); Assert.assertEquals(offer.getResourcesList(), response.offerResources.iterator().next().getResources()); expected = Arrays.asList(Status.COMPLETE, Status.COMPLETE, Status.COMPLETE, Status.COMPLETE, Status.PENDING); Assert.assertEquals(expected, getStepStatuses(plan)); }
@VisibleForTesting SortedSet<Long> findPortsToUse(Offer offer, int maxCount) { SortedSet<Long> portsToUse = new TreeSet<Long>(); List<Value.Range> portRangesList = null; // Locate the port resource in the offer for (Resource resource : offer.getResourcesList()) { if (resource.getName().equals(PORT_RESOURCE_NAME)) { portRangesList = resource.getRanges().getRangeList(); break; } } LOGGER.fine("portRangesList=" + portRangesList); /** * We need to find maxCount ports to use. * We are provided a list of port ranges to use * We are assured by the offer check that we have enough ports to use */ // Check this port range for ports that we can use if (portRangesList != null) { for (Value.Range currentPortRange : portRangesList) { // Check each port until we reach the end of the current range long begin = currentPortRange.getBegin(); long end = currentPortRange.getEnd(); for (long candidatePort = begin; candidatePort <= end && portsToUse.size() < maxCount; candidatePort++) { portsToUse.add(candidatePort); } } } return portsToUse; }
/** * Checks whether the cloud Mesos slave attributes match those from the Mesos offer. * * @param offer Mesos offer data object. * @return true if all the offer attributes match and false if not. */ private boolean slaveAttributesMatch(Offer offer, JSONObject slaveAttributes) { //Accept any and all Mesos slave offers by default. boolean slaveTypeMatch = true; //Collect the list of attributes from the offer as key-value pairs Map<String, String> attributesMap = new HashMap<String, String>(); for (Attribute attribute : offer.getAttributesList()) { attributesMap.put(attribute.getName(), attribute.getText().getValue()); } if (slaveAttributes != null && slaveAttributes.size() > 0) { //Iterate over the cloud attributes to see if they exist in the offer attributes list. Iterator iterator = slaveAttributes.keys(); while (iterator.hasNext()) { String key = (String) iterator.next(); //If there is a single absent attribute then we should reject this offer. if (!(attributesMap.containsKey(key) && attributesMap.get(key).toString().equals(slaveAttributes.getString(key)))) { slaveTypeMatch = false; break; } } } return slaveTypeMatch; }
/** * All offers in each batch of offers will be either be launched or declined. */ @Override @SuppressWarnings("checkstyle:hiddenfield") public void resourceOffers(final SchedulerDriver driver, final List<Protos.Offer> offers) { final Map<String, NodeDescriptorEventImpl.Builder> nodeDescriptorEvents = new HashMap<>(); for (final Offer offer : offers) { if (nodeDescriptorEvents.get(offer.getSlaveId().getValue()) == null) { nodeDescriptorEvents.put(offer.getSlaveId().getValue(), NodeDescriptorEventImpl.newBuilder() .setIdentifier(offer.getSlaveId().getValue()) .setHostName(offer.getHostname()) .setPort(this.mesosSlavePort) .setMemorySize(getMemory(offer))); } else { final NodeDescriptorEventImpl.Builder builder = nodeDescriptorEvents.get(offer.getSlaveId().getValue()); builder.setMemorySize(builder.build().getMemorySize() + getMemory(offer)); } this.offers.put(offer.getId().getValue(), offer); } for (final NodeDescriptorEventImpl.Builder ndpBuilder : nodeDescriptorEvents.values()) { this.reefEventHandlers.onNodeDescriptor(ndpBuilder.build()); } if (outstandingRequests.size() > 0) { doResourceRequest(outstandingRequests.remove()); } }
/** * Returns the resources which are not expected by this service. When uninstalling, all resources are unexpected. * The {@link UninstallScheduler} just keeps track of them on its 'checklist' as they are removed. */ @Override public UnexpectedResourcesResponse getUnexpectedResources(Collection<Protos.Offer> unusedOffers) { Collection<OfferResources> unexpected = unusedOffers.stream() .map(offer -> new OfferResources(offer).addAll(offer.getResourcesList().stream() // Omit any unreserved resources, and any unrefined pre-reserved resources. // In addition, checking for a valid resource_id label is a good sanity check to avoid // potentially unreserving any resources that weren't originally created by the SDK. // This is in addition to separate filtering in FrameworkScheduler of reserved Marathon volumes. .filter(resource -> ResourceUtils.hasResourceId(resource)) .collect(Collectors.toList()))) .collect(Collectors.toList()); try { recorder.recordCleanupOrUninstall(unexpected); } catch (Exception e) { // Failed to record the upcoming dereservation. Don't return the resources as unexpected until we can record // the dereservation. logger.error("Failed to record unexpected resources", e); return UnexpectedResourcesResponse.failed(Collections.emptyList()); } return UnexpectedResourcesResponse.processed(unexpected); }
private void parseOffer(Offer offer) { // Pull out the cpus, memory, disk, and 2 ports from the offer. for (Resource resource : offer.getResourcesList()) { if (resource.getName().equals("cpus") && resource.getType() == Value.Type.SCALAR) { cpus = resource.getScalar().getValue(); cpuRole = resource.getRole(); } else if (resource.getName().equals("mem") && resource.getType() == Value.Type.SCALAR) { mem = resource.getScalar().getValue(); memRole = resource.getRole(); } else if (resource.getName().equals("disk") && resource.getType() == Value.Type.SCALAR) { disk = resource.getScalar().getValue(); diskRole = resource.getRole(); } else if (resource.getName().equals("ports") && resource.getType() == Value.Type.RANGES) { portRole = resource.getRole(); ports = resource.getRanges().getRangeList(); } } }
public static Protos.Offer generateUpdateOffer( String frameworkId, Protos.TaskInfo taskInfo, Protos.TaskInfo templateTaskInfo, double cpu, int memory, int disk) { final String offerUUID = UUID.randomUUID().toString(); return Protos.Offer .newBuilder() .setId(Protos.OfferID.newBuilder().setValue(offerUUID)) .setFrameworkId(Protos.FrameworkID.newBuilder().setValue(frameworkId)) .setSlaveId(Protos.SlaveID.newBuilder().setValue(taskInfo.getSlaveId().getValue())) .setHostname("127.0.0.1") .addAllResources(taskInfo.getResourcesList()) .addAllResources(taskInfo.getExecutor().getResourcesList()) .addAllResources(templateTaskInfo.getResourcesList()) .addResources(ResourceUtils.getUnreservedScalar("cpus", cpu)) .addResources(ResourceUtils.getUnreservedScalar("mem", memory)) .addResources(ResourceUtils.getUnreservedScalar("disk", disk)) .build(); }