Fix create container from template 31/30731/3
authorPiotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
Mon, 24 Nov 2014 16:10:29 +0000 (17:10 +0100)
committerJan Olszak <j.olszak@samsung.com>
Tue, 25 Nov 2014 10:09:37 +0000 (02:09 -0800)
[Bug/Feature]   Templates stops working after migration to lxc
[Cause]         N/A
[Solution]      N/A
[Verification]  Build, install, run tests

Change-Id: Ifbc0db612391eb7460b757b3cd12dda79183178b

common/utils/environment.cpp
common/utils/environment.hpp
server/configs/CMakeLists.txt
server/configs/lxc-templates/template.sh [new file with mode: 0755]
server/configs/templates/template.conf
server/containers-manager.cpp

index eaaef12..73c7057 100644 (file)
@@ -84,8 +84,9 @@ bool dropRoot(uid_t uid, gid_t gid, const std::vector<unsigned int>& caps)
     return true;
 }
 
-bool launchAsRoot(const std::function<void()>& func)
+bool launchAsRoot(const std::function<bool()>& func)
 {
+    // TODO optimize if getuid() == 0
     pid_t pid = fork();
     if (pid < 0) {
         LOGE("Fork failed: " << strerror(errno));
@@ -99,8 +100,11 @@ bool launchAsRoot(const std::function<void()>& func)
         }
 
         try {
-            func();
-        } catch (std::exception& e) {
+            if (!func()) {
+                LOGE("Failed to successfully execute func");
+                ::exit(EXIT_FAILURE);
+            }
+        } catch (const std::exception& e) {
             LOGE("Failed to successfully execute func: " << e.what());
             ::exit(EXIT_FAILURE);
         }
index 120b6ac..07a767e 100644 (file)
@@ -50,7 +50,7 @@ bool dropRoot(uid_t uid, gid_t gid, const std::vector<unsigned int>& caps);
  *
  * This function forks, sets UID 0 to child process and calls func.
  */
-bool launchAsRoot(const std::function<void()>& func);
+bool launchAsRoot(const std::function<bool()>& func);
 
 
 } // namespace utils
