Commit 98775689 authored by Robert Ricci's avatar Robert Ricci

Merge in policy changes from the assing-devel branch

parent 2f63dfe6
......@@ -228,6 +228,7 @@ cout << "Physical Graph: " << parse_ptop(PG,SG,ptopfile) << endl;
// Calculate the minimum spanning tree for the switches - we only consider one
// potential path between each pair of switches.
// XXX: Should soon be replaced by calculate_shortest_routes()
void calculate_switch_MST() {
cout << "Calculating shortest paths on switch fabric." << endl;
......@@ -744,6 +745,20 @@ nosuchtype:
#endif
}
// Perfrom a pre-cehck to make sure that polices that are checkable at precheck
// time are not violated. Returns 1 if everything is A-OK, 0 otherwise
// TODO - move away from using global variables
int policy_precheck() {
cout << "Policy precheck:" << endl;
if (tb_featuredesire::check_desire_policies()) {
cout << "Policy precheck succeeded" << endl;
return 1;
} else {
cout << "*** Policy precheck failed!" << endl;
return 0;
}
}
// Signal handler - add a convneint way to kill assign and make it return an
// unretryable error
void exit_unretryable(int signal) {
......@@ -948,7 +963,13 @@ int main(int argc,char **argv) {
}
}
#endif
// Run the policy precheck - the idea behind running this last is that some
// policy violations might become more clear after doing pruning
if (!policy_precheck()) {
exit(EXIT_UNRETRYABLE);
}
// Bomb out early if we're only doing the prechecks
if (prechecks_only) {
exit(EXIT_SUCCESS);
......
......@@ -25,7 +25,9 @@ tb_featuredesire::tb_featuredesire(fstring _my_name) : my_name(_my_name),
global(false), local(false),
l_additive(false), g_one_is_okay(false),
g_more_than_one(false),
in_use_globally(0) {
in_use_globally(0), desire_policy(),
feature_policy(), desire_users(0),
desire_total_weight(0.0f) {
static int highest_id = 0;
// Pick a unique numeric identifier for this feature/desire
......@@ -112,6 +114,72 @@ void tb_featuredesire::remove_global_user(int howmany) {
assert(in_use_globally >= 0);
}
/*
* Functions for manipulating policies
*/
void tb_featuredesire::disallow_desire() {
desire_policy.disallow();
}
void tb_featuredesire::allow_desire() {
desire_policy.allow();
}
void tb_featuredesire::limit_desire(double limit) {
desire_policy.limit_use(limit);
}
void tb_featuredesire::unlimit_desire() {
desire_policy.unlimit_use();
}
/*
* Bookkeeping functions
*/
void tb_featuredesire::add_desire_user(double weight) {
desire_users++;
desire_total_weight += weight;
}
int tb_featuredesire::get_desire_users() {
return desire_users;
}
double tb_featuredesire::get_desire_total_weight() {
return desire_total_weight;
}
/*
* Check desire violations - true means everything was okay, false otherwise
*/
bool tb_featuredesire::check_desire_policies() {
int errors = 0;
name_featuredesire_map::const_iterator it = featuredesires_by_name.begin();
while (it != featuredesires_by_name.end()) {
tb_featuredesire *fd = it->second;
if (!fd->desire_policy.is_allowable() && fd->desire_users) {
cout << " *** Policy violation: " << endl
<< " Feature " << it->first
<< " requested, but prohibited by policy" << endl;
errors++;
} else {
if (fd->desire_policy.is_limited() &&
(fd->desire_total_weight > fd->desire_policy.get_limit())) {
cout << " *** Policy violation: " << endl
<< " Feature " << it->first
<< " requested with weight " << fd->desire_total_weight
<< " but limted to " << fd->desire_policy.get_limit()
<< " by policy" << endl;
errors++;
}
}
it++;
}
if (errors) {
return false;
} else {
return true;
}
}
/*********************************************************************
* tb_node_featuredesire
*********************************************************************/
......
......@@ -16,8 +16,44 @@
using namespace std;
/*
* Base class for features and desires - not intended to be used directly, only
* to be subclassed by tb_feature and tb_desire
* This small class is used to describe policies in force regarding features
* and desires. The idea behind putting this it its own class is that you want
* to be able to apply baiscally the same policies to features and desires, but
* treat them seperateley.
*/
class tb_featuredesire_policy {
public:
tb_featuredesire_policy(): allowable(true), limited_use(false),
min_use(0.0f), max_use(0.0f) { ; };
/*
* Functions for maintaining FD policy state. Inline, since they're
* so simple.
*/
void allow() { allowable = true; };
void disallow() { allowable = false; }
bool is_allowable() { return this->allowable; };
void limit_use(double howmuch) { limited_use = true; max_use = howmuch; };
void unlimit_use() { limited_use = false; max_use = 0.0f; }
bool is_limited() { return limited_use; }
double get_limit() { return max_use; }
friend ostream &operator<<(ostream &o, const tb_featuredesire_policy &fdp);
private:
// Indicates whether or not we are allowed to use this feature or
// desire, and if so, how much of it we are allowed to use. Note that
// while these limits are global, this is different from using a global
// FD - it is a policy knob that can be applied in the ptop file
bool allowable;
bool limited_use;
double max_use;
// Note: min_use not implemented, as it's not clear what the point
// would be
double min_use;
};
/*
* Base class for features and desires.
*/
class tb_featuredesire {
public:
......@@ -43,7 +79,7 @@ class tb_featuredesire {
inline bool is_g_one() const { return g_one_is_okay; }
inline bool is_g_more() const { return g_more_than_one; }
inline int global_use_count() const { return in_use_globally; }
inline fstring name() const { return my_name; }
inline fstring name() const { return my_name; }
/*
* Operators, primarily for use with the STL
......@@ -63,7 +99,34 @@ class tb_featuredesire {
*/
void add_global_user(int howmany = 1);
void remove_global_user(int howmany = 1);
/*
* Simple bookkeeping
*/
void add_desire_user(double weight);
int get_desire_users();
double get_desire_total_weight();
/*
* Functions for manipulating the policies for features or desires with
* this name.
* NOTE: Only desire policies implement for now
*/
void disallow_desire();
void allow_desire();
void limit_desire(double limit);
void unlimit_desire();
/*
* Check to see if any desires violate policies - this is checkable at
* any time (after all desires and policies have been set up), because
* it is not dependant on the current mapping. Returns true if
* everything is okay, false if not.
* Feature policy violations, which are not yet implemented, will be
* much harder because of thise.
*/
static bool check_desire_policies();
private:
/*
* This is private, so that we can force callers to go through the
......@@ -87,11 +150,25 @@ class tb_featuredesire {
bool l_additive; // If a local FD, is additive
// Counts how many instances of this feature are in use across all
// nodes - for use with global nodes
// nodes - for use with global features
int in_use_globally;
typedef map<fstring,tb_featuredesire*> name_featuredesire_map;
static name_featuredesire_map featuredesires_by_name;
/*
* Policies for using features and desires with the name. NOTE: Only
* feature policies implemented yet, as they are easier to check for.
*/
tb_featuredesire_policy feature_policy;
tb_featuredesire_policy desire_policy;
/*
* Some simple bookkeeping stuff, currently only used to enforce
* policies.
*/
int desire_users;
double desire_total_weight;
};
/*
......@@ -141,6 +218,9 @@ class tb_node_featuredesire {
const bool is_l_additive() const {
return featuredesire_obj->is_l_additive();
}
void add_desire_user(double weight) const {
featuredesire_obj->add_desire_user(weight);
}
score_and_violations add_global_user() const;
score_and_violations remove_global_user() const;
......
......@@ -16,7 +16,7 @@ by Ricci, Alfeld, and Lepreau about assign.
##### ptop (physical topology) file
ptop file: <line>*
<line> ::= <node_line> | <link_line> | <type_limit_line>
<line> ::= <node_line> | <link_line> | <type_limit_line> | <policy_line>
<node_line> ::= node <node_name> <node_type>+ [- <feature>* [- <flag>* ]]
<node_type> ::= "*"?<type_name>:<type_count>
......@@ -30,6 +30,9 @@ ptop file: <line>*
<type_limit_line> ::= set-type-limit <node_type> <int>
<policy_line> ::= policy <desire_policy>
<desire_policy> ::= desire <feature_name> ( disallow | limit <float> )
Interpretation:
<node_line> - though a node can have several types that it can satisfy, it is
......@@ -79,6 +82,10 @@ Interpretation:
file. The other two portions are mostly ignored.
<type_limit_line> - used to enforce Emulab policies: ie. this experiment is
not allowed to use more than 10 pc3000 nodes
<policy_line> - used to indicate policies for mapping the experiment. The only
policies currently supported are 'desire' policies, which can be used to
disallow the top file from requesting a particular desire, or limit the
total weight that can be given to a desire
##### top (virtual topology) file
......
......@@ -321,6 +321,7 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
#endif
}
}
} else if (command == "set-type-limit") {
if (parsed_line.size() != 3) {
ptop_error("Bad set-type-limit line, requires two arguments.");
......@@ -337,7 +338,36 @@ int parse_ptop(tb_pgraph &PG, tb_sgraph &SG, istream& i)
}
ptypes[type]->set_max_users(max);
} else if (command == "policy") {
if (parsed_line.size() < 3) {
ptop_error("No policy type given.");
} else {
if (parsed_line[1] == "desire") {
fstring desire = parsed_line[2];
fstring type = parsed_line[3];
tb_featuredesire *fd_obj =
tb_featuredesire::get_featuredesire_obj(desire);
if (type == "disallow") {
fd_obj->disallow_desire();
} else if (type == "limit") {
if (parsed_line.size() != 5) {
ptop_error("Missing desire limit");
} else {
double limit;
if (sscanf(parsed_line[4].c_str(),"%lf",&limit) != 1) {
ptop_error("Malformed desire limit");
} else {
fd_obj->limit_desire(limit);
}
}
} else {
ptop_error("Unknown policy for desire");
}
} else {
ptop_error("Only desire policies are supported.");
}
}
} else {
ptop_error("Unknown directive: " << command << ".");
}
......
......@@ -152,8 +152,9 @@ int parse_top(tb_vgraph &VG, istream& i)
top_error("Bad desire, bad weight.");
gweight = 0;
}
v->desires.push_front(
tb_node_featuredesire(desirename,gweight));
tb_node_featuredesire node_fd(desirename, gweight);
node_fd.add_desire_user(gweight);
v->desires.push_front(node_fd);
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment