Skip to content

Commit 42d1066

Browse files
authored
Merge pull request #141 from richiMarchi/save_load_topology
load old topology at startup and save each modification to file
2 parents 2692c3f + 2b42e45 commit 42d1066

40 files changed

+1162
-118
lines changed

Documentation/polycubed/polycubed.rst

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,34 @@ If the same parameter is specified in both, the configuration file and the comma
5454
daemon: true
5555
#p: 6000 <-- this is NOT supported, only long options are
5656

57+
58+
59+
Persistency
60+
^^^^^^^^^^^
61+
62+
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.
63+
This enables polycubed also to recover from failures, such as rebooting the machine.
64+
By default, the daemon keeps in memory an instance of all the topology, including the configuration of each individual service.
65+
Topology and configuration are automatically updated at each new command; the configuration is also dumped to disk, on file ``/etc/polycube/cubes.yaml``.
66+
The standard behavior of the daemon at startup is to load the latest topology that was active at the end of the previous execution.
67+
Users can load a different topology file by using the ``--cubes-dump`` flag followed by the path to the file.
68+
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.
69+
Finally, persistency can be disabled with the ``--cubes-nodump`` flag; this would also avoid any (very limited) performance penalty introduced by this feature.
70+
71+
::
72+
73+
# start polycubed with custom cubes configuration
74+
polycubed --cubes-dump ~/Desktop/myCubes.yaml
75+
76+
# start polycubed with an empty topology
77+
polycubed --cubes-init
78+
79+
# start daemon without topology saving functionalities
80+
polycubed --cubes-nodump
81+
82+
83+
5784
Rest API
5885
^^^^^^^^
5986

60-
TODO...
87+
TODO...

src/libs/polycube/include/polycube/services/cube.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,19 @@ std::shared_ptr<PortType> Cube<PortType>::add_port(const std::string &port_name,
120120

121121
std::tie(iter, inserted) = ports_by_name_.emplace(port_name, port);
122122
ports_by_id_.emplace(port->index(), port);
123+
/*
124+
* When a transparent cube is attached to a port, it can query the service
125+
* to get some port parameters (e.g., MAC address). If the transparent cube
126+
* is attached while the port is being created these parameters will be not
127+
* configured yet.
128+
* This workaround first creates the port and then passes the configuration
129+
* to attach the transparent cubes. The configuration that is passed
130+
* in the constructor is ignored in the daemon.
131+
* The solution for this workaround would be to implement the notification
132+
* mechanishm, so when the parameters are configured those are pushed to the
133+
* transparent cube.
134+
*/
135+
port->set_conf(conf.getBase());
123136
return iter->second;
124137
} catch (const std::exception &ex) {
125138
cube_->remove_port(port_name);

src/polycubed/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ set(polycubed_sources
6262
utils/veth.cpp
6363
utils/netlink.cpp
6464
utils/utils.cpp
65+
cubes_dump.cpp
6566
${server_sources}
6667
${CMAKE_CURRENT_BINARY_DIR}/load_services.cpp
6768
${CMAKE_CURRENT_BINARY_DIR}/version.cpp)

src/polycubed/src/base_model.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,4 +244,24 @@ Response BaseModel::set_span(const std::string &cube_name,
244244
return Response{kOk, ::strdup("")};
245245
}
246246

247+
Response BaseModel::get_port_tcubes(const std::string &cube_name,
248+
const std::string &port_name) const {
249+
auto cube_ = ServiceController::get_cube(cube_name);
250+
if (cube_ == nullptr) {
251+
return Response{kNoContent, ::strdup("Cube does not exist")};
252+
}
253+
254+
// TODO: is this case even possible?
255+
auto cube = std::dynamic_pointer_cast<CubeIface>(cube_);
256+
if (cube == nullptr) {
257+
return Response{kNoContent, ::strdup("Cube is transparent")};
258+
}
259+
260+
auto port_ = cube->get_port(port_name);
261+
auto port = std::dynamic_pointer_cast<Port>(port_);
262+
nlohmann::json j = port->get_cubes_names();
263+
264+
return Response{kOk, ::strdup(j.dump().c_str())};
265+
}
266+
247267
} // namespace polycube::polycubed

src/polycubed/src/base_model.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class BaseModel {
5050
Response get_span(const std::string &cube_name) const;
5151
Response set_span(const std::string &cube_name,
5252
const nlohmann::json &json);
53+
Response get_port_tcubes(const std::string &cube_name,
54+
const std::string &port_name) const;
5355
};
5456

5557
} // namespace polycube::polycubed

