#include "lxc/cgroup.hpp"
#include "logger/logger.hpp"
#include "utils/fs.hpp"
+#include "utils/paths.hpp"
#include <sys/stat.h>
#include <fcntl.h>
}
}
+std::string getCgroupPath(const std::string& zoneName,
+ const std::string& cgroupController,
+ const std::string& cgroupName)
+{
+ return utils::createFilePath("/sys/fs/cgroup",
+ cgroupController,
+ "lxc",
+ zoneName,
+ cgroupName);
+}
+
} // namespace
bool setCgroup(const std::string& zoneName,
+ const std::string& cgroupController,
const std::string& cgroupName,
const std::string& value)
{
- const std::string path = "/sys/fs/cgroup/devices/lxc/" + zoneName + "/" + cgroupName;
+ const std::string path = getCgroupPath(zoneName, cgroupController, cgroupName);
LOGD("Set '" << value << "' to " << path);
return utils::saveFileContent(path, value);
}
+bool getCgroup(const std::string& zoneName,
+ const std::string& cgroupController,
+ const std::string& cgroupName,
+ std::string& value)
+{
+ const std::string path = getCgroupPath(zoneName, cgroupController, cgroupName);
+ return utils::readFirstLineOfFile(path, value);
+}
+
bool isDevice(const std::string& device)
{
struct stat devStat;
snprintf(value, sizeof(value), "%c %u:%u %s", type, major, minor, perm.c_str());
std::string name = grant ? "devices.allow" : "devices.deny";
- return setCgroup(zoneName, name, value);
+ return setCgroup(zoneName, "devices", name, value);
}
namespace lxc {
bool setCgroup(const std::string& zoneName,
+ const std::string& cgroupController,
const std::string& cgroupName,
const std::string& value);
+bool getCgroup(const std::string& zoneName,
+ const std::string& cgroupController,
+ const std::string& cgroupName,
+ std::string& value);
+
bool isDevice(const std::string& device);
bool setDeviceAccess(const std::string& zoneName,
return true;
}
+bool readFirstLineOfFile(const std::string& path, std::string& ret)
+{
+ std::ifstream file(path);
+ if (!file) {
+ LOGD(path << ": could not open for reading");
+ return false;
+ }
+
+ std::getline(file, ret);
+ if (!file) {
+ LOGD(path << ": read error");
+ return false;
+ }
+ return true;
+}
+
bool removeFile(const std::string& path)
{
LOGD(path << ": exists, removing.");
bool saveFileContent(const std::string& path, const std::string& content);
/**
+ * Read a line from file
+ * Its goal is to read a kernel config files (eg. from /proc, /sys/)
+ */
+bool readFirstLineOfFile(const std::string& path, std::string& ret);
+
+/**
* Remove file
*/
bool removeFile(const std::string& path);
#include "logger/logger.hpp"
#include "utils/paths.hpp"
#include "utils/c-array.hpp"
+#include "lxc/cgroup.hpp"
#include <cassert>
+#include <climits>
namespace vasum {
void ZoneAdmin::setSchedulerLevel(SchedulerLevel sched)
{
+ assert(isRunning());
+
switch (sched) {
case SchedulerLevel::FOREGROUND:
LOGD(mId << ": Setting SchedulerLevel::FOREGROUND");
}
-void ZoneAdmin::setSchedulerParams(std::uint64_t, std::uint64_t, std::int64_t)
-//void ZoneAdmin::setSchedulerParams(std::uint64_t cpuShares, std::uint64_t vcpuPeriod, std::int64_t vcpuQuota)
+void ZoneAdmin::setSchedulerParams(std::uint64_t cpuShares,
+ std::uint64_t vcpuPeriod,
+ std::int64_t vcpuQuota)
{
-// assert(mZone);
-//
-// int maxParams = 3;
-// int numParamsBuff = 0;
-//
-// std::unique_ptr<virTypedParameter[]> params(new virTypedParameter[maxParams]);
-//
-// virTypedParameterPtr paramsTmp = params.get();
-//
-// virTypedParamsAddULLong(¶msTmp, &numParamsBuff, &maxParams, VIR_DOMAIN_SCHEDULER_CPU_SHARES, cpuShares);
-// virTypedParamsAddULLong(¶msTmp, &numParamsBuff, &maxParams, VIR_DOMAIN_SCHEDULER_VCPU_PERIOD, vcpuPeriod);
-// virTypedParamsAddLLong(¶msTmp, &numParamsBuff, &maxParams, VIR_DOMAIN_SCHEDULER_VCPU_QUOTA, vcpuQuota);
-//
-// if (virDomainSetSchedulerParameters(mZone.get(), params.get(), numParamsBuff) < 0) {
-// LOGE(mId << ": Error while setting the zone's scheduler params:\n"
-// << libvirt::libvirtFormatError());
-// throw ZoneOperationException();
-// }
+ 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()
std::int64_t ZoneAdmin::getSchedulerQuota()
{
-// assert(mZone);
-//
-// int numParamsBuff;
-// std::unique_ptr<char, void(*)(void*)> type(virDomainGetSchedulerType(mZone.get(), &numParamsBuff), free);
-//
-// if (type == NULL || numParamsBuff <= 0 || strcmp(type.get(), "posix") != 0) {
-// LOGE(mId << ": Error while getting the zone's scheduler type:\n"
-// << libvirt::libvirtFormatError());
-// throw ZoneOperationException();
-// }
-//
-// std::unique_ptr<virTypedParameter[]> params(new virTypedParameter[numParamsBuff]);
-//
-// if (virDomainGetSchedulerParameters(mZone.get(), params.get(), &numParamsBuff) < 0) {
-// LOGE(mId << ": Error while getting the zone's scheduler params:\n"
-// << libvirt::libvirtFormatError());
-// throw ZoneOperationException();
-// }
-//
-// long long quota;
-// if (virTypedParamsGetLLong(params.get(),
-// numParamsBuff,
-// VIR_DOMAIN_SCHEDULER_VCPU_QUOTA,
-// "a) <= 0) {
-// LOGE(mId << ": Error while getting the zone's scheduler quota param:\n"
-// << libvirt::libvirtFormatError());
-// throw ZoneOperationException();
-// }
-//
-// return quota;
- return 0;
+ 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 */,
if (mConfig.enableDbusIntegration) {
mConnectionTransport.reset(new ZoneConnectionTransport(mRunMountPoint));
}
+
mAdmin->start();
if (mConfig.enableDbusIntegration) {
+ // Increase cpu quota before connect, otherwise it'd take ages.
+ goForeground();
connect();
}
-
- // Send to the background only after we're connected, otherwise it'd take ages.
- LOGD(getId() << ": sending to the background");
- goBackground();
+ // refocus in ZonesManager will adjust cpu quota after all
}
void Zone::stop()
{
Lock lock(mReconnectMutex);
+ if (mAdmin->isRunning()) {
+ // boost stopping
+ goForeground();
+ }
disconnect();
mAdmin->stop();
mConnectionTransport.reset();
}
for (auto& zone : mZones) {
- std::string id = zone->getId();
- if (id == idToFocus) {
- LOGD(id << ": being sent to foreground");
- zone->goForeground();
- } else {
- LOGD(id << ": being sent to background");
- zone->goBackground();
+ if (zone->isRunning()) {
+ std::string id = zone->getId();
+ if (id == idToFocus) {
+ LOGD(id << ": being sent to foreground");
+ zone->goForeground();
+ } else {
+ LOGD(id << ": being sent to background");
+ zone->goBackground();
+ }
}
}
mActiveZoneId = idToFocus;
LOGT("Lock zone");
try {
+ zone.goBackground();// make sure it will be in background after unlock
zone.suspend();
refocus();
} catch (ZoneOperationException& e) {
BOOST_CHECK(admin->isRunning());
}
-//BOOST_AUTO_TEST_CASE(SchedulerLevelTest)
-//{
-// auto admin = create(TEST_CONFIG_PATH);
-//
-// admin->start();
-// ensureStarted();
-// admin->setSchedulerLevel(SchedulerLevel::FOREGROUND);
-// BOOST_REQUIRE(admin->getSchedulerQuota() == config.cpuQuotaForeground);
-// admin->setSchedulerLevel(SchedulerLevel::BACKGROUND);
-// BOOST_REQUIRE(admin->getSchedulerQuota() == config.cpuQuotaBackground);
-//}
+BOOST_AUTO_TEST_CASE(SchedulerLevelTest)
+{
+ BOOST_REQUIRE(mConfig.cpuQuotaForeground != mConfig.cpuQuotaBackground);
+
+ auto admin = create(TEST_CONFIG_PATH);
+
+ 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()