Stubs for get/set ipv4/ipv6, destroy netdev and list netdev 21/35621/8
authorMateusz Malicki <m.malicki2@samsung.com>
Thu, 19 Feb 2015 14:44:34 +0000 (15:44 +0100)
committerMateusz Malicki <m.malicki2@samsung.com>
Mon, 2 Mar 2015 16:18:38 +0000 (17:18 +0100)
[Feature]       Stubs (cli, client, server) for get/set ipv4/ipv6,
                destroy netdev and list netdev netdev
[Cause]         N/A
[Solution]      N/A
[Verification]  Build, run cli commnads

Change-Id: Ia1dc21e5fb252b2f83d617abec785bce7d6ffc9e

18 files changed:
cli/command-line-interface.cpp
cli/command-line-interface.hpp
cli/main.cpp
client/CMakeLists.txt
client/vasum-client-impl.cpp
client/vasum-client-impl.hpp
client/vasum-client.cpp
client/vasum-client.h
common/netlink/netlink-message.cpp
server/host-connection.cpp
server/host-connection.hpp
server/host-dbus-definitions.hpp
server/zone-admin.cpp
server/zone-admin.hpp
server/zone.cpp
server/zone.hpp
server/zones-manager.cpp
server/zones-manager.hpp

index a189a92..77e9dc5 100644 (file)
@@ -38,6 +38,7 @@
 #include <fcntl.h>
 #include <cassert>
 #include <linux/if_link.h>
+#include <arpa/inet.h>
 
 using namespace std;
 
@@ -394,5 +395,133 @@ void create_netdev_phys(int pos, int argc, const char** argv)
                   argv[pos + 2]));
 }
 
+void zone_get_netdevs(int pos, int argc, const char** argv)
+{
+    using namespace std::placeholders;
+
+    if (argc <= pos + 1) {
+        throw runtime_error("Not enough parameters");
+    }
+    VsmArrayString ids;
+    one_shot(bind(vsm_zone_get_netdevs,
+                  _1,
+                  argv[pos + 1],
+                  &ids));
+    string delim;
+    for (VsmString* id = ids; *id; ++id) {
+        cout << delim << *id;
+        delim = ", ";
+    }
+    if (delim.empty()) {
+        cout << "There is no network device in zone";
+    }
+    cout << endl;
+    vsm_array_string_free(ids);
+}
+
+void netdev_get_ipv4_addr(int pos, int argc, const char** argv)
+{
+    using namespace std::placeholders;
+
+    if (argc <= pos + 2) {
+        throw runtime_error("Not enough parameters");
+    }
+    in_addr addr;
+    one_shot(bind(vsm_netdev_get_ipv4_addr,
+                  _1,
+                  argv[pos + 1],
+                  argv[pos + 2],
+                  &addr));
+    char buf[INET_ADDRSTRLEN];
+    if (inet_ntop(AF_INET, &addr, buf, INET_ADDRSTRLEN) == NULL) {
+        throw runtime_error("Server gave the wrong address format");
+    }
+    cout << buf << endl;
+}
+
+void netdev_get_ipv6_addr(int pos, int argc, const char** argv)
+{
+    using namespace std::placeholders;
+
+    if (argc <= pos + 2) {
+        throw runtime_error("Not enough parameters");
+    }
+    in6_addr addr;
+    one_shot(bind(vsm_netdev_get_ipv6_addr,
+                  _1,
+                  argv[pos + 1],
+                  argv[pos + 2],
+                  &addr));
+    char buf[INET6_ADDRSTRLEN];
+    if (inet_ntop(AF_INET6, &addr, buf, INET6_ADDRSTRLEN) == NULL) {
+        throw runtime_error("Server gave the wrong address format");
+    }
+    cout << buf << endl;
+}
+
+void netdev_set_ipv4_addr(int pos, int argc, const char** argv)
+{
+    using namespace std::placeholders;
+
+    if (argc <= pos + 4) {
+        throw runtime_error("Not enough parameters");
+    }
+    in_addr addr;
+    if (inet_pton(AF_INET, argv[pos + 3], &addr) != 1) {
+        throw runtime_error("Wrong address format");
+    };
+    one_shot(bind(vsm_netdev_set_ipv4_addr,
+                  _1,
+                  argv[pos + 1],
+                  argv[pos + 2],
+                  &addr,
+                  stoi(argv[pos + 4])));
+}
+
+void netdev_set_ipv6_addr(int pos, int argc, const char** argv)
+{
+    using namespace std::placeholders;
+
+    if (argc <= pos + 4) {
+        throw runtime_error("Not enough parameters");
+    }
+    in6_addr addr;
+    if (inet_pton(AF_INET6, argv[pos + 3], &addr) != 1) {
+        throw runtime_error("Wrong address format");
+    };
+    one_shot(bind(vsm_netdev_set_ipv6_addr,
+                  _1,
+                  argv[pos + 1],
+                  argv[pos + 2],
+                  &addr,
+                  stoi(argv[pos + 4])));
+}
+
+void netdev_up(int pos, int argc, const char** argv)
+{
+    using namespace std::placeholders;
+
+    if (argc <= pos + 2) {
+        throw runtime_error("Not enough parameters");
+    }
+    one_shot(bind(vsm_netdev_up,
+                  _1,
+                  argv[pos + 1],
+                  argv[pos + 2]));
+}
+
+void netdev_down(int pos, int argc, const char** argv)
+{
+    using namespace std::placeholders;
+
+    if (argc <= pos + 2) {
+        throw runtime_error("Not enough parameters");
+    }
+    one_shot(bind(vsm_netdev_down,
+                  _1,
+                  argv[pos + 1],
+                  argv[pos + 2]));
+}
+
 } // namespace cli
 } // namespace vasum
