softwarecontainer  0.18.0-739e8d7 2017-05-04
softwarecontainer::DeviceNodeGateway Class Reference

This gateway is responsible for exposing device nodes in an LXC container. More...

#include <devicenodegateway.h>

Inheritance diagram for softwarecontainer::DeviceNodeGateway:
[legend]
Collaboration diagram for softwarecontainer::DeviceNodeGateway:
[legend]

Public Types

enum  GatewayState : unsigned int { CREATED, CONFIGURED, ACTIVATED }
 

Public Member Functions

 DeviceNodeGateway (std::shared_ptr< ContainerAbstractInterface > container)
 
virtual bool readConfigElement (const json_t *element) override
 Gateway specific parsing of config elements. More...
 
virtual bool activateGateway () override
 Implements Gateway::activateGateway. More...
 
virtual bool teardownGateway () override
 Implements Gateway::teardownGateway. More...
 
virtual std::string id () const
 Returns the ID of the gateway. More...
 
virtual bool setConfig (const json_t *config)
 Configure this gateway according to the supplied JSON configuration string. More...
 
virtual bool activate ()
 Applies any configuration set by setConfig() More...
 
virtual bool teardown ()
 Restore system to the state prior to launching of gateway. More...
 
virtual bool isConfigured ()
 Is the gateway configured or not? More...
 
virtual bool isActivated ()
 Is the gateway activated or not? More...
 
bool bindMount (const std::string &src, const std::string &dst, const std::string &tmpContainerRoot, bool readOnly, bool writeBufferEnabled=false)
 bindMount Bind mount a src directory to another position dst. More...
 
bool tmpfsMount (const std::string dst, const int maxSize)
 tmpfsMount Mount a tmpfs in the dst path and limit size of the tmpfs to maxSize More...
 

Static Public Attributes

static constexpr const char * ID
 

Protected Member Functions

std::shared_ptr< ContainerAbstractInterfacegetContainer ()
 Get a handle to the associated container. More...
 
bool setEnvironmentVariable (const std::string &variable, const std::string &value)
 Set an environment variable in the associated container. More...
 
bool writeToFile (const std::string &path, const std::string &content)
 
void markFileForDeletion (const std::string &path)
 
bool overlayMount (const std::string &lower, const std::string &upper, const std::string &work, const std::string &dst)
 overlayMount Mount a directory with an overlay on top of it. More...
 
bool syncOverlayMount (const std::string &lower, const std::string &upper)
 syncOverlayMount Copy the directory structure from upper layer to the lower layer More...
 
bool createSharedMountPoint (const std::string &path)
 createSharedMountPoint Make the mount point shared, ie new mount points created in one bind mount will also be created in the other mount point. More...
 
bool pathInList (const std::string path)
 checks whether given path is already added to clean up handlers or not More...
 

Protected Attributes

bool m_activatedOnce
 
std::vector< std::unique_ptr< CleanUpHandler > > m_cleanupHandlers
 m_cleanupHandlers A vector of cleanupHandlers added during the lifetime of the FileToolKitWithUndo that will be run from the destructor. More...
 
std::vector< std::unique_ptr< CreateDir > > m_createDirList
 m_createDirList A vector of CreateDir classes. More...
 

Detailed Description

This gateway is responsible for exposing device nodes in an LXC container.

The basic operation looks as follows:

  • DeviceNodeGateway (DNG) is loaded with a JSON configuration detailing a list of devices to create, with device names (mandatory) and permission modes (optional)

Notes:

  • activate() will stop creating devices in the container upon first failure

Definition at line 41 of file devicenodegateway.h.

Member Function Documentation

bool softwarecontainer::DeviceNodeGateway::readConfigElement ( const json_t *  element)
overridevirtual

Gateway specific parsing of config elements.

All gateways implement this method in order to provide gateway specific parsing of the configuration content.

Parameters
elementA JSON configuration item.
Returns
false if an error was encountered while parsing, true otherwise.

Implements softwarecontainer::Gateway.

Definition at line 32 of file devicenodegateway.cpp.

References softwarecontainer::Device::parse().

33 {
34  Device dev;
35 
36  if (!dev.parse(element)) {
37  log_error() << "Could not parse device node configuration";
38  return false;
39  }
40 
41  return m_logic.updateDeviceList(dev);
42 }

