Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ProcessContainers] Update Dobby implementation #1771

Merged
merged 7 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,21 +1,8 @@
/*
* If not stated otherwise in this file or this component's LICENSE file the
* following copyright and licenses apply:
*
* Copyright 2020 Metrological
*
* 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.
*/

#include "processcontainers/Messaging.h"
#include "processcontainers/ContainerProducer.h"
#include "processcontainers/ContainerAdministrator.h"
#include "processcontainers/common/CGroupContainerInfo.h"

#include "DobbyImplementation.h"
#include <Dobby/DobbyProxy.h>
Expand All @@ -26,31 +13,22 @@
namespace Thunder {

namespace ProcessContainers {
// Container administrator
// ----------------------------------
IContainerAdministrator& ProcessContainers::IContainerAdministrator::Instance()
{
static DobbyContainerAdministrator& dobbyContainerAdministrator = Core::SingletonType<DobbyContainerAdministrator>::Instance();

return dobbyContainerAdministrator;
}

IContainer* DobbyContainerAdministrator::Container(const string& id, IStringIterator& searchpaths, const string& logpath, const string& configuration VARIABLE_IS_NOT_USED)
Core::ProxyType<IContainer> DobbyContainerAdministrator::Container(const string& id, IStringIterator& searchpaths,
const string& logpath, const string& configuration VARIABLE_IS_NOT_USED)
{
searchpaths.Reset(0);
while (searchpaths.Next()) {
auto path = searchpaths.Current();

auto createContainer = [&](bool useSpecFile, const string &path) -> IContainer* {
auto createContainer = [&](bool useSpecFile, const string &path) -> Core::ProxyType<IContainer> {
// Make sure no leftover will interfere...
if (ContainerNameTaken(id)) {
DestroyContainer(id);
}
this->InternalLock();
DobbyContainer* container = new DobbyContainer(id, path, logpath, useSpecFile);
InsertContainer(container);
this->InternalUnlock();

Core::ProxyType<IContainer> container;
container = ContainerAdministrator::Instance().Create<DobbyContainer>(*this, id, path, logpath, useSpecFile);
return container;
};

Expand All @@ -71,17 +49,16 @@ namespace ProcessContainers {

TRACE(Trace::Error, (_T("Could not find suitable container config for %s in any search path"), id.c_str()));

return nullptr;
return Core::ProxyType<IContainer>();
}

DobbyContainerAdministrator::DobbyContainerAdministrator()
: BaseContainerAdministrator()
uint32_t DobbyContainerAdministrator::Initialize(const string& config VARIABLE_IS_NOT_USED)
{
mIpcService = AI_IPC::createIpcService("unix:path=/var/run/dbus/system_bus_socket", "org.rdk.dobby.processcontainers");

if (!mIpcService) {
TRACE(Trace::Error, (_T("Failed to create Dobby IPC service")));
return;
return Core::ERROR_GENERAL;
} else {
// Start the IPCService which kicks off the event dispatcher thread
mIpcService->start();
Expand All @@ -90,15 +67,15 @@ namespace ProcessContainers {
// Create a DobbyProxy remote service that wraps up the dbus API
// calls to the Dobby daemon
mDobbyProxy = std::make_shared<DobbyProxy>(mIpcService, DOBBY_SERVICE, DOBBY_OBJECT);
}

DobbyContainerAdministrator::~DobbyContainerAdministrator()
{
return Core::ERROR_NONE;
}

void DobbyContainerAdministrator::Logging(const string& logPath VARIABLE_IS_NOT_USED, const string& loggingOptions VARIABLE_IS_NOT_USED)
void DobbyContainerAdministrator::Deinitialize()
{
// Only container-scope logging
mDobbyProxy.reset();
mIpcService->stop();
mIpcService.reset();
}

void DobbyContainerAdministrator::DestroyContainer(const string& name)
Expand All @@ -115,7 +92,6 @@ namespace ProcessContainers {

// Dobby stop is async - block until we get the notification the container
// has actually stopped
this->InternalLock();

_stopPromise = std::promise<void>();
const void* vp = static_cast<void*>(new std::string(name));
Expand All @@ -139,8 +115,6 @@ namespace ProcessContainers {
}
}

this->InternalUnlock();

// Always make sure we unregister our callback
mDobbyProxy->unregisterListener(listenerId);

Expand Down Expand Up @@ -186,8 +160,9 @@ namespace ProcessContainers {

// Container
// ------------------------------------
DobbyContainer::DobbyContainer(const string& name, const string& path, const string& logPath, bool useSpecFile)
DobbyContainer::DobbyContainer(DobbyContainerAdministrator& admin, const string& name, const string& path, const string& logPath, const bool useSpecFile)
: _adminLock()
, _admin(admin)
, _name(name)
, _path(path)
, _logPath(logPath)
Expand All @@ -199,13 +174,9 @@ namespace ProcessContainers {

DobbyContainer::~DobbyContainer()
{
auto& admin = static_cast<DobbyContainerAdministrator&>(DobbyContainerAdministrator::Instance());

if (admin.ContainerNameTaken(_name) == true) {
if (_admin.ContainerNameTaken(_name) == true) {
Stop(Core::infinite);
}

admin.RemoveContainer(this);
}

const string& DobbyContainer::Id() const
Expand All @@ -216,10 +187,9 @@ namespace ProcessContainers {
uint32_t DobbyContainer::Pid() const
{
uint32_t returnedPid = 0;
auto& admin = static_cast<DobbyContainerAdministrator&>(DobbyContainerAdministrator::Instance());

if (_pid.IsSet() == false) {
std::string containerInfoString = admin.mDobbyProxy->getContainerInfo(_descriptor);
std::string containerInfoString = _admin.mDobbyProxy->getContainerInfo(_descriptor);

if (containerInfoString.empty()) {
TRACE(Trace::Warning, (_T("Failed to get info for container %s"), _name.c_str()));
Expand Down Expand Up @@ -315,10 +285,9 @@ namespace ProcessContainers {
bool DobbyContainer::IsRunning() const
{
bool result = false;
auto& admin = static_cast<DobbyContainerAdministrator&>(DobbyContainerAdministrator::Instance());

// We got a state back successfully, work out what that means in English
switch (static_cast<IDobbyProxyEvents::ContainerState>(admin.mDobbyProxy->getContainerState(_descriptor))) {
switch (static_cast<IDobbyProxyEvents::ContainerState>(_admin.mDobbyProxy->getContainerState(_descriptor))) {
case IDobbyProxyEvents::ContainerState::Invalid:
result = false;
break;
Expand Down Expand Up @@ -350,8 +319,6 @@ namespace ProcessContainers {
bool result = false;

_adminLock.Lock();
auto& admin = static_cast<DobbyContainerAdministrator&>(DobbyContainerAdministrator::Instance());

std::list<int> emptyList;

// construct the full command to run with all the arguments
Expand All @@ -372,9 +339,9 @@ namespace ProcessContainers {
std::string containerSpecString = specFileStream.str();
TRACE(ProcessContainers::ProcessContainerization, (_T("container spec string: %s"), containerSpecString.c_str()));

_descriptor = admin.mDobbyProxy->startContainerFromSpec(_name, containerSpecString , emptyList, fullCommand);
_descriptor = _admin.mDobbyProxy->startContainerFromSpec(_name, containerSpecString , emptyList, fullCommand);
} else {
_descriptor = admin.mDobbyProxy->startContainerFromBundle(_name, _path, emptyList, fullCommand);
_descriptor = _admin.mDobbyProxy->startContainerFromBundle(_name, _path, emptyList, fullCommand);
}
// startContainer returns -1 on failure
if (_descriptor <= 0) {
Expand All @@ -395,9 +362,8 @@ namespace ProcessContainers {
bool result = false;

_adminLock.Lock();
auto& admin = static_cast<DobbyContainerAdministrator&>(DobbyContainerAdministrator::Instance());

bool stoppedSuccessfully = admin.mDobbyProxy->stopContainer(_descriptor, false);
bool stoppedSuccessfully = _admin.mDobbyProxy->stopContainer(_descriptor, false);

if (!stoppedSuccessfully) {
TRACE(Trace::Error, (_T("Failed to stop container, internal Dobby error. id: %s descriptor: %d"), _name.c_str(), _descriptor));
Expand All @@ -409,6 +375,9 @@ namespace ProcessContainers {
return result;
}

// FACTORY REGISTRATION
static ContainerProducerRegistrationType<DobbyContainerAdministrator, IContainer::containertype::DOBBY> registration;

} // namespace ProcessContainers

} // namespace Thunder
Original file line number Diff line number Diff line change
@@ -1,31 +1,9 @@
/*
* If not stated otherwise in this file or this component's LICENSE file the
* following copyright and licenses apply:
*
* Copyright 2020 Metrological
*
* 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.
*/

#pragma once

#include "processcontainers/ProcessContainer.h"
#include "processcontainers/common/BaseAdministrator.h"
#include "processcontainers/common/BaseRefCount.h"
#include "processcontainers/ContainerAdministrator.h"
#include "processcontainers/common/CGroupContainerInfo.h"

#include "Messaging.h"

#include <Dobby/DobbyProtocol.h>
#include <Dobby/Public/Dobby/IDobbyProxy.h>

Expand All @@ -37,30 +15,30 @@ namespace ProcessContainers {
const string CONFIG_NAME = "/config.json";
const string CONFIG_NAME_SPEC = "/spec.json";

class DobbyContainer : public BaseRefCount<IContainer> {
private:
friend class DobbyContainerAdministrator;

DobbyContainer(const string& name, const string& path, const string& logPath, bool useSpecFile = false);
class DobbyContainerAdministrator;

class DobbyContainer : public IContainer {
public:
DobbyContainer(DobbyContainerAdministrator& admin, const string& name, const string& path, const string& logPath, const bool useSpecFile = false);
DobbyContainer(const DobbyContainer&) = delete;
DobbyContainer& operator=(const DobbyContainer&) = delete;
~DobbyContainer() override;

public:
// IContainerMethods
containertype Type() const override { return IContainer::DOBBY; }
const string& Id() const override;
uint32_t Pid() const override;
bool IsRunning() const override;
bool Start(const string& command, IStringIterator& parameters) override;
bool Stop(const uint32_t timeout /*ms*/) override;

IMemoryInfo* Memory() const override;
IProcessorInfo* ProcessorInfo() const override;
INetworkInterfaceIterator* NetworkInterfaces() const override;

private:
mutable Core::CriticalSection _adminLock;
DobbyContainerAdministrator& _admin;
string _name;
string _path;
string _logPath;
Expand All @@ -69,29 +47,27 @@ namespace ProcessContainers {
bool _useSpecFile;
};

class DobbyContainerAdministrator : public BaseContainerAdministrator<DobbyContainer> {
private:
class DobbyContainerAdministrator : public IContainerProducer {
friend class DobbyContainer;
friend class Core::SingletonType<DobbyContainerAdministrator>;

DobbyContainerAdministrator();
public:
DobbyContainerAdministrator() = default;
~DobbyContainerAdministrator() override = default;
DobbyContainerAdministrator(const DobbyContainerAdministrator&) = delete;
DobbyContainerAdministrator& operator=(const DobbyContainerAdministrator&) = delete;

private:
std::shared_ptr<AI_IPC::IIpcService> mIpcService; // Ipc Service instance
std::shared_ptr<IDobbyProxy> mDobbyProxy; // DobbyProxy instance
public:
~DobbyContainerAdministrator() override;

IContainer* Container(const string& id,
IStringIterator& searchpaths,
const string& logpath,
const string& configuration) override; //searchpaths will be searched in order in which they are iterated

// IContainerAdministrator methods
void Logging(const string& logDir, const string& loggingOptions) override;
public:
// IContainerProducer methods
uint32_t Initialize(const string& config) override;
void Deinitialize() override;
Core::ProxyType<IContainer> Container(const string& id, IStringIterator& searchpaths,
const string& logpath, const string& configuration) override;

protected:
private:
void DestroyContainer(const string& name); // make sure that no leftovers from previous launch will cause crash
bool ContainerNameTaken(const string& name);
void containerStopCallback(int32_t cd, const std::string& containerId,
Expand Down
Loading