%dir /etc/vasum/lxc-templates
%dir /etc/vasum/templates
%config /etc/vasum/daemon.conf
-%config /etc/vasum/zones/*.conf
%attr(755,root,root) /etc/vasum/lxc-templates/*.sh
%config /etc/vasum/templates/*.conf
%{_unitdir}/vasum.service
MESSAGE(STATUS "Installing configs to " ${VSM_CONFIG_INSTALL_DIR})
-FILE(GLOB zone_CONF zones/*.conf)
FILE(GLOB admin_CONF lxc-templates/*.sh)
FILE(GLOB template_CONF templates/*.conf)
INSTALL(FILES ${CMAKE_BINARY_DIR}/dbus-1/system.d/org.tizen.vasum.host.conf
DESTINATION ${SYSCONF_INSTALL_DIR}/dbus-1/system.d/)
-INSTALL(FILES ${zone_CONF}
- DESTINATION ${VSM_CONFIG_INSTALL_DIR}/zones)
+INSTALL(DIRECTORY DESTINATION ${VSM_CONFIG_INSTALL_DIR}/zones) #TODO temporary solution
INSTALL(PROGRAMS ${admin_CONF}
DESTINATION ${VSM_CONFIG_INSTALL_DIR}/lxc-templates)
{
- "zoneConfigs" : ["zones/private.conf", "zones/business.conf"],
+ "dbPath" : "/usr/dbspace/vasum.db",
+ "zoneConfigs" : [],
"zonesPath" : "${DATA_DIR}/.zones",
"zoneImagePath" : "",
- "zoneTemplatePath" : "templates",
+ "zoneTemplatePath" : "/etc/vasum/templates/template.conf",
"zoneNewConfigPrefix" : "/var/lib/vasum",
"runMountPointPrefix" : "/var/run/zones",
- "foregroundId" : "private",
- "defaultId" : "private",
+ "foregroundId" : "",
+ "defaultId" : "",
"lxcTemplatePrefix" : "/etc/vasum/lxc-templates",
"inputConfig" : {"enabled" : true,
"device" : "gpio_keys.6",
+++ /dev/null
-{
- "name" : "business",
- "lxcTemplate" : "tizen-common-wayland.sh",
- "initWithArgs" : [],
- "ipv4Gateway" : "10.0.102.1",
- "ipv4" : "10.0.102.2",
- "cpuQuotaForeground" : -1,
- "cpuQuotaBackground" : 10000,
- "enableDbusIntegration" : true,
- "privilege" : 1,
- "vt" : 3,
- "switchToDefaultAfterTimeout" : true,
- "runMountPoint" : "business/run",
- "permittedToSend" : [ "/tmp/.*" ],
- "permittedToRecv" : [ "/tmp/.*" ],
- "validLinkPrefixes" : [ "/tmp/",
- "/run/",
- "/opt/usr/data/",
- "/opt/usr/dbsapce/" ]
-}
+++ /dev/null
-{
- "name" : "private",
- "lxcTemplate" : "tizen-common-wayland.sh",
- "initWithArgs" : [],
- "ipv4Gateway" : "10.0.101.1",
- "ipv4" : "10.0.101.2",
- "cpuQuotaForeground" : -1,
- "cpuQuotaBackground" : 10000,
- "enableDbusIntegration" : true,
- "privilege" : 10,
- "vt" : 2,
- "switchToDefaultAfterTimeout" : true,
- "runMountPoint" : "private/run",
- "permittedToSend" : [ "/tmp/.*" ],
- "permittedToRecv" : [ "/tmp/.*" ],
- "validLinkPrefixes" : [ "/tmp/",
- "/run/",
- "/opt/usr/data/",
- "/opt/usr/dbsapce/" ]
-}
const std::string PROGRAM_NAME_AND_VERSION =
"Vasum Server " PROGRAM_VERSION;
+const std::string CONFIG_PATH = "/etc/vasum/daemon.conf";
+
+
} // namespace
int main(int argc, char* argv[])
{
- std::string configPath;
bool runAsRoot = false;
try {
("root,r", "Don't drop root privileges at startup")
("version,v", "show application version")
("log-level,l", po::value<std::string>()->default_value("DEBUG"), "set log level")
- ("config,c", po::value<std::string>()->default_value("/etc/vasum/daemon.conf"), "server configuration file")
;
po::variables_map vm;
Logger::setLogBackend(new SystemdJournalBackend());
#endif
- configPath = vm["config"].as<std::string>();
runAsRoot = vm.count("root") > 0;
} catch (std::exception& e) {
}
try {
- Server server(configPath, runAsRoot);
- server.run();
+ Server server(CONFIG_PATH);
+ server.run(runAsRoot);
server.reloadIfRequired(argv);
} catch (std::exception& e) {
namespace vasum {
-Server::Server(const std::string& configPath, bool runAsRoot)
+Server::Server(const std::string& configPath)
: mConfigPath(configPath)
{
- if (!prepareEnvironment(configPath, runAsRoot)) {
- throw ServerException("Environment setup failed");
- }
-}
-
-
-Server::~Server()
-{
}
} // namespace
-void Server::run()
+void Server::run(bool asRoot)
{
+ if (!prepareEnvironment(mConfigPath, asRoot)) {
+ throw ServerException("Environment setup failed");
+ }
+
signal(SIGINT, signalHandler);
signal(SIGTERM, signalHandler);
signal(SIGUSR1, signalHandler);
class Server {
public:
- Server(const std::string& configPath, bool runAsRoot = true);
- virtual ~Server();
-
- /**
- * Set needed caps, groups and drop root privileges.
- */
- static bool prepareEnvironment(const std::string& configPath, bool runAsRoot);
+ Server(const std::string& configPath);
/**
* Starts all the zones and blocks until SIGINT, SIGTERM or SIGUSR1
*/
- void run();
+ void run(bool asRoot);
/**
* Reload the server by launching execve on itself if SIGUSR1 was sent to server.
* Equivalent of sending SIGINT or SIGTERM signal
*/
void terminate();
+
private:
std::string mConfigPath;
+
+ /**
+ * Set needed caps, groups and drop root privileges.
+ */
+ static bool prepareEnvironment(const std::string& configPath, bool runAsRoot);
+
};
namespace vasum {
-
-const std::string ZONES_MANAGER_CONFIG_PATH = "/etc/vasum/config/daemon.conf";
-
struct ZonesManagerConfig {
/**
- * List of zones' configs that we manage.
- * File paths can be relative to the ZoneManager config file.
+ * Path to config database.
*/
- std::vector<std::string> zoneConfigs;
+ std::string dbPath;
/**
* An ID of a currently focused/foreground zone.
CONFIG_REGISTER
(
- zoneConfigs,
+ dbPath,
foregroundId,
defaultId,
zonesPath,
)
};
+struct ZonesManagerDynamicConfig {
+
+ /**
+ * List of zones' configs that we manage.
+ * File paths can be relative to the ZoneManager config file.
+ */
+ std::vector<std::string> zoneConfigs;
+
+ CONFIG_REGISTER
+ (
+ zoneConfigs
+ )
+};
} // namespace vasum
const unsigned int ZONE_IP_BASE_THIRD_OCTET = 100;
const unsigned int ZONE_VT_BASE = 1;
+std::string getConfigName(const std::string& zoneId)
+{
+ return "zones/" + zoneId + ".conf";
+}
+
+template<typename T>
+void remove(std::vector<T>& v, const T& item)
+{
+ // erase-remove idiom, ask google for explanation
+ v.erase(std::remove(v.begin(), v.end(), item), v.end());
+}
+
} // namespace
-ZonesManager::ZonesManager(const std::string& managerConfigPath)
- : mWorker(utils::Worker::create()), mDetachOnExit(false)
+ZonesManager::ZonesManager(const std::string& configPath)
+ : mWorker(utils::Worker::create())
+ , mDetachOnExit(false)
{
LOGD("Instantiating ZonesManager object...");
- mConfigPath = managerConfigPath;
- config::loadFromFile(mConfigPath, mConfig);
+ config::loadFromFile(configPath, mConfig);
+ config::loadFromKVStoreWithJsonFile(mConfig.dbPath, configPath, mDynamicConfig);
mProxyCallPolicy.reset(new ProxyCallPolicy(mConfig.proxyCallRules));
mHostConnection.setRevokeDeviceCallback(bind(&ZonesManager::handleRevokeDeviceCall,
this, _1, _2, _3));
- for (auto& zoneConfig : mConfig.zoneConfigs) {
- createZone(zoneConfig);
+ for (const auto& zoneConfig : mDynamicConfig.zoneConfigs) {
+ createZone(utils::createFilePath(mConfig.zoneNewConfigPrefix, zoneConfig));
}
// check if default zone exists, throw ZoneOperationException if not found
LOGD("ZonesManager object destroyed");
}
-void ZonesManager::createZone(const std::string& zoneConfig)
+void ZonesManager::saveDynamicConfig()
{
- std::string baseConfigPath = utils::dirName(mConfigPath);
- std::string zoneConfigPath = utils::getAbsolutePath(zoneConfig, baseConfigPath);
+ config::saveToKVStore(mConfig.dbPath, mDynamicConfig);
+}
+void ZonesManager::createZone(const std::string& zoneConfigPath)
+{
LOGT("Creating Zone " << zoneConfigPath);
std::unique_ptr<Zone> zone(new Zone(mWorker->createSubWorker(),
mConfig.zonesPath,
// after zone is created successfully, put a file informing that zones are enabled
if (mZones.size() == 1) {
if (!utils::saveFileContent(
- utils::createFilePath(mConfig.zonesPath, "/", ENABLED_FILE_NAME), "")) {
+ utils::createFilePath(mConfig.zonesPath, ENABLED_FILE_NAME), "")) {
throw ZoneOperationException(ENABLED_FILE_NAME + ": cannot create.");
}
}
mZones.erase(it);
if (mZones.size() == 0) {
- if (!utils::removeFile(utils::createFilePath(mConfig.zonesPath, "/", ENABLED_FILE_NAME))) {
+ if (!utils::removeFile(utils::createFilePath(mConfig.zonesPath, ENABLED_FILE_NAME))) {
LOGE("Failed to remove enabled file.");
}
}
+
+ // update dynamic config
+ remove(mDynamicConfig.zoneConfigs, getConfigName(zoneId));
+ saveDynamicConfig();
}
void ZonesManager::focus(const std::string& zoneId)
{
namespace fs = boost::filesystem;
- std::string resultFileDir = utils::dirName(resultPath);
- if (!fs::exists(resultFileDir)) {
- if (!utils::createEmptyDir(resultFileDir)) {
+ if (fs::exists(resultPath)) {
+ LOGT(resultPath << " already exists, removing");
+ fs::remove(resultPath);
+ } else {
+ std::string resultFileDir = utils::dirName(resultPath);
+ if (!utils::createDirs(resultFileDir, fs::perms::owner_all |
+ fs::perms::group_read | fs::perms::group_exe |
+ fs::perms::others_read | fs::perms::others_exe)) {
LOGE("Unable to create directory for new config.");
throw ZoneOperationException("Unable to create directory for new config.");
}
}
- fs::path resultFile(resultPath);
- if (fs::exists(resultFile)) {
- LOGT(resultPath << " already exists, removing");
- fs::remove(resultFile);
- }
-
std::string config;
if (!utils::readFileContent(templatePath, config)) {
LOGE("Failed to read template config file.");
}
// restrict new config file so that only owner (vasum) can write it
- fs::permissions(resultPath, fs::perms::owner_all |
+ fs::permissions(resultPath, fs::perms::owner_read | fs::perms::owner_write |
fs::perms::group_read |
fs::perms::others_read);
}
return;
}
- const std::string zonePathStr = utils::createFilePath(mConfig.zonesPath, "/", id, "/");
+ const std::string zonePathStr = utils::createFilePath(mConfig.zonesPath, id, "/");
// copy zone image if config contains path to image
LOGT("Image path: " << mConfig.zoneImagePath);
}
// generate paths to new configuration files
- std::string baseDir = utils::dirName(mConfigPath);
- std::string configDir = utils::getAbsolutePath(mConfig.zoneNewConfigPrefix, baseDir);
- std::string templateDir = utils::getAbsolutePath(mConfig.zoneTemplatePath, baseDir);
-
- std::string configPath = utils::createFilePath(templateDir, "/", ZONE_TEMPLATE_CONFIG_PATH);
- std::string newConfigPath = utils::createFilePath(configDir, "/zones/", id + ".conf");
+ std::string newConfigName = getConfigName(id);
+ std::string newConfigPath = utils::createFilePath(mConfig.zoneNewConfigPrefix, newConfigName);
auto removeAllWrapper = [](const std::string& path) -> bool {
try {
};
try {
- LOGI("Generating config from " << configPath << " to " << newConfigPath);
- generateNewConfig(id, configPath, newConfigPath);
+ LOGI("Generating config from " << mConfig.zoneTemplatePath << " to " << newConfigPath);
+ generateNewConfig(id, mConfig.zoneTemplatePath, newConfigPath);
} catch (VasumException& e) {
LOGE("Generate config failed: " << e.what());
return;
}
+ mDynamicConfig.zoneConfigs.push_back(newConfigName);
+ saveDynamicConfig();
+
result->setVoid();
}
*
* @param zoneConfig config of new zone
*/
- void createZone(const std::string& zoneConfig);
+ void createZone(const std::string& zoneConfigPath);
/**
* Destroy zone.
utils::Worker::Pointer mWorker;
mutable Mutex mMutex; // used to protect mZones
- ZonesManagerConfig mConfig;
- std::string mConfigPath;
+ ZonesManagerConfig mConfig; //TODO make it const
+ ZonesManagerDynamicConfig mDynamicConfig;
HostConnection mHostConnection;
// to hold InputMonitor pointer to monitor if zone switching sequence is recognized
std::unique_ptr<InputMonitor> mSwitchingSequenceMonitor;
ZoneMap mZones; // map of zones, id is the key
bool mDetachOnExit;
+ void saveDynamicConfig();
void switchingSequenceMonitorNotify();
void generateNewConfig(const std::string& id,
const std::string& templatePath,
{
+ "dbPath" : "/tmp/ut-zones/vasum.db",
"zoneConfigs" : ["zones/console1-dbus.conf",
"zones/console2-dbus.conf",
"zones/console3-dbus.conf"],
"defaultId" : "ut-zones-manager-console1-dbus",
"zonesPath" : "/tmp/ut-zones",
"zoneImagePath" : "",
- "zoneTemplatePath" : "",
- "zoneNewConfigPrefix" : "",
+ "zoneTemplatePath" : "no_need_for_templates_in_this_test",
+ "zoneNewConfigPrefix" : "@VSM_TEST_CONFIG_INSTALL_DIR@/client/ut-client/",
"runMountPointPrefix" : "",
"lxcTemplatePrefix" : "@VSM_TEST_LXC_TEMPLATES_INSTALL_DIR@",
"inputConfig" : {"enabled" : false,
{
+ "dbPath" : "/tmp/ut-zones/vasum.db",
"zoneConfigs" : ["zones/zone1.conf", "missing/file/path/missing.conf", "zones/zone3.conf"],
"zonesPath" : "/tmp/ut-zones",
"zoneImagePath" : "",
"zoneTemplatePath" : "no_need_for_templates_in_this_test",
- "zoneNewConfigPrefix" : "",
+ "zoneNewConfigPrefix" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-server/",
"runMountPointPrefix" : "",
"foregroundId" : "ut-server-zone1",
"defaultId" : "ut-server-zone1",
{
+ "dbPath" : "/tmp/ut-zones/vasum.db",
"zoneConfigs" : ["zones/zone1.conf", "zones/zone2.conf", "zones/zone3.conf"],
"zonesPath" : "/tmp/ut-zones",
"zoneImagePath" : "",
"zoneTemplatePath" : "no_need_for_templates_in_this_test",
- "zoneNewConfigPrefix" : "",
+ "zoneNewConfigPrefix" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-server/",
"runMountPointPrefix" : "",
"foregroundId" : "ut-server-zone1",
"defaultId" : "ut-server-zone1",
{
+ "dbPath" : "/tmp/ut-zones/vasum.db",
"zoneConfigs" : ["zones/console1.conf", "missing/file/path/missing.conf", "zones/console3.conf"],
"runMountPointPrefix" : "",
"foregroundId" : "ut-zones-manager-console1",
"defaultId" : "ut-zones-manager-console1",
"zonesPath" : "/tmp/ut-zones",
"zoneImagePath" : "",
- "zoneTemplatePath" : "templates",
+ "zoneTemplatePath" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/templates/template.conf",
"zoneNewConfigPrefix" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/",
"lxcTemplatePrefix" : "@VSM_TEST_LXC_TEMPLATES_INSTALL_DIR@",
"inputConfig" : {"enabled" : false,
{
+ "dbPath" : "/tmp/ut-zones/vasum.db",
"zoneConfigs" : ["zones/console1.conf", "zones/console2.conf", "zones/console3.conf"],
"runMountPointPrefix" : "",
"foregroundId" : "ut-zones-manager-console1",
"defaultId" : "in_no_way_there_is_a_valid_id_here",
"zonesPath" : "/tmp/ut-zones",
"zoneImagePath" : "",
- "zoneTemplatePath" : "templates",
+ "zoneTemplatePath" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/templates/template.conf",
"zoneNewConfigPrefix" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/",
"lxcTemplatePrefix" : "@VSM_TEST_LXC_TEMPLATES_INSTALL_DIR@",
"inputConfig" : {"enabled" : false,
{
+ "dbPath" : "/tmp/ut-zones/vasum.db",
"zoneConfigs" : ["zones/console1.conf", "zones/console2.conf", "zones/console3.conf"],
"runMountPointPrefix" : "",
"foregroundId" : "this_id_does_not_exist",
"defaultId" : "ut-zones-manager-console1",
"zonesPath" : "/tmp/ut-zones",
"zoneImagePath" : "",
- "zoneTemplatePath" : "templates",
+ "zoneTemplatePath" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/templates/template.conf",
"zoneNewConfigPrefix" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/",
"lxcTemplatePrefix" : "@VSM_TEST_LXC_TEMPLATES_INSTALL_DIR@",
"inputConfig" : {"enabled" : false,
{
+ "dbPath" : "/tmp/ut-zones/vasum.db",
"zoneConfigs" : [],
"foregroundId" : "",
"defaultId" : "",
"zonesPath" : "/tmp/ut-zones",
"zoneImagePath" : "",
- "zoneTemplatePath" : "templates",
- "zoneNewConfigPrefix" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/",
+ "zoneTemplatePath" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/templates/template.conf",
+ "zoneNewConfigPrefix" : "/tmp/ut-zones/generated-configs/",
"runMountPointPrefix" : "",
"lxcTemplatePrefix" : "@VSM_TEST_LXC_TEMPLATES_INSTALL_DIR@",
"inputConfig" : {"enabled" : false,
{
+ "dbPath" : "/tmp/ut-zones/vasum.db",
"zoneConfigs" : ["zones/console1.conf", "zones/console2.conf", "zones/console3.conf"],
"runMountPointPrefix" : "",
"foregroundId" : "ut-zones-manager-console1",
"defaultId" : "ut-zones-manager-console1",
"zonesPath" : "/tmp/ut-zones",
"zoneImagePath" : "",
- "zoneTemplatePath" : "templates",
+ "zoneTemplatePath" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/templates/template.conf",
"zoneNewConfigPrefix" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/",
"lxcTemplatePrefix" : "@VSM_TEST_LXC_TEMPLATES_INSTALL_DIR@",
"inputConfig" : {"enabled" : false,
{
+ "dbPath" : "/tmp/ut-zones/vasum.db",
"zoneConfigs" : ["zones/console1-dbus.conf",
"zones/console2-dbus.conf",
"zones/console3-dbus.conf"],
"defaultId" : "ut-zones-manager-console1-dbus",
"zonesPath" : "/tmp/ut-zones",
"zoneImagePath" : "",
- "zoneTemplatePath" : "templates",
+ "zoneTemplatePath" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/templates/template.conf",
"zoneNewConfigPrefix" : "@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/",
"runMountPointPrefix" : "",
"lxcTemplatePrefix" : "@VSM_TEST_LXC_TEMPLATES_INSTALL_DIR@",
namespace {
const std::string ZONES_PATH = "/tmp/ut-zones"; // the same as in daemon.conf
+const bool AS_ROOT = true;
struct Fixture {
vasum::utils::ScopedDir mZonesPathGuard;
BOOST_AUTO_TEST_CASE(BuggyConfigTest)
{
- BOOST_REQUIRE_THROW(Server(BUGGY_CONFIG_PATH).run(), ConfigException);
+ BOOST_REQUIRE_THROW(Server(BUGGY_CONFIG_PATH).run(AS_ROOT), ConfigException);
}
BOOST_AUTO_TEST_CASE(MissingConfigTest)
{
- BOOST_REQUIRE_THROW(Server(MISSING_CONFIG_PATH).run(), ConfigException);
+ BOOST_REQUIRE_THROW(Server(MISSING_CONFIG_PATH).run(AS_ROOT), ConfigException);
}
BOOST_AUTO_TEST_CASE(TerminateTest)
{
Server s(TEST_CONFIG_PATH);
s.terminate();
- s.run();
+ s.run(AS_ROOT);
}
BOOST_AUTO_TEST_CASE(RunTerminateTest)
{
Server s(TEST_CONFIG_PATH);
- std::future<void> runFuture = std::async(std::launch::async, [&] {s.run();});
+ std::future<void> runFuture = std::async(std::launch::async, [&] {s.run(AS_ROOT);});
// give a chance to run a thread
std::this_thread::sleep_for(std::chrono::milliseconds(200));
BOOST_CHECK_EQUAL(cm.getRunningForegroundZoneId(), "");
}
+BOOST_AUTO_TEST_CASE(CreateDestroyZonePersistenceTest)
+{
+ const std::string zone = "test1";
+
+ Latch callDone;
+ auto resultCallback = [&]() {
+ callDone.set();
+ };
+
+ auto getZoneIds = []() -> std::vector<std::string> {
+ ZonesManager cm(EMPTY_DBUS_CONFIG_PATH);
+ cm.startAll();
+
+ DbusAccessory dbus(DbusAccessory::HOST_ID);
+ return dbus.callMethodGetZoneIds();
+ };
+
+ BOOST_CHECK(getZoneIds().empty());
+
+ // create zone
+ {
+ ZonesManager cm(EMPTY_DBUS_CONFIG_PATH);
+ DbusAccessory dbus(DbusAccessory::HOST_ID);
+ dbus.callAsyncMethodCreateZone(zone, resultCallback);
+ BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+ }
+
+ {
+ auto ids = getZoneIds();
+ BOOST_CHECK_EQUAL(1, ids.size());
+ BOOST_CHECK(ids.at(0) == zone);
+ }
+
+ // destroy zone
+ {
+ ZonesManager cm(EMPTY_DBUS_CONFIG_PATH);
+ DbusAccessory dbus(DbusAccessory::HOST_ID);
+ dbus.callAsyncMethodDestroyZone(zone, resultCallback);
+ BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+ }
+
+ BOOST_CHECK(getZoneIds().empty());
+}
+
BOOST_AUTO_TEST_CASE(StartShutdownZoneTest)
{
const std::string zone1 = "ut-zones-manager-console1-dbus";