Here is the call graph for this function:

bool softwarecontainer::DeviceNodeGateway::activateGateway ( )
overridevirtual

Implements Gateway::activateGateway.

This function will iterate over all devices and issue mknod and chmod commands, which are run in the container.

Returns
true upon success; all commands executed successfully
false otherwise

Implements softwarecontainer::Gateway.

Definition at line 44 of file devicenodegateway.cpp.

45 {
46  auto devlist = m_logic.getDevList();
47  if (devlist.empty()) {
48  log_info() << "Activate was called when no devices has been configured.";
49  return false;
50  }
51 
52  for (auto &dev : devlist) {
53  if (!dev->activate(getContainer())) {
54  return false;
55  }
56  }
57  return true;
58 }
std::shared_ptr< ContainerAbstractInterface > getContainer()
Get a handle to the associated container.
Definition: gateway.cpp:128
bool softwarecontainer::DeviceNodeGateway::teardownGateway ( )
overridevirtual

Implements Gateway::teardownGateway.

Implements softwarecontainer::Gateway.

Definition at line 60 of file devicenodegateway.cpp.

61 {
62  return true;
63 }
std::string softwarecontainer::Gateway::id ( ) const
virtualinherited

Returns the ID of the gateway.

Returns
Returns the ID of the gateway as a string

Definition at line 36 of file gateway.cpp.

Referenced by softwarecontainer::Gateway::activate(), softwarecontainer::DBusGatewayInstance::DBusGatewayInstance(), softwarecontainer::Gateway::setConfig(), and softwarecontainer::Gateway::teardown().

37 {
38  return m_id;
39 }

Here is the caller graph for this function:

bool softwarecontainer::Gateway::setConfig ( const json_t *  config)
virtualinherited

Configure this gateway according to the supplied JSON configuration string.

Parameters
configJSON string containing gateway-specific JSON configuration
Returns
true if config was successfully parsed, false otherwise
Exceptions
GatewayErrorIf called on an already activated gateway.

Reimplemented in softwarecontainer::DBusGateway.

Definition at line 41 of file gateway.cpp.

References softwarecontainer::Gateway::id(), and softwarecontainer::Gateway::readConfigElement().

42 {
43  if (GatewayState::ACTIVATED == m_state && !m_isDynamic) {
44  std::string message = "Can not configure a gateway that is already activated "
45  "if the gateway does not support dynamic behavior. "
46  "Gateway ID: " + id();
47  log_error() << message;
48  throw GatewayError(message);
49  }
50 
51  if (!json_is_array(config)) {
52  log_error() << "Root JSON element is not an array";
53  return false;
54  }
55 
56  if (json_array_size(config) == 0) {
57  log_error() << "Root JSON array is empty";
58  return false;
59  }
60 
61  for(size_t i = 0; i < json_array_size(config); i++) {
62  json_t *element = json_array_get(config, i);
63  if (!json_is_object(element)) {
64  log_error() << "json configuration is not an object";
65  return false;
66  }
67 
68  if (!readConfigElement(element)) {
69  log_warning() << "Could not read config element";
70  return false;
71  }
72  }
73 
74  m_state = GatewayState::CONFIGURED;
75  return true;
76 }
virtual std::string id() const
Returns the ID of the gateway.
Definition: gateway.cpp:36
virtual bool readConfigElement(const json_t *element)=0
Gateway specific parsing of config elements.

Here is the call graph for this function:

bool softwarecontainer::Gateway::activate ( )
virtualinherited

Applies any configuration set by setConfig()

Returns
true upon successful application of configuration, false otherwise
Exceptions
GatewayErrorIf called on an already activated gateway, or if the gateway has not been previously configured, or if there is not container instance set.

Reimplemented in softwarecontainer::DBusGateway.

Definition at line 78 of file gateway.cpp.

References softwarecontainer::Gateway::id().

