Add APIs for formatting systemd slice/scope names

There are some interesting escaping rules to consider when dealing
with systemd slice/scope names. Thus it is helpful to have APIs
for formatting names

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2013-07-26 15:18:55 +01:00
parent 2d95e8b100
commit 4574b475df
4 changed files with 145 additions and 2 deletions

View File

@ -1936,6 +1936,8 @@ virSysinfoSetup;
# util/virsystemd.h
virSystemdCreateMachine;
virSystemdMakeScopeName;
virSystemdMakeSliceName;
# util/virthread.h

View File

@ -27,9 +27,96 @@
#include "viralloc.h"
#include "virutil.h"
#include "virlog.h"
#include "virerror.h"
#define VIR_FROM_THIS VIR_FROM_SYSTEMD
static void virSystemdEscapeName(virBufferPtr buf,
const char *name)
{
static const char hextable[16] = "0123456789abcdef";
#define ESCAPE(c) \
do { \
virBufferAddChar(buf, '\\'); \
virBufferAddChar(buf, 'x'); \
virBufferAddChar(buf, hextable[(c >> 4) & 15]); \
virBufferAddChar(buf, hextable[c & 15]); \
} while (0)
#define VALID_CHARS \
"0123456789" \
"abcdefghijklmnopqrstuvwxyz" \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
":-_.\\"
if (*name == '.') {
ESCAPE(*name);
name++;
}
while (*name) {
if (*name == '/')
virBufferAddChar(buf, '-');
else if (*name == '-' ||
*name == '\\' ||
!strchr(VALID_CHARS, *name))
ESCAPE(*name);
else
virBufferAddChar(buf, *name);
name++;
}
#undef ESCAPE
#undef VALID_CHARS
}
char *virSystemdMakeScopeName(const char *name,
const char *drivername,
const char *partition)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
if (*partition == '/')
partition++;
virSystemdEscapeName(&buf, partition);
virBufferAddChar(&buf, '-');
virSystemdEscapeName(&buf, drivername);
virBufferAddLit(&buf, "\\x2d");
virSystemdEscapeName(&buf, name);
virBufferAddLit(&buf, ".scope");
if (virBufferError(&buf)) {
virReportOOMError();
return NULL;
}
return virBufferContentAndReset(&buf);
}
char *virSystemdMakeSliceName(const char *partition)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
if (*partition == '/')
partition++;
virSystemdEscapeName(&buf, partition);
virBufferAddLit(&buf, ".slice");
if (virBufferError(&buf)) {
virReportOOMError();
return NULL;
}
return virBufferContentAndReset(&buf);
}
/**
* virSystemdCreateMachine:
* @name: driver unique name of the machine
@ -75,8 +162,8 @@ int virSystemdCreateMachine(const char *name,
goto cleanup;
if (partition) {
if (virAsprintf(&slicename, "%s.slice", partition) < 0)
goto cleanup;
if (!(slicename = virSystemdMakeSliceName(partition)))
goto cleanup;
} else {
if (VIR_STRDUP(slicename, "") < 0)
goto cleanup;

View File

@ -24,6 +24,11 @@
# include "internal.h"
char *virSystemdMakeScopeName(const char *name,
const char *drivername,
const char *slicename);
char *virSystemdMakeSliceName(const char *partition);
int virSystemdCreateMachine(const char *name,
const char *drivername,
bool privileged,

View File

@ -138,6 +138,38 @@ static int testCreateBadSystemd(const void *opaque ATTRIBUTE_UNUSED)
return 0;
}
struct testScopeData {
const char *name;
const char *partition;
const char *expected;
};
static int
testScopeName(const void *opaque)
{
const struct testScopeData *data = opaque;
int ret = -1;
char *actual = NULL;
if (!(actual = virSystemdMakeScopeName(data->name,
"lxc",
data->partition)))
goto cleanup;
if (STRNEQ(actual, data->expected)) {
fprintf(stderr, "Expected '%s' but got '%s'\n",
data->expected, actual);
goto cleanup;
}
ret = 0;
cleanup:
VIR_FREE(actual);
return ret;
}
static int
mymain(void)
{
@ -152,6 +184,23 @@ mymain(void)
if (virtTestRun("Test create bad systemd ", 1, testCreateBadSystemd, NULL) < 0)
ret = -1;
#define TEST_SCOPE(name, partition, unitname) \
do { \
struct testScopeData data = { \
name, partition, unitname \
}; \
if (virtTestRun("Test scopename", 1, testScopeName, &data) < 0) \
ret = -1; \
} while (0)
TEST_SCOPE("demo", "/machine", "machine-lxc\\x2ddemo.scope");
TEST_SCOPE("demo-name", "/machine", "machine-lxc\\x2ddemo\\x2dname.scope");
TEST_SCOPE("demo!name", "/machine", "machine-lxc\\x2ddemo\\x21name.scope");
TEST_SCOPE(".demo", "/machine", "machine-lxc\\x2d\\x2edemo.scope");
TEST_SCOPE("demo", "/machine/eng-dept", "machine-eng\\x2ddept-lxc\\x2ddemo.scope");
TEST_SCOPE("demo", "/machine/eng-dept/testing!stuff",
"machine-eng\\x2ddept-testing\\x21stuff-lxc\\x2ddemo.scope");
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
}