John,
I am sorry I took so long to get back to you.
I only looked at the contract operations in contract.c and assumed
everything that used Python was correct since I am not familiar with the
Python-C interface. Please find my comments below.
contract.c: 157
The call to ct_pr_tmpl_set_svc_aux() can fail. If it happens, the
auxiliary field will revert to the default value, empty string, in the
current code. If xend can cope with a contract that has
svc:/system/xvm/xend as service FMRI and "" as auxiliary field, there
will be no compelling reason to handle the error, but you should not
ignore the value. Use (void).
close(2) and ct_ctl_abandon(3contract) return int but is ignored.
One way to avoid the abandon_contract() code, it to set the inherit
parameter for the process contracts holding the qemu process. Just call
ct_pr_tmpl_set_param(cfd, CT_PR_INHERIT)
before you ct_tmpl_activate()
This way, if xend is restarted, svc.startd will transfer the qemu
contracts to the contract holding xend. If desired, after xend is
restarted, it can adopt the qemu contracts from the process contract
xend is member of. I attached an example based on your code exemplifying
the behavior described above. Please let me know if you have questions.
Antonello
John Levon wrote:
Can I please get reviews for:
6664938 xend needs to run qemu instances in a new contract
http://cr.opensolaris.org/~johnlev/qemu-contract/
thanks
john
#include <unistd.h>
int
main(void)
{
for(;;)
sleep(30);
}
/*
* xend contract management alternative
*/
#include <libcontract.h>
#include <sys/contract/process.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <procfs.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
int
create_contract(const char *name)
{
int flags;
int cfd;
cfd = open64("/system/contract/process/template", O_RDWR);
if (cfd == -1)
return (-1);
if ((flags = fcntl(cfd, F_GETFD, 0)) == -1) {
(void) close(cfd);
return (-1);
}
if (fcntl(cfd, F_SETFD, flags | FD_CLOEXEC) == -1) {
(void) close(cfd);
return (-1);
}
if (name != NULL)
if (ct_pr_tmpl_set_svc_aux(cfd, name) != 0) {
(void) fprintf(stderr, "failed to set aux\n");
exit(1);
}
if (ct_pr_tmpl_set_param(cfd, CT_PR_INHERIT) != 0) {
(void) fprintf(stderr, "failed to set ct param\n");
return (-1);
}
if (ct_tmpl_activate(cfd)) {
(void) close(cfd);
return (-1);
}
return (cfd);
}
void
adopt_contracts()
{
int pfd, sfd, i;
psinfo_t info;
ct_stathdl_t st;
ctid_t *pc, ctid;
uint_t pcn;
char pname[PATH_MAX];
(void) snprintf(pname, sizeof (pname), "/proc/%d/psinfo", getpid());
if ((pfd = open(pname, O_RDONLY)) == -1) {
(void) fprintf(stderr,
"Identity crisis, cannot tell who am I! %s\n",
strerror(errno));
exit(1);
}
if (read(pfd, &info, sizeof (info)) != sizeof (info)) {
(void) fprintf(stderr,
"Cannot read psinfo! %s\n", strerror(errno));
exit(1);
}
ctid = info.pr_contract;
(void) close(pfd);
(void) snprintf(pname, sizeof (pname),
"/system/contract/process/%d/status", ctid);
if ((sfd = open64(pname, O_RDONLY)) == -1) {
(void) fprintf(stderr, "Cannot open %s: %s\n", pname,
strerror(errno));
exit(1);
}
if (ct_status_read(sfd, CTD_ALL, &st)) {
(void) fprintf(stderr, "Could not read status of contract "
"%d %s fd %d %s\n",
ctid, pname, sfd, strerror(errno));
exit(1);
}
if (ct_pr_status_get_contracts(st, &pc, &pcn) == 0) {
for(i = 0; i < pcn; ++i) {
int ctfdi;
(void) snprintf(pname, sizeof (pname),
"/system/contract/process/%d/ctl", pc[i]);
if ((ctfdi = open64(pname, O_WRONLY)) == -1) {
continue;
}
if (ct_ctl_adopt(ctfdi) != 0)
(void) fprintf(stderr,
"could not adopt contract %d", ctfdi);
(void) close(ctfdi);
}
} else {
(void) printf("could not read contracts\n");
}
ct_status_free(st);
(void) close(sfd);
}
int
main(int argc, char **argv)
{
int ctfd;
int ret;
int ex;
int i;
int parent = 1;
char name[CT_PARAM_MAX_SIZE];
/*
* First adopt my predecessor's kids
*/
adopt_contracts();
for (i = 0; i < 3; ++i) {
(void) snprintf(name, sizeof (name), "qemu-fake: %d", i + 1);
if ((ctfd = create_contract(name)) == -1) {
(void) fprintf(stderr, "failed to create contract\n");
exit(1);
}
if (parent == 1) {
ret = fork();
if (ret == -1) {
(void) fprintf(stderr, "failed to fork()\n");
exit(1);
} else if (ret == 0) {
parent = 0;
execv("/export/home/acruz/work/creview/xen/qemu-fake", argv);
(void) printf("exec failed: %s\n",
strerror(errno));
exit(1);
}
}
}
for(;;)
sleep(30);
}
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<!--
Copyright 2006 Sun Microsystems, Inc. All rights reserved.
Use is subject to license terms.
CDDL HEADER START
The contents of this file are subject to the terms of the
Common Development and Distribution License (the "License").
You may not use this file except in compliance with the License.
You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
or http://www.opensolaris.org/os/licensing.
See the License for the specific language governing permissions
and limitations under the License.
When distributing Covered Code, include this CDDL HEADER in each
file and include the License file at usr/src/OPENSOLARIS.LICENSE.
If applicable, add the following below this CDDL HEADER, with the
fields enclosed by brackets "[]" replaced with your own identifying
information: Portions Copyright [yyyy] [name of copyright owner]
CDDL HEADER END
NOTE: This service manifest is not editable; its contents will
be overwritten by package or patch operations, including
operating system upgrade. Make customizations in a different
file.
-->
<service_bundle type='manifest' name='export'>
<service name='system/xvm/xend-fake' type='service' version='1'>
<create_default_instance enabled='false'/>
<single_instance/>
<dependency name='fs-local' grouping='require_all' restart_on='none'
type='service'>
<service_fmri value='svc:/system/filesystem/local' />
</dependency>
<exec_method name='start' type='method'
exec='/export/home/acruz/work/creview/xen/xend-fake.sh'
timeout_seconds='10' />
<!-- Note: /usr/lib/xend stop just ends up doing a 'kill', except
unsafely and wrongly; so instead we just use the known-good
contract kill here. -->
<exec_method name='stop' type='method'
exec=':kill' timeout_seconds='60' />
<property_group name='config' type='application'>
<stability value='Unstable' />
<propval name='enable-dump' type='boolean'
value='true' />
<propval name='xend-unix-server' type='boolean'
value='true' />
<propval name='xend-relocation-server' type='boolean'
value='true' />
<propval name='xend-relocation-address' type='astring'
value='127.0.0.1' />
<propval name='xend-relocation-hosts-allow' type='astring'
value='^localhost$' />
<!-- XXPV: it's doubtful this a good default for us. -->
<propval name='dom0-min-mem' type='integer'
value='196' />
<propval name='dom0-cpus' type='integer'
value='0' />
<propval name='default-nic' type='astring'
value='' />
</property_group>
<stability value='Unstable'/>
<template>
<common_name>
<loctext xml:lang='C'>Hypervisor Control Daemon</loctext>
</common_name>
<documentation>
<manpage title='xend' section='1M'
manpath='/usr/share/man' />
</documentation>
</template>
</service>
</service_bundle>
_______________________________________________
xen-discuss mailing list
[email protected]