index 34ac013..eb33428 100644 (file)
@@ -208,6 +208,55 @@ void create_netdev_macvlan(int pos, int argc, const char** argv);
  */
 void create_netdev_phys(int pos, int argc, const char** argv);
 
+/**
+ * Parses command line arguments and prints result of vsm_zone_get_netdevs
+ *
+ * @see vsm_zone_get_netdevs
+ */
+void zone_get_netdevs(int pos, int argc, const char** argv);
+
+/**
+ * Parses command line arguments and prints result of vsm_netdev_get_ipv4_addr
+ *
+ * @see vsm_netdev_get_ipv4_addr
+ */
+void netdev_get_ipv4_addr(int pos, int argc, const char** argv);
+
+/**
+ * Parses command line arguments and and prints result of vsm_netdev_get_ipv6_addr
+ *
+ * @see vsm_netdev_get_ipv6_addr
+ */
+void netdev_get_ipv6_addr(int pos, int argc, const char** argv);
+
+/**
+ * Parses command line arguments and call vsm_netdev_set_ipv4_addr
+ *
+ * @see vsm_netdev_set_ipv4_addr
+ */
+void netdev_set_ipv4_addr(int pos, int argc, const char** argv);
+
+/**
+ * Parses command line arguments and call vsm_netdev_set_ipv6_addr
+ *
+ * @see vsm_netdev_set_ipv6_addr
+ */
+void netdev_set_ipv6_addr(int pos, int argc, const char** argv);
+
+/**
+ * Parses command line arguments and call vsm_netdev_up
+ *
+ * @see vsm_netdev_up
+ */
+void netdev_up(int pos, int argc, const char** argv);
+
+/**
+ * Parses command line arguments and call vsm_netdev_down
+ *
+ * @see vsm_netdev_down
+ */
+void netdev_down(int pos, int argc, const char** argv);
+
 } // namespace cli
 } // namespace vasum
 
index 38a8ae5..5f073be 100644 (file)
@@ -170,6 +170,72 @@ std::map<std::string, CommandLineInterface> commands = {
             {{"zone_id", "id zone name"},
              {"devId", "network device id"}}
         }
+    },
+    {
+        "zone_get_netdevs", {
+            zone_get_netdevs,
+            "zone_get_netdevs zone_id",
+            "List network devices in the zone",
+            {{"zone_id", "id zone name"}}
+        }
+    },
+    {
+        "netdev_get_ipv4_addr", {
+            netdev_get_ipv4_addr,
+            "netdev_get_ipv4_addr zone_id netdev_id",
+            "Get ipv4 address",
+            {{"zone_id", "id zone name"},
+             {"netdev_id", "network device name"}}
+        }
+    },
+    {
+        "netdev_get_ipv6_addr", {
+            netdev_get_ipv6_addr,
+            "netdev_get_ipv6_addr zone_id netdev_id",
+            "Get ipv6 address",
+            {{"zone_id", "id zone name"},
+             {"netdev_id", "network device name"}}
+        }
+    },
+    {
+        "netdev_set_ipv4_addr", {
+            netdev_set_ipv4_addr,
+            "netdev_set_ipv4_addr zone_id netdev_id address prefix_len",
+            "Set ipv4 address",
+            {{"zone_id", "id zone name"},
+             {"netdev_id", "network device name"},
+             {"address", "ipv4 address"},
+             {"prefix_len", "bit length of prefix"}}
+        }
+    },
+    {
+        "netdev_set_ipv6_addr", {
+            netdev_set_ipv6_addr,
+            "netdev_set_ipv6_addr zone_id netdev_id address prefix_len",
+            "Set ipv6 address",
+            {{"zone_id", "id zone name"},
+             {"netdev_id", "network device name"},
+             {"address", "ipv6 address"},
+             {"prefix_len", "bit length of prefix"}}
+        }
+    },
+    {
+        "netdev_up", {
+            netdev_up,
+            "netdev_up zone_id netdev_id",
+            "Turn up a network device in the zone",
+            {{"zone_id", "id zone name"},
+             {"netdev_id", "network device id"}}
+        }
+    },
+    {
+        "zone_get_netdevs", {
+            zone_get_netdevs,
+            "zone_get_netdevs zone_id",
+            "Turn down a network device in the zone",
+            {{"zone_id", "id zone name"},
+             {"netdev_id", "network device id"}}
+        }
     }
 };
 
