initial commit

This commit is contained in:
faraphel 2024-12-22 23:05:52 +01:00
commit 811f80c92c
17 changed files with 549 additions and 0 deletions

41
source/gns3/GnsNode.cpp Normal file
View file

@ -0,0 +1,41 @@
#include "GnsNode.hpp"
#include "GnsPort.hpp"
#include "GnsProject.hpp"
#include <cpr/cpr.h>
#include <vector>
namespace gns {
GnsNode::GnsNode(const GnsProject *project, std::string uuid, const std::vector<GnsPort>& ports) {
this->project = project;
this->uuid = std::move(uuid);
this->ports = ports;
}
std::string GnsNode::getApiBase() const {
return this->project->getApiBase() + "nodes/" + this->uuid;
}
std::string GnsNode::getUuid() const {
return this->uuid;
}
std::vector<GnsPort> GnsNode::getPorts() const {
return this->ports;
}
void GnsNode::start() const {
// request the API endpoint
cpr::Url endpoint = this->getApiBase() + "start";
cpr::Response response = Post(endpoint);
// check for a valid response
if (response.error.code != cpr::ErrorCode::OK)
throw std::runtime_error(response.error.message);
}
}

53
source/gns3/GnsNode.hpp Normal file
View file

@ -0,0 +1,53 @@
#pragma once
#include "GnsPort.hpp"
#include <string>
#include <vector>
namespace gns {
class GnsProject;
/**
* Represent a GNS3 node
*/
class GnsNode {
public:
GnsNode(const GnsProject* project, std::string uuid, const std::vector<GnsPort>& ports);
/**
* Get the base URL for the node API
* @return the base URL for the node API
*/
[[nodiscard]] std::string getApiBase() const;
/**
* Get the uuid of the node
* @return the uuid of the node
*/
[[nodiscard]] std::string getUuid() const;
/**
* Get the ports of the node
* @return the ports of the node
*/
[[nodiscard]] std::vector<GnsPort> getPorts() const;
/**
* Start the node
*/
void start() const;
private:
const GnsProject* project;
std::string uuid;
std::vector<GnsPort> ports;
};
}

12
source/gns3/GnsPort.cpp Normal file
View file

@ -0,0 +1,12 @@
#include "GnsPort.hpp"
namespace gns {
GnsPort::GnsPort(const std::optional<std::string>& mac_address) {
this->mac_address = mac_address;
}
}

20
source/gns3/GnsPort.hpp Normal file
View file

@ -0,0 +1,20 @@
#pragma once
#include <optional>
#include <string>
namespace gns {
/**
* Represent a port of a GNS3 node
*/
class GnsPort {
public:
explicit GnsPort(const std::optional<std::string>& mac_address);
std::optional<std::string> mac_address;
};
}

View file

@ -0,0 +1,74 @@
#include "GnsProject.hpp"
#include "GnsServer.hpp"
#include "GnsPort.hpp"
#include <cpr/cpr.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace gns {
GnsProject::GnsProject(const GnsServer* server, std::string uuid) {
this->server = server;
this->uuid = std::move(uuid);
}
std::string GnsProject::getApiBase() const {
return this->server->getApiBase() + "projects/" + this->uuid + "/";
}
std::string GnsProject::getUuid() const {
return this->uuid;
}
std::vector<GnsNode> GnsProject::getNodes() const {
std::vector<GnsNode> nodes;
// request the API endpoint
cpr::Url endpoint = this->getApiBase() + "nodes";
cpr::Response response = Get(endpoint);
// check for a valid response
if (response.error.code != cpr::ErrorCode::OK)
throw std::runtime_error(response.error.message);
// check for valid content
if (response.header["Content-Type"] != "application/json")
throw std::runtime_error("Data must be JSON formatted.");
// parse the data
json data = json::parse(response.text);
// deserialize the projects
nodes.reserve(data.size());
for (const auto& node_data : data) {
// parse the ports of the node
std::vector<json> ports_data = node_data.value("ports", std::vector<json>{});
std::vector<GnsPort> ports;
ports.reserve(ports_data.size());
for (const auto& port_data : ports_data) {
// get the mac of the port
std::optional<std::string> mac_address;
if (port_data.contains("mac_address"))
mac_address.emplace(port_data["mac_address"]);
// save the port data
ports.emplace_back(mac_address);
}
// save the node
nodes.emplace_back(
this,
node_data["node_id"],
ports
);
}
return nodes;
}
}

View file

@ -0,0 +1,45 @@
#pragma once
#include <string>
#include <vector>
#include "GnsNode.hpp"
namespace gns {
class GnsServer;
/**
* Represent a GNS3 project.
*/
class GnsProject {
public:
GnsProject(const GnsServer* server, std::string uuid);
/**
* Get the base prefix for an API request
* @return the base prefix for an API request
*/
[[nodiscard]] std::string getApiBase() const;
/**
* Get the uuid of the project
* @return the uuid of the project
*/
[[nodiscard]] std::string getUuid() const;
/**
* Get all the nodes of the project
* @return all the nodes of the project
*/
[[nodiscard]] std::vector<GnsNode> getNodes() const;
private:
const GnsServer* server;
std::string uuid;
};
}

62
source/gns3/GnsServer.cpp Normal file
View file

@ -0,0 +1,62 @@
#include "GnsServer.hpp"
#include <cpr/cpr.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace gns {
GnsServer::GnsServer(const std::string &host, const std::uint16_t port) {
this->host = host;
this->port = port;
}
std::string GnsServer::getApiBase() const {
return "http://" + this->host + ":" + std::to_string(this->port) + "/v2/";
}
std::vector<GnsProject> GnsServer::getProjects() const {
std::vector<GnsProject> projects;
// request the API endpoint
cpr::Url endpoint = this->getApiBase() + "projects";
cpr::Response response = Get(endpoint);
// check for a valid response
if (response.error.code != cpr::ErrorCode::OK)
throw std::runtime_error(response.error.message);
// check for valid content
if (response.header["Content-Type"] != "application/json")
throw std::runtime_error("Data must be JSON formatted.");
// parse the data
json data = json::parse(response.text);
// deserialize the projects
projects.reserve(data.size());
for (const auto& project_data : data)
projects.emplace_back(
this,
project_data["project_id"]
);
return projects;
}
std::vector<GnsNode> GnsServer::getNodes() const {
std::vector<GnsNode> nodes;
// get all the nodes from all the projects
for (const GnsProject& project : this->getProjects()) {
std::vector<GnsNode> project_nodes = project.getNodes();
nodes.insert(nodes.end(), project_nodes.begin(), project_nodes.end());
}
return nodes;
}
}

44
source/gns3/GnsServer.hpp Normal file
View file

@ -0,0 +1,44 @@
#pragma once
#include <string>
#include <cstdint>
#include <vector>
#include "GnsProject.hpp"
namespace gns {
/**
* Represent a GNS3 server
* Wrapper around the GNS3 API (https://gns3-server.readthedocs.io/en/latest/endpoints.html)
*/
class GnsServer {
public:
GnsServer(const std::string& host, std::uint16_t port);
/**
* Get the base prefix for an API request
* @return the base prefix for an API request
*/
[[nodiscard]] std::string getApiBase() const;
/**
* Get all the projects in the server
* @return all the projects in the server
*/
[[nodiscard]] std::vector<GnsProject> getProjects() const;
/**
* Get all the nodes in the server
* @return all the nodes in the server
*/
[[nodiscard]] std::vector<GnsNode> getNodes() const;
private:
std::string host;
std::uint16_t port;
};
}