#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 {
-namespace {
-
-// TODO: this should be in zone's configuration file
-const int SHUTDOWN_WAIT = 10;
-
-} // namespace
-
const std::uint64_t DEFAULT_CPU_SHARES = 1024;
const std::uint64_t DEFAULT_VCPU_PERIOD_MS = 100000;
-ZoneAdmin::ZoneAdmin(const std::string& zonesPath,
- const std::string& lxcTemplatePrefix,
- const ZoneConfig& config)
+ZoneAdmin::ZoneAdmin(const std::string& zoneId,
+ const std::string& zonesPath,
+ const std::string& zoneTemplatePrefix,
+ const ZoneConfig& config,
+ const ZoneDynamicConfig& dynamicConfig)
: mConfig(config),
- mZone(zonesPath, config.name),
- mId(mZone.getName()),
+ mDynamicConfig(dynamicConfig),
+ mZone(zonesPath, zoneId),
+ mId(zoneId),
mDetachOnExit(false),
mDestroyOnExit(false)
{
if (!mZone.isDefined()) {
- const std::string lxcTemplate = utils::getAbsolutePath(config.lxcTemplate,
- lxcTemplatePrefix);
- LOGI(mId << ": Creating zone from template: " << lxcTemplate);
+ const std::string zoneTemplate = utils::getAbsolutePath(config.zoneTemplate,
+ zoneTemplatePrefix);
+ LOGI(mId << ": Creating zone from template: " << zoneTemplate);
utils::CStringArrayBuilder args;
- if (!config.ipv4Gateway.empty()) {
+ if (!dynamicConfig.ipv4Gateway.empty()) {
args.add("--ipv4-gateway");
- args.add(config.ipv4Gateway.c_str());
+ args.add(dynamicConfig.ipv4Gateway.c_str());
}
- if (!config.ipv4.empty()) {
+ if (!dynamicConfig.ipv4.empty()) {
args.add("--ipv4");
- args.add(config.ipv4.c_str());
+ args.add(dynamicConfig.ipv4.c_str());
}
- const std::string vt = std::to_string(config.vt);
- if (config.vt > 0) {
+ const std::string vt = std::to_string(dynamicConfig.vt);
+ if (dynamicConfig.vt > 0) {
args.add("--vt");
args.add(vt.c_str());
}
- if (!mZone.create(lxcTemplate, args.c_array())) {
+ if (!mZone.create(zoneTemplate, args.c_array())) {
throw ZoneOperationException("Could not create zone");
}
}
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");
}
return;
}
- if (!mZone.shutdown(SHUTDOWN_WAIT)) {
+ if (!mZone.shutdown(mConfig.shutdownTimeout)) {
// force stop
if (!mZone.stop()) {
throw ZoneOperationException("Could not stop zone");
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,
+ 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