23 #include "softwarecontainererror.h" 25 #include "config/configerror.h" 26 #include "config/configdefinition.h" 27 #include "config/softwarecontainerconfig.h" 28 #include "capability/servicemanifestfileloader.h" 33 std::shared_ptr<Config> config,
34 std::shared_ptr<SoftwareContainerFactory> factory,
35 std::shared_ptr<ContainerUtilityInterface> utility):
36 m_mainLoopContext(mainLoopContext),
39 m_containerUtility(utility)
41 m_containerIdPool.push_back(0);
45 m_config->getIntValue(ConfigDefinition::SC_GROUP,
46 ConfigDefinition::SC_SHUTDOWN_TIMEOUT_KEY);
47 std::string sharedMountsDir =
48 m_config->getStringValue(ConfigDefinition::SC_GROUP,
49 ConfigDefinition::SC_SHARED_MOUNTS_DIR_KEY);
50 std::string lxcConfigPath =
51 m_config->getStringValue(ConfigDefinition::SC_GROUP,
52 ConfigDefinition::SC_LXC_CONFIG_PATH_KEY);
53 #ifdef ENABLE_NETWORKGATEWAY 55 bool createBridge = m_config->getBoolValue(ConfigDefinition::SC_GROUP,
56 ConfigDefinition::SC_CREATE_BRIDGE_KEY);
57 std::string bridgeDevice = m_config->getStringValue(ConfigDefinition::SC_GROUP,
58 ConfigDefinition::SC_BRIDGE_DEVICE_KEY);
59 std::string bridgeIp = m_config->getStringValue(ConfigDefinition::SC_GROUP,
60 ConfigDefinition::SC_BRIDGE_IP_KEY);
61 std::string bridgeNetmask = m_config->getStringValue(ConfigDefinition::SC_GROUP,
62 ConfigDefinition::SC_BRIDGE_NETMASK_KEY);
63 int bridgeNetmaskBits = m_config->getIntValue(ConfigDefinition::SC_GROUP,
64 ConfigDefinition::SC_BRIDGE_NETMASK_BITLENGTH_KEY);
65 std::string bridgeNetAddr = m_config->getStringValue(ConfigDefinition::SC_GROUP,
66 ConfigDefinition::SC_BRIDGE_NETADDR_KEY);
67 #endif // ENABLE_NETWORKGATEWAY 70 std::string serviceManifestDir =
71 m_config->getStringValue(ConfigDefinition::SC_GROUP,
72 ConfigDefinition::SC_SERVICE_MANIFEST_DIR_KEY);
73 std::string defaultServiceManifestDir =
74 m_config->getStringValue(ConfigDefinition::SC_GROUP,
75 ConfigDefinition::SC_DEFAULT_SERVICE_MANIFEST_DIR_KEY);
80 m_filteredConfigStore = std::make_shared<FilteredConfigStore>(std::move(loader));
81 m_defaultConfigStore = std::make_shared<DefaultConfigStore>(std::move(defaultLoader));
83 m_containerUtility->removeOldContainers();
84 m_containerUtility->checkWorkspace();
87 #ifdef ENABLE_NETWORKGATEWAY
101 SoftwareContainerAgent::~SoftwareContainerAgent()
105 void SoftwareContainerAgent::assertContainerExists(ContainerID containerID)
107 if (containerID >= INT32_MAX) {
108 std::string errorMessage(
"Invalid Container ID: " 109 + std::to_string(containerID)
110 +
". ID can not be greater than INT32");
111 log_error() << errorMessage;
115 if (containerID < 0) {
116 std::string errorMessage(
"Invalid Container ID: " 117 + std::to_string(containerID)
118 +
". ID can not be negative");
119 log_error() << errorMessage;
122 if (1 > m_containers.count(containerID)) {
123 std::string errorMessage(
"Invalid Container ID: " 124 + std::to_string(containerID)
125 +
". No container matching that ID exists.");
126 log_error() << errorMessage;
133 std::vector<ContainerID> containerIDs;
134 for (
auto &cont : m_containers) {
135 containerIDs.push_back(cont.first);
143 assertContainerExists(containerID);
145 m_containers.erase(containerID);
146 m_containerIdPool.push_back(containerID);
151 assertContainerExists(containerID);
152 return m_containers[containerID];
156 ContainerID SoftwareContainerAgent::findSuitableId()
158 ContainerID availableID = m_containerIdPool.back();
159 if (m_containerIdPool.size() > 1) {
160 m_containerIdPool.pop_back();
162 m_containerIdPool[0]++;
170 profilepoint(
"createContainerStart");
171 profilefunction(
"createContainerFunction");
174 std::unique_ptr<DynamicContainerOptions> options = m_optionParser.
parse(config);
175 std::unique_ptr<SoftwareContainerConfig> containerConfig = options->toConfig(m_containerConfig);
178 ContainerID containerID = findSuitableId();
179 auto container = m_factory->createContainer(containerID, std::move(containerConfig));
180 log_debug() <<
"Created container with ID :" << containerID;
182 m_containers[containerID] = container;
187 const std::string &cmdLine,
188 const std::string &workingDirectory,
189 const std::string &outputFile,
190 const EnvironmentVariables &env,
191 std::function<
void (pid_t,
int)> listener)
193 profilefunction(
"executeFunction");
194 SoftwareContainerPtr container =
getContainer(containerID);
203 if (!m_containers[containerID]->previouslyConfigured()) {
204 log_info() <<
"Container not configured yet, configuring with default capabilities, if any";
206 if (!updateGatewayConfigs(containerID, gatewayConfigs)) {
207 std::string errorMessage(
"Could not set default capabilities on container " + std::to_string(containerID));
208 log_error() << errorMessage;
215 auto job = container->createCommandJob(cmdLine);
216 if (
nullptr == job) {
217 std::string errorMessage(
"Could not create job instance for " + cmdLine);
218 log_error() << errorMessage;
222 job->setOutputFile(outputFile);
223 job->setEnvironmentVariables(env);
224 job->setWorkingDirectory(workingDirectory);
228 std::string errorMessage(
"Could not start job");
229 log_error() << errorMessage;
235 listener(pid, exitCode);
236 }, m_mainLoopContext);
238 profilepoint(
"executeEnd");
245 profilefunction(
"shutdownContainerFunction");
247 SoftwareContainerPtr container =
getContainer(containerID);
249 int timeout = m_containerConfig.containerShutdownTimeout();
250 container->shutdown(timeout);
255 std::string errorMessage(
"Could not delete the container" + std::string(err.what()));
256 log_error() << errorMessage;
263 SoftwareContainerPtr container =
getContainer(containerID);
264 container->suspend();
269 SoftwareContainerPtr container =
getContainer(containerID);
274 const std::string &pathInHost,
275 const std::string &pathInContainer,
278 profilefunction(
"bindMountFunction");
279 SoftwareContainerPtr container =
getContainer(containerID);
281 bool result = container->bindMount(pathInHost,
285 std::string errorMessage(
"Unable to bind mount " + pathInHost +
" to " + pathInContainer);
286 log_error() << errorMessage;
291 bool SoftwareContainerAgent::updateGatewayConfigs(
const ContainerID &containerID,
294 profilefunction(
"updateGatewayConfigs");
295 SoftwareContainerPtr container =
getContainer(containerID);
297 return container->startGateways(configs);
302 return m_filteredConfigStore->IDs();
306 const std::vector<std::string> &capabilities)
308 if (capabilities.empty()) {
309 log_warning() <<
"Got empty list of capabilities";
314 std::string caps =
"";
315 for (
const std::string &capName : capabilities) {
316 caps +=
" " + capName;
318 log_debug() <<
"Will attempt to set capabilities:" + caps;
324 if (filteredConfigs.empty()) {
325 std::string errorMessage(
"One or more capabilities were not found");
326 log_error() << errorMessage;
330 gatewayConfigs.append(filteredConfigs);
333 if (!updateGatewayConfigs(containerID, gatewayConfigs)) {
334 std::string errorMessage(
"Could not set gateway configuration for capability");
335 log_error() << errorMessage;
Contains the softwarecontainer::SoftwareContainerAgent class.
void addProcessListener(SignalConnectionsHandler &connections, pid_t pid, std::function< void(pid_t, int)> function, Glib::RefPtr< Glib::MainContext > context)
addProcessListener Adds a glib child watch for a process.
void setCapabilities(const ContainerID &containerID, const std::vector< std::string > &capabilities)
Set capabilities for the container.
std::vector< ContainerID > listContainers()
get a list of all containers
std::vector< std::string > listCapabilities()
List all capabilities that the user can set.
Contains all values that should be passed to SoftwareContainer on creation.
std::unique_ptr< DynamicContainerOptions > parse(const std::string &config)
Parse config needed for starting up the container in a correct manner.
ContainerID createContainer(const std::string &config)
Create a new container.
void suspendContainer(ContainerID containerID)
suspends execution of a container
pid_t execute(ContainerID containerID, const std::string &cmdLine, const std::string &workingDirectory, const std::string &outputFile, const EnvironmentVariables &env, std::function< void(pid_t, int)> listener)
Launch the given command in a the given container.
void resumeContainer(ContainerID containerID)
resumes execution of a container
void bindMount(const ContainerID containerID, const std::string &pathInHost, const std::string &pathInContainer, bool readOnly)
Bind mount a folder into the container.
SoftwareContainerPtr getContainer(ContainerID containerID)
Fetches a pointer to a SoftwareContainer matching an ID.
void shutdownContainer(ContainerID containerID)
shuts down a container
SoftwareContainerAgent(Glib::RefPtr< Glib::MainContext > mainLoopContext, std::shared_ptr< Config > config, std::shared_ptr< SoftwareContainerFactory > factory, std::shared_ptr< ContainerUtilityInterface > utility)
creates a new agent object and runs some initialization
Developers guide to adding a config item:
void deleteContainer(ContainerID containerID)
delete container by ID
An error occured in SoftwareContainerAgent.