| 52 | |
| 53 | |
| 54 | Try<Nothing> additive( |
| 55 | const SlaveInfo& previous, |
| 56 | const SlaveInfo& current) |
| 57 | { |
| 58 | if (previous.hostname() != current.hostname()) { |
| 59 | return Error( |
| 60 | "Configuration change not permitted under `additive` policy: " |
| 61 | "Hostname changed from " + |
| 62 | previous.hostname() + " to " + current.hostname()); |
| 63 | } |
| 64 | |
| 65 | if (previous.port() != current.port()) { |
| 66 | return Error( |
| 67 | "Configuration change not permitted under `additive` policy: " |
| 68 | "Port changed from " + stringify(previous.port()) + " to " + |
| 69 | stringify(current.port())); |
| 70 | } |
| 71 | |
| 72 | if (previous.has_domain() && !(previous.domain() == current.domain())) { |
| 73 | return Error( |
| 74 | "Configuration change not permitted under `additive` policy: " |
| 75 | "Domain changed from " + stringify(previous.domain()) + " to " + |
| 76 | stringify(current.domain())); |
| 77 | } |
| 78 | |
| 79 | // As a side effect, the Resources constructor also normalizes all addable |
| 80 | // resources, e.g. 'cpus:5;cpus:5' -> cpus:10 |
| 81 | Resources previousResources(previous.resources()); |
| 82 | Resources currentResources(current.resources()); |
| 83 | |
| 84 | // TODO(bennoe): We should probably check `resources.size()` and switch to a |
| 85 | // smarter algorithm for the matching when its bigger than, say, 20. |
| 86 | for (const Resource& resource : previousResources) { |
| 87 | Option<Resource> match = currentResources.match(resource); |
| 88 | |
| 89 | if (match.isNone()) { |
| 90 | return Error( |
| 91 | "Configuration change not permitted under 'additive' policy. " |
| 92 | "Resource not found: " + stringify(resource)); |
| 93 | } |
| 94 | |
| 95 | switch (resource.type()) { |
| 96 | case Value::SCALAR: { |
| 97 | if (!(resource.scalar() <= match->scalar())) { |
| 98 | return Error( |
| 99 | "Configuration change not permitted under 'additive' policy: " |
| 100 | "Value of scalar resource '" + resource.name() + "' decreased " |
| 101 | "from " + stringify(resource.scalar()) + " to " + |
| 102 | stringify(match->scalar())); |
| 103 | } |
| 104 | continue; |
| 105 | } |
| 106 | case Value::RANGES: { |
| 107 | if (!(resource.ranges() <= match->ranges())) { |
| 108 | return Error( |
| 109 | "Configuration change not permitted under 'additive' policy: " |
| 110 | "Previous value of range resource '" + resource.name() + "' (" + |
| 111 | stringify(resource.ranges()) + ") not included in current " + |