78  {
79  if (GatewayState::ACTIVATED == m_state && !m_isDynamic) {
80  std::string message = "Can not activate a gateway that is already activated "
81  "if the gateway does not support dynamic behavior. "
82  "Gateway ID: " + id();
83  log_error() << message;
84  throw GatewayError(message);
85  }
86 
87  if (GatewayState::CONFIGURED != m_state) {
88  std::string message = "Activate was called on a gateway which is not in configured state. "
89  "Gateway ID: " + id();
90  log_error() << message;
91  throw GatewayError(message);
92  }
93 
94  if (!activateGateway()) {
95  log_error() << "Couldn't activate gateway: " << id();
96  return false;
97  }
98 
99  m_state = GatewayState::ACTIVATED;
100  return true;
101 }
virtual std::string id() const
Returns the ID of the gateway.
Definition: gateway.cpp:36

Here is the call graph for this function:

bool softwarecontainer::Gateway::teardown ( )
virtualinherited

Restore system to the state prior to launching of gateway.

Any cleanup code (removal of files, virtual interfaces, etc) should be placed here.

Returns
true upon successful clean-up, false otherwise
Exceptions
GatewayErrorIf called on a non activated gateway.

Reimplemented in softwarecontainer::DBusGateway.

Definition at line 103 of file gateway.cpp.

References softwarecontainer::Gateway::id().

Referenced by softwarecontainer::DBusGatewayInstance::DBusGatewayInstance().

103  {
104  /* At this point, a gateway should either be in state ACTIVATED if it is non-dynamic, or
105  if it is dynamic it should have been activated at least once before.
106  */
107  if (GatewayState::ACTIVATED != m_state && !m_activatedOnce) {
108  std::string message = "Teardown called on non-activated gateway. Gateway ID: " + id();
109  log_error() << message;
110  throw GatewayError(message);
111  }
112 
113  if (!teardownGateway()) {
114  log_error() << "Could not tear down gateway: " << id();
115  return false;
116  }
117 
118  // Return to a state of nothingness
119  m_state = GatewayState::CREATED;
120 
121  /* Since we have been torn down, we should not be considered to have been
122  activated any more. */
123  m_activatedOnce = false;
124 
125  return true;
126 }
virtual std::string id() const
Returns the ID of the gateway.
Definition: gateway.cpp:36

Here is the call graph for this function:

Here is the caller graph for this function:

bool softwarecontainer::Gateway::isConfigured ( )
virtualinherited

Is the gateway configured or not?

Reimplemented in softwarecontainer::DBusGateway.

Definition at line 134 of file gateway.cpp.

135 {
136  return m_state >= GatewayState::CONFIGURED;
137 }
bool softwarecontainer::Gateway::isActivated ( )
virtualinherited

Is the gateway activated or not?

Dynamic gateways will return true if they have been activated at least once. Non-dynamic gateways will return true if they are in state ACTIVATED

Reimplemented in softwarecontainer::DBusGateway.

Definition at line 139 of file gateway.cpp.

Referenced by softwarecontainer::DBusGatewayInstance::DBusGatewayInstance().

140 {
141  // For dynamic gateways it's only relevant to know if it has been activated
142  // at least once, the current state is not important
143  if (m_isDynamic) {
144  return m_activatedOnce;
145  }
146 
147  // For non-dynamic gateways, the current state is the only relevant info
148  return m_state >= GatewayState::ACTIVATED;
149 }

Here is the caller graph for this function:

std::shared_ptr< ContainerAbstractInterface > softwarecontainer::Gateway::getContainer ( )
protectedinherited

Get a handle to the associated container.

Exceptions
GatewayErrorIf called before setContainer() has been called.

Definition at line 128 of file gateway.cpp.

Referenced by softwarecontainer::NetworkGateway::activateGateway(), softwarecontainer::DBusGatewayInstance::activateGateway(), softwarecontainer::WaylandGateway::readConfigElement(), and softwarecontainer::NetworkGateway::teardownGateway().

129 {
130  std::shared_ptr<ContainerAbstractInterface> ptrCopy = m_container;
131  return ptrCopy;
132 }

Here is the caller graph for this function:

bool softwarecontainer::Gateway::setEnvironmentVariable ( const std::string &  variable,
const std::string &  value 
)
protectedinherited

Set an environment variable in the associated container.

bool softwarecontainer::FileToolkitWithUndo::bindMount ( const std::string &  src,
const std::string &  dst,
const std::string &  tmpContainerRoot,
bool  readOnly,
bool  writeBufferEnabled = false 
)
inherited

bindMount Bind mount a src directory to another position dst.

