Skip to content

Commit

Permalink
Merge pull request #141 from richiMarchi/save_load_topology
Browse files Browse the repository at this point in the history
load old topology at startup and save each modification to file
  • Loading branch information
frisso committed Jun 21, 2019
2 parents 2692c3f + 2b42e45 commit 42d1066
Show file tree
Hide file tree
Showing 40 changed files with 1,162 additions and 118 deletions.
29 changes: 28 additions & 1 deletion Documentation/polycubed/polycubed.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,34 @@ If the same parameter is specified in both, the configuration file and the comma
daemon: true
#p: 6000 <-- this is NOT supported, only long options are



Persistency
^^^^^^^^^^^

Polycubed has persistent capabilities, which means that (1) it can automatically load the configuration that was present when the daemon was shut down, (2) each time a configuration command is issued, it is automatically dumped on disk.
This enables polycubed also to recover from failures, such as rebooting the machine.
By default, the daemon keeps in memory an instance of all the topology, including the configuration of each individual service.
Topology and configuration are automatically updated at each new command; the configuration is also dumped to disk, on file ``/etc/polycube/cubes.yaml``.
The standard behavior of the daemon at startup is to load the latest topology that was active at the end of the previous execution.
Users can load a different topology file by using the ``--cubes-dump`` flag followed by the path to the file.
In case we want to start polycubed with an empty topology, avoiding any possible load at startup, we can launch polycubed with the ``--cubes-init`` flag. Beware that in this case any existing configuration in the default file will be overwritten.
Finally, persistency can be disabled with the ``--cubes-nodump`` flag; this would also avoid any (very limited) performance penalty introduced by this feature.

::

# start polycubed with custom cubes configuration
polycubed --cubes-dump ~/Desktop/myCubes.yaml

# start polycubed with an empty topology
polycubed --cubes-init

# start daemon without topology saving functionalities
polycubed --cubes-nodump



Rest API
^^^^^^^^

