mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-07-06 09:55:46 +00:00
implement usb and pci hot attach in AppArmor driver
Description: Implement AppArmorSetSecurityHostdevLabel() and AppArmorRestoreSecurityHostdevLabel() for hostdev and pcidev attach. virt-aa-helper also has to be adjusted because *FileIterate() is used for pci and usb devices and the corresponding XML for hot attached hostdev and pcidev is not in the XML passed to virt-aa-helper. The new '-F filename' option is added to append a rule to the profile as opposed to the existing '-f filename', which rewrites the libvirt-<uuid>.files file anew. This new '-F' option will append a rule to an existing libvirt-<uuid>.files if it exists, otherwise it acts the same as '-f'. load_profile() and reload_profile() have been adjusted to add an 'append' argument, which when true will use '-F' instead of '-f' when executing virt-aa-helper. All existing calls to load_profile() and reload_profile() have been adjusted to use the old behavior (ie append==false) except AppArmorSetSavedStateLabel() where it made sense to use the new behavior. This patch also adds tests for '-F'. Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/640993
This commit is contained in:
parent
f095424600
commit
593e0072eb
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* AppArmor security driver for libvirt
|
* AppArmor security driver for libvirt
|
||||||
* Copyright (C) 2009 Canonical Ltd.
|
* Copyright (C) 2009-2010 Canonical Ltd.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -35,12 +35,20 @@
|
|||||||
#include "virterror_internal.h"
|
#include "virterror_internal.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
|
#include "pci.h"
|
||||||
|
#include "hostusb.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_SECURITY
|
#define VIR_FROM_THIS VIR_FROM_SECURITY
|
||||||
#define SECURITY_APPARMOR_VOID_DOI "0"
|
#define SECURITY_APPARMOR_VOID_DOI "0"
|
||||||
#define SECURITY_APPARMOR_NAME "apparmor"
|
#define SECURITY_APPARMOR_NAME "apparmor"
|
||||||
#define VIRT_AA_HELPER BINDIR "/virt-aa-helper"
|
#define VIRT_AA_HELPER BINDIR "/virt-aa-helper"
|
||||||
|
|
||||||
|
/* Data structure to pass to *FileIterate so we have everything we need */
|
||||||
|
struct SDPDOP {
|
||||||
|
virSecurityDriverPtr drv;
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* profile_status returns '-1' on error, '0' if loaded
|
* profile_status returns '-1' on error, '0' if loaded
|
||||||
*
|
*
|
||||||
@ -149,8 +157,10 @@ profile_status_file(const char *str)
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
load_profile(virSecurityDriverPtr drv,
|
load_profile(virSecurityDriverPtr drv,
|
||||||
const char *profile, virDomainObjPtr vm,
|
const char *profile,
|
||||||
const char *fn)
|
virDomainObjPtr vm,
|
||||||
|
const char *fn,
|
||||||
|
bool append)
|
||||||
{
|
{
|
||||||
int rc = -1, status, ret;
|
int rc = -1, status, ret;
|
||||||
bool create = true;
|
bool create = true;
|
||||||
@ -178,6 +188,12 @@ load_profile(virSecurityDriverPtr drv,
|
|||||||
};
|
};
|
||||||
ret = virExec(argv, NULL, NULL, &child,
|
ret = virExec(argv, NULL, NULL, &child,
|
||||||
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
|
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
|
||||||
|
} else if (fn && append) {
|
||||||
|
const char *const argv[] = {
|
||||||
|
VIRT_AA_HELPER, "-p", probe, "-r", "-u", profile, "-F", fn, NULL
|
||||||
|
};
|
||||||
|
ret = virExec(argv, NULL, NULL, &child,
|
||||||
|
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
|
||||||
} else if (fn) {
|
} else if (fn) {
|
||||||
const char *const argv[] = {
|
const char *const argv[] = {
|
||||||
VIRT_AA_HELPER, "-p", probe, "-r", "-u", profile, "-f", fn, NULL
|
VIRT_AA_HELPER, "-p", probe, "-r", "-u", profile, "-f", fn, NULL
|
||||||
@ -285,7 +301,9 @@ cleanup:
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
reload_profile(virSecurityDriverPtr drv,
|
reload_profile(virSecurityDriverPtr drv,
|
||||||
virDomainObjPtr vm, const char *fn)
|
virDomainObjPtr vm,
|
||||||
|
const char *fn,
|
||||||
|
bool append)
|
||||||
{
|
{
|
||||||
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
|
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
@ -299,7 +317,7 @@ reload_profile(virSecurityDriverPtr drv,
|
|||||||
|
|
||||||
/* Update the profile only if it is loaded */
|
/* Update the profile only if it is loaded */
|
||||||
if (profile_loaded(secdef->imagelabel) >= 0) {
|
if (profile_loaded(secdef->imagelabel) >= 0) {
|
||||||
if (load_profile(drv, secdef->imagelabel, vm, fn) < 0) {
|
if (load_profile(drv, secdef->imagelabel, vm, fn, append) < 0) {
|
||||||
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot update AppArmor profile "
|
_("cannot update AppArmor profile "
|
||||||
"\'%s\'"),
|
"\'%s\'"),
|
||||||
@ -315,6 +333,42 @@ reload_profile(virSecurityDriverPtr drv,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
AppArmorSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
|
||||||
|
const char *file, void *opaque)
|
||||||
|
{
|
||||||
|
struct SDPDOP *ptr = opaque;
|
||||||
|
virDomainObjPtr vm = ptr->vm;
|
||||||
|
|
||||||
|
if (reload_profile(ptr->drv, vm, file, true) < 0) {
|
||||||
|
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
|
||||||
|
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot update AppArmor profile "
|
||||||
|
"\'%s\'"),
|
||||||
|
secdef->imagelabel);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
AppArmorSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
|
||||||
|
const char *file, void *opaque)
|
||||||
|
{
|
||||||
|
struct SDPDOP *ptr = opaque;
|
||||||
|
virDomainObjPtr vm = ptr->vm;
|
||||||
|
|
||||||
|
if (reload_profile(ptr->drv, vm, file, true) < 0) {
|
||||||
|
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
|
||||||
|
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot update AppArmor profile "
|
||||||
|
"\'%s\'"),
|
||||||
|
secdef->imagelabel);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Called on libvirtd startup to see if AppArmor is available */
|
/* Called on libvirtd startup to see if AppArmor is available */
|
||||||
static int
|
static int
|
||||||
AppArmorSecurityDriverProbe(void)
|
AppArmorSecurityDriverProbe(void)
|
||||||
@ -426,7 +480,8 @@ AppArmorSetSecurityAllLabel(virSecurityDriverPtr drv,
|
|||||||
|
|
||||||
/* if the profile is not already loaded, then load one */
|
/* if the profile is not already loaded, then load one */
|
||||||
if (profile_loaded(vm->def->seclabel.label) < 0) {
|
if (profile_loaded(vm->def->seclabel.label) < 0) {
|
||||||
if (load_profile(drv, vm->def->seclabel.label, vm, stdin_path) < 0) {
|
if (load_profile(drv, vm->def->seclabel.label, vm, stdin_path,
|
||||||
|
false) < 0) {
|
||||||
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot generate AppArmor profile "
|
_("cannot generate AppArmor profile "
|
||||||
"\'%s\'"), vm->def->seclabel.label);
|
"\'%s\'"), vm->def->seclabel.label);
|
||||||
@ -549,7 +604,7 @@ AppArmorRestoreSecurityImageLabel(virSecurityDriverPtr drv,
|
|||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virDomainDiskDefPtr disk ATTRIBUTE_UNUSED)
|
virDomainDiskDefPtr disk ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
return reload_profile(drv, vm, NULL);
|
return reload_profile(drv, vm, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when hotplugging */
|
/* Called when hotplugging */
|
||||||
@ -580,7 +635,8 @@ AppArmorSetSecurityImageLabel(virSecurityDriverPtr drv,
|
|||||||
|
|
||||||
/* update the profile only if it is loaded */
|
/* update the profile only if it is loaded */
|
||||||
if (profile_loaded(secdef->imagelabel) >= 0) {
|
if (profile_loaded(secdef->imagelabel) >= 0) {
|
||||||
if (load_profile(drv, secdef->imagelabel, vm, disk->src) < 0) {
|
if (load_profile(drv, secdef->imagelabel, vm, disk->src,
|
||||||
|
false) < 0) {
|
||||||
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("cannot update AppArmor profile "
|
_("cannot update AppArmor profile "
|
||||||
"\'%s\'"),
|
"\'%s\'"),
|
||||||
@ -622,22 +678,69 @@ AppArmorReserveSecurityLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
AppArmorSetSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
|
AppArmorSetSecurityHostdevLabel(virSecurityDriverPtr drv,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)
|
virDomainHostdevDefPtr dev)
|
||||||
|
|
||||||
{
|
{
|
||||||
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
|
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
|
||||||
|
struct SDPDOP *ptr;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
|
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* TODO: call load_profile with an update vm->def */
|
if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (profile_loaded(secdef->imagelabel) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(ptr) < 0)
|
||||||
|
return -1;
|
||||||
|
ptr->drv = drv;
|
||||||
|
ptr->vm = vm;
|
||||||
|
|
||||||
|
switch (dev->source.subsys.type) {
|
||||||
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
||||||
|
usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
|
||||||
|
dev->source.subsys.u.usb.device);
|
||||||
|
|
||||||
|
if (!usb)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
ret = usbDeviceFileIterate(usb, AppArmorSetSecurityUSBLabel, ptr);
|
||||||
|
usbFreeDevice(usb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
|
||||||
|
pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
|
||||||
|
dev->source.subsys.u.pci.bus,
|
||||||
|
dev->source.subsys.u.pci.slot,
|
||||||
|
dev->source.subsys.u.pci.function);
|
||||||
|
|
||||||
|
if (!pci)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
ret = pciDeviceFileIterate(pci, AppArmorSetSecurityPCILabel, ptr);
|
||||||
|
pciFreeDevice(pci);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
VIR_FREE(ptr);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
AppArmorRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
|
AppArmorRestoreSecurityHostdevLabel(virSecurityDriverPtr drv,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)
|
virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)
|
||||||
|
|
||||||
@ -646,8 +749,7 @@ AppArmorRestoreSecurityHostdevLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
|
|||||||
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
|
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* TODO: call load_profile (needs virDomainObjPtr vm) */
|
return reload_profile(drv, vm, NULL, false);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -655,7 +757,7 @@ AppArmorSetSavedStateLabel(virSecurityDriverPtr drv,
|
|||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
const char *savefile)
|
const char *savefile)
|
||||||
{
|
{
|
||||||
return reload_profile(drv, vm, savefile);
|
return reload_profile(drv, vm, savefile, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -664,7 +766,7 @@ AppArmorRestoreSavedStateLabel(virSecurityDriverPtr drv,
|
|||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
const char *savefile ATTRIBUTE_UNUSED)
|
const char *savefile ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
return reload_profile(drv, vm, NULL);
|
return reload_profile(drv, vm, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
virSecurityDriver virAppArmorSecurityDriver = {
|
virSecurityDriver virAppArmorSecurityDriver = {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* virt-aa-helper: wrapper program used by AppArmor security driver.
|
* virt-aa-helper: wrapper program used by AppArmor security driver.
|
||||||
* Copyright (C) 2009 Canonical Ltd.
|
* Copyright (C) 2009-2010 Canonical Ltd.
|
||||||
*
|
*
|
||||||
* See COPYING.LIB for the License of this software
|
* See COPYING.LIB for the License of this software
|
||||||
*
|
*
|
||||||
@ -54,7 +54,8 @@ typedef struct {
|
|||||||
char *hvm; /* type of hypervisor (eg hvm, xen) */
|
char *hvm; /* type of hypervisor (eg hvm, xen) */
|
||||||
char *arch; /* machine architecture */
|
char *arch; /* machine architecture */
|
||||||
int bits; /* bits in the guest */
|
int bits; /* bits in the guest */
|
||||||
char *newdisk; /* newly added disk */
|
char *newfile; /* newly added file */
|
||||||
|
bool append; /* append to .files instead of rewrite */
|
||||||
} vahControl;
|
} vahControl;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -68,7 +69,7 @@ vahDeinit(vahControl * ctl)
|
|||||||
VIR_FREE(ctl->files);
|
VIR_FREE(ctl->files);
|
||||||
VIR_FREE(ctl->hvm);
|
VIR_FREE(ctl->hvm);
|
||||||
VIR_FREE(ctl->arch);
|
VIR_FREE(ctl->arch);
|
||||||
VIR_FREE(ctl->newdisk);
|
VIR_FREE(ctl->newfile);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -84,6 +85,8 @@ vah_usage(void)
|
|||||||
" -a | --add load profile\n"
|
" -a | --add load profile\n"
|
||||||
" -c | --create create profile from template\n"
|
" -c | --create create profile from template\n"
|
||||||
" -D | --delete unload and delete profile\n"
|
" -D | --delete unload and delete profile\n"
|
||||||
|
" -f | --add-file <file> add file to profile\n"
|
||||||
|
" -F | --append-file <file> append file to profile\n"
|
||||||
" -r | --replace reload profile\n"
|
" -r | --replace reload profile\n"
|
||||||
" -R | --remove unload profile\n"
|
" -R | --remove unload profile\n"
|
||||||
" -h | --help this help\n"
|
" -h | --help this help\n"
|
||||||
@ -227,18 +230,33 @@ parserCommand(const char *profile_name, const char cmd)
|
|||||||
* Update the dynamic files
|
* Update the dynamic files
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
update_include_file(const char *include_file, const char *included_files)
|
update_include_file(const char *include_file, const char *included_files,
|
||||||
|
bool append)
|
||||||
{
|
{
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
int plen;
|
int plen, flen;
|
||||||
int fd;
|
int fd;
|
||||||
char *pcontent = NULL;
|
char *pcontent = NULL;
|
||||||
|
char *existing = NULL;
|
||||||
const char *warning =
|
const char *warning =
|
||||||
"# DO NOT EDIT THIS FILE DIRECTLY. IT IS MANAGED BY LIBVIRT.\n";
|
"# DO NOT EDIT THIS FILE DIRECTLY. IT IS MANAGED BY LIBVIRT.\n";
|
||||||
|
|
||||||
if (virAsprintf(&pcontent, "%s%s", warning, included_files) == -1) {
|
if (virFileExists(include_file)) {
|
||||||
vah_error(NULL, 0, "could not allocate memory for profile");
|
flen = virFileReadAll(include_file, MAX_FILE_LEN, &existing);
|
||||||
return rc;
|
if (flen < 0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (append && virFileExists(include_file)) {
|
||||||
|
if (virAsprintf(&pcontent, "%s%s", existing, included_files) == -1) {
|
||||||
|
vah_error(NULL, 0, "could not allocate memory for profile");
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (virAsprintf(&pcontent, "%s%s", warning, included_files) == -1) {
|
||||||
|
vah_error(NULL, 0, "could not allocate memory for profile");
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plen = strlen(pcontent);
|
plen = strlen(pcontent);
|
||||||
@ -248,20 +266,9 @@ update_include_file(const char *include_file, const char *included_files)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* only update the disk profile if it is different */
|
/* only update the disk profile if it is different */
|
||||||
if (virFileExists(include_file)) {
|
if (flen > 0 && flen == plen && STREQLEN(existing, pcontent, plen)) {
|
||||||
char *existing = NULL;
|
rc = 0;
|
||||||
int flen = virFileReadAll(include_file, MAX_FILE_LEN, &existing);
|
goto clean;
|
||||||
if (flen < 0)
|
|
||||||
goto clean;
|
|
||||||
|
|
||||||
if (flen == plen) {
|
|
||||||
if (STREQLEN(existing, pcontent, plen)) {
|
|
||||||
rc = 0;
|
|
||||||
VIR_FREE(existing);
|
|
||||||
goto clean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VIR_FREE(existing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write the file */
|
/* write the file */
|
||||||
@ -284,6 +291,7 @@ update_include_file(const char *include_file, const char *included_files)
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
VIR_FREE(pcontent);
|
VIR_FREE(pcontent);
|
||||||
|
VIR_FREE(existing);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -958,8 +966,8 @@ get_files(vahControl * ctl)
|
|||||||
} /* switch */
|
} /* switch */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctl->newdisk)
|
if (ctl->newfile)
|
||||||
if (vah_add_file(&buf, ctl->newdisk, "rw") != 0)
|
if (vah_add_file(&buf, ctl->newfile, "rw") != 0)
|
||||||
goto clean;
|
goto clean;
|
||||||
|
|
||||||
if (virBufferError(&buf)) {
|
if (virBufferError(&buf)) {
|
||||||
@ -987,6 +995,7 @@ vahParseArgv(vahControl * ctl, int argc, char **argv)
|
|||||||
{"dryrun", 0, 0, 'd'},
|
{"dryrun", 0, 0, 'd'},
|
||||||
{"delete", 0, 0, 'D'},
|
{"delete", 0, 0, 'D'},
|
||||||
{"add-file", 0, 0, 'f'},
|
{"add-file", 0, 0, 'f'},
|
||||||
|
{"append-file", 0, 0, 'F'},
|
||||||
{"help", 0, 0, 'h'},
|
{"help", 0, 0, 'h'},
|
||||||
{"replace", 0, 0, 'r'},
|
{"replace", 0, 0, 'r'},
|
||||||
{"remove", 0, 0, 'R'},
|
{"remove", 0, 0, 'R'},
|
||||||
@ -994,7 +1003,7 @@ vahParseArgv(vahControl * ctl, int argc, char **argv)
|
|||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
while ((arg = getopt_long(argc, argv, "acdDhrRH:b:u:p:f:", opt,
|
while ((arg = getopt_long(argc, argv, "acdDhrRH:b:u:p:f:F:", opt,
|
||||||
&idx)) != -1) {
|
&idx)) != -1) {
|
||||||
switch (arg) {
|
switch (arg) {
|
||||||
case 'a':
|
case 'a':
|
||||||
@ -1010,8 +1019,10 @@ vahParseArgv(vahControl * ctl, int argc, char **argv)
|
|||||||
ctl->cmd = 'D';
|
ctl->cmd = 'D';
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
if ((ctl->newdisk = strdup(optarg)) == NULL)
|
case 'F':
|
||||||
|
if ((ctl->newfile = strdup(optarg)) == NULL)
|
||||||
vah_error(ctl, 1, "could not allocate memory for disk");
|
vah_error(ctl, 1, "could not allocate memory for disk");
|
||||||
|
ctl->append = arg == 'F';
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
vah_usage();
|
vah_usage();
|
||||||
@ -1127,14 +1138,19 @@ main(int argc, char **argv)
|
|||||||
if (ctl->cmd == 'c' && virFileExists(profile))
|
if (ctl->cmd == 'c' && virFileExists(profile))
|
||||||
vah_error(ctl, 1, "profile exists");
|
vah_error(ctl, 1, "profile exists");
|
||||||
|
|
||||||
virBufferVSprintf(&buf, " \"%s/log/libvirt/**/%s.log\" w,\n",
|
if (ctl->append && ctl->newfile) {
|
||||||
LOCAL_STATE_DIR, ctl->def->name);
|
if (vah_add_file(&buf, ctl->newfile, "rw") != 0)
|
||||||
virBufferVSprintf(&buf, " \"%s/lib/libvirt/**/%s.monitor\" rw,\n",
|
goto clean;
|
||||||
LOCAL_STATE_DIR, ctl->def->name);
|
} else {
|
||||||
virBufferVSprintf(&buf, " \"%s/run/libvirt/**/%s.pid\" rwk,\n",
|
virBufferVSprintf(&buf, " \"%s/log/libvirt/**/%s.log\" w,\n",
|
||||||
LOCAL_STATE_DIR, ctl->def->name);
|
LOCAL_STATE_DIR, ctl->def->name);
|
||||||
if (ctl->files)
|
virBufferVSprintf(&buf, " \"%s/lib/libvirt/**/%s.monitor\" rw,\n",
|
||||||
virBufferVSprintf(&buf, "%s", ctl->files);
|
LOCAL_STATE_DIR, ctl->def->name);
|
||||||
|
virBufferVSprintf(&buf, " \"%s/run/libvirt/**/%s.pid\" rwk,\n",
|
||||||
|
LOCAL_STATE_DIR, ctl->def->name);
|
||||||
|
if (ctl->files)
|
||||||
|
virBufferVSprintf(&buf, "%s", ctl->files);
|
||||||
|
}
|
||||||
|
|
||||||
if (virBufferError(&buf)) {
|
if (virBufferError(&buf)) {
|
||||||
virBufferFreeAndReset(&buf);
|
virBufferFreeAndReset(&buf);
|
||||||
@ -1149,7 +1165,8 @@ main(int argc, char **argv)
|
|||||||
vah_info(included_files);
|
vah_info(included_files);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else if ((rc = update_include_file(include_file,
|
} else if ((rc = update_include_file(include_file,
|
||||||
included_files)) != 0)
|
included_files,
|
||||||
|
ctl->append)) != 0)
|
||||||
goto clean;
|
goto clean;
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,6 +179,8 @@ else
|
|||||||
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,/boot/initrd,g" > "$test_xml"
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,/boot/initrd,g" > "$test_xml"
|
||||||
testme "1" "-r with invalid -f with probing" "-p 1 -r -u $valid_uuid -f $bad_disk" "$test_xml"
|
testme "1" "-r with invalid -f with probing" "-p 1 -r -u $valid_uuid -f $bad_disk" "$test_xml"
|
||||||
testme "1" "-r with invalid -f without probing" "-p 0 -r -u $valid_uuid -f $bad_disk" "$test_xml"
|
testme "1" "-r with invalid -f without probing" "-p 0 -r -u $valid_uuid -f $bad_disk" "$test_xml"
|
||||||
|
testme "1" "-r with invalid -F with probing" "-p 1 -r -u $valid_uuid -F $bad_disk" "$test_xml"
|
||||||
|
testme "1" "-r with invalid -F without probing" "-p 0 -r -u $valid_uuid -F $bad_disk" "$test_xml"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1</disk>,g" > "$test_xml"
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1</disk>,g" > "$test_xml"
|
||||||
@ -237,6 +239,12 @@ testme "0" "replace (adding disk)" "-r -u $valid_uuid -f $disk2" "$test_xml"
|
|||||||
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" > "$test_xml"
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" > "$test_xml"
|
||||||
testme "0" "replace (adding non-existent disk)" "-r -u $valid_uuid -f $nonexistent" "$test_xml"
|
testme "0" "replace (adding non-existent disk)" "-r -u $valid_uuid -f $nonexistent" "$test_xml"
|
||||||
|
|
||||||
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" > "$test_xml"
|
||||||
|
testme "0" "replace (appending disk)" "-r -u $valid_uuid -F $disk2" "$test_xml"
|
||||||
|
|
||||||
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" > "$test_xml"
|
||||||
|
testme "0" "replace (appending non-existent disk)" "-r -u $valid_uuid -F $nonexistent" "$test_xml"
|
||||||
|
|
||||||
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" | sed "s,</devices>,<disk type='block' device='cdrom'><target dev='hdc' bus='ide'/><readonly/></disk></devices>,g" > "$test_xml"
|
cat "$template_xml" | sed "s,###UUID###,$uuid,g" | sed "s,###DISK###,$disk1,g" | sed "s,</devices>,<disk type='block' device='cdrom'><target dev='hdc' bus='ide'/><readonly/></disk></devices>,g" > "$test_xml"
|
||||||
testme "0" "disk (empty cdrom)" "-r -u $valid_uuid" "$test_xml"
|
testme "0" "disk (empty cdrom)" "-r -u $valid_uuid" "$test_xml"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user