Parameters
srcPath to mount from
dstPath to mount to
readOnlyMake the bind mount destination read only
writeBufferEnabledEnable write buffers on the bind mount.
Returns
true on success, false on failure

Definition at line 53 of file filetoolkitwithundo.cpp.

References softwarecontainer::existsInFileSystem(), softwarecontainer::isDirectory(), and softwarecontainer::FileToolkitWithUndo::m_createDirList.

Referenced by softwarecontainer::Container::bindMountInContainer().

58 {
59  unsigned long flags = 0;
60  std::string fstype;
61  int mountRes;
62  std::unique_ptr<CreateDir> createDirInstance = std::unique_ptr<CreateDir>(new CreateDir());
63 
64  if (!existsInFileSystem(src)) {
65  log_error() << src << " does not exist on the host, can not bindMount";
66  return false;
67  }
68 
69  if (!existsInFileSystem(dst)) {
70  log_error() << dst << " does not exist on the host, can not bindMount";
71  return false;
72  }
73 
74  log_debug() << "Bind-mounting " << src << " in " << dst << ", flags: " << flags;
75 
76  if(writeBufferEnabled && isDirectory(src)) {
77  std::string upperDir , workDir;
78 
79  // In case the tmpContainerRoot is set to nothing we need to create a
80  // good bindmount directory.
81  if (tmpContainerRoot == "") {
82  upperDir = createDirInstance->createTempDirectoryFromTemplate("/tmp/sc-bindmount-upper-XXXXXX");
83  workDir = createDirInstance->createTempDirectoryFromTemplate("/tmp/sc-bindmount-work-XXXXXX");
84  } else {
85  upperDir = createDirInstance->createTempDirectoryFromTemplate(tmpContainerRoot + "/bindmount-upper-XXXXXX");
86  workDir = createDirInstance->createTempDirectoryFromTemplate(tmpContainerRoot + "/bindmount-work-XXXXXX");
87  }
88  fstype.assign("overlay");
89 
90  std::ostringstream os;
91  os << "lowerdir=" << src << ",upperdir=" << upperDir << ",workdir=" << workDir;
92 
93  log_debug() << "writeBufferEnabled, config: " << os.str();
94 
95  mountRes = mount("overlay", dst.c_str(), fstype.c_str(), flags, os.str().c_str());
96  log_debug() << "mountRes: " << mountRes;
97  } else {
98  const void *data = nullptr;
99  flags = MS_BIND;
100  mountRes = mount(src.c_str(), dst.c_str(), fstype.c_str(), flags, data);
101  }
102 
103  if (mountRes == 0) {
104  log_verbose() << "Bind-mounted folder " << src << " in " << dst;
105  } else {
106  log_error() << "Could not mount into container: src=" << src
107  << " , dst=" << dst << " err=" << strerror(errno);
108  return false;
109  }
110 
111  if (readOnly && !writeBufferEnabled) {
112  const void *data = nullptr;
113 
114  flags = MS_REMOUNT | MS_RDONLY | MS_BIND;
115 
116  log_debug() << "Re-mounting read-only" << src << " in "
117  << dst << ", flags: " << flags;
118  mountRes = mount(src.c_str(), dst.c_str(), fstype.c_str(), flags, data);
119  if (mountRes != 0) {
120  // Failure
121  log_error() << "Could not re-mount " << src << " , read-only on "
122  << dst << " err=" << strerror(errno);
123  return false;
124  }
125  }
126  m_createDirList.push_back(std::move(createDirInstance));
127  return true;
128 }
std::vector< std::unique_ptr< CreateDir > > m_createDirList
m_createDirList A vector of CreateDir classes.
bool isDirectory(const std::string &path)
isDirectory Check if path is a directory
bool existsInFileSystem(const std::string &path)
existsInFileSystem Check if path exists

Here is the call graph for this function:

Here is the caller graph for this function:

bool softwarecontainer::FileToolkitWithUndo::tmpfsMount ( const std::string  dst,
const int  maxSize 
)
inherited

tmpfsMount Mount a tmpfs in the dst path and limit size of the tmpfs to maxSize

Parameters
dstThe destination to mount a tmpfs on
maxSizeThe max size of the tmpfs being mounted
Returns

Definition at line 177 of file filetoolkitwithundo.cpp.

