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]

Reply via email to