index ab4a94f..e4f9df9 100644 (file)
@@ -21,6 +21,7 @@ MESSAGE(STATUS "Installing configs to " ${SC_CONFIG_INSTALL_DIR})
 
 FILE(GLOB container_CONF     containers/*.conf)
 FILE(GLOB admin_CONF         lxc-templates/*.sh)
+FILE(GLOB template_CONF      templates/*.conf)
 
 ## Generate ####################################################################
 CONFIGURE_FILE(systemd/security-containers.service.in
@@ -44,5 +45,8 @@ INSTALL(FILES       ${container_CONF}
 INSTALL(PROGRAMS    ${admin_CONF}
         DESTINATION ${SC_CONFIG_INSTALL_DIR}/lxc-templates)
 
+INSTALL(PROGRAMS    ${template_CONF}
+        DESTINATION ${SC_CONFIG_INSTALL_DIR}/templates)
+
 INSTALL(FILES       ${CMAKE_BINARY_DIR}/systemd/security-containers.service
         DESTINATION ${SYSTEMD_UNIT_DIR})
diff --git a/server/configs/lxc-templates/template.sh b/server/configs/lxc-templates/template.sh
new file mode 100755 (executable)
index 0000000..c03a050
--- /dev/null
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+echo LXC template, args: $@
+
+options=$(getopt -o p:n: -l rootfs:,path:,name: -- "$@")
+if [ $? -ne 0 ]; then
+    exit 1
+fi
+eval set -- "$options"
+
+while true
+do
+    case "$1" in
+        -p|--path)      path=$2; shift 2;;
+        --rootfs)       rootfs=$2; shift 2;;
+        -n|--name)      name=$2; shift 2;;
+        --)             shift 1; break ;;
+        *)              break ;;
+    esac
+done
+
+br_name="virbr-${name}"
+sub_net="103" # TODO from param
+
+# XXX assume rootfs if mounted from iso
+
+# Prepare container configuration file
+> ${path}/config
+cat <<EOF >> ${path}/config
+lxc.utsname = ${name}
+lxc.rootfs = ${rootfs}
+
+# userns 1-to-1 mapping
+#lxc.id_map = u 0 0 65536
+#lxc.id_map = g 0 0 65536
+
+lxc.pts = 256
+lxc.tty = 0
+
+lxc.mount.auto = proc sys cgroup
+lxc.mount.entry = /var/run/containers/${name}/run var/run none rw,bind 0 0
+
+lxc.network.type = veth
+lxc.network.link =  ${br_name}
+lxc.network.flags = up
+lxc.network.name = eth0
+lxc.network.veth.pair = veth-${name}
+lxc.network.ipv4.gateway = 10.0.${sub_net}.1
+lxc.network.ipv4 = 10.0.${sub_net}.2/24
+
+lxc.hook.pre-start = ${path}/pre-start.sh
+
+#lxc.loglevel = TRACE
+#lxc.logfile = /tmp/${name}.log
+EOF
+
+# prepare pre start hook
+cat <<EOF >> ${path}/pre-start.sh
+if [ -z "\$(/usr/sbin/brctl show | /bin/grep -P "${br_name}\t")" ]
+then
+    /usr/sbin/brctl addbr ${br_name}
+    /usr/sbin/brctl setfd ${br_name} 0
+    /sbin/ifconfig ${br_name} 10.0.${sub_net}.1 netmask 255.255.255.0 up
+fi
+if [ -z "\$(/usr/sbin/iptables -t nat -S | /bin/grep MASQUERADE)" ]
+then
+    /bin/echo 1 > /proc/sys/net/ipv4/ip_forward
+    /usr/sbin/iptables -t nat -A POSTROUTING -s 10.0.0.0/16 ! -d 10.0.0.0/16 -j MASQUERADE
+fi
+EOF
+
+chmod 755 ${path}/pre-start.sh
index a8f47fc..f91bf5f 100644 (file)
@@ -1,4 +1,7 @@
 {
+    "name" : "~NAME~",
+    "lxcTemplate" : "template.sh",
+    "initWithArgs" : [],
     "cpuQuotaForeground" : -1,
     "cpuQuotaBackground" : 1000,
     "privilege" : 10,
index 62dbc14..def04c2 100644 (file)
@@ -41,9 +41,6 @@
 
 #include <boost/filesystem.hpp>
 #include <boost/regex.hpp>
-#include <boost/uuid/uuid.hpp>
-#include <boost/uuid/uuid_io.hpp>
-#include <boost/uuid/uuid_generators.hpp>
 #include <boost/exception/diagnostic_information.hpp>
 #include <cassert>
 #include <string>
@@ -70,7 +67,6 @@ const std::string HOST_ID = "host";
 const std::string CONTAINER_TEMPLATE_CONFIG_PATH = "template.conf";
 
 const boost::regex CONTAINER_NAME_REGEX("~NAME~");
-const boost::regex CONTAINER_UUID_REGEX("~UUID~");
 const boost::regex CONTAINER_IP_THIRD_OCTET_REGEX("~IP~");
 
 const unsigned int CONTAINER_IP_BASE_THIRD_OCTET = 100;
@@ -522,12 +518,15 @@ void ContainersManager::handleGetContainerInfoCall(const std::string& id,
         result->setError(api::ERROR_INTERNAL, "Unrecognized state of container");
         return;
     }
-    const std::string rootPath = boost::filesystem::absolute(id, mConfig.containersPath).string();
+    const auto containerPath = boost::filesystem::absolute(id, mConfig.containersPath);
+    const auto rootfsDir = boost::filesystem::path("rootfs");
+    const auto rootfsPath = containerPath / rootfsDir;
+
     result->set(g_variant_new("((siss))",
                               id.c_str(),
                               container->getVT(),
                               state,
-                              rootPath.c_str()));
+                              rootfsPath.string().c_str()));
 }
 
 void ContainersManager::handleSetActiveContainerCall(const std::string& id,
@@ -581,14 +580,10 @@ void ContainersManager::generateNewConfig(const std::string& id,
 
     std::string resultConfig = boost::regex_replace(config, CONTAINER_NAME_REGEX, id);
 
-    boost::uuids::uuid u = boost::uuids::random_generator()();
-    std::string uuidStr = to_string(u);
-    LOGD("uuid: " << uuidStr);
-    resultConfig = boost::regex_replace(resultConfig, CONTAINER_UUID_REGEX, uuidStr);
-
     // generate third IP octet for network config
+    // TODO change algorithm after implementing removeContainer
     std::string thirdOctetStr = std::to_string(CONTAINER_IP_BASE_THIRD_OCTET + mContainers.size() + 1);
-    LOGD("ip_third_octet: " << thirdOctetStr);
+    LOGD("IP third octet: " << thirdOctetStr);
     resultConfig = boost::regex_replace(resultConfig, CONTAINER_IP_THIRD_OCTET_REGEX, thirdOctetStr);
 
     if (!utils::saveFileContent(resultPath, resultConfig)) {
@@ -630,7 +625,7 @@ void ContainersManager::handleAddContainerCall(const std::string& id,
     }
 
     // copy container image if config contains path to image
-    LOGT("image path: " << mConfig.containerImagePath);
+    LOGT("Image path: " << mConfig.containerImagePath);
     if (!mConfig.containerImagePath.empty()) {
         auto copyImageContentsWrapper = std::bind(&utils::copyImageContents,
                                                   mConfig.containerImagePath,
@@ -659,6 +654,7 @@ void ContainersManager::handleAddContainerCall(const std::string& id,
         } catch(const std::exception& e) {
             LOGW("Failed to remove data: " << boost::diagnostic_information(e));
         }
+        return true;
     };
 
     try {
@@ -682,13 +678,13 @@ void ContainersManager::handleAddContainerCall(const std::string& id,
         return;
     }
 
-    auto resultCallback = [this, id, result, containerPathStr, removeAllWrapper](bool succeeded) {
+    auto resultCallback = [this, id, result](bool succeeded) {
         if (succeeded) {
             focus(id);
             result->setVoid();
         } else {
             LOGE("Failed to start container.");
-            utils::launchAsRoot(std::bind(removeAllWrapper, containerPathStr));
+            // TODO removeContainer
             result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED,
                              "Failed to start container.");
         }