Apache Mesos
resources.hpp
Go to the documentation of this file.
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #ifndef __MESOS_V1_RESOURCES_HPP__
18 #define __MESOS_V1_RESOURCES_HPP__
19 
20 #include <map>
21 #include <iosfwd>
22 #include <set>
23 #include <string>
24 #include <vector>
25 
26 #include <google/protobuf/repeated_field.h>
27 
28 #include <mesos/v1/mesos.hpp>
29 #include <mesos/v1/values.hpp>
30 
31 #include <stout/bytes.hpp>
32 #include <stout/check.hpp>
33 #include <stout/error.hpp>
34 #include <stout/foreach.hpp>
35 #include <stout/hashmap.hpp>
36 #include <stout/json.hpp>
37 #include <stout/lambda.hpp>
38 #include <stout/nothing.hpp>
39 #include <stout/option.hpp>
40 #include <stout/try.hpp>
41 
42 
43 // Resources come in three types: scalar, ranges, and sets. These are
44 // represented using protocol buffers. To make manipulation of
45 // resources easier within the Mesos core and for scheduler writers,
46 // we provide generic overloaded operators (see below) as well as a
47 // general Resources class that encapsulates a collection of protocol
48 // buffer Resource objects. The Resources class also provides a few
49 // static routines to allow parsing resources (e.g., from the command
50 // line), as well as determining whether or not a Resource object is
51 // valid. Note that many of these operations have not been optimized
52 // but instead just written for correct semantics.
53 
54 namespace mesos {
55 namespace v1 {
56 
57 // Forward declaration.
58 class ResourceConversion;
59 
60 
61 // Helper functions.
62 bool operator==(
63  const Resource::ReservationInfo& left,
64  const Resource::ReservationInfo& right);
65 
66 
67 bool operator!=(
68  const Resource::ReservationInfo& left,
69  const Resource::ReservationInfo& right);
70 
71 
72 // NOTE: Resource objects stored in the class are always valid, are in
73 // the "post-reservation-refinement" format, and kept combined if possible.
74 // It is the caller's responsibility to validate any Resource object or
75 // repeated Resource protobufs before constructing a Resources object.
76 // Otherwise, invalid Resource objects will be silently stripped.
77 // Invalid Resource objects will also be silently ignored when used in
78 // arithmetic operations (e.g., +=, -=, etc.).
79 class Resources
80 {
81 private:
82  // An internal abstraction to facilitate managing shared resources.
83  // It allows 'Resources' to group identical shared resource objects
84  // together into a single 'Resource_' object and tracked by its internal
85  // counter. Non-shared resource objects are not grouped.
86  //
87  // The rest of the private section is below the public section. We
88  // need to define Resource_ first because the public typedefs below
89  // depend on it.
90  class Resource_
91  {
92  public:
93  /*implicit*/ Resource_(const Resource& _resource)
94  : resource(_resource),
95  sharedCount(None())
96  {
97  // Setting the counter to 1 to denote "one copy" of the shared resource.
98  if (resource.has_shared()) {
99  sharedCount = 1;
100  }
101  }
102 
103  // By implicitly converting to Resource we are able to keep Resource_
104  // logic internal and expose only the protobuf object.
105  operator const Resource&() const { return resource; }
106 
107  // Check whether this Resource_ object corresponds to a shared resource.
108  bool isShared() const { return sharedCount.isSome(); }
109 
110  // Validates this Resource_ object.
111  Option<Error> validate() const;
112 
113  // Check whether this Resource_ object is empty.
114  bool isEmpty() const;
115 
116  // The `Resource_` arithmetic, comparison operators and `contains()`
117  // method require the wrapped `resource` protobuf to have the same
118  // sharedness.
119  //
120  // For shared resources, the `resource` protobuf needs to be equal,
121  // and only the shared counters are adjusted or compared.
122  // For non-shared resources, the shared counters are none and the
123  // semantics of the Resource_ object's operators/contains() method
124  // are the same as those of the Resource objects.
125 
126  // Checks if this Resource_ is a superset of the given Resource_.
127  bool contains(const Resource_& that) const;
128 
129  // The arithmetic operators, viz. += and -= assume that the corresponding
130  // Resource objects are addable or subtractable already.
131  Resource_& operator+=(const Resource_& that);
132  Resource_& operator-=(const Resource_& that);
133 
134  bool operator==(const Resource_& that) const;
135  bool operator!=(const Resource_& that) const;
136 
137  // Friend classes and functions for access to private members.
138  friend class Resources;
139  friend std::ostream& operator<<(
140  std::ostream& stream, const Resource_& resource_);
141 
142  private:
143  // The protobuf Resource that is being managed.
144  Resource resource;
145 
146  // The counter for grouping shared 'resource' objects, None if the
147  // 'resource' is non-shared. This is an int so as to support arithmetic
148  // operations involving subtraction.
149  Option<int> sharedCount;
150  };
151 
152 public:
165  static Try<Resource> parse(
166  const std::string& name,
167  const std::string& value,
168  const std::string& role);
169 
184  static Try<Resources> parse(
185  const std::string& text,
186  const std::string& defaultRole = "*");
187 
208  const JSON::Array& resourcesJSON,
209  const std::string& defaultRole = "*");
210 
229  const std::string& text,
230  const std::string& defaultRole = "*");
231 
245  const std::string& text,
246  const std::string& defaultRole = "*");
247 
260  static Option<Error> validate(const Resource& resource);
261 
279  static Option<Error> validate(
280  const google::protobuf::RepeatedPtrField<Resource>& resources);
281 
282  // NOTE: The following predicate functions assume that the given resource is
283  // validated, and is in the "post-reservation-refinement" format. That is,
284  // the reservation state is represented by `Resource.reservations` field,
285  // and `Resource.role` and `Resource.reservation` fields are not set.
286  //
287  // See 'Resource Format' section in `mesos.proto` for more details.
288 
289  // Tests if the given Resource object is empty.
290  static bool isEmpty(const Resource& resource);
291 
292  // Tests if the given Resource object is a persistent volume.
293  static bool isPersistentVolume(const Resource& resource);
294 
295  // Tests if the given Resource object is a disk of the specified type.
296  static bool isDisk(
297  const Resource& resource,
299 
300  // Tests if the given Resource object is reserved. If the role is
301  // specified, tests that it's reserved for the given role.
302  static bool isReserved(
303  const Resource& resource,
304  const Option<std::string>& role = None());
305 
306  // Tests if the given Resource object is allocatable to the given role.
307  // A resource object is allocatable to 'role' if:
308  // * it is reserved to an ancestor of that role in the hierarchy, OR
309  // * it is reserved to 'role' itself, OR
310  // * it is unreserved.
311  static bool isAllocatableTo(
312  const Resource& resource,
313  const std::string& role);
314 
315  // Tests if the given Resource object is unreserved.
316  static bool isUnreserved(const Resource& resource);
317 
318  // Tests if the given Resource object is dynamically reserved.
319  static bool isDynamicallyReserved(const Resource& resource);
320 
321  // Tests if the given Resource object is revocable.
322  static bool isRevocable(const Resource& resource);
323 
324  // Tests if the given Resource object is shared.
325  static bool isShared(const Resource& resource);
326 
327  // Tests if the given Resource object has refined reservations.
328  static bool hasRefinedReservations(const Resource& resource);
329 
330  // Tests if the given Resource object is provided by a resource provider.
331  static bool hasResourceProvider(const Resource& resource);
332 
333  // Returns the role to which the given Resource object is reserved for.
334  // This must be called only when the resource is reserved!
335  static const std::string& reservationRole(const Resource& resource);
336 
337  // Shrinks a scalar type `resource` to the target size.
338  // Returns true if the resource was shrunk to the target size,
339  // or the resource is already within the target size.
340  // Returns false otherwise (i.e. the resource is indivisible.
341  // E.g. MOUNT volume).
342  static bool shrink(Resource* resource, const Value::Scalar& target);
343 
344  // Returns the summed up Resources given a hashmap<Key, Resources>.
345  //
346  // NOTE: While scalar resources such as "cpus" sum correctly,
347  // non-scalar resources such as "ports" do not.
348  // e.g. "cpus:2" + "cpus:1" = "cpus:3"
349  // "ports:[0-100]" + "ports:[0-100]" = "ports:[0-100]"
350  //
351  // TODO(mpark): Deprecate this function once we introduce the
352  // concept of "cluster-wide" resources which provides correct
353  // semantics for summation over all types of resources. (e.g.
354  // non-scalar)
355  template <typename Key>
356  static Resources sum(const hashmap<Key, Resources>& _resources)
357  {
358  Resources result;
359 
360  foreachvalue (const Resources& resources, _resources) {
361  result += resources;
362  }
363 
364  return result;
365  }
366 
368 
369  // TODO(jieyu): Consider using C++11 initializer list.
370  /*implicit*/ Resources(const Resource& resource);
371 
372  /*implicit*/
373  Resources(const std::vector<Resource>& _resources);
374 
375  /*implicit*/
376  Resources(const google::protobuf::RepeatedPtrField<Resource>& _resources);
377 
378  Resources(const Resources& that) : resources(that.resources) {}
379 
381  {
382  if (this != &that) {
383  resources = that.resources;
384  }
385  return *this;
386  }
387 
388  bool empty() const { return resources.size() == 0; }
389 
390  size_t size() const { return resources.size(); }
391 
392  // Checks if this Resources is a superset of the given Resources.
393  bool contains(const Resources& that) const;
394 
395  // Checks if this Resources contains the given Resource.
396  bool contains(const Resource& that) const;
397 
398  // Count the Resource objects that match the specified value.
399  //
400  // NOTE:
401  // - For a non-shared resource the count can be at most 1 because all
402  // non-shared Resource objects in Resources are unique.
403  // - For a shared resource the count can be greater than 1.
404  // - If the resource is not in the Resources object, the count is 0.
405  size_t count(const Resource& that) const;
406 
407  // Allocates the resources to the given role (by setting the
408  // `AllocationInfo.role`). Any existing allocation will be
409  // over-written.
410  void allocate(const std::string& role);
411 
412  // Unallocates the resources.
413  void unallocate();
414 
415  // Filter resources based on the given predicate.
417  const lambda::function<bool(const Resource&)>& predicate) const;
418 
419  // Returns the reserved resources, by role.
421 
422  // Returns the reserved resources for the role, if specified.
423  // Note that the "*" role represents unreserved resources,
424  // and will be ignored.
425  Resources reserved(const Option<std::string>& role = None()) const;
426 
427  // Returns resources allocatable to role. See `isAllocatableTo` for the
428  // definition of 'allocatableTo'.
429  Resources allocatableTo(const std::string& role) const;
430 
431  // Returns the unreserved resources.
432  Resources unreserved() const;
433 
434  // Returns the persistent volumes.
436 
437  // Returns the revocable resources.
438  Resources revocable() const;
439 
440  // Returns the non-revocable resources, effectively !revocable().
441  Resources nonRevocable() const;
442 
443  // Returns the shared resources.
444  Resources shared() const;
445 
446  // Returns the non-shared resources.
447  Resources nonShared() const;
448 
449  // Returns the per-role allocations within these resource objects.
450  // This must be called only when the resources are allocated!
452 
453  // Returns a `Resources` object with the new reservation added to the back.
454  // The new reservation must be a valid refinement of the current reservation.
455  Resources pushReservation(const Resource::ReservationInfo& reservation) const;
456 
457  // Returns a `Resources` object with the last reservation removed.
458  // Every resource in `Resources` must have `resource.reservations_size() > 0`.
459  Resources popReservation() const;
460 
461  // Returns a `Resources` object with all of the reservations removed.
462  Resources toUnreserved() const;
463 
464  // Returns a Resources object that contains all the scalar resources
465  // in this object, but with their AllocationInfo, ReservationInfo,
466  // DiskInfo, and SharedInfo omitted. The `role` and RevocableInfo,
467  // if any, are preserved. Because we clear ReservationInfo but
468  // preserve `role`, this means that stripping a dynamically reserved
469  // resource makes it effectively statically reserved.
470  //
471  // This is intended for code that would like to aggregate together
472  // Resource values without regard for metadata like whether the
473  // resource is reserved or the particular volume ID in use. For
474  // example, when calculating the total resources in a cluster,
475  // preserving such information has a major performance cost.
477 
478  // Finds a Resources object with the same amount of each resource
479  // type as "targets" from these Resources. The roles specified in
480  // "targets" set the preference order. For each resource type,
481  // resources are first taken from the specified role, then from '*',
482  // then from any other role.
483  // TODO(jieyu): 'find' contains some allocation logic for scalars and
484  // fixed set / range elements. However, this is not sufficient for
485  // schedulers that want, say, any N available ports. We should
486  // consider moving this to an internal "allocation" library for our
487  // example frameworks to leverage.
488  Option<Resources> find(const Resources& targets) const;
489 
490  // Applies a resource conversion by taking out the `consumed`
491  // resources and adding back the `converted` resources. Returns an
492  // Error if the conversion cannot be applied.
493  Try<Resources> apply(const ResourceConversion& conversion) const;
494 
495  // Obtains the conversion from the given operation and applies the
496  // conversion. This method serves a syntax sugar for applying a
497  // resource conversion.
498  // TODO(jieyu): Consider remove this method once we updated all the
499  // call sites.
500  Try<Resources> apply(const Offer::Operation& operation) const;
501 
502  template <typename Iterable>
503  Try<Resources> apply(const Iterable& iterable) const
504  {
505  Resources result = *this;
506 
507  foreach (const auto& t, iterable) {
508  Try<Resources> converted = result.apply(t);
509  if (converted.isError()) {
510  return Error(converted.error());
511  }
512 
513  result = converted.get();
514  }
515 
516  return result;
517  }
518 
519  // Helpers to get resource values. We consider all roles here.
520  template <typename T>
521  Option<T> get(const std::string& name) const;
522 
523  // Get resources of the given name.
524  Resources get(const std::string& name) const;
525 
526  // Get all the resources that are scalars.
527  Resources scalars() const;
528 
529  // Get the set of unique resource names.
530  std::set<std::string> names() const;
531 
532  // Get the types of resources associated with each resource name.
533  // NOTE: Resources of the same name must have the same type, as
534  // enforced by Resources::parse().
535  std::map<std::string, Value_Type> types() const;
536 
537  // Helpers to get known resource types.
538  // TODO(vinod): Fix this when we make these types as first class
539  // protobufs.
540  Option<double> cpus() const;
541  Option<double> gpus() const;
542  Option<Bytes> mem() const;
543  Option<Bytes> disk() const;
544 
545  // TODO(vinod): Provide a Ranges abstraction.
547 
548  // TODO(jieyu): Consider returning an EphemeralPorts abstraction
549  // which holds the ephemeral ports allocation logic.
551 
552  // NOTE: Non-`const` `iterator`, `begin()` and `end()` are __intentionally__
553  // defined with `const` semantics in order to prevent mutable access to the
554  // `Resource` objects within `resources`.
555  typedef std::vector<Resource_>::const_iterator iterator;
556  typedef std::vector<Resource_>::const_iterator const_iterator;
557 
559  {
560  return static_cast<const std::vector<Resource_>&>(resources).begin();
561  }
562 
564  {
565  return static_cast<const std::vector<Resource_>&>(resources).end();
566  }
567 
568  const_iterator begin() const { return resources.begin(); }
569  const_iterator end() const { return resources.end(); }
570 
571  // Using this operator makes it easy to copy a resources object into
572  // a protocol buffer field.
573  // Note that the google::protobuf::RepeatedPtrField<Resource> is
574  // generated at runtime.
575  operator google::protobuf::RepeatedPtrField<Resource>() const;
576 
577  bool operator==(const Resources& that) const;
578  bool operator!=(const Resources& that) const;
579 
580  // NOTE: If any error occurs (e.g., input Resource is not valid or
581  // the first operand is not a superset of the second operand while
582  // doing subtraction), the semantics is as though the second operand
583  // was actually just an empty resource (as though you didn't do the
584  // operation at all).
585  Resources operator+(const Resource& that) const;
586  Resources operator+(const Resources& that) const;
587  Resources& operator+=(const Resource& that);
588  Resources& operator+=(const Resources& that);
589 
590  Resources operator-(const Resource& that) const;
591  Resources operator-(const Resources& that) const;
592  Resources& operator-=(const Resource& that);
593  Resources& operator-=(const Resources& that);
594 
595  friend std::ostream& operator<<(
596  std::ostream& stream, const Resource_& resource_);
597 
598 private:
599  // Similar to 'contains(const Resource&)' but skips the validity
600  // check. This can be used to avoid the performance overhead of
601  // calling 'contains(const Resource&)' when the resource can be
602  // assumed valid (e.g. it's inside a Resources).
603  //
604  // TODO(jieyu): Measure performance overhead of validity check to
605  // ensure this is warranted.
606  bool _contains(const Resource_& that) const;
607 
608  // Similar to the public 'find', but only for a single Resource
609  // object. The target resource may span multiple roles, so this
610  // returns Resources.
611  Option<Resources> find(const Resource& target) const;
612 
613  // Validation-free versions of += and -= `Resource_` operators.
614  // These can be used when `r` is already validated.
615  //
616  // NOTE: `Resource` objects are implicitly converted to `Resource_`
617  // objects, so here the API can also accept a `Resource` object.
618  void add(const Resource_& r);
619  void subtract(const Resource_& r);
620 
621  Resources operator+(const Resource_& that) const;
622  Resources& operator+=(const Resource_& that);
623 
624  Resources operator-(const Resource_& that) const;
625  Resources& operator-=(const Resource_& that);
626 
627  std::vector<Resource_> resources;
628 };
629 
630 
631 std::ostream& operator<<(
632  std::ostream& stream,
633  const Resources::Resource_& resource);
634 
635 
636 std::ostream& operator<<(std::ostream& stream, const Resource& resource);
637 
638 
639 std::ostream& operator<<(std::ostream& stream, const Resources& resources);
640 
641 
642 std::ostream& operator<<(
643  std::ostream& stream,
644  const google::protobuf::RepeatedPtrField<Resource>& resources);
645 
646 
648  const google::protobuf::RepeatedPtrField<Resource>& left,
649  const Resources& right)
650 {
651  return Resources(left) + right;
652 }
653 
654 
656  const google::protobuf::RepeatedPtrField<Resource>& left,
657  const Resources& right)
658 {
659  return Resources(left) - right;
660 }
661 
662 
663 inline bool operator==(
664  const google::protobuf::RepeatedPtrField<Resource>& left,
665  const Resources& right)
666 {
667  return Resources(left) == right;
668 }
669 
670 
671 template <typename Key>
674  const hashmap<Key, Resources>& right)
675 {
676  foreachpair (const Key& key, const Resources& resources, right) {
677  left[key] += resources;
678  }
679  return left;
680 }
681 
682 
683 template <typename Key>
685  const hashmap<Key, Resources>& left,
686  const hashmap<Key, Resources>& right)
687 {
688  hashmap<Key, Resources> result = left;
689  result += right;
690  return result;
691 }
692 
693 
699 {
700 public:
701  typedef lambda::function<Try<Nothing>(const Resources&)> PostValidation;
702 
704  const Resources& _consumed,
705  const Resources& _converted,
706  const Option<PostValidation>& _postValidation = None())
707  : consumed(_consumed),
708  converted(_converted),
709  postValidation(_postValidation) {}
710 
711  Try<Resources> apply(const Resources& resources) const;
712 
716 };
717 
718 } // namespace v1 {
719 } // namespace mesos {
720 
721 #endif // __MESOS_V1_RESOURCES_HPP__
Try< Resources > apply(const Resources &resources) const
Resources toUnreserved() const
Resources revocable() const
Resources reserved(const Option< std::string > &role=None()) const
Resources & operator=(const Resources &that)
Definition: resources.hpp:380
static Option< Error > validate(const Resource &resource)
Validates a Resource object.
Definition: errorbase.hpp:35
Resources unreserved() const
const_iterator end()
Definition: resources.hpp:563
static bool isPersistentVolume(const Resource &resource)
Definition: try.hpp:34
Option< Bytes > disk() const
Resources nonRevocable() const
Option< double > cpus() const
Try< Resources > apply(const Iterable &iterable) const
Definition: resources.hpp:503
static Try< std::vector< Resource > > fromJSON(const JSON::Array &resourcesJSON, const std::string &defaultRole="*")
Parses an input JSON array into a vector of Resource objects.
Resources popReservation() const
Resources persistentVolumes() const
static Try< std::vector< Resource > > fromSimpleString(const std::string &text, const std::string &defaultRole="*")
Parses an input text string into a vector of Resource objects.
bool empty() const
Definition: resources.hpp:388
Resources(const Resources &that)
Definition: resources.hpp:378
Definition: resources.hpp:79
static bool isAllocatableTo(const Resource &resource, const std::string &role)
bool operator==(const Resources &that) const
static const std::string & reservationRole(const Resource &resource)
Definition: json.hpp:194
Resources filter(const lambda::function< bool(const Resource &)> &predicate) const
static bool hasResourceProvider(const Resource &resource)
Operation
Definition: cgroups.hpp:441
Future< Nothing > add(const T &metric)
Definition: metrics.hpp:95
Resources & operator-=(const Resource &that)
static bool isDynamicallyReserved(const Resource &resource)
std::map< std::string, Value_Type > types() const
static Try< Resource > parse(const std::string &name, const std::string &value, const std::string &role)
Returns a Resource with the given name, value, and role.
static bool hasRefinedReservations(const Resource &resource)
static bool isReserved(const Resource &resource, const Option< std::string > &role=None())
hashmap< Key, Resources > & operator+=(hashmap< Key, Resources > &left, const hashmap< Key, Resources > &right)
Definition: resources.hpp:672
hashmap< std::string, Resources > allocations() const
Definition: hashmap.hpp:38
Resources pushReservation(const Resource::ReservationInfo &reservation) const
Represents a resource conversion, usually as a result of an offer operation.
Definition: resources.hpp:698
const_iterator begin() const
Definition: resources.hpp:568
Resources createStrippedScalarQuantity() const
size_t size() const
Definition: resources.hpp:390
bool contains(const Resources &that) const
hashmap< std::string, Resources > reservations() const
Resources nonShared() const
static bool isShared(const Resource &resource)
Resources operator-(const Resource &that) const
std::vector< Resource_ >::const_iterator const_iterator
Definition: resources.hpp:556
Resources consumed
Definition: resources.hpp:713
ResourceConversion(const Resources &_consumed, const Resources &_converted, const Option< PostValidation > &_postValidation=None())
Definition: resources.hpp:703
void allocate(const std::string &role)
const_iterator end() const
Definition: resources.hpp:569
Definition: resources.hpp:79
#define foreachpair(KEY, VALUE, ELEMS)
Definition: foreach.hpp:51
bool operator==(const CommandInfo &left, const CommandInfo &right)
#define foreachvalue(VALUE, ELEMS)
Definition: foreach.hpp:77
Option< Value::Ranges > ports() const
Resources()
Definition: resources.hpp:367
friend std::ostream & operator<<(std::ostream &stream, const Resource_ &resource_)
static Try error(const E &e)
Definition: try.hpp:42
lambda::function< Try< Nothing >const Resources &)> PostValidation
Definition: resources.hpp:701
Resources operator-(const google::protobuf::RepeatedPtrField< Resource > &left, const Resources &right)
Definition: resources.hpp:655
const_iterator begin()
Definition: resources.hpp:558
Resources operator+(const google::protobuf::RepeatedPtrField< Resource > &left, const Resources &right)
Definition: resources.hpp:647
size_t count(const Resource &that) const
Definition: none.hpp:27
bool isError() const
Definition: try.hpp:71
Option< Bytes > mem() const
bool operator!=(const Resources &that) const
static bool isRevocable(const Resource &resource)
Type
Definition: capabilities.hpp:79
Resources scalars() const
Resources converted
Definition: resources.hpp:714
Resources allocatableTo(const std::string &role) const
std::vector< Resource_ >::const_iterator iterator
Definition: resources.hpp:555
static bool isUnreserved(const Resource &resource)
Try< uint32_t > type(const std::string &path)
Option< Value::Ranges > ephemeral_ports() const
static Try< std::vector< Resource > > fromString(const std::string &text, const std::string &defaultRole="*")
Parse an input string into a vector of Resource objects.
Resources operator+(const Resource &that) const
bool operator!=(const Labels &left, const Labels &right)
Try< Resources > apply(const ResourceConversion &conversion) const
static bool isDisk(const Resource &resource, const Resource::DiskInfo::Source::Type &type)
std::set< std::string > names() const
static bool shrink(Resource *resource, const Value::Scalar &target)
std::ostream & operator<<(std::ostream &stream, const Attribute &attribute)
static Resources sum(const hashmap< Key, Resources > &_resources)
Definition: resources.hpp:356
const T & get() const
Definition: try.hpp:73
constexpr const char * name
Definition: shell.hpp:41
Option< Resources > find(const Resources &targets) const
Resources shared() const
Resources & operator+=(const Resource &that)
Option< double > gpus() const
Option< PostValidation > postValidation
Definition: resources.hpp:715
static bool isEmpty(const Resource &resource)