References softwarecontainer::isDirectoryEmpty(), softwarecontainer::FileToolkitWithUndo::m_cleanupHandlers, and softwarecontainer::FileToolkitWithUndo::m_createDirList.

Referenced by softwarecontainer::SoftwareContainer::SoftwareContainer().

178 {
179  std::string fstype = "tmpfs";
180  unsigned long flags = 0;
181  std::unique_ptr<CreateDir> createDirInstance = std::unique_ptr<CreateDir>(new CreateDir());
182 
183  if (!createDirInstance->createDirectory(dst)) {
184  log_error() << "Failed to create " << dst << " directory for tmpfs mount";
185  return false;
186  }
187 
188  std::string mountoptions = logging::StringBuilder() << "size=" << maxSize;
189 
190  bool directoryIsEmpty = isDirectoryEmpty(dst);
191 
192  int mountRes = mount("tmpfs", dst.c_str(), fstype.c_str(), flags, mountoptions.c_str());
193 
194  if (0 == mountRes) {
195  log_verbose() << "tmpfs mounted in " << dst;
196  m_cleanupHandlers.emplace_back(new MountCleanUpHandler(dst));
197  } else {
198  log_error() << "Could not mount tmpfs into directory: " << dst << " size=" << maxSize;
199  return false;
200  }
201 
202  m_createDirList.push_back(std::move(createDirInstance));
203  return true;
204 }
std::vector< std::unique_ptr< CleanUpHandler > > m_cleanupHandlers
m_cleanupHandlers A vector of cleanupHandlers added during the lifetime of the FileToolKitWithUndo th...
bool isDirectoryEmpty(const std::string &path)
isDirectoryEmpty Check if path is empty
std::vector< std::unique_ptr< CreateDir > > m_createDirList
m_createDirList A vector of CreateDir classes.

Here is the call graph for this function:

Here is the caller graph for this function:

bool softwarecontainer::FileToolkitWithUndo::overlayMount ( const std::string &  lower,
const std::string &  upper,
const std::string &  work,
const std::string &  dst 
)
protectedinherited

overlayMount Mount a directory with an overlay on top of it.

An overlay protects the lower filesystem from writes by writing to the upper file system through the work directory.

Parameters
lowerThe lower file system, this will be read only.
upperThe upper file system, this can be a tmpfs/ramfs of some kind. This is where final writes wind up
workThis is a work directory, preferably a tmpfs/ramfs of some kind. This is where writes wind up temporarily.
dstWhere the overlay filesystem will be mounted.
Returns
true on success, false on failure

Definition at line 130 of file filetoolkitwithundo.cpp.

References softwarecontainer::FileToolkitWithUndo::m_cleanupHandlers, and softwarecontainer::FileToolkitWithUndo::m_createDirList.

Referenced by softwarecontainer::Container::create().

134 {
135  std::string fstype = "overlay";
136  unsigned long flags = 0;
137  std::unique_ptr<CreateDir> createDirInstance = std::unique_ptr<CreateDir>(new CreateDir());
138 
139  if (!createDirInstance->createDirectory(lower)
140  || !createDirInstance->createDirectory(upper)
141  || !createDirInstance->createDirectory(work)
142  || !createDirInstance->createDirectory(dst))
143  {
144  log_error() << "Failed to create lower/upper/work directory for overlayMount. lowerdir=" <<
145  lower << ", upperdir=" << upper << ", workdir=" << work;
146  return false;
147  }
148 
149  std::string mountoptions = logging::StringBuilder() << "lowerdir=" << lower
150  << ",upperdir=" << upper
151  << ",workdir=" << work;
152 
153  int mountRes = mount("overlay", dst.c_str(), fstype.c_str(), flags, mountoptions.c_str());
154 
155  if (mountRes == 0) {
156  log_verbose() << "overlayMounted folder " << lower << " in " << dst;
157  m_cleanupHandlers.emplace_back(new MountCleanUpHandler(dst));
158  m_cleanupHandlers.emplace_back(new OverlaySyncCleanupHandler(upper, lower));
159  } else {
160  log_error() << "Could not mount into container: upper=" << upper
161  << ",lower=" << lower
162  << ",work=" << work
163  << " at dst=" << dst << " err=" << strerror(errno);
164  return false;
165  }
166 
167  m_createDirList.push_back(std::move(createDirInstance));
168  return true;
169 }
std::vector< std::unique_ptr< CleanUpHandler > > m_cleanupHandlers
m_cleanupHandlers A vector of cleanupHandlers added during the lifetime of the FileToolKitWithUndo th...
std::vector< std::unique_ptr< CreateDir > > m_createDirList
m_createDirList A vector of CreateDir classes.