index 7060b7b..558f3a7 100644 (file)
@@ -23,7 +23,9 @@ FILE(GLOB project_SRCS *.cpp *.hpp *.h)
 FILE(GLOB common_SRCS ${COMMON_FOLDER}/utils/callback-guard.hpp
                       ${COMMON_FOLDER}/utils/callback-guard.cpp
                       ${COMMON_FOLDER}/utils/glib-loop.cpp
-                      ${COMMON_FOLDER}/utils/glib-loop.hpp)
+                      ${COMMON_FOLDER}/utils/glib-loop.hpp
+                      ${COMMON_FOLDER}/base-exception.hpp
+                      ${COMMON_FOLDER}/base-exception.cpp)
 
 SET(_LIB_VERSION_ "0.0.1")
 SET(_LIB_SOVERSION_ "0")
index d6f4217..d8ba562 100644 (file)
 #include <utils/glib-loop.hpp>
 #include <host-dbus-definitions.hpp>
 #include <zone-dbus-definitions.hpp>
+#include <base-exception.hpp>
 
+#include <algorithm>
+#include <tuple>
+#include <vector>
 #include <cstring>
 #include <cassert>
 #include <fstream>
+#include <arpa/inet.h>
 
 using namespace std;
 using namespace dbus;
@@ -77,6 +82,21 @@ void toDict(GVariant* in, VsmArrayString* keys, VsmArrayString* values)
     *values = outv;
 }
 
+vector<tuple<string, string>> toDict(GVariant* in)
+{
+    assert(in);
+
+    const gchar* key;
+    const gchar* value;
+    vector<tuple<string, string>> dict;
+    GVariantIter iter;
+    g_variant_iter_init(&iter, in);
+    while (g_variant_iter_loop(&iter, "(&s&s)", &key, &value)) {
+        dict.push_back(make_tuple<string, string>(key, value));
+    }
+    return dict;
+}
+
 void toBasic(GVariant* in, char** str)
 {
     assert(in);
@@ -152,6 +172,37 @@ void toArray(GVariant* in, T** scArray)
     *scArray = ids;
 }
 
