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

Ubuntu snap: Use SNAP_DATA env var. Add documentation. #160

Merged
merged 4 commits into from
Mar 9, 2023
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
12 changes: 10 additions & 2 deletions client-lite/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,16 @@ file (GLOB files_docs_common
src/util/*.cpp
)

# Enable easy debugging in devdebug mode by not requiring running as root
if (DO_DEV_DEBUG)
if (DO_BUILD_FOR_SNAP)
# Use relative paths here. Agent will prefix them with $SNAP_DATA environment variable at runtime.
# This should match the slots declared in snapcraft-agent.yaml.
# These cmake vars are used in Debian maintainer scripts like postrm/postinst but snap does not use those scripts.
message("Agent: Build to create an Ubuntu Snap package")
set(docs_svc_config_dir_path "etc")
set(docs_svc_log_dir_path "log")
set(docs_svc_run_dir_path "run")
elseif (DO_DEV_DEBUG)
# Enable easy debugging in devdebug mode by not requiring running as root
message("Agent: Dev debug mode")
set(docs_svc_config_dir_path "/tmp/etc/${DOSVC_BIN_NAME}")
set(docs_svc_log_dir_path "/tmp/log/${DOSVC_BIN_NAME}")
Expand Down
6 changes: 4 additions & 2 deletions client-lite/src/exe/docs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,17 @@ HRESULT Run() try

RestPortAdvertiser portAdvertiser(controller.Port());
DoLogInfo("Port number written to %s", portAdvertiser.OutFilePath().data());

#ifndef DO_BUILD_FOR_SNAP
DropPermissions();
#endif


DOLog::Init(docli::GetLogDirectory(), DOLog::Level::Verbose);

DoLogInfo("Started, %s", msdoutil::ComponentVersion().c_str());
DoLogInfo("**Paths**\nLog: %s\nRun: %s\nConfig: %s\nSdkConfig: %s\nAdminConfig: %s",
docli::GetLogDirectory().c_str(), docli::GetRuntimeDirectory().c_str(), docli::GetConfigDirectory().c_str(),
docli::GetSDKConfigFilePath().c_str(), docli::GetAdminConfigFilePath().c_str());

ProcessController procController([&downloadManager]()
{
Expand Down
34 changes: 29 additions & 5 deletions client-lite/src/util/do_persistence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,60 @@
#include "do_common.h"
#include "do_persistence.h"

#include <cstdlib> // std::getenv

namespace docli
{

static std::string ConstructPath(const char* suffix)
{
std::string outputPath;
#ifdef DO_BUILD_FOR_SNAP
const char* snapDataRoot = std::getenv("SNAP_DATA");
THROW_HR_IF(E_UNEXPECTED, (snapDataRoot == nullptr) || (*snapDataRoot == '\0'));
outputPath = snapDataRoot;
if (outputPath.back() != '/')
{
outputPath.push_back('/');
}
if (*suffix == '/')
{
++suffix;
}
outputPath += suffix;
#else
outputPath = suffix;
#endif
return outputPath;
}

const std::string& GetLogDirectory()
{
static std::string logDirectory(DO_AGENT_LOG_DIRECTORY_PATH);
static std::string logDirectory(ConstructPath(DO_AGENT_LOG_DIRECTORY_PATH));
return logDirectory;
}

const std::string& GetRuntimeDirectory()
{
static std::string runDirectory(DO_RUN_DIRECTORY_PATH);
static std::string runDirectory(ConstructPath(DO_RUN_DIRECTORY_PATH));
return runDirectory;
}

const std::string& GetConfigDirectory()
{
static std::string configDirectory(DO_CONFIG_DIRECTORY_PATH);
static std::string configDirectory(ConstructPath(DO_CONFIG_DIRECTORY_PATH));
return configDirectory;
}

const std::string& GetSDKConfigFilePath()
{
static std::string configFilePath(DO_CONFIG_DIRECTORY_PATH "/sdk-config.json");
static std::string configFilePath(ConstructPath(DO_CONFIG_DIRECTORY_PATH "/sdk-config.json"));
return configFilePath;
}

const std::string& GetAdminConfigFilePath()
{
static std::string configFilePath(DO_CONFIG_DIRECTORY_PATH "/admin-config.json");
static std::string configFilePath(ConstructPath(DO_CONFIG_DIRECTORY_PATH "/admin-config.json"));
return configFilePath;
}

Expand Down
8 changes: 4 additions & 4 deletions client-lite/src/util/proc_launch_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ inline void InitializePath(const std::string& path, mode_t mode = 0) try
boost::filesystem::path dirPath(path);
if (!boost::filesystem::exists(dirPath))
{
DoLogInfo("Creating directory at %s", path.c_str());
boost::filesystem::create_directory(dirPath);
DoLogInfo("Creating directories for %s", path.c_str());
boost::filesystem::create_directories(dirPath);

if (mode != 0)
{
Expand All @@ -80,8 +80,6 @@ inline void InitializeDOPaths()

inline void DropPermissions()
{
uid_t userid = GetUserIdByName("do");

// process is running as root, drop privileges
if (getuid() == 0)
{
Expand All @@ -94,6 +92,8 @@ inline void DropPermissions()
{
THROW_HR_MSG(E_FAIL, "setgid: Unable to drop group privileges: %u, errno: %d", groupid, errno);
}

uid_t userid = GetUserIdByName("do");
if (setuid(userid) != 0)
{
THROW_HR_MSG(E_FAIL, "setuid: Unable to drop user privileges: %u, errno: %d", userid, errno);
Expand Down
3 changes: 3 additions & 0 deletions sdk-cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ target_compile_definitions(${DO_SDK_LIB_NAME}
if (DO_DEV_DEBUG)
target_compile_definitions(${DO_SDK_LIB_NAME} PRIVATE DO_DEV_DEBUG)
endif ()
if (DO_BUILD_FOR_SNAP)
target_compile_definitions(${DO_SDK_LIB_NAME} PRIVATE DO_BUILD_FOR_SNAP)
endif ()
if (DO_PLATFORM_LINUX OR DO_PLATFORM_MAC)
# TODO(shishirb) Remove internal use of exceptions on these platforms
target_compile_definitions(${DO_SDK_LIB_NAME} PRIVATE DO_ENABLE_EXCEPTIONS)
Expand Down
38 changes: 34 additions & 4 deletions sdk-cpp/src/internal/rest/util/do_persistence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,45 @@
// Licensed under the MIT License.

#include <string>

#include "do_persistence.h"

#include "do_errors.h"
#include "do_error_helpers.h"

namespace microsoft
{
namespace deliveryoptimization
{
namespace details
{

#ifdef DO_BUILD_FOR_SNAP
static std::string ConstructPath(const char* suffix)
{
const char* snapDataRoot = std::getenv("SNAP_DATA");
if ((snapDataRoot == nullptr) || (*snapDataRoot == '\0'))
{
ThrowException(microsoft::deliveryoptimization::errc::unexpected);
}
std::string outputPath = snapDataRoot;
if (outputPath.back() != '/')
{
outputPath.push_back('/');
}
if (*suffix == '/')
{
++suffix;
}
outputPath += suffix;
return outputPath;
}
#endif

const std::string& GetRuntimeDirectory()
{
#ifdef DO_DEV_DEBUG
#ifdef DO_BUILD_FOR_SNAP
static std::string runDirectory(ConstructPath("do-port-numbers"));
#elif defined(DO_DEV_DEBUG)
static std::string runDirectory("/tmp/run/deliveryoptimization-agent");
#else
static std::string runDirectory("/var/run/deliveryoptimization-agent");
Expand All @@ -24,7 +50,9 @@ const std::string& GetRuntimeDirectory()

const std::string& GetConfigFilePath()
{
#ifdef DO_DEV_DEBUG
#ifdef DO_BUILD_FOR_SNAP
static std::string configFilePath(ConstructPath("do-configs/sdk-config.json"));
#elif defined(DO_DEV_DEBUG)
static std::string configFilePath("/tmp/etc/deliveryoptimization-agent/sdk-config.json");
#else
static std::string configFilePath("/etc/deliveryoptimization-agent/sdk-config.json");
Expand All @@ -35,7 +63,9 @@ const std::string& GetConfigFilePath()
// TODO(shishirb): this is used only in test
const std::string& GetAdminConfigFilePath()
{
#ifdef DO_DEV_DEBUG
#ifdef DO_BUILD_FOR_SNAP
static std::string configFilePath(ConstructPath("do-configs/admin-config.json"));
#elif defined(DO_DEV_DEBUG)
static std::string configFilePath("/tmp/etc/deliveryoptimization-agent/admin-config.json");
#else
static std::string configFilePath("/etc/deliveryoptimization-agent/admin-config.json");
Expand Down
16 changes: 8 additions & 8 deletions sdk-cpp/tests/download_tests_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,14 +588,15 @@ TEST_F(DownloadTests, FileDeletionAfterPause)
#endif
}

#if defined(DO_INTERFACE_REST)
// SNAP: tests only have read permissions into the 'port numbers' directory
#if defined(DO_INTERFACE_REST) and !defined(DO_BUILD_FOR_SNAP)

TEST_F(DownloadTests, SimpleBlockingDownloadTest_ClientNotRunning)
{
TestHelpers::StopService("deliveryoptimization-agent.service");
TestHelpers::StopService(g_docsSvcName.c_str());
auto startService = dotest::util::scope_exit([]()
{
TestHelpers::StartService("deliveryoptimization-agent.service");
TestHelpers::StartService(g_docsSvcName.c_str());
});
TestHelpers::DeleteRestPortFiles(); // can be removed if docs deletes file on shutdown

Expand All @@ -614,11 +615,10 @@ TEST_F(DownloadTests, SimpleBlockingDownloadTest_ClientNotRunning)

TEST_F(DownloadTests, SimpleBlockingDownloadTest_ClientNotRunningPortFilePresent)
{
// TODO(shishirb) Service name should come from cmake
TestHelpers::StopService("deliveryoptimization-agent.service");
TestHelpers::StopService(g_docsSvcName.c_str());
auto startService = dotest::util::scope_exit([]()
{
TestHelpers::StartService("deliveryoptimization-agent.service");
TestHelpers::StartService(g_docsSvcName.c_str());
});
TestHelpers::DeleteRestPortFiles();
TestHelpers::CreateRestPortFiles(1);
Expand All @@ -638,10 +638,10 @@ TEST_F(DownloadTests, SimpleBlockingDownloadTest_ClientNotRunningPortFilePresent

TEST_F(DownloadTests, MultipleRestPortFileExists_Download)
{
TestHelpers::StopService("deliveryoptimization-agent.service");
TestHelpers::StopService(g_docsSvcName.c_str());
auto startService = dotest::util::scope_exit([]()
{
TestHelpers::StartService("deliveryoptimization-agent.service");
TestHelpers::StartService(g_docsSvcName.c_str());
});
TestHelpers::CreateRestPortFiles(5);
ASSERT_GE(TestHelpers::CountRestPortFiles(), 5u);
Expand Down
5 changes: 5 additions & 0 deletions sdk-cpp/tests/rest/port_discovery_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,13 @@ void PortDiscoveryTests::TearDown()
TestHelpers::StartService(g_docsSvcName);
}

// SNAP: tests only have read permissions into the 'port numbers' directory
#ifndef DO_BUILD_FOR_SNAP

TEST_F(PortDiscoveryTests, DiscoverPortTest)
{
std::string foundPort = msdod::CPortFinder::GetDOPort(false);
ASSERT_EQ(foundPort, samplePortNumber);
}

#endif
9 changes: 6 additions & 3 deletions sdk-cpp/tests/rest/test_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,24 @@ int TestHelpers::ShutdownProcess(std::string procName)

void TestHelpers::RestartService(const std::string& name)
{
#ifndef DO_BUILD_FOR_SNAP
// 'snap' does not support reset-failed
const auto resetCmd = dtu::FormatString("systemctl reset-failed %s", name.c_str());
dtu::ExecuteSystemCommand(resetCmd.data()); // avoids hitting start-limit-hit error in systemd
#endif

const auto restartCmd = dtu::FormatString("systemctl restart %s", name.c_str());
const auto restartCmd = dtu::FormatString(DO_SERVICE_CONTROLLER " restart %s", name.c_str());
dtu::ExecuteSystemCommand(restartCmd.data());
}

void TestHelpers::StartService(const std::string& name)
{
dtu::ExecuteSystemCommand(dtu::FormatString("systemctl start %s", name.c_str()).data());
dtu::ExecuteSystemCommand(dtu::FormatString(DO_SERVICE_CONTROLLER " start %s", name.c_str()).data());
}

void TestHelpers::StopService(const std::string& name)
{
dtu::ExecuteSystemCommand(dtu::FormatString("systemctl stop %s", name.c_str()).data());
dtu::ExecuteSystemCommand(dtu::FormatString(DO_SERVICE_CONTROLLER " stop %s", name.c_str()).data());
}

int TestHelpers::_KillProcess(int pid, int signal)
Expand Down
12 changes: 9 additions & 3 deletions sdk-cpp/tests/test_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ const uint64_t g_largeFileSizeBytes = 536870440u;
const uint64_t g_prodFileSizeBytes = 25006511u;

#ifdef DO_BUILD_FOR_SNAP
std::string downloadPath = "/var/lib/deliveryoptimization-snap-downloads-root";
// For testing production scenario, use the same path DU agent will use
static const std::string downloadPath = "/var/lib/deviceupdate-agent-downloads";
#else
std::string downloadPath = (boost::filesystem::temp_directory_path()).string();
static const std::string downloadPath = boost::filesystem::temp_directory_path().string();
#endif

const std::string g_largeFileUrl = "http://main.oremdl.microsoft.com.nsatc.net/dotc/ReplacementDCATFile.txt";
Expand All @@ -35,9 +36,14 @@ const std::chrono::seconds g_smallFileWaitTime = 10s;
const std::chrono::seconds g_largeFileWaitTime = 5min;

#if defined(DO_INTERFACE_REST)
const std::string g_docsProcName = "deliveryoptimization-agent";

#ifdef DO_BUILD_FOR_SNAP
const std::string g_docsSvcName = "deliveryoptimization-client.agent";
#else
const std::string g_docsSvcName = "deliveryoptimization-agent.service";
#endif

#endif

// This MCC instance only works within our test lab azure VMs. Can be overriden via cmdline.
std::string g_mccHostName = "10.1.0.70";
9 changes: 8 additions & 1 deletion sdk-cpp/tests/test_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@
#include <chrono>
#include <string>

#ifdef DO_BUILD_FOR_SNAP
// Using systemctl within snap package results in "Running in chroot, ignoring request".
// Use the snap command instead.
#define DO_SERVICE_CONTROLLER "snap"
#else
#define DO_SERVICE_CONTROLLER "systemctl"
#endif

extern const uint64_t g_smallFileSizeBytes;
extern const uint64_t g_largeFileSizeBytes;
extern const uint64_t g_prodFileSizeBytes;

#if defined(DO_INTERFACE_REST)
extern const std::string g_docsProcName;
extern const std::string g_docsSvcName;
#elif defined(DO_INTERFACE_COM)
extern const std::string g_smallFilePhfInfoJson;
Expand Down
15 changes: 15 additions & 0 deletions snapcraft-options/connect-snaps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#! /bin/bash

# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# $ snap connect <snap>:<plug> <snap>:<slot>

set -e

# Plug agent snap into sdk-tests snap downloads slot
sudo snap connect deliveryoptimization-client:deviceupdate-agent-downloads deliveryoptimization-sdk-tests:downloads-folder

# Plug sdk-tests snap into agent's run and config slots
sudo snap connect deliveryoptimization-sdk-tests:do-port-numbers deliveryoptimization-client:do-port-numbers
sudo snap connect deliveryoptimization-sdk-tests:do-configs deliveryoptimization-client:do-configs
Loading