TODO...
TODO...
13 changes: 13 additions & 0 deletions src/libs/polycube/include/polycube/services/cube.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,19 @@ std::shared_ptr<PortType> Cube<PortType>::add_port(const std::string &port_name,

std::tie(iter, inserted) = ports_by_name_.emplace(port_name, port);
ports_by_id_.emplace(port->index(), port);
/*
* When a transparent cube is attached to a port, it can query the service
* to get some port parameters (e.g., MAC address). If the transparent cube
* is attached while the port is being created these parameters will be not
* configured yet.
* This workaround first creates the port and then passes the configuration
* to attach the transparent cubes. The configuration that is passed
* in the constructor is ignored in the daemon.
* The solution for this workaround would be to implement the notification
* mechanishm, so when the parameters are configured those are pushed to the
* transparent cube.
*/
port->set_conf(conf.getBase());
return iter->second;
} catch (const std::exception &ex) {
cube_->remove_port(port_name);
Expand Down
1 change: 1 addition & 0 deletions src/polycubed/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ set(polycubed_sources
utils/veth.cpp
utils/netlink.cpp
utils/utils.cpp
cubes_dump.cpp
${server_sources}
${CMAKE_CURRENT_BINARY_DIR}/load_services.cpp
${CMAKE_CURRENT_BINARY_DIR}/version.cpp)
Expand Down
20 changes: 20 additions & 0 deletions src/polycubed/src/base_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,4 +244,24 @@ Response BaseModel::set_span(const std::string &cube_name,
return Response{kOk, ::strdup("")};
}

Response BaseModel::get_port_tcubes(const std::string &cube_name,
const std::string &port_name) const {
auto cube_ = ServiceController::get_cube(cube_name);
if (cube_ == nullptr) {
return Response{kNoContent, ::strdup("Cube does not exist")};
}

// TODO: is this case even possible?
auto cube = std::dynamic_pointer_cast<CubeIface>(cube_);
if (cube == nullptr) {
return Response{kNoContent, ::strdup("Cube is transparent")};
}

auto port_ = cube->get_port(port_name);
auto port = std::dynamic_pointer_cast<Port>(port_);
nlohmann::json j = port->get_cubes_names();

return Response{kOk, ::strdup(j.dump().c_str())};
}

} // namespace polycube::polycubed
2 changes: 2 additions & 0 deletions src/polycubed/src/base_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class BaseModel {
Response get_span(const std::string &cube_name) const;
Response set_span(const std::string &cube_name,
const nlohmann::json &json);
Response get_port_tcubes(const std::string &cube_name,
const std::string &port_name) const;
};

} // namespace polycube::polycubed
56 changes: 55 additions & 1 deletion src/polycubed/src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ namespace configuration {

#define LOGLEVEL spdlog::level::level_enum::info
#define DAEMON false
#define CUBESINIT false
#define CUBESNODUMP false
#define PIDFILE "/var/run/polycube.pid"
#define SERVER_PORT 9000
#define SERVER_IP "localhost"
#define LOGFILE "/var/log/polycube/polycubed.log"
#define CONFIGFILEDIR "/etc/polycube"
#define CONFIGFILENAME "polycubed.conf"
#define CUBESDUMPFILE "cubes.yaml"
#define CONFIGFILE (CONFIGFILEDIR "/" CONFIGFILENAME)
#define CUBESDUMPFILEPATH (CONFIGFILEDIR "/" CUBESDUMPFILE)

static void show_usage(const std::string &name) {
std::cout << std::boolalpha;
Expand All @@ -64,6 +68,11 @@ static void show_usage(const std::string &name) {
<< ")" << std::endl;
std::cout << "--configfile: configuration file (default: " << CONFIGFILE
<< ")" << std::endl;
std::cout << "--cubes-dump: file that keeps the last topology, "
"including the configuration of all cubes (default: " << CUBESDUMPFILEPATH
<< ")" << std::endl;
std::cout << "--cubes-init: starts the daemon with an empty topology" << std::endl;
std::cout << "--cubes-nodump: starts the daemon without dumping updates to file" << std::endl;
std::cout << "--cert-blacklist: path to black listed certificates"
<< std::endl;
std::cout << "--cert-whitelist: path to white listed certificates"
Expand Down Expand Up @@ -95,7 +104,10 @@ Config::Config()
server_port(SERVER_PORT),
server_ip(SERVER_IP),
logfile(LOGFILE),
configfile(CONFIGFILE) {}
configfile(CONFIGFILE),
cubes_dump_file(CUBESDUMPFILEPATH),
cubes_init(CUBESINIT),
cubes_nodump(CUBESNODUMP){}

Config::~Config() {}

Expand Down Expand Up @@ -180,6 +192,31 @@ void Config::setLogFile(const std::string &value) {
logfile = value;
}

std::string Config::getCubesDumpFilePath() const {
return cubes_dump_file;
}

void Config::setCubesDumpFilePath(const std::string &value) {
CHECK_OVERWRITE("cubes-dump", value, cubes_dump_file, CUBESDUMPFILEPATH);
cubes_dump_file = value;
}

bool Config::getCubesInitTopology() const {
return cubes_init;
}

void Config::setCubesInitTopology() {
cubes_init = true;
}

bool Config::getCubesNoDump() const {
return cubes_nodump;
}

void Config::setCubesNoDump() {
cubes_nodump = true;
}

std::string Config::getCertPath() const {
return cert_path;
}
Expand Down Expand Up @@ -246,6 +283,8 @@ void Config::create_configuration_file(const std::string &path) {
file << "addr: " << server_ip << std::endl;
file << "# file to save polycube logs" << std::endl;
file << "logfile: " << logfile << std::endl;
file << "# file to save last topology" << std::endl;
file << "cubes-dump: " << cubes_dump_file << std::endl;
file << "# Security related:" << std::endl;
file << "# server certificate " << std::endl;
file << "#cert: path_to_certificate_file" << std::endl;
Expand All @@ -270,6 +309,9 @@ void Config::dump() {
logger->info(" port: {}", server_port);
logger->info(" addr: {}", server_ip);
logger->info(" logfile: {}", logfile);
logger->info(" cubes-dump: {}", cubes_dump_file);
logger->info(" cubes-init: {}", cubes_init);
logger->info(" cubes-nodump: {}", cubes_nodump);
if (!cert_path.empty()) {
logger->info(" cert: {}", cert_path);
}
Expand Down Expand Up @@ -363,6 +405,9 @@ static struct option options[] = {
{"cacert", required_argument, NULL, 5},
{"cert-whitelist", required_argument, NULL, 6},
{"cert-blacklist", required_argument, NULL, 7},
{"cubes-dump", required_argument, NULL, 8},
{"cubes-init", no_argument, NULL, 9},
{"cubes-nodump", no_argument, NULL, 10},
{NULL, 0, NULL, 0},
};

Expand Down Expand Up @@ -408,6 +453,15 @@ void Config::load_from_cli(int argc, char *argv[]) {
case 7:
setCertBlacklistPath(optarg);
break;
case 8:
setCubesDumpFilePath(optarg);
break;
case 9:
setCubesInitTopology();
break;
case 10:
setCubesNoDump();
break;
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions src/polycubed/src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ class Config {
std::string getLogFile() const;
void setLogFile(const std::string &value);

// file where last topology is saved
std::string getCubesDumpFilePath() const;
void setCubesDumpFilePath(const std::string &value);

// set to get an empty topology
bool getCubesInitTopology() const;
void setCubesInitTopology();

// set to avoid daemon to dump updates to file
bool getCubesNoDump() const;
void setCubesNoDump();

// path of certificate & key to be used in server
std::string getCertPath() const;
void setCertPath(const std::string &value);
Expand Down Expand Up @@ -80,11 +92,14 @@ class Config {

spdlog::level::level_enum loglevel;
bool daemon;
bool cubes_init;
bool cubes_nodump;
std::string pidfile;
uint16_t server_port;
std::string server_ip;
std::string logfile;
std::string configfile;
std::string cubes_dump_file;
std::string cert_path, key_path;
std::string cacert_path;
std::string cert_whitelist_path;
Expand Down

0 comments on commit 42d1066

Please sign in to comment.