+string toString(const in_addr* addr)
+{
+    char buf[INET_ADDRSTRLEN];
+    const char* ret = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
+    if (ret == NULL) {
+        throw runtime_error(getSystemErrorMessage());
+    }
+    return ret;
+}
+
+string toString(const in6_addr* addr)
+{
+    char buf[INET6_ADDRSTRLEN];
+    const char* ret = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
+    if (ret == NULL) {
+        throw runtime_error(getSystemErrorMessage());
+    }
+    return ret;
+}
+
+GVariant* createTupleArray(const vector<tuple<string, string>>& dict)
+{
+    GVariantBuilder builder;
+    g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+    for (const auto entry : dict) {
+        g_variant_builder_add(&builder, "(ss)", get<0>(entry).c_str(), get<1>(entry).c_str());
+    }
+    return g_variant_builder_end(&builder);
+}
+
+
 VsmStatus toStatus(const exception& ex)
 {
     if (typeid(DbusCustomException) == typeid(ex)) {
@@ -530,34 +581,162 @@ VsmStatus Client::vsm_revoke_device(const char* id, const char* device) noexcept
     return callMethod(HOST_INTERFACE, api::host::METHOD_REVOKE_DEVICE, args_in);
 }
 
-VsmStatus Client::vsm_zone_get_netdevs(const char*, VsmArrayString*) noexcept
+VsmStatus Client::vsm_zone_get_netdevs(const char* zone, VsmArrayString* netdevIds) noexcept
 {
-    mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented");
-    return vsm_get_status();
+    assert(zone);
+    assert(netdevIds);
+
+    GVariant* out = NULL;
+    GVariant* args_in = g_variant_new("(s)", zone);
+    VsmStatus ret = callMethod(HOST_INTERFACE,
+                               api::host::METHOD_GET_NETDEV_LIST,
+                               args_in,
+                               "(as)",
+                               &out);
+    if (ret != VSMCLIENT_SUCCESS) {
+        return ret;
+    }
+    GVariant* unpacked;
+    g_variant_get(out, "(*)", &unpacked);
+    toArray(unpacked, netdevIds);
+    g_variant_unref(unpacked);
+    g_variant_unref(out);
+    return ret;
 }
 
-VsmStatus Client::vsm_netdev_get_ipv4_addr(const char*, const char*, struct in_addr*) noexcept
+VsmStatus Client::vsm_netdev_get_ipv4_addr(const char* zone,
+                                           const char* netdevId,
+                                           struct in_addr* addr) noexcept
 {
-    mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented");
+    assert(zone);
+    assert(netdevId);
+    assert(addr);
+
+    GVariant* out = NULL;
+    GVariant* args_in = g_variant_new("(ss)", zone, netdevId);
+    VsmStatus ret = callMethod(HOST_INTERFACE,
+                               api::host::METHOD_GET_NETDEV_ATTRS,
+                               args_in,
+                               "(a(ss))",
+                               &out);
+    if (ret != VSMCLIENT_SUCCESS) {
+        return ret;
+    }
+    GVariant* unpacked;
+    g_variant_get(out, "(*)", &unpacked);
+    vector<tuple<string, string>> attrs = toDict(unpacked);
+    g_variant_unref(unpacked);
+    g_variant_unref(out);
+
+    auto it = find_if(attrs.begin(), attrs.end(), [](const tuple<string, string>& entry) {
+            return get<0>(entry) == "ipv4";
+    });
+    if (it != attrs.end()) {
+       if (inet_pton(AF_INET, get<1>(*it).c_str(), addr) != 1) {
+           mStatus = Status(VSMCLIENT_CUSTOM_ERROR, "Invalid response data");
+           return vsm_get_status();
+       }
+       mStatus = Status();
+       return vsm_get_status();
+    }
+    mStatus = Status(VSMCLIENT_CUSTOM_ERROR, "Address not found");
     return vsm_get_status();
 }
 
-VsmStatus Client::vsm_netdev_get_ipv6_addr(const char*, const char*, struct in6_addr*) noexcept
+VsmStatus Client::vsm_netdev_get_ipv6_addr(const char* zone,
+                                           const char* netdevId,
+                                           struct in6_addr* addr) noexcept
 {
-    mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented");
+    assert(zone);
+    assert(netdevId);
+    assert(addr);
+
+    GVariant* out = NULL;
+    GVariant* args_in = g_variant_new("(ss)", zone, netdevId);
+    VsmStatus ret = callMethod(HOST_INTERFACE,
+                               api::host::METHOD_GET_NETDEV_ATTRS,
+                               args_in,
+                               "(a(ss))",
+                               &out);
+    if (ret != VSMCLIENT_SUCCESS) {
+        return ret;
+    }
+    GVariant* unpacked;
+    g_variant_get(out, "(*)", &unpacked);
+    vector<tuple<string, string>> attrs = toDict(unpacked);
+    g_variant_unref(unpacked);
+    g_variant_unref(out);
+
+    //XXX: return only one address
+    auto it = find_if(attrs.begin(), attrs.end(), [](const tuple<string, string>& entry) {
+            return get<0>(entry) == "ipv6";
+    });
+    if (it != attrs.end()) {
+       if (inet_pton(AF_INET6, get<1>(*it).c_str(), addr) != 1) {
+           mStatus = Status(VSMCLIENT_CUSTOM_ERROR, "Invalid response data");
+           return vsm_get_status();
+       }
+       mStatus = Status();
+       return vsm_get_status();
+    }
+    mStatus = Status(VSMCLIENT_CUSTOM_ERROR, "Address not found");
     return vsm_get_status();
 }
 
-VsmStatus Client::vsm_netdev_set_ipv4_addr(const char*, const char*, struct in_addr*, int) noexcept
+VsmStatus Client::vsm_netdev_set_ipv4_addr(const char* zone,
+                                           const char* netdevId,
+                                           struct in_addr* addr,
+                                           int mask) noexcept
 {
-    mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented");
-    return vsm_get_status();
+    try {
+        GVariant* dict = createTupleArray({make_tuple("ipv4", toString(addr)),
+                                          make_tuple("mask", to_string(mask))});
+        GVariant* args_in = g_variant_new("(ss@a(ss))", zone, netdevId, dict);
+        return callMethod(HOST_INTERFACE, api::host::METHOD_SET_NETDEV_ATTRS, args_in);
+    } catch (exception& ex) {
+        mStatus = Status(VSMCLIENT_INVALID_ARGUMENT, ex.what());
+        return vsm_get_status();
+    }
 }
 
-VsmStatus Client::vsm_netdev_set_ipv6_addr(const char*, const char*, struct in6_addr*, int) noexcept
+VsmStatus Client::vsm_netdev_set_ipv6_addr(const char* zone,
+                                           const char* netdevId,
+                                           struct in6_addr* addr,
+                                           int mask) noexcept
 {
-    mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented");
-    return vsm_get_status();
+    try {
+        GVariant* dict = createTupleArray({make_tuple("ipv6", toString(addr)),
+                                          make_tuple("mask", to_string(mask))});
+        GVariant* args_in = g_variant_new("(ss@a(ss))", zone, netdevId, dict);
+        return callMethod(HOST_INTERFACE, api::host::METHOD_SET_NETDEV_ATTRS, args_in);
+    } catch (exception& ex) {
+        mStatus = Status(VSMCLIENT_INVALID_ARGUMENT, ex.what());
+        return vsm_get_status();
+    }
+}
+
+VsmStatus Client::vsm_netdev_up(const char* zone, const char* netdevId) noexcept
+{
+    try {
+        GVariant* dict = createTupleArray({make_tuple("up", "true")});
+        GVariant* args_in = g_variant_new("(ss@a(ss))", zone, netdevId, dict);
+        return callMethod(HOST_INTERFACE, api::host::METHOD_SET_NETDEV_ATTRS, args_in);
+    } catch (exception& ex) {
+        mStatus = Status(VSMCLIENT_INVALID_ARGUMENT, ex.what());
+        return vsm_get_status();
+    }
+}
+
+VsmStatus Client::vsm_netdev_down(const char* zone, const char* netdevId) noexcept
+{
+    try {
+        GVariant* dict = createTupleArray({make_tuple("up", "false")});
+        GVariant* args_in = g_variant_new("(ss@a(ss))", zone, netdevId, dict);
+        return callMethod(HOST_INTERFACE, api::host::METHOD_SET_NETDEV_ATTRS, args_in);
+    } catch (exception& ex) {
+        mStatus = Status(VSMCLIENT_INVALID_ARGUMENT, ex.what());
+        return vsm_get_status();
+    }
 }
 
 VsmStatus Client::vsm_create_netdev_veth(const char* zone,
index 193f140..9399839 100644 (file)
@@ -229,6 +229,16 @@ public:
                                        int prefix) noexcept;
 
     /**
+     *  @see ::vsm_netdev_up
+     */
+    VsmStatus vsm_netdev_up(const char* zone, const char* netdevId) noexcept;
+
+    /**
+     *  @see ::vsm_netdev_down
+     */
+    VsmStatus vsm_netdev_down(const char* zone, const char* netdevId) noexcept;
+
+    /**
      *  @see ::vsm_create_netdev_veth
      */
     VsmStatus vsm_create_netdev_veth(const char* zone,
index 1f011c1..9c0ca60 100644 (file)
@@ -250,6 +250,20 @@ API VsmStatus vsm_netdev_set_ipv6_addr(VsmClient client,
     return getClient(client).vsm_netdev_set_ipv6_addr(zone, netdevId, addr, prefix);
 }
 
+API VsmStatus vsm_netdev_up(VsmClient client,
+                            const char* zone,
+                            const char* netdevId)
+{
+    return getClient(client).vsm_netdev_up(zone, netdevId);
+}
+
+API VsmStatus vsm_netdev_down(VsmClient client,
+                              const char* zone,
+                              const char* netdevId)
+{
+    return getClient(client).vsm_netdev_down(zone, netdevId);
+}
+
 API VsmStatus vsm_create_netdev_veth(VsmClient client,
                                      const char* zone,
                                      const char* zoneDev,
index 1fb48b1..0bd40ad 100644 (file)
@@ -552,6 +552,31 @@ VsmStatus vsm_netdev_set_ipv6_addr(VsmClient client,
                                    int prefix);
 
 /**
+ * Turn up a network device in the zone
+ *
+ * @param[in] client vasum-server's client
+ * @param[in] zone zone name
+ * @param[in] netdevId netdev id
+ * @return status of this function call
+ */
+VsmStatus vsm_netdev_up(VsmClient client,
+                        const char* zone,
+                        const char* netdevId);
+
+/**
+ * Turn down a network device in the zone
+ *
+ * @param[in] client vasum-server's client
+ * @param[in] zone zone name
+ * @param[in] netdevId netdev id
+ * @return status of this function call
+ */
+VsmStatus vsm_netdev_down(VsmClient client,
+                          const char* zone,
+                          const char* netdevId);
+
+
+/**
  * Create veth netdev in zone
  *
  * @param[in] client vasum-server's client
index 72d3597..9f33450 100644 (file)
 #define PAGE_SIZE 4096
 #endif
 
+namespace {
+
 const int NLMSG_GOOD_SIZE = 2*PAGE_SIZE;
-constexpr rtattr* NLMSG_TAIL(nlmsghdr* nmsg)
+inline rtattr* NLMSG_TAIL(nlmsghdr* nmsg)
 {
     return reinterpret_cast<rtattr*>(reinterpret_cast<char*>(nmsg) + NLMSG_ALIGN(nmsg->nlmsg_len));
 }
 
+} // namespace
+
 namespace vasum {
 namespace netlink {
 
index 75c4433..6790480 100644 (file)
@@ -130,6 +130,21 @@ void HostConnection::setGetZoneInfoCallback(const GetZoneInfoCallback& callback)
     mGetZoneInfoCallback = callback;
 }
 
+void HostConnection::setSetNetdevAttrsCallback(const SetNetdevAttrsCallback& callback)
+{
+    mSetNetdevAttrsCallback = callback;
+}
+
+void HostConnection::setGetNetdevAttrsCallback(const GetNetdevAttrsCallback& callback)
+{
+    mGetNetdevAttrsCallback = callback;
+}
+
+void HostConnection::setGetNetdevListCallback(const GetNetdevListCallback& callback)
+{
+    mGetNetdevListCallback = callback;
+}
+
 void HostConnection::setCreateNetdevVethCallback(const CreateNetdevVethCallback& callback)
 {
     mCreateNetdevVethCallback = callback;
@@ -296,6 +311,44 @@ void HostConnection::onMessageCall(const std::string& objectPath,
         return;
     }
 
+    if (methodName == api::host::METHOD_SET_NETDEV_ATTRS){
+        const gchar* zone = NULL;
+        const gchar* netdev = NULL;
+        GVariantIter* iter;
+        g_variant_get(parameters, "(&s&sa(ss))", &zone, &netdev, &iter);
+        gchar* key = NULL;
+        gchar* value = NULL;
+        std::vector<std::tuple<std::string, std::string>> attrs;
+        while (g_variant_iter_loop(iter, "(&s&s)", &key, &value)) {
+            attrs.push_back(std::make_tuple<std::string, std::string>(key, value));
+        }
+        g_variant_iter_free(iter);
+        if (mSetNetdevAttrsCallback) {
+            mSetNetdevAttrsCallback(zone, netdev, attrs, result);
+        }
+        return;
+    }
+
+    if (methodName == api::host::METHOD_GET_NETDEV_ATTRS){
+        const gchar* zone = NULL;
+        const gchar* netdev = NULL;
+        g_variant_get(parameters, "(&s&s)", &zone, &netdev);
+        if (mGetNetdevAttrsCallback) {
+            mGetNetdevAttrsCallback(zone, netdev, result);
+        }
+        return;
+    }
+
+    if (methodName == api::host::METHOD_GET_NETDEV_LIST){
+        const gchar* zone = NULL;
+        g_variant_get(parameters, "(&s)", &zone);
+        if (mGetNetdevListCallback) {
+            mGetNetdevListCallback(zone, result);
+        }
+        return;
+    }
+
+
     if (methodName == api::host::METHOD_CREATE_NETDEV_VETH) {
         const gchar* id = NULL;
         const gchar* zoneDev = NULL;
index 649ed15..569c68f 100644 (file)
@@ -30,6 +30,8 @@
 
 #include <mutex>
 #include <condition_variable>
+#include <tuple>
+#include <vector>
 
 
 namespace vasum {
@@ -60,8 +62,20 @@ public:
     typedef std::function<void(const std::string& id,
                                dbus::MethodResultBuilder::Pointer result
                               )> GetZoneInfoCallback;
-    typedef std::function<void(const std::string& id,
-                               const std::string& zoneDev,
+    typedef std::function<void(const std::string& zone,
+                               const std::string& netdev,
+                               const std::vector<std::tuple<std::string, std::string>>& attrs,
+                               dbus::MethodResultBuilder::Pointer result
+                              )> SetNetdevAttrsCallback;
+    typedef std::function<void(const std::string& zone,
+                               const std::string& netdev,
+                               dbus::MethodResultBuilder::Pointer result
+                              )> GetNetdevAttrsCallback;
+    typedef std::function<void(const std::string& zone,
+                               dbus::MethodResultBuilder::Pointer result
+                              )> GetNetdevListCallback;
+    typedef std::function<void(const std::string& zone,
+                               const std::string& netdev,
                                const std::string& hostDev,
                                dbus::MethodResultBuilder::Pointer result
                               )> CreateNetdevVethCallback;
@@ -165,6 +179,21 @@ public:
     void setGetZoneInfoCallback(const GetZoneInfoCallback& callback);
 
     /**
+     * Register a callback called to set network device attributes
+     */
+    void setSetNetdevAttrsCallback(const SetNetdevAttrsCallback& callback);
+
+    /**
+     * Register a callback called to get network device attributes
+     */
+    void setGetNetdevAttrsCallback(const GetNetdevAttrsCallback& callback);
+
+    /**
+     * Register a callback called to get network device list
+     */
+    void setGetNetdevListCallback(const GetNetdevListCallback& callback);
+
+    /**
      * Register a callback called to create veth
      */
     void setCreateNetdevVethCallback(const CreateNetdevVethCallback& callback);
@@ -270,6 +299,9 @@ private:
     GetZoneIdsCallback mGetZoneIdsCallback;
     GetActiveZoneIdCallback mGetActiveZoneIdCallback;
     GetZoneInfoCallback mGetZoneInfoCallback;
+    SetNetdevAttrsCallback mSetNetdevAttrsCallback;
+    GetNetdevAttrsCallback mGetNetdevAttrsCallback;
+    GetNetdevListCallback mGetNetdevListCallback;
     CreateNetdevVethCallback mCreateNetdevVethCallback;
     CreateNetdevMacvlanCallback mCreateNetdevMacvlanCallback;
     CreateNetdevPhysCallback mCreateNetdevPhysCallback;
index 6d25bb1..2c2a201 100644 (file)
@@ -42,6 +42,9 @@ const std::string METHOD_GET_ZONE_DBUSES       = "GetZoneDbuses";
 const std::string METHOD_GET_ZONE_ID_LIST      = "GetZoneIds";
 const std::string METHOD_GET_ACTIVE_ZONE_ID    = "GetActiveZoneId";
 const std::string METHOD_GET_ZONE_INFO         = "GetZoneInfo";
+const std::string METHOD_SET_NETDEV_ATTRS      = "SetNetdevAttrs";
+const std::string METHOD_GET_NETDEV_ATTRS      = "GetNetdevAttrs";
+const std::string METHOD_GET_NETDEV_LIST       = "GetNetdevList";
 const std::string METHOD_CREATE_NETDEV_VETH    = "CreateNetdevVeth";
 const std::string METHOD_CREATE_NETDEV_MACVLAN = "CreateNetdevMacvlan";
 const std::string METHOD_CREATE_NETDEV_PHYS    = "CreateNetdevPhys";
@@ -88,6 +91,20 @@ const std::string DEFINITION =
     "      <arg type='s' name='id' direction='in'/>"
     "      <arg type='(siss)' name='result' direction='out'/>"
     "    </method>"
+    "    <method name='" + METHOD_SET_NETDEV_ATTRS + "'>"
+    "      <arg type='s' name='zone' direction='in'/>"
+    "      <arg type='s' name='netdev' direction='in'/>"
+    "      <arg type='a(ss)' name='attributes' direction='in'/>"
+    "    </method>"
+    "    <method name='" + METHOD_GET_NETDEV_ATTRS + "'>"
+    "      <arg type='s' name='zone' direction='in'/>"
+    "      <arg type='s' name='netdev' direction='in'/>"
+    "      <arg type='a(ss)' name='attributes' direction='out'/>"
+    "    </method>"
+    "    <method name='" + METHOD_GET_NETDEV_LIST + "'>"
+    "      <arg type='s' name='zone' direction='in'/>"
+    "      <arg type='as' name='list' direction='out'/>"
+    "    </method>"
     "    <method name='" + METHOD_CREATE_NETDEV_VETH + "'>"
     "      <arg type='s' name='id' direction='in'/>"
     "      <arg type='s' name='zoneDev' direction='in'/>"
index 5a4adfa..519b172 100644 (file)
@@ -289,4 +289,19 @@ void ZoneAdmin::moveNetdev(const std::string& devId)
     netdev::movePhys(mZone.getInitPid(), devId);
 }
 
+void ZoneAdmin::setNetdevAttrs(const std::string& /* netdev */, const NetdevAttrs& /* attrs */)
+{
+    throw ZoneOperationException("Not implemented");
+}
+
+ZoneAdmin::NetdevAttrs ZoneAdmin::getNetdevAttrs(const std::string& /* netdev */)
+{
+    throw ZoneOperationException("Not implemented");
+}
+
+std::vector<std::string> ZoneAdmin::getNetdevList()
+{
+    throw ZoneOperationException("Not implemented");
+}
+
 } // namespace vasum
index 9125a6d..44d2613 100644 (file)
@@ -41,6 +41,7 @@ enum class SchedulerLevel {
 class ZoneAdmin {
 
 public:
+    typedef std::vector<std::tuple<std::string, std::string>> NetdevAttrs;
 
     /**
      * ZoneAdmin constructor
@@ -148,6 +149,21 @@ public:
      */
     void moveNetdev(const std::string& devId);
 
+    /**
+     * Set network device attributes
+     */
+    void setNetdevAttrs(const std::string& netdev, const NetdevAttrs& attrs);
+
+    /**
+     * Get network device attributes
+     */
+    NetdevAttrs getNetdevAttrs(const std::string& netdev);
+
+    /**
+     * Get network device list
+     */
+    std::vector<std::string> getNetdevList();
+
 private:
     const ZoneConfig& mConfig;
     lxc::LxcZone mZone;
index 0607fda..fed66fa 100644 (file)
@@ -441,4 +441,22 @@ void Zone::removeDeclaration(const std::string& declarationId)
     mProvision->remove(declarationId);
 }
 
+void Zone::setNetdevAttrs(const std::string& netdev, const ZoneAdmin::NetdevAttrs& attrs)
+{
+    Lock lock(mReconnectMutex);
+    mAdmin->setNetdevAttrs(netdev, attrs);
+}
+
+ZoneAdmin::NetdevAttrs Zone::getNetdevAttrs(const std::string& netdev)
+{
+    Lock lock(mReconnectMutex);
+    return mAdmin->getNetdevAttrs(netdev);
+}
+
+std::vector<std::string> Zone::getNetdevList()
+{
+    Lock lock(mReconnectMutex);
+    return mAdmin->getNetdevList();
+}
+
 } // namespace vasum
index 759faa3..832fcec 100644 (file)
@@ -285,6 +285,21 @@ public:
      */
     void moveNetdev(const std::string& devId);
 
+    /**
+     * Set network device attributes
+     */
+    void setNetdevAttrs(const std::string& netdev, const ZoneAdmin::NetdevAttrs& attrs);
+
+    /**
+     * Get network device attributes
+     */
+    ZoneAdmin::NetdevAttrs getNetdevAttrs(const std::string& netdev);
+
+    /**
+     * Get network device list
+     */
+    std::vector<std::string> getNetdevList();
+
 private:
     utils::Worker::Pointer mWorker;
     ZoneConfig mConfig;
index 5f0dca4..283f57f 100644 (file)
@@ -141,6 +141,15 @@ ZonesManager::ZonesManager(const std::string& configPath)
     mHostConnection.setGetZoneInfoCallback(bind(&ZonesManager::handleGetZoneInfoCall,
                                                 this, _1, _2));
 
+    mHostConnection.setSetNetdevAttrsCallback(bind(&ZonesManager::handleSetNetdevAttrsCall,
+                                                this, _1, _2, _3, _4));
+
+    mHostConnection.setGetNetdevAttrsCallback(bind(&ZonesManager::handleGetNetdevAttrsCall,
+                                                this, _1, _2, _3));
+
+    mHostConnection.setGetNetdevListCallback(bind(&ZonesManager::handleGetNetdevListCall,
+                                                this, _1, _2));
+
     mHostConnection.setCreateNetdevVethCallback(bind(&ZonesManager::handleCreateNetdevVethCall,
                                                 this, _1, _2, _3, _4));
 
@@ -803,6 +812,78 @@ void ZonesManager::handleGetZoneInfoCall(const std::string& id,
                               zone.getRootPath().c_str()));
 }
 