src/polycubed/src/config.cpp

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,17 @@ namespace configuration {
3232

3333
#define LOGLEVEL spdlog::level::level_enum::info
3434
#define DAEMON false
35+
#define CUBESINIT false
36+
#define CUBESNODUMP false
3537
#define PIDFILE "/var/run/polycube.pid"
3638
#define SERVER_PORT 9000
3739
#define SERVER_IP "localhost"
3840
#define LOGFILE "/var/log/polycube/polycubed.log"
3941
#define CONFIGFILEDIR "/etc/polycube"
4042
#define CONFIGFILENAME "polycubed.conf"
43+
#define CUBESDUMPFILE "cubes.yaml"
4144
#define CONFIGFILE (CONFIGFILEDIR "/" CONFIGFILENAME)
45+
#define CUBESDUMPFILEPATH (CONFIGFILEDIR "/" CUBESDUMPFILE)
4246

4347
static void show_usage(const std::string &name) {
4448
std::cout << std::boolalpha;
@@ -64,6 +68,11 @@ static void show_usage(const std::string &name) {
6468
<< ")" << std::endl;
6569
std::cout << "--configfile: configuration file (default: " << CONFIGFILE
6670
<< ")" << std::endl;
71+
std::cout << "--cubes-dump: file that keeps the last topology, "
72+
"including the configuration of all cubes (default: " << CUBESDUMPFILEPATH
73+
<< ")" << std::endl;
74+
std::cout << "--cubes-init: starts the daemon with an empty topology" << std::endl;
75+
std::cout << "--cubes-nodump: starts the daemon without dumping updates to file" << std::endl;
6776
std::cout << "--cert-blacklist: path to black listed certificates"
6877
<< std::endl;
6978
std::cout << "--cert-whitelist: path to white listed certificates"
@@ -95,7 +104,10 @@ Config::Config()
95104
server_port(SERVER_PORT),
96105
server_ip(SERVER_IP),
97106
logfile(LOGFILE),
98-
configfile(CONFIGFILE) {}
107+
configfile(CONFIGFILE),
108+
cubes_dump_file(CUBESDUMPFILEPATH),
109+
cubes_init(CUBESINIT),
110+
cubes_nodump(CUBESNODUMP){}
99111

100112
Config::~Config() {}
101113

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

195+
std::string Config::getCubesDumpFilePath() const {
196+
return cubes_dump_file;
197+
}
198+
199+
void Config::setCubesDumpFilePath(const std::string &value) {
200+
CHECK_OVERWRITE("cubes-dump", value, cubes_dump_file, CUBESDUMPFILEPATH);
201+
cubes_dump_file = value;
202+
}
203+
204+
bool Config::getCubesInitTopology() const {
205+
return cubes_init;
206+
}
207+
208+
void Config::setCubesInitTopology() {
209+
cubes_init = true;
210+
}
211+
212+
bool Config::getCubesNoDump() const {
213+
return cubes_nodump;
214+
}
215+
216+
void Config::setCubesNoDump() {
217+
cubes_nodump = true;
218+
}
219+
183220
std::string Config::getCertPath() const {
184221
return cert_path;
185222
}
@@ -246,6 +283,8 @@ void Config::create_configuration_file(const std::string &path) {
246283
file << "addr: " << server_ip << std::endl;
247284
file << "# file to save polycube logs" << std::endl;
248285
file << "logfile: " << logfile << std::endl;
286+
file << "# file to save last topology" << std::endl;
287+
file << "cubes-dump: " << cubes_dump_file << std::endl;
249288
file << "# Security related:" << std::endl;
250289
file << "# server certificate " << std::endl;
251290
file << "#cert: path_to_certificate_file" << std::endl;
@@ -270,6 +309,9 @@ void Config::dump() {
270309
logger->info(" port: {}", server_port);
271310
logger->info(" addr: {}", server_ip);
272311
logger->info(" logfile: {}", logfile);
312+
logger->info(" cubes-dump: {}", cubes_dump_file);
313+
logger->info(" cubes-init: {}", cubes_init);
314+
logger->info(" cubes-nodump: {}", cubes_nodump);
273315
if (!cert_path.empty()) {
274316
logger->info(" cert: {}", cert_path);
275317
}
@@ -363,6 +405,9 @@ static struct option options[] = {
363405
{"cacert", required_argument, NULL, 5},
364406
{"cert-whitelist", required_argument, NULL, 6},
365407
{"cert-blacklist", required_argument, NULL, 7},
408+
{"cubes-dump", required_argument, NULL, 8},
409+
{"cubes-init", no_argument, NULL, 9},
410+
{"cubes-nodump", no_argument, NULL, 10},
366411
{NULL, 0, NULL, 0},
367412
};
368413

@@ -408,6 +453,15 @@ void Config::load_from_cli(int argc, char *argv[]) {
408453
case 7:
409454
setCertBlacklistPath(optarg);
410455
break;
456+
case 8:
457+
setCubesDumpFilePath(optarg);
458+
break;
459+
case 9:
460+
setCubesInitTopology();
461+
break;
462+
case 10:
463+
setCubesNoDump();
464+
break;
411465
}
412466
}
413467
}

src/polycubed/src/config.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ class Config {
5353
std::string getLogFile() const;
5454
void setLogFile(const std::string &value);
5555

56+
// file where last topology is saved
57+
std::string getCubesDumpFilePath() const;
58+
void setCubesDumpFilePath(const std::string &value);
59+
60+
// set to get an empty topology
61+
bool getCubesInitTopology() const;
62+
void setCubesInitTopology();
63+
64+
// set to avoid daemon to dump updates to file
65+
bool getCubesNoDump() const;
66+
void setCubesNoDump();
67+
5668
// path of certificate & key to be used in server
5769
std::string getCertPath() const;
5870
void setCertPath(const std::string &value);
@@ -80,11 +92,14 @@ class Config {
8092

8193
spdlog::level::level_enum loglevel;
8294
bool daemon;
95+
bool cubes_init;
96+
bool cubes_nodump;
8397
std::string pidfile;
8498
uint16_t server_port;
8599
std::string server_ip;
86100
std::string logfile;
87101
std::string configfile;
102+
std::string cubes_dump_file;
88103
std::string cert_path, key_path;
89104
std::string cacert_path;
90105
std::string cert_whitelist_path;

0 commit comments

Comments
 (0)