+++ /dev/null
-/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact: Jan Olszak <j.olszak@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-/**
- * @file
- * @author Jan Olszak (j.olszak@samsung.com)
- * @brief Implementation of class for administrating one zone
- */
-
-#include "config.hpp"
-
-#include "zone-admin.hpp"
-#include "exception.hpp"
-#include "netdev.hpp"
-
-#include "logger/logger.hpp"
-#include "utils/paths.hpp"
-#include "utils/c-array.hpp"
-#include "lxc/cgroup.hpp"
-
-#include <cassert>
-#include <climits>
-#include <thread>
-#include <chrono>
-
-
-namespace vasum {
-
-const std::uint64_t DEFAULT_CPU_SHARES = 1024;
-const std::uint64_t DEFAULT_VCPU_PERIOD_MS = 100000;
-
-ZoneAdmin::ZoneAdmin(const std::string& zoneId,
- const std::string& zonesPath,
- const std::string& zoneTemplateDir,
- const ZoneConfig& config,
- const ZoneDynamicConfig& dynamicConfig)
- : mConfig(config),
- mDynamicConfig(dynamicConfig),
- mZone(zonesPath, zoneId),
- mId(zoneId),
- mDetachOnExit(false),
- mDestroyOnExit(false)
-{
- LOGD(mId << ": Instantiating ZoneAdmin object");
-
- if (!mZone.isDefined()) {
-
- const std::string zoneTemplate = utils::getAbsolutePath(config.zoneTemplate,
- zoneTemplateDir);
- LOGI(mId << ": Creating zone from template: " << zoneTemplate);
- utils::CStringArrayBuilder args;
- if (!dynamicConfig.ipv4Gateway.empty()) {
- args.add("--ipv4-gateway");
- args.add(dynamicConfig.ipv4Gateway.c_str());
- }
- if (!dynamicConfig.ipv4.empty()) {
- args.add("--ipv4");
- args.add(dynamicConfig.ipv4.c_str());
- }
- const std::string vt = std::to_string(dynamicConfig.vt);
- if (dynamicConfig.vt > 0) {
- args.add("--vt");
- args.add(vt.c_str());
- }
- if (!mZone.create(zoneTemplate, args.c_array())) {
- throw ZoneOperationException("Could not create zone");
- }
- }
-}
-
-
-ZoneAdmin::~ZoneAdmin()
-{
- LOGD(mId << ": Destroying ZoneAdmin object...");
-
- if (mDestroyOnExit) {
- if (!mZone.stop()) {
- LOGE(mId << ": Failed to stop the zone");
- }
- if (!mZone.destroy()) {
- LOGE(mId << ": Failed to destroy the zone");
- }
- }
-
- if (!mDetachOnExit) {
- // Try to forcefully stop
- if (!mZone.stop()) {
- LOGE(mId << ": Failed to stop the zone");
- }
- }
-
- LOGD(mId << ": ZoneAdmin object destroyed");
-}
-
-
-const std::string& ZoneAdmin::getId() const
-{
- return mId;
-}
-
-
-void ZoneAdmin::start()
-{
- LOGD(mId << ": Starting...");
- if (isRunning()) {
- LOGD(mId << ": Already running - nothing to do...");
- return;
- }
-
- utils::CStringArrayBuilder args;
- for (const std::string& arg : mConfig.initWithArgs) {
- args.add(arg.c_str());
- }
- if (args.empty()) {
- args.add("/sbin/init");
- }
-
- if (!mZone.start(args.c_array())) {
- throw ZoneOperationException("Could not start zone");
- }
-
- // Wait until the full platform launch with graphical stack.
- // VT should be activated by a graphical stack.
- // If we do it with 'zoneToFocus.activateVT' before starting the graphical stack,
- // graphical stack initialization failed and we finally switch to the black screen.
- // Skip waiting when graphical stack is not running (unit tests).
- if (mDynamicConfig.vt > 0) {
- // TODO, timeout is a temporary solution
- std::this_thread::sleep_for(std::chrono::milliseconds(4000));
- }
-
- LOGD(mId << ": Started");
-}
-
-
-void ZoneAdmin::stop()
-{
- LOGD(mId << ": Stopping procedure started...");
- if (isStopped()) {
- LOGD(mId << ": Already crashed/down/off - nothing to do");
- return;
- }
-
- if (!mZone.shutdown(mConfig.shutdownTimeout)) {
- // force stop
- if (!mZone.stop()) {
- throw ZoneOperationException("Could not stop zone");
- }
- }
-
- LOGD(mId << ": Stopping procedure ended");
-}
-
-
-void ZoneAdmin::destroy()
-{
- LOGD(mId << ": Destroying procedure started...");
-
- if (!mZone.destroy()) {
- throw ZoneOperationException("Could not destroy zone");
- }
-
- LOGD(mId << ": Destroying procedure ended");
-}
-
-
-bool ZoneAdmin::isRunning()
-{
- return mZone.getState() == lxc::LxcZone::State::RUNNING;
-}
-
-
-bool ZoneAdmin::isStopped()
-{
- return mZone.getState() == lxc::LxcZone::State::STOPPED;
-}
-
-
-void ZoneAdmin::suspend()
-{
- LOGD(mId << ": Pausing...");
- if (!mZone.freeze()) {
- throw ZoneOperationException("Could not pause zone");
- }
- LOGD(mId << ": Paused");
-}
-
-
-void ZoneAdmin::resume()
-{
- LOGD(mId << ": Resuming...");
- if (!mZone.unfreeze()) {
- throw ZoneOperationException("Could not resume zone");
- }
- LOGD(mId << ": Resumed");
-}
-
-
-bool ZoneAdmin::isPaused()
-{
- return mZone.getState() == lxc::LxcZone::State::FROZEN;
-}
-
-
-void ZoneAdmin::setSchedulerLevel(SchedulerLevel sched)
-{
- assert(isRunning());
-
- switch (sched) {
- case SchedulerLevel::FOREGROUND:
- LOGD(mId << ": Setting SchedulerLevel::FOREGROUND");
- setSchedulerParams(DEFAULT_CPU_SHARES,
- DEFAULT_VCPU_PERIOD_MS,
- mConfig.cpuQuotaForeground);
- break;
- case SchedulerLevel::BACKGROUND:
- LOGD(mId << ": Setting SchedulerLevel::BACKGROUND");
- setSchedulerParams(DEFAULT_CPU_SHARES,
- DEFAULT_VCPU_PERIOD_MS,
- mConfig.cpuQuotaBackground);
- break;
- default:
- assert(0 && "Unknown sched parameter value");
- }
-}
-
-
-void ZoneAdmin::setSchedulerParams(std::uint64_t cpuShares,
- std::uint64_t vcpuPeriod,
- std::int64_t vcpuQuota)
-{
- assert(vcpuPeriod >= 1000 && vcpuPeriod <= 1000000);
- assert(vcpuQuota == -1 ||
- (vcpuQuota >= 1000 && vcpuQuota <= static_cast<std::int64_t>(ULLONG_MAX / 1000)));
-
- if (!lxc::setCgroup(mId, "cpu", "cpu.shares", std::to_string(cpuShares)) ||
- !lxc::setCgroup(mId, "cpu", "cpu.cfs_period_us", std::to_string(vcpuPeriod)) ||
- !lxc::setCgroup(mId, "cpu", "cpu.cfs_quota_us", std::to_string(vcpuQuota))) {
-
- LOGE(mId << ": Error while setting the zone's scheduler params");
- throw ZoneOperationException("Could not set scheduler params");
- }
-}
-
-void ZoneAdmin::setDetachOnExit()
-{
- mDetachOnExit = true;
-}
-
-void ZoneAdmin::setDestroyOnExit()
-{
- mDestroyOnExit = true;
-}
-
-std::int64_t ZoneAdmin::getSchedulerQuota()
-{
- std::string ret;
- if (!lxc::getCgroup(mId, "cpu", "cpu.cfs_quota_us", ret)) {
- LOGE(mId << ": Error while getting the zone's scheduler quota param");
- throw ZoneOperationException("Could not get scheduler quota param");
- }
- return std::stoll(ret);
-}
-
-void ZoneAdmin::createNetdevVeth(const std::string& zoneDev,
- const std::string& hostDev)
-{
- netdev::createVeth(mZone.getInitPid(), zoneDev, hostDev);
-}
-
-void ZoneAdmin::createNetdevMacvlan(const std::string& zoneDev,
- const std::string& hostDev,
- const uint32_t& mode)
-{
- netdev::createMacvlan(mZone.getInitPid(), zoneDev, hostDev, static_cast<macvlan_mode>(mode));
-}
-
-void ZoneAdmin::moveNetdev(const std::string& devId)
-{
- netdev::movePhys(mZone.getInitPid(), devId);
-}
-
-void ZoneAdmin::destroyNetdev(const std::string& devId)
-{
- netdev::destroyNetdev(devId, mZone.getInitPid());
-}
-
-void ZoneAdmin::setNetdevAttrs(const std::string& netdev, const NetdevAttrs& attrs)
-{
- netdev::setAttrs(mZone.getInitPid(), netdev, attrs);
-}
-
-ZoneAdmin::NetdevAttrs ZoneAdmin::getNetdevAttrs(const std::string& netdev)
-{
- return netdev::getAttrs(mZone.getInitPid(), netdev);
-}
-
-std::vector<std::string> ZoneAdmin::getNetdevList()
-{
- return netdev::listNetdev(mZone.getInitPid());
-}
-
-void ZoneAdmin::deleteNetdevIpAddress(const std::string& netdev, const std::string& ip)
-{
- netdev::deleteIpAddress(mZone.getInitPid(), netdev, ip);
-}
-
-} // namespace vasum
+++ /dev/null
-/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact: Jan Olszak <j.olszak@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-/**
- * @file
- * @author Jan Olszak (j.olszak@samsung.com)
- * @brief Declaration of the class for administrating one zone
- */
-
-
-#ifndef SERVER_ZONE_ADMIN_HPP
-#define SERVER_ZONE_ADMIN_HPP
-
-#include "zone-config.hpp"
-#include "lxc/zone.hpp"
-#include "netdev.hpp"
-
-namespace vasum {
-
-
-enum class SchedulerLevel {
- FOREGROUND,
- BACKGROUND
-};
-
-class ZoneAdmin {
-
-public:
- typedef netdev::Attrs NetdevAttrs;
-
- /**
- * ZoneAdmin constructor
- * @param zoneId zone id
- * @param zonesPath directory where zones are defined (configs, rootfs etc)
- * @param zoneTemplateDir directory where templates are stored
- * @param config zones config
- * @param dynamicConfig zones dynamic config
- */
- ZoneAdmin(const std::string& zoneId,
- const std::string& zonesPath,
- const std::string& zoneTemplateDir,
- const ZoneConfig& config,
- const ZoneDynamicConfig& dynamicConfig);
- virtual ~ZoneAdmin();
-
- /**
- * Get the zone id
- */
- const std::string& getId() const;
-
- /**
- * Boot the zone to the background.
- */
- void start();
-
- /**
- * Try to shutdown the zone, if failed, kill it.
- */
- void stop();
-
- /**
- * Destroy stopped zone. In particular it removes whole zones rootfs.
- */
- void destroy();
-
- /**
- * @return Is the zone running?
- */
- bool isRunning();
-
- /**
- * Check if the zone is stopped. It's NOT equivalent to !isRunning,
- * because it checks different internal zone states. There are other states,
- * (e.g. paused) when the zone isn't running nor stopped.
- *
- * @return Is the zone stopped?
- */
- bool isStopped();
-
- /**
- * Suspends an active zone, the process is frozen
- * without further access to CPU resources and I/O,
- * but the memory used by the zone
- * at the hypervisor level will stay allocated
- */
- void suspend();
-
- /**
- * Resume the zone after suspension.
- */
- void resume();
-
- /**
- * @return Is the zone in a paused state?
- */
- bool isPaused();
-
- /**
- * Sets the zones scheduler CFS quota.
- */
- void setSchedulerLevel(SchedulerLevel sched);
-
- /**
- * Set whether zone should be detached on exit.
- */
- void setDetachOnExit();
-
- /**
- * Set if zone should be destroyed on exit.
- */
- void setDestroyOnExit();
-
- /**
- * @return Scheduler CFS quota,
- * TODO: this function is only for UNIT TESTS
- */
- std::int64_t getSchedulerQuota();
-
- /**
- * Create veth network device
- */
- void createNetdevVeth(const std::string& zoneDev,
- const std::string& hostDev);
-
- /**
- * Create macvlan network device
- */
- void createNetdevMacvlan(const std::string& zoneDev,
- const std::string& hostDev,
- const uint32_t& mode);
-
- /**
- * Move network device to zone
- */
- void moveNetdev(const std::string& devId);
-
- /**
- * Destroy network device in zone
- */
- void destroyNetdev(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();
-
- /**
- * Remove ipv4/ipv6 address from network device
- */
- void deleteNetdevIpAddress(const std::string& netdev, const std::string& ip);
-
-private:
- const ZoneConfig& mConfig;
- const ZoneDynamicConfig& mDynamicConfig;
- lxc::LxcZone mZone;
- const std::string mId;
- bool mDetachOnExit;
- bool mDestroyOnExit;
-
- void setSchedulerParams(std::uint64_t cpuShares, std::uint64_t vcpuPeriod, std::int64_t vcpuQuota);
-};
-
-
-} // namespace vasum
-
-
-#endif // SERVER_ZONE_ADMIN_HPP
#include "zone.hpp"
#include "dynamic-config-scheme.hpp"
-#include "base-exception.hpp"
+#include "exception.hpp"
#include "logger/logger.hpp"
#include "utils/paths.hpp"
#include "utils/vt.hpp"
+#include "utils/c-array.hpp"
+#include "lxc/cgroup.hpp"
#include "config/manager.hpp"
#include <boost/filesystem.hpp>
+#include <cassert>
+#include <climits>
#include <string>
#include <thread>
+#include <chrono>
namespace vasum {
const std::string STATE_RUNNING = "running";
const std::string STATE_PAUSED = "paused";
+const std::uint64_t DEFAULT_CPU_SHARES = 1024;
+const std::uint64_t DEFAULT_VCPU_PERIOD_MS = 100000;
+
} // namespace
Zone::Zone(const std::string& zoneId,
const std::string& zoneTemplateDir,
const std::string& baseRunMountPointPath)
: mDbPath(dbPath)
+ , mZone(zonesPath, zoneId)
+ , mId(zoneId)
+ , mDetachOnExit(false)
+ , mDestroyOnExit(false)
{
+ LOGD(mId << ": Instantiating Zone object");
+
const std::string dbPrefix = getZoneDbPrefix(zoneId);
config::loadFromKVStoreWithJsonFile(dbPath, zoneTemplatePath, mConfig, dbPrefix);
config::loadFromKVStoreWithJsonFile(dbPath, zoneTemplatePath, mDynamicConfig, dbPrefix);
mRunMountPoint = fs::absolute(mDynamicConfig.runMountPoint, baseRunMountPointPath).string();
}
- mAdmin.reset(new ZoneAdmin(zoneId, zonesPath, zoneTemplateDir, mConfig, mDynamicConfig));
+ if (!mZone.isDefined()) {
+ const std::string zoneTemplate = utils::getAbsolutePath(mConfig.zoneTemplate,
+ zoneTemplateDir);
+ LOGI(mId << ": Creating zone from template: " << zoneTemplate);
+ utils::CStringArrayBuilder args;
+ if (!mDynamicConfig.ipv4Gateway.empty()) {
+ args.add("--ipv4-gateway");
+ args.add(mDynamicConfig.ipv4Gateway.c_str());
+ }
+ if (!mDynamicConfig.ipv4.empty()) {
+ args.add("--ipv4");
+ args.add(mDynamicConfig.ipv4.c_str());
+ }
+ const std::string vt = std::to_string(mDynamicConfig.vt);
+ if (mDynamicConfig.vt > 0) {
+ args.add("--vt");
+ args.add(vt.c_str());
+ }
+ if (!mZone.create(zoneTemplate, args.c_array())) {
+ throw ZoneOperationException("Could not create zone");
+ }
+ }
const fs::path zonePath = fs::path(zonesPath) / zoneId;
mRootPath = (zonePath / fs::path("rootfs")).string();
mProvision.reset(new ZoneProvision(mRootPath, zoneTemplatePath, dbPath, dbPrefix, mConfig.validLinkPrefixes));
}
+Zone::~Zone()
+{
+ LOGD(mId << ": Destroying Zone object...");
+
+ if (mDestroyOnExit) {
+ if (!mZone.stop()) {
+ LOGE(mId << ": Failed to stop the zone");
+ }
+ if (!mZone.destroy()) {
+ LOGE(mId << ": Failed to destroy the zone");
+ }
+ }
+
+ if (!mDetachOnExit && !mDestroyOnExit) {
+ // Try to forcefully stop
+ if (!mZone.stop()) {
+ LOGE(mId << ": Failed to stop the zone");
+ }
+ }
+
+ LOGD(mId << ": Zone object destroyed");
+}
+
const std::vector<boost::regex>& Zone::getPermittedToSend() const
{
return mPermittedToSend;
const std::string& Zone::getId() const
{
Lock lock(mReconnectMutex);
- return mAdmin->getId();
+ return mId;
}
int Zone::getPrivilege() const
void Zone::saveDynamicConfig()
{
- config::saveToKVStore(mDbPath, mDynamicConfig, getZoneDbPrefix(getId()));
+ config::saveToKVStore(mDbPath, mDynamicConfig, getZoneDbPrefix(mId));
}
void Zone::updateRequestedState(const std::string& state)
{
// assume mutex is locked
if (state != mDynamicConfig.requestedState) {
- LOGT("Set requested state of " << getId() << " to " << state);
+ LOGT("Set requested state of " << mId << " to " << state);
mDynamicConfig.requestedState = state;
saveDynamicConfig();
}
{
Lock lock(mReconnectMutex);
requestedState = mDynamicConfig.requestedState;
- LOGT("Requested state of " << getId() << ": " << requestedState);
+ LOGT("Requested state of " << mId << ": " << requestedState);
}
if (requestedState == STATE_RUNNING) {
void Zone::start()
{
Lock lock(mReconnectMutex);
+
+ LOGD(mId << ": Starting...");
+
updateRequestedState(STATE_RUNNING);
mProvision->start();
- mAdmin->start();
+
+ if (isRunning()) {
+ LOGD(mId << ": Already running - nothing to do...");
+ return;
+ }
+
+ utils::CStringArrayBuilder args;
+ for (const std::string& arg : mConfig.initWithArgs) {
+ args.add(arg.c_str());
+ }
+ if (args.empty()) {
+ args.add("/sbin/init");
+ }
+
+ if (!mZone.start(args.c_array())) {
+ throw ZoneOperationException("Could not start zone");
+ }
+
+ // Wait until the full platform launch with graphical stack.
+ // VT should be activated by a graphical stack.
+ // If we do it with 'zoneToFocus.activateVT' before starting the graphical stack,
+ // graphical stack initialization failed and we finally switch to the black screen.
+ // Skip waiting when graphical stack is not running (unit tests).
+ if (mDynamicConfig.vt > 0) {
+ // TODO, timeout is a temporary solution
+ std::this_thread::sleep_for(std::chrono::milliseconds(4000));
+ }
+
+ LOGD(mId << ": Started");
+
// Increase cpu quota before connect, otherwise it'd take ages.
goForeground();
// refocus in ZonesManager will adjust cpu quota after all
void Zone::stop(bool saveState)
{
Lock lock(mReconnectMutex);
+
+ LOGD(mId << ": Stopping procedure started...");
+
if (saveState) {
updateRequestedState(STATE_STOPPED);
}
- if (mAdmin->isRunning()) {
+ if (isRunning()) {
// boost stopping
goForeground();
}
- mAdmin->stop();
+
+ if (isStopped()) {
+ LOGD(mId << ": Already crashed/down/off - nothing to do");
+ return;
+ }
+
+ if (!mZone.shutdown(mConfig.shutdownTimeout)) {
+ // force stop
+ if (!mZone.stop()) {
+ throw ZoneOperationException("Could not stop zone");
+ }
+ }
+
mProvision->stop();
+
+ LOGD(mId << ": Stopping procedure ended");
}
int Zone::getVT() const
const std::string& hostDev)
{
Lock lock(mReconnectMutex);
- mAdmin->createNetdevVeth(zoneDev, hostDev);
+ netdev::createVeth(mZone.getInitPid(), zoneDev, hostDev);
}
void Zone::createNetdevMacvlan(const std::string& zoneDev,
const uint32_t& mode)
{
Lock lock(mReconnectMutex);
- mAdmin->createNetdevMacvlan(zoneDev, hostDev, mode);
+ netdev::createMacvlan(mZone.getInitPid(), zoneDev, hostDev, static_cast<macvlan_mode>(mode));
}
void Zone::moveNetdev(const std::string& devId)
{
Lock lock(mReconnectMutex);
- mAdmin->moveNetdev(devId);
+ netdev::movePhys(mZone.getInitPid(), devId);
}
void Zone::destroyNetdev(const std::string& devId)
{
Lock lock(mReconnectMutex);
- mAdmin->destroyNetdev(devId);
+ netdev::destroyNetdev(devId, mZone.getInitPid());
}
void Zone::goForeground()
{
Lock lock(mReconnectMutex);
- mAdmin->setSchedulerLevel(SchedulerLevel::FOREGROUND);
+ setSchedulerLevel(SchedulerLevel::FOREGROUND);
}
void Zone::goBackground()
{
Lock lock(mReconnectMutex);
- mAdmin->setSchedulerLevel(SchedulerLevel::BACKGROUND);
+ setSchedulerLevel(SchedulerLevel::BACKGROUND);
}
void Zone::setDetachOnExit()
{
Lock lock(mReconnectMutex);
- mAdmin->setDetachOnExit();
+ mDetachOnExit = true;
}
void Zone::setDestroyOnExit()
{
Lock lock(mReconnectMutex);
- mAdmin->setDestroyOnExit();
+ mDestroyOnExit = true;
}
bool Zone::isRunning()
{
Lock lock(mReconnectMutex);
- return mAdmin->isRunning();
+ return mZone.getState() == lxc::LxcZone::State::RUNNING;
}
bool Zone::isStopped()
{
Lock lock(mReconnectMutex);
- return mAdmin->isStopped();
+ return mZone.getState() == lxc::LxcZone::State::STOPPED;
}
void Zone::suspend()
{
Lock lock(mReconnectMutex);
- mAdmin->suspend();
+
+ LOGD(mId << ": Pausing...");
+ if (!mZone.freeze()) {
+ throw ZoneOperationException("Could not pause zone");
+ }
+ LOGD(mId << ": Paused");
+
updateRequestedState(STATE_PAUSED);
}
void Zone::resume()
{
Lock lock(mReconnectMutex);
- mAdmin->resume();
+
+ LOGD(mId << ": Resuming...");
+ if (!mZone.unfreeze()) {
+ throw ZoneOperationException("Could not resume zone");
+ }
+ LOGD(mId << ": Resumed");
+
updateRequestedState(STATE_RUNNING);
}
bool Zone::isPaused()
{
Lock lock(mReconnectMutex);
- return mAdmin->isPaused();
+ return mZone.getState() == lxc::LxcZone::State::FROZEN;
}
bool Zone::isSwitchToDefaultAfterTimeoutAllowed() const
mProvision->remove(declarationId);
}
-void Zone::setNetdevAttrs(const std::string& netdev, const ZoneAdmin::NetdevAttrs& attrs)
+void Zone::setNetdevAttrs(const std::string& netdev, const NetdevAttrs& attrs)
{
Lock lock(mReconnectMutex);
- mAdmin->setNetdevAttrs(netdev, attrs);
+ netdev::setAttrs(mZone.getInitPid(), netdev, attrs);
}
-ZoneAdmin::NetdevAttrs Zone::getNetdevAttrs(const std::string& netdev)
+Zone::NetdevAttrs Zone::getNetdevAttrs(const std::string& netdev)
{
Lock lock(mReconnectMutex);
- return mAdmin->getNetdevAttrs(netdev);
+ return netdev::getAttrs(mZone.getInitPid(), netdev);
}
std::vector<std::string> Zone::getNetdevList()
{
Lock lock(mReconnectMutex);
- return mAdmin->getNetdevList();
+ return netdev::listNetdev(mZone.getInitPid());
}
void Zone::deleteNetdevIpAddress(const std::string& netdev, const std::string& ip)
{
Lock lock(mReconnectMutex);
- mAdmin->deleteNetdevIpAddress(netdev, ip);
+ netdev::deleteIpAddress(mZone.getInitPid(), netdev, ip);
+}
+
+std::int64_t Zone::getSchedulerQuota()
+{
+ std::string ret;
+ if (!lxc::getCgroup(mId, "cpu", "cpu.cfs_quota_us", ret)) {
+ LOGE(mId << ": Error while getting the zone's scheduler quota param");
+ throw ZoneOperationException("Could not get scheduler quota param");
+ }
+ return std::stoll(ret);
+}
+
+void Zone::setSchedulerLevel(SchedulerLevel sched)
+{
+ assert(isRunning());
+
+ switch (sched) {
+ case SchedulerLevel::FOREGROUND:
+ LOGD(mId << ": Setting SchedulerLevel::FOREGROUND");
+ setSchedulerParams(DEFAULT_CPU_SHARES,
+ DEFAULT_VCPU_PERIOD_MS,
+ mConfig.cpuQuotaForeground);
+ break;
+ case SchedulerLevel::BACKGROUND:
+ LOGD(mId << ": Setting SchedulerLevel::BACKGROUND");
+ setSchedulerParams(DEFAULT_CPU_SHARES,
+ DEFAULT_VCPU_PERIOD_MS,
+ mConfig.cpuQuotaBackground);
+ break;
+ default:
+ assert(0 && "Unknown sched parameter value");
+ }
+}
+
+void Zone::setSchedulerParams(std::uint64_t cpuShares,
+ std::uint64_t vcpuPeriod,
+ std::int64_t vcpuQuota)
+{
+ assert(vcpuPeriod >= 1000 && vcpuPeriod <= 1000000);
+ assert(vcpuQuota == -1 ||
+ (vcpuQuota >= 1000 && vcpuQuota <= static_cast<std::int64_t>(ULLONG_MAX / 1000)));
+
+ if (!lxc::setCgroup(mId, "cpu", "cpu.shares", std::to_string(cpuShares)) ||
+ !lxc::setCgroup(mId, "cpu", "cpu.cfs_period_us", std::to_string(vcpuPeriod)) ||
+ !lxc::setCgroup(mId, "cpu", "cpu.cfs_quota_us", std::to_string(vcpuQuota))) {
+
+ LOGE(mId << ": Error while setting the zone's scheduler params");
+ throw ZoneOperationException("Could not set scheduler params");
+ }
}
} // namespace vasum
#define SERVER_ZONE_HPP
#include "zone-config.hpp"
-#include "zone-admin.hpp"
#include "zone-provision.hpp"
+#include "lxc/zone.hpp"
+#include "netdev.hpp"
+
#include <mutex>
#include <string>
#include <memory>
namespace vasum {
+enum class SchedulerLevel {
+ FOREGROUND,
+ BACKGROUND
+};
+
class Zone {
public:
+ typedef netdev::Attrs NetdevAttrs;
+
/**
* Zone constructor
* @param zoneId zone id
const std::string& baseRunMountPointPath);
Zone(const Zone&) = delete;
Zone& operator=(const Zone&) = delete;
+ ~Zone();
typedef std::function<void(bool succeeded)> StartAsyncResultCallback;
*/
const std::vector<boost::regex>& getPermittedToRecv() const;
- // ZoneAdmin API
-
/**
* Get the zone id
*/
/**
* Set if zone should be detached on exit.
- *
- * This sends detach flag to ZoneAdmin object.
*/
void setDetachOnExit();
bool isStopped();
/**
- * Suspend zone.
+ * Suspends an active zone, the process is frozen
+ * without further access to CPU resources and I/O,
+ * but the memory used by the zone
+ * at the hypervisor level will stay allocated
*/
void suspend();
/**
* Set network device attributes
*/
- void setNetdevAttrs(const std::string& netdev, const ZoneAdmin::NetdevAttrs& attrs);
+ void setNetdevAttrs(const std::string& netdev, const NetdevAttrs& attrs);
/**
* Get network device attributes
*/
- ZoneAdmin::NetdevAttrs getNetdevAttrs(const std::string& netdev);
+ NetdevAttrs getNetdevAttrs(const std::string& netdev);
/**
* Get network device list
*/
void deleteNetdevIpAddress(const std::string& netdev, const std::string& ip);
+ /**
+ * Sets the zones scheduler CFS quota.
+ */
+ void setSchedulerLevel(SchedulerLevel sched);
+
+ /**
+ * @return Scheduler CFS quota,
+ * TODO: this function is only for UNIT TESTS
+ */
+ std::int64_t getSchedulerQuota();
+
private:
ZoneConfig mConfig;
ZoneDynamicConfig mDynamicConfig;
std::vector<boost::regex> mPermittedToSend;
std::vector<boost::regex> mPermittedToRecv;
- std::unique_ptr<ZoneAdmin> mAdmin;
std::unique_ptr<ZoneProvision> mProvision;
mutable std::recursive_mutex mReconnectMutex;
std::string mRunMountPoint;
std::string mRootPath;
std::string mDbPath;
+ lxc::LxcZone mZone;
+ const std::string mId;
+ bool mDetachOnExit;
+ bool mDestroyOnExit;
void onNameLostCallback();
void saveDynamicConfig();
void updateRequestedState(const std::string& state);
+ void setSchedulerParams(std::uint64_t cpuShares, std::uint64_t vcpuPeriod, std::int64_t vcpuQuota);
};
#include "common-definitions.hpp"
#include "dynamic-config-scheme.hpp"
#include "zones-manager.hpp"
-#include "zone-admin.hpp"
#include "lxc/cgroup.hpp"
#include "exception.hpp"
+++ /dev/null
-/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact: Jan Olszak <j.olszak@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-
-/**
- * @file
- * @author Jan Olszak (j.olszak@samsung.com)
- * @brief Unit tests of the ZoneAdmin class
- */
-
-#include "config.hpp"
-#include "ut.hpp"
-
-#include "zone-admin.hpp"
-#include "exception.hpp"
-
-#include "utils/glib-loop.hpp"
-#include "utils/scoped-dir.hpp"
-#include "config/manager.hpp"
-
-using namespace vasum;
-
-namespace {
-
-const std::string TEMPLATES_DIR = VSM_TEST_TEMPLATES_INSTALL_DIR;
-const std::string TEST_CONFIG_PATH = TEMPLATES_DIR + "/default.conf";
-const std::string TEST_NO_SHUTDOWN_CONFIG_PATH = TEMPLATES_DIR + "/test-no-shutdown.conf";
-const std::string BUGGY_CONFIG_PATH = TEMPLATES_DIR + "/buggy-init.conf";
-const std::string MISSING_CONFIG_PATH = TEMPLATES_DIR + "/missing.conf";
-const std::string ZONES_PATH = "/tmp/ut-zones";
-
-struct Fixture {
- utils::ScopedGlibLoop mLoop;
- utils::ScopedDir mZonesPathGuard;
-
- ZoneConfig mConfig;
- ZoneDynamicConfig mDynamicConfig;
-
- Fixture()
- : mZonesPathGuard(ZONES_PATH)
- {}
-
- std::unique_ptr<ZoneAdmin> create(const std::string& configPath)
- {
- config::loadFromJsonFile(configPath, mConfig);
- config::loadFromJsonFile(configPath, mDynamicConfig);
- return std::unique_ptr<ZoneAdmin>(new ZoneAdmin("zoneId",
- ZONES_PATH,
- TEMPLATES_DIR,
- mConfig,
- mDynamicConfig));
- }
-
- void ensureStarted()
- {
- // wait for zones init to fully start
- std::this_thread::sleep_for(std::chrono::milliseconds(200));
- }
-};
-
-} // namespace
-
-
-BOOST_FIXTURE_TEST_SUITE(ZoneAdminSuite, Fixture)
-
-BOOST_AUTO_TEST_CASE(ConstructorDestructor)
-{
- auto admin = create(TEST_CONFIG_PATH);
- admin.reset();
-}
-
-BOOST_AUTO_TEST_CASE(MissingConfig)
-{
- BOOST_REQUIRE_EXCEPTION(create(MISSING_CONFIG_PATH),
- ZoneOperationException,
- WhatEquals("Could not create zone"));
-}
-
-BOOST_AUTO_TEST_CASE(Start)
-{
- auto admin = create(TEST_CONFIG_PATH);
-
- admin->start();
- ensureStarted();
-
- BOOST_CHECK(admin->isRunning());
-}
-
-BOOST_AUTO_TEST_CASE(StartBuggy)
-{
- auto admin = create(BUGGY_CONFIG_PATH);
- BOOST_REQUIRE_EXCEPTION(admin->start(),
- ZoneOperationException,
- WhatEquals("Could not start zone"));
-}
-
-BOOST_AUTO_TEST_CASE(StopShutdown)
-{
- auto admin = create(TEST_CONFIG_PATH);
-
- admin->start();
- ensureStarted();
- BOOST_REQUIRE(admin->isRunning());
-
- admin->stop();
- BOOST_CHECK(!admin->isRunning());
- BOOST_CHECK(admin->isStopped());
-}
-
-// This test needs to wait for a shutdown timer in stop() method. This takes 10s+.
-BOOST_AUTO_TEST_CASE(StopDestroy)
-{
- auto admin = create(TEST_NO_SHUTDOWN_CONFIG_PATH);
-
- admin->start();
- ensureStarted();
- BOOST_REQUIRE(admin->isRunning());
-
- admin->stop();
- BOOST_CHECK(!admin->isRunning());
- BOOST_CHECK(admin->isStopped());
-}
-
-BOOST_AUTO_TEST_CASE(SuspendResume)
-{
- auto admin = create(TEST_NO_SHUTDOWN_CONFIG_PATH);
-
- admin->start();
- ensureStarted();
- BOOST_REQUIRE(admin->isRunning());
-
- admin->suspend();
- BOOST_CHECK(!admin->isRunning());
- BOOST_CHECK(!admin->isStopped());
- BOOST_CHECK(admin->isPaused());
-
- admin->resume();
- BOOST_CHECK(!admin->isPaused());
- BOOST_CHECK(!admin->isStopped());
- BOOST_CHECK(admin->isRunning());
-}
-
-BOOST_AUTO_TEST_CASE(ForegroundBackgroundSchedulerLevel)
-{
- auto admin = create(TEST_CONFIG_PATH);
-
- BOOST_REQUIRE(mConfig.cpuQuotaForeground != mConfig.cpuQuotaBackground);
-
- admin->start();
- ensureStarted();
-
- admin->setSchedulerLevel(SchedulerLevel::FOREGROUND);
- BOOST_CHECK_EQUAL(admin->getSchedulerQuota(), mConfig.cpuQuotaForeground);
-
- admin->setSchedulerLevel(SchedulerLevel::BACKGROUND);
- BOOST_CHECK_EQUAL(admin->getSchedulerQuota(), mConfig.cpuQuotaBackground);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
#include "utils/exception.hpp"
#include "utils/glib-loop.hpp"
#include "utils/scoped-dir.hpp"
+#include "config/manager.hpp"
#include "config/exception.hpp"
#include "netdev.hpp"
const std::string TEMPLATES_DIR = VSM_TEST_TEMPLATES_INSTALL_DIR;
const std::string TEST_CONFIG_PATH = TEMPLATES_DIR + "/default.conf";
+const std::string TEST_NO_SHUTDOWN_CONFIG_PATH = TEMPLATES_DIR + "/test-no-shutdown.conf";
const std::string TEST_DBUS_CONFIG_PATH = TEMPLATES_DIR + "/console-dbus.conf";
const std::string BUGGY_CONFIG_PATH = TEMPLATES_DIR + "/buggy-template.conf";
+const std::string BUGGY_INIT_CONFIG_PATH = TEMPLATES_DIR + "/buggy-init.conf";
const std::string MISSING_CONFIG_PATH = TEMPLATES_DIR + "/missing-config.conf";
const std::string ZONES_PATH = "/tmp/ut-zones";
const std::string DB_PATH = ZONES_PATH + "/vasum.db";
c->stop(true);
}
+BOOST_AUTO_TEST_CASE(StartBuggyInit)
+{
+ auto c = create(BUGGY_INIT_CONFIG_PATH);
+ BOOST_REQUIRE_EXCEPTION(c->start(),
+ ZoneOperationException,
+ WhatEquals("Could not start zone"));
+}
+
+BOOST_AUTO_TEST_CASE(StopShutdown)
+{
+ auto c = create(TEST_CONFIG_PATH);
+
+ c->start();
+ ensureStarted();
+ BOOST_REQUIRE(c->isRunning());
+
+ c->stop(true);
+ BOOST_CHECK(!c->isRunning());
+ BOOST_CHECK(c->isStopped());
+}
+
+// This test needs to wait for a shutdown timer in stop() method. This takes 10s+.
+BOOST_AUTO_TEST_CASE(StopDestroy)
+{
+ auto c = create(TEST_NO_SHUTDOWN_CONFIG_PATH);
+
+ c->start();
+ ensureStarted();
+ BOOST_REQUIRE(c->isRunning());
+
+ c->stop(true);
+ BOOST_CHECK(!c->isRunning());
+ BOOST_CHECK(c->isStopped());
+}
+
+BOOST_AUTO_TEST_CASE(SuspendResume)
+{
+ auto c = create(TEST_NO_SHUTDOWN_CONFIG_PATH);
+
+ c->start();
+ ensureStarted();
+ BOOST_REQUIRE(c->isRunning());
+
+ c->suspend();
+ BOOST_CHECK(!c->isRunning());
+ BOOST_CHECK(!c->isStopped());
+ BOOST_CHECK(c->isPaused());
+
+ c->resume();
+ BOOST_CHECK(!c->isPaused());
+ BOOST_CHECK(!c->isStopped());
+ BOOST_CHECK(c->isRunning());
+}
+
+BOOST_AUTO_TEST_CASE(ForegroundBackgroundSchedulerLevel)
+{
+ auto c = create(TEST_CONFIG_PATH);
+ ZoneConfig refConfig;
+ config::loadFromJsonFile(TEST_CONFIG_PATH, refConfig);
+
+ BOOST_REQUIRE(refConfig.cpuQuotaForeground != refConfig.cpuQuotaBackground);
+
+ c->start();
+ ensureStarted();
+
+ c->setSchedulerLevel(SchedulerLevel::FOREGROUND);
+ BOOST_CHECK_EQUAL(c->getSchedulerQuota(), refConfig.cpuQuotaForeground);
+
+ c->setSchedulerLevel(SchedulerLevel::BACKGROUND);
+ BOOST_CHECK_EQUAL(c->getSchedulerQuota(), refConfig.cpuQuotaBackground);
+}
+
BOOST_AUTO_TEST_CASE(DbusConnection)
{
mRunGuard.create("/tmp/ut-run"); // the same path as in zone template
c->start();
ensureStarted();
c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME);
- ZoneAdmin::NetdevAttrs attrs = c->getNetdevAttrs(ZONE_NETDEV);
+ Zone::NetdevAttrs attrs = c->getNetdevAttrs(ZONE_NETDEV);
bool gotMtu = false;
bool gotFlags = false;
bool gotType = false;
c->start();
ensureStarted();
c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME);
- ZoneAdmin::NetdevAttrs attrsIn;
+ Zone::NetdevAttrs attrsIn;
attrsIn.push_back(std::make_tuple("mtu", "500"));
c->setNetdevAttrs(ZONE_NETDEV, attrsIn);
bool gotMtu = false;
- ZoneAdmin::NetdevAttrs attrsOut = c->getNetdevAttrs(ZONE_NETDEV);
+ Zone::NetdevAttrs attrsOut = c->getNetdevAttrs(ZONE_NETDEV);
for (auto& attr : attrsOut) {
if (std::get<0>(attr) == "mtu") {
BOOST_CHECK(!gotMtu);
c->start();
ensureStarted();
c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME);
- ZoneAdmin::NetdevAttrs attrsIn;
+ Zone::NetdevAttrs attrsIn;
attrsIn.push_back(std::make_tuple("ipv4", "ip:192.168.4.1,prefixlen:24"));
c->setNetdevAttrs(ZONE_NETDEV, attrsIn);
- ZoneAdmin::NetdevAttrs attrsOut = c->getNetdevAttrs(ZONE_NETDEV);
+ Zone::NetdevAttrs attrsOut = c->getNetdevAttrs(ZONE_NETDEV);
int gotIp = 0;
for (auto& attr : attrsOut) {
if (std::get<0>(attr) == "ipv4") {
c->start();
ensureStarted();
c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME);
- ZoneAdmin::NetdevAttrs attrsIn;
+ Zone::NetdevAttrs attrsIn;
attrsIn.push_back(std::make_tuple("ipv6", "ip:2001:db8::1,prefixlen:64"));
c->setNetdevAttrs(ZONE_NETDEV, attrsIn);
- ZoneAdmin::NetdevAttrs attrsOut = c->getNetdevAttrs(ZONE_NETDEV);
+ Zone::NetdevAttrs attrsOut = c->getNetdevAttrs(ZONE_NETDEV);
int gotIp = 0;
for (auto& attr : attrsOut) {
if (std::get<0>(attr) == "ipv6") {
BOOST_AUTO_TEST_CASE(DelNetdevIpAddress)
{
- auto contain = [](const ZoneAdmin::NetdevAttrs& container, const std::string& key) {
+ auto contain = [](const Zone::NetdevAttrs& container, const std::string& key) {
return container.end() != find_if(container.begin(),
container.end(),
- [&](const ZoneAdmin::NetdevAttrs::value_type& value) {
+ [&](const Zone::NetdevAttrs::value_type& value) {
return std::get<0>(value) == key;
});
};
c->start();
ensureStarted();
c->createNetdevVeth(ZONE_NETDEV, BRIDGE_NAME);
- ZoneAdmin::NetdevAttrs attrs;
+ Zone::NetdevAttrs attrs;
attrs.push_back(std::make_tuple("ipv6", "ip:2001:db8::1,prefixlen:64"));
attrs.push_back(std::make_tuple("ipv4", "ip:192.168.4.1,prefixlen:24"));
c->setNetdevAttrs(ZONE_NETDEV, attrs);