+void ZonesManager::handleSetNetdevAttrsCall(const std::string& zone,
+                                            const std::string& netdev,
+                                            const std::vector<
+                                                std::tuple<std::string, std::string>>& attrs,
+                                            dbus::MethodResultBuilder::Pointer result)
+{
+    LOGI("SetNetdevAttrs call");
+    try {
+        Lock lock(mMutex);
+
+        getZone(zone).setNetdevAttrs(netdev, attrs);
+        result->setVoid();
+    } catch (const InvalidZoneIdException&) {
+        LOGE("No zone with id=" << zone);
+        result->setError(api::ERROR_INVALID_ID, "No such zone id");
+    } catch (const VasumException& ex) {
+        LOGE("Can't set attributes: " << ex.what());
+        result->setError(api::ERROR_INTERNAL, ex.what());
+    }
+}
+
+void ZonesManager::handleGetNetdevAttrsCall(const std::string& zone,
+                                            const std::string& netdev,
+                                            dbus::MethodResultBuilder::Pointer result)
+{
+    LOGI("GetNetdevAttrs call");
+    try {
+        Lock lock(mMutex);
+
+        const auto attrs = getZone(zone).getNetdevAttrs(netdev);
+
+        GVariantBuilder builder;
+        g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+        for (const auto entry : attrs) {
+            g_variant_builder_add(&builder,
+                                  "(ss)",
+                                  std::get<0>(entry).c_str(),
+                                  std::get<1>(entry).c_str());
+        }
+        result->set(g_variant_builder_end(&builder));
+    } catch (const InvalidZoneIdException&) {
+        LOGE("No zone with id=" << zone);
+        result->setError(api::ERROR_INVALID_ID, "No such zone id");
+    } catch (const VasumException& ex) {
+        LOGE("Can't set attributes: " << ex.what());
+        result->setError(api::ERROR_INTERNAL, ex.what());
+    }
+}
+
+void ZonesManager::handleGetNetdevListCall(const std::string& zone,
+                                           dbus::MethodResultBuilder::Pointer result)
+{
+    LOGI("GetNetdevList call");
+    try {
+        Lock lock(mMutex);
+        std::vector<GVariant*> netdevs;
+        for(auto& netdev: getZone(zone).getNetdevList()){
+            netdevs.push_back(g_variant_new_string(netdev.c_str()));
+        }
+        GVariant* array = g_variant_new_array(G_VARIANT_TYPE("s"),
+                                              netdevs.data(),
+                                              netdevs.size());
+        result->set(g_variant_new("(@as)", array));
+    } catch (const InvalidZoneIdException&) {
+        LOGE("No zone with id=" << zone);
+        result->setError(api::ERROR_INVALID_ID, "No such zone id");
+    } catch (const VasumException& ex) {
+        LOGE("Can't set attributes: " << ex.what());
+        result->setError(api::ERROR_INTERNAL, ex.what());
+    }
+}
+
 void ZonesManager::handleCreateNetdevVethCall(const std::string& zone,
                                               const std::string& zoneDev,
                                               const std::string& hostDev,
@@ -814,7 +895,7 @@ void ZonesManager::handleCreateNetdevVethCall(const std::string& zone,
 
         getZone(zone).createNetdevVeth(zoneDev, hostDev);
         result->setVoid();
-    } catch (const std::out_of_range&) {
+    } catch (const InvalidZoneIdException&) {
         LOGE("No zone with id=" << zone);
         result->setError(api::ERROR_INVALID_ID, "No such zone id");
     } catch (const VasumException& ex) {
@@ -835,7 +916,7 @@ void ZonesManager::handleCreateNetdevMacvlanCall(const std::string& zone,
 
         getZone(zone).createNetdevMacvlan(zoneDev, hostDev, mode);
         result->setVoid();
-    } catch (const std::out_of_range&) {
+    } catch (const InvalidZoneIdException&) {
         LOGE("No zone with id=" << zone);
         result->setError(api::ERROR_INVALID_ID, "No such zone id");
     } catch (const VasumException& ex) {
@@ -854,7 +935,7 @@ void ZonesManager::handleCreateNetdevPhysCall(const std::string& zone,
 
         getZone(zone).moveNetdev(devId);
         result->setVoid();
-    } catch (const std::out_of_range&) {
+    } catch (const InvalidZoneIdException&) {
         LOGE("No zone with id=" << zone);
         result->setError(api::ERROR_INVALID_ID, "No such zone id");
     } catch (const VasumException& ex) {
index df5e12b..ee1606d 100644 (file)
@@ -161,6 +161,15 @@ private:
     void handleGetZoneIdsCall(dbus::MethodResultBuilder::Pointer result);
     void handleGetActiveZoneIdCall(dbus::MethodResultBuilder::Pointer result);
     void handleGetZoneInfoCall(const std::string& id, dbus::MethodResultBuilder::Pointer result);
+    void handleSetNetdevAttrsCall(const std::string& zone,
+                                  const std::string& netdev,
+                                  const std::vector<std::tuple<std::string, std::string>>& attrs,
+                                  dbus::MethodResultBuilder::Pointer result);
+    void handleGetNetdevAttrsCall(const std::string& zone,
+                                  const std::string& netdev,
+                                  dbus::MethodResultBuilder::Pointer result);
+    void handleGetNetdevListCall(const std::string& zone,
+                                 dbus::MethodResultBuilder::Pointer result);
     void handleCreateNetdevVethCall(const std::string& zone,
                                     const std::string& zoneDev,
                                     const std::string& hostDev,