Here is the caller graph for this function:

bool softwarecontainer::FileToolkitWithUndo::syncOverlayMount ( const std::string &  lower,
const std::string &  upper 
)
protectedinherited

syncOverlayMount Copy the directory structure from upper layer to the lower layer

Parameters
lowerThe lower layer used in an overlay file system.
upperThe upper layer in an overlay file system.
Returns
true on success, false on failure

Definition at line 171 of file filetoolkitwithundo.cpp.

References softwarecontainer::RecursiveCopy::copy(), and softwarecontainer::RecursiveCopy::getInstance().

173 {
174  return RecursiveCopy::getInstance().copy(upper, lower);
175 }
static RecursiveCopy & getInstance()
getInstance Gets the RecursiveCopy instance.
bool copy(std::string src, std::string dst)
copy Copy files from src to dst

Here is the call graph for this function:

bool softwarecontainer::FileToolkitWithUndo::createSharedMountPoint ( const std::string &  path)
protectedinherited

createSharedMountPoint Make the mount point shared, ie new mount points created in one bind mount will also be created in the other mount point.

Parameters
pathThe mount path to make shared.
Returns
true on success, false on failure

Definition at line 206 of file filetoolkitwithundo.cpp.

References softwarecontainer::FileToolkitWithUndo::m_cleanupHandlers.

Referenced by softwarecontainer::Container::initialize().

207 {
208  auto mountRes = mount(path.c_str(), path.c_str(), "", MS_BIND, nullptr);
209  if (mountRes != 0) {
210  log_error() << "Could not bind mount " << path << " to itself";
211  return false;
212  }
213 
214  mountRes = mount(path.c_str(), path.c_str(), "", MS_UNBINDABLE, nullptr);
215  if (mountRes != 0) {
216  log_error() << "Could not make " << path << " unbindable";
217  return false;
218  }
219 
220  mountRes = mount(path.c_str(), path.c_str(), "", MS_SHARED, nullptr);
221  if (mountRes != 0) {
222  log_error() << "Could not make " << path << " shared";
223  return false;
224  }
225 
226  m_cleanupHandlers.emplace_back(new MountCleanUpHandler(path));
227  log_debug() << "Created shared mount point at " << path;
228 
229  return true;
230 }
std::vector< std::unique_ptr< CleanUpHandler > > m_cleanupHandlers
m_cleanupHandlers A vector of cleanupHandlers added during the lifetime of the FileToolKitWithUndo th...

Here is the caller graph for this function:

bool softwarecontainer::FileToolkitWithUndo::pathInList ( const std::string  path)
protectedinherited

checks whether given path is already added to clean up handlers or not

This function will be called only before adding new CleanUpHandler for FileCleanUpHandler and DirectoryCleanUpHandler. The reason behind this, only indicated CleanUpHandlers are related with file/directory removal operations.

Parameters
astring path name to check
Returns
true if the path is already exist, false otherwise

Definition at line 232 of file filetoolkitwithundo.cpp.

References softwarecontainer::FileToolkitWithUndo::m_cleanupHandlers.

Referenced by softwarecontainer::Container::bindMountInContainer().

233 {
234 
235  for (auto &element : m_cleanupHandlers) {
236  if (element->queryName() == path) {
237  return true;
238  }
239  }
240  return false;
241 }
std::vector< std::unique_ptr< CleanUpHandler > > m_cleanupHandlers
m_cleanupHandlers A vector of cleanupHandlers added during the lifetime of the FileToolKitWithUndo th...

Here is the caller graph for this function:

Field Documentation

std::vector<std::unique_ptr<CleanUpHandler> > softwarecontainer::FileToolkitWithUndo::m_cleanupHandlers
protectedinherited
std::vector<std::unique_ptr<CreateDir> > softwarecontainer::FileToolkitWithUndo::m_createDirList
protectedinherited

The documentation for this class was generated from the following files: