mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
tools: remove xend and associated python modules
I've retained xen.lowlevel.{xc,xs} since they seem more widely useful. I also
kept xen.lowlevel.xl even though it is disabled by default and IMHO useless in
its current form.
I've tried to clean up the various associated bits like example configs, init
scripts, udev rules etc but no doubt I have missed something, those can easily
be cleaned up later.
I've also removed xm-test since although it could in theory be reworked to
test xl it hasn't been touched for years. If someone wants to resurrect it
then they could do so via the git history.
This has been built but not runtime tested.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
v2: Clean out some .*ignore cruft
Remove some xm/xend docs.
This commit is contained in:
1 parent
e04254f7bc
commit
9e8672f1c3
503 files changed
+7
-83858
No files matched your search
-14
@@ -245,8 +245,6 @@ tools/vtpm/tpm_emulator/*
|
||||
tools/vtpm/vtpm/*
|
||||
tools/vtpm_manager/manager/vtpm_managerd
|
||||
tools/xcutils/lsevtchn
|
||||
tools/xcutils/xc_restore
|
||||
tools/xcutils/xc_save
|
||||
tools/xcutils/readnotes
|
||||
tools/xenfb/sdlfb
|
||||
tools/xenfb/vncfb
|
||||
@@ -279,18 +277,6 @@ tools/xentrace/xentrace_setsize
|
||||
tools/xentrace/tbctl
|
||||
tools/xentrace/xenctx
|
||||
tools/xentrace/xentrace
|
||||
tools/xm-test/ramdisk/buildroot
|
||||
tools/xm-test/aclocal.m4
|
||||
tools/xm-test/autom4te
|
||||
tools/xm-test/install-sh
|
||||
tools/xm-test/mkinstalldirs
|
||||
tools/xm-test/missing
|
||||
tools/xm-test/config(ure|.log|.status|.guess|.sub)
|
||||
tools/xm-test/Makefile(.in)*
|
||||
tools/xm-test/*/Makefile(.in)*
|
||||
tools/xm-test/lib/XmTestLib/config.py
|
||||
tools/xm-test/lib/XmTestReport/xmtest.py
|
||||
tools/xm-test/tests/*.test
|
||||
tools/ocaml-xenstored*
|
||||
xen/.banner
|
||||
xen/System.map
|
||||
|
||||
@@ -278,18 +278,6 @@
|
||||
^tools/xentrace/tbctl$
|
||||
^tools/xentrace/xenctx$
|
||||
^tools/xentrace/xentrace$
|
||||
^tools/xm-test/ramdisk/buildroot
|
||||
^tools/xm-test/aclocal.m4$
|
||||
^tools/xm-test/autom4te
|
||||
^tools/xm-test/install-sh$
|
||||
^tools/xm-test/mkinstalldirs$
|
||||
^tools/xm-test/missing$
|
||||
^tools/xm-test/config(ure|.log|.status|.guess|.sub)$
|
||||
^tools/xm-test/Makefile(.in)*$
|
||||
^tools/xm-test/.*/Makefile(.in)*$
|
||||
^tools/xm-test/lib/XmTestLib/config.py$
|
||||
^tools/xm-test/lib/XmTestReport/xmtest.py$
|
||||
^tools/xm-test/tests/.*\.test$
|
||||
^tools/firmware/ovmf-remote
|
||||
^tools/firmware/ovmf$
|
||||
^tools/qemu-xen-traditional-dir-remote
|
||||
|
||||
@@ -255,8 +255,6 @@ REMUS
|
||||
M: Shriram Rajagopalan <rshriram@cs.ubc.ca>
|
||||
S: Maintained
|
||||
F: tools/remus/
|
||||
F: tools/python/xen/remus/
|
||||
F: tools/python/xen/lowlevel/checkpoint/
|
||||
F: tools/blktap2/drivers/block-remus.c
|
||||
F: tools/blktap2/drivers/hashtable*
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ CONFIG_ROMBIOS := @rombios@
|
||||
CONFIG_SEABIOS := @seabios@
|
||||
CONFIG_QEMU_TRAD := @qemu_traditional@
|
||||
CONFIG_QEMU_XEN := @qemu_xen@
|
||||
CONFIG_XEND := @xend@
|
||||
CONFIG_BLKTAP1 := @blktap1@
|
||||
|
||||
#System options
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
xend-config.sxp - Xen daemon configuration file
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
/etc/xen/xend-config.sxp
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The xend(1) program requires xend-config.sxp to specify operating
|
||||
parameters which determine the behavior of the daemon at runtime.
|
||||
|
||||
The parameters are specified in S-expression format. See the example
|
||||
configuration file in I</etc/xen/xend-config.sxp> for details.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
The following lists the daemon configuration parameters:
|
||||
|
||||
=over 4
|
||||
|
||||
=item I<logfile>
|
||||
|
||||
The location of the file to record runtime log messages. Defaults to
|
||||
I</var/log/xen/xend.log>.
|
||||
|
||||
=item I<loglevel>
|
||||
|
||||
Filters out messages below the specified level. Possible values are
|
||||
DEBUG, INFO, WARNING, ERROR, CRITICAL. Defaults to I<DEBUG>.
|
||||
|
||||
=item I<xend-http-server>
|
||||
|
||||
A boolean value that tells xend whether or not to start the http
|
||||
stream socket management server. Defaults to I<no>.
|
||||
|
||||
=item I<xend-unix-server>
|
||||
|
||||
A boolean value that tells xend whether or not to start the unix
|
||||
domain socket management server. This is required for the CLI tools
|
||||
to operate. Defaults to I<yes>.
|
||||
|
||||
=item I<xend-relocation-server>
|
||||
|
||||
A boolean value that tells xend whether or not to start the relocation
|
||||
server. This is required for cross-machine migrations. Defaults to
|
||||
I<no>.
|
||||
|
||||
=item I<xend-unix-path>
|
||||
|
||||
The location of the unix domain socket the xend-unix-server will use
|
||||
to communicate with the management tools. Defaults to
|
||||
I</var/lib/xend/xend-socket>.
|
||||
|
||||
=item I<xend-port>
|
||||
|
||||
The port that will be used by the http management server. Defaults to
|
||||
I<8000>.
|
||||
|
||||
=item I<xend-relocation-port>
|
||||
|
||||
The port that will be used by the relocation server. Defaults to
|
||||
I<8002>.
|
||||
|
||||
=item I<xend-address>
|
||||
|
||||
The address to which the http management server will bind. Defaults
|
||||
to I<''> which means "all interfaces".
|
||||
|
||||
=item I<xend-relocation-address>
|
||||
|
||||
The address to which the relocation server will bind. Defaults to
|
||||
I<''> which means "all interfaces".
|
||||
|
||||
=item I<console-limit>
|
||||
|
||||
The kilobyte buffer limit that will be enforced by the console server.
|
||||
This limit is set per-domain, and is needed to prevent a single domain
|
||||
from overwhelming the console server with massive amounts of data.
|
||||
Defaults to I<1024>.
|
||||
|
||||
=item I<network-script>
|
||||
|
||||
The name of the script in I</etc/xen/scripts> that will be run to
|
||||
setup the networking environment. This can be any name, but in
|
||||
general is either I<network-bridge> or I<network-route>.
|
||||
|
||||
=item I<vif-script>
|
||||
|
||||
The name of the script in I</etc/xen/scripts> that will be run to
|
||||
setup a virtual interface when it is created or destroyed. This needs
|
||||
to (in general) work in unison with the I<network-script>.
|
||||
|
||||
=item I<dom0-min-mem>
|
||||
|
||||
This specifies the minimum number of megabytes that will be reserved
|
||||
for Domain0. If this value is positive, Domain0 will be automatically
|
||||
ballooned down to this limit to make space for new domains. If this
|
||||
is set to 0, Domain0 will not be automatically ballooned.
|
||||
|
||||
=item I<dom0-cpus>
|
||||
|
||||
This specifies the number of CPUs that Domain0 will be allowed to use.
|
||||
If the value is 0, all available CPUs will be used by Domain0.
|
||||
|
||||
=item I<enable-dump>
|
||||
|
||||
A boolean value that tells xend whether or not core dumps of guest
|
||||
domains should be saved when a crash occurs. Defaults to I<no>.
|
||||
|
||||
=item I<external-migration-tool>
|
||||
|
||||
The name of an application or script that can handle external device
|
||||
migration, such as for example virtual TPM migration. An example
|
||||
script is I</etc/xen/scripts/external-device-migrate>.
|
||||
|
||||
=item I<device-create-timeout>
|
||||
|
||||
Integer value that tells xend how long it should wait for a new device
|
||||
to be created. Defaults to I<100>.
|
||||
|
||||
=item I<device-destroy-timeout>
|
||||
|
||||
Integer value that tells xend how long it should wait for a device to
|
||||
be destroyed. Defaults to I<100>.
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
An example configuration with relocation enabled for the local network:
|
||||
|
||||
=over 4
|
||||
|
||||
(xend-relocation-server yes)
|
||||
(xend-relocation-address 192.0.2.192)
|
||||
(network-script network-bridge)
|
||||
(vif-script vif-bridge)
|
||||
(dom0-min-mem 0)
|
||||
(dom0-cpus 0)
|
||||
|
||||
=back
|
||||
|
||||
=head1 CAVEATS
|
||||
|
||||
Note that relocation is currently unsecured and is very dangerous if
|
||||
left enabled. No authentication is performed, and very little sanity
|
||||
checking takes place. Enable at your own risk.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
B<xend>(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dan Smith <danms@us.ibm.com>
|
||||
|
||||
@@ -12,7 +12,6 @@ The B<xl> program is the new tool for managing Xen guest
|
||||
domains. The program can be used to create, pause, and shutdown
|
||||
domains. It can also be used to list current domains, enable or pin
|
||||
VCPUs, and attach or detach virtual block devices.
|
||||
The old B<xm> tool is deprecated and should not be used.
|
||||
|
||||
The basic structure of every B<xl> command is almost always:
|
||||
|
||||
|
||||
-1004
File diff suppressed because it is too large.
Load diff
@@ -1,358 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
xmdomain.cfg - xm domain config file format
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
/etc/xen/myxendomain
|
||||
/etc/xen/myxendomain2
|
||||
/etc/xen/auto/myxenautostarted
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<xm>(1) program uses python executable config files to define
|
||||
domains to create from scratch. Each of these config files needs to
|
||||
contain a number of required options, and may specify many more.
|
||||
|
||||
Domain configuration files live in /etc/xen by default, if you store
|
||||
config files anywhere else the full path to the config file must be
|
||||
specified in the I<xm create> command.
|
||||
|
||||
/etc/xen/auto is a special case. Domain config files in that
|
||||
directory will be started automatically at system boot if the
|
||||
xendomain init script is enabled. The contents of /etc/xen/auto
|
||||
should be symlinks to files in /etc/xen to allow I<xm create> to be
|
||||
used without full paths.
|
||||
|
||||
Options are specified by I<name = value> statements in the
|
||||
xmdomain.cfg files.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
The following lists the most commonly used options for a domain config
|
||||
file.
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<kernel>
|
||||
|
||||
The kernel image for the domain. The format of the parameter is the
|
||||
fully qualified path to the kernel image file,
|
||||
i.e. I</boot/vmlinuz-2.6.12-xenU>.
|
||||
|
||||
|
||||
=item B<ramdisk>
|
||||
|
||||
The initial ramdisk for the domain. The format of the parameter is
|
||||
the fully qualified path to the initrd, i.e. I</boot/initrd.gz>. On
|
||||
many Linux distros you will not need a ramdisk if using the default
|
||||
xen kernel.
|
||||
|
||||
=item B<memory>
|
||||
|
||||
The amount of RAM, in megabytes, to allocate to the domain when it
|
||||
starts. Allocating insufficient memory for a domain may produce
|
||||
extremely bizarre behavior. If there isn't enough free memory left on
|
||||
the machine to fulfil this request, the domain will fail to start.
|
||||
|
||||
Xen does not support overcommit of memory, so the total memory of all
|
||||
guests (+ 64 MB needed for Xen) must be less than or equal to the
|
||||
physical RAM in the machine.
|
||||
|
||||
=item B<name>
|
||||
|
||||
A unique name for the domain. Attempting to create two domains with
|
||||
the same name will cause an error.
|
||||
|
||||
=item B<root>
|
||||
|
||||
Specifies the root device for the domain. This is required for Linux
|
||||
domains, and possibly other OSes.
|
||||
|
||||
=item B<nics>
|
||||
|
||||
The number of network interfaces allocated to the domain on boot. It
|
||||
defaults to 1.
|
||||
|
||||
=item B<disk>
|
||||
|
||||
An array of block device stanzas, in the form:
|
||||
|
||||
disk = [ "stanza1", "stanza2", ... ]
|
||||
|
||||
Each stanza has 3 terms, separated by commas,
|
||||
"backend-dev,frontend-dev,mode".
|
||||
|
||||
=over 4
|
||||
|
||||
=item I<backend-dev>
|
||||
|
||||
The device in the backend domain that will be exported to the guest
|
||||
(frontend) domain. Supported formats include:
|
||||
|
||||
I<phy:device> - export the physical device listed. The device can be
|
||||
in symbolic form, as in sda7, or as the hex major/minor number, as in
|
||||
0x301 (which is hda1).
|
||||
|
||||
I<file://path/to/file> - export the file listed as a loopback device.
|
||||
This will take care of the loopback setup before exporting the device.
|
||||
|
||||
=item I<frontend-dev>
|
||||
|
||||
How the device should appear in the guest domain. The device can be
|
||||
in symbolic form, as in sda7, or as the hex major/minor number, as in
|
||||
0x301 (which is hda1).
|
||||
|
||||
=item I<mode>
|
||||
|
||||
The access mode for the device. There are currently 2 valid options,
|
||||
I<r> (read-only), I<w> (read/write).
|
||||
|
||||
=back
|
||||
|
||||
=item B<vif>
|
||||
|
||||
An array of virtual interface stanzas in the form:
|
||||
|
||||
vif = [ "stanza1", "stanza2", ... ]
|
||||
|
||||
Each stanza specifies a set of I<name = value> options separated by
|
||||
commas, in the form: "name1=value1, name2=value2, ..."
|
||||
|
||||
B<OPTIONS>
|
||||
|
||||
=over 4
|
||||
|
||||
=item I<bridge>
|
||||
|
||||
The network bridge to be used for this device. This is especially
|
||||
needed if multiple bridges exist on the machine.
|
||||
|
||||
=item I<mac>
|
||||
|
||||
The MAC address for the virtual interface. If mac is not specified,
|
||||
one will be randomly chosen by xen with the 00:16:3e vendor id prefix.
|
||||
|
||||
=back
|
||||
|
||||
=item B<vfb>
|
||||
|
||||
A virtual frame buffer stanza in the form:
|
||||
|
||||
vfb = [ "stanza" ]
|
||||
|
||||
The stanza specifies a set of I<name = value> options separated by
|
||||
commas, in the form: "name1=value1, name2=value2, ..."
|
||||
|
||||
B<OPTIONS>
|
||||
|
||||
=over 4
|
||||
|
||||
=item I<type>
|
||||
|
||||
There are currently two valid options: I<vnc> starts a VNC server that
|
||||
lets you connect an external VNC viewer, and I<sdl> starts an internal
|
||||
viewer.
|
||||
|
||||
=item I<vncdisplay>
|
||||
|
||||
The VNC display number to use, defaults to the domain ID. The
|
||||
VNC server listens on port 5900 + display number.
|
||||
|
||||
=item I<vnclisten>
|
||||
|
||||
The listening address for the VNC server, default 127.0.0.1.
|
||||
|
||||
=item I<vncunused>
|
||||
|
||||
If non-zero, the VNC server listens on the first unused port above
|
||||
5900.
|
||||
|
||||
=item I<vncpasswd>
|
||||
|
||||
Overrides the XenD configured default password.
|
||||
|
||||
=item I<display>
|
||||
|
||||
Display to use for the internal viewer, defaults to environment
|
||||
variable I<DISPLAY>.
|
||||
|
||||
=item I<xauthority>
|
||||
|
||||
Authority file to use for the internal viewer, defaults to environment
|
||||
variable I<XAUTHORITY>.
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
=head1 ADDITIONAL OPTIONS
|
||||
|
||||
The following options are also supported in the config file, though
|
||||
are far more rarely used.
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<builder>
|
||||
|
||||
Which builder should be used to construct the domain. This defaults
|
||||
to the I<linux> if not specified, which is the builder for
|
||||
paravirtualized Linux domains.
|
||||
|
||||
=item B<cpu>
|
||||
|
||||
Specifies which CPU the domain should be started on, where 0 specifies
|
||||
the first cpu, 1 the second, and so on. This defaults to -1, which
|
||||
means Xen is free to pick which CPU to start on.
|
||||
|
||||
=item B<cpus>
|
||||
|
||||
Specifies a list of CPUs on which the domains' VCPUs are allowed to
|
||||
execute upon. The syntax supports ranges (0-3), and negation, ^1.
|
||||
For instance:
|
||||
|
||||
cpus = "0-3,5,^1"
|
||||
|
||||
Will result in CPUs 0, 2, 3, 5 being available for use by the domain.
|
||||
|
||||
=item B<extra>
|
||||
|
||||
Extra information to append to the end of the kernel parameter line.
|
||||
The format is a string, the contents of which can be anything that the
|
||||
kernel supports. For instance:
|
||||
|
||||
extra = "4"
|
||||
|
||||
Will cause the domain to boot to runlevel 4.
|
||||
|
||||
=item B<nfs_server>
|
||||
|
||||
The IP address of the NFS server to use as the root device for the
|
||||
domain. In order to do this you'll need to specify I<root=/dev/nfs>,
|
||||
and specify I<nfs_root>.
|
||||
|
||||
=item B<nfs_root>
|
||||
|
||||
The directory on the NFS server to be used as the root filesystem.
|
||||
Specified as a fully qualified path, i.e. I</full/path/to/root/dir>.
|
||||
|
||||
=item B<vcpus>
|
||||
|
||||
The number of virtual cpus to allocate to the domain. In order to use
|
||||
this the xen kernel must be compiled with SMP support.
|
||||
|
||||
This defaults to 1, meaning running the domain as a UP.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DOMAIN SHUTDOWN OPTIONS
|
||||
|
||||
There are 3 options which control domain shutdown (both planned and
|
||||
unplanned) under certain events. The 3 events currently captured are:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<on_shutdown>
|
||||
|
||||
Triggered on either an I<xm shutdown> or graceful shutdown from inside
|
||||
the DomU.
|
||||
|
||||
=item B<on_reboot>
|
||||
|
||||
Triggered on either an I<xm reboot> or graceful reboot from inside the
|
||||
DomU.
|
||||
|
||||
=item B<on_crash>
|
||||
|
||||
Triggered when a DomU goes to the crashed state for any reason.
|
||||
|
||||
=back
|
||||
|
||||
All of them take one of 4 valid states listed below.
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<destroy>
|
||||
|
||||
The domain will be cleaned up completely. No attempt at respawning
|
||||
will occur. This is what a typical shutdown would look like.
|
||||
|
||||
=item B<restart>
|
||||
|
||||
The domain will be restarted with the same name as the old domain.
|
||||
This is what a typical reboot would look like.
|
||||
|
||||
=item B<preserve>
|
||||
|
||||
The domain will not be cleaned up at all. This is often useful for
|
||||
crash state domains which ensures that enough evidence is to debug the
|
||||
real issue.
|
||||
|
||||
=item B<rename-restart>
|
||||
|
||||
The old domain will not be cleaned up, but will be renamed so a new
|
||||
domain can be restarted in it's place. The old domain will be renamed with
|
||||
a suffix -1, -2, etc, and assigned a new random UUID; the new domain will
|
||||
keep the original name and UUID. The old domain will release the devices that
|
||||
it holds, so that the new one may take them.
|
||||
|
||||
=back
|
||||
|
||||
Additionally, the "on_crash" event can also take:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<coredump-destroy>
|
||||
|
||||
Dump the crashed domain's core and then destroy it.
|
||||
|
||||
=item B<coredump-restart>
|
||||
|
||||
Dump the crashed domain's core and then restart it.
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
The following are quick examples of ways that domains might be
|
||||
configured. They should not be considered an exhaustive set.
|
||||
|
||||
=over 4
|
||||
|
||||
=item I<A Loopback File as Root>
|
||||
|
||||
kernel = "/boot/vmlinuz-2.6-xenU"
|
||||
memory = 128
|
||||
name = "MyLinux"
|
||||
root = "/dev/hda1 ro"
|
||||
disk = [ "file:/var/xen/mylinux.img,hda1,w" ]
|
||||
|
||||
This creates a domain called MyLinux with 128 MB of memory using a
|
||||
default xen kernel, and the file /var/xen/mylinux.img loopback mounted
|
||||
at hda1, which is the root filesystem.
|
||||
|
||||
=item I<NFS Root>
|
||||
|
||||
FIXME: write me
|
||||
|
||||
=item I<LVM Root>
|
||||
|
||||
FIXME: write me
|
||||
|
||||
=item I<Two Networks>
|
||||
|
||||
FIXME: write me
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
B<xm>(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Sean Dague <sean at dague dot net>
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
Not all options are currently documented
|
||||
Vendored
-48
@@ -688,7 +688,6 @@ seabios_path
|
||||
qemu_xen
|
||||
qemu_traditional
|
||||
blktap1
|
||||
xend
|
||||
debug
|
||||
seabios
|
||||
rombios
|
||||
@@ -765,7 +764,6 @@ enable_ovmf
|
||||
enable_rombios
|
||||
enable_seabios
|
||||
enable_debug
|
||||
enable_xend
|
||||
enable_blktap1
|
||||
enable_qemu_traditional
|
||||
with_system_qemu
|
||||
@@ -1427,7 +1425,6 @@ Optional Features:
|
||||
--disable-rombios Disable ROM BIOS (default is ENABLED)
|
||||
--disable-seabios Disable SeaBIOS (default is ENABLED)
|
||||
--disable-debug Disable debug build of tools (default is ENABLED)
|
||||
--enable-xend Enable xend toolstack (default is DISABLED)
|
||||
--enable-blktap1 Enable blktap1 tools (default is DISABLED)
|
||||
--enable-qemu-traditional
|
||||
Enable qemu traditional device model, (DEFAULT is on
|
||||
@@ -3747,29 +3744,6 @@ debug=$ax_cv_debug
|
||||
|
||||
|
||||
|
||||
# Check whether --enable-xend was given.
|
||||
if test "${enable_xend+set}" = set; then :
|
||||
enableval=$enable_xend;
|
||||
fi
|
||||
|
||||
|
||||
if test "x$enable_xend" = "xno"; then :
|
||||
|
||||
ax_cv_xend="n"
|
||||
|
||||
elif test "x$enable_xend" = "xyes"; then :
|
||||
|
||||
ax_cv_xend="y"
|
||||
|
||||
elif test -z $ax_cv_xend; then :
|
||||
|
||||
ax_cv_xend="n"
|
||||
|
||||
fi
|
||||
xend=$ax_cv_xend
|
||||
|
||||
|
||||
|
||||
# Check whether --enable-blktap1 was given.
|
||||
if test "${enable_blktap1+set}" = set; then :
|
||||
enableval=$enable_blktap1;
|
||||
@@ -9480,25 +9454,3 @@ $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
|
||||
fi
|
||||
|
||||
|
||||
if test "x$xend" = "xy" ; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You have enabled the xend toolstack.
|
||||
|
||||
xend is deprecated and scheduled for removal. Please migrate to another
|
||||
toolstack ASAP.
|
||||
|
||||
See http://wiki.xen.org/wiki/Choice_of_Toolstacks for information on
|
||||
other alternatives, including xl which is designed to be a drop in
|
||||
replacement for xm (http://wiki.xen.org/wiki/XL).
|
||||
" >&5
|
||||
$as_echo "$as_me: WARNING: You have enabled the xend toolstack.
|
||||
|
||||
xend is deprecated and scheduled for removal. Please migrate to another
|
||||
toolstack ASAP.
|
||||
|
||||
See http://wiki.xen.org/wiki/Choice_of_Toolstacks for information on
|
||||
other alternatives, including xl which is designed to be a drop in
|
||||
replacement for xm (http://wiki.xen.org/wiki/XL).
|
||||
" >&2;}
|
||||
|
||||
fi
|
||||
@@ -58,7 +58,6 @@ AX_ARG_DEFAULT_DISABLE([ovmf], [Enable OVMF])
|
||||
AX_ARG_DEFAULT_ENABLE([rombios], [Disable ROM BIOS])
|
||||
AX_ARG_DEFAULT_ENABLE([seabios], [Disable SeaBIOS])
|
||||
AX_ARG_DEFAULT_ENABLE([debug], [Disable debug build of tools])
|
||||
AX_ARG_DEFAULT_DISABLE([xend], [Enable xend toolstack])
|
||||
AX_ARG_DEFAULT_DISABLE([blktap1], [Enable blktap1 tools])
|
||||
|
||||
AC_ARG_ENABLE([qemu-traditional],
|
||||
@@ -245,15 +244,3 @@ AC_CHECK_HEADERS([yajl/yajl_version.h sys/eventfd.h])
|
||||
|
||||
AC_OUTPUT()
|
||||
|
||||
AS_IF([test "x$xend" = "xy" ], [
|
||||
AC_MSG_WARN(
|
||||
[You have enabled the xend toolstack.
|
||||
|
||||
xend is deprecated and scheduled for removal. Please migrate to another
|
||||
toolstack ASAP.
|
||||
|
||||
See http://wiki.xen.org/wiki/Choice_of_Toolstacks for information on
|
||||
other alternatives, including xl which is designed to be a drop in
|
||||
replacement for xm (http://wiki.xen.org/wiki/XL).
|
||||
])
|
||||
])
|
||||
@@ -5,18 +5,6 @@ include $(XEN_ROOT)/tools/Rules.mk
|
||||
XEN_READMES = README
|
||||
XEN_READMES += README.incompatibilities
|
||||
|
||||
XEN_CONFIGS-$(CONFIG_XEND) += xend-config.sxp
|
||||
XEN_CONFIGS-$(CONFIG_XEND) += xm-config.xml
|
||||
XEN_CONFIGS-$(CONFIG_XEND) += xmexample1
|
||||
XEN_CONFIGS-$(CONFIG_XEND) += xmexample2
|
||||
XEN_CONFIGS-$(CONFIG_XEND) += xmexample3
|
||||
XEN_CONFIGS-$(CONFIG_XEND) += xmexample.hvm
|
||||
XEN_CONFIGS-$(CONFIG_XEND) += xmexample.hvm-stubdom
|
||||
XEN_CONFIGS-$(CONFIG_XEND) += xmexample.pv-grub
|
||||
XEN_CONFIGS-$(CONFIG_XEND) += xmexample.nbd
|
||||
XEN_CONFIGS-$(CONFIG_XEND) += xend-pci-quirks.sxp
|
||||
XEN_CONFIGS-$(CONFIG_XEND) += xend-pci-permissive.sxp
|
||||
|
||||
XEN_CONFIGS += xlexample.hvm
|
||||
XEN_CONFIGS += xlexample.pvlinux
|
||||
XEN_CONFIGS += xl.conf
|
||||
|
||||
@@ -1,304 +0,0 @@
|
||||
# -*- sh -*-
|
||||
|
||||
#
|
||||
# Xend configuration file.
|
||||
#
|
||||
|
||||
# This example configuration is appropriate for an installation that
|
||||
# utilizes a bridged network configuration. Access to xend via http
|
||||
# is disabled.
|
||||
|
||||
# Commented out entries show the default for that entry, unless otherwise
|
||||
# specified.
|
||||
|
||||
#(logfile /var/log/xen/xend.log)
|
||||
#(loglevel DEBUG)
|
||||
|
||||
# Uncomment the line below. Set the value to flask, acm, or dummy to
|
||||
# select a security module.
|
||||
|
||||
#(xsm_module_name dummy)
|
||||
|
||||
# The Xen-API server configuration.
|
||||
#
|
||||
# This value configures the ports, interfaces, and access controls for the
|
||||
# Xen-API server. Each entry in the list starts with either unix, a port
|
||||
# number, or an address:port pair. If this is "unix", then a UDP socket is
|
||||
# opened, and this entry applies to that. If it is a port, then Xend will
|
||||
# listen on all interfaces on that TCP port, and if it is an address:port
|
||||
# pair, then Xend will listen on the specified port, using the interface with
|
||||
# the specified address.
|
||||
#
|
||||
# The subsequent string configures the user-based access control for the
|
||||
# listener in question. This can be one of "none" or "pam", indicating either
|
||||
# that users should be allowed access unconditionally, or that the local
|
||||
# Pluggable Authentication Modules configuration should be used. If this
|
||||
# string is missing or empty, then "pam" is used.
|
||||
#
|
||||
# The final string gives the host-based access control for that listener. If
|
||||
# this is missing or empty, then all connections are accepted. Otherwise,
|
||||
# this should be a space-separated sequence of regular expressions; any host
|
||||
# with a fully-qualified domain name or an IP address that matches one of
|
||||
# these regular expressions will be accepted.
|
||||
#
|
||||
# Example: listen on TCP port 9363 on all interfaces, accepting connections
|
||||
# only from machines in example.com or localhost, and allow access through
|
||||
# the unix domain socket unconditionally:
|
||||
#
|
||||
# (xen-api-server ((9363 pam '^localhost$ example\\.com$')
|
||||
# (unix none)))
|
||||
#
|
||||
# Optionally, the TCP Xen-API server can use SSL by specifying the private
|
||||
# key and certificate location:
|
||||
#
|
||||
# (9367 pam '' xen-api.key xen-api.crt)
|
||||
#
|
||||
# Default:
|
||||
# (xen-api-server ((unix)))
|
||||
|
||||
|
||||
#(xend-http-server no)
|
||||
#(xend-unix-server no)
|
||||
#(xend-tcp-xmlrpc-server no)
|
||||
#(xend-unix-xmlrpc-server yes)
|
||||
#(xend-relocation-server no)
|
||||
(xend-relocation-server yes)
|
||||
#(xend-relocation-ssl-server no)
|
||||
#(xend-udev-event-server no)
|
||||
|
||||
#(xend-unix-path /var/lib/xend/xend-socket)
|
||||
|
||||
|
||||
# Address and port xend should use for the legacy TCP XMLRPC interface,
|
||||
# if xend-tcp-xmlrpc-server is set.
|
||||
#(xend-tcp-xmlrpc-server-address 'localhost')
|
||||
#(xend-tcp-xmlrpc-server-port 8006)
|
||||
|
||||
# SSL key and certificate to use for the legacy TCP XMLRPC interface.
|
||||
# Setting these will mean that this port serves only SSL connections as
|
||||
# opposed to plaintext ones.
|
||||
#(xend-tcp-xmlrpc-server-ssl-key-file xmlrpc.key)
|
||||
#(xend-tcp-xmlrpc-server-ssl-cert-file xmlrpc.crt)
|
||||
|
||||
|
||||
# Port xend should use for the HTTP interface, if xend-http-server is set.
|
||||
#(xend-port 8000)
|
||||
|
||||
# Port xend should use for the relocation interface, if xend-relocation-server
|
||||
# is set.
|
||||
#(xend-relocation-port 8002)
|
||||
|
||||
# Port xend should use for the ssl relocation interface, if
|
||||
# xend-relocation-ssl-server is set.
|
||||
#(xend-relocation-ssl-port 8003)
|
||||
|
||||
# SSL key and certificate to use for the ssl relocation interface, if
|
||||
# xend-relocation-ssl-server is set.
|
||||
#(xend-relocation-server-ssl-key-file xmlrpc.key)
|
||||
#(xend-relocation-server-ssl-cert-file xmlrpc.crt)
|
||||
|
||||
# Whether to use ssl as default when relocating.
|
||||
#(xend-relocation-ssl no)
|
||||
|
||||
# Address xend should listen on for HTTP connections, if xend-http-server is
|
||||
# set.
|
||||
# Specifying 'localhost' prevents remote connections.
|
||||
# Specifying the empty string '' (the default) allows all connections.
|
||||
#(xend-address '')
|
||||
#(xend-address localhost)
|
||||
|
||||
# Address xend should listen on for relocation-socket connections, if
|
||||
# xend-relocation-server is set.
|
||||
# Meaning and default as for xend-address above.
|
||||
# Also, interface name is allowed (e.g. eth0) there to get the
|
||||
# relocation address to be bound on.
|
||||
#(xend-relocation-address '')
|
||||
|
||||
# The hosts allowed to talk to the relocation port. If this is empty (the
|
||||
# default), then all connections are allowed (assuming that the connection
|
||||
# arrives on a port and interface on which we are listening; see
|
||||
# xend-relocation-port and xend-relocation-address above). Otherwise, this
|
||||
# should be a space-separated sequence of regular expressions. Any host with
|
||||
# a fully-qualified domain name or an IP address that matches one of these
|
||||
# regular expressions will be accepted.
|
||||
#
|
||||
# For example:
|
||||
# (xend-relocation-hosts-allow '^localhost$ ^.*\\.example\\.org$')
|
||||
#
|
||||
#(xend-relocation-hosts-allow '')
|
||||
(xend-relocation-hosts-allow '^localhost$ ^localhost\\.localdomain$')
|
||||
|
||||
# The limit (in kilobytes) on the size of the console buffer
|
||||
#(console-limit 1024)
|
||||
|
||||
##
|
||||
# To bridge network traffic, like this:
|
||||
#
|
||||
# dom0: ----------------- bridge -> real eth0 -> the network
|
||||
# |
|
||||
# domU: fake eth0 -> vifN.0 -+
|
||||
#
|
||||
# use
|
||||
#
|
||||
# (network-script network-bridge)
|
||||
#
|
||||
# Your default ethernet device is used as the outgoing interface, by default.
|
||||
# To use a different one (e.g. eth1) use
|
||||
#
|
||||
# (network-script 'network-bridge netdev=eth1')
|
||||
#
|
||||
# The bridge is named eth0, by default (yes, really!)
|
||||
#
|
||||
|
||||
# It is normally much better to create the bridge yourself in
|
||||
# /etc/network/interfaces. network-bridge start does nothing if you
|
||||
# already have a bridge, and network-bridge stop does nothing if the
|
||||
# default bridge name (normally eth0) is not a bridge. See
|
||||
# bridge-utils-interfaces(5) for full information on the syntax in
|
||||
# /etc/network/interfaces, but you probably want something like this:
|
||||
# iface xenbr0 inet static
|
||||
# address [etc]
|
||||
# netmask [etc]
|
||||
# [etc]
|
||||
# bridge_ports eth0
|
||||
#
|
||||
# To have network-bridge create a differently-named bridge, use:
|
||||
# (network-script 'network-bridge bridge=<name>')
|
||||
#
|
||||
# It is possible to use the network-bridge script in more complicated
|
||||
# scenarios, such as having two outgoing interfaces, with two bridges, and
|
||||
# two fake interfaces per guest domain. To do things like this, write
|
||||
# yourself a wrapper script, and call network-bridge from it, as appropriate.
|
||||
#
|
||||
(network-script network-bridge)
|
||||
|
||||
# The script used to control virtual interfaces. This can be overridden on a
|
||||
# per-vif basis when creating a domain or a configuring a new vif. The
|
||||
# vif-bridge script is designed for use with the network-bridge script, or
|
||||
# similar configurations.
|
||||
#
|
||||
# If you have overridden the bridge name using
|
||||
# (network-script 'network-bridge bridge=<name>') then you may wish to do the
|
||||
# same here. The bridge name can also be set when creating a domain or
|
||||
# configuring a new vif, but a value specified here would act as a default.
|
||||
#
|
||||
# If you are using only one bridge, the vif-bridge script will discover that,
|
||||
# so there is no need to specify it explicitly. The default is to use
|
||||
# the bridge which is listed first in the output from brctl.
|
||||
#
|
||||
(vif-script vif-bridge)
|
||||
|
||||
|
||||
## Use the following if network traffic is routed, as an alternative to the
|
||||
# settings for bridged networking given above.
|
||||
#(network-script network-route)
|
||||
#(vif-script vif-route)
|
||||
|
||||
|
||||
## Use the following if network traffic is routed with NAT, as an alternative
|
||||
# to the settings for bridged networking given above.
|
||||
#(network-script network-nat)
|
||||
#(vif-script vif-nat)
|
||||
|
||||
# dom0-min-mem is the lowest permissible memory level (in MB) for dom0.
|
||||
# This is a minimum both for auto-ballooning (as enabled by
|
||||
# enable-dom0-ballooning below) and for xm mem-set when applied to dom0.
|
||||
(dom0-min-mem 196)
|
||||
|
||||
# Whether to enable auto-ballooning of dom0 to allow domUs to be created.
|
||||
# If enable-dom0-ballooning = no, dom0 will never balloon out.
|
||||
(enable-dom0-ballooning yes)
|
||||
|
||||
# 32-bit paravirtual domains can only consume physical
|
||||
# memory below 168GB. On systems with memory beyond that address,
|
||||
# they'll be confined to memory below 128GB.
|
||||
# Using total_available_memory (in GB) to specify the amount of memory reserved
|
||||
# in the memory pool exclusively for 32-bit paravirtual domains.
|
||||
# Additionally you should use dom0_mem = <-Value> as a parameter in
|
||||
# xen kernel to reserve the memory for 32-bit paravirtual domains, default
|
||||
# is "0" (0GB).
|
||||
(total_available_memory 0)
|
||||
|
||||
# In SMP system, dom0 will use dom0-cpus # of CPUS
|
||||
# If dom0-cpus = 0, dom0 will take all cpus available
|
||||
(dom0-cpus 0)
|
||||
|
||||
# Whether to enable core-dumps when domains crash.
|
||||
#(enable-dump no)
|
||||
|
||||
# The tool used for initiating virtual TPM migration
|
||||
#(external-migration-tool '')
|
||||
|
||||
# The interface for VNC servers to listen on. Defaults
|
||||
# to 127.0.0.1 To restore old 'listen everywhere' behaviour
|
||||
# set this to 0.0.0.0
|
||||
#(vnc-listen '127.0.0.1')
|
||||
|
||||
# The default password for VNC console on HVM domain.
|
||||
# Empty string is no authentication.
|
||||
(vncpasswd '')
|
||||
|
||||
# The VNC server can be told to negotiate a TLS session
|
||||
# to encryption all traffic, and provide x509 cert to
|
||||
# clients enabling them to verify server identity. The
|
||||
# GTK-VNC widget, virt-viewer, virt-manager and VeNCrypt
|
||||
# all support the VNC extension for TLS used in QEMU. The
|
||||
# TightVNC/RealVNC/UltraVNC clients do not.
|
||||
#
|
||||
# To enable this create x509 certificates / keys in the
|
||||
# directory ${XEN_CONFIG_DIR} + vnc
|
||||
#
|
||||
# ca-cert.pem - The CA certificate
|
||||
# server-cert.pem - The Server certificate signed by the CA
|
||||
# server-key.pem - The server private key
|
||||
#
|
||||
# and then uncomment this next line
|
||||
# (vnc-tls 1)
|
||||
|
||||
# The certificate dir can be pointed elsewhere..
|
||||
#
|
||||
# (vnc-x509-cert-dir vnc)
|
||||
|
||||
# The server can be told to request & validate an x509
|
||||
# certificate from the client. Only clients with a cert
|
||||
# signed by the trusted CA will be able to connect. This
|
||||
# is more secure the password auth alone. Passwd auth can
|
||||
# used at the same time if desired. To enable client cert
|
||||
# checking uncomment this:
|
||||
#
|
||||
# (vnc-x509-verify 1)
|
||||
|
||||
# The default keymap to use for the VM's virtual keyboard
|
||||
# when not specififed in VM's configuration
|
||||
#(keymap 'en-us')
|
||||
|
||||
# Script to run when the label of a resource has changed.
|
||||
#(resource-label-change-script '')
|
||||
|
||||
# Rotation count of qemu-dm log file.
|
||||
#(qemu-dm-logrotate-count 10)
|
||||
|
||||
# Path where persistent domain configuration is stored.
|
||||
# Default is /var/lib/xend/domains/
|
||||
#(xend-domains-path /var/lib/xend/domains)
|
||||
|
||||
# Number of seconds xend will wait for device creation and
|
||||
# destruction
|
||||
#(device-create-timeout 100)
|
||||
#(device-destroy-timeout 100)
|
||||
|
||||
# When assigning device to HVM guest, we use the strict check for HVM guest by
|
||||
# default. (For PV guest, we use loose check automatically if necessary.)
|
||||
# When we assign device to HVM guest, if we meet with the co-assignment
|
||||
# issues or the ACS issue, we could try changing the option to 'no' -- however,
|
||||
# we have to realize this may incur security issue and we can't make sure the
|
||||
# device assignment could really work properly even after we do this.
|
||||
#(pci-passthrough-strict-check yes)
|
||||
|
||||
# If we have a very big scsi device configuration, start of xend is slow,
|
||||
# because xend scans all the device paths to build its internal PSCSI device
|
||||
# list. If we need only a few devices for assigning to a guest, we can reduce
|
||||
# the scan to this device. Set list list of device paths in same syntax like in
|
||||
# command lsscsi, e.g. ('16:0:0:0' '15:0')
|
||||
# (pscsi-device-mask ('*'))
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
###############################################################################
|
||||
# Configuration file for granting quiry PCI devices full write access to their
|
||||
# configuration space. This file should only be used when you are unable to
|
||||
# determine the exact registers required by your device. Even so, it should
|
||||
# be used only temporarily.
|
||||
#
|
||||
# SEND A MESSAGE TO xen-devel@lists.xensource.com IF YOU USE THIS FILE.
|
||||
#
|
||||
# Using this file should NOT be necessary. If you must use it to make some
|
||||
# device work, send a message to the above list with as much information about
|
||||
# your device as possible so the developers can make accomodations for it.
|
||||
# Once developers make the necessary updates you can remove the corresponding
|
||||
# entry for your device.
|
||||
###############################################################################
|
||||
# Entries are formated as follows: <vendor>:<device>[:<subvendor>:<subdevice>]
|
||||
#
|
||||
# Example: Appending to an existing list
|
||||
#
|
||||
# (unconstrained_dev_ids
|
||||
# ('XXXX:XXXX:XXXX:XXXX' # existing entry
|
||||
# 'YYYY:YYYY:YYYY:YYYY' # new entry 1
|
||||
# 'ZZZZ:ZZZZ') # new entry 2
|
||||
# )
|
||||
###############################################################################
|
||||
(unconstrained_dev_ids
|
||||
#('0123:4567:89AB:CDEF')
|
||||
)
|
||||
@@ -1,96 +0,0 @@
|
||||
###############################################################################
|
||||
# Configuration file for quirky PCI devices that require write-access to
|
||||
# parts of the configuration space. Use this file to specific PCI device
|
||||
# IDs and the configuration space fields to which those devices must be
|
||||
# able to write.
|
||||
#
|
||||
# Length is important, so be sure to match new entries with the
|
||||
# lengths of comparable existing entries.
|
||||
#
|
||||
# Additions to this file take effect as soon as a new domain with a
|
||||
# matching device is started. However, to remove a field that was
|
||||
# previously applied to a device you must unbind the device from
|
||||
# pciback.
|
||||
###############################################################################
|
||||
# This is a bogus entry to show how a new device would be added to the list
|
||||
#
|
||||
# (new_quirky_dev_name
|
||||
# (pci_ids
|
||||
# ('0123:4567:890A:BCEF')
|
||||
# )
|
||||
#
|
||||
# (pci_config_space_fields
|
||||
# ('12345678:1:00000000')
|
||||
# )
|
||||
# )
|
||||
###############################################################################
|
||||
|
||||
(tg3
|
||||
(pci_ids
|
||||
# Entries are formated as follows:
|
||||
# <vendor>:<device>[:<subvendor>:<subdevice>]
|
||||
('14e4:1644' # Broadcom Tigon3 5700
|
||||
'14e4:1645' # Broadcom Tigon3 5701
|
||||
'14e4:1646' # Broadcom Tigon3 5702
|
||||
'14e4:1647' # Broadcom Tigon3 5703
|
||||
'14e4:1648' # Broadcom Tigon3 5704
|
||||
'14e4:164d' # Broadcom Tigon3 5702FE
|
||||
'14e4:1653' # Broadcom Tigon3 5705
|
||||
'14e4:1654' # Broadcom Tigon3 5705_2
|
||||
'14e4:165d' # Broadcom Tigon3 5705M
|
||||
'14e4:165e' # Broadcom Tigon3 5705M_2
|
||||
'14e4:16a6' # Broadcom Tigon3 5702X
|
||||
'14e4:16a7' # Broadcom Tigon3 5703X
|
||||
'14e4:16a8' # Broadcom Tigon3 5704S
|
||||
'14e4:16c6' # Broadcom Tigon3 5702A3
|
||||
'14e4:16c7' # Broadcom Tigon3 5703A3
|
||||
'14e4:1696' # Broadcom Tigon3 5782
|
||||
'14e4:169c' # Broadcom Tigon3 5788
|
||||
'14e4:169d' # Broadcom Tigon3 5789
|
||||
'14e4:170d' # Broadcom Tigon3 5901
|
||||
'14e4:1649' # Broadcom Tigon3 5704S_2
|
||||
'14e4:166e' # Broadcom Tigon3 5705F
|
||||
'14e4:1658' # Broadcom Tigon3 5720
|
||||
'14e4:1659' # Broadcom Tigon3 5721
|
||||
'14e4:1676' # Broadcom Tigon3 5750
|
||||
'14e4:1677' # Broadcom Tigon3 5751
|
||||
'14e4:167c' # Broadcom Tigon3 5750M
|
||||
'14e4:167d' # Broadcom Tigon3 5751M
|
||||
'14e4:167e' # Broadcom Tigon3 5751F
|
||||
'14e4:1600' # Broadcom Tigon3 5752
|
||||
'14e4:1601' # Broadcom Tigon3 5752M
|
||||
'14e4:16f7' # Broadcom Tigon3 5753
|
||||
'14e4:16fd' # Broadcom Tigon3 5753M
|
||||
'14e4:16fe' # Broadcom Tigon3 5753F
|
||||
'14e4:1668' # Broadcom Tigon3 5714
|
||||
'14e4:1678' # Broadcom Tigon3 5715
|
||||
'14e4:166a' # Broadcom Tigon3 5780
|
||||
'14e4:166b' # Broadcom Tigon3 5780S
|
||||
'14e4:16dd' # Broadcom Tigon3 5781
|
||||
'1148:4400' # Syskonnect 9DXX
|
||||
'1148:4500' # Syskonnect 9MXX
|
||||
'173b:03e8' # Altima AC1000
|
||||
'173b:03e9' # Altima AC1001
|
||||
'173b:03eb' # Altima AC1003
|
||||
'173b:03ea' # Altima AC9100
|
||||
'106b:1645') # Apple Tigon3
|
||||
)
|
||||
|
||||
(pci_config_space_fields
|
||||
# Entries are formated as follows:
|
||||
# <register>:<size>:<mask>
|
||||
# size is measured in bytes (1,2,4 are valid sizes)
|
||||
# mask is currently unused; use all zero's
|
||||
('00000078:4:00000000' # TG3PCI_REG_BASE_ADDR
|
||||
'0000007c:4:00000000' # TG3PCI_MEM_WIN_BASE_ADDR
|
||||
'00000080:4:00000000' # TG3PCI_REG_DATA
|
||||
'00000084:4:00000000' # TG3PCI_MEM_WIN_DATA
|
||||
'00000090:4:00000000' # TG3PCI_MISC_LOCAL_CTRL
|
||||
'00000068:4:00000000' # TG3PCI_MISC_HOST_CTRL
|
||||
'0000009C:4:00000000' # TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_LOW
|
||||
'00000098:4:00000000' # TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_HIGH
|
||||
'000000a4:4:00000000' # TG3PCI_RCV_RET_RING_CON_IDX + TG3_64BIT_REG_LOW
|
||||
'000000a0:4:00000000' # TG3PCI_RCV_RET_RING_CON_IDX + TG3_64BIT_REG_HIGH
|
||||
'00000070:4:00000000') # TG3PCI_PCISTATE
|
||||
)
|
||||
)
|
||||
@@ -1,45 +0,0 @@
|
||||
<!--
|
||||
|
||||
Copyright (C) 2006 XenSource Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
-->
|
||||
|
||||
<!--
|
||||
|
||||
This is a configuration file for xm; it should be placed in
|
||||
/etc/xen/xm-config.xml. If this file is missing, then xm will fall back to
|
||||
the normal behaviour that's in Xen 3.0.4 and below. The settings here are
|
||||
most useful for experimenting with the Xen-API preview in Xen 3.0.4.
|
||||
|
||||
-->
|
||||
|
||||
<xm>
|
||||
<!-- The server element describes how to talk to Xend. The type may be
|
||||
Xen-API or LegacyXMLRPC (the default). The URI is that of the
|
||||
server; you might try http://server:9363/ or
|
||||
httpu:///var/run/xend/xen-api.sock for the Xen-API, or
|
||||
httpu:///var/run/xend/xmlrpc.sock for the legacy server.
|
||||
|
||||
The username and password attributes will be used to log in if Xen-API
|
||||
is being used.
|
||||
-->
|
||||
<!--
|
||||
<server type='Xen-API'
|
||||
uri='http://localhost:9363/'
|
||||
username='me'
|
||||
password='mypassword' />
|
||||
-->
|
||||
</xm>
|
||||
@@ -1,373 +0,0 @@
|
||||
# -*- mode: python; -*-
|
||||
#============================================================================
|
||||
# Python configuration setup for 'xm create'.
|
||||
# This script sets the parameters used when a domain is created using 'xm create'.
|
||||
# You use a separate script for each domain you want to create, or
|
||||
# you can set the parameters for the domain on the xm command line.
|
||||
#============================================================================
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Kernel image file.
|
||||
kernel = "hvmloader"
|
||||
|
||||
# The domain build function. HVM domain uses 'hvm'.
|
||||
builder='hvm'
|
||||
|
||||
# Initial memory allocation (in megabytes) for the new domain.
|
||||
#
|
||||
# WARNING: Creating a domain with insufficient memory may cause out of
|
||||
# memory errors. The domain needs enough memory to boot kernel
|
||||
# and modules. Allocating less than 32MBs is not recommended.
|
||||
memory = 128
|
||||
|
||||
# Shadow pagetable memory for the domain, in MB.
|
||||
# If not explicictly set, xend will pick an appropriate value.
|
||||
# Should be at least 2KB per MB of domain memory, plus a few MB per vcpu.
|
||||
# shadow_memory = 8
|
||||
|
||||
# Whether to transparently share this domain's memory with other domains.
|
||||
# default = 0
|
||||
# memory_sharing = 0
|
||||
|
||||
# A name for your domain. All domains must have different names.
|
||||
name = "ExampleHVMDomain"
|
||||
|
||||
# 128-bit UUID for the domain. The default behavior is to generate a new UUID
|
||||
# on each call to 'xm create'.
|
||||
#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9"
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# The number of cpus guest platform has, default=1
|
||||
#vcpus=1
|
||||
|
||||
# Enable/disable HVM guest PAE, default=1 (enabled)
|
||||
#pae=1
|
||||
|
||||
# Enable/disable HVM guest ACPI, default=1 (enabled)
|
||||
#acpi=1
|
||||
|
||||
# Enable/disable HVM APIC mode, default=1 (enabled)
|
||||
# Note that this option is ignored if vcpus > 1
|
||||
#apic=1
|
||||
|
||||
# Enable/disable extended power management support within HVM guest, i.e., beyond
|
||||
# S3, S4, S5 within guest like exposing battery meter.
|
||||
# 0 (default option, extended power management support disabled)
|
||||
# 1 (pass-through mode; uses pass-through as needed; efficient but limited in scope)
|
||||
# 2 (non pass-through mode; extended scope, likely to work on all applicable environment
|
||||
# but comparitively less efficient than pass-through mode)
|
||||
# xen_extended_power_mgmt=0
|
||||
|
||||
# List of which CPUS this domain is allowed to use, default Xen picks
|
||||
#cpus = "" # leave to Xen to pick
|
||||
#cpus = "0" # all vcpus run on CPU0
|
||||
#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5
|
||||
#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3
|
||||
|
||||
# Optionally define mac and/or bridge for the network interfaces.
|
||||
# Random MACs are assigned if not given.
|
||||
#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0, model=ne2k_pci' ]
|
||||
# type=ioemu specify the NIC is an ioemu device not netfront
|
||||
vif = [ 'type=ioemu, bridge=xenbr0' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define the disk devices you want the domain to have access to, and
|
||||
# what you want them accessible as.
|
||||
# Each disk entry is of the form phy:UNAME,DEV,MODE
|
||||
# where UNAME is the device, DEV is the device name the domain will see,
|
||||
# and MODE is r for read-only, w for read-write.
|
||||
|
||||
#disk = [ 'phy:hda1,hda1,r' ]
|
||||
disk = [ 'file:/var/images/min-el3-i386.img,hda,w', ',hdc:cdrom,r' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Configure the behaviour when a domain exits. There are three 'reasons'
|
||||
# for a domain to stop: poweroff, reboot, and crash. For each of these you
|
||||
# may specify:
|
||||
#
|
||||
# "destroy", meaning that the domain is cleaned up as normal;
|
||||
# "restart", meaning that a new domain is started in place of the old
|
||||
# one;
|
||||
# "preserve", meaning that no clean-up is done until the domain is
|
||||
# manually destroyed (using xm destroy, for example); or
|
||||
# "rename-restart", meaning that the old domain is not cleaned up, but is
|
||||
# renamed and a new domain started in its place.
|
||||
#
|
||||
# In the event a domain stops due to a crash, you have the additional options:
|
||||
#
|
||||
# "coredump-destroy", meaning dump the crashed domain's core and then destroy;
|
||||
# "coredump-restart', meaning dump the crashed domain's core and the restart.
|
||||
#
|
||||
# The default is
|
||||
#
|
||||
# on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# For backwards compatibility we also support the deprecated option restart
|
||||
#
|
||||
# restart = 'onreboot' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'destroy'
|
||||
#
|
||||
# restart = 'always' means on_poweroff = 'restart'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# restart = 'never' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'destroy'
|
||||
# on_crash = 'destroy'
|
||||
|
||||
#on_poweroff = 'destroy'
|
||||
#on_reboot = 'restart'
|
||||
#on_crash = 'restart'
|
||||
|
||||
#============================================================================
|
||||
|
||||
# Device Model to be used
|
||||
device_model = 'qemu-dm'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# boot on floppy (a), hard disk (c), Network (n) or CD-ROM (d)
|
||||
# default: hard disk, cd-rom, floppy
|
||||
#boot="cda"
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# write to temporary files instead of disk image files
|
||||
#snapshot=1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable SDL library for graphics, default = 0
|
||||
sdl=0
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable OpenGL for texture rendering inside the SDL window, default = 1
|
||||
# valid only if sdl is enabled.
|
||||
opengl=1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable VNC library for graphics, default = 1
|
||||
vnc=1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# address that should be listened on for the VNC server if vnc is set.
|
||||
# default is to use 'vnc-listen' setting from
|
||||
# auxbin.xen_configdir() + /xend-config.sxp
|
||||
#vnclisten="127.0.0.1"
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# set VNC display number, default = domid
|
||||
#vncdisplay=1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# try to find an unused port for the VNC server, default = 1
|
||||
#vncunused=1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# set password for domain's VNC console
|
||||
# default is depents on vncpasswd in xend-config.sxp
|
||||
vncpasswd=''
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# no graphics, use serial port
|
||||
#nographic=0
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable stdvga, default = 0 (use cirrus logic device model)
|
||||
stdvga=0
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# serial port re-direct to pty deivce, /dev/pts/n
|
||||
# then xm console or minicom can connect
|
||||
serial='pty'
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# tsc_mode : TSC mode (0=default, 1=native TSC, 2=never emulate, 3=pvrdtscp)
|
||||
# emulate TSC provides synced TSC for all vcpus, but lose perfomrance.
|
||||
# native TSC leverages hardware's TSC(no perf loss), but vcpu's TSC may lose
|
||||
# sync due to hardware's unreliable/unsynced TSC between CPUs.
|
||||
# default intelligently uses native TSC on machines where it is safe, but
|
||||
# switches to emulated if necessary after save/restore/migration
|
||||
# pvrdtscp is for intelligent apps that use special Xen-only paravirtualized
|
||||
# cpuid instructions to obtain offset/scaling/migration info and maximize
|
||||
# performance within pools of machines that support the rdtscp instruction
|
||||
tsc_mode=0
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Qemu Monitor, default is disable
|
||||
# Use ctrl-alt-2 to connect
|
||||
#monitor=1
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# enable sound card support, [sb16|es1370|all|..,..], default none
|
||||
#soundhw='sb16'
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# set the real time clock to local time [default=0 i.e. set to utc]
|
||||
#localtime=1
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# set the real time clock offset in seconds [default=0 i.e. same as dom0]
|
||||
#rtc_timeoffset=3600
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# start in full screen
|
||||
#full-screen=1
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Enable USB support (specific devices specified at runtime through the
|
||||
# monitor window)
|
||||
#usb=1
|
||||
|
||||
# Enable USB mouse support (only enable one of the following, `mouse' for
|
||||
# PS/2 protocol relative mouse, `tablet' for
|
||||
# absolute mouse)
|
||||
#usbdevice='mouse'
|
||||
#usbdevice='tablet'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Set keyboard layout, default is en-us keyboard.
|
||||
#keymap='ja'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Enable/disable xen platform PCI device, default=1 (enabled)
|
||||
#xen_platform_pci=1
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure guest CPUID responses:
|
||||
#
|
||||
#cpuid=[ '1:ecx=xxxxxxxxxxx00xxxxxxxxxxxxxxxxxxx,
|
||||
# eax=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ]
|
||||
# - Unset the SSE4 features (CPUID.1[ECX][20-19])
|
||||
# - Default behaviour for all other bits in ECX And EAX registers.
|
||||
#
|
||||
# Each successive character represent a lesser-significant bit:
|
||||
# '1' -> force the corresponding bit to 1
|
||||
# '0' -> force to 0
|
||||
# 'x' -> Get a safe value (pass through and mask with the default policy)
|
||||
# 'k' -> pass through the host bit value
|
||||
# 's' -> as 'k' but preserve across save/restore and migration
|
||||
#
|
||||
# Expose to the guest multi-core cpu instead of multiple processors
|
||||
# Example for intel, expose a 8-core processor :
|
||||
#cpuid=['1:edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
||||
# ebx=xxxxxxxx00010000xxxxxxxxxxxxxxxx',
|
||||
# '4,0:eax=001111xxxxxxxxxxxxxxxxxxxxxxxxxx']
|
||||
# - CPUID.1[EDX][HT] : Enable HT
|
||||
# - CPUID.1[EBX] : Number of vcpus * 2
|
||||
# - CPUID.4,0[EAX] : Number of vcpus * 2 - 1
|
||||
#vcpus=8
|
||||
#
|
||||
# Example for amd, expose a 5-core processor :
|
||||
# cpuid = ['1:ebx=xxxxxxxx00001010xxxxxxxxxxxxxxxx,
|
||||
# edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx',
|
||||
# '0x80000001:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1x',
|
||||
# '0x80000008:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx001001']
|
||||
# - CPUID.1[EBX] : Threads per Core * Cores per Socket (2 * #vcpus)
|
||||
# - CPUID.1[EDX][HT] : Enable HT
|
||||
# - CPUID.0x80000001[CmpLegacy] : Use legacy method
|
||||
# - CPUID.0x80000008[ECX] : #vcpus * 2 - 1
|
||||
#vcpus=5
|
||||
#
|
||||
# Downgrade the cpuid to make a better compatibility for migration :
|
||||
# Look like a generic 686 :
|
||||
# cpuid = [ '0:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0',
|
||||
# '1:eax=0x06b1,
|
||||
# ecx=xxxxxxxxxxx0000xx00xxx0000000xx0,
|
||||
# edx=xxx00000xxxxxxx0xxxxxxxxx0xxxxxx',
|
||||
# '4:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0',
|
||||
# '0x80000000:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0']
|
||||
# with the highest leaf
|
||||
# - CPUID.0[EAX] : Set the highest leaf
|
||||
# - CPUID.1[EAX] : 686
|
||||
# - CPUID.1[ECX] : Mask some features
|
||||
# - CPUID.1[EDX] : Mask some features
|
||||
# - CPUID.4 : Reply like the highest leaf, in our case CPUID.3
|
||||
# - CPUID.0x80000000 : No extension we are on a Pentium III, reply like the
|
||||
# highest leaf (CPUID.3).
|
||||
#
|
||||
# Configure host CPUID consistency checks, which must be satisfied for this
|
||||
# VM to be allowed to run on this host's processor type:
|
||||
#cpuid_check=[ '1:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx1xxxxx' ]
|
||||
# - Host must have VMX feature flag set
|
||||
#
|
||||
# The format is similar to the above for 'cpuid':
|
||||
# '1' -> the bit must be '1'
|
||||
# '0' -> the bit must be '0'
|
||||
# 'x' -> we don't care (do not check)
|
||||
# 's' -> the bit must be the same as on the host that started this VM
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure passthrough PCI{,-X,e} devices:
|
||||
#
|
||||
# pci=[ '[SSSS:]BB:DD.F[,option1[,option2[...]]]', ... ]
|
||||
#
|
||||
# [SSSS]:BB:DD.F "bus segment:bus:device.function"(1) of the device to
|
||||
# be assigned, bus segment is optional. All fields are
|
||||
# in hexadecimal and no field should be longer than that
|
||||
# as shown in the pattern. Successful assignment may need
|
||||
# certain hardware support and additional configurations
|
||||
# (e.g. VT-d, see docs/misc/vtd.txt for more details).
|
||||
#
|
||||
# (1) bus segment is sometimes also referred to as the PCI "domain",
|
||||
# not to be confused with Xen domain.
|
||||
#
|
||||
#
|
||||
# optionN per-device options in "key=val" format. Current
|
||||
# available options are:
|
||||
# - msitranslate=0|1
|
||||
# per-device overriden of pci_msitranslate, see below
|
||||
# - power_mgmt=0|1
|
||||
# per-device overriden of pci_power_mgmt, see below
|
||||
#
|
||||
#pci=[ '07:00.0', '07:00.1' ]
|
||||
|
||||
# MSI-INTx translation for MSI capable devices:
|
||||
#
|
||||
# If it's set, Xen will enable MSI for the device that supports it even
|
||||
# if the guest don't use MSI. In the case, an IO-APIC type interrupt will
|
||||
# be injected to the guest every time a corresponding MSI message is
|
||||
# received.
|
||||
# If the guest enables MSI or MSI-X, the translation is automatically
|
||||
# turned off.
|
||||
#
|
||||
#pci_msitranslate=1
|
||||
|
||||
# PCI Power Management:
|
||||
#
|
||||
# If it's set, the guest OS will be able to program D0-D3hot states of the
|
||||
# PCI device for the purpose of low power consumption.
|
||||
#
|
||||
#pci_power_mgmt=0
|
||||
|
||||
# Enable graphics passthrough:
|
||||
#
|
||||
# If it's set, and specify graphics device BDF in pci passthrough option,
|
||||
# like pci=['xx:xx.x'], it enables graphics passthrough, default=0 (disabled)
|
||||
#gfx_passthru=0
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure PVSCSI devices:
|
||||
#
|
||||
#vscsi=[ 'PDEV, VDEV' ]
|
||||
#
|
||||
# PDEV gives physical SCSI device to be attached to specified guest
|
||||
# domain by one of the following identifier format.
|
||||
# - XX:XX:XX:XX (4-tuples with decimal notation which shows
|
||||
# "host:channel:target:lun")
|
||||
# - /dev/sdxx or sdx
|
||||
# - /dev/stxx or stx
|
||||
# - /dev/sgxx or sgx
|
||||
# - result of 'scsi_id -gu -s'.
|
||||
# ex. # scsi_id -gu -s /block/sdb
|
||||
# 36000b5d0006a0000006a0257004c0000
|
||||
#
|
||||
# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as
|
||||
# which the specified guest domain recognize.
|
||||
#
|
||||
|
||||
#vscsi = [ '/dev/sdx, 0:0:0:0' ]
|
||||
@@ -1,317 +0,0 @@
|
||||
# -*- mode: python; -*-
|
||||
#============================================================================
|
||||
# Python configuration setup for 'xm create'.
|
||||
# This script sets the parameters used when a domain is created using 'xm create'.
|
||||
# You use a separate script for each domain you want to create, or
|
||||
# you can set the parameters for the domain on the xm command line.
|
||||
#============================================================================
|
||||
#
|
||||
# This is a version using a stubdomain for device model
|
||||
# The differences with xmexample.hvm are marked with "STUBDOM"
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Kernel image file.
|
||||
kernel = "hvmloader"
|
||||
|
||||
# The domain build function. HVM domain uses 'hvm'.
|
||||
builder='hvm'
|
||||
|
||||
# Initial memory allocation (in megabytes) for the new domain.
|
||||
#
|
||||
# WARNING: Creating a domain with insufficient memory may cause out of
|
||||
# memory errors. The domain needs enough memory to boot kernel
|
||||
# and modules. Allocating less than 32MBs is not recommended.
|
||||
memory = 128
|
||||
|
||||
# Shadow pagetable memory for the domain, in MB.
|
||||
# If not explicictly set, xend will pick an appropriate value.
|
||||
# Should be at least 2KB per MB of domain memory, plus a few MB per vcpu.
|
||||
# shadow_memory = 8
|
||||
|
||||
# A name for your domain. All domains must have different names.
|
||||
name = "xmexample.hvm"
|
||||
|
||||
# 128-bit UUID for the domain. The default behavior is to generate a new UUID
|
||||
# on each call to 'xm create'.
|
||||
#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9"
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# The number of cpus guest platform has, default=1
|
||||
#vcpus=1
|
||||
|
||||
# Enable/disable HVM guest PAE, default=1 (enabled)
|
||||
#pae=1
|
||||
|
||||
# Enable/disable HVM guest ACPI, default=1 (enabled)
|
||||
#acpi=1
|
||||
|
||||
# Enable/disable HVM APIC mode, default=1 (enabled)
|
||||
# Note that this option is ignored if vcpus > 1
|
||||
#apic=1
|
||||
|
||||
# List of which CPUS this domain is allowed to use, default Xen picks
|
||||
#cpus = "" # leave to Xen to pick
|
||||
#cpus = "0" # all vcpus run on CPU0
|
||||
#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5
|
||||
#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3
|
||||
|
||||
# Optionally define mac and/or bridge for the network interfaces.
|
||||
# Random MACs are assigned if not given.
|
||||
#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0, model=ne2k_pci' ]
|
||||
# type=ioemu specify the NIC is an ioemu device not netfront
|
||||
vif = [ 'type=ioemu, bridge=xenbr0' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define the disk devices you want the domain to have access to, and
|
||||
# what you want them accessible as.
|
||||
# Each disk entry is of the form phy:UNAME,DEV,MODE
|
||||
# where UNAME is the device, DEV is the device name the domain will see,
|
||||
# and MODE is r for read-only, w for read-write.
|
||||
|
||||
disk = [ 'file:/var/images/min-el3-i386.img,hda,w', 'phy:/dev/cdrom,hdc:cdrom,r' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Configure the behaviour when a domain exits. There are three 'reasons'
|
||||
# for a domain to stop: poweroff, reboot, and crash. For each of these you
|
||||
# may specify:
|
||||
#
|
||||
# "destroy", meaning that the domain is cleaned up as normal;
|
||||
# "restart", meaning that a new domain is started in place of the old
|
||||
# one;
|
||||
# "preserve", meaning that no clean-up is done until the domain is
|
||||
# manually destroyed (using xm destroy, for example); or
|
||||
# "rename-restart", meaning that the old domain is not cleaned up, but is
|
||||
# renamed and a new domain started in its place.
|
||||
#
|
||||
# In the event a domain stops due to a crash, you have the additional options:
|
||||
#
|
||||
# "coredump-destroy", meaning dump the crashed domain's core and then destroy;
|
||||
# "coredump-restart', meaning dump the crashed domain's core and the restart.
|
||||
#
|
||||
# The default is
|
||||
#
|
||||
# on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# For backwards compatibility we also support the deprecated option restart
|
||||
#
|
||||
# restart = 'onreboot' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'destroy'
|
||||
#
|
||||
# restart = 'always' means on_poweroff = 'restart'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# restart = 'never' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'destroy'
|
||||
# on_crash = 'destroy'
|
||||
|
||||
#on_poweroff = 'destroy'
|
||||
#on_reboot = 'restart'
|
||||
#on_crash = 'restart'
|
||||
|
||||
#============================================================================
|
||||
|
||||
# Device Model to be used
|
||||
#
|
||||
# STUBDOM: this is a script that creates the stub domain running the device
|
||||
# model
|
||||
device_model = 'stubdom-dm'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# boot on floppy (a), hard disk (c), Network (n) or CD-ROM (d)
|
||||
# default: hard disk, cd-rom, floppy
|
||||
boot="cda"
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# write to temporary files instead of disk image files
|
||||
#snapshot=1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable SDL library for graphics, default = 0
|
||||
#
|
||||
sdl=0
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable OpenGL for texture rendering inside the SDL window, default = 1
|
||||
# valid only if sdl is enabled.
|
||||
#
|
||||
opengl=1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable VNC library for graphics, default = 1
|
||||
vnc=1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# address that should be listened on for the VNC server if vnc is set.
|
||||
# default is to use 'vnc-listen' setting from
|
||||
# auxbin.xen_configdir() + /xend-config.sxp
|
||||
#vnclisten="127.0.0.1"
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# set VNC display number, default = domid
|
||||
#vncdisplay=1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# try to find an unused port for the VNC server, default = 1
|
||||
#vncunused=1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable spawning vncviewer for domain's console
|
||||
# (only valid when vnc=1), default = 0
|
||||
#vncconsole=0
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# set password for domain's VNC console
|
||||
# default is depents on vncpasswd in xend-config.sxp
|
||||
vncpasswd=''
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# no graphics, use serial port
|
||||
#nographic=0
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable stdvga, default = 0 (use cirrus logic device model)
|
||||
stdvga=0
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# serial port re-direct to pty deivce, /dev/pts/n
|
||||
# then xm console or minicom can connect
|
||||
#
|
||||
# In the stubdoms case this option adds a secondary console to the
|
||||
# stubdom because there is always one for logging.
|
||||
# To connect to the guest serial you can use "xm console -n 1"
|
||||
# followed by the domain name of the stubdom.
|
||||
#serial='pty'
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Qemu Monitor, default is disable
|
||||
# Use ctrl-alt-2 to connect
|
||||
#monitor=1
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# enable sound card support, [sb16|es1370|all|..,..], default none
|
||||
#
|
||||
# STUBDOM: not supported
|
||||
#soundhw='sb16'
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# set the real time clock to local time [default=0 i.e. set to utc]
|
||||
#localtime=1
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# set the real time clock offset in seconds [default=0 i.e. same as dom0]
|
||||
#rtc_timeoffset=3600
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# start in full screen
|
||||
#full-screen=1
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Enable USB support (specific devices specified at runtime through the
|
||||
# monitor window)
|
||||
#usb=1
|
||||
|
||||
# Enable USB mouse support (only enable one of the following, `mouse' for
|
||||
# PS/2 protocol relative mouse, `tablet' for
|
||||
# absolute mouse)
|
||||
#usbdevice='mouse'
|
||||
#usbdevice='tablet'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Set keyboard layout, default is en-us keyboard.
|
||||
#keymap='ja'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure guest CPUID responses:
|
||||
#
|
||||
#cpuid=[ '1:ecx=xxxxxxxxxxx00xxxxxxxxxxxxxxxxxxx,
|
||||
# eax=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ]
|
||||
# - Unset the SSE4 features (CPUID.1[ECX][20-19])
|
||||
# - Default behaviour for all other bits in ECX And EAX registers.
|
||||
#
|
||||
# Each successive character represent a lesser-significant bit:
|
||||
# '1' -> force the corresponding bit to 1
|
||||
# '0' -> force to 0
|
||||
# 'x' -> Get a safe value (pass through and mask with the default policy)
|
||||
# 'k' -> pass through the host bit value
|
||||
# 's' -> as 'k' but preserve across save/restore and migration
|
||||
#
|
||||
# Expose to the guest multi-core cpu instead of multiple processors
|
||||
# Example for intel, expose a 8-core processor :
|
||||
#cpuid=['1:edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
||||
# ebx=xxxxxxxx00010000xxxxxxxxxxxxxxxx',
|
||||
# '4,0:eax=001111xxxxxxxxxxxxxxxxxxxxxxxxxx']
|
||||
# - CPUID.1[EDX][HT] : Enable HT
|
||||
# - CPUID.1[EBX] : Number of vcpus * 2
|
||||
# - CPUID.4,0[EAX] : Number of vcpus * 2 - 1
|
||||
#vcpus=8
|
||||
#
|
||||
# Example for amd, expose a 5-core processor :
|
||||
# cpuid = ['1:ebx=xxxxxxxx00001010xxxxxxxxxxxxxxxx,
|
||||
# edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx',
|
||||
# '0x80000001:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1x',
|
||||
# '0x80000008:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx001001']
|
||||
# - CPUID.1[EBX] : Threads per Core * Cores per Socket (2 * #vcpus)
|
||||
# - CPUID.1[EDX][HT] : Enable HT
|
||||
# - CPUID.0x80000001[CmpLegacy] : Use legacy method
|
||||
# - CPUID.0x80000008[ECX] : #vcpus * 2 - 1
|
||||
#vcpus=5
|
||||
#
|
||||
# Downgrade the cpuid to make a better compatibility for migration :
|
||||
# Look like a generic 686 :
|
||||
# cpuid = [ '0:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0',
|
||||
# '1:eax=0x06b1,
|
||||
# ecx=xxxxxxxxxx0000xx00xxx0000000xx0,
|
||||
# edx=xx00000xxxxxxx0xxxxxxxxx0xxxxxx',
|
||||
# '4:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0',
|
||||
# '0x80000000:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0']
|
||||
# with the highest leaf
|
||||
# - CPUID.0[EAX] : Set the highest leaf
|
||||
# - CPUID.1[EAX] : 686
|
||||
# - CPUID.1[ECX] : Mask some features
|
||||
# - CPUID.1[EDX] : Mask some features
|
||||
# - CPUID.4 : Reply like the highest leaf, in our case CPUID.3
|
||||
# - CPUID.0x80000000 : No extension we are on a Pentium III, reply like the
|
||||
# highest leaf (CPUID.3).
|
||||
#
|
||||
# Configure host CPUID consistency checks, which must be satisfied for this
|
||||
# VM to be allowed to run on this host's processor type:
|
||||
#cpuid_check=[ '1:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx1xxxxx' ]
|
||||
# - Host must have VMX feature flag set
|
||||
#
|
||||
# The format is similar to the above for 'cpuid':
|
||||
# '1' -> the bit must be '1'
|
||||
# '0' -> the bit must be '0'
|
||||
# 'x' -> we don't care (do not check)
|
||||
# 's' -> the bit must be the same as on the host that started this VM
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure PVSCSI devices:
|
||||
#
|
||||
#vscsi=[ 'PDEV, VDEV' ]
|
||||
#
|
||||
# PDEV gives physical SCSI device to be attached to specified guest
|
||||
# domain by one of the following identifier format.
|
||||
# - XX:XX:XX:XX (4-tuples with decimal notation which shows
|
||||
# "host:channel:target:lun")
|
||||
# - /dev/sdxx or sdx
|
||||
# - /dev/stxx or stx
|
||||
# - /dev/sgxx or sgx
|
||||
# - result of 'scsi_id -gu -s'.
|
||||
# ex. # scsi_id -gu -s /block/sdb
|
||||
# 36000b5d0006a0000006a0257004c0000
|
||||
#
|
||||
# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as
|
||||
# which the specified guest domain recognize.
|
||||
#
|
||||
|
||||
#vscsi = [ '/dev/sdx, 0:0:0:0' ]
|
||||
@@ -1,26 +0,0 @@
|
||||
# -*- mode: python; -*-
|
||||
#
|
||||
# xm create configuration example.
|
||||
#
|
||||
# This configuration is appropriate for using Network Block Device (NBD)
|
||||
# filesystems.
|
||||
#
|
||||
# Each of these parameters will need changing to match your setup.
|
||||
#
|
||||
|
||||
kernel = "/boot/vmlinuz-2.6.13-15b-xen"
|
||||
ramdisk = "/boot/initrd-2.6.13-15b-xen"
|
||||
|
||||
# WARNING: Creating a domain with insufficient memory may cause out of
|
||||
# memory errors. The domain needs enough memory to boot kernel
|
||||
# and modules. Allocating less than 32MBs is not recommended.
|
||||
memory = 128
|
||||
|
||||
name = "nbd4"
|
||||
vif = [ '' ]
|
||||
# Please change PORT
|
||||
disk = [ 'nbd:134.100.233.115 20004,hda1,w' ]
|
||||
dhcp = "dhcp"
|
||||
hostname= "nbd4"
|
||||
root = "/dev/hda1 ro"
|
||||
extra = "3"
|
||||
@@ -1,172 +0,0 @@
|
||||
# -*- mode: python; -*-
|
||||
#============================================================================
|
||||
# Python configuration setup for 'xm create'.
|
||||
# This script sets the parameters used when a domain is created using 'xm create'.
|
||||
# You use a separate script for each domain you want to create, or
|
||||
# you can set the parameters for the domain on the xm command line.
|
||||
#============================================================================
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# PV GRUB image file.
|
||||
kernel = "pv-grub.gz"
|
||||
|
||||
# Optional provided menu.lst.
|
||||
#ramdisk = "/boot/guests/menu.lst"
|
||||
|
||||
# Sets path to menu.lst
|
||||
extra = "(hd0,0)/boot/grub/menu.lst"
|
||||
# can be a TFTP-served path (DHCP will automatically be run)
|
||||
# extra = "(nd)/netboot/menu.lst"
|
||||
# can be configured automatically by GRUB's DHCP option 150 (see grub manual)
|
||||
# extra = ""
|
||||
|
||||
# Initial memory allocation (in megabytes) for the new domain.
|
||||
#
|
||||
# WARNING: Creating a domain with insufficient memory may cause out of
|
||||
# memory errors. The domain needs enough memory to boot kernel
|
||||
# and modules. Allocating less than 32MBs is not recommended.
|
||||
memory = 128
|
||||
|
||||
# A name for your domain. All domains must have different names.
|
||||
name = "ExampleDomain"
|
||||
|
||||
# 128-bit UUID for the domain. The default behavior is to generate a new UUID
|
||||
# on each call to 'xm create'.
|
||||
#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9"
|
||||
|
||||
# List of which CPUS this domain is allowed to use, default Xen picks
|
||||
#cpus = "" # leave to Xen to pick
|
||||
#cpus = "0" # all vcpus run on CPU0
|
||||
#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5
|
||||
#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3
|
||||
|
||||
# Number of Virtual CPUS to use, default is 1
|
||||
#vcpus = 1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define network interfaces.
|
||||
|
||||
# By default, no network interfaces are configured. You may have one created
|
||||
# with sensible defaults using an empty vif clause:
|
||||
#
|
||||
# vif = [ '' ]
|
||||
#
|
||||
# or optionally override backend, bridge, ip, mac, script, type, or vifname:
|
||||
#
|
||||
# vif = [ 'mac=00:16:3e:00:00:11, bridge=xenbr0' ]
|
||||
#
|
||||
# or more than one interface may be configured:
|
||||
#
|
||||
# vif = [ '', 'bridge=xenbr1' ]
|
||||
|
||||
vif = [ '' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define the disk devices you want the domain to have access to, and
|
||||
# what you want them accessible as.
|
||||
# Each disk entry is of the form phy:UNAME,DEV,MODE
|
||||
# where UNAME is the device, DEV is the device name the domain will see,
|
||||
# and MODE is r for read-only, w for read-write.
|
||||
|
||||
disk = [ 'phy:hda1,hda1,w' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define frame buffer device.
|
||||
#
|
||||
# By default, no frame buffer device is configured.
|
||||
#
|
||||
# To create one using the SDL backend and sensible defaults:
|
||||
#
|
||||
# vfb = [ 'sdl=1' ]
|
||||
#
|
||||
# This uses environment variables XAUTHORITY and DISPLAY. You
|
||||
# can override that:
|
||||
#
|
||||
# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ]
|
||||
#
|
||||
# To create one using the VNC backend and sensible defaults:
|
||||
#
|
||||
# vfb = [ 'vnc=1' ]
|
||||
#
|
||||
# The backend listens on 127.0.0.1 port 5900+N by default, where N is
|
||||
# the domain ID. You can override both address and N:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=1' ]
|
||||
#
|
||||
# Or you can bind the first unused port above 5900:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ]
|
||||
#
|
||||
# You can override the password:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ]
|
||||
#
|
||||
# Empty password disables authentication. Defaults to the vncpasswd
|
||||
# configured in xend-config.sxp.
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Configure the behaviour when a domain exits. There are three 'reasons'
|
||||
# for a domain to stop: poweroff, reboot, and crash. For each of these you
|
||||
# may specify:
|
||||
#
|
||||
# "destroy", meaning that the domain is cleaned up as normal;
|
||||
# "restart", meaning that a new domain is started in place of the old
|
||||
# one;
|
||||
# "preserve", meaning that no clean-up is done until the domain is
|
||||
# manually destroyed (using xm destroy, for example); or
|
||||
# "rename-restart", meaning that the old domain is not cleaned up, but is
|
||||
# renamed and a new domain started in its place.
|
||||
#
|
||||
# In the event a domain stops due to a crash, you have the additional options:
|
||||
#
|
||||
# "coredump-destroy", meaning dump the crashed domain's core and then destroy;
|
||||
# "coredump-restart', meaning dump the crashed domain's core and the restart.
|
||||
#
|
||||
# The default is
|
||||
#
|
||||
# on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# For backwards compatibility we also support the deprecated option restart
|
||||
#
|
||||
# restart = 'onreboot' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'destroy'
|
||||
#
|
||||
# restart = 'always' means on_poweroff = 'restart'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# restart = 'never' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'destroy'
|
||||
# on_crash = 'destroy'
|
||||
|
||||
#on_poweroff = 'destroy'
|
||||
#on_reboot = 'restart'
|
||||
#on_crash = 'restart'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure PVSCSI devices:
|
||||
#
|
||||
#vscsi=[ 'PDEV, VDEV' ]
|
||||
#
|
||||
# PDEV gives physical SCSI device to be attached to specified guest
|
||||
# domain by one of the following identifier format.
|
||||
# - XX:XX:XX:XX (4-tuples with decimal notation which shows
|
||||
# "host:channel:target:lun")
|
||||
# - /dev/sdxx or sdx
|
||||
# - /dev/stxx or stx
|
||||
# - /dev/sgxx or sgx
|
||||
# - result of 'scsi_id -gu -s'.
|
||||
# ex. # scsi_id -gu -s /block/sdb
|
||||
# 36000b5d0006a0000006a0257004c0000
|
||||
#
|
||||
# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as
|
||||
# which the specified guest domain recognize.
|
||||
#
|
||||
|
||||
#vscsi = [ '/dev/sdx, 0:0:0:0' ]
|
||||
|
||||
#============================================================================
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
# -*- mode: python; -*-
|
||||
#============================================================================
|
||||
# Python configuration setup for 'xm create'.
|
||||
# This script sets the parameters used when a domain is created using 'xm create'.
|
||||
# You use a separate script for each domain you want to create, or
|
||||
# you can set the parameters for the domain on the xm command line.
|
||||
#============================================================================
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Kernel image file.
|
||||
kernel = "/boot/vmlinuz-2.6.10-xenU"
|
||||
|
||||
# Optional ramdisk.
|
||||
#ramdisk = "/boot/initrd.gz"
|
||||
|
||||
# The domain build function. Default is 'linux'.
|
||||
#builder='linux'
|
||||
|
||||
# Initial memory allocation (in megabytes) for the new domain.
|
||||
#
|
||||
# WARNING: Creating a domain with insufficient memory may cause out of
|
||||
# memory errors. The domain needs enough memory to boot kernel
|
||||
# and modules. Allocating less than 32MBs is not recommended.
|
||||
memory = 64
|
||||
|
||||
# A name for your domain. All domains must have different names.
|
||||
name = "ExampleDomain"
|
||||
|
||||
# 128-bit UUID for the domain. The default behavior is to generate a new UUID
|
||||
# on each call to 'xm create'.
|
||||
#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9"
|
||||
|
||||
# List of which CPUS this domain is allowed to use, default Xen picks
|
||||
#cpus = "" # leave to Xen to pick
|
||||
#cpus = "0" # all vcpus run on CPU0
|
||||
#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5
|
||||
#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3
|
||||
|
||||
# Number of Virtual CPUS to use, default is 1
|
||||
#vcpus = 1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define network interfaces.
|
||||
|
||||
# By default, no network interfaces are configured. You may have one created
|
||||
# with sensible defaults using an empty vif clause:
|
||||
#
|
||||
# vif = [ '' ]
|
||||
#
|
||||
# or optionally override backend, bridge, ip, mac, script, type, or vifname:
|
||||
#
|
||||
# vif = [ 'mac=00:16:3e:00:00:11, bridge=xenbr0' ]
|
||||
#
|
||||
# or more than one interface may be configured:
|
||||
#
|
||||
# vif = [ '', 'bridge=xenbr1' ]
|
||||
|
||||
vif = [ '' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define the disk devices you want the domain to have access to, and
|
||||
# what you want them accessible as.
|
||||
# Each disk entry is of the form phy:UNAME,DEV,MODE
|
||||
# where UNAME is the device, DEV is the device name the domain will see,
|
||||
# and MODE is r for read-only, w for read-write.
|
||||
|
||||
disk = [ 'phy:hda1,hda1,w' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define frame buffer device.
|
||||
#
|
||||
# By default, no frame buffer device is configured.
|
||||
#
|
||||
# To create one using the SDL backend and sensible defaults:
|
||||
#
|
||||
# vfb = [ 'sdl=1' ]
|
||||
#
|
||||
# This uses environment variables XAUTHORITY and DISPLAY. You
|
||||
# can override that:
|
||||
#
|
||||
# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ]
|
||||
#
|
||||
# To create one using the VNC backend and sensible defaults:
|
||||
#
|
||||
# vfb = [ 'vnc=1' ]
|
||||
#
|
||||
# The backend listens on 127.0.0.1 port 5900+N by default, where N is
|
||||
# the domain ID. You can override both address and N:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=1' ]
|
||||
#
|
||||
# Or you can bind the first unused port above 5900:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ]
|
||||
#
|
||||
# You can override the password:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ]
|
||||
#
|
||||
# Empty password disables authentication. Defaults to the vncpasswd
|
||||
# configured in xend-config.sxp.
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Set the kernel command line for the new domain.
|
||||
# You only need to define the IP parameters and hostname if the domain's
|
||||
# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
|
||||
# You can use 'extra' to set the runlevel and custom environment
|
||||
# variables used by custom rc scripts (e.g. VMID=, usr= ).
|
||||
|
||||
# Set if you want dhcp to allocate the IP address.
|
||||
#dhcp="dhcp"
|
||||
# Set netmask.
|
||||
#netmask=
|
||||
# Set default gateway.
|
||||
#gateway=
|
||||
# Set the hostname.
|
||||
#hostname= "vm%d" % vmid
|
||||
|
||||
# Set root device.
|
||||
root = "/dev/hda1 ro"
|
||||
|
||||
# Root device for nfs.
|
||||
#root = "/dev/nfs"
|
||||
# The nfs server.
|
||||
#nfs_server = '192.0.2.1'
|
||||
# Root directory on the nfs server.
|
||||
#nfs_root = '/full/path/to/root/directory'
|
||||
|
||||
# Sets runlevel 4.
|
||||
extra = "4"
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Configure the behaviour when a domain exits. There are three 'reasons'
|
||||
# for a domain to stop: poweroff, reboot, and crash. For each of these you
|
||||
# may specify:
|
||||
#
|
||||
# "destroy", meaning that the domain is cleaned up as normal;
|
||||
# "restart", meaning that a new domain is started in place of the old
|
||||
# one;
|
||||
# "preserve", meaning that no clean-up is done until the domain is
|
||||
# manually destroyed (using xm destroy, for example); or
|
||||
# "rename-restart", meaning that the old domain is not cleaned up, but is
|
||||
# renamed and a new domain started in its place.
|
||||
#
|
||||
# In the event a domain stops due to a crash, you have the additional options:
|
||||
#
|
||||
# "coredump-destroy", meaning dump the crashed domain's core and then destroy;
|
||||
# "coredump-restart', meaning dump the crashed domain's core and the restart.
|
||||
#
|
||||
# The default is
|
||||
#
|
||||
# on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# For backwards compatibility we also support the deprecated option restart
|
||||
#
|
||||
# restart = 'onreboot' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'destroy'
|
||||
#
|
||||
# restart = 'always' means on_poweroff = 'restart'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# restart = 'never' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'destroy'
|
||||
# on_crash = 'destroy'
|
||||
|
||||
#on_poweroff = 'destroy'
|
||||
#on_reboot = 'restart'
|
||||
#on_crash = 'restart'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure PVSCSI devices:
|
||||
#
|
||||
#vscsi=[ 'PDEV, VDEV' ]
|
||||
#
|
||||
# PDEV gives physical SCSI device to be attached to specified guest
|
||||
# domain by one of the following identifier format.
|
||||
# - XX:XX:XX:XX (4-tuples with decimal notation which shows
|
||||
# "host:channel:target:lun")
|
||||
# - /dev/sdxx or sdx
|
||||
# - /dev/stxx or stx
|
||||
# - /dev/sgxx or sgx
|
||||
# - result of 'scsi_id -gu -s'.
|
||||
# ex. # scsi_id -gu -s /block/sdb
|
||||
# 36000b5d0006a0000006a0257004c0000
|
||||
#
|
||||
# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as
|
||||
# which the specified guest domain recognize.
|
||||
#
|
||||
|
||||
#vscsi = [ '/dev/sdx, 0:0:0:0' ]
|
||||
|
||||
#============================================================================
|
||||
|
||||
@@ -1,232 +0,0 @@
|
||||
# -*- mode: python; -*-
|
||||
#============================================================================
|
||||
# Example Python setup script for 'xm create'.
|
||||
# This script sets the parameters used when a domain is created using 'xm create'.
|
||||
#
|
||||
# This is a relatively advanced script that uses a parameter, vmid, to control
|
||||
# the settings. So this script can be used to start a set of domains by
|
||||
# setting the vmid parameter on the 'xm create' command line. For example:
|
||||
#
|
||||
# xm create vmid=1
|
||||
# xm create vmid=2
|
||||
# xm create vmid=3
|
||||
#
|
||||
# The vmid is purely a script variable, and has no effect on the the domain
|
||||
# id assigned to the new domain.
|
||||
#============================================================================
|
||||
|
||||
# Define script variables here.
|
||||
# xm_vars is defined automatically, use xm_vars.var() to define a variable.
|
||||
|
||||
# This function checks that 'vmid' has been given a valid value.
|
||||
# It is called automatically by 'xm create'.
|
||||
def vmid_check(var, val):
|
||||
val = int(val)
|
||||
if val <= 0:
|
||||
raise ValueError
|
||||
return val
|
||||
|
||||
# Define the 'vmid' variable so that 'xm create' knows about it.
|
||||
xm_vars.var('vmid',
|
||||
use="Virtual machine id. Integer greater than 0.",
|
||||
check=vmid_check)
|
||||
|
||||
# Check the defined variables have valid values..
|
||||
xm_vars.check()
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Kernel image file.
|
||||
kernel = "/boot/vmlinuz-2.6.10-xenU"
|
||||
|
||||
# Optional ramdisk.
|
||||
#ramdisk = "/boot/initrd.gz"
|
||||
|
||||
# The domain build function. Default is 'linux'.
|
||||
#builder='linux'
|
||||
|
||||
# Initial memory allocation (in megabytes) for the new domain.
|
||||
#
|
||||
# WARNING: Creating a domain with insufficient memory may cause out of
|
||||
# memory errors. The domain needs enough memory to boot kernel
|
||||
# and modules. Allocating less than 32MBs is not recommended.
|
||||
memory = 64
|
||||
|
||||
# A name for the new domain. All domains have to have different names,
|
||||
# so we use the vmid to create a name.
|
||||
name = "VM%d" % vmid
|
||||
|
||||
# 128-bit UUID for the domain. The default behavior is to generate a new UUID
|
||||
# on each call to 'xm create'.
|
||||
#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9"
|
||||
|
||||
# List of which CPUS this domain is allowed to use, default Xen picks
|
||||
#cpus = "" # leave to Xen to pick
|
||||
#cpus = "0" # all vcpus run on CPU0
|
||||
#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5
|
||||
#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3
|
||||
#cpus = "%s" % vmid # set based on vmid (mod number of CPUs)
|
||||
|
||||
# Number of Virtual CPUS to use, default is 1
|
||||
#vcpus = 1
|
||||
vcpus = 4 # make your domain a 4-way
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define network interfaces.
|
||||
|
||||
# By default, no network interfaces are configured. You may have one created
|
||||
# with sensible defaults using an empty vif clause:
|
||||
#
|
||||
# vif = [ '' ]
|
||||
#
|
||||
# or optionally override backend, bridge, ip, mac, script, type, or vifname:
|
||||
#
|
||||
# vif = [ 'mac=00:16:3e:00:00:11, bridge=xenbr0' ]
|
||||
#
|
||||
# or more than one interface may be configured:
|
||||
#
|
||||
# vif = [ '', 'bridge=xenbr1' ]
|
||||
|
||||
vif = [ '' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define the disk devices you want the domain to have access to, and
|
||||
# what you want them accessible as.
|
||||
# Each disk entry is of the form phy:UNAME,DEV,MODE
|
||||
# where UNAME is the device, DEV is the device name the domain will see,
|
||||
# and MODE is r for read-only, w for read-write.
|
||||
|
||||
# This makes the disk device depend on the vmid - assuming
|
||||
# that devices sda7, sda8 etc. exist. The device is exported
|
||||
# to all domains as sda1.
|
||||
# All domains get sda6 read-only (to use for /usr, see below).
|
||||
disk = [ 'phy:sda%d,sda1,w' % (7+vmid),
|
||||
'phy:sda6,sda6,r' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define frame buffer device.
|
||||
#
|
||||
# By default, no frame buffer device is configured.
|
||||
#
|
||||
# To create one using the SDL backend and sensible defaults:
|
||||
#
|
||||
# vfb = [ 'sdl=1' ]
|
||||
#
|
||||
# This uses environment variables XAUTHORITY and DISPLAY. You
|
||||
# can override that:
|
||||
#
|
||||
# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ]
|
||||
#
|
||||
# To create one using the VNC backend and sensible defaults:
|
||||
#
|
||||
# vfb = [ 'vnc=1' ]
|
||||
#
|
||||
# The backend listens on 127.0.0.1 port 5900+N by default, where N is
|
||||
# the domain ID. You can override both address and N:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=%d' % vmid ]
|
||||
#
|
||||
# Or you can bind the first unused port above 5900:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ]
|
||||
#
|
||||
# You can override the password:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ]
|
||||
#
|
||||
# Empty password disables authentication. Defaults to the vncpasswd
|
||||
# configured in xend-config.sxp.
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Set the kernel command line for the new domain.
|
||||
# You only need to define the IP parameters and hostname if the domain's
|
||||
# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
|
||||
# You can use 'extra' to set the runlevel and custom environment
|
||||
# variables used by custom rc scripts (e.g. VMID=, usr= ).
|
||||
|
||||
# Set if you want dhcp to allocate the IP address.
|
||||
#dhcp="dhcp"
|
||||
# Set netmask.
|
||||
#netmask=
|
||||
# Set default gateway.
|
||||
#gateway=
|
||||
# Set the hostname.
|
||||
#hostname= "vm%d" % vmid
|
||||
|
||||
# Set root device.
|
||||
root = "/dev/sda1 ro"
|
||||
|
||||
# Root device for nfs.
|
||||
#root = "/dev/nfs"
|
||||
# The nfs server.
|
||||
#nfs_server = '192.0.2.1'
|
||||
# Root directory on the nfs server.
|
||||
#nfs_root = '/full/path/to/root/directory'
|
||||
|
||||
# Sets runlevel 4 and the device for /usr.
|
||||
extra = "4 VMID=%d usr=/dev/sda6" % vmid
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Configure the behaviour when a domain exits. There are three 'reasons'
|
||||
# for a domain to stop: poweroff, reboot, and crash. For each of these you
|
||||
# may specify:
|
||||
#
|
||||
# "destroy", meaning that the domain is cleaned up as normal;
|
||||
# "restart", meaning that a new domain is started in place of the old
|
||||
# one;
|
||||
# "preserve", meaning that no clean-up is done until the domain is
|
||||
# manually destroyed (using xm destroy, for example); or
|
||||
# "rename-restart", meaning that the old domain is not cleaned up, but is
|
||||
# renamed and a new domain started in its place.
|
||||
#
|
||||
# In the event a domain stops due to a crash, you have the additional options:
|
||||
#
|
||||
# "coredump-destroy", meaning dump the crashed domain's core and then destroy;
|
||||
# "coredump-restart', meaning dump the crashed domain's core and the restart.
|
||||
#
|
||||
# The default is
|
||||
#
|
||||
# on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# For backwards compatibility we also support the deprecated option restart
|
||||
#
|
||||
# restart = 'onreboot' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'destroy'
|
||||
#
|
||||
# restart = 'always' means on_poweroff = 'restart'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# restart = 'never' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'destroy'
|
||||
# on_crash = 'destroy'
|
||||
|
||||
#on_poweroff = 'destroy'
|
||||
#on_reboot = 'restart'
|
||||
#on_crash = 'restart'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure PVSCSI devices:
|
||||
#
|
||||
#vscsi=[ 'PDEV, VDEV' ]
|
||||
#
|
||||
# PDEV gives physical SCSI device to be attached to specified guest
|
||||
# domain by one of the following identifier format.
|
||||
# - XX:XX:XX:XX (4-tuples with decimal notation which shows
|
||||
# "host:channel:target:lun")
|
||||
# - /dev/sdxx or sdx
|
||||
# - /dev/stxx or stx
|
||||
# - /dev/sgxx or sgx
|
||||
# - result of 'scsi_id -gu -s'.
|
||||
# ex. # scsi_id -gu -s /block/sdb
|
||||
# 36000b5d0006a0000006a0257004c0000
|
||||
#
|
||||
# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as
|
||||
# which the specified guest domain recognize.
|
||||
#
|
||||
|
||||
#vscsi = [ '/dev/sdx, 0:0:0:0' ]
|
||||
|
||||
#============================================================================
|
||||
@@ -1,218 +0,0 @@
|
||||
# -*- mode: python; -*-
|
||||
#============================================================================
|
||||
# Example Python setup script for 'xm create'.
|
||||
# This script sets the parameters used when a domain is created using 'xm create'.
|
||||
#
|
||||
# This is a relatively advanced script that uses a parameter, vmid, to control
|
||||
# the settings. So this script can be used to start a set of domains by
|
||||
# setting the vmid parameter on the 'xm create' command line. For example:
|
||||
#
|
||||
# xm create vmid=1
|
||||
# xm create vmid=2
|
||||
# xm create vmid=3
|
||||
#
|
||||
# The vmid is purely a script variable, and has no effect on the the domain
|
||||
# id assigned to the new domain.
|
||||
#============================================================================
|
||||
|
||||
# Define script variables here.
|
||||
# xm_vars is defined automatically, use xm_vars.var() to define a variable.
|
||||
|
||||
# This function checks that 'vmid' has been given a valid value.
|
||||
# It is called automatically by 'xm create'.
|
||||
def vmid_check(var, val):
|
||||
val = int(val)
|
||||
if val <= 0:
|
||||
raise ValueError
|
||||
return val
|
||||
|
||||
# Define the 'vmid' variable so that 'xm create' knows about it.
|
||||
xm_vars.var('vmid',
|
||||
use="Virtual machine id. Integer greater than 0.",
|
||||
check=vmid_check)
|
||||
|
||||
# Check the defined variables have valid values..
|
||||
xm_vars.check()
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Kernel image file.
|
||||
kernel = "/path/to/domU/kernel"
|
||||
|
||||
# Optional ramdisk.
|
||||
#ramdisk = "/boot/initrd.gz"
|
||||
|
||||
# The domain build function. Default is 'linux'.
|
||||
#builder='linux'
|
||||
|
||||
# Initial memory allocation (in megabytes) for the new domain.
|
||||
#
|
||||
# WARNING: Creating a domain with insufficient memory may cause out of
|
||||
# memory errors. The domain needs enough memory to boot kernel
|
||||
# and modules. Allocating less than 32MBs is not recommended.
|
||||
memory = 64
|
||||
|
||||
# A name for the new domain. All domains have to have different names,
|
||||
# so we use the vmid to create a name.
|
||||
name = "VM%d" % vmid
|
||||
|
||||
# 128-bit UUID for the domain. The default behavior is to generate a new UUID
|
||||
# on each call to 'xm create'.
|
||||
#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9"
|
||||
|
||||
# List of which CPUS this domain is allowed to use, default Xen picks
|
||||
#cpus = "" # leave to Xen to pick
|
||||
#cpus = "0" # all vcpus run on CPU0
|
||||
#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5
|
||||
#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3
|
||||
cpus = "%s" % vmid # set based on vmid (mod number of CPUs)
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define network interfaces.
|
||||
|
||||
# Optionally define mac and/or bridge for the network interfaces.
|
||||
# Random MACs are assigned if not given.
|
||||
|
||||
vif = [ 'ip=192.168.%d.1/24' % (vmid)]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define the disk devices you want the domain to have access to, and
|
||||
# what you want them accessible as.
|
||||
# Each disk entry is of the form phy:UNAME,DEV,MODE
|
||||
# where UNAME is the device, DEV is the device name the domain will see,
|
||||
# and MODE is r for read-only, w for read-write.
|
||||
|
||||
# This makes the disk device depend on the vmid - assuming
|
||||
# tHat devices sda7, sda8 etc. exist. The device is exported
|
||||
# to all domains as sda1.
|
||||
# All domains get sda6 read-only (to use for /usr, see below).
|
||||
disk = [ 'phy:hda%d,hda1,w' % (vmid)]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define frame buffer device.
|
||||
#
|
||||
# By default, no frame buffer device is configured.
|
||||
#
|
||||
# To create one using the SDL backend and sensible defaults:
|
||||
#
|
||||
# vfb = [ 'sdl=1' ]
|
||||
#
|
||||
# This uses environment variables XAUTHORITY and DISPLAY. You
|
||||
# can override that:
|
||||
#
|
||||
# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ]
|
||||
#
|
||||
# To create one using the VNC backend and sensible defaults:
|
||||
#
|
||||
# vfb = [ 'vnc=1' ]
|
||||
#
|
||||
# The backend listens on 127.0.0.1 port 5900+N by default, where N is
|
||||
# the domain ID. You can override both address and N:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=%d' % vmid ]
|
||||
#
|
||||
# Or you can bind the first unused port above 5900:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ]
|
||||
#
|
||||
# You can override the password:
|
||||
#
|
||||
# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ]
|
||||
#
|
||||
# Empty password disables authentication. Defaults to the vncpasswd
|
||||
# configured in xend-config.sxp.
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Set the kernel command line for the new domain.
|
||||
# You only need to define the IP parameters and hostname if the domain's
|
||||
# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
|
||||
# You can use 'extra' to set the runlevel and custom environment
|
||||
# variables used by custom rc scripts (e.g. VMID=, usr= ).
|
||||
|
||||
# Set if you want dhcp to allocate the IP address.
|
||||
dhcp="off"
|
||||
ip="192.168.%d.2" % (vmid)
|
||||
# Set netmask.
|
||||
netmask="255.255.255.0"
|
||||
# Set default gateway.
|
||||
gateway="192.168.%d.1" % (vmid)
|
||||
# Set the hostname.
|
||||
hostname= "domain-%d.xeno" % vmid
|
||||
|
||||
# Set root device.
|
||||
root = "/dev/hda1 ro"
|
||||
|
||||
# Root device for nfs.
|
||||
#root = "/dev/nfs"
|
||||
# The nfs server.
|
||||
#nfs_server = "10.212.4.103"
|
||||
# Root directory on the nfs server.
|
||||
#nfs_root = "/path/to/root/filesystem"
|
||||
|
||||
# Sets runlevel 4 and the device for /usr.
|
||||
extra = "4 VMID=%d" % vmid
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Configure the behaviour when a domain exits. There are three 'reasons'
|
||||
# for a domain to stop: poweroff, reboot, and crash. For each of these you
|
||||
# may specify:
|
||||
#
|
||||
# "destroy", meaning that the domain is cleaned up as normal;
|
||||
# "restart", meaning that a new domain is started in place of the old
|
||||
# one;
|
||||
# "preserve", meaning that no clean-up is done until the domain is
|
||||
# manually destroyed (using xm destroy, for example); or
|
||||
# "rename-restart", meaning that the old domain is not cleaned up, but is
|
||||
# renamed and a new domain started in its place.
|
||||
#
|
||||
# In the event a domain stops due to a crash, you have the additional options:
|
||||
#
|
||||
# "coredump-destroy", meaning dump the crashed domain's core and then destroy;
|
||||
# "coredump-restart', meaning dump the crashed domain's core and the restart.
|
||||
#
|
||||
# The default is
|
||||
#
|
||||
# on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# For backwards compatibility we also support the deprecated option restart
|
||||
#
|
||||
# restart = 'onreboot' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'destroy'
|
||||
#
|
||||
# restart = 'always' means on_poweroff = 'restart'
|
||||
# on_reboot = 'restart'
|
||||
# on_crash = 'restart'
|
||||
#
|
||||
# restart = 'never' means on_poweroff = 'destroy'
|
||||
# on_reboot = 'destroy'
|
||||
# on_crash = 'destroy'
|
||||
|
||||
#on_poweroff = 'destroy'
|
||||
#on_reboot = 'restart'
|
||||
#on_crash = 'restart'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Configure PVSCSI devices:
|
||||
#
|
||||
#vscsi=[ 'PDEV, VDEV' ]
|
||||
#
|
||||
# PDEV gives physical SCSI device to be attached to specified guest
|
||||
# domain by one of the following identifier format.
|
||||
# - XX:XX:XX:XX (4-tuples with decimal notation which shows
|
||||
# "host:channel:target:lun")
|
||||
# - /dev/sdxx or sdx
|
||||
# - /dev/stxx or stx
|
||||
# - /dev/sgxx or sgx
|
||||
# - result of 'scsi_id -gu -s'.
|
||||
# ex. # scsi_id -gu -s /block/sdb
|
||||
# 36000b5d0006a0000006a0257004c0000
|
||||
#
|
||||
# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as
|
||||
# which the specified guest domain recognize.
|
||||
#
|
||||
|
||||
#vscsi = [ '/dev/sdx, 0:0:0:0' ]
|
||||
|
||||
#============================================================================
|
||||
@@ -2,7 +2,6 @@ XEN_ROOT = $(CURDIR)/../../..
|
||||
include $(XEN_ROOT)/tools/Rules.mk
|
||||
|
||||
# Init scripts.
|
||||
XEND_INITD = init.d/xend
|
||||
XENDOMAINS_INITD = init.d/xendomains
|
||||
XENDOMAINS_SYSCONFIG = init.d/sysconfig.xendomains
|
||||
|
||||
@@ -30,7 +29,6 @@ XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh
|
||||
XEN_SCRIPT_DATA += block-common.sh
|
||||
|
||||
UDEV_RULES_DIR = $(CONFIG_DIR)/udev
|
||||
UDEV_RULES-$(CONFIG_XEND) = xend.rules
|
||||
UDEV_RULES = xen-backend.rules $(UDEV_RULES-y)
|
||||
|
||||
.PHONY: all
|
||||
@@ -47,9 +45,6 @@ install: all install-initd install-scripts install-udev
|
||||
install-initd:
|
||||
[ -d $(DESTDIR)$(INITD_DIR) ] || $(INSTALL_DIR) $(DESTDIR)$(INITD_DIR)
|
||||
[ -d $(DESTDIR)$(SYSCONFIG_DIR) ] || $(INSTALL_DIR) $(DESTDIR)$(SYSCONFIG_DIR)
|
||||
ifeq ($(CONFIG_XEND),y)
|
||||
$(INSTALL_PROG) $(XEND_INITD) $(DESTDIR)$(INITD_DIR)
|
||||
endif
|
||||
$(INSTALL_PROG) $(XENDOMAINS_INITD) $(DESTDIR)$(INITD_DIR)
|
||||
$(INSTALL_DATA) $(XENDOMAINS_SYSCONFIG) $(DESTDIR)$(SYSCONFIG_DIR)/xendomains
|
||||
$(INSTALL_PROG) $(XENCOMMONS_INITD) $(DESTDIR)$(INITD_DIR)
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# xend Script to start and stop the Xen control daemon.
|
||||
#
|
||||
# Author: Keir Fraser <keir.fraser@cl.cam.ac.uk>
|
||||
#
|
||||
# chkconfig: 2345 98 01
|
||||
# description: Starts and stops the Xen control daemon.
|
||||
### BEGIN INIT INFO
|
||||
# Provides: xend
|
||||
# Required-Start: $syslog $remote_fs xenstored xenconsoled
|
||||
# Should-Start:
|
||||
# Required-Stop: $syslog $remote_fs xenstored xenconsoled
|
||||
# Should-Stop:
|
||||
# Default-Start: 2 3 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Start/stop xend
|
||||
# Description: Starts and stops the Xen control daemon.
|
||||
### END INIT INFO
|
||||
|
||||
. /etc/xen/scripts/hotplugpath.sh
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
# Wait for Xend to be up
|
||||
function await_daemons_up
|
||||
{
|
||||
i=1
|
||||
rets=10
|
||||
${SBINDIR}/xend status
|
||||
while [ $? -ne 0 -a $i -lt $rets ]; do
|
||||
sleep 1
|
||||
echo -n .
|
||||
i=$(($i + 1))
|
||||
${SBINDIR}/xend status
|
||||
done
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo "WARNING: Enabling the xend toolstack."
|
||||
echo "xend is deprecated and scheduled for removal. Please migrate"
|
||||
echo "to another toolstack ASAP."
|
||||
|
||||
if [ -z "`ps -C xenconsoled -o pid=`" ]; then
|
||||
echo "xencommons should be started first."
|
||||
exit 1
|
||||
fi
|
||||
# mkdir shouldn't be needed as most distros have this already created. Default to using subsys.
|
||||
# See docs/misc/distro_mapping.txt
|
||||
mkdir -p /var/lock
|
||||
if [ -d /var/lock/subsys ] ; then
|
||||
touch /var/lock/subsys/xend
|
||||
else
|
||||
touch /var/lock/xend
|
||||
fi
|
||||
${SBINDIR}/xend start
|
||||
await_daemons_up
|
||||
;;
|
||||
stop)
|
||||
${SBINDIR}/xend stop
|
||||
rm -f /var/lock/subsys/xend /var/lock/xend
|
||||
;;
|
||||
status)
|
||||
${SBINDIR}/xend status
|
||||
;;
|
||||
reload)
|
||||
${SBINDIR}/xend reload
|
||||
;;
|
||||
restart|force-reload)
|
||||
${SBINDIR}/xend restart
|
||||
await_daemons_up
|
||||
;;
|
||||
*)
|
||||
# do not advertise unreasonable commands that there is no reason
|
||||
# to use with this device
|
||||
echo $"Usage: $0 {start|stop|status|restart|reload|force-reload}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit $?
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
SUBSYSTEM=="pci", RUN+="socket:/org/xen/xend/udev_event"
|
||||
SUBSYSTEM=="scsi", RUN+="socket:/org/xen/xend/udev_event"
|
||||
SUBSYSTEM=="usb", RUN+="socket:/org/xen/xend/udev_event"
|
||||
#SUBSYSTEM=="net", KERNEL!="vif[0-9]*.[0-9]*|tap[0-9]*.[0-9]*", RUN+="socket:/org/xen/xend/udev_event"
|
||||
@@ -8,8 +8,7 @@ XEN_SCRIPTS += vif-bridge
|
||||
XEN_SCRIPTS += vif-ip
|
||||
|
||||
XEN_SCRIPT_DATA =
|
||||
XEN_RCD_PROG-$(CONFIG_XEND) = rc.d/xend
|
||||
XEN_RCD_PROG = rc.d/xencommons $(XEN_RCD_PROG-y) rc.d/xendomains rc.d/xen-watchdog
|
||||
XEN_RCD_PROG = rc.d/xencommons rc.d/xendomains rc.d/xen-watchdog
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# PROVIDE: xend
|
||||
# REQUIRE: xencommons
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
DIR=$(dirname "$0")
|
||||
. "${DIR}/xen-hotplugpath.sh"
|
||||
|
||||
LD_LIBRARY_PATH="${LIBDIR}"
|
||||
export LD_LIBRARY_PATH PYTHONPATH
|
||||
PATH="${PATH}:${SBINDIR}"
|
||||
export PATH
|
||||
|
||||
name="xend"
|
||||
rcvar=$name
|
||||
start_precmd="xend_precmd"
|
||||
start_cmd="xend_startcmd"
|
||||
stop_cmd="xend_stop"
|
||||
status_cmd="xend_status"
|
||||
extra_commands="status"
|
||||
required_files="/kern/xen/privcmd"
|
||||
|
||||
XENBACKENDD_PIDFILE="/var/run/xenbackendd.pid"
|
||||
#XENBACKENDD_DEBUG=1
|
||||
|
||||
xend_precmd()
|
||||
{
|
||||
mkdir -p /var/run/xend || exit 1
|
||||
mkdir -p /var/run/xend/boot || exit 1
|
||||
}
|
||||
|
||||
xend_startcmd()
|
||||
{
|
||||
printf "Starting xenbackendd.\n"
|
||||
|
||||
XENBACKENDD_ARGS=""
|
||||
if [ -n "${XENBACKENDD_DEBUG}" ]; then
|
||||
XENBACKENDD_ARGS="${XENBACKENDD_ARGS} -d"
|
||||
fi
|
||||
|
||||
${SBINDIR}/xenbackendd ${XENBACKENDD_ARGS}
|
||||
|
||||
printf "Starting xend.\n"
|
||||
${SBINDIR}/xend start >/dev/null 2>&1
|
||||
}
|
||||
|
||||
xend_stop()
|
||||
{
|
||||
printf "Stopping xenbackendd, xend\n"
|
||||
xb_pid=$(check_pidfile ${XENBACKENDD_PIDFILE} ${SBINDIR}/xenbackendd)
|
||||
if test -n "$xb_pid";
|
||||
then
|
||||
kill -${sig_stop:-TERM} $xb_pid
|
||||
fi
|
||||
while pgrep -f ${SBINDIR}/xend >/dev/null 2>&1; do
|
||||
pkill -${sig_stop:-KILL} -f ${SBINDIR}/xend
|
||||
done
|
||||
wait_for_pids $xb_pid
|
||||
rm -f /var/lock/subsys/xend /var/lock/xend /var/run/xenbackendd.pid
|
||||
}
|
||||
|
||||
xend_status()
|
||||
{
|
||||
${SBINDIR}/xend status
|
||||
}
|
||||
|
||||
load_rc_config $name
|
||||
run_rc_command "$1"
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
#include "libxlutil.h"
|
||||
#include "xl.h"
|
||||
|
||||
#define XEND_LOCK { "/var/lock/subsys/xend", "/var/lock/xend" }
|
||||
|
||||
xentoollog_logger_stdiostream *logger;
|
||||
int dryrun_only;
|
||||
int force_execution;
|
||||
@@ -299,7 +297,6 @@ int main(int argc, char **argv)
|
||||
int ret;
|
||||
void *config_data = 0;
|
||||
int config_len = 0;
|
||||
const char *locks[] = XEND_LOCK;
|
||||
|
||||
while ((opt = getopt(argc, argv, "+vftN")) >= 0) {
|
||||
switch (opt) {
|
||||
@@ -357,19 +354,6 @@ int main(int argc, char **argv)
|
||||
ret = 1;
|
||||
goto xit;
|
||||
}
|
||||
if (cspec->modifies && !dryrun_only) {
|
||||
for (int i = 0; i < sizeof(locks)/sizeof(locks[0]); i++) {
|
||||
if (!access(locks[i], F_OK) && !force_execution) {
|
||||
fprintf(stderr,
|
||||
"xend is running, which may cause unpredictable results when using\n"
|
||||
"this xl command. Please shut down xend before continuing.\n\n"
|
||||
"(This check can be overridden with the -f option.)\n"
|
||||
);
|
||||
ret = 1;
|
||||
goto xit;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = cspec->cmd_impl(argc, argv);
|
||||
} else if (!strcmp(cmd, "help")) {
|
||||
help(argv[1]);
|
||||
|
||||
+3
-15
@@ -16,26 +16,14 @@ build: genpath genwrap.py $(XEN_ROOT)/tools/libxl/libxl_types.idl \
|
||||
$(XEN_ROOT)/tools/libxl/libxl_types.idl \
|
||||
xen/lowlevel/xl/_pyxl_types.h \
|
||||
xen/lowlevel/xl/_pyxl_types.c
|
||||
CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py build --xend=$(CONFIG_XEND)
|
||||
CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py build
|
||||
|
||||
.PHONY: install
|
||||
install: install-dtd
|
||||
install:
|
||||
CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py install \
|
||||
$(PYTHON_PREFIX_ARG) --root="$(DESTDIR)" --force --xend=$(CONFIG_XEND)
|
||||
$(PYTHON_PREFIX_ARG) --root="$(DESTDIR)" --force
|
||||
|
||||
$(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
|
||||
ifeq ($(CONFIG_XEND),y)
|
||||
$(INSTALL_PYTHON_PROG) xen/xm/xm $(DESTDIR)$(SBINDIR)/xm
|
||||
$(INSTALL_PYTHON_PROG) xen/xend/xend $(DESTDIR)$(SBINDIR)/xend
|
||||
endif
|
||||
|
||||
install-dtd: all
|
||||
ifeq ($(CONFIG_XEND),y)
|
||||
$(INSTALL_DIR) $(DESTDIR)$(SHAREDIR)/xen
|
||||
$(INSTALL_DATA) xen/xm/create.dtd $(DESTDIR)$(SHAREDIR)/xen
|
||||
else
|
||||
:
|
||||
endif
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: logging
|
||||
Version: 0.4.9.2
|
||||
Summary: A logging module for Python
|
||||
Home-page: http://www.red-dove.com/python_logging.html
|
||||
Author: Vinay Sajip
|
||||
Author-email: vinay_sajip@red-dove.com
|
||||
License: Copyright (C) 2001-2004 by Vinay Sajip. All Rights Reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Vinay Sajip
|
||||
not be used in advertising or publicity pertaining to distribution
|
||||
of the software without specific, written prior permission.
|
||||
|
||||
VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
Description: This module is intended to provide a standard error logging mechanism in Python as per PEP 282.
|
||||
Platform: UNKNOWN
|
||||
@@ -1,311 +0,0 @@
|
||||
This module is intended to provide error logging functionality for Python
|
||||
programs. It aims to be aligned with Python Enhancement Proposal (PEP) 282.
|
||||
|
||||
For more information on the package itself, see python_logging.html. In it,
|
||||
there is a description of each file in the distribution.
|
||||
You can also use pydoc to browse the interfaces.
|
||||
|
||||
Change History
|
||||
--------------
|
||||
|
||||
Version Date Description
|
||||
=============================================================================
|
||||
0.4.9.2 28 Feb 2004 Traceback text is now cached.
|
||||
Tracebacks can be propagated across sockets as text.
|
||||
Added makeLogRecord() to allow a LogRecord to be
|
||||
created from a dictionary.
|
||||
Closing a handler now removes it from the internal list
|
||||
used by shutdown().
|
||||
Made close() call flush() for handlers where this makes
|
||||
sense (thanks to Jim Jewett).
|
||||
The exc_info keyword parameter can be used to pass an
|
||||
exception tuple as well as a flag indicating that the
|
||||
current exception should be logged.
|
||||
A shutdown hook is registered to call shutdown() on
|
||||
application (Python) exit (thanks to Jim Jewett).
|
||||
Removed redundant error check in setLoggerClass().
|
||||
Added RESET_ERROR to logging.config.
|
||||
SocketHandler now uses an exponential backoff strategy
|
||||
(thanks to Robert Olson).
|
||||
Minor documentation corrections.
|
||||
-----------------------------------------------------------------------------
|
||||
0.4.8 22 Apr 2003 Made _listener global in stopListening().
|
||||
Made listen() correctly pass the specified port.
|
||||
Removed some redundant imports in __init__.py.
|
||||
Added the record being processed as a parameter to
|
||||
handleError (thanks to Gordon den Otter for the idea).
|
||||
Handler.handle returns the result of applying the
|
||||
filter to the record (thanks to Gordon den Otter for
|
||||
the idea).
|
||||
Added a seek(0, 2) in RotatingFileHandler before the
|
||||
tell() call. This is because under Windows, tell()
|
||||
returns 0 until the first actual write (thanks to
|
||||
Gordon den Otter for the patch).
|
||||
Altered findCaller to not use inspect (thanks to
|
||||
Jeremy Hylton for the patch).
|
||||
Renamed warn and WARN to warning and WARNING. This may
|
||||
break existing code, but the standard Python module
|
||||
will use warning/WARNING rather than warn/WARN. The
|
||||
fatal and FATAL synonyms for critical and CRITICAL
|
||||
have also been removed.
|
||||
Added defaultEncoding and some support for encoding
|
||||
Unicode messages (thanks to Stéphane Bidoul for the
|
||||
suggestion).
|
||||
Added process ID to the list of LogRecord attributes.
|
||||
Modified Logger.removeHandler so that it does not
|
||||
close the handler on removal.
|
||||
Modified SMTPHandler to treat a single "to address"
|
||||
correctly (thanks to Anthony Baxter).
|
||||
Modified SMTPHandler to add a date header to the SMTP
|
||||
message (thanks to David Driver for the suggestion).
|
||||
Modified HTTPHandler to factor out the mapping of
|
||||
a LogRecord to a dictionary (thanks to Franz Glasner
|
||||
for the patch).
|
||||
-----------------------------------------------------------------------------
|
||||
0.4.7 15 Nov 2002 Made into a package with three modules: __init__ (the
|
||||
core code), handlers (all handlers other than
|
||||
FileHandler and its bases) and config (all the config
|
||||
stuff). Before doing this:
|
||||
Updated docstrings to include a short line, then a
|
||||
blank line, then more descriptive text.
|
||||
Renamed 'lvl' to 'level' in various functions.
|
||||
Changed FileHandler to use "a" and "w" instead of "a+"
|
||||
and "w+".
|
||||
Moved log file rotation functionality from FileHandler
|
||||
to a new class RotatingFileHandler.
|
||||
Improved docstring describing rollover.
|
||||
Updated makePickle to use 4-byte length and struct
|
||||
module, likewise logrecv.py. Also updated on-the-fly
|
||||
config reader to use 4-byte length/struct module.
|
||||
Altered ConfigParser test to look at 'readline' rather
|
||||
than 'read'.
|
||||
Added optional "defaults" argument to fileConfig, to
|
||||
be passed to ConfigParser.
|
||||
Renamed ALL to NOTSET to avoid confusion.
|
||||
Commented out getRootLogger(), as obsolete.
|
||||
To do regression testing, run log_test.py and compare
|
||||
the created files stdout.log and stderr.log against
|
||||
the files stdout.exp and stderr.exp. They should match
|
||||
except fir a couple of exception messages which give
|
||||
absolute file paths.
|
||||
Updated python_logging.html to remove links to
|
||||
logging_pydoc.html, which has been removed from the
|
||||
distribution.
|
||||
Changed default for raiseExceptions to 1.
|
||||
-----------------------------------------------------------------------------
|
||||
0.4.6 08 Jul 2002 Added raiseExceptions to allow conditional propagation
|
||||
of exceptions which occur during handling.
|
||||
Added converter to Formatter to allow use of any
|
||||
function to convert time from seconds to a tuple. It
|
||||
still defaults to time.localtime but now you can also
|
||||
use time.gmtime.
|
||||
Added log_test22.py to test the conversion feature.
|
||||
Changed rootlogger default level to WARN - was DEBUG.
|
||||
Updated some docstrings.
|
||||
Moved import of threading to where thread is imported.
|
||||
If either is unavailable, threading support is off.
|
||||
Updated minor defects in python_logging.html.
|
||||
Check to see if ConfigParser has readfp method; if it
|
||||
does and an object with a 'read' method is passed in,
|
||||
assumes a file-like object and uses readfp to read it
|
||||
in.
|
||||
-----------------------------------------------------------------------------
|
||||
0.4.5 04 Jun 2002 Fixed bug which caused problem if no args to message
|
||||
(suggested by Hye-Shik Chang).
|
||||
Fixed bug in _fixupParents (thanks to Nicholas Veeser)
|
||||
and added log_test19.py as a test case for this bug.
|
||||
Added getMessage to LogRecord (code was moved here from
|
||||
Formatter.format)
|
||||
Applied str() to record.msg to allow arbitrary classes
|
||||
to determine the formatting (as msg can now be a class
|
||||
instance).
|
||||
Table of Contents added to python_logging.html, the
|
||||
section on Loggers updated, and the logconf.ini file
|
||||
section annotated.
|
||||
Added log_test20.py which demonstrates how to use
|
||||
class instances to provide alternatives to numeric
|
||||
severities as mechanisms for control of logging.
|
||||
Added log_test21.py which builds on log_test20.py to
|
||||
show how you can use a regular expression-based Filter
|
||||
for flexible matching similar to e.g. Protomatter
|
||||
Syslog, where you can filter on e.g. "a.*" or "*.b" or
|
||||
"a.*.c".
|
||||
_levelNames changed to contain reverse mappings as well
|
||||
as forward mappings (leveltext->level as well as level
|
||||
-> leveltext). The reverse mappings are used by
|
||||
fileConfig().
|
||||
fileConfig() now more forgiving of missing options in
|
||||
.ini file - sensible defaults now used when some
|
||||
options are absent. Also, eval() is used less when
|
||||
interpreting .ini file contents - int() and dict lookup
|
||||
are used in more places.
|
||||
-----------------------------------------------------------------------------
|
||||
0.4.4 02 May 2002 getEffectiveLevel() returns ALL instead of None when
|
||||
nothing found. Modified references to level=0 to
|
||||
level=ALL in a couple of places.
|
||||
SocketHandler now inherits from Handler (it used to
|
||||
inherit from StreamHandler, for no good reason).
|
||||
getLock() renamed to createLock().
|
||||
Docstring tidy-ups, and some tidying up of
|
||||
DatagramHandler.
|
||||
Factored out unpickling in logrecv.py.
|
||||
Added log_test18.py to illustrate MatchFilter, which is
|
||||
a general matching filter.
|
||||
Improved FileHandler.doRollover() so that the base
|
||||
file name is always the most recent, then .1, then .2
|
||||
etc. up to the maximum backup count. Renamed formal
|
||||
args and attributes used in rollover.
|
||||
Changed LogRecord attributes lvl -> levelno, level ->
|
||||
levelname (less ambiguity)
|
||||
Formatter.format searches for "%(asctime)" rather than
|
||||
"(asctime)"
|
||||
Renamed _start_time to _startTime
|
||||
Formatter.formatTime now returns the time
|
||||
Altered logrecv.py to support stopping servers
|
||||
programmatically
|
||||
Added log_test.py as overall test harness
|
||||
basicConfig() can now be safely called more than once
|
||||
Modified test scripts to make it easier to call them
|
||||
from log_test.py
|
||||
Moved SOAPHandler from core to log_test13.py. It's not
|
||||
general enough to be in the core; most production use
|
||||
will have differing RPC signatures.
|
||||
-----------------------------------------------------------------------------
|
||||
0.4.3 14 Apr 2002 Bug fix one-off error message to go to sys.stderr
|
||||
rather than sys.stdout.
|
||||
logrecv.py fix TCP for busy network.
|
||||
Thread safety - added locking to Handler and for shared
|
||||
data in module, and log_test16.py to test it.
|
||||
Added socket listener to allow on-the-fly configuration
|
||||
and added log_test17.py to test it.
|
||||
-----------------------------------------------------------------------------
|
||||
0.4.2 11 Apr 2002 Bug fix fileConfig() - setup of MemoryHandler target
|
||||
and errors when loggers have no handlers set or
|
||||
handlers have no formatters set
|
||||
logconf.py - seems to hang if window closed when combo
|
||||
dropdown is showing - added code to close popup on exit
|
||||
Some tweaks to _srcfile computation (normpath added)
|
||||
findCaller() optimized, now a lot faster!
|
||||
Logger.removeHandler now closes the handler before
|
||||
removing it
|
||||
fileConfig() removes existing handlers before adding
|
||||
the new set, to avoid memory leakage when repeated
|
||||
calls are made
|
||||
Fixed logrecv.py bug which hogged CPU time when TCP
|
||||
connection was closed from the client
|
||||
Added log_test14.py to demonstrate/test a DBHandler
|
||||
which writes logging records into an RDBMS using the
|
||||
Python Database API 2.0 (to run, you need something
|
||||
which supports this already installed - I tested with
|
||||
mxODBC)
|
||||
Made getLogger name argument optional - returns root
|
||||
logger if omitted
|
||||
Altered Filter to take a string initializer, filtering
|
||||
a sub-hierarchy rooted at a particular point (idea from
|
||||
Denis S. Otkidach).
|
||||
Added log_test15.py to test Filter initializer
|
||||
Minor docstring changes
|
||||
-----------------------------------------------------------------------------
|
||||
0.4.1 03 Apr 2002 Bug fix SMTPHandler - extra \r\n needed (Oleg Orlov)
|
||||
Added BufferingHandler, BufferingFormatter
|
||||
Renamed getChainedPriority to getEffectiveLevel
|
||||
Removed Logger.getRoot as it is redundant
|
||||
Added log_test9.py to test Buffering classes and
|
||||
to show an XMLFormatter example.
|
||||
Added setLoggerClass.
|
||||
Added log_test10.py to test setLoggerClass, using an
|
||||
example Logger-derived class which outputs exception
|
||||
info even for DEBUG level logging calls
|
||||
Added log_test11.py to test a buffering implementation
|
||||
of SMTPHandler
|
||||
Changed logging call implementation to allow keyword
|
||||
arguments (Kevin Butler and others)
|
||||
Changed default SysLogHandler implementation.
|
||||
Renamed "additive" to "propagate" as it better
|
||||
describes the attribute.
|
||||
Added HTTPHandler.
|
||||
Modified logrecv.py to remove "both" option and to add
|
||||
"HTTP" and "SOAP" options (SOAP option needs you to
|
||||
have PyXML-0.6.6 and ZSI installed - for logrecv.py
|
||||
only, and not for the core logging module itself).
|
||||
Added log_test12.py to test HTTPHandler.
|
||||
Added log_test13.py to test SOAPHandler.
|
||||
Formatted to Python source guidelines (spaces, indent
|
||||
of 4, within 80 columns).
|
||||
More method renamings (result of feedback) - _handle()
|
||||
renamed to emit(), _logRecord() renamed to handle().
|
||||
Renamed FATAL to CRITICAL (David Goodger), but left
|
||||
fatal() and FATAL in (until PEP is changed)
|
||||
Changed configuration file format to ConfigParser
|
||||
format.
|
||||
Factored filter application functionality out to a new
|
||||
Filterer class. The isLoggable() method is renamed to
|
||||
filter() in both Filter and Filterer classes.
|
||||
Altered SMTPHandler __init__ to accept (host, port)
|
||||
for the mail internet address.
|
||||
Added GUI configurator which uses Tkinter and the new
|
||||
configuration file format. (See logconf.py and an
|
||||
example configuration file in logconf.ini)
|
||||
Altered log_test3.py to test with the new file format.
|
||||
-----------------------------------------------------------------------------
|
||||
0.4 21 Mar 2002 Incorporated comments/patches from Ollie Rutherfurd:
|
||||
-Added level filtering for handlers.
|
||||
-Return root logger if no name specified in getLogger.
|
||||
Incorporated comments from Greg Ward:
|
||||
-Added distutils setup.py script.
|
||||
Added formatter initialization in Handler.__init__.
|
||||
Tidied up docstrings.
|
||||
Added removeHandler to Logger.
|
||||
Added removeFilter to Logger and Handler.
|
||||
logrecv.py modified to keep connection alive until
|
||||
client closes it.
|
||||
SocketHandler modified to not reset connection after
|
||||
each logging event.
|
||||
Added shutdown function which closes open sockets
|
||||
Renamed DEFAULT_LOGGING_PORT->DEFAULT_TCP_LOGGING_PORT
|
||||
Added DEFAULT_UDP_LOGGING_PORT
|
||||
Added log_test4.py (example of arbitrary levels)
|
||||
Added addLevelName, changed behaviour of getLevelName
|
||||
Fixed bugs in DatagramHandler
|
||||
Added SMTPHandler implementation
|
||||
Added log_test5.py to test SMTPHandler
|
||||
Added SysLogHandler (contribution from Nicolas Untz
|
||||
based on Sam Rushing's syslog.py)
|
||||
Modified log_test1.py to add a SysLogHandler
|
||||
Added rollover functionality to FileHandler
|
||||
Added NTEventLogHandler (based on Win32 extensions)
|
||||
Added MemoryHandler implementation
|
||||
Added log_test7.py to test MemoryHandler
|
||||
Added log_test8.py to test FileHandler rollover
|
||||
Added logException method to Logger
|
||||
Added formatException method to Formatter
|
||||
Added log_test6.py to test NTEventHandler and
|
||||
logException
|
||||
Numerous internal method renamings (sorry - but better
|
||||
to do this now, rather than when we enter beta status).
|
||||
-----------------------------------------------------------------------------
|
||||
0.3 14 Mar 2002 First public release, for early feedback
|
||||
-----------------------------------------------------------------------------
|
||||
0.2 Consolidated into single file (for internal use only)
|
||||
-----------------------------------------------------------------------------
|
||||
0.1 Initial implementation (for internal use only)
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
COPYRIGHT
|
||||
-----------------------------------------------------------------------------
|
||||
Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Vinay Sajip
|
||||
not be used in advertising or publicity pertaining to distribution
|
||||
of the software without specific, written prior permission.
|
||||
VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
@@ -1,32 +0,0 @@
|
||||
BODY, P, UL, OL {font-family: Verdana, Arial, Helvetica, Geneva, sans-serif ; background: white; color: black; font-size: 10pt; }
|
||||
CODE {font-family: "Courier New", Courier, Monaco, monospace ; }
|
||||
PRE {font-family: "Courier New", Courier, Monaco, monospace ; }
|
||||
.program { color: navy; font-family: "Courier New", Courier, Monaco, monospace }
|
||||
.output { color: maroon }
|
||||
HR {color: gray ; }
|
||||
.navbar { font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; background: #FFFF66 ; border-style: none none solid none; border-width: thin; padding: 2px;}
|
||||
.navarea { background: #FFFF66 ; }
|
||||
TR { font-size: 10pt }
|
||||
.red { color: #FF0000 }
|
||||
.maroon { color: #800000 }
|
||||
.comment { color: green }
|
||||
.optional { color: silver }
|
||||
.strong { font-weight: bold }
|
||||
TR.tblheading { background: silver ; }
|
||||
.notrecommended {color: #666666 ; }
|
||||
.deemphasized {color: #666666 ; }
|
||||
TABLE.densetable {font-size: 80% ; }
|
||||
TH { text-align: left; background: silver }
|
||||
TR.summaryrow { font-size: 90%; background: #00FFFF ; }
|
||||
CAPTION {font-size: 100% ; }
|
||||
.embeddedfloat {float: right; margin-left: 3em}
|
||||
.bigtd { font-size: 18pt }
|
||||
TD, .normaltd { vertical-align: top; background: #EEEEEE; font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; font-size: 10pt }
|
||||
H1, H2, H3, H4, H5, H6 {font-family: Verdana, Arial, Helvetica, Geneva, sans-serif ; }
|
||||
H4 {margin-bottom: 0.5em }
|
||||
H5, H6 {margin-bottom: 0.1em }
|
||||
A:link {color: blue ; }
|
||||
A:visited {color: purple ; }
|
||||
A:active {color: red ; }
|
||||
A { font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; font-size: 10pt }
|
||||
.warning { color: red }
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,301 +0,0 @@
|
||||
# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
"""
|
||||
Configuration functions for the logging package for Python. The core package
|
||||
is based on PEP 282 and comments thereto in comp.lang.python, and influenced
|
||||
by Apache's log4j system.
|
||||
|
||||
Should work under Python versions >= 1.5.2, except that source line
|
||||
information is not available unless 'sys._getframe()' is.
|
||||
|
||||
Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
|
||||
|
||||
To use, simply 'import logging' and log away!
|
||||
"""
|
||||
|
||||
import sys, logging, logging.handlers, string, thread, threading, socket, struct, os
|
||||
|
||||
from SocketServer import ThreadingTCPServer, StreamRequestHandler
|
||||
|
||||
|
||||
DEFAULT_LOGGING_CONFIG_PORT = 9030
|
||||
|
||||
if sys.platform == "win32":
|
||||
RESET_ERROR = 10054 #WSAECONNRESET
|
||||
else:
|
||||
RESET_ERROR = 104 #ECONNRESET
|
||||
|
||||
#
|
||||
# The following code implements a socket listener for on-the-fly
|
||||
# reconfiguration of logging.
|
||||
#
|
||||
# _listener holds the server object doing the listening
|
||||
_listener = None
|
||||
|
||||
def fileConfig(fname, defaults=None):
|
||||
"""
|
||||
Read the logging configuration from a ConfigParser-format file.
|
||||
|
||||
This can be called several times from an application, allowing an end user
|
||||
the ability to select from various pre-canned configurations (if the
|
||||
developer provides a mechanism to present the choices and load the chosen
|
||||
configuration).
|
||||
In versions of ConfigParser which have the readfp method [typically
|
||||
shipped in 2.x versions of Python], you can pass in a file-like object
|
||||
rather than a filename, in which case the file-like object will be read
|
||||
using readfp.
|
||||
"""
|
||||
import ConfigParser
|
||||
|
||||
cp = ConfigParser.ConfigParser(defaults)
|
||||
if hasattr(cp, 'readfp') and hasattr(fname, 'readline'):
|
||||
cp.readfp(fname)
|
||||
else:
|
||||
cp.read(fname)
|
||||
#first, do the formatters...
|
||||
flist = cp.get("formatters", "keys")
|
||||
if len(flist):
|
||||
flist = string.split(flist, ",")
|
||||
formatters = {}
|
||||
for form in flist:
|
||||
sectname = "formatter_%s" % form
|
||||
opts = cp.options(sectname)
|
||||
if "format" in opts:
|
||||
fs = cp.get(sectname, "format", 1)
|
||||
else:
|
||||
fs = None
|
||||
if "datefmt" in opts:
|
||||
dfs = cp.get(sectname, "datefmt", 1)
|
||||
else:
|
||||
dfs = None
|
||||
f = logging.Formatter(fs, dfs)
|
||||
formatters[form] = f
|
||||
#next, do the handlers...
|
||||
#critical section...
|
||||
logging._acquireLock()
|
||||
try:
|
||||
try:
|
||||
#first, lose the existing handlers...
|
||||
logging._handlers.clear()
|
||||
#now set up the new ones...
|
||||
hlist = cp.get("handlers", "keys")
|
||||
if len(hlist):
|
||||
hlist = string.split(hlist, ",")
|
||||
handlers = {}
|
||||
fixups = [] #for inter-handler references
|
||||
for hand in hlist:
|
||||
sectname = "handler_%s" % hand
|
||||
klass = cp.get(sectname, "class")
|
||||
opts = cp.options(sectname)
|
||||
if "formatter" in opts:
|
||||
fmt = cp.get(sectname, "formatter")
|
||||
else:
|
||||
fmt = ""
|
||||
klass = eval(klass, vars(logging))
|
||||
args = cp.get(sectname, "args")
|
||||
args = eval(args, vars(logging))
|
||||
h = apply(klass, args)
|
||||
if "level" in opts:
|
||||
level = cp.get(sectname, "level")
|
||||
h.setLevel(logging._levelNames[level])
|
||||
if len(fmt):
|
||||
h.setFormatter(formatters[fmt])
|
||||
#temporary hack for FileHandler and MemoryHandler.
|
||||
if klass == logging.handlers.MemoryHandler:
|
||||
if "target" in opts:
|
||||
target = cp.get(sectname,"target")
|
||||
else:
|
||||
target = ""
|
||||
if len(target): #the target handler may not be loaded yet, so keep for later...
|
||||
fixups.append((h, target))
|
||||
handlers[hand] = h
|
||||
#now all handlers are loaded, fixup inter-handler references...
|
||||
for fixup in fixups:
|
||||
h = fixup[0]
|
||||
t = fixup[1]
|
||||
h.setTarget(handlers[t])
|
||||
#at last, the loggers...first the root...
|
||||
llist = cp.get("loggers", "keys")
|
||||
llist = string.split(llist, ",")
|
||||
llist.remove("root")
|
||||
sectname = "logger_root"
|
||||
root = logging.root
|
||||
log = root
|
||||
opts = cp.options(sectname)
|
||||
if "level" in opts:
|
||||
level = cp.get(sectname, "level")
|
||||
log.setLevel(logging._levelNames[level])
|
||||
for h in root.handlers[:]:
|
||||
root.removeHandler(h)
|
||||
hlist = cp.get(sectname, "handlers")
|
||||
if len(hlist):
|
||||
hlist = string.split(hlist, ",")
|
||||
for hand in hlist:
|
||||
log.addHandler(handlers[hand])
|
||||
#and now the others...
|
||||
#we don't want to lose the existing loggers,
|
||||
#since other threads may have pointers to them.
|
||||
#existing is set to contain all existing loggers,
|
||||
#and as we go through the new configuration we
|
||||
#remove any which are configured. At the end,
|
||||
#what's left in existing is the set of loggers
|
||||
#which were in the previous configuration but
|
||||
#which are not in the new configuration.
|
||||
existing = root.manager.loggerDict.keys()
|
||||
#now set up the new ones...
|
||||
for log in llist:
|
||||
sectname = "logger_%s" % log
|
||||
qn = cp.get(sectname, "qualname")
|
||||
opts = cp.options(sectname)
|
||||
if "propagate" in opts:
|
||||
propagate = cp.getint(sectname, "propagate")
|
||||
else:
|
||||
propagate = 1
|
||||
logger = logging.getLogger(qn)
|
||||
if qn in existing:
|
||||
existing.remove(qn)
|
||||
if "level" in opts:
|
||||
level = cp.get(sectname, "level")
|
||||
logger.setLevel(logging._levelNames[level])
|
||||
for h in logger.handlers[:]:
|
||||
logger.removeHandler(h)
|
||||
logger.propagate = propagate
|
||||
logger.disabled = 0
|
||||
hlist = cp.get(sectname, "handlers")
|
||||
if len(hlist):
|
||||
hlist = string.split(hlist, ",")
|
||||
for hand in hlist:
|
||||
logger.addHandler(handlers[hand])
|
||||
#Disable any old loggers. There's no point deleting
|
||||
#them as other threads may continue to hold references
|
||||
#and by disabling them, you stop them doing any logging.
|
||||
for log in existing:
|
||||
root.manager.loggerDict[log].disabled = 1
|
||||
except:
|
||||
import traceback
|
||||
ei = sys.exc_info()
|
||||
traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
|
||||
del ei
|
||||
finally:
|
||||
logging._releaseLock()
|
||||
|
||||
def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
|
||||
"""
|
||||
Start up a socket server on the specified port, and listen for new
|
||||
configurations.
|
||||
|
||||
These will be sent as a file suitable for processing by fileConfig().
|
||||
Returns a Thread object on which you can call start() to start the server,
|
||||
and which you can join() when appropriate. To stop the server, call
|
||||
stopListening().
|
||||
"""
|
||||
if not thread:
|
||||
raise NotImplementedError, "listen() needs threading to work"
|
||||
|
||||
class ConfigStreamHandler(StreamRequestHandler):
|
||||
"""
|
||||
Handler for a logging configuration request.
|
||||
|
||||
It expects a completely new logging configuration and uses fileConfig
|
||||
to install it.
|
||||
"""
|
||||
def handle(self):
|
||||
"""
|
||||
Handle a request.
|
||||
|
||||
Each request is expected to be a 4-byte length,
|
||||
followed by the config file. Uses fileConfig() to do the
|
||||
grunt work.
|
||||
"""
|
||||
import tempfile
|
||||
try:
|
||||
conn = self.connection
|
||||
chunk = conn.recv(4)
|
||||
if len(chunk) == 4:
|
||||
slen = struct.unpack(">L", chunk)[0]
|
||||
chunk = self.connection.recv(slen)
|
||||
while len(chunk) < slen:
|
||||
chunk = chunk + conn.recv(slen - len(chunk))
|
||||
#Apply new configuration. We'd like to be able to
|
||||
#create a StringIO and pass that in, but unfortunately
|
||||
#1.5.2 ConfigParser does not support reading file
|
||||
#objects, only actual files. So we create a temporary
|
||||
#file and remove it later.
|
||||
file = tempfile.mktemp(".ini")
|
||||
f = open(file, "w")
|
||||
f.write(chunk)
|
||||
f.close()
|
||||
fileConfig(file)
|
||||
os.remove(file)
|
||||
except socket.error, e:
|
||||
if type(e.args) != types.TupleType:
|
||||
raise
|
||||
else:
|
||||
errcode = e.args[0]
|
||||
if errcode != RESET_ERROR:
|
||||
raise
|
||||
|
||||
class ConfigSocketReceiver(ThreadingTCPServer):
|
||||
"""
|
||||
A simple TCP socket-based logging config receiver.
|
||||
"""
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT,
|
||||
handler=None):
|
||||
ThreadingTCPServer.__init__(self, (host, port), handler)
|
||||
logging._acquireLock()
|
||||
self.abort = 0
|
||||
logging._releaseLock()
|
||||
self.timeout = 1
|
||||
|
||||
def serve_until_stopped(self):
|
||||
import select
|
||||
abort = 0
|
||||
while not abort:
|
||||
rd, wr, ex = select.select([self.socket.fileno()],
|
||||
[], [],
|
||||
self.timeout)
|
||||
if rd:
|
||||
self.handle_request()
|
||||
logging._acquireLock()
|
||||
abort = self.abort
|
||||
logging._releaseLock()
|
||||
|
||||
def serve(rcvr, hdlr, port):
|
||||
server = rcvr(port=port, handler=hdlr)
|
||||
global _listener
|
||||
logging._acquireLock()
|
||||
_listener = server
|
||||
logging._releaseLock()
|
||||
server.serve_until_stopped()
|
||||
|
||||
return threading.Thread(target=serve,
|
||||
args=(ConfigSocketReceiver,
|
||||
ConfigStreamHandler, port))
|
||||
|
||||
def stopListening():
|
||||
"""
|
||||
Stop the listening server which was created with a call to listen().
|
||||
"""
|
||||
global _listener
|
||||
if _listener:
|
||||
logging._acquireLock()
|
||||
_listener.abort = 1
|
||||
_listener = None
|
||||
logging._releaseLock()
|
||||
@@ -1,787 +0,0 @@
|
||||
# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
"""
|
||||
Additional handlers for the logging package for Python. The core package is
|
||||
based on PEP 282 and comments thereto in comp.lang.python, and influenced by
|
||||
Apache's log4j system.
|
||||
|
||||
Should work under Python versions >= 1.5.2, except that source line
|
||||
information is not available unless 'sys._getframe()' is.
|
||||
|
||||
Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
|
||||
|
||||
To use, simply 'import logging' and log away!
|
||||
"""
|
||||
|
||||
import sys, logging, socket, types, os, string, cPickle, struct, time
|
||||
|
||||
from SocketServer import ThreadingTCPServer, StreamRequestHandler
|
||||
|
||||
#
|
||||
# Some constants...
|
||||
#
|
||||
|
||||
DEFAULT_TCP_LOGGING_PORT = 9020
|
||||
DEFAULT_UDP_LOGGING_PORT = 9021
|
||||
DEFAULT_HTTP_LOGGING_PORT = 9022
|
||||
DEFAULT_SOAP_LOGGING_PORT = 9023
|
||||
SYSLOG_UDP_PORT = 514
|
||||
|
||||
|
||||
class RotatingFileHandler(logging.FileHandler):
|
||||
def __init__(self, filename, mode="a", maxBytes=0, backupCount=0):
|
||||
"""
|
||||
Open the specified file and use it as the stream for logging.
|
||||
|
||||
By default, the file grows indefinitely. You can specify particular
|
||||
values of maxBytes and backupCount to allow the file to rollover at
|
||||
a predetermined size.
|
||||
|
||||
Rollover occurs whenever the current log file is nearly maxBytes in
|
||||
length. If backupCount is >= 1, the system will successively create
|
||||
new files with the same pathname as the base file, but with extensions
|
||||
".1", ".2" etc. appended to it. For example, with a backupCount of 5
|
||||
and a base file name of "app.log", you would get "app.log",
|
||||
"app.log.1", "app.log.2", ... through to "app.log.5". The file being
|
||||
written to is always "app.log" - when it gets filled up, it is closed
|
||||
and renamed to "app.log.1", and if files "app.log.1", "app.log.2" etc.
|
||||
exist, then they are renamed to "app.log.2", "app.log.3" etc.
|
||||
respectively.
|
||||
|
||||
If maxBytes is zero, rollover never occurs.
|
||||
"""
|
||||
logging.FileHandler.__init__(self, filename, mode)
|
||||
self.maxBytes = maxBytes
|
||||
self.backupCount = backupCount
|
||||
if maxBytes > 0:
|
||||
self.mode = "a"
|
||||
|
||||
def doRollover(self):
|
||||
"""
|
||||
Do a rollover, as described in __init__().
|
||||
"""
|
||||
|
||||
self.stream.close()
|
||||
if self.backupCount > 0:
|
||||
for i in range(self.backupCount - 1, 0, -1):
|
||||
sfn = "%s.%d" % (self.baseFilename, i)
|
||||
dfn = "%s.%d" % (self.baseFilename, i + 1)
|
||||
if os.path.exists(sfn):
|
||||
#print "%s -> %s" % (sfn, dfn)
|
||||
if os.path.exists(dfn):
|
||||
os.remove(dfn)
|
||||
os.rename(sfn, dfn)
|
||||
dfn = self.baseFilename + ".1"
|
||||
if os.path.exists(dfn):
|
||||
os.remove(dfn)
|
||||
os.rename(self.baseFilename, dfn)
|
||||
#print "%s -> %s" % (self.baseFilename, dfn)
|
||||
self.stream = open(self.baseFilename, "w")
|
||||
|
||||
def emit(self, record):
|
||||
"""
|
||||
Emit a record.
|
||||
|
||||
Output the record to the file, catering for rollover as described
|
||||
in doRollover().
|
||||
"""
|
||||
if self.maxBytes > 0: # are we rolling over?
|
||||
msg = "%s\n" % self.format(record)
|
||||
self.stream.seek(0, 2) #due to non-posix-compliant Windows feature
|
||||
if self.stream.tell() + len(msg) >= self.maxBytes:
|
||||
self.doRollover()
|
||||
logging.FileHandler.emit(self, record)
|
||||
|
||||
|
||||
class SocketHandler(logging.Handler):
|
||||
"""
|
||||
A handler class which writes logging records, in pickle format, to
|
||||
a streaming socket. The socket is kept open across logging calls.
|
||||
If the peer resets it, an attempt is made to reconnect on the next call.
|
||||
The pickle which is sent is that of the LogRecord's attribute dictionary
|
||||
(__dict__), so that the receiver does not need to have the logging module
|
||||
installed in order to process the logging event.
|
||||
|
||||
To unpickle the record at the receiving end into a LogRecord, use the
|
||||
makeLogRecord function.
|
||||
"""
|
||||
|
||||
def __init__(self, host, port):
|
||||
"""
|
||||
Initializes the handler with a specific host address and port.
|
||||
|
||||
The attribute 'closeOnError' is set to 1 - which means that if
|
||||
a socket error occurs, the socket is silently closed and then
|
||||
reopened on the next logging call.
|
||||
"""
|
||||
logging.Handler.__init__(self)
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.sock = None
|
||||
self.closeOnError = 0
|
||||
self.retryTime = None
|
||||
#
|
||||
# Exponential backoff parameters.
|
||||
#
|
||||
self.retryStart = 1.0
|
||||
self.retryMax = 30.0
|
||||
self.retryFactor = 2.0
|
||||
|
||||
def makeSocket(self):
|
||||
"""
|
||||
A factory method which allows subclasses to define the precise
|
||||
type of socket they want.
|
||||
"""
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect((self.host, self.port))
|
||||
return s
|
||||
|
||||
def createSocket(self):
|
||||
"""
|
||||
Try to create a socket, using an exponential backoff with
|
||||
a max retry time. Thanks to Robert Olson for the original patch
|
||||
(SF #815911) which has been slightly refactored.
|
||||
"""
|
||||
now = time.time()
|
||||
# Either retryTime is None, in which case this
|
||||
# is the first time back after a disconnect, or
|
||||
# we've waited long enough.
|
||||
if self.retryTime is None:
|
||||
attempt = 1
|
||||
else:
|
||||
attempt = (now >= self.retryTime)
|
||||
if attempt:
|
||||
try:
|
||||
self.sock = self.makeSocket()
|
||||
self.retryTime = None # next time, no delay before trying
|
||||
except:
|
||||
#Creation failed, so set the retry time and return.
|
||||
if self.retryTime is None:
|
||||
self.retryPeriod = self.retryStart
|
||||
else:
|
||||
self.retryPeriod = self.retryPeriod * self.retryFactor
|
||||
if self.retryPeriod > self.retryMax:
|
||||
self.retryPeriod = self.retryMax
|
||||
self.retryTime = now + self.retryPeriod
|
||||
|
||||
def send(self, s):
|
||||
"""
|
||||
Send a pickled string to the socket.
|
||||
|
||||
This function allows for partial sends which can happen when the
|
||||
network is busy.
|
||||
"""
|
||||
if self.sock is None:
|
||||
self.createSocket()
|
||||
#self.sock can be None either because we haven't reached the retry
|
||||
#time yet, or because we have reached the retry time and retried,
|
||||
#but are still unable to connect.
|
||||
if self.sock:
|
||||
try:
|
||||
if hasattr(self.sock, "sendall"):
|
||||
self.sock.sendall(s)
|
||||
else:
|
||||
sentsofar = 0
|
||||
left = len(s)
|
||||
while left > 0:
|
||||
sent = self.sock.send(s[sentsofar:])
|
||||
sentsofar = sentsofar + sent
|
||||
left = left - sent
|
||||
except socket.error:
|
||||
self.sock.close()
|
||||
self.sock = None # so we can call createSocket next time
|
||||
|
||||
def makePickle(self, record):
|
||||
"""
|
||||
Pickles the record in binary format with a length prefix, and
|
||||
returns it ready for transmission across the socket.
|
||||
"""
|
||||
ei = record.exc_info
|
||||
if ei:
|
||||
dummy = self.format(record) # just to get traceback text into record.exc_text
|
||||
record.exc_info = None # to avoid Unpickleable error
|
||||
s = cPickle.dumps(record.__dict__, 1)
|
||||
if ei:
|
||||
record.exc_info = ei # for next handler
|
||||
slen = struct.pack(">L", len(s))
|
||||
return slen + s
|
||||
|
||||
def handleError(self, record):
|
||||
"""
|
||||
Handle an error during logging.
|
||||
|
||||
An error has occurred during logging. Most likely cause -
|
||||
connection lost. Close the socket so that we can retry on the
|
||||
next event.
|
||||
"""
|
||||
if self.closeOnError and self.sock:
|
||||
self.sock.close()
|
||||
self.sock = None #try to reconnect next time
|
||||
else:
|
||||
logging.Handler.handleError(self, record)
|
||||
|
||||
def emit(self, record):
|
||||
"""
|
||||
Emit a record.
|
||||
|
||||
Pickles the record and writes it to the socket in binary format.
|
||||
If there is an error with the socket, silently drop the packet.
|
||||
If there was a problem with the socket, re-establishes the
|
||||
socket.
|
||||
"""
|
||||
try:
|
||||
s = self.makePickle(record)
|
||||
self.send(s)
|
||||
except:
|
||||
self.handleError(record)
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Closes the socket.
|
||||
"""
|
||||
if self.sock:
|
||||
self.sock.close()
|
||||
self.sock = None
|
||||
logging.Handler.close(self)
|
||||
|
||||
class DatagramHandler(SocketHandler):
|
||||
"""
|
||||
A handler class which writes logging records, in pickle format, to
|
||||
a datagram socket. The pickle which is sent is that of the LogRecord's
|
||||
attribute dictionary (__dict__), so that the receiver does not need to
|
||||
have the logging module installed in order to process the logging event.
|
||||
|
||||
To unpickle the record at the receiving end into a LogRecord, use the
|
||||
makeLogRecord function.
|
||||
|
||||
"""
|
||||
def __init__(self, host, port):
|
||||
"""
|
||||
Initializes the handler with a specific host address and port.
|
||||
"""
|
||||
SocketHandler.__init__(self, host, port)
|
||||
self.closeOnError = 0
|
||||
|
||||
def makeSocket(self):
|
||||
"""
|
||||
The factory method of SocketHandler is here overridden to create
|
||||
a UDP socket (SOCK_DGRAM).
|
||||
"""
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
return s
|
||||
|
||||
def send(self, s):
|
||||
"""
|
||||
Send a pickled string to a socket.
|
||||
|
||||
This function no longer allows for partial sends which can happen
|
||||
when the network is busy - UDP does not guarantee delivery and
|
||||
can deliver packets out of sequence.
|
||||
"""
|
||||
self.sock.sendto(s, (self.host, self.port))
|
||||
|
||||
class SysLogHandler(logging.Handler):
|
||||
"""
|
||||
A handler class which sends formatted logging records to a syslog
|
||||
server. Based on Sam Rushing's syslog module:
|
||||
http://www.nightmare.com/squirl/python-ext/misc/syslog.py
|
||||
Contributed by Nicolas Untz (after which minor refactoring changes
|
||||
have been made).
|
||||
"""
|
||||
|
||||
# from <linux/sys/syslog.h>:
|
||||
# ======================================================================
|
||||
# priorities/facilities are encoded into a single 32-bit quantity, where
|
||||
# the bottom 3 bits are the priority (0-7) and the top 28 bits are the
|
||||
# facility (0-big number). Both the priorities and the facilities map
|
||||
# roughly one-to-one to strings in the syslogd(8) source code. This
|
||||
# mapping is included in this file.
|
||||
#
|
||||
# priorities (these are ordered)
|
||||
|
||||
LOG_EMERG = 0 # system is unusable
|
||||
LOG_ALERT = 1 # action must be taken immediately
|
||||
LOG_CRIT = 2 # critical conditions
|
||||
LOG_ERR = 3 # error conditions
|
||||
LOG_WARNING = 4 # warning conditions
|
||||
LOG_NOTICE = 5 # normal but significant condition
|
||||
LOG_INFO = 6 # informational
|
||||
LOG_DEBUG = 7 # debug-level messages
|
||||
|
||||
# facility codes
|
||||
LOG_KERN = 0 # kernel messages
|
||||
LOG_USER = 1 # random user-level messages
|
||||
LOG_MAIL = 2 # mail system
|
||||
LOG_DAEMON = 3 # system daemons
|
||||
LOG_AUTH = 4 # security/authorization messages
|
||||
LOG_SYSLOG = 5 # messages generated internally by syslogd
|
||||
LOG_LPR = 6 # line printer subsystem
|
||||
LOG_NEWS = 7 # network news subsystem
|
||||
LOG_UUCP = 8 # UUCP subsystem
|
||||
LOG_CRON = 9 # clock daemon
|
||||
LOG_AUTHPRIV = 10 # security/authorization messages (private)
|
||||
|
||||
# other codes through 15 reserved for system use
|
||||
LOG_LOCAL0 = 16 # reserved for local use
|
||||
LOG_LOCAL1 = 17 # reserved for local use
|
||||
LOG_LOCAL2 = 18 # reserved for local use
|
||||
LOG_LOCAL3 = 19 # reserved for local use
|
||||
LOG_LOCAL4 = 20 # reserved for local use
|
||||
LOG_LOCAL5 = 21 # reserved for local use
|
||||
LOG_LOCAL6 = 22 # reserved for local use
|
||||
LOG_LOCAL7 = 23 # reserved for local use
|
||||
|
||||
priority_names = {
|
||||
"alert": LOG_ALERT,
|
||||
"crit": LOG_CRIT,
|
||||
"critical": LOG_CRIT,
|
||||
"debug": LOG_DEBUG,
|
||||
"emerg": LOG_EMERG,
|
||||
"err": LOG_ERR,
|
||||
"error": LOG_ERR, # DEPRECATED
|
||||
"info": LOG_INFO,
|
||||
"notice": LOG_NOTICE,
|
||||
"panic": LOG_EMERG, # DEPRECATED
|
||||
"warn": LOG_WARNING, # DEPRECATED
|
||||
"warning": LOG_WARNING,
|
||||
}
|
||||
|
||||
facility_names = {
|
||||
"auth": LOG_AUTH,
|
||||
"authpriv": LOG_AUTHPRIV,
|
||||
"cron": LOG_CRON,
|
||||
"daemon": LOG_DAEMON,
|
||||
"kern": LOG_KERN,
|
||||
"lpr": LOG_LPR,
|
||||
"mail": LOG_MAIL,
|
||||
"news": LOG_NEWS,
|
||||
"security": LOG_AUTH, # DEPRECATED
|
||||
"syslog": LOG_SYSLOG,
|
||||
"user": LOG_USER,
|
||||
"uucp": LOG_UUCP,
|
||||
"local0": LOG_LOCAL0,
|
||||
"local1": LOG_LOCAL1,
|
||||
"local2": LOG_LOCAL2,
|
||||
"local3": LOG_LOCAL3,
|
||||
"local4": LOG_LOCAL4,
|
||||
"local5": LOG_LOCAL5,
|
||||
"local6": LOG_LOCAL6,
|
||||
"local7": LOG_LOCAL7,
|
||||
}
|
||||
|
||||
def __init__(self, address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER):
|
||||
"""
|
||||
Initialize a handler.
|
||||
|
||||
If address is specified as a string, UNIX socket is used.
|
||||
If facility is not specified, LOG_USER is used.
|
||||
"""
|
||||
logging.Handler.__init__(self)
|
||||
|
||||
self.address = address
|
||||
self.facility = facility
|
||||
if type(address) == types.StringType:
|
||||
self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
||||
# syslog may require either DGRAM or STREAM sockets
|
||||
try:
|
||||
self.socket.connect(address)
|
||||
except socket.error:
|
||||
self.socket.close()
|
||||
self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
self.socket.connect(address)
|
||||
self.unixsocket = 1
|
||||
else:
|
||||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
self.unixsocket = 0
|
||||
|
||||
self.formatter = None
|
||||
|
||||
# curious: when talking to the unix-domain '/dev/log' socket, a
|
||||
# zero-terminator seems to be required. this string is placed
|
||||
# into a class variable so that it can be overridden if
|
||||
# necessary.
|
||||
log_format_string = '<%d>%s\000'
|
||||
|
||||
def encodePriority (self, facility, priority):
|
||||
"""
|
||||
Encode the facility and priority. You can pass in strings or
|
||||
integers - if strings are passed, the facility_names and
|
||||
priority_names mapping dictionaries are used to convert them to
|
||||
integers.
|
||||
"""
|
||||
if type(facility) == types.StringType:
|
||||
facility = self.facility_names[facility]
|
||||
if type(priority) == types.StringType:
|
||||
priority = self.priority_names[priority]
|
||||
return (facility << 3) | priority
|
||||
|
||||
def close (self):
|
||||
"""
|
||||
Closes the socket.
|
||||
"""
|
||||
if self.unixsocket:
|
||||
self.socket.close()
|
||||
logging.Handler.close(self)
|
||||
|
||||
def emit(self, record):
|
||||
"""
|
||||
Emit a record.
|
||||
|
||||
The record is formatted, and then sent to the syslog server. If
|
||||
exception information is present, it is NOT sent to the server.
|
||||
"""
|
||||
msg = self.format(record)
|
||||
"""
|
||||
We need to convert record level to lowercase, maybe this will
|
||||
change in the future.
|
||||
"""
|
||||
msg = self.log_format_string % (
|
||||
self.encodePriority(self.facility,
|
||||
string.lower(record.levelname)),
|
||||
msg)
|
||||
try:
|
||||
if self.unixsocket:
|
||||
self.socket.send(msg)
|
||||
else:
|
||||
self.socket.sendto(msg, self.address)
|
||||
except:
|
||||
self.handleError(record)
|
||||
|
||||
class SMTPHandler(logging.Handler):
|
||||
"""
|
||||
A handler class which sends an SMTP email for each logging event.
|
||||
"""
|
||||
def __init__(self, mailhost, fromaddr, toaddrs, subject):
|
||||
"""
|
||||
Initialize the handler.
|
||||
|
||||
Initialize the instance with the from and to addresses and subject
|
||||
line of the email. To specify a non-standard SMTP port, use the
|
||||
(host, port) tuple format for the mailhost argument.
|
||||
"""
|
||||
logging.Handler.__init__(self)
|
||||
if type(mailhost) == types.TupleType:
|
||||
host, port = mailhost
|
||||
self.mailhost = host
|
||||
self.mailport = port
|
||||
else:
|
||||
self.mailhost = mailhost
|
||||
self.mailport = None
|
||||
self.fromaddr = fromaddr
|
||||
if type(toaddrs) == types.StringType:
|
||||
toaddrs = [toaddrs]
|
||||
self.toaddrs = toaddrs
|
||||
self.subject = subject
|
||||
|
||||
def getSubject(self, record):
|
||||
"""
|
||||
Determine the subject for the email.
|
||||
|
||||
If you want to specify a subject line which is record-dependent,
|
||||
override this method.
|
||||
"""
|
||||
return self.subject
|
||||
|
||||
weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
||||
|
||||
monthname = [None,
|
||||
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
||||
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
||||
|
||||
def date_time(self):
|
||||
"""Return the current date and time formatted for a MIME header."""
|
||||
year, month, day, hh, mm, ss, wd, y, z = time.gmtime(time.time())
|
||||
s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
|
||||
self.weekdayname[wd],
|
||||
day, self.monthname[month], year,
|
||||
hh, mm, ss)
|
||||
return s
|
||||
|
||||
def emit(self, record):
|
||||
"""
|
||||
Emit a record.
|
||||
|
||||
Format the record and send it to the specified addressees.
|
||||
"""
|
||||
try:
|
||||
import smtplib
|
||||
port = self.mailport
|
||||
if not port:
|
||||
port = smtplib.SMTP_PORT
|
||||
smtp = smtplib.SMTP(self.mailhost, port)
|
||||
msg = self.format(record)
|
||||
msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % (
|
||||
self.fromaddr,
|
||||
string.join(self.toaddrs, ","),
|
||||
self.getSubject(record),
|
||||
self.date_time(), msg)
|
||||
smtp.sendmail(self.fromaddr, self.toaddrs, msg)
|
||||
smtp.quit()
|
||||
except:
|
||||
self.handleError(record)
|
||||
|
||||
class NTEventLogHandler(logging.Handler):
|
||||
"""
|
||||
A handler class which sends events to the NT Event Log. Adds a
|
||||
registry entry for the specified application name. If no dllname is
|
||||
provided, win32service.pyd (which contains some basic message
|
||||
placeholders) is used. Note that use of these placeholders will make
|
||||
your event logs big, as the entire message source is held in the log.
|
||||
If you want slimmer logs, you have to pass in the name of your own DLL
|
||||
which contains the message definitions you want to use in the event log.
|
||||
"""
|
||||
def __init__(self, appname, dllname=None, logtype="Application"):
|
||||
logging.Handler.__init__(self)
|
||||
try:
|
||||
import win32evtlogutil, win32evtlog
|
||||
self.appname = appname
|
||||
self._welu = win32evtlogutil
|
||||
if not dllname:
|
||||
dllname = os.path.split(self._welu.__file__)
|
||||
dllname = os.path.split(dllname[0])
|
||||
dllname = os.path.join(dllname[0], r'win32service.pyd')
|
||||
self.dllname = dllname
|
||||
self.logtype = logtype
|
||||
self._welu.AddSourceToRegistry(appname, dllname, logtype)
|
||||
self.deftype = win32evtlog.EVENTLOG_ERROR_TYPE
|
||||
self.typemap = {
|
||||
logging.DEBUG : win32evtlog.EVENTLOG_INFORMATION_TYPE,
|
||||
logging.INFO : win32evtlog.EVENTLOG_INFORMATION_TYPE,
|
||||
logging.WARNING : win32evtlog.EVENTLOG_WARNING_TYPE,
|
||||
logging.ERROR : win32evtlog.EVENTLOG_ERROR_TYPE,
|
||||
logging.CRITICAL: win32evtlog.EVENTLOG_ERROR_TYPE,
|
||||
}
|
||||
except ImportError:
|
||||
print "The Python Win32 extensions for NT (service, event "\
|
||||
"logging) appear not to be available."
|
||||
self._welu = None
|
||||
|
||||
def getMessageID(self, record):
|
||||
"""
|
||||
Return the message ID for the event record. If you are using your
|
||||
own messages, you could do this by having the msg passed to the
|
||||
logger being an ID rather than a formatting string. Then, in here,
|
||||
you could use a dictionary lookup to get the message ID. This
|
||||
version returns 1, which is the base message ID in win32service.pyd.
|
||||
"""
|
||||
return 1
|
||||
|
||||
def getEventCategory(self, record):
|
||||
"""
|
||||
Return the event category for the record.
|
||||
|
||||
Override this if you want to specify your own categories. This version
|
||||
returns 0.
|
||||
"""
|
||||
return 0
|
||||
|
||||
def getEventType(self, record):
|
||||
"""
|
||||
Return the event type for the record.
|
||||
|
||||
Override this if you want to specify your own types. This version does
|
||||
a mapping using the handler's typemap attribute, which is set up in
|
||||
__init__() to a dictionary which contains mappings for DEBUG, INFO,
|
||||
WARNING, ERROR and CRITICAL. If you are using your own levels you will
|
||||
either need to override this method or place a suitable dictionary in
|
||||
the handler's typemap attribute.
|
||||
"""
|
||||
return self.typemap.get(record.levelno, self.deftype)
|
||||
|
||||
def emit(self, record):
|
||||
"""
|
||||
Emit a record.
|
||||
|
||||
Determine the message ID, event category and event type. Then
|
||||
log the message in the NT event log.
|
||||
"""
|
||||
if self._welu:
|
||||
try:
|
||||
id = self.getMessageID(record)
|
||||
cat = self.getEventCategory(record)
|
||||
type = self.getEventType(record)
|
||||
msg = self.format(record)
|
||||
self._welu.ReportEvent(self.appname, id, cat, type, [msg])
|
||||
except:
|
||||
self.handleError(record)
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Clean up this handler.
|
||||
|
||||
You can remove the application name from the registry as a
|
||||
source of event log entries. However, if you do this, you will
|
||||
not be able to see the events as you intended in the Event Log
|
||||
Viewer - it needs to be able to access the registry to get the
|
||||
DLL name.
|
||||
"""
|
||||
#self._welu.RemoveSourceFromRegistry(self.appname, self.logtype)
|
||||
logging.Handler.close(self)
|
||||
|
||||
class HTTPHandler(logging.Handler):
|
||||
"""
|
||||
A class which sends records to a Web server, using either GET or
|
||||
POST semantics.
|
||||
"""
|
||||
def __init__(self, host, url, method="GET"):
|
||||
"""
|
||||
Initialize the instance with the host, the request URL, and the method
|
||||
("GET" or "POST")
|
||||
"""
|
||||
logging.Handler.__init__(self)
|
||||
method = string.upper(method)
|
||||
if method not in ["GET", "POST"]:
|
||||
raise ValueError, "method must be GET or POST"
|
||||
self.host = host
|
||||
self.url = url
|
||||
self.method = method
|
||||
|
||||
def mapLogRecord(self, record):
|
||||
"""
|
||||
Default implementation of mapping the log record into a dict
|
||||
that is sent as the CGI data. Overwrite in your class.
|
||||
Contributed by Franz Glasner.
|
||||
"""
|
||||
return record.__dict__
|
||||
|
||||
def emit(self, record):
|
||||
"""
|
||||
Emit a record.
|
||||
|
||||
Send the record to the Web server as an URL-encoded dictionary
|
||||
"""
|
||||
try:
|
||||
import httplib, urllib
|
||||
h = httplib.HTTP(self.host)
|
||||
url = self.url
|
||||
data = urllib.urlencode(self.mapLogRecord(record))
|
||||
if self.method == "GET":
|
||||
if (string.find(url, '?') >= 0):
|
||||
sep = '&'
|
||||
else:
|
||||
sep = '?'
|
||||
url = url + "%c%s" % (sep, data)
|
||||
h.putrequest(self.method, url)
|
||||
if self.method == "POST":
|
||||
h.putheader("Content-length", str(len(data)))
|
||||
h.endheaders()
|
||||
if self.method == "POST":
|
||||
h.send(data)
|
||||
h.getreply() #can't do anything with the result
|
||||
except:
|
||||
self.handleError(record)
|
||||
|
||||
class BufferingHandler(logging.Handler):
|
||||
"""
|
||||
A handler class which buffers logging records in memory. Whenever each
|
||||
record is added to the buffer, a check is made to see if the buffer should
|
||||
be flushed. If it should, then flush() is expected to do what's needed.
|
||||
"""
|
||||
def __init__(self, capacity):
|
||||
"""
|
||||
Initialize the handler with the buffer size.
|
||||
"""
|
||||
logging.Handler.__init__(self)
|
||||
self.capacity = capacity
|
||||
self.buffer = []
|
||||
|
||||
def shouldFlush(self, record):
|
||||
"""
|
||||
Should the handler flush its buffer?
|
||||
|
||||
Returns true if the buffer is up to capacity. This method can be
|
||||
overridden to implement custom flushing strategies.
|
||||
"""
|
||||
return (len(self.buffer) >= self.capacity)
|
||||
|
||||
def emit(self, record):
|
||||
"""
|
||||
Emit a record.
|
||||
|
||||
Append the record. If shouldFlush() tells us to, call flush() to process
|
||||
the buffer.
|
||||
"""
|
||||
self.buffer.append(record)
|
||||
if self.shouldFlush(record):
|
||||
self.flush()
|
||||
|
||||
def flush(self):
|
||||
"""
|
||||
Override to implement custom flushing behaviour.
|
||||
|
||||
This version just zaps the buffer to empty.
|
||||
"""
|
||||
self.buffer = []
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Close the handler.
|
||||
|
||||
This version just flushes and chains to the parent class' close().
|
||||
"""
|
||||
self.flush()
|
||||
logging.Handler.close(self)
|
||||
|
||||
class MemoryHandler(BufferingHandler):
|
||||
"""
|
||||
A handler class which buffers logging records in memory, periodically
|
||||
flushing them to a target handler. Flushing occurs whenever the buffer
|
||||
is full, or when an event of a certain severity or greater is seen.
|
||||
"""
|
||||
def __init__(self, capacity, flushLevel=logging.ERROR, target=None):
|
||||
"""
|
||||
Initialize the handler with the buffer size, the level at which
|
||||
flushing should occur and an optional target.
|
||||
|
||||
Note that without a target being set either here or via setTarget(),
|
||||
a MemoryHandler is no use to anyone!
|
||||
"""
|
||||
BufferingHandler.__init__(self, capacity)
|
||||
self.flushLevel = flushLevel
|
||||
self.target = target
|
||||
|
||||
def shouldFlush(self, record):
|
||||
"""
|
||||
Check for buffer full or a record at the flushLevel or higher.
|
||||
"""
|
||||
return (len(self.buffer) >= self.capacity) or \
|
||||
(record.levelno >= self.flushLevel)
|
||||
|
||||
def setTarget(self, target):
|
||||
"""
|
||||
Set the target handler for this handler.
|
||||
"""
|
||||
self.target = target
|
||||
|
||||
def flush(self):
|
||||
"""
|
||||
For a MemoryHandler, flushing means just sending the buffered
|
||||
records to the target, if there is one. Override if you want
|
||||
different behaviour.
|
||||
"""
|
||||
if self.target:
|
||||
for record in self.buffer:
|
||||
self.target.handle(record)
|
||||
self.buffer = []
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Flush, set the target to None and lose the buffer.
|
||||
"""
|
||||
self.flush()
|
||||
self.target = None
|
||||
BufferingHandler.close(self)
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,29 +0,0 @@
|
||||
from distutils.core import setup
|
||||
|
||||
setup(name = "logging",
|
||||
description="A logging module for Python",
|
||||
long_description = """This module is intended to provide a standard error logging mechanism in Python as per PEP 282.""",
|
||||
license="""Copyright (C) 2001-2004 by Vinay Sajip. All Rights Reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Vinay Sajip
|
||||
not be used in advertising or publicity pertaining to distribution
|
||||
of the software without specific, written prior permission.
|
||||
|
||||
VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.""",
|
||||
version = "0.4.9.2",
|
||||
author = "Vinay Sajip",
|
||||
author_email = "vinay_sajip@red-dove.com",
|
||||
maintainer = "Vinay Sajip",
|
||||
maintainer_email = "vinay_sajip@red-dove.com",
|
||||
url = "http://www.red-dove.com/python_logging.html",
|
||||
packages = ["logging"],
|
||||
)
|
||||
@@ -1,5 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.warning("Hello")
|
||||
logging.error("Still here...")
|
||||
logging.warning("Goodbye")
|
||||
@@ -1,60 +0,0 @@
|
||||
[loggers]
|
||||
keys=root,log02,log03,log04,log05
|
||||
|
||||
[handlers]
|
||||
keys=hand01
|
||||
|
||||
[formatters]
|
||||
keys=form01
|
||||
|
||||
[logger_root]
|
||||
level=WARN
|
||||
propagate=1
|
||||
channel=
|
||||
parent=
|
||||
qualname=(root)
|
||||
handlers=hand01
|
||||
|
||||
[logger_log02]
|
||||
level=CRITICAL
|
||||
propagate=1
|
||||
channel=A
|
||||
parent=(root)
|
||||
qualname=A
|
||||
handlers=
|
||||
|
||||
[logger_log03]
|
||||
level=CRITICAL
|
||||
propagate=1
|
||||
channel=B
|
||||
parent=log02
|
||||
qualname=A.B
|
||||
handlers=
|
||||
|
||||
[logger_log04]
|
||||
level=CRITICAL
|
||||
propagate=1
|
||||
channel=C
|
||||
parent=log03
|
||||
qualname=A.B.C
|
||||
handlers=
|
||||
|
||||
[logger_log05]
|
||||
level=CRITICAL
|
||||
propagate=1
|
||||
channel=D
|
||||
parent=log04
|
||||
qualname=A.B.C.D
|
||||
handlers=
|
||||
|
||||
[handler_hand01]
|
||||
class=StreamHandler
|
||||
level=NOTSET
|
||||
formatter=form01
|
||||
stream=sys.stderr
|
||||
args=(sys.stderr,)
|
||||
|
||||
[formatter_form01]
|
||||
format=critical.ini %(name)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
[loggers]
|
||||
keys=root,log02,log03,log04,log05
|
||||
|
||||
[handlers]
|
||||
keys=hand01
|
||||
|
||||
[formatters]
|
||||
keys=form01
|
||||
|
||||
[logger_root]
|
||||
level=WARN
|
||||
propagate=1
|
||||
channel=
|
||||
parent=
|
||||
qualname=(root)
|
||||
handlers=hand01
|
||||
|
||||
[logger_log02]
|
||||
level=DEBUG
|
||||
propagate=1
|
||||
channel=A
|
||||
parent=(root)
|
||||
qualname=A
|
||||
handlers=
|
||||
|
||||
[logger_log03]
|
||||
level=DEBUG
|
||||
propagate=1
|
||||
channel=B
|
||||
parent=log02
|
||||
qualname=A.B
|
||||
handlers=
|
||||
|
||||
[logger_log04]
|
||||
level=DEBUG
|
||||
propagate=1
|
||||
channel=C
|
||||
parent=log03
|
||||
qualname=A.B.C
|
||||
handlers=
|
||||
|
||||
[logger_log05]
|
||||
level=DEBUG
|
||||
propagate=1
|
||||
channel=D
|
||||
parent=log04
|
||||
qualname=A.B.C.D
|
||||
handlers=
|
||||
|
||||
[handler_hand01]
|
||||
class=StreamHandler
|
||||
level=NOTSET
|
||||
formatter=form01
|
||||
stream=sys.stderr
|
||||
args=(sys.stderr,)
|
||||
|
||||
[formatter_form01]
|
||||
format=debug.ini %(name)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
[loggers]
|
||||
keys=root,log02,log03,log04,log05
|
||||
|
||||
[handlers]
|
||||
keys=hand01
|
||||
|
||||
[formatters]
|
||||
keys=form01
|
||||
|
||||
[logger_root]
|
||||
level=WARN
|
||||
propagate=1
|
||||
channel=
|
||||
parent=
|
||||
qualname=(root)
|
||||
handlers=hand01
|
||||
|
||||
[logger_log02]
|
||||
level=ERROR
|
||||
propagate=1
|
||||
channel=A
|
||||
parent=(root)
|
||||
qualname=A
|
||||
handlers=
|
||||
|
||||
[logger_log03]
|
||||
level=ERROR
|
||||
propagate=1
|
||||
channel=B
|
||||
parent=log02
|
||||
qualname=A.B
|
||||
handlers=
|
||||
|
||||
[logger_log04]
|
||||
level=ERROR
|
||||
propagate=1
|
||||
channel=C
|
||||
parent=log03
|
||||
qualname=A.B.C
|
||||
handlers=
|
||||
|
||||
[logger_log05]
|
||||
level=ERROR
|
||||
propagate=1
|
||||
channel=D
|
||||
parent=log04
|
||||
qualname=A.B.C.D
|
||||
handlers=
|
||||
|
||||
[handler_hand01]
|
||||
class=StreamHandler
|
||||
level=NOTSET
|
||||
formatter=form01
|
||||
stream=sys.stderr
|
||||
args=(sys.stderr,)
|
||||
|
||||
[formatter_form01]
|
||||
format=error.ini %(name)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
<event name="root" level="20" filename="log_test9.py" lineno="66">
|
||||
<message>Info index = 90</message>
|
||||
</event>
|
||||
<event name="root" level="20" filename="log_test9.py" lineno="66">
|
||||
<message>Info index = 91</message>
|
||||
</event>
|
||||
<event name="root" level="20" filename="log_test9.py" lineno="66">
|
||||
<message>Info index = 92</message>
|
||||
</event>
|
||||
<event name="root" level="20" filename="log_test9.py" lineno="66">
|
||||
<message>Info index = 93</message>
|
||||
</event>
|
||||
<event name="root" level="20" filename="log_test9.py" lineno="66">
|
||||
<message>Info index = 94</message>
|
||||
</event>
|
||||
<event name="root" level="20" filename="log_test9.py" lineno="66">
|
||||
<message>Info index = 95</message>
|
||||
</event>
|
||||
<event name="root" level="20" filename="log_test9.py" lineno="66">
|
||||
<message>Info index = 96</message>
|
||||
</event>
|
||||
<event name="root" level="20" filename="log_test9.py" lineno="66">
|
||||
<message>Info index = 97</message>
|
||||
</event>
|
||||
<event name="root" level="20" filename="log_test9.py" lineno="66">
|
||||
<message>Info index = 98</message>
|
||||
</event>
|
||||
<event name="root" level="20" filename="log_test9.py" lineno="66">
|
||||
<message>Info index = 99</message>
|
||||
</event>
|
||||
@@ -1,158 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""Test harness for the logging module. Run all tests.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import os, sys, logging, threading, time
|
||||
|
||||
BANNER = "-- %-10s %-6s --------------------------------------------------------\n"
|
||||
|
||||
def banner(nm, typ):
|
||||
sep = BANNER % (nm, typ)
|
||||
sys.stdout.write(sep)
|
||||
sys.stdout.flush()
|
||||
sys.stderr.write(sep)
|
||||
sys.stderr.flush()
|
||||
|
||||
def main():
|
||||
oldout = sys.stdout
|
||||
olderr = sys.stderr
|
||||
sys.stdout = open("stdout.log", "w")
|
||||
sys.stderr = open("stderr.log", "w")
|
||||
logging.basicConfig()
|
||||
root = logging.getLogger("")
|
||||
hdlr0 = root.handlers[0]
|
||||
#Set up servers
|
||||
import logrecv
|
||||
threads = []
|
||||
tcpserver = logrecv.LogRecordSocketReceiver()
|
||||
tcpserver.logname = ""
|
||||
threads.append(threading.Thread(target=logrecv.runTCP, args=(tcpserver,)))
|
||||
udpserver = logrecv.LogRecordDatagramReceiver()
|
||||
udpserver.logname = ""
|
||||
threads.append(threading.Thread(target=logrecv.runUDP, args=(udpserver,)))
|
||||
httpserver = logrecv.LogRecordHTTPReceiver()
|
||||
httpserver.logname = ""
|
||||
threads.append(threading.Thread(target=logrecv.runHTTP, args=(httpserver,)))
|
||||
soapserver = None
|
||||
if logrecv.SOAPServer:
|
||||
soapserver = logrecv.SOAPServer()
|
||||
soapserver.modules = (sys.modules["logrecv"],)
|
||||
soapserver.logname = ""
|
||||
threads.append(threading.Thread(target=logrecv.runSOAP, args=(soapserver,)))
|
||||
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
try:
|
||||
import log_test0
|
||||
banner("log_test0", "begin")
|
||||
log_test0.main()
|
||||
banner("log_test0", "end")
|
||||
try:
|
||||
import log_test1
|
||||
banner("log_test1", "begin")
|
||||
log_test1.main()
|
||||
banner("log_test1", "end")
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
import log_test2
|
||||
banner("log_test2", "begin")
|
||||
log_test2.main()
|
||||
banner("log_test2", "end")
|
||||
time.sleep(3)
|
||||
|
||||
#Skip 3 as it tests fileConfig
|
||||
|
||||
banner("log_test4", "begin")
|
||||
import log_test4
|
||||
banner("log_test4", "end")
|
||||
|
||||
#Skip 5 as it tests SMTPHandler, can't easily check results automatically
|
||||
|
||||
#Skip 6 as it tests NTEventLogHandler, can't easily check results automatically
|
||||
|
||||
banner("log_test7", "begin")
|
||||
root.removeHandler(hdlr0)
|
||||
import log_test7
|
||||
root.addHandler(hdlr0)
|
||||
banner("log_test7", "end")
|
||||
|
||||
banner("log_test8", "begin")
|
||||
import log_test8
|
||||
root.removeHandler(hdlr0)
|
||||
log_test8.main()
|
||||
root.addHandler(hdlr0)
|
||||
banner("log_test8", "end")
|
||||
|
||||
banner("log_test9", "begin")
|
||||
import log_test9
|
||||
root.removeHandler(hdlr0)
|
||||
log_test9.main()
|
||||
root.addHandler(hdlr0)
|
||||
banner("log_test9", "end")
|
||||
|
||||
banner("log_test10", "begin")
|
||||
import log_test10
|
||||
log_test10.main()
|
||||
banner("log_test10", "end")
|
||||
|
||||
#Skip 11 as it tests SMTPHandler, can't easily check results automatically
|
||||
|
||||
import log_test12
|
||||
banner("log_test12", "begin")
|
||||
log_test12.main()
|
||||
banner("log_test12", "end")
|
||||
|
||||
import log_test13
|
||||
banner("log_test13", "begin")
|
||||
log_test13.main()
|
||||
banner("log_test13", "end")
|
||||
|
||||
import log_test15
|
||||
banner("log_test15", "begin")
|
||||
log_test15.test(log_test15.FILTER)
|
||||
banner("log_test15", "end")
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
finally:
|
||||
#shut down servers
|
||||
olderr.write("Tidying up...")
|
||||
tcpserver.abort = 1
|
||||
udpserver.abort = 1
|
||||
httpserver.abort = 1
|
||||
if soapserver:
|
||||
soapserver.abort = 1
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
sys.stdout.close()
|
||||
sys.stdout = oldout
|
||||
#don't close this, as hdlr0 references it. hdlr0 will be closed at application exit
|
||||
#sys.stderr.close()
|
||||
sys.stderr = olderr
|
||||
print "Test run completed."
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,118 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""Test harness for the logging module. A basic test of levels.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import logging
|
||||
msgcount = 0
|
||||
|
||||
def nextmessage():
|
||||
global msgcount
|
||||
rv = "Message %d" % msgcount
|
||||
msgcount = msgcount + 1
|
||||
return rv
|
||||
|
||||
def main():
|
||||
logging.basicConfig()
|
||||
logging.getLogger("").setLevel(logging.DEBUG)
|
||||
ERR = logging.getLogger("ERR")
|
||||
ERR.setLevel(logging.ERROR)
|
||||
INF = logging.getLogger("INF")
|
||||
INF.setLevel(logging.INFO)
|
||||
INF_ERR = logging.getLogger("INF.ERR")
|
||||
INF_ERR.setLevel(logging.ERROR)
|
||||
DEB = logging.getLogger("DEB")
|
||||
DEB.setLevel(logging.DEBUG)
|
||||
|
||||
INF_UNDEF = logging.getLogger("INF.UNDEF")
|
||||
INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF")
|
||||
UNDEF = logging.getLogger("UNDEF")
|
||||
|
||||
GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF")
|
||||
CHILD = logging.getLogger("INF.BADPARENT")
|
||||
|
||||
#These should log
|
||||
ERR.log(logging.CRITICAL, nextmessage())
|
||||
ERR.error(nextmessage())
|
||||
|
||||
INF.log(logging.CRITICAL, nextmessage())
|
||||
INF.error(nextmessage())
|
||||
INF.warning(nextmessage())
|
||||
INF.info(nextmessage())
|
||||
|
||||
INF_UNDEF.log(logging.CRITICAL, nextmessage())
|
||||
INF_UNDEF.error(nextmessage())
|
||||
INF_UNDEF.warning(nextmessage())
|
||||
INF_UNDEF.info(nextmessage())
|
||||
|
||||
INF_ERR.log(logging.CRITICAL, nextmessage())
|
||||
INF_ERR.error(nextmessage())
|
||||
|
||||
INF_ERR_UNDEF.log(logging.CRITICAL, nextmessage())
|
||||
INF_ERR_UNDEF.error(nextmessage())
|
||||
|
||||
DEB.log(logging.CRITICAL, nextmessage())
|
||||
DEB.error(nextmessage())
|
||||
DEB.warning(nextmessage())
|
||||
DEB.info(nextmessage())
|
||||
DEB.debug(nextmessage())
|
||||
|
||||
UNDEF.log(logging.CRITICAL, nextmessage())
|
||||
UNDEF.error(nextmessage())
|
||||
UNDEF.warning(nextmessage())
|
||||
UNDEF.info(nextmessage())
|
||||
|
||||
GRANDCHILD.log(logging.CRITICAL, nextmessage())
|
||||
CHILD.log(logging.CRITICAL, nextmessage())
|
||||
|
||||
#These should not log
|
||||
ERR.warning(nextmessage())
|
||||
ERR.info(nextmessage())
|
||||
ERR.debug(nextmessage())
|
||||
|
||||
INF.debug(nextmessage())
|
||||
INF_UNDEF.debug(nextmessage())
|
||||
|
||||
INF_ERR.warning(nextmessage())
|
||||
INF_ERR.info(nextmessage())
|
||||
INF_ERR.debug(nextmessage())
|
||||
INF_ERR_UNDEF.warning(nextmessage())
|
||||
INF_ERR_UNDEF.info(nextmessage())
|
||||
INF_ERR_UNDEF.debug(nextmessage())
|
||||
|
||||
INF.info("Messages should bear numbers 0 through 24.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
#print sys.argv[0]
|
||||
args = sys.argv[1:]
|
||||
if "-profile" in args:
|
||||
import profile, pstats
|
||||
args.remove("-profile")
|
||||
statf = "log_test0.pro"
|
||||
profile.run("main()", statf)
|
||||
stats = pstats.Stats(statf)
|
||||
stats.strip_dirs().sort_stats('time').print_stats()
|
||||
else:
|
||||
main()
|
||||
@@ -1,85 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""Test harness for the logging module. A test showing exception handling and use of SysLogHandler.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import sys, logging
|
||||
import syslog
|
||||
|
||||
class SLHandler(logging.Handler):
|
||||
def __init__(self, ident, logopt=0, facility=syslog.LOG_USER):
|
||||
logging.Handler.__init__(self)
|
||||
self.ident = ident
|
||||
self.logopt = logopt
|
||||
self.facility = facility
|
||||
self.mappings = {
|
||||
logging.DEBUG: syslog.LOG_DEBUG,
|
||||
logging.INFO: syslog.LOG_INFO,
|
||||
logging.WARNING: syslog.LOG_WARNING,
|
||||
logging.ERROR: syslog.LOG_ERR,
|
||||
logging.CRITICAL: syslog.LOG_CRIT,
|
||||
}
|
||||
|
||||
def encodeLevel(self, level):
|
||||
return self.mappings.get(level, syslog.LOG_INFO)
|
||||
|
||||
def emit(self, record):
|
||||
syslog.openlog(self.ident, self.logopt, self.facility)
|
||||
msg = self.format(record)
|
||||
prio = self.encodeLevel(record.levelno)
|
||||
syslog.syslog(prio, msg)
|
||||
syslog.closelog()
|
||||
|
||||
def config():
|
||||
logging.basicConfig()
|
||||
logging.getLogger("").setLevel(logging.DEBUG)
|
||||
if __name__ == "__main__":
|
||||
fmt = logging.Formatter("%(asctime)s %(filename)s:%(lineno)d %(levelname)-5s - %(message)s")
|
||||
hdlr = logging.FileHandler("tmp.tmp")
|
||||
hdlr.setFormatter(fmt)
|
||||
logging.getLogger("").addHandler(hdlr)
|
||||
else:
|
||||
fmt = None
|
||||
hdlr = SLHandler("log_test1")
|
||||
if fmt:
|
||||
hdlr.setFormatter(fmt)
|
||||
logging.getLogger("").addHandler(hdlr)
|
||||
return hdlr
|
||||
|
||||
def run():
|
||||
logging.info("Starting...")
|
||||
try:
|
||||
print "7" + 4
|
||||
except Exception, e:
|
||||
logging.error("Problem %s (%d)", "ERROR", logging.ERROR, exc_info=1)
|
||||
logging.debug("Problem %s (%d)", "DEBUG", logging.DEBUG, exc_info=1)
|
||||
logging.info("Done.")
|
||||
|
||||
|
||||
def main():
|
||||
hdlr = config()
|
||||
run()
|
||||
logging.getLogger("").removeHandler(hdlr)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,87 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""Test harness for the logging module. Shows use of a user-defined Logger subclass.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import sys
|
||||
import locale
|
||||
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
|
||||
from logging import *
|
||||
|
||||
LOG_FORMAT = "%(asctime)s %(levelname)-5s %(message)s"
|
||||
DATE_FORMAT = "%x %X"
|
||||
|
||||
class MyLogger(Logger):
|
||||
"""
|
||||
A simple example of a logger extension.
|
||||
"""
|
||||
def debug(self, msg, *args, **kwargs):
|
||||
"""
|
||||
This overridden method passes exception information for DEBUG level calls
|
||||
"""
|
||||
if self.manager.disable >= DEBUG:
|
||||
return
|
||||
if DEBUG >= self.getEffectiveLevel():
|
||||
exc_info = kwargs.get("exc_info", 0)
|
||||
ei = None
|
||||
if exc_info:
|
||||
ei = sys.exc_info()
|
||||
if not ei[1]:
|
||||
ei = None
|
||||
self._log(DEBUG, msg, args, ei)
|
||||
del ei
|
||||
|
||||
class NotALogger:
|
||||
pass
|
||||
|
||||
def config():
|
||||
try:
|
||||
setLoggerClass(NotALogger)
|
||||
except Exception, e:
|
||||
sys.stderr.write("%s\n" % e)
|
||||
setLoggerClass(MyLogger)
|
||||
if __name__ == "__main__":
|
||||
basicConfig()
|
||||
if __name__ == "__main__":
|
||||
getLogger("").handlers[0].setFormatter(Formatter(LOG_FORMAT, DATE_FORMAT))
|
||||
|
||||
def run():
|
||||
getLogger("").setLevel(DEBUG)
|
||||
logger = getLogger("mylogger")
|
||||
logger.info("Starting...")
|
||||
logger.debug("Debug message not in exception handler (no traceback)")
|
||||
logger.info("About to throw exception...")
|
||||
try:
|
||||
print "7" + 4
|
||||
except Exception, e:
|
||||
logger.debug("Debug message inside exception handler (traceback)",exc_info=1)
|
||||
logger.info("Done.")
|
||||
|
||||
def main():
|
||||
config()
|
||||
run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,72 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""Test harness for the logging module. Tests BufferingSMTPHandler, an alternative implementation
|
||||
of SMTPHandler.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import string, logging, logging.handlers
|
||||
|
||||
MAILHOST = 'beta'
|
||||
FROM = 'log_test11@red-dove.com'
|
||||
TO = ['arkadi_renko']
|
||||
SUBJECT = 'Test Logging email from Python logging module (buffering)'
|
||||
|
||||
class BufferingSMTPHandler(logging.handlers.BufferingHandler):
|
||||
def __init__(self, mailhost, fromaddr, toaddrs, subject, capacity):
|
||||
logging.handlers.BufferingHandler.__init__(self, capacity)
|
||||
self.mailhost = mailhost
|
||||
self.mailport = None
|
||||
self.fromaddr = fromaddr
|
||||
self.toaddrs = toaddrs
|
||||
self.subject = subject
|
||||
self.setFormatter(logging.Formatter("%(asctime)s %(levelname)-5s %(message)s"))
|
||||
|
||||
def flush(self):
|
||||
if len(self.buffer) > 0:
|
||||
try:
|
||||
import smtplib
|
||||
port = self.mailport
|
||||
if not port:
|
||||
port = smtplib.SMTP_PORT
|
||||
smtp = smtplib.SMTP(self.mailhost, port)
|
||||
msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (self.fromaddr, string.join(self.toaddrs, ","), self.subject)
|
||||
for record in self.buffer:
|
||||
s = self.format(record)
|
||||
print s
|
||||
msg = msg + s + "\r\n"
|
||||
smtp.sendmail(self.fromaddr, self.toaddrs, msg)
|
||||
smtp.quit()
|
||||
except:
|
||||
self.handleError(None) # no particular record
|
||||
self.buffer = []
|
||||
|
||||
def test():
|
||||
logger = logging.getLogger("")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.addHandler(BufferingSMTPHandler(MAILHOST, FROM, TO, SUBJECT, 10))
|
||||
for i in xrange(102):
|
||||
logger.info("Info index = %d", i)
|
||||
logging.shutdown()
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests HTTPHandler.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import sys, string, logging, logging.handlers
|
||||
|
||||
def main():
|
||||
import pdb
|
||||
host = "localhost:%d" % logging.handlers.DEFAULT_HTTP_LOGGING_PORT
|
||||
gh = logging.handlers.HTTPHandler(host, '/log', 'GET')
|
||||
ph = logging.handlers.HTTPHandler(host, '/log', 'POST')
|
||||
logger = logging.getLogger("log_test12")
|
||||
logger.propagate = 0
|
||||
logger.addHandler(gh)
|
||||
logger.addHandler(ph)
|
||||
logging.getLogger("").setLevel(logging.DEBUG)
|
||||
logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz")
|
||||
logger.debug("Pack my %s with twelve dozen %s", "box", "liquor jugs")
|
||||
gh.close()
|
||||
ph.close()
|
||||
logger.removeHandler(gh)
|
||||
logger.removeHandler(ph)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,106 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Implements a SOAPHandler class which
|
||||
can be used to form the basis of extended SOAP functionality.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import string, logging, logging.handlers, types
|
||||
|
||||
SOAP_MESSAGE = """<SOAP-ENV:Envelope
|
||||
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:logging="http://www.red-dove.com/logging"
|
||||
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
|
||||
>
|
||||
<SOAP-ENV:Body>
|
||||
<logging:log>
|
||||
%s
|
||||
</logging:log>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>
|
||||
"""
|
||||
|
||||
class SOAPHandler(logging.Handler):
|
||||
"""
|
||||
A class which sends records to a SOAP server.
|
||||
"""
|
||||
def __init__(self, host, url):
|
||||
"""
|
||||
Initialize the instance with the host and the request URL
|
||||
"""
|
||||
logging.Handler.__init__(self)
|
||||
self.host = host
|
||||
self.url = url
|
||||
|
||||
def emit(self, record):
|
||||
"""
|
||||
Send the record to the Web server as a SOAP message
|
||||
"""
|
||||
try:
|
||||
import httplib
|
||||
h = httplib.HTTP(self.host)
|
||||
h.putrequest("POST", self.url)
|
||||
keys = record.__dict__.keys()
|
||||
keys.sort()
|
||||
args = ""
|
||||
for key in keys:
|
||||
v = record.__dict__[key]
|
||||
if type(v) == types.StringType:
|
||||
t = "string"
|
||||
elif (type(v) == types.IntType) or (type(v) == types.LongType):
|
||||
t = "integer"
|
||||
elif type(v) == types.FloatType:
|
||||
t = "float"
|
||||
else:
|
||||
t = "string"
|
||||
args = args + "%12s<logging:%s xsi:type=\"xsd:%s\">%s</logging:%s>\n" % ("",
|
||||
key, t, str(v), key)
|
||||
data = SOAP_MESSAGE % args[:-1]
|
||||
h.putheader("Content-type", "text/plain; charset=\"utf-8\"")
|
||||
h.putheader("Content-length", str(len(data)))
|
||||
h.endheaders()
|
||||
#print data
|
||||
h.send(data)
|
||||
r = h.getreply() #can't do anything with the result
|
||||
f = h.getfile()
|
||||
if f:
|
||||
#print f.read()
|
||||
f.close()
|
||||
except:
|
||||
self.handleError(record)
|
||||
|
||||
def main():
|
||||
sh = SOAPHandler('localhost:%d' % logging.handlers.DEFAULT_SOAP_LOGGING_PORT, '/log')
|
||||
logger = logging.getLogger("log_test13")
|
||||
logging.getLogger("").setLevel(logging.DEBUG)
|
||||
logger.propagate = 0
|
||||
logger.addHandler(sh)
|
||||
logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz")
|
||||
logger.debug("Pack my %s with five dozen %s", "box", "liquor jugs")
|
||||
logger.removeHandler(sh)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. An example handler - DBHandler -
|
||||
which writes to an Python DB API 2.0 data source. You'll need to set this
|
||||
source up before you run the test.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import sys, string, time, logging
|
||||
|
||||
class DBHandler(logging.Handler):
|
||||
def __init__(self, dsn, uid='', pwd=''):
|
||||
logging.Handler.__init__(self)
|
||||
import mx.ODBC.Windows
|
||||
self.dsn = dsn
|
||||
self.uid = uid
|
||||
self.pwd = pwd
|
||||
self.conn = mx.ODBC.Windows.connect(self.dsn, self.uid, self.pwd)
|
||||
self.SQL = """INSERT INTO Events (
|
||||
Created,
|
||||
RelativeCreated,
|
||||
Name,
|
||||
LogLevel,
|
||||
LevelText,
|
||||
Message,
|
||||
Filename,
|
||||
Pathname,
|
||||
Lineno,
|
||||
Milliseconds,
|
||||
Exception,
|
||||
Thread
|
||||
)
|
||||
VALUES (
|
||||
%(dbtime)s,
|
||||
%(relativeCreated)d,
|
||||
'%(name)s',
|
||||
%(levelno)d,
|
||||
'%(levelname)s',
|
||||
'%(message)s',
|
||||
'%(filename)s',
|
||||
'%(pathname)s',
|
||||
%(lineno)d,
|
||||
%(msecs)d,
|
||||
'%(exc_text)s',
|
||||
'%(thread)s'
|
||||
);
|
||||
"""
|
||||
self.cursor = self.conn.cursor()
|
||||
|
||||
def formatDBTime(self, record):
|
||||
record.dbtime = time.strftime("#%m/%d/%Y#", time.localtime(record.created))
|
||||
|
||||
def emit(self, record):
|
||||
try:
|
||||
#use default formatting
|
||||
self.format(record)
|
||||
#now set the database time up
|
||||
self.formatDBTime(record)
|
||||
if record.exc_info:
|
||||
record.exc_text = logging._defaultFormatter.formatException(record.exc_info)
|
||||
else:
|
||||
record.exc_text = ""
|
||||
sql = self.SQL % record.__dict__
|
||||
self.cursor.execute(sql)
|
||||
self.conn.commit()
|
||||
except:
|
||||
import traceback
|
||||
ei = sys.exc_info()
|
||||
traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
|
||||
del ei
|
||||
|
||||
def close(self):
|
||||
self.cursor.close()
|
||||
self.conn.close()
|
||||
logging.Handler.close(self)
|
||||
|
||||
dh = DBHandler('Logging')
|
||||
logger = logging.getLogger("")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.addHandler(dh)
|
||||
logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz")
|
||||
logger.debug("Pack my %s with five dozen %s", "box", "liquor jugs")
|
||||
try:
|
||||
import math
|
||||
math.exp(1000)
|
||||
except:
|
||||
logger.exception("Problem with %s", "math.exp")
|
||||
logging.shutdown()
|
||||
@@ -1,70 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests Filter.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import sys, logging
|
||||
|
||||
FILTER = "a.b"
|
||||
|
||||
def message(s):
|
||||
sys.stderr.write("%s\n" % s)
|
||||
|
||||
def doLog():
|
||||
logging.getLogger("a").info("Info 1")
|
||||
logging.getLogger("a.b").info("Info 2")
|
||||
logging.getLogger("a.c").info("Info 3")
|
||||
logging.getLogger("a.b.c").info("Info 4")
|
||||
logging.getLogger("a.b.c.d").info("Info 5")
|
||||
logging.getLogger("a.bb.c").info("Info 6")
|
||||
logging.getLogger("b").info("Info 7")
|
||||
logging.getLogger("b.a").info("Info 8")
|
||||
logging.getLogger("c.a.b").info("Info 9")
|
||||
logging.getLogger("a.bb").info("Info 10")
|
||||
|
||||
def test(fs):
|
||||
root = logging.getLogger()
|
||||
root.setLevel(logging.DEBUG)
|
||||
if __name__ == "__main__":
|
||||
hand = logging.StreamHandler()
|
||||
hand.setFormatter(logging.Formatter("%(name)-10s %(message)s"))
|
||||
root.addHandler(hand)
|
||||
else:
|
||||
hand = root.handlers[0]
|
||||
message("Unfiltered...")
|
||||
doLog()
|
||||
message("Filtered with '%s'..." % fs)
|
||||
filt = logging.Filter(fs)
|
||||
hand.addFilter(filt)
|
||||
doLog()
|
||||
hand.removeFilter(filt)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
if len(sys.argv) > 1:
|
||||
fs = sys.argv[1]
|
||||
else:
|
||||
fs = FILTER
|
||||
test(fs)
|
||||
@@ -1,73 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests thread safety.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import logging, logging.handlers, thread, threading, random
|
||||
|
||||
logging.raiseExceptions = 1
|
||||
|
||||
NUM_THREADS = 10
|
||||
LOOP_COUNT = 10000
|
||||
|
||||
LOG_MESSAGES = [
|
||||
(logging.DEBUG, "%3d This is a %s message", "debug"),
|
||||
(logging.INFO, "%3d This is an %s message", "informational"),
|
||||
(logging.WARNING, "%3d This is a %s message", "warning"),
|
||||
(logging.ERROR, "%3d This is an %s message", "error"),
|
||||
(logging.CRITICAL, "%3d This is a %s message", "critical"),
|
||||
]
|
||||
|
||||
LOG_NAMES = ["A", "A.B", "A.B.C", "A.B.C.D"]
|
||||
|
||||
def doLog(num):
|
||||
logger = logging.getLogger('')
|
||||
logger.info("*** thread %s started (%d)", thread.get_ident(), num)
|
||||
for i in xrange(LOOP_COUNT):
|
||||
logger = logging.getLogger(random.choice(LOG_NAMES))
|
||||
a = random.choice(LOG_MESSAGES)
|
||||
args = a[0:2] + (num,) + a[2:]
|
||||
apply(logger.log, args)
|
||||
|
||||
def test():
|
||||
f = logging.Formatter("%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s")
|
||||
root = logging.getLogger('')
|
||||
root.setLevel(logging.DEBUG)
|
||||
h = logging.FileHandler('thread.log', 'w')
|
||||
root.addHandler(h)
|
||||
h.setFormatter(f)
|
||||
h = logging.handlers.SocketHandler('localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
|
||||
#h = logging.handlers.DatagramHandler('localhost', logging.handlers.DEFAULT_UDP_LOGGING_PORT)
|
||||
root.addHandler(h)
|
||||
threads = []
|
||||
for i in xrange(NUM_THREADS):
|
||||
threads.append(threading.Thread(target=doLog, args=(len(threads),)))
|
||||
for t in threads:
|
||||
t.start()
|
||||
for t in threads:
|
||||
t.join()
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
||||
@@ -1,111 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests thread safety.
|
||||
|
||||
To use as a server, run with no arguments in one process.
|
||||
To use as a client, run with arguments "-client <filename>" where <filename>
|
||||
is the name of a file containing a logging configuration.
|
||||
The example files debug.ini, warn.ini, error.ini and critical.ini are
|
||||
provided to use in the test. They each have a customized message format
|
||||
(prefixed with their name) and the loggers have their levels set to the
|
||||
value implied by their name.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import sys, logging, logging.config, thread, threading, random, time, struct
|
||||
|
||||
NUM_THREADS = 10
|
||||
LOOP_COUNT = 10
|
||||
|
||||
CONFIG_PORT = 9077
|
||||
|
||||
logging.raiseExceptions = 1
|
||||
|
||||
LOG_MESSAGES = [
|
||||
(logging.DEBUG, "%3d This is a %s message", "debug"),
|
||||
(logging.INFO, "%3d This is an %s message", "informational"),
|
||||
(logging.WARNING, "%3d This is a %s message", "warning"),
|
||||
(logging.ERROR, "%3d This is an %s message", "error"),
|
||||
(logging.CRITICAL, "%3d This is a %s message", "critical"),
|
||||
]
|
||||
|
||||
LOG_NAMES = ["A", "A.B", "A.B.C", "A.B.C.D"]
|
||||
|
||||
def doLog(num):
|
||||
logger = logging.getLogger('')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.info("*** thread %s started (%d)", thread.get_ident(), num)
|
||||
for i in xrange(LOOP_COUNT):
|
||||
logger = logging.getLogger(random.choice(LOG_NAMES))
|
||||
a = random.choice(LOG_MESSAGES)
|
||||
args = a[0:2] + (num,) + a[2:]
|
||||
time.sleep(random.random() * 3)
|
||||
apply(logger.log, args)
|
||||
|
||||
def runserver():
|
||||
f = logging.Formatter("%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s")
|
||||
root = logging.getLogger('')
|
||||
h = logging.StreamHandler()
|
||||
root.addHandler(h)
|
||||
h.setFormatter(f)
|
||||
threads = []
|
||||
for i in xrange(NUM_THREADS):
|
||||
threads.append(threading.Thread(target=doLog, args=(len(threads),)))
|
||||
threads.append(logging.config.listen(CONFIG_PORT)) #don't use default port
|
||||
for t in threads:
|
||||
t.start()
|
||||
for t in threads[:-1]:
|
||||
t.join()
|
||||
logging.config.stopListening()
|
||||
threads[-1].join()
|
||||
|
||||
def runclient(fname):
|
||||
import socket
|
||||
|
||||
print "configuring with '%s'" % fname
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect(('localhost', CONFIG_PORT))
|
||||
f = open(fname, "r")
|
||||
s = f.read()
|
||||
f.close()
|
||||
slen = struct.pack(">L", len(s))
|
||||
s = slen + s
|
||||
sentsofar = 0
|
||||
left = len(s)
|
||||
while left > 0:
|
||||
sent = sock.send(s[sentsofar:])
|
||||
sentsofar = sentsofar + sent
|
||||
left = left - sent
|
||||
sock.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "-client" not in sys.argv:
|
||||
runserver()
|
||||
else:
|
||||
sys.argv.remove("-client")
|
||||
if len(sys.argv) > 1:
|
||||
fname = sys.argv[1]
|
||||
else:
|
||||
fname = "warn.ini"
|
||||
runclient(fname)
|
||||
@@ -1,102 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests MatchFilter.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import logging, types, string
|
||||
|
||||
class MatchFilter(logging.Filter):
|
||||
def __init__(self, **kwargs):
|
||||
self.dict = kwargs
|
||||
|
||||
def matchOne(self, key, value, record):
|
||||
rv = getattr(record, key)
|
||||
if key != "name":
|
||||
if key not in ["message", "msg"]:
|
||||
return rv == value
|
||||
else:
|
||||
return string.find(str(rv), value) >= 0
|
||||
else:
|
||||
if rv == value:
|
||||
return 1
|
||||
nlen = len(value)
|
||||
if string.find(rv, value, 0, nlen) != 0:
|
||||
return 0
|
||||
if rv[nlen] == ".":
|
||||
return 1
|
||||
|
||||
def matchValue(self, key, record):
|
||||
vl = self.dict [key]
|
||||
if type(vl) != types.ListType:
|
||||
rv = self.matchOne(key, vl, record)
|
||||
else:
|
||||
for v in vl:
|
||||
rv = self.matchOne(key, v, record)
|
||||
if rv:
|
||||
break
|
||||
return rv
|
||||
|
||||
def filter(self, record):
|
||||
rv = 1
|
||||
for k in self.dict.keys():
|
||||
if self.matchValue(k, record):
|
||||
rv = 0
|
||||
break
|
||||
return rv
|
||||
|
||||
def doLog(logger, n):
|
||||
logger.debug("Debug %d" % n)
|
||||
logger.info("Info %d" % n)
|
||||
logger.warning("Warning %d" % n)
|
||||
logger.error("Error %d" % n)
|
||||
logger.critical("Critical %d" % n)
|
||||
|
||||
def test():
|
||||
fmt = logging.Formatter("%(name)-10s %(levelname)-9s %(message)s")
|
||||
hand = logging.StreamHandler()
|
||||
hand.setFormatter(fmt)
|
||||
root = logging.getLogger("")
|
||||
root.setLevel(logging.DEBUG)
|
||||
root.addHandler(hand)
|
||||
loggers = ['A',
|
||||
'A.B',
|
||||
'A.BB',
|
||||
'A.C',
|
||||
'AA.B',
|
||||
'A.B.C',
|
||||
'A.B.C.D',
|
||||
'A.B.C.D.E',
|
||||
'Z.A.B',
|
||||
]
|
||||
filt = MatchFilter(name = ['A.C', 'A.B.C'], #reject these loggers and their children
|
||||
levelno = [logging.WARNING, logging.CRITICAL], #reject these levels,
|
||||
msg = 'bug 2' #reject if this in message
|
||||
)
|
||||
hand.addFilter(filt)
|
||||
for log in loggers:
|
||||
doLog(logging.getLogger(log), loggers.index(log))
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""Test harness for the logging module. A basic test of parents.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
def main():
|
||||
logging.basicConfig()
|
||||
root = logging.getLogger("")
|
||||
ab = logging.getLogger("a.b")
|
||||
abc = logging.getLogger("a.b.c")
|
||||
root.setLevel(logging.ERROR)
|
||||
ab.setLevel(logging.INFO)
|
||||
abc.info("Info")
|
||||
abc.warning("Warning")
|
||||
abc.error("Error")
|
||||
print "abc = %s" % abc
|
||||
print "abc.parent = %s" % abc.parent
|
||||
print "ab = %s" % ab
|
||||
print "ab.parent = %s" % ab.parent
|
||||
print "root = %s" % root
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
print sys.argv[0]
|
||||
args = sys.argv[1:]
|
||||
if "-profile" in args:
|
||||
import profile, pstats
|
||||
args.remove("-profile")
|
||||
statf = "log_test19.pro"
|
||||
profile.run("main()", statf)
|
||||
stats = pstats.Stats(statf)
|
||||
stats.strip_dirs().sort_stats('time').print_stats()
|
||||
else:
|
||||
main()
|
||||
@@ -1,119 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests logger levels and basic Formatter, and logging to
|
||||
sockets.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import logging, logging.handlers, socket
|
||||
|
||||
msgcount = 0
|
||||
|
||||
def nextmessage():
|
||||
global msgcount
|
||||
rv = "Message %d" % msgcount
|
||||
msgcount = msgcount + 1
|
||||
return rv
|
||||
|
||||
def main():
|
||||
logging.basicConfig()
|
||||
logging.getLogger("").setLevel(logging.DEBUG)
|
||||
hdlr = logging.handlers.SocketHandler('localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
|
||||
if __name__ == "__main__":
|
||||
hdlr.setFormatter(logging.Formatter("%(asctime)s %(name)-19s %(levelname)-5s - %(message)s"))
|
||||
logging.getLogger("").addHandler(hdlr)
|
||||
ERR = logging.getLogger("ERR")
|
||||
ERR.setLevel(logging.ERROR)
|
||||
INF = logging.getLogger("INF")
|
||||
INF.setLevel(logging.INFO)
|
||||
INF_ERR = logging.getLogger("INF.ERR")
|
||||
INF_ERR.setLevel(logging.ERROR)
|
||||
DEB = logging.getLogger("DEB")
|
||||
DEB.setLevel(logging.DEBUG)
|
||||
|
||||
INF_UNDEF = logging.getLogger("INF.UNDEF")
|
||||
INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF")
|
||||
UNDEF = logging.getLogger("UNDEF")
|
||||
|
||||
GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF")
|
||||
CHILD = logging.getLogger("INF.BADPARENT")
|
||||
|
||||
#These should log
|
||||
ERR.log(logging.CRITICAL, nextmessage())
|
||||
ERR.error(nextmessage())
|
||||
|
||||
INF.log(logging.CRITICAL, nextmessage())
|
||||
INF.error(nextmessage())
|
||||
INF.warning(nextmessage())
|
||||
INF.info(nextmessage())
|
||||
|
||||
INF_UNDEF.log(logging.CRITICAL, nextmessage())
|
||||
INF_UNDEF.error(nextmessage())
|
||||
INF_UNDEF.warning(nextmessage())
|
||||
INF_UNDEF.info(nextmessage())
|
||||
|
||||
INF_ERR.log(logging.CRITICAL, nextmessage())
|
||||
INF_ERR.error(nextmessage())
|
||||
|
||||
INF_ERR_UNDEF.log(logging.CRITICAL, nextmessage())
|
||||
INF_ERR_UNDEF.error(nextmessage())
|
||||
|
||||
DEB.log(logging.CRITICAL, nextmessage())
|
||||
DEB.error(nextmessage())
|
||||
DEB.warning(nextmessage())
|
||||
DEB.info(nextmessage())
|
||||
DEB.debug(nextmessage())
|
||||
|
||||
UNDEF.log(logging.CRITICAL, nextmessage())
|
||||
UNDEF.error(nextmessage())
|
||||
UNDEF.warning(nextmessage())
|
||||
UNDEF.info(nextmessage())
|
||||
|
||||
GRANDCHILD.log(logging.CRITICAL, nextmessage())
|
||||
CHILD.log(logging.CRITICAL, nextmessage())
|
||||
|
||||
#These should not log
|
||||
ERR.warning(nextmessage())
|
||||
ERR.info(nextmessage())
|
||||
ERR.debug(nextmessage())
|
||||
|
||||
INF.debug(nextmessage())
|
||||
INF_UNDEF.debug(nextmessage())
|
||||
|
||||
INF_ERR.warning(nextmessage())
|
||||
INF_ERR.info(nextmessage())
|
||||
INF_ERR.debug(nextmessage())
|
||||
INF_ERR_UNDEF.warning(nextmessage())
|
||||
INF_ERR_UNDEF.info(nextmessage())
|
||||
INF_ERR_UNDEF.debug(nextmessage())
|
||||
|
||||
INF.info("Messages should bear numbers 0 through 24.")
|
||||
hdlr.close()
|
||||
logging.getLogger("").removeHandler(hdlr)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except socket.error:
|
||||
print "\nA socket error occurred. Ensure that logrecv.py is running to receive logging requests from this script."
|
||||
@@ -1,84 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""Test harness for the logging module. Demonstrates the use of custom class
|
||||
instances for messages and filtering based on classes.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
class MyClass:
|
||||
def __init__(self, arg1, arg2):
|
||||
self.arg1 = arg1
|
||||
self.arg2 = arg2
|
||||
|
||||
def __str__(self):
|
||||
return "%s, %s" % (self.arg1, self.arg2)
|
||||
|
||||
class MyChildClass(MyClass):
|
||||
pass
|
||||
|
||||
class ClassFilter(logging.Filter):
|
||||
def __init__(self, klass):
|
||||
self.klass = klass
|
||||
|
||||
def filter(self, record):
|
||||
return isinstance(record.msg, self.klass)
|
||||
|
||||
class MyClassFilter(ClassFilter):
|
||||
def __init__(self, arg):
|
||||
ClassFilter.__init__(self, MyClass)
|
||||
self.arg = arg
|
||||
|
||||
def filter(self, record):
|
||||
return ClassFilter.filter(self, record) and (record.msg.arg2 == self.arg)
|
||||
|
||||
def main():
|
||||
handler = logging.StreamHandler()
|
||||
root = logging.getLogger("")
|
||||
root.setLevel(logging.DEBUG)
|
||||
root.addHandler(handler)
|
||||
root.addFilter(MyClassFilter("world"))
|
||||
#Not logged, as it's not a MyClass instance
|
||||
root.info("%s, %s", "Hello", "world")
|
||||
#Logged, as it's an appropriate instance which matches the filter criteria
|
||||
root.info(MyClass("Hello", "world"))
|
||||
#Not logged, as it's an appropriate class but doesn't match the filter criteria
|
||||
root.info(MyClass("Hello", "world!"))
|
||||
#Logged, as it's an appropriate instance which matches the filter criteria
|
||||
root.info(MyClass("Goodbye", "world"))
|
||||
#Logged, as it's an appropriate class which matches the filter criteria
|
||||
root.info(MyChildClass("Hello again", "world"))
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
args = sys.argv[1:]
|
||||
if "-profile" in args:
|
||||
import profile, pstats
|
||||
args.remove("-profile")
|
||||
statf = "log_test20.pro"
|
||||
profile.run("main()", statf)
|
||||
stats = pstats.Stats(statf)
|
||||
stats.strip_dirs().sort_stats('time').print_stats()
|
||||
else:
|
||||
main()
|
||||
@@ -1,141 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""Test harness for the logging module. Demonstrates the use of a wildcard
|
||||
name-space filter with and without custom message classes.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import logging, re, string, types
|
||||
|
||||
class TaggedEvent:
|
||||
def __init__(self, tag, msg):
|
||||
self.tag = tag
|
||||
self.msg = msg
|
||||
|
||||
def __str__(self):
|
||||
return "%s: %s" % (self.tag, self.msg)
|
||||
|
||||
class WildcardFilter(logging.Filter):
|
||||
def __init__(self, wildcards):
|
||||
self.setWildcards(wildcards)
|
||||
|
||||
def setWildcard(self, wildcard):
|
||||
arr = string.split(wildcard, ".")
|
||||
for i in xrange(len(arr)):
|
||||
s = arr[i]
|
||||
if s == "*":
|
||||
arr[i] = r'[\w.]*'
|
||||
elif string.find(s, "*") > 0:
|
||||
arr[i] = string.replace(s, "*", r'[\w]*')
|
||||
s = "^%s$" % string.join(arr, r'\.')
|
||||
self.patterns.append(re.compile(s))
|
||||
|
||||
def setWildcards(self, wildcards):
|
||||
if type(wildcards) != types.ListType:
|
||||
wildcards = [wildcards]
|
||||
self.patterns = []
|
||||
for wildcard in wildcards:
|
||||
self.setWildcard(wildcard)
|
||||
|
||||
def filter(self, record):
|
||||
rv = 0
|
||||
for pat in self.patterns:
|
||||
m = pat.match(record.name)
|
||||
if m is not None:
|
||||
rv = 1
|
||||
break
|
||||
return rv
|
||||
|
||||
class TagFilter(WildcardFilter):
|
||||
def filter(self, record):
|
||||
rv = 0
|
||||
if isinstance(record.msg, TaggedEvent):
|
||||
tag = record.msg.tag
|
||||
else:
|
||||
tag = record.name
|
||||
for pat in self.patterns:
|
||||
m = pat.match(tag)
|
||||
if m is not None:
|
||||
rv = 1
|
||||
break
|
||||
return rv
|
||||
|
||||
def main():
|
||||
handler = logging.StreamHandler()
|
||||
root = logging.getLogger("")
|
||||
root.setLevel(logging.DEBUG)
|
||||
ab = logging.getLogger("a.b")
|
||||
abc = logging.getLogger("a.b.c")
|
||||
|
||||
root.addHandler(handler)
|
||||
filter = WildcardFilter("*.b")
|
||||
handler.addFilter(filter)
|
||||
|
||||
ab.info("#1 from a.b") #logged
|
||||
abc.info("#1 from a.b.c") #not logged
|
||||
filter.setWildcards("*.b.c")
|
||||
ab.info("#2 from a.b") #not logged
|
||||
abc.info("#2 from a.b.c") #logged
|
||||
filter.setWildcards("*.b*")
|
||||
ab.info("#3 from a.b") #logged
|
||||
abc.info("#3 from a.b.c") #not logged
|
||||
filter.setWildcards("*")
|
||||
ab.info("#4 from a.b") #logged
|
||||
abc.info("#4 from a.b.c") #logged
|
||||
filter.setWildcards("a*")
|
||||
ab.info("#5 from a.b") #not logged
|
||||
abc.info("#5 from a.b.c") #not logged
|
||||
filter.setWildcards("a.*")
|
||||
ab.info("#6 from a.b") #logged
|
||||
abc.info("#6 from a.b.c") #logged
|
||||
filter.setWildcards("*.b.*")
|
||||
ab.info("#7 from a.b") #not logged
|
||||
abc.info("#7 from a.b.c") #logged
|
||||
filter.setWildcards(["*.b", "*.b.*"])
|
||||
ab.info("#8 from a.b") #logged
|
||||
abc.info("#8 from a.b.c") #logged
|
||||
filter.setWildcards(["a.*.c"])
|
||||
ab.info("#9 from a.b") #not logged
|
||||
abc.info("#9 from a.b.c") #logged
|
||||
|
||||
#Now test filtering with a tagged class
|
||||
handler.removeFilter(filter)
|
||||
tagfilter = TagFilter(["*.b", "*.b.*"])
|
||||
root.addFilter(tagfilter)
|
||||
root.info(TaggedEvent("a.b", "#10")) #logged
|
||||
root.info(TaggedEvent("a.c", "#10")) #not logged
|
||||
root.info(TaggedEvent("a.b.c", "#10")) #logged
|
||||
root.info(TaggedEvent("a.b.d", "#10")) #logged
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
args = sys.argv[1:]
|
||||
if "-profile" in args:
|
||||
import profile, pstats
|
||||
args.remove("-profile")
|
||||
statf = "log_test21.pro"
|
||||
profile.run("main()", statf)
|
||||
stats = pstats.Stats(statf)
|
||||
stats.strip_dirs().sort_stats('time').print_stats()
|
||||
else:
|
||||
main()
|
||||
@@ -1,50 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""Test harness for the logging module. Demonstrates the use of different
|
||||
converters for time(secs) -> time(tuple).
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import logging, time
|
||||
|
||||
def main():
|
||||
handler = logging.StreamHandler()
|
||||
f1 = logging.Formatter("%(asctime)s %(message)s", "%m/%d %H:%M:%S")
|
||||
f2 = logging.Formatter("%(asctime)s %(message)s", "%m/%d %H:%M:%S")
|
||||
f2.converter = time.gmtime
|
||||
handler.setFormatter(f1)
|
||||
root = logging.getLogger("")
|
||||
root.setLevel(logging.DEBUG)
|
||||
root.addHandler(handler)
|
||||
root.info("Something happened! [should be in local time]")
|
||||
handler.setFormatter(f2)
|
||||
root.info("Something else happened! [should be in GMT]")
|
||||
handler.setFormatter(f1)
|
||||
root.info("Something happened again! [should be in local time]")
|
||||
logging.Formatter.converter = time.gmtime
|
||||
root.info("Something else happened again! [should be in GMT]")
|
||||
logging.Formatter.converter = time.localtime
|
||||
root.info("Something else happened yet again! [should be in local time]")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,95 +0,0 @@
|
||||
[loggers]
|
||||
keys=root,area1,area11,area111,area1111,area11111,area111111
|
||||
|
||||
[handlers]
|
||||
keys=console,file,socket,datagram,syslog,NT,SMTP
|
||||
|
||||
[formatters]
|
||||
keys=short,medium,long
|
||||
|
||||
[logger_root]
|
||||
handlers=console
|
||||
level=DEBUG
|
||||
|
||||
[logger_area1]
|
||||
level=DEBUG
|
||||
qualname=log02
|
||||
handlers=file
|
||||
|
||||
[logger_area11]
|
||||
level=INFO
|
||||
qualname=log02.log03
|
||||
handlers=socket
|
||||
|
||||
[logger_area111]
|
||||
level=WARN
|
||||
propagate=0
|
||||
qualname=log02.log03.log04
|
||||
handlers=datagram
|
||||
|
||||
[logger_area1111]
|
||||
level=ERROR
|
||||
qualname=log02.log03.log04.log05
|
||||
handlers=syslog
|
||||
|
||||
[logger_area11111]
|
||||
level=CRITICAL
|
||||
qualname=log02.log03.log04.log05.log06
|
||||
handlers=NT
|
||||
|
||||
[logger_area111111]
|
||||
level=WARN
|
||||
qualname=log02.log03.log04.log05.log06.log07
|
||||
handlers=SMTP
|
||||
|
||||
[handler_console]
|
||||
class=StreamHandler
|
||||
formatter=medium
|
||||
stream=sys.stdout
|
||||
args=(sys.stdout,)
|
||||
|
||||
[handler_file]
|
||||
class=FileHandler
|
||||
level=DEBUG
|
||||
formatter=long
|
||||
args=('python.log', 'w')
|
||||
|
||||
[handler_socket]
|
||||
class=handlers.SocketHandler
|
||||
level=INFO
|
||||
formatter=medium
|
||||
args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)
|
||||
|
||||
[handler_datagram]
|
||||
class=handlers.DatagramHandler
|
||||
level=WARN
|
||||
formatter=medium
|
||||
args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)
|
||||
|
||||
[handler_syslog]
|
||||
class=handlers.SysLogHandler
|
||||
level=ERROR
|
||||
formatter=short
|
||||
args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
|
||||
|
||||
[handler_NT]
|
||||
class=handlers.NTEventLogHandler
|
||||
level=CRITICAL
|
||||
formatter=medium
|
||||
args=('Python Application', '', 'Application')
|
||||
|
||||
[handler_SMTP]
|
||||
class=handlers.SMTPHandler
|
||||
level=WARN
|
||||
formatter=long
|
||||
args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')
|
||||
|
||||
[formatter_short]
|
||||
format=%(message)s
|
||||
|
||||
[formatter_long]
|
||||
format=%(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s
|
||||
|
||||
[formatter_medium]
|
||||
format=%(asctime)s %(levelname)s %(message)s
|
||||
datefmt=%m-%d-%Y
|
||||
@@ -1,70 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests new fileConfig (not yet a complete test).
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import logging, logging.config
|
||||
|
||||
def doLog(logger):
|
||||
logger.debug("Debug")
|
||||
logger.info("Info")
|
||||
logger.warning("Warning")
|
||||
logger.error("Error")
|
||||
logger.critical("Critical")
|
||||
|
||||
def main():
|
||||
logging.config.fileConfig("log_test3.ini")
|
||||
logger = logging.getLogger(None)
|
||||
print "---------------------------------------------------"
|
||||
print "-- Logging to root; messages appear on console only"
|
||||
print "---------------------------------------------------"
|
||||
doLog(logger)
|
||||
print "----------------------------------------------------------------------"
|
||||
print "-- Logging to log02; messages appear on console and in file python.log"
|
||||
print "----------------------------------------------------------------------"
|
||||
logger = logging.getLogger("log02")
|
||||
doLog(logger)
|
||||
print "--------------------------------------------------------------------------"
|
||||
print "-- Logging to log02.log03; messages appear on console, in file python.log,"
|
||||
print "-- and at logrecv.py tcp (if running. <= DEBUG messages will not appear)."
|
||||
print "--------------------------------------------------------------------------"
|
||||
logger = logging.getLogger("log02.log03")
|
||||
doLog(logger)
|
||||
print "-----------------------------------------------------------------------"
|
||||
print "-- Logging to log02.log03.log04; messages appear only at logrecv.py udp"
|
||||
print "-- (if running. <= INFO messages will not appear)."
|
||||
print "-----------------------------------------------------------------------"
|
||||
logger = logging.getLogger("log02.log03.log04")
|
||||
doLog(logger)
|
||||
print "--------------------------------------------------------------------"
|
||||
print "-- Logging to log02.log03.log04.log05.log06; messages appear at"
|
||||
print "-- logrecv.py udp (if running. < CRITICAL messages will not appear)."
|
||||
print "--------------------------------------------------------------------"
|
||||
logger = logging.getLogger("log02.log03.log04.log05.log06")
|
||||
doLog(logger)
|
||||
print "-- All done."
|
||||
logging.shutdown()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,168 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests arbitrary logging levels, filtering, and
|
||||
use of strftime formatting.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import locale, sys
|
||||
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
|
||||
def message(s):
|
||||
sys.stderr.write("%s\n" % s)
|
||||
|
||||
#
|
||||
# First, we define our levels. There can be as many as you want - the only limitations are that
|
||||
# they should be integers, the lowest should be > 0 and larger values mean less information being
|
||||
# logged. If you need specific level values which do not fit into these limitations, you can use
|
||||
# a mapping dictionary to convert between your application levels and the logging system.
|
||||
#
|
||||
SILENT = 10
|
||||
TACITURN = 9
|
||||
TERSE = 8
|
||||
EFFUSIVE = 7
|
||||
SOCIABLE = 6
|
||||
VERBOSE = 5
|
||||
TALKATIVE = 4
|
||||
GARRULOUS = 3
|
||||
CHATTERBOX = 2
|
||||
BORING = 1
|
||||
|
||||
LEVEL_RANGE = range(BORING, SILENT + 1)
|
||||
|
||||
#
|
||||
# Next, we define names for our levels. You don't need to do this - in which case the system will
|
||||
# use "Level n" to denote the text for the level.
|
||||
#
|
||||
my_logging_levels = {
|
||||
SILENT : 'Silent',
|
||||
TACITURN : 'Taciturn',
|
||||
TERSE : 'Terse',
|
||||
EFFUSIVE : 'Effusive',
|
||||
SOCIABLE : 'Sociable',
|
||||
VERBOSE : 'Verbose',
|
||||
TALKATIVE : 'Talkative',
|
||||
GARRULOUS : 'Garrulous',
|
||||
CHATTERBOX: 'Chatterbox',
|
||||
BORING : 'Boring',
|
||||
}
|
||||
|
||||
#
|
||||
# Now, tell the logging system to associate names with our levels.
|
||||
#
|
||||
for lvl in my_logging_levels.keys():
|
||||
logging.addLevelName(lvl, my_logging_levels[lvl])
|
||||
|
||||
#
|
||||
# Now, define a test function which logs an event at each of our levels.
|
||||
#
|
||||
def doLog(log):
|
||||
for lvl in LEVEL_RANGE:
|
||||
log.log(lvl, "This should only be seen at the '%s' logging level (or lower)", logging.getLevelName(lvl))
|
||||
|
||||
#
|
||||
# Get the root logger and add a console hander to it, when run as a script.
|
||||
#
|
||||
log = logging.getLogger("")
|
||||
|
||||
if __name__ == "__main__":
|
||||
hdlr = logging.StreamHandler()
|
||||
hdlr.setFormatter(logging.Formatter("%(asctime)s %(message)s", "%X")) #date format is as per the locale
|
||||
log.addHandler(hdlr)
|
||||
else:
|
||||
hdlr = log.handlers[0]
|
||||
#
|
||||
# Set the logging level to each different value and call the utility function to log events.
|
||||
# In the output, you should see that each time round the loop, the logging events actually output
|
||||
# decreases.
|
||||
#
|
||||
for lvl in LEVEL_RANGE:
|
||||
message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
|
||||
log.setLevel(lvl)
|
||||
doLog(log)
|
||||
#
|
||||
# Now, we demonstrate level filtering at the handler level. Tell the handler defined above
|
||||
# to filter at level 'SOCIABLE', and repeat the above loop. Compare the output from the two runs.
|
||||
#
|
||||
hdlr.setLevel(SOCIABLE)
|
||||
message("-- Filtering at handler level to SOCIABLE --")
|
||||
for lvl in LEVEL_RANGE:
|
||||
message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
|
||||
log.setLevel(lvl)
|
||||
doLog(log)
|
||||
|
||||
hdlr.setLevel(0) #turn off level filtering at the handler
|
||||
|
||||
#
|
||||
# Now, let's demonstrate filtering. Suppose for some perverse reason we only want to print out
|
||||
# all except GARRULOUS messages. Let's create a filter for this purpose...
|
||||
#
|
||||
class SpecificLevelFilter(logging.Filter):
|
||||
def __init__(self, lvl):
|
||||
self.level = lvl
|
||||
|
||||
def filter(self, record):
|
||||
return self.level != record.levelno
|
||||
|
||||
class GarrulousFilter(SpecificLevelFilter):
|
||||
def __init__(self):
|
||||
SpecificLevelFilter.__init__(self, GARRULOUS)
|
||||
|
||||
garr = GarrulousFilter()
|
||||
hdlr.addFilter(garr)
|
||||
message("-- Filtering using GARRULOUS filter --")
|
||||
for lvl in LEVEL_RANGE:
|
||||
message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
|
||||
log.setLevel(lvl)
|
||||
doLog(log)
|
||||
#
|
||||
# Now, let's demonstrate filtering at the logger. This time, use a filter which excludes SOCIABLE
|
||||
# and TACITURN messages. Note that GARRULOUS events are still excluded.
|
||||
#
|
||||
class VerySpecificFilter(logging.Filter):
|
||||
def filter(self, record):
|
||||
return record.levelno not in [SOCIABLE, TACITURN]
|
||||
|
||||
spec = VerySpecificFilter()
|
||||
log.addFilter(spec)
|
||||
message("-- Filtering using specific filter for SOCIABLE, TACITURN --")
|
||||
for lvl in LEVEL_RANGE:
|
||||
message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl))
|
||||
log.setLevel(lvl)
|
||||
doLog(log)
|
||||
|
||||
log.removeFilter(spec)
|
||||
hdlr.removeFilter(garr)
|
||||
#Undo the one level which clashes...for regression tests
|
||||
logging.addLevelName(logging.DEBUG, "DEBUG")
|
||||
|
||||
#
|
||||
# Er...that's it for now
|
||||
#
|
||||
if __name__ == "__main__":
|
||||
print "All done."
|
||||
logging.shutdown()
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests SMTPHandler.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import logging, logging.handlers
|
||||
|
||||
MAILHOST = 'beta'
|
||||
FROM = 'log_test5@yourdomain.com'
|
||||
TO = ['arkadi_renko']
|
||||
SUBJECT = 'Test Logging email from Python logging module (non-buffering)'
|
||||
|
||||
def main():
|
||||
log = logging.getLogger("")
|
||||
log.setLevel(logging.DEBUG)
|
||||
hdlr = logging.handlers.SMTPHandler(MAILHOST, FROM, TO, SUBJECT)
|
||||
hdlr.setFormatter(logging.Formatter("%(asctime)s %(levelname)-5s %(message)s"))
|
||||
log.addHandler(hdlr)
|
||||
log.info("Test email contents")
|
||||
log.removeHandler(hdlr)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests NTEventLogHandler.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import logging, logging.handlers
|
||||
|
||||
def main():
|
||||
ntl = logging.handlers.NTEventLogHandler("Python Logging Test")
|
||||
logger = logging.getLogger("")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.addHandler(ntl)
|
||||
logger.debug("This is a '%s' message", "Debug")
|
||||
logger.info("This is a '%s' message", "Info")
|
||||
logger.warning("This is a '%s' message", "Warning")
|
||||
logger.error("This is a '%s' message", "Error")
|
||||
logger.critical("This is a '%s' message", "Critical")
|
||||
try:
|
||||
x = 4 / 0
|
||||
except:
|
||||
logger.info("This is an %s (or should that be %s?)", "informational exception", "exceptional information", exc_info=1)
|
||||
logger.exception("This is the same stuff, via a %s", "exception() call")
|
||||
logger.removeHandler(ntl)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests MemoryHandler.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import sys, logging, logging.handlers
|
||||
|
||||
def message(s):
|
||||
sys.stderr.write("%s\n" % s)
|
||||
|
||||
sh = logging.StreamHandler()
|
||||
mh = logging.handlers.MemoryHandler(10,logging.WARNING, sh)
|
||||
logger = logging.getLogger("")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.addHandler(mh)
|
||||
message("-- logging at DEBUG, nothing should be seen yet --")
|
||||
logger.debug("Debug message")
|
||||
message("-- logging at INFO, nothing should be seen yet --")
|
||||
logger.info("Info message")
|
||||
message("-- logging at WARNING, 3 messages should be seen --")
|
||||
logger.warning("Warning message")
|
||||
for i in xrange(102):
|
||||
message("-- logging %d at level INFO, messages should be seen every 10 events --" % i)
|
||||
logger.info("Info index = %d", i)
|
||||
sh.close()
|
||||
mh.close()
|
||||
logger.removeHandler(mh)
|
||||
@@ -1,69 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests FileHandler rollover.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import logging, logging.handlers
|
||||
import locale
|
||||
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
|
||||
sequence = 0
|
||||
|
||||
def doLog(logger):
|
||||
global sequence
|
||||
sequence = sequence + 1
|
||||
logger.debug("%6d This message should be at level %d - %s", sequence,\
|
||||
logging.DEBUG, logging.getLevelName(logging.DEBUG))
|
||||
sequence = sequence + 1
|
||||
logger.info("%6d This message should be at level %d - %s", sequence,
|
||||
logging.INFO, logging.getLevelName(logging.INFO))
|
||||
sequence = sequence + 1
|
||||
logger.warning("%6d This message should be at level %d - %s", sequence,\
|
||||
logging.WARNING, logging.getLevelName(logging.WARNING))
|
||||
sequence = sequence + 1
|
||||
logger.error("%6d This message should be at level %d - %s", sequence,\
|
||||
logging.ERROR, logging.getLevelName(logging.ERROR))
|
||||
sequence = sequence + 1
|
||||
logger.critical("%6d This message should be at level %d - %s", sequence,\
|
||||
logging.CRITICAL, logging.getLevelName(logging.CRITICAL))
|
||||
|
||||
def main():
|
||||
logger = logging.getLogger("") #root logger
|
||||
logger.setLevel(logging.DEBUG)
|
||||
if __name__ == "__main__":
|
||||
logname = "rollover.log"
|
||||
else:
|
||||
logname = "log_test_rollover.log"
|
||||
hdlr = logging.handlers.RotatingFileHandler(logname, "a", 5000, 3)
|
||||
if __name__ == "__main__":
|
||||
fmt = logging.Formatter("%(asctime)s %(levelname)-5s %(message)s", "%x %X")
|
||||
hdlr.setFormatter(fmt)
|
||||
logger.addHandler(hdlr)
|
||||
for i in xrange(100):
|
||||
doLog(logger)
|
||||
logger.removeHandler(hdlr)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,71 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# This file is part of the Python logging distribution. See
|
||||
# http://www.red-dove.com/python_logging.html
|
||||
#
|
||||
"""
|
||||
A test harness for the logging module. Tests BufferingHandler, BufferingFormatter.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
import logging, logging.handlers
|
||||
|
||||
class XMLFormatter(logging.BufferingFormatter):
|
||||
"""
|
||||
A formatter which formats a set of records using XML, using an example DTD called "logging.dtd".
|
||||
"""
|
||||
def __init__(self):
|
||||
fmtstr = """
|
||||
<event name="%(name)s" level="%(levelno)d" filename="%(filename)s" lineno="%(lineno)d">
|
||||
<message>%(message)s</message>
|
||||
</event>"""
|
||||
logging.BufferingFormatter.__init__(self, logging.Formatter(fmtstr))
|
||||
|
||||
# def formatHeader(self, records):
|
||||
# return """
|
||||
#<?xml version="1.0" ?><!DOCTYPE eventSet SYSTEM "logging.dtd">
|
||||
#<eventSet xmlns="http://www.red-dove.com/logging">"""
|
||||
#
|
||||
# def formatFooter(self, records):
|
||||
# return "</eventSet>"
|
||||
|
||||
class XMLHandler(logging.handlers.BufferingHandler):
|
||||
def __init__(self, capacity):
|
||||
logging.handlers.BufferingHandler.__init__(self, capacity)
|
||||
self.setFormatter(XMLFormatter())
|
||||
|
||||
def flush(self):
|
||||
if len(self.buffer) > 0:
|
||||
file = open("events.xml","w")
|
||||
file.write(self.formatter.format(self.buffer))
|
||||
file.close()
|
||||
self.buffer = []
|
||||
|
||||
def main():
|
||||
logger = logging.getLogger("")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
xh = XMLHandler(10)
|
||||
logger.addHandler(xh)
|
||||
for i in xrange(100):
|
||||
logger.info("Info index = %d", i)
|
||||
xh.close()
|
||||
logger.removeHandler(xh)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,180 +0,0 @@
|
||||
[loggers]
|
||||
keys=root,log02,log03,log04,log05,log06,log07
|
||||
|
||||
[handlers]
|
||||
keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09
|
||||
|
||||
[formatters]
|
||||
keys=form01,form02,form03,form04,form05,form06,form07,form08,form09
|
||||
|
||||
[logger_root]
|
||||
level=NOTSET
|
||||
propagate=1
|
||||
channel=
|
||||
parent=
|
||||
qualname=(root)
|
||||
handlers=hand01
|
||||
|
||||
[logger_log02]
|
||||
level=DEBUG
|
||||
propagate=1
|
||||
channel=log02
|
||||
parent=(root)
|
||||
qualname=log02
|
||||
handlers=hand02
|
||||
|
||||
[logger_log03]
|
||||
level=INFO
|
||||
propagate=1
|
||||
channel=log03
|
||||
parent=log02
|
||||
qualname=log02.log03
|
||||
handlers=hand03
|
||||
|
||||
[logger_log04]
|
||||
level=WARN
|
||||
propagate=0
|
||||
channel=log04
|
||||
parent=log03
|
||||
qualname=log02.log03.log04
|
||||
handlers=hand04
|
||||
|
||||
[logger_log05]
|
||||
level=ERROR
|
||||
propagate=1
|
||||
channel=log05
|
||||
parent=log04
|
||||
qualname=log02.log03.log04.log05
|
||||
handlers=hand05
|
||||
|
||||
[logger_log06]
|
||||
level=CRITICAL
|
||||
propagate=1
|
||||
channel=log06
|
||||
parent=log05
|
||||
qualname=log02.log03.log04.log05.log06
|
||||
handlers=hand06
|
||||
|
||||
[logger_log07]
|
||||
level=WARN
|
||||
propagate=1
|
||||
channel=log07
|
||||
parent=log06
|
||||
qualname=log02.log03.log04.log05.log06.log07
|
||||
handlers=hand07
|
||||
|
||||
[handler_hand01]
|
||||
class=StreamHandler
|
||||
level=NOTSET
|
||||
formatter=form01
|
||||
stream=sys.stdout
|
||||
args=(sys.stdout,)
|
||||
|
||||
[handler_hand02]
|
||||
class=FileHandler
|
||||
level=DEBUG
|
||||
formatter=form02
|
||||
filename=python.log
|
||||
mode=w
|
||||
args=('python.log', 'w')
|
||||
|
||||
[handler_hand03]
|
||||
class=handlers.SocketHandler
|
||||
level=INFO
|
||||
formatter=form03
|
||||
host=localhost
|
||||
port=handlers.DEFAULT_TCP_LOGGING_PORT
|
||||
args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)
|
||||
|
||||
[handler_hand04]
|
||||
class=handlers.DatagramHandler
|
||||
level=WARN
|
||||
formatter=form04
|
||||
host=localhost
|
||||
port=handlers.DEFAULT_UDP_LOGGING_PORT
|
||||
args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)
|
||||
|
||||
[handler_hand05]
|
||||
class=handlers.SysLogHandler
|
||||
level=ERROR
|
||||
formatter=form05
|
||||
host=localhost
|
||||
port=handlers.SYSLOG_UDP_PORT
|
||||
facility=LOG_USER
|
||||
args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
|
||||
|
||||
[handler_hand06]
|
||||
class=handlers.NTEventLogHandler
|
||||
level=CRITICAL
|
||||
formatter=form06
|
||||
appname=Python Application
|
||||
dllname=
|
||||
logtype=Application
|
||||
args=('Python Application', '', 'Application')
|
||||
|
||||
[handler_hand07]
|
||||
class=handlers.SMTPHandler
|
||||
level=WARN
|
||||
formatter=form07
|
||||
host=localhost
|
||||
port=25
|
||||
from=from@abc
|
||||
to=user1@abc,user2@xyz
|
||||
subject=Logger Subject
|
||||
args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')
|
||||
|
||||
[handler_hand08]
|
||||
class=handlers.MemoryHandler
|
||||
level=NOTSET
|
||||
formatter=form08
|
||||
capacity=10
|
||||
flushlevel=ERROR
|
||||
target=
|
||||
args=(10, ERROR)
|
||||
|
||||
[handler_hand09]
|
||||
class=handlers.HTTPHandler
|
||||
level=NOTSET
|
||||
formatter=form09
|
||||
host=localhost
|
||||
port=9022
|
||||
url=/log
|
||||
method=GET
|
||||
args=('localhost:9022', '/log', 'GET')
|
||||
|
||||
[formatter_form01]
|
||||
format=F1 %(asctime)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
[formatter_form02]
|
||||
format=F2 %(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
[formatter_form03]
|
||||
format=F3 %(asctime)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
[formatter_form04]
|
||||
format=%(asctime)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
[formatter_form05]
|
||||
format=F5 %(asctime)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
[formatter_form06]
|
||||
format=F6 %(asctime)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
[formatter_form07]
|
||||
format=F7 %(asctime)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
[formatter_form08]
|
||||
format=F8 %(asctime)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
[formatter_form09]
|
||||
format=F9 %(asctime)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!-- Author: Vinay Sajip, Red Dove Consultants Ltd. http://www.red-dove.com/ -->
|
||||
|
||||
<!-- THIS IS ONLY A VERY SIMPLE EXAMPLE -->
|
||||
|
||||
<!ELEMENT logging:events (logging:event*)>
|
||||
|
||||
<!ELEMENT logging:event (logging:message)>
|
||||
|
||||
<!ATTLIST logging:event
|
||||
name CDATA #REQUIRED
|
||||
level CDATA #REQUIRED
|
||||
created CDATA #IMPLIED
|
||||
filename CDATA #IMPLIED
|
||||
lineno CDATA #IMPLIED
|
||||
>
|
||||
|
||||
<!ELEMENT logging:message (#PCDATA)>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<!DOCTYPE events SYSTEM "logging.dtd" [<!ENTITY data SYSTEM "events.xml">]>
|
||||
<events xmlns="http://www.red-dove.com/logging">
|
||||
&data;
|
||||
</events>
|
||||
@@ -1,36 +0,0 @@
|
||||
[loggers]
|
||||
keys=root
|
||||
|
||||
[handlers]
|
||||
keys=hand01,hand02
|
||||
|
||||
[formatters]
|
||||
keys=form01
|
||||
|
||||
[logger_root]
|
||||
level=NOTSET
|
||||
propagate=1
|
||||
channel=
|
||||
parent=
|
||||
qualname=(root)
|
||||
handlers=hand01,hand02
|
||||
|
||||
[handler_hand01]
|
||||
class=FileHandler
|
||||
level=NOTSET
|
||||
formatter=form01
|
||||
filename=logrecv.log
|
||||
mode=w
|
||||
args=('logrecv.log', 'w')
|
||||
|
||||
[handler_hand02]
|
||||
class=StreamHandler
|
||||
level=NOTSET
|
||||
formatter=form01
|
||||
stream=sys.stderr
|
||||
args=(sys.stderr,)
|
||||
|
||||
[formatter_form01]
|
||||
format=%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s
|
||||
datefmt=
|
||||
|
||||
@@ -1,443 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
#
|
||||
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright notice appear in all copies and that
|
||||
# both that copyright notice and this permission notice appear in
|
||||
# supporting documentation, and that the name of Vinay Sajip
|
||||
# not be used in advertising or publicity pertaining to distribution
|
||||
# of the software without specific, written prior permission.
|
||||
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
||||
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
||||
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
"""
|
||||
Simple socket-based logging event receiver for use with "logging.py" logging
|
||||
module.
|
||||
|
||||
Should work under Python versions >= 1.5.2, except that source line information
|
||||
is not available unless 'inspect' is.
|
||||
|
||||
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
|
||||
"""
|
||||
|
||||
from select import select
|
||||
import sys, string, struct, types, cPickle, socket
|
||||
import logging, logging.handlers, logging.config
|
||||
|
||||
TIMEOUT = 10
|
||||
if sys.platform == "win32":
|
||||
RESET_ERROR = 10054
|
||||
else:
|
||||
RESET_ERROR = 0 #FIXME get correct value for Unix...
|
||||
|
||||
logging.raiseExceptions = 1
|
||||
|
||||
#
|
||||
# TCP receiver
|
||||
#
|
||||
|
||||
from SocketServer import ThreadingTCPServer, StreamRequestHandler
|
||||
|
||||
class LogRecordStreamHandler(StreamRequestHandler):
|
||||
"""
|
||||
Handler for a streaming logging request. It basically logs the record
|
||||
using whatever logging policy is configured locally.
|
||||
"""
|
||||
|
||||
def handle(self):
|
||||
"""
|
||||
Handle multiple requests - each expected to be a 4-byte length,
|
||||
followed by the LogRecord in pickle format. Logs the record
|
||||
according to whatever policy is configured locally.
|
||||
"""
|
||||
while 1:
|
||||
try:
|
||||
chunk = self.connection.recv(4)
|
||||
if len(chunk) < 4:
|
||||
break
|
||||
slen = struct.unpack(">L", chunk)[0]
|
||||
chunk = self.connection.recv(slen)
|
||||
while len(chunk) < slen:
|
||||
chunk = chunk + self.connection.recv(slen - len(chunk))
|
||||
obj = self.unPickle(chunk)
|
||||
record = logging.makeLogRecord(obj)
|
||||
self.handleLogRecord(record)
|
||||
except socket.error, e:
|
||||
if type(e.args) != types.TupleType:
|
||||
raise
|
||||
else:
|
||||
errcode = e.args[0]
|
||||
if errcode != RESET_ERROR:
|
||||
raise
|
||||
break
|
||||
|
||||
def unPickle(self, data):
|
||||
return cPickle.loads(data)
|
||||
|
||||
def handleLogRecord(self, record):
|
||||
#if a name is specified, we use the named logger rather than the one
|
||||
#implied by the record. This is so test harnesses don't get into
|
||||
#endless loops (particularly log_test.py, which has this code and the
|
||||
#client code in the same Python instance)
|
||||
if self.server.logname is not None:
|
||||
name = self.server.logname
|
||||
else:
|
||||
name = record.name
|
||||
logger = logging.getLogger(name)
|
||||
logger.handle(record)
|
||||
|
||||
class LogRecordSocketReceiver(ThreadingTCPServer):
|
||||
"""
|
||||
A simple-minded TCP socket-based logging receiver suitable for test
|
||||
purposes.
|
||||
"""
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def __init__(self, host='localhost', port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
|
||||
handler=LogRecordStreamHandler):
|
||||
ThreadingTCPServer.__init__(self, (host, port), handler)
|
||||
self.abort = 0
|
||||
self.timeout = 1
|
||||
self.logname = None
|
||||
|
||||
def serve_until_stopped(self):
|
||||
import select
|
||||
abort = 0
|
||||
while not abort:
|
||||
rd, wr, ex = select.select([self.socket.fileno()],
|
||||
[], [],
|
||||
self.timeout)
|
||||
if rd:
|
||||
self.handle_request()
|
||||
abort = self.abort
|
||||
|
||||
#
|
||||
# UDP receiver
|
||||
#
|
||||
|
||||
from SocketServer import ThreadingUDPServer, DatagramRequestHandler
|
||||
|
||||
class LogRecordDatagramHandler(DatagramRequestHandler):
|
||||
"""
|
||||
Handler for a datagram logging request. It basically logs the record using
|
||||
whatever logging policy is configured locally.
|
||||
"""
|
||||
def handle(self):
|
||||
chunk = self.packet
|
||||
slen = struct.unpack(">L", chunk[:4])[0]
|
||||
chunk = chunk[4:]
|
||||
assert len(chunk) == slen
|
||||
obj = self.unPickle(chunk)
|
||||
record = logging.LogRecord(None, None, "", 0, "", (), None)
|
||||
record.__dict__.update(obj)
|
||||
self.handleLogRecord(record)
|
||||
|
||||
def unPickle(self, data):
|
||||
return cPickle.loads(data)
|
||||
|
||||
def handleLogRecord(self, record):
|
||||
#if a name is specified, we use the named logger rather than the one
|
||||
#implied by the record. This is so test harnesses don't get into
|
||||
#endless loops (particularly log_test.py, which has this code and the
|
||||
#client code in the same Python instance)
|
||||
if self.server.logname is not None:
|
||||
name = self.server.logname
|
||||
else:
|
||||
name = record.name
|
||||
logger = logging.getLogger(name)
|
||||
logger.handle(record)
|
||||
|
||||
def finish(self):
|
||||
pass
|
||||
|
||||
class LogRecordDatagramReceiver(ThreadingUDPServer):
|
||||
"""
|
||||
A simple-minded UDP datagram-based logging receiver suitable for test
|
||||
purposes.
|
||||
"""
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def __init__(self, host='localhost', port=logging.handlers.DEFAULT_UDP_LOGGING_PORT,
|
||||
handler=LogRecordDatagramHandler):
|
||||
ThreadingUDPServer.__init__(self, (host, port), handler)
|
||||
self.abort = 0
|
||||
self.timeout = 1
|
||||
self.logname = None
|
||||
|
||||
def serve_until_stopped(self):
|
||||
import select
|
||||
abort = 0
|
||||
while not abort:
|
||||
rd, wr, ex = select.select([self.socket.fileno()],
|
||||
[], [],
|
||||
self.timeout)
|
||||
if rd:
|
||||
self.handle_request()
|
||||
abort = self.abort
|
||||
|
||||
#
|
||||
# HTTP receiver
|
||||
#
|
||||
|
||||
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
||||
|
||||
import cgi
|
||||
|
||||
class LogRecordHTTPHandler(BaseHTTPRequestHandler):
|
||||
def makeDict(self, fs):
|
||||
dict = {}
|
||||
for mfs in fs.list:
|
||||
dict[mfs.name] = mfs.value
|
||||
for key in ["args", "exc_info", "exc_text", "lineno", "msecs", "created",
|
||||
"thread", "levelno", "relativeCreated"]:
|
||||
if dict.has_key(key):
|
||||
dict[key] = eval(dict[key])
|
||||
return dict
|
||||
|
||||
def do_GET(self):
|
||||
"""Serve a GET request."""
|
||||
sts = "OK"
|
||||
env = { 'REQUEST_METHOD' : 'GET'}
|
||||
try:
|
||||
i = string.find(self.path, '?')
|
||||
if i >= 0:
|
||||
env['QUERY_STRING'] = self.path[i + 1:]
|
||||
fs = cgi.FieldStorage(environ=env)
|
||||
dict = self.makeDict(fs)
|
||||
record = logging.LogRecord(None, None, "", 0, "", (), None)
|
||||
record.__dict__.update(dict)
|
||||
self.handleLogRecord(record)
|
||||
except Exception, e:
|
||||
sts = "ERROR"
|
||||
raise
|
||||
self.send_head()
|
||||
self.wfile.write("GET %s" % sts)
|
||||
|
||||
def handleLogRecord(self, record):
|
||||
#if a name is specified, we use the named logger rather than the one
|
||||
#implied by the record. This is so test harnesses don't get into
|
||||
#endless loops (particularly log_test.py, which has this code and the
|
||||
#client code in the same Python instance)
|
||||
if self.server.logname is not None:
|
||||
name = self.server.logname
|
||||
else:
|
||||
name = record.name
|
||||
logger = logging.getLogger(name)
|
||||
logger.handle(record)
|
||||
|
||||
def do_HEAD(self):
|
||||
"""Serve a HEAD request."""
|
||||
self.send_head()
|
||||
|
||||
def do_POST(self):
|
||||
"""Serve a POST request."""
|
||||
sts = "OK"
|
||||
env = { 'REQUEST_METHOD' : 'POST'}
|
||||
try:
|
||||
length = self.headers.getheader('content-length')
|
||||
if length:
|
||||
env['CONTENT_LENGTH'] = length
|
||||
#print self.headers
|
||||
i = string.find(self.path, '?')
|
||||
if i >= 0:
|
||||
env['QUERY_STRING'] = self.path[i + 1:]
|
||||
fs = cgi.FieldStorage(fp=self.rfile, environ=env)
|
||||
dict = self.makeDict(fs)
|
||||
record = logging.LogRecord(None, None, "", 0, "", (), None)
|
||||
record.__dict__.update(dict)
|
||||
self.handleLogRecord(record)
|
||||
except Exception, e:
|
||||
print e
|
||||
sys.stdout.flush()
|
||||
sts = "ERROR"
|
||||
raise
|
||||
self.send_head()
|
||||
self.wfile.write("POST %s" % sts)
|
||||
|
||||
def send_head(self):
|
||||
"""Common code for GET and HEAD commands.
|
||||
|
||||
This sends the response code and MIME headers.
|
||||
|
||||
Return value is either a file object (which has to be copied
|
||||
to the outputfile by the caller unless the command was HEAD,
|
||||
and must be closed by the caller under all circumstances), or
|
||||
None, in which case the caller has nothing further to do.
|
||||
|
||||
"""
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", "text/plain")
|
||||
self.end_headers()
|
||||
|
||||
def log_message(self, *args):
|
||||
#comment out the following line if you don't want to show requests
|
||||
#apply(BaseHTTPRequestHandler.log_message, (self,) + args)
|
||||
pass
|
||||
|
||||
class LogRecordHTTPReceiver(HTTPServer):
|
||||
def __init__(self, host='localhost', port=logging.handlers.DEFAULT_HTTP_LOGGING_PORT,
|
||||
handler=LogRecordHTTPHandler):
|
||||
HTTPServer.__init__(self, (host, port), handler)
|
||||
self.abort = 0
|
||||
self.timeout = 1
|
||||
self.logname = None
|
||||
|
||||
def serve_until_stopped(self):
|
||||
import select
|
||||
abort = 0
|
||||
while not abort:
|
||||
rd, wr, ex = select.select([self.socket.fileno()],
|
||||
[], [],
|
||||
self.timeout)
|
||||
if rd:
|
||||
self.handle_request()
|
||||
abort = self.abort
|
||||
|
||||
|
||||
#
|
||||
# SOAP receiver
|
||||
#
|
||||
|
||||
try:
|
||||
from ZSI import dispatch
|
||||
|
||||
logname = None
|
||||
|
||||
def log(args, created, exc_info, exc_text, filename, levelname, levelno, lineno, module, msecs, msg, name, pathname, process, relativeCreated, thread):
|
||||
record = logging.LogRecord(None, None, "", 0, "", (), None)
|
||||
record.args = eval(args)
|
||||
record.exc_info = eval(exc_info)
|
||||
record.exc_text = eval(exc_text)
|
||||
record.created = created
|
||||
record.filename = filename
|
||||
record.module = module
|
||||
record.levelname = levelname
|
||||
record.lineno = lineno
|
||||
record.levelno = levelno
|
||||
record.msecs = msecs
|
||||
record.msg = msg
|
||||
record.name = name
|
||||
record.pathname = pathname
|
||||
record.process = process
|
||||
record.relativeCreated = relativeCreated
|
||||
record.thread = thread
|
||||
#if a name is specified, we use the named logger rather than the one
|
||||
#implied by the record. This is so test harnesses don't get into
|
||||
#endless loops (particularly log_test.py, which has this code and the
|
||||
#client code in the same Python instance)
|
||||
if logname is not None:
|
||||
lname = logname
|
||||
else:
|
||||
lname = name
|
||||
logger = logging.getLogger(lname)
|
||||
logger.handle(record)
|
||||
|
||||
class MySOAPRequestHandler(dispatch.SOAPRequestHandler):
|
||||
def log_message(self, *args):
|
||||
#comment out the following line if you don't want to show requests
|
||||
#apply(BaseHTTPRequestHandler.log_message, (self,) + args)
|
||||
pass
|
||||
|
||||
class SOAPServer(HTTPServer):
|
||||
def __init__(self, port=logging.handlers.DEFAULT_SOAP_LOGGING_PORT):
|
||||
address = ('', port)
|
||||
HTTPServer.__init__(self, address, MySOAPRequestHandler)
|
||||
self.abort = 0
|
||||
self.timeout = 1
|
||||
self.logname = None
|
||||
self.docstyle = 0
|
||||
self.nsdict = {}
|
||||
self.typesmodule = None
|
||||
self.rpc = 1
|
||||
self.modules = (sys.modules["__main__"],)
|
||||
|
||||
def serve_until_stopped(self):
|
||||
import select
|
||||
abort = 0
|
||||
while not abort:
|
||||
rd, wr, ex = select.select([self.socket.fileno()],
|
||||
[], [],
|
||||
self.timeout)
|
||||
if rd:
|
||||
global logname
|
||||
logname = self.logname
|
||||
self.handle_request()
|
||||
abort = self.abort
|
||||
|
||||
except ImportError:
|
||||
"Import failed"
|
||||
SOAPServer = None
|
||||
|
||||
def runTCP(tcpserver=None):
|
||||
if not tcpserver:
|
||||
tcpserver = LogRecordSocketReceiver()
|
||||
print "About to start TCP server..."
|
||||
tcpserver.serve_until_stopped()
|
||||
|
||||
def runUDP(udpserver=None):
|
||||
if not udpserver:
|
||||
udpserver = LogRecordDatagramReceiver()
|
||||
print "About to start UDP server..."
|
||||
udpserver.serve_until_stopped()
|
||||
|
||||
def runHTTP(httpserver=None):
|
||||
if not httpserver:
|
||||
httpserver = LogRecordHTTPReceiver()
|
||||
print "About to start HTTP server..."
|
||||
httpserver.serve_until_stopped()
|
||||
|
||||
def runSOAP(soapserver=None):
|
||||
if not SOAPServer:
|
||||
print "Sorry, ZSI is not available. Install PyXML-0.6.6 and ZSI first."
|
||||
print "See README.txt and python_logging.html for more information."
|
||||
else:
|
||||
if not soapserver:
|
||||
soapserver = SOAPServer()
|
||||
print "About to start SOAP server..."
|
||||
soapserver.serve_until_stopped()
|
||||
|
||||
FORMAT_STR = "%(asctime)s %(name)-19s %(levelname)-5s - %(message)s"
|
||||
|
||||
if __name__ == "__main__":
|
||||
if (len(sys.argv) < 2) or not (string.lower(sys.argv[1]) in \
|
||||
["udp", "tcp", "http", "soap"]):
|
||||
print "usage: logrecv.py [UDP|TCP|HTTP|SOAP]"
|
||||
else:
|
||||
#logging.basicConfig()
|
||||
logging.config.fileConfig("logrecv.ini")
|
||||
# both = string.lower(sys.argv[1]) == "both"
|
||||
# hdlr = logging.FileHandler("test.log")
|
||||
# hdlr.setFormatter(logging.Formatter(FORMAT_STR))
|
||||
# logging.getLogger("").addHandler(hdlr)
|
||||
# if both:
|
||||
# import threading
|
||||
# tcpthread = threading.Thread(target=runTCP)
|
||||
# udpthread = threading.Thread(target=runUDP)
|
||||
# tcpthread.start()
|
||||
# udpthread.start()
|
||||
# tcpthread.join()
|
||||
# udpthread.join()
|
||||
# else:
|
||||
# tcp = string.lower(sys.argv[1]) == "tcp"
|
||||
# if tcp:
|
||||
# runTCP()
|
||||
# else:
|
||||
# runUDP()
|
||||
arg = string.lower(sys.argv[1])
|
||||
if arg == "tcp":
|
||||
runTCP()
|
||||
elif arg == "udp":
|
||||
runUDP()
|
||||
elif arg == "http":
|
||||
runHTTP()
|
||||
elif arg == "soap":
|
||||
runSOAP()
|
||||
@@ -1,13 +0,0 @@
|
||||
import logging, mymodule
|
||||
|
||||
logging.basicConfig()
|
||||
|
||||
log = logging.getLogger("MyApp")
|
||||
log.setLevel(logging.DEBUG) #set verbosity to show all messages of severity >= DEBUG
|
||||
log.info("Starting my app")
|
||||
try:
|
||||
mymodule.doIt()
|
||||
except Exception, e:
|
||||
log.exception("There was a problem.")
|
||||
log.info("Ending my app")
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import logging
|
||||
log = logging.getLogger("MyModule")
|
||||
|
||||
def doIt():
|
||||
log.debug("Doin' stuff...")
|
||||
#do stuff...
|
||||
raise TypeError, "Bogus type error for testing"
|
||||
|
||||
@@ -1,566 +0,0 @@
|
||||
-- log_test0 begin --------------------------------------------------------
|
||||
CRITICAL:ERR:Message 0
|
||||
ERROR:ERR:Message 1
|
||||
CRITICAL:INF:Message 2
|
||||
ERROR:INF:Message 3
|
||||
WARNING:INF:Message 4
|
||||
INFO:INF:Message 5
|
||||
CRITICAL:INF.UNDEF:Message 6
|
||||
ERROR:INF.UNDEF:Message 7
|
||||
WARNING:INF.UNDEF:Message 8
|
||||
INFO:INF.UNDEF:Message 9
|
||||
CRITICAL:INF.ERR:Message 10
|
||||
ERROR:INF.ERR:Message 11
|
||||
CRITICAL:INF.ERR.UNDEF:Message 12
|
||||
ERROR:INF.ERR.UNDEF:Message 13
|
||||
CRITICAL:DEB:Message 14
|
||||
ERROR:DEB:Message 15
|
||||
WARNING:DEB:Message 16
|
||||
INFO:DEB:Message 17
|
||||
DEBUG:DEB:Message 18
|
||||
CRITICAL:UNDEF:Message 19
|
||||
ERROR:UNDEF:Message 20
|
||||
WARNING:UNDEF:Message 21
|
||||
INFO:UNDEF:Message 22
|
||||
CRITICAL:INF.BADPARENT.UNDEF:Message 23
|
||||
CRITICAL:INF.BADPARENT:Message 24
|
||||
INFO:INF:Messages should bear numbers 0 through 24.
|
||||
-- log_test0 end --------------------------------------------------------
|
||||
-- log_test2 begin --------------------------------------------------------
|
||||
CRITICAL:ERR:Message 0
|
||||
ERROR:ERR:Message 1
|
||||
CRITICAL:INF:Message 2
|
||||
ERROR:INF:Message 3
|
||||
WARNING:INF:Message 4
|
||||
INFO:INF:Message 5
|
||||
CRITICAL:INF.UNDEF:Message 6
|
||||
ERROR:INF.UNDEF:Message 7
|
||||
WARNING:INF.UNDEF:Message 8
|
||||
INFO:INF.UNDEF:Message 9
|
||||
CRITICAL:INF.ERR:Message 10
|
||||
ERROR:INF.ERR:Message 11
|
||||
CRITICAL:INF.ERR.UNDEF:Message 12
|
||||
ERROR:INF.ERR.UNDEF:Message 13
|
||||
CRITICAL:DEB:Message 14
|
||||
ERROR:DEB:Message 15
|
||||
WARNING:DEB:Message 16
|
||||
INFO:DEB:Message 17
|
||||
DEBUG:DEB:Message 18
|
||||
CRITICAL:UNDEF:Message 19
|
||||
ERROR:UNDEF:Message 20
|
||||
WARNING:UNDEF:Message 21
|
||||
INFO:UNDEF:Message 22
|
||||
CRITICAL:INF.BADPARENT.UNDEF:Message 23
|
||||
CRITICAL:INF.BADPARENT:Message 24
|
||||
INFO:INF:Messages should bear numbers 0 through 24.
|
||||
-- log_test2 end --------------------------------------------------------
|
||||
CRITICAL:ERR:Message 0
|
||||
ERROR:ERR:Message 1
|
||||
CRITICAL:INF:Message 2
|
||||
ERROR:INF:Message 3
|
||||
WARNING:INF:Message 4
|
||||
INFO:INF:Message 5
|
||||
CRITICAL:INF.UNDEF:Message 6
|
||||
ERROR:INF.UNDEF:Message 7
|
||||
WARNING:INF.UNDEF:Message 8
|
||||
INFO:INF.UNDEF:Message 9
|
||||
CRITICAL:INF.ERR:Message 10
|
||||
ERROR:INF.ERR:Message 11
|
||||
CRITICAL:INF.ERR.UNDEF:Message 12
|
||||
ERROR:INF.ERR.UNDEF:Message 13
|
||||
CRITICAL:DEB:Message 14
|
||||
ERROR:DEB:Message 15
|
||||
WARNING:DEB:Message 16
|
||||
INFO:DEB:Message 17
|
||||
DEBUG:DEB:Message 18
|
||||
CRITICAL:UNDEF:Message 19
|
||||
ERROR:UNDEF:Message 20
|
||||
WARNING:UNDEF:Message 21
|
||||
INFO:UNDEF:Message 22
|
||||
CRITICAL:INF.BADPARENT.UNDEF:Message 23
|
||||
CRITICAL:INF.BADPARENT:Message 24
|
||||
INFO:INF:Messages should bear numbers 0 through 24.
|
||||
-- log_test4 begin --------------------------------------------------------
|
||||
-- setting logging level to 'Boring' -----
|
||||
Boring:root:This should only be seen at the 'Boring' logging level (or lower)
|
||||
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
|
||||
Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower)
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Chatterbox' -----
|
||||
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
|
||||
Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower)
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Garrulous' -----
|
||||
Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower)
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Talkative' -----
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Verbose' -----
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Sociable' -----
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Effusive' -----
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Terse' -----
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Taciturn' -----
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Silent' -----
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- Filtering at handler level to SOCIABLE --
|
||||
-- setting logging level to 'Boring' -----
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Chatterbox' -----
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Garrulous' -----
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Talkative' -----
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Verbose' -----
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Sociable' -----
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Effusive' -----
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Terse' -----
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Taciturn' -----
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Silent' -----
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- Filtering using GARRULOUS filter --
|
||||
-- setting logging level to 'Boring' -----
|
||||
Boring:root:This should only be seen at the 'Boring' logging level (or lower)
|
||||
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Chatterbox' -----
|
||||
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Garrulous' -----
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Talkative' -----
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Verbose' -----
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Sociable' -----
|
||||
Sociable:root:This should only be seen at the 'Sociable' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Effusive' -----
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Terse' -----
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Taciturn' -----
|
||||
Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Silent' -----
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- Filtering using specific filter for SOCIABLE, TACITURN --
|
||||
-- setting logging level to 'Boring' -----
|
||||
Boring:root:This should only be seen at the 'Boring' logging level (or lower)
|
||||
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Chatterbox' -----
|
||||
Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower)
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Garrulous' -----
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Talkative' -----
|
||||
Talkative:root:This should only be seen at the 'Talkative' logging level (or lower)
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Verbose' -----
|
||||
Verbose:root:This should only be seen at the 'Verbose' logging level (or lower)
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Sociable' -----
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Effusive' -----
|
||||
Effusive:root:This should only be seen at the 'Effusive' logging level (or lower)
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Terse' -----
|
||||
Terse:root:This should only be seen at the 'Terse' logging level (or lower)
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Taciturn' -----
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- setting logging level to 'Silent' -----
|
||||
Silent:root:This should only be seen at the 'Silent' logging level (or lower)
|
||||
-- log_test4 end --------------------------------------------------------
|
||||
-- log_test7 begin --------------------------------------------------------
|
||||
-- logging at DEBUG, nothing should be seen yet --
|
||||
-- logging at INFO, nothing should be seen yet --
|
||||
-- logging at WARNING, 3 messages should be seen --
|
||||
Debug message
|
||||
Info message
|
||||
Warning message
|
||||
-- logging 0 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 1 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 2 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 3 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 4 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 5 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 6 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 7 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 8 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 9 at level INFO, messages should be seen every 10 events --
|
||||
Info index = 0
|
||||
Info index = 1
|
||||
Info index = 2
|
||||
Info index = 3
|
||||
Info index = 4
|
||||
Info index = 5
|
||||
Info index = 6
|
||||
Info index = 7
|
||||
Info index = 8
|
||||
Info index = 9
|
||||
-- logging 10 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 11 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 12 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 13 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 14 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 15 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 16 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 17 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 18 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 19 at level INFO, messages should be seen every 10 events --
|
||||
Info index = 10
|
||||
Info index = 11
|
||||
Info index = 12
|
||||
Info index = 13
|
||||
Info index = 14
|
||||
Info index = 15
|
||||
Info index = 16
|
||||
Info index = 17
|
||||
Info index = 18
|
||||
Info index = 19
|
||||
-- logging 20 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 21 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 22 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 23 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 24 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 25 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 26 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 27 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 28 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 29 at level INFO, messages should be seen every 10 events --
|
||||
Info index = 20
|
||||
Info index = 21
|
||||
Info index = 22
|
||||
Info index = 23
|
||||
Info index = 24
|
||||
Info index = 25
|
||||
Info index = 26
|
||||
Info index = 27
|
||||
Info index = 28
|
||||
Info index = 29
|
||||
-- logging 30 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 31 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 32 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 33 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 34 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 35 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 36 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 37 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 38 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 39 at level INFO, messages should be seen every 10 events --
|
||||
Info index = 30
|
||||
Info index = 31
|
||||
Info index = 32
|
||||
Info index = 33
|
||||
Info index = 34
|
||||
Info index = 35
|
||||
Info index = 36
|
||||
Info index = 37
|
||||
Info index = 38
|
||||
Info index = 39
|
||||
-- logging 40 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 41 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 42 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 43 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 44 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 45 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 46 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 47 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 48 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 49 at level INFO, messages should be seen every 10 events --
|
||||
Info index = 40
|
||||
Info index = 41
|
||||
Info index = 42
|
||||
Info index = 43
|
||||
Info index = 44
|
||||
Info index = 45
|
||||
Info index = 46
|
||||
Info index = 47
|
||||
Info index = 48
|
||||
Info index = 49
|
||||
-- logging 50 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 51 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 52 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 53 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 54 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 55 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 56 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 57 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 58 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 59 at level INFO, messages should be seen every 10 events --
|
||||
Info index = 50
|
||||
Info index = 51
|
||||
Info index = 52
|
||||
Info index = 53
|
||||
Info index = 54
|
||||
Info index = 55
|
||||
Info index = 56
|
||||
Info index = 57
|
||||
Info index = 58
|
||||
Info index = 59
|
||||
-- logging 60 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 61 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 62 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 63 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 64 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 65 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 66 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 67 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 68 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 69 at level INFO, messages should be seen every 10 events --
|
||||
Info index = 60
|
||||
Info index = 61
|
||||
Info index = 62
|
||||
Info index = 63
|
||||
Info index = 64
|
||||
Info index = 65
|
||||
Info index = 66
|
||||
Info index = 67
|
||||
Info index = 68
|
||||
Info index = 69
|
||||
-- logging 70 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 71 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 72 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 73 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 74 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 75 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 76 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 77 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 78 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 79 at level INFO, messages should be seen every 10 events --
|
||||
Info index = 70
|
||||
Info index = 71
|
||||
Info index = 72
|
||||
Info index = 73
|
||||
Info index = 74
|
||||
Info index = 75
|
||||
Info index = 76
|
||||
Info index = 77
|
||||
Info index = 78
|
||||
Info index = 79
|
||||
-- logging 80 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 81 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 82 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 83 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 84 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 85 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 86 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 87 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 88 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 89 at level INFO, messages should be seen every 10 events --
|
||||
Info index = 80
|
||||
Info index = 81
|
||||
Info index = 82
|
||||
Info index = 83
|
||||
Info index = 84
|
||||
Info index = 85
|
||||
Info index = 86
|
||||
Info index = 87
|
||||
Info index = 88
|
||||
Info index = 89
|
||||
-- logging 90 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 91 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 92 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 93 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 94 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 95 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 96 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 97 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 98 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 99 at level INFO, messages should be seen every 10 events --
|
||||
Info index = 90
|
||||
Info index = 91
|
||||
Info index = 92
|
||||
Info index = 93
|
||||
Info index = 94
|
||||
Info index = 95
|
||||
Info index = 96
|
||||
Info index = 97
|
||||
Info index = 98
|
||||
Info index = 99
|
||||
-- logging 100 at level INFO, messages should be seen every 10 events --
|
||||
-- logging 101 at level INFO, messages should be seen every 10 events --
|
||||
Info index = 100
|
||||
Info index = 101
|
||||
-- log_test7 end --------------------------------------------------------
|
||||
-- log_test8 begin --------------------------------------------------------
|
||||
-- log_test8 end --------------------------------------------------------
|
||||
-- log_test9 begin --------------------------------------------------------
|
||||
-- log_test9 end --------------------------------------------------------
|
||||
-- log_test10 begin --------------------------------------------------------
|
||||
logger not derived from logging.Logger: NotALogger
|
||||
INFO:mylogger:Starting...
|
||||
DEBUG:mylogger:Debug message not in exception handler (no traceback)
|
||||
INFO:mylogger:About to throw exception...
|
||||
DEBUG:mylogger:Debug message inside exception handler (traceback)
|
||||
Traceback (most recent call last):
|
||||
File "C:\Projects\RDC\Python\packages\logging\test\log_test10.py", line 77, in run
|
||||
print "7" + 4
|
||||
TypeError: cannot concatenate 'str' and 'int' objects
|
||||
INFO:mylogger:Done.
|
||||
-- log_test10 end --------------------------------------------------------
|
||||
-- log_test12 begin --------------------------------------------------------
|
||||
INFO:log_test12:Jackdaws love my big sphinx of quartz
|
||||
INFO:log_test12:Jackdaws love my big sphinx of quartz
|
||||
DEBUG:log_test12:Pack my box with twelve dozen liquor jugs
|
||||
DEBUG:log_test12:Pack my box with twelve dozen liquor jugs
|
||||
-- log_test12 end --------------------------------------------------------
|
||||
-- log_test13 begin --------------------------------------------------------
|
||||
INFO:log_test13:Jackdaws love my big sphinx of quartz
|
||||
DEBUG:log_test13:Pack my box with five dozen liquor jugs
|
||||
-- log_test13 end --------------------------------------------------------
|
||||
-- log_test15 begin --------------------------------------------------------
|
||||
Unfiltered...
|
||||
INFO:a:Info 1
|
||||
INFO:a.b:Info 2
|
||||
INFO:a.c:Info 3
|
||||
INFO:a.b.c:Info 4
|
||||
INFO:a.b.c.d:Info 5
|
||||
INFO:a.bb.c:Info 6
|
||||
INFO:b:Info 7
|
||||
INFO:b.a:Info 8
|
||||
INFO:c.a.b:Info 9
|
||||
INFO:a.bb:Info 10
|
||||
Filtered with 'a.b'...
|
||||
INFO:a.b:Info 2
|
||||
INFO:a.b.c:Info 4
|
||||
INFO:a.b.c.d:Info 5
|
||||
-- log_test15 end --------------------------------------------------------
|
||||
@@ -1,24 +0,0 @@
|
||||
About to start TCP server...
|
||||
About to start UDP server...
|
||||
About to start HTTP server...
|
||||
About to start SOAP server...
|
||||
-- log_test0 begin --------------------------------------------------------
|
||||
-- log_test0 end --------------------------------------------------------
|
||||
-- log_test2 begin --------------------------------------------------------
|
||||
-- log_test2 end --------------------------------------------------------
|
||||
-- log_test4 begin --------------------------------------------------------
|
||||
-- log_test4 end --------------------------------------------------------
|
||||
-- log_test7 begin --------------------------------------------------------
|
||||
-- log_test7 end --------------------------------------------------------
|
||||
-- log_test8 begin --------------------------------------------------------
|
||||
-- log_test8 end --------------------------------------------------------
|
||||
-- log_test9 begin --------------------------------------------------------
|
||||
-- log_test9 end --------------------------------------------------------
|
||||
-- log_test10 begin --------------------------------------------------------
|
||||
-- log_test10 end --------------------------------------------------------
|
||||
-- log_test12 begin --------------------------------------------------------
|
||||
-- log_test12 end --------------------------------------------------------
|
||||
-- log_test13 begin --------------------------------------------------------
|
||||
-- log_test13 end --------------------------------------------------------
|
||||
-- log_test15 begin --------------------------------------------------------
|
||||
-- log_test15 end --------------------------------------------------------
|
||||
@@ -1,60 +0,0 @@
|
||||
[loggers]
|
||||
keys=root,log02,log03,log04,log05
|
||||
|
||||
[handlers]
|
||||
keys=hand01
|
||||
|
||||
[formatters]
|
||||
keys=form01
|
||||
|
||||
[logger_root]
|
||||
level=WARN
|
||||
propagate=1
|
||||
channel=
|
||||
parent=
|
||||
qualname=(root)
|
||||
handlers=hand01
|
||||
|
||||
[logger_log02]
|
||||
level=WARN
|
||||
propagate=1
|
||||
channel=A
|
||||
parent=(root)
|
||||
qualname=A
|
||||
handlers=
|
||||
|
||||
[logger_log03]
|
||||
level=WARN
|
||||
propagate=1
|
||||
channel=B
|
||||
parent=log02
|
||||
qualname=A.B
|
||||
handlers=
|
||||
|
||||
[logger_log04]
|
||||
level=WARN
|
||||
propagate=1
|
||||
channel=C
|
||||
parent=log03
|
||||
qualname=A.B.C
|
||||
handlers=
|
||||
|
||||
[logger_log05]
|
||||
level=WARN
|
||||
propagate=1
|
||||
channel=D
|
||||
parent=log04
|
||||
qualname=A.B.C.D
|
||||
handlers=
|
||||
|
||||
[handler_hand01]
|
||||
class=StreamHandler
|
||||
level=NOTSET
|
||||
formatter=form01
|
||||
stream=sys.stderr
|
||||
args=(sys.stderr,)
|
||||
|
||||
[formatter_form01]
|
||||
format=warn.ini %(name)s %(levelname)s %(message)s
|
||||
datefmt=
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#============================================================================
|
||||
# Install the logging package from python 2.3 if not present.
|
||||
#============================================================================
|
||||
import os
|
||||
|
||||
try:
|
||||
import logging
|
||||
except ImportError:
|
||||
print 'logging package not found: installing'
|
||||
os.chdir('logging-0.4.9.2')
|
||||
execfile('setup.py')
|
||||
@@ -1,44 +0,0 @@
|
||||
/******************************************************************************
|
||||
* ptsname.c
|
||||
*
|
||||
* A python extension to expose the POSIX ptsname() function.
|
||||
*
|
||||
* Copyright (C) 2007 XenSource Ltd
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Needed for Python versions earlier than 2.3. */
|
||||
#ifndef PyMODINIT_FUNC
|
||||
#define PyMODINIT_FUNC DL_EXPORT(void)
|
||||
#endif
|
||||
|
||||
static PyObject *do_ptsname(PyObject *self, PyObject *args)
|
||||
{
|
||||
int fd;
|
||||
char *path;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i", &fd))
|
||||
return NULL;
|
||||
|
||||
path = ptsname(fd);
|
||||
|
||||
if (!path)
|
||||
{
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyString_FromString(path);
|
||||
}
|
||||
|
||||
static PyMethodDef ptsname_methods[] = {
|
||||
{ "ptsname", do_ptsname, METH_VARARGS },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC initptsname(void)
|
||||
{
|
||||
Py_InitModule("ptsname", ptsname_methods);
|
||||
}
|
||||
+2
-93
@@ -27,58 +27,6 @@ xs = Extension("xs",
|
||||
depends = [ PATH_XENSTORE + "/libxenstore.so" ],
|
||||
sources = [ "xen/lowlevel/xs/xs.c" ])
|
||||
|
||||
scf = Extension("scf",
|
||||
extra_compile_args = extra_compile_args,
|
||||
include_dirs = [ "xen/lowlevel/scf" ],
|
||||
library_dirs = [ ],
|
||||
libraries = [ ],
|
||||
depends = [ ],
|
||||
sources = [ "xen/lowlevel/scf/scf.c" ])
|
||||
|
||||
process = Extension("process",
|
||||
extra_compile_args = extra_compile_args,
|
||||
include_dirs = [ "xen/lowlevel/process" ],
|
||||
library_dirs = [ ],
|
||||
libraries = [ "contract" ],
|
||||
depends = [ ],
|
||||
sources = [ "xen/lowlevel/process/process.c" ])
|
||||
|
||||
flask = Extension("flask",
|
||||
extra_compile_args = extra_compile_args,
|
||||
include_dirs = [ PATH_XEN, PATH_LIBXC, "xen/lowlevel/flask" ],
|
||||
library_dirs = [ PATH_LIBXC ],
|
||||
libraries = [ "xenctrl" ],
|
||||
depends = [ PATH_LIBXC + "/libxenctrl.so" ],
|
||||
sources = [ "xen/lowlevel/flask/flask.c" ])
|
||||
|
||||
ptsname = Extension("ptsname",
|
||||
extra_compile_args = extra_compile_args,
|
||||
include_dirs = [ "ptsname" ],
|
||||
library_dirs = [ ],
|
||||
libraries = [ ],
|
||||
depends = [ ],
|
||||
sources = [ "ptsname/ptsname.c" ])
|
||||
|
||||
checkpoint = Extension("checkpoint",
|
||||
extra_compile_args = extra_compile_args,
|
||||
include_dirs = [ PATH_XEN, PATH_LIBXC, PATH_XENSTORE ],
|
||||
library_dirs = [ PATH_LIBXC, PATH_XENSTORE ],
|
||||
libraries = [ "xenctrl", "xenguest", "xenstore", "rt" ],
|
||||
depends = [ PATH_LIBXC + "/libxenctrl.so",
|
||||
PATH_LIBXC + "/libxenguest.so",
|
||||
PATH_XENSTORE + "/libxenstore.so" ],
|
||||
sources = [ "xen/lowlevel/checkpoint/checkpoint.c",
|
||||
"xen/lowlevel/checkpoint/libcheckpoint.c"])
|
||||
|
||||
netlink = Extension("netlink",
|
||||
extra_compile_args = extra_compile_args,
|
||||
include_dirs = [ ],
|
||||
library_dirs = [ ],
|
||||
libraries = [ ],
|
||||
depends = [ ],
|
||||
sources = [ "xen/lowlevel/netlink/netlink.c",
|
||||
"xen/lowlevel/netlink/libnetlink.c"])
|
||||
|
||||
xl = Extension("xl",
|
||||
extra_compile_args = extra_compile_args,
|
||||
include_dirs = [ PATH_XEN, PATH_LIBXL, PATH_LIBXC, "xen/lowlevel/xl" ],
|
||||
@@ -88,54 +36,15 @@ xl = Extension("xl",
|
||||
sources = [ "xen/lowlevel/xl/xl.c", "xen/lowlevel/xl/_pyxl_types.c" ])
|
||||
|
||||
plat = os.uname()[0]
|
||||
modules = [ xc, xs, ptsname, flask ]
|
||||
modules = [ xc, xs ]
|
||||
#modules.extend([ xl ])
|
||||
if plat == 'SunOS':
|
||||
modules.extend([ scf, process ])
|
||||
if plat == 'Linux':
|
||||
modules.extend([ checkpoint, netlink ])
|
||||
|
||||
enable_xend = True
|
||||
new_argv = []
|
||||
for arg in sys.argv:
|
||||
if arg == "--xend=y":
|
||||
enable_xend = True
|
||||
elif arg == "--xend=n":
|
||||
enable_xend = False
|
||||
else:
|
||||
new_argv.append(arg)
|
||||
sys.argv = new_argv
|
||||
|
||||
if enable_xend:
|
||||
xend_packages = [
|
||||
'xen.util',
|
||||
'xen.util.xsm',
|
||||
'xen.util.xsm.dummy',
|
||||
'xen.util.xsm.flask',
|
||||
'xen.util.xsm.acm',
|
||||
'xen.xend',
|
||||
'xen.xend.server',
|
||||
'xen.xend.xenstore',
|
||||
'xen.xm',
|
||||
'xen.web',
|
||||
'xen.remus',
|
||||
'xen.xend.tests',
|
||||
'xen.xend.server.tests',
|
||||
'xen.xend.xenstore.tests',
|
||||
'xen.xm.tests'
|
||||
]
|
||||
else:
|
||||
xend_packages = []
|
||||
|
||||
setup(name = 'xen',
|
||||
version = '3.0',
|
||||
description = 'Xen',
|
||||
packages = ['xen',
|
||||
'xen.lowlevel',
|
||||
] + xend_packages,
|
||||
],
|
||||
ext_package = "xen.lowlevel",
|
||||
ext_modules = modules
|
||||
)
|
||||
|
||||
os.chdir('logging')
|
||||
execfile('setup.py')
|
||||
@@ -1,371 +0,0 @@
|
||||
/* python bridge to checkpointing API */
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include <xenstore.h>
|
||||
#include <xenctrl.h>
|
||||
|
||||
#include "checkpoint.h"
|
||||
|
||||
#define PKG "xen.lowlevel.checkpoint"
|
||||
|
||||
static PyObject* CheckpointError;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
checkpoint_state cps;
|
||||
|
||||
/* milliseconds between checkpoints */
|
||||
unsigned int interval;
|
||||
int armed;
|
||||
|
||||
PyObject* suspend_cb;
|
||||
PyObject* postcopy_cb;
|
||||
PyObject* checkpoint_cb;
|
||||
|
||||
PyThreadState* threadstate;
|
||||
} CheckpointObject;
|
||||
|
||||
static int suspend_trampoline(void* data);
|
||||
static int postcopy_trampoline(void* data);
|
||||
static int checkpoint_trampoline(void* data);
|
||||
|
||||
static PyObject* Checkpoint_new(PyTypeObject* type, PyObject* args,
|
||||
PyObject* kwargs)
|
||||
{
|
||||
CheckpointObject* self = (CheckpointObject*)type->tp_alloc(type, 0);
|
||||
|
||||
if (!self)
|
||||
return NULL;
|
||||
|
||||
checkpoint_init(&self->cps);
|
||||
self->suspend_cb = NULL;
|
||||
self->armed = 0;
|
||||
|
||||
return (PyObject*)self;
|
||||
}
|
||||
|
||||
static int Checkpoint_init(PyObject* obj, PyObject* args, PyObject* kwargs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Checkpoint_dealloc(CheckpointObject* self)
|
||||
{
|
||||
checkpoint_close(&self->cps);
|
||||
|
||||
self->ob_type->tp_free((PyObject*)self);
|
||||
}
|
||||
|
||||
static PyObject* pycheckpoint_open(PyObject* obj, PyObject* args)
|
||||
{
|
||||
CheckpointObject* self = (CheckpointObject*)obj;
|
||||
checkpoint_state* cps = &self->cps;
|
||||
unsigned int domid;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "I", &domid))
|
||||
return NULL;
|
||||
|
||||
if (checkpoint_open(cps, domid) < 0) {
|
||||
PyErr_SetString(CheckpointError, checkpoint_error(cps));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject* pycheckpoint_close(PyObject* obj, PyObject* args)
|
||||
{
|
||||
CheckpointObject* self = (CheckpointObject*)obj;
|
||||
|
||||
if (checkpoint_resume(&self->cps) < 0)
|
||||
fprintf(stderr, "%s\n", checkpoint_error(&self->cps));
|
||||
|
||||
checkpoint_close(&self->cps);
|
||||
|
||||
Py_XDECREF(self->suspend_cb);
|
||||
self->suspend_cb = NULL;
|
||||
Py_XDECREF(self->postcopy_cb);
|
||||
self->postcopy_cb = NULL;
|
||||
Py_XDECREF(self->checkpoint_cb);
|
||||
self->checkpoint_cb = NULL;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject* pycheckpoint_start(PyObject* obj, PyObject* args) {
|
||||
CheckpointObject* self = (CheckpointObject*)obj;
|
||||
|
||||
PyObject* iofile;
|
||||
PyObject* suspend_cb = NULL;
|
||||
PyObject* postcopy_cb = NULL;
|
||||
PyObject* checkpoint_cb = NULL;
|
||||
unsigned int interval = 0;
|
||||
unsigned int flags = 0;
|
||||
|
||||
int fd;
|
||||
struct save_callbacks callbacks;
|
||||
int rc;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O|OOOII", &iofile, &suspend_cb, &postcopy_cb,
|
||||
&checkpoint_cb, &interval, &flags))
|
||||
return NULL;
|
||||
|
||||
self->interval = interval;
|
||||
|
||||
Py_INCREF(iofile);
|
||||
Py_XINCREF(suspend_cb);
|
||||
Py_XINCREF(postcopy_cb);
|
||||
Py_XINCREF(checkpoint_cb);
|
||||
|
||||
fd = PyObject_AsFileDescriptor(iofile);
|
||||
Py_DECREF(iofile);
|
||||
if (fd < 0) {
|
||||
PyErr_SetString(PyExc_TypeError, "invalid file handle");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (suspend_cb && suspend_cb != Py_None) {
|
||||
if (!PyCallable_Check(suspend_cb)) {
|
||||
PyErr_SetString(PyExc_TypeError, "suspend callback not callable");
|
||||
goto err;
|
||||
}
|
||||
self->suspend_cb = suspend_cb;
|
||||
} else
|
||||
self->suspend_cb = NULL;
|
||||
|
||||
if (postcopy_cb && postcopy_cb != Py_None) {
|
||||
if (!PyCallable_Check(postcopy_cb)) {
|
||||
PyErr_SetString(PyExc_TypeError, "postcopy callback not callable");
|
||||
return NULL;
|
||||
}
|
||||
self->postcopy_cb = postcopy_cb;
|
||||
} else
|
||||
self->postcopy_cb = NULL;
|
||||
|
||||
if (checkpoint_cb && checkpoint_cb != Py_None) {
|
||||
if (!PyCallable_Check(checkpoint_cb)) {
|
||||
PyErr_SetString(PyExc_TypeError, "checkpoint callback not callable");
|
||||
return NULL;
|
||||
}
|
||||
self->checkpoint_cb = checkpoint_cb;
|
||||
} else
|
||||
self->checkpoint_cb = NULL;
|
||||
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.suspend = suspend_trampoline;
|
||||
callbacks.postcopy = postcopy_trampoline;
|
||||
callbacks.checkpoint = checkpoint_trampoline;
|
||||
callbacks.data = self;
|
||||
|
||||
self->threadstate = PyEval_SaveThread();
|
||||
rc = checkpoint_start(&self->cps, fd, &callbacks, flags);
|
||||
PyEval_RestoreThread(self->threadstate);
|
||||
|
||||
if (rc < 0) {
|
||||
PyErr_SetString(CheckpointError, checkpoint_error(&self->cps));
|
||||
goto err;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
err:
|
||||
self->suspend_cb = NULL;
|
||||
Py_XDECREF(suspend_cb);
|
||||
self->postcopy_cb = NULL;
|
||||
Py_XDECREF(postcopy_cb);
|
||||
self->checkpoint_cb = NULL;
|
||||
Py_XDECREF(checkpoint_cb);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyMethodDef Checkpoint_methods[] = {
|
||||
{ "open", pycheckpoint_open, METH_VARARGS,
|
||||
"open connection to xen" },
|
||||
{ "close", pycheckpoint_close, METH_NOARGS,
|
||||
"close connection to xen" },
|
||||
{ "start", pycheckpoint_start, METH_VARARGS | METH_KEYWORDS,
|
||||
"begin a checkpoint" },
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
static PyTypeObject CheckpointType = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
PKG ".checkpointer", /* tp_name */
|
||||
sizeof(CheckpointObject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)Checkpoint_dealloc, /* tp_dealloc */
|
||||
NULL, /* tp_print */
|
||||
NULL, /* tp_getattr */
|
||||
NULL, /* tp_setattr */
|
||||
NULL, /* tp_compare */
|
||||
NULL, /* tp_repr */
|
||||
NULL, /* tp_as_number */
|
||||
NULL, /* tp_as_sequence */
|
||||
NULL, /* tp_as_mapping */
|
||||
NULL, /* tp_hash */
|
||||
NULL, /* tp_call */
|
||||
NULL, /* tp_str */
|
||||
NULL, /* tp_getattro */
|
||||
NULL, /* tp_setattro */
|
||||
NULL, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
"Checkpoint object", /* tp_doc */
|
||||
NULL, /* tp_traverse */
|
||||
NULL, /* tp_clear */
|
||||
NULL, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
NULL, /* tp_iter */
|
||||
NULL, /* tp_iternext */
|
||||
Checkpoint_methods, /* tp_methods */
|
||||
NULL, /* tp_members */
|
||||
NULL, /* tp_getset */
|
||||
NULL, /* tp_base */
|
||||
NULL, /* tp_dict */
|
||||
NULL, /* tp_descr_get */
|
||||
NULL, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
(initproc)Checkpoint_init, /* tp_init */
|
||||
NULL, /* tp_alloc */
|
||||
Checkpoint_new, /* tp_new */
|
||||
};
|
||||
|
||||
static PyMethodDef methods[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static char doc[] = "checkpoint API";
|
||||
|
||||
PyMODINIT_FUNC initcheckpoint(void) {
|
||||
PyObject *m;
|
||||
|
||||
if (PyType_Ready(&CheckpointType) < 0)
|
||||
return;
|
||||
|
||||
m = Py_InitModule3(PKG, methods, doc);
|
||||
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
Py_INCREF(&CheckpointType);
|
||||
PyModule_AddObject(m, "checkpointer", (PyObject*)&CheckpointType);
|
||||
|
||||
CheckpointError = PyErr_NewException(PKG ".error", NULL, NULL);
|
||||
Py_INCREF(CheckpointError);
|
||||
PyModule_AddObject(m, "error", CheckpointError);
|
||||
|
||||
block_timer();
|
||||
}
|
||||
|
||||
/* private functions */
|
||||
|
||||
/* bounce C suspend call into python equivalent.
|
||||
* returns 1 on success or 0 on failure */
|
||||
static int suspend_trampoline(void* data)
|
||||
{
|
||||
CheckpointObject* self = (CheckpointObject*)data;
|
||||
|
||||
PyObject* result;
|
||||
|
||||
/* call default suspend function, then python hook if available */
|
||||
if (self->armed) {
|
||||
if (checkpoint_wait(&self->cps) < 0) {
|
||||
fprintf(stderr, "%s\n", checkpoint_error(&self->cps));
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (self->interval) {
|
||||
self->armed = 1;
|
||||
checkpoint_settimer(&self->cps, self->interval);
|
||||
}
|
||||
|
||||
if (!checkpoint_suspend(&self->cps)) {
|
||||
fprintf(stderr, "%s\n", checkpoint_error(&self->cps));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!self->suspend_cb)
|
||||
return 1;
|
||||
|
||||
PyEval_RestoreThread(self->threadstate);
|
||||
result = PyObject_CallFunction(self->suspend_cb, NULL);
|
||||
self->threadstate = PyEval_SaveThread();
|
||||
|
||||
if (!result)
|
||||
return 0;
|
||||
|
||||
if (result == Py_None || PyObject_IsTrue(result)) {
|
||||
Py_DECREF(result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Py_DECREF(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int postcopy_trampoline(void* data)
|
||||
{
|
||||
CheckpointObject* self = (CheckpointObject*)data;
|
||||
|
||||
PyObject* result;
|
||||
int rc = 0;
|
||||
|
||||
if (!self->postcopy_cb)
|
||||
goto resume;
|
||||
|
||||
PyEval_RestoreThread(self->threadstate);
|
||||
result = PyObject_CallFunction(self->postcopy_cb, NULL);
|
||||
|
||||
if (result && (result == Py_None || PyObject_IsTrue(result)))
|
||||
rc = 1;
|
||||
|
||||
Py_XDECREF(result);
|
||||
self->threadstate = PyEval_SaveThread();
|
||||
|
||||
resume:
|
||||
if (checkpoint_resume(&self->cps) < 0) {
|
||||
fprintf(stderr, "%s\n", checkpoint_error(&self->cps));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int checkpoint_trampoline(void* data)
|
||||
{
|
||||
CheckpointObject* self = (CheckpointObject*)data;
|
||||
|
||||
PyObject* result;
|
||||
|
||||
if (checkpoint_postflush(&self->cps) < 0) {
|
||||
fprintf(stderr, "%s\n", checkpoint_error(&self->cps));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!self->checkpoint_cb)
|
||||
return 0;
|
||||
|
||||
PyEval_RestoreThread(self->threadstate);
|
||||
result = PyObject_CallFunction(self->checkpoint_cb, NULL);
|
||||
self->threadstate = PyEval_SaveThread();
|
||||
|
||||
if (!result)
|
||||
return 0;
|
||||
|
||||
if (result == Py_None || PyObject_IsTrue(result)) {
|
||||
Py_DECREF(result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Py_DECREF(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/* API for checkpointing */
|
||||
|
||||
#ifndef _CHECKPOINT_H_
|
||||
#define _CHECKPOINT_H_ 1
|
||||
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <xenguest.h>
|
||||
#include <xenstore.h>
|
||||
|
||||
typedef enum {
|
||||
dt_unknown,
|
||||
dt_pv,
|
||||
dt_hvm,
|
||||
dt_pvhvm /* HVM with PV drivers */
|
||||
} checkpoint_domtype;
|
||||
|
||||
typedef struct {
|
||||
xc_interface *xch;
|
||||
xc_evtchn *xce; /* event channel handle */
|
||||
struct xs_handle* xsh; /* xenstore handle */
|
||||
int watching_shutdown; /* state of watch on @releaseDomain */
|
||||
|
||||
unsigned int domid;
|
||||
checkpoint_domtype domtype;
|
||||
int fd;
|
||||
|
||||
int suspend_evtchn, suspend_lockfd;
|
||||
|
||||
char* errstr;
|
||||
|
||||
/* suspend deadline thread support */
|
||||
volatile int suspended;
|
||||
volatile int done;
|
||||
pthread_t suspend_thr;
|
||||
sem_t suspended_sem;
|
||||
sem_t resumed_sem;
|
||||
timer_t timer;
|
||||
} checkpoint_state;
|
||||
|
||||
#define CHECKPOINT_FLAGS_COMPRESSION 1
|
||||
char* checkpoint_error(checkpoint_state* s);
|
||||
|
||||
void checkpoint_init(checkpoint_state* s);
|
||||
int checkpoint_open(checkpoint_state* s, unsigned int domid);
|
||||
void checkpoint_close(checkpoint_state* s);
|
||||
int checkpoint_start(checkpoint_state* s, int fd,
|
||||
struct save_callbacks* callbacks,
|
||||
unsigned int remus_flags);
|
||||
int checkpoint_suspend(checkpoint_state* s);
|
||||
int checkpoint_resume(checkpoint_state* s);
|
||||
int checkpoint_postflush(checkpoint_state* s);
|
||||
|
||||
int checkpoint_settimer(checkpoint_state* s, int millis);
|
||||
int checkpoint_wait(checkpoint_state* s);
|
||||
void block_timer(void);
|
||||
void unblock_timer(void);
|
||||
|
||||
#endif
|
||||
@@ -1,850 +0,0 @@
|
||||
/* API for checkpointing */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <xenctrl.h>
|
||||
#include <xenguest.h>
|
||||
#include <xenstore.h>
|
||||
|
||||
#include "checkpoint.h"
|
||||
|
||||
static char errbuf[256];
|
||||
|
||||
static int setup_suspend_evtchn(checkpoint_state* s);
|
||||
static void release_suspend_evtchn(checkpoint_state *s);
|
||||
static int setup_shutdown_watch(checkpoint_state* s);
|
||||
static int check_shutdown(checkpoint_state* s);
|
||||
static void release_shutdown_watch(checkpoint_state* s);
|
||||
|
||||
static int evtchn_suspend(checkpoint_state* s);
|
||||
static int compat_suspend(checkpoint_state* s);
|
||||
static int pollfd(checkpoint_state* s, int fd);
|
||||
|
||||
static int switch_qemu_logdirty(checkpoint_state* s, int enable);
|
||||
static int suspend_hvm(checkpoint_state* s);
|
||||
static int suspend_qemu(checkpoint_state* s);
|
||||
static int resume_qemu(checkpoint_state* s);
|
||||
static int send_qemu(checkpoint_state* s);
|
||||
|
||||
static int create_suspend_timer(checkpoint_state* s);
|
||||
static int delete_suspend_timer(checkpoint_state* s);
|
||||
static int create_suspend_thread(checkpoint_state* s);
|
||||
static void stop_suspend_thread(checkpoint_state* s);
|
||||
|
||||
/* Returns a string describing the most recent error returned by
|
||||
* a checkpoint function. Static -- do not free. */
|
||||
char* checkpoint_error(checkpoint_state* s)
|
||||
{
|
||||
return s->errstr;
|
||||
}
|
||||
|
||||
void checkpoint_init(checkpoint_state* s)
|
||||
{
|
||||
s->xch = NULL;
|
||||
s->xce = NULL;
|
||||
s->xsh = NULL;
|
||||
s->watching_shutdown = 0;
|
||||
|
||||
s->domid = 0;
|
||||
s->domtype = dt_unknown;
|
||||
s->fd = -1;
|
||||
|
||||
s->suspend_evtchn = -1;
|
||||
s->suspend_lockfd = -1;
|
||||
|
||||
s->errstr = NULL;
|
||||
|
||||
s->suspended = 0;
|
||||
s->done = 0;
|
||||
s->suspend_thr = 0;
|
||||
s->timer = 0;
|
||||
}
|
||||
|
||||
/* open a checkpoint session to guest domid */
|
||||
int checkpoint_open(checkpoint_state* s, unsigned int domid)
|
||||
{
|
||||
xc_dominfo_t dominfo;
|
||||
unsigned long pvirq;
|
||||
|
||||
s->domid = domid;
|
||||
|
||||
s->xch = xc_interface_open(0,0,0);
|
||||
if (!s->xch) {
|
||||
s->errstr = "could not open control interface (are you root?)";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->xsh = xs_daemon_open();
|
||||
if (!s->xsh) {
|
||||
checkpoint_close(s);
|
||||
s->errstr = "could not open xenstore handle";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->xce = xc_evtchn_open(NULL, 0);
|
||||
if (s->xce == NULL) {
|
||||
checkpoint_close(s);
|
||||
s->errstr = "could not open event channel handle";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (xc_domain_getinfo(s->xch, s->domid, 1, &dominfo) < 0) {
|
||||
checkpoint_close(s);
|
||||
s->errstr = "could not get domain info";
|
||||
|
||||
return -1;
|
||||
}
|
||||
if (dominfo.hvm) {
|
||||
if (xc_get_hvm_param(s->xch, s->domid, HVM_PARAM_CALLBACK_IRQ, &pvirq)) {
|
||||
checkpoint_close(s);
|
||||
s->errstr = "could not get HVM callback IRQ";
|
||||
|
||||
return -1;
|
||||
}
|
||||
s->domtype = pvirq ? dt_pvhvm : dt_hvm;
|
||||
} else
|
||||
s->domtype = dt_pv;
|
||||
|
||||
if (setup_shutdown_watch(s) < 0) {
|
||||
checkpoint_close(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s->domtype == dt_pv) {
|
||||
if (setup_suspend_evtchn(s) < 0) {
|
||||
fprintf(stderr, "WARNING: suspend event channel unavailable, "
|
||||
"falling back to slow xenstore signalling\n");
|
||||
}
|
||||
} else if (s->domtype == dt_pvhvm) {
|
||||
checkpoint_close(s);
|
||||
s->errstr = "PV-on-HVM is unsupported";
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void checkpoint_close(checkpoint_state* s)
|
||||
{
|
||||
if (s->timer)
|
||||
delete_suspend_timer(s);
|
||||
if (s->suspend_thr)
|
||||
stop_suspend_thread(s);
|
||||
|
||||
release_shutdown_watch(s);
|
||||
release_suspend_evtchn(s);
|
||||
|
||||
if (s->xch) {
|
||||
xc_interface_close(s->xch);
|
||||
s->xch = NULL;
|
||||
}
|
||||
if (s->xce != NULL) {
|
||||
xc_evtchn_close(s->xce);
|
||||
s->xce = NULL;
|
||||
}
|
||||
if (s->xsh) {
|
||||
xs_daemon_close(s->xsh);
|
||||
s->xsh = NULL;
|
||||
}
|
||||
|
||||
s->domid = 0;
|
||||
s->fd = -1;
|
||||
}
|
||||
|
||||
/* we toggle logdirty ourselves around the xc_domain_save call --
|
||||
* it avoids having to pass around checkpoint_state */
|
||||
static int noop_switch_logdirty(int domid, unsigned enable, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int checkpoint_start(checkpoint_state* s, int fd,
|
||||
struct save_callbacks* callbacks,
|
||||
unsigned int remus_flags)
|
||||
{
|
||||
int hvm, rc;
|
||||
int flags = XCFLAGS_LIVE;
|
||||
unsigned long vm_generationid_addr;
|
||||
|
||||
if (!s->domid) {
|
||||
s->errstr = "checkpoint state not opened";
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->fd = fd;
|
||||
|
||||
hvm = s->domtype > dt_pv;
|
||||
if (hvm) {
|
||||
char path[128];
|
||||
char *addr;
|
||||
|
||||
sprintf(path, "/local/domain/%u/hvmloader/generation-id-address", s->domid);
|
||||
addr = xs_read(s->xsh, XBT_NULL, path, NULL);
|
||||
|
||||
vm_generationid_addr = (addr) ? strtoul(addr, NULL, 0) : 0;
|
||||
free(addr);
|
||||
|
||||
flags |= XCFLAGS_HVM;
|
||||
if (switch_qemu_logdirty(s, 1))
|
||||
return -1;
|
||||
} else {
|
||||
vm_generationid_addr = 0;
|
||||
}
|
||||
if (remus_flags & CHECKPOINT_FLAGS_COMPRESSION)
|
||||
flags |= XCFLAGS_CHECKPOINT_COMPRESS;
|
||||
|
||||
callbacks->switch_qemu_logdirty = noop_switch_logdirty;
|
||||
|
||||
rc = xc_domain_save(s->xch, fd, s->domid, 0, 0, flags, callbacks, hvm,
|
||||
vm_generationid_addr);
|
||||
|
||||
if (hvm)
|
||||
switch_qemu_logdirty(s, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* suspend the domain. Returns 0 on failure, 1 on success */
|
||||
int checkpoint_suspend(checkpoint_state* s)
|
||||
{
|
||||
struct timeval tv;
|
||||
int rc;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
fprintf(stderr, "PROF: suspending at %lu.%06lu\n", (unsigned long)tv.tv_sec,
|
||||
(unsigned long)tv.tv_usec);
|
||||
|
||||
if (s->suspend_evtchn >= 0)
|
||||
rc = evtchn_suspend(s);
|
||||
else if (s->domtype == dt_hvm)
|
||||
rc = suspend_hvm(s);
|
||||
else
|
||||
rc = compat_suspend(s);
|
||||
|
||||
return rc < 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
/* wait for a suspend to be triggered by another thread */
|
||||
int checkpoint_wait(checkpoint_state* s)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!s->suspend_thr) {
|
||||
s->errstr = "checkpoint timer is not active\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
rc = sem_wait(&s->suspended_sem);
|
||||
if (rc < 0 && errno != EINTR) {
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"error waiting for suspend semaphore: %d %d\n", rc, errno);
|
||||
s->errstr = errbuf;
|
||||
return -1;
|
||||
}
|
||||
} while (rc < 0);
|
||||
|
||||
if (!s->suspended) {
|
||||
snprintf(errbuf, sizeof(errbuf), "domain not suspended?\n");
|
||||
s->errstr = errbuf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* let guest execution resume */
|
||||
int checkpoint_resume(checkpoint_state* s)
|
||||
{
|
||||
struct timeval tv;
|
||||
int rc;
|
||||
|
||||
if (xc_domain_resume(s->xch, s->domid, 1)) {
|
||||
snprintf(errbuf, sizeof(errbuf), "error resuming domain: %d", errno);
|
||||
s->errstr = errbuf;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
fprintf(stderr, "PROF: resumed at %lu.%06lu\n", (unsigned long)tv.tv_sec,
|
||||
(unsigned long)tv.tv_usec);
|
||||
|
||||
if (s->domtype > dt_pv && resume_qemu(s) < 0)
|
||||
return -1;
|
||||
|
||||
/* restore watchability in xenstore */
|
||||
if (xs_resume_domain(s->xsh, s->domid) < 0)
|
||||
fprintf(stderr, "error resuming domain in xenstore\n");
|
||||
|
||||
s->suspended = 0;
|
||||
|
||||
if (s->suspend_thr) {
|
||||
if ((rc = sem_post(&s->resumed_sem)))
|
||||
fprintf(stderr, "error posting resume semaphore\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* called after xc_domain_save has flushed its buffer */
|
||||
int checkpoint_postflush(checkpoint_state *s)
|
||||
{
|
||||
if (s->domtype > dt_pv && send_qemu(s) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* force suspend within millis ms if copy hasn't completed yet */
|
||||
int checkpoint_settimer(checkpoint_state* s, int millis)
|
||||
{
|
||||
struct itimerspec t;
|
||||
int err;
|
||||
|
||||
if (!s->suspend_thr) {
|
||||
if (create_suspend_timer(s) < 0)
|
||||
return -1;
|
||||
|
||||
if (create_suspend_thread(s) < 0) {
|
||||
delete_suspend_timer(s);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
t.it_value.tv_sec = millis / 1000;
|
||||
t.it_value.tv_nsec = (millis % 1000) * 1000000L;
|
||||
t.it_interval.tv_sec = t.it_value.tv_sec;
|
||||
t.it_interval.tv_nsec = t.it_value.tv_nsec;
|
||||
|
||||
if ((err = timer_settime(s->timer, 0, &t, NULL))) {
|
||||
fprintf(stderr, "Error arming timer: %d\n", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int delete_suspend_timer(checkpoint_state* s)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (s->timer) {
|
||||
if ((rc = timer_delete(s->timer)))
|
||||
fprintf(stderr, "Error deleting timer: %s\n", strerror(errno));
|
||||
s->timer = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Set up event channel used to signal a guest to suspend itself */
|
||||
static int setup_suspend_evtchn(checkpoint_state* s)
|
||||
{
|
||||
int port;
|
||||
|
||||
port = xs_suspend_evtchn_port(s->domid);
|
||||
if (port < 0) {
|
||||
s->errstr = "failed to read suspend event channel";
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->suspend_evtchn = xc_suspend_evtchn_init_exclusive(s->xch, s->xce,
|
||||
s->domid, port, &s->suspend_lockfd);
|
||||
if (s->suspend_evtchn < 0) {
|
||||
s->errstr = "failed to bind suspend event channel";
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "bound to suspend event channel %u:%d as %d\n", s->domid, port,
|
||||
s->suspend_evtchn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* release suspend event channels bound to guest */
|
||||
static void release_suspend_evtchn(checkpoint_state *s)
|
||||
{
|
||||
/* TODO: teach xen to clean up if port is unbound */
|
||||
if (s->xce != NULL && s->suspend_evtchn >= 0) {
|
||||
xc_suspend_evtchn_release(s->xch, s->xce, s->domid,
|
||||
s->suspend_evtchn, &s->suspend_lockfd);
|
||||
s->suspend_evtchn = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int setup_shutdown_watch(checkpoint_state* s)
|
||||
{
|
||||
char buf[16];
|
||||
|
||||
/* write domain ID to watch so we can ignore other domain shutdowns */
|
||||
snprintf(buf, sizeof(buf), "%u", s->domid);
|
||||
if ( !xs_watch(s->xsh, "@releaseDomain", buf) ) {
|
||||
fprintf(stderr, "Could not bind to shutdown watch\n");
|
||||
return -1;
|
||||
}
|
||||
/* watch fires once on registration */
|
||||
s->watching_shutdown = 1;
|
||||
check_shutdown(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns -1 on error or death, 0 if domain is running, 1 if suspended */
|
||||
static int check_shutdown(checkpoint_state* s) {
|
||||
unsigned int count;
|
||||
int xsfd;
|
||||
char **vec;
|
||||
char buf[16];
|
||||
xc_dominfo_t info;
|
||||
|
||||
xsfd = xs_fileno(s->xsh);
|
||||
|
||||
/* loop on watch if it fires for another domain */
|
||||
while (1) {
|
||||
if (pollfd(s, xsfd) < 0)
|
||||
return -1;
|
||||
|
||||
vec = xs_read_watch(s->xsh, &count);
|
||||
if (s->watching_shutdown == 1) {
|
||||
s->watching_shutdown = 2;
|
||||
return 0;
|
||||
}
|
||||
if (!vec) {
|
||||
fprintf(stderr, "empty watch fired\n");
|
||||
continue;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%d", s->domid);
|
||||
if (!strcmp(vec[XS_WATCH_TOKEN], buf))
|
||||
break;
|
||||
}
|
||||
|
||||
if (xc_domain_getinfo(s->xch, s->domid, 1, &info) != 1
|
||||
|| info.domid != s->domid) {
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"error getting info for domain %u", s->domid);
|
||||
s->errstr = errbuf;
|
||||
return -1;
|
||||
}
|
||||
if (!info.shutdown) {
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"domain %u not shut down", s->domid);
|
||||
s->errstr = errbuf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info.shutdown_reason != SHUTDOWN_suspend)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void release_shutdown_watch(checkpoint_state* s) {
|
||||
char buf[16];
|
||||
|
||||
if (!s->xsh)
|
||||
return;
|
||||
if (!s->watching_shutdown)
|
||||
return;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", s->domid);
|
||||
if (!xs_unwatch(s->xsh, "@releaseDomain", buf))
|
||||
fprintf(stderr, "Could not release shutdown watch\n");
|
||||
|
||||
s->watching_shutdown = 0;
|
||||
}
|
||||
|
||||
static int evtchn_suspend(checkpoint_state* s)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = xc_evtchn_notify(s->xce, s->suspend_evtchn);
|
||||
if (rc < 0) {
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"failed to notify suspend event channel: %d", rc);
|
||||
s->errstr = errbuf;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
do
|
||||
if (!(rc = pollfd(s, xc_evtchn_fd(s->xce))))
|
||||
rc = xc_evtchn_pending(s->xce);
|
||||
while (rc >= 0 && rc != s->suspend_evtchn);
|
||||
if (rc <= 0)
|
||||
return -1;
|
||||
|
||||
if (xc_evtchn_unmask(s->xce, s->suspend_evtchn) < 0) {
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"failed to unmask suspend notification channel: %d", rc);
|
||||
s->errstr = errbuf;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* suspend through xenstore if suspend event channel is unavailable */
|
||||
static int compat_suspend(checkpoint_state* s)
|
||||
{
|
||||
char path[128];
|
||||
|
||||
sprintf(path, "/local/domain/%u/control/shutdown", s->domid);
|
||||
|
||||
if (!xs_write(s->xsh, XBT_NULL, path, "suspend", 7)) {
|
||||
s->errstr = "error signalling qemu logdirty";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (check_shutdown(s) != 1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns -1 if fd does not become readable within timeout */
|
||||
static int pollfd(checkpoint_state* s, int fd)
|
||||
{
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
int rc;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd, &rfds);
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 500000;
|
||||
|
||||
rc = select(fd + 1, &rfds, NULL, NULL, &tv);
|
||||
|
||||
if (rc < 0) {
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"error polling fd: %s", strerror(errno));
|
||||
s->errstr = errbuf;
|
||||
} else if (!rc) {
|
||||
snprintf(errbuf, sizeof(errbuf), "timeout polling fd");
|
||||
s->errstr = errbuf;
|
||||
} else if (! FD_ISSET(fd, &rfds)) {
|
||||
snprintf(errbuf, sizeof(errbuf), "unknown error polling fd");
|
||||
s->errstr = errbuf;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* adapted from the eponymous function in xc_save */
|
||||
static int switch_qemu_logdirty(checkpoint_state *s, int enable)
|
||||
{
|
||||
char path[128];
|
||||
char *tail, *cmd, *response;
|
||||
char **vec;
|
||||
unsigned int len;
|
||||
|
||||
sprintf(path, "/local/domain/0/device-model/%u/logdirty/", s->domid);
|
||||
tail = path + strlen(path);
|
||||
|
||||
strcpy(tail, "ret");
|
||||
if (!xs_watch(s->xsh, path, "qemu-logdirty-ret")) {
|
||||
s->errstr = "error watching qemu logdirty return";
|
||||
return 1;
|
||||
}
|
||||
/* null fire. XXX unify with shutdown watch! */
|
||||
vec = xs_read_watch(s->xsh, &len);
|
||||
free(vec);
|
||||
|
||||
strcpy(tail, "cmd");
|
||||
cmd = enable ? "enable" : "disable";
|
||||
if (!xs_write(s->xsh, XBT_NULL, path, cmd, strlen(cmd))) {
|
||||
s->errstr = "error signalling qemu logdirty";
|
||||
return 1;
|
||||
}
|
||||
|
||||
vec = xs_read_watch(s->xsh, &len);
|
||||
free(vec);
|
||||
|
||||
strcpy(tail, "ret");
|
||||
xs_unwatch(s->xsh, path, "qemu-logdirty-ret");
|
||||
|
||||
response = xs_read(s->xsh, XBT_NULL, path, &len);
|
||||
if (!len || strcmp(response, cmd)) {
|
||||
if (len)
|
||||
free(response);
|
||||
s->errstr = "qemu logdirty command failed";
|
||||
return 1;
|
||||
}
|
||||
free(response);
|
||||
fprintf(stderr, "qemu logdirty mode: %s\n", cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int suspend_hvm(checkpoint_state *s)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
fprintf(stderr, "issuing HVM suspend hypercall\n");
|
||||
rc = xc_domain_shutdown(s->xch, s->domid, SHUTDOWN_suspend);
|
||||
if (rc < 0) {
|
||||
s->errstr = "shutdown hypercall failed";
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "suspend hypercall returned %d\n", rc);
|
||||
|
||||
if (check_shutdown(s) != 1)
|
||||
return -1;
|
||||
|
||||
rc = suspend_qemu(s);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int suspend_qemu(checkpoint_state *s)
|
||||
{
|
||||
char path[128];
|
||||
|
||||
fprintf(stderr, "pausing QEMU\n");
|
||||
|
||||
sprintf(path, "/local/domain/0/device-model/%d/command", s->domid);
|
||||
if (!xs_write(s->xsh, XBT_NULL, path, "save", 4)) {
|
||||
fprintf(stderr, "error signalling QEMU to save\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(path, "/local/domain/0/device-model/%d/state", s->domid);
|
||||
|
||||
do {
|
||||
char* state;
|
||||
unsigned int len;
|
||||
|
||||
state = xs_read(s->xsh, XBT_NULL, path, &len);
|
||||
if (!state) {
|
||||
s->errstr = "error reading QEMU state";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strcmp(state, "paused")) {
|
||||
free(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(state);
|
||||
usleep(1000);
|
||||
} while(1);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int resume_qemu(checkpoint_state *s)
|
||||
{
|
||||
char path[128];
|
||||
fprintf(stderr, "resuming QEMU\n");
|
||||
|
||||
sprintf(path, "/local/domain/0/device-model/%d/command", s->domid);
|
||||
if (!xs_write(s->xsh, XBT_NULL, path, "continue", 8)) {
|
||||
fprintf(stderr, "error signalling QEMU to resume\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_qemu(checkpoint_state *s)
|
||||
{
|
||||
char buf[8192];
|
||||
char path[128];
|
||||
struct stat sb;
|
||||
uint32_t qlen = 0;
|
||||
int qfd;
|
||||
int rc;
|
||||
|
||||
if (s->fd < 0)
|
||||
return -1;
|
||||
|
||||
sprintf(path, "/var/lib/xen/qemu-save.%d", s->domid);
|
||||
|
||||
if (stat(path, &sb) < 0) {
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"error getting QEMU state file status: %s", strerror(errno));
|
||||
s->errstr = errbuf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
qlen = sb.st_size;
|
||||
qfd = open(path, O_RDONLY);
|
||||
if (qfd < 0) {
|
||||
snprintf(errbuf, sizeof(errbuf), "error opening QEMU state file: %s",
|
||||
strerror(errno));
|
||||
s->errstr = errbuf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Sending %u bytes of QEMU state\n", qlen);
|
||||
if (write(s->fd, "RemusDeviceModelState", 21) != 21) {
|
||||
s->errstr = "error writing QEMU header";
|
||||
close(qfd);
|
||||
return -1;
|
||||
}
|
||||
if (write(s->fd, &qlen, sizeof(qlen)) != sizeof(qlen)) {
|
||||
s->errstr = "error writing QEMU size";
|
||||
close(qfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((rc = read(qfd, buf, qlen > sizeof(buf) ? sizeof(buf) : qlen)) > 0) {
|
||||
qlen -= rc;
|
||||
if (write(s->fd, buf, rc) != rc) {
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rc < 0) {
|
||||
snprintf(errbuf, sizeof(errbuf), "error writing QEMU state: %s",
|
||||
strerror(errno));
|
||||
s->errstr = errbuf;
|
||||
}
|
||||
|
||||
close(qfd);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*thread responsible to suspend the domain early if necessary*/
|
||||
static void *suspend_thread(void *arg)
|
||||
{
|
||||
checkpoint_state* s = (checkpoint_state*)arg;
|
||||
sigset_t tss;
|
||||
int rc;
|
||||
int sig;
|
||||
|
||||
fprintf(stderr, "Suspend thread started\n");
|
||||
|
||||
sigemptyset(&tss);
|
||||
sigaddset(&tss, SIGRTMIN);
|
||||
|
||||
while (1) {
|
||||
/* wait for checkpoint thread to signal resume */
|
||||
if ((rc = sem_wait(&s->resumed_sem)))
|
||||
fprintf(stderr, "Error waiting on resume semaphore\n");
|
||||
|
||||
if ((rc = sigwait(&tss, &sig))) {
|
||||
fprintf(stderr, "sigwait failed: %d %d\n", rc, errno);
|
||||
break;
|
||||
}
|
||||
if (sig != SIGRTMIN)
|
||||
fprintf(stderr, "received unexpected signal %d\n", sig);
|
||||
|
||||
if (s->done)
|
||||
break;
|
||||
|
||||
if (s->suspended) {
|
||||
fprintf(stderr, "domain already suspended?\n");
|
||||
} else {
|
||||
rc = checkpoint_suspend(s);
|
||||
if (rc)
|
||||
s->suspended = 1;
|
||||
else
|
||||
fprintf(stderr, "checkpoint_suspend failed\n");
|
||||
}
|
||||
|
||||
if ((rc = sem_post(&s->suspended_sem)))
|
||||
fprintf(stderr, "Error posting suspend semaphore\n");
|
||||
}
|
||||
|
||||
fprintf(stderr, "Suspend thread exiting\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int create_suspend_timer(checkpoint_state* s)
|
||||
{
|
||||
struct sigevent event;
|
||||
int err;
|
||||
|
||||
event.sigev_notify = SIGEV_SIGNAL;
|
||||
event.sigev_signo = SIGRTMIN;
|
||||
event.sigev_value.sival_int = 0;
|
||||
|
||||
if ((err = timer_create(CLOCK_REALTIME, &event, &s->timer))) {
|
||||
snprintf(errbuf, sizeof(errbuf), "Error creating timer: %d\n", err);
|
||||
s->errstr = errbuf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void block_timer(void)
|
||||
{
|
||||
sigset_t tss;
|
||||
|
||||
sigemptyset(&tss);
|
||||
sigaddset(&tss, SIGRTMIN);
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, &tss, NULL);
|
||||
}
|
||||
|
||||
void unblock_timer(void)
|
||||
{
|
||||
sigset_t tss;
|
||||
|
||||
sigemptyset(&tss);
|
||||
sigaddset(&tss, SIGRTMIN);
|
||||
|
||||
pthread_sigmask(SIG_UNBLOCK, &tss, NULL);
|
||||
}
|
||||
|
||||
static int create_suspend_thread(checkpoint_state* s)
|
||||
{
|
||||
int err;
|
||||
|
||||
if ((err = sem_init(&s->suspended_sem, 0, 0))) {
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"Error initializing suspend semaphore: %d\n", err);
|
||||
s->errstr = errbuf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((err = sem_init(&s->resumed_sem, 0, 0))) {
|
||||
snprintf(errbuf, sizeof(errbuf),
|
||||
"Error initializing resume semaphore: %d\n", err);
|
||||
s->errstr = errbuf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* signal mask should be inherited */
|
||||
block_timer();
|
||||
|
||||
if ((err = pthread_create(&s->suspend_thr, NULL, suspend_thread, s))) {
|
||||
snprintf(errbuf, sizeof(errbuf), "Error creating suspend thread: %d\n", err);
|
||||
s->errstr = errbuf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stop_suspend_thread(checkpoint_state* s)
|
||||
{
|
||||
int err;
|
||||
|
||||
s->done = 1;
|
||||
|
||||
err = sem_post(&s->resumed_sem);
|
||||
|
||||
err = pthread_join(s->suspend_thr, NULL);
|
||||
s->suspend_thr = 0;
|
||||
}
|
||||
@@ -1,292 +0,0 @@
|
||||
/******************************************************************************
|
||||
* flask.c
|
||||
*
|
||||
* Authors: George Coker, <gscoker@alpha.ncsc.mil>
|
||||
* Michael LeMay, <mdlemay@epoch.ncsc.mil>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include <xenctrl.h>
|
||||
|
||||
#define PKG "xen.lowlevel.flask"
|
||||
#define CLS "flask"
|
||||
|
||||
#define CTX_LEN 1024
|
||||
|
||||
static PyObject *xc_error_obj;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD;
|
||||
xc_interface *xc_handle;
|
||||
} XcObject;
|
||||
|
||||
static PyObject *pyflask_context_to_sid(PyObject *self, PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
xc_interface *xc_handle;
|
||||
char *ctx;
|
||||
char *buf;
|
||||
uint32_t len;
|
||||
uint32_t sid;
|
||||
int ret;
|
||||
|
||||
static char *kwd_list[] = { "context", NULL };
|
||||
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list,
|
||||
&ctx) )
|
||||
return NULL;
|
||||
|
||||
len = strlen(ctx);
|
||||
|
||||
buf = malloc(len);
|
||||
if (!buf) {
|
||||
errno = -ENOMEM;
|
||||
PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
memcpy(buf, ctx, len);
|
||||
|
||||
xc_handle = xc_interface_open(0,0,0);
|
||||
if (!xc_handle) {
|
||||
free(buf);
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
ret = xc_flask_context_to_sid(xc_handle, buf, len, &sid);
|
||||
|
||||
xc_interface_close(xc_handle);
|
||||
|
||||
free(buf);
|
||||
|
||||
if ( ret != 0 ) {
|
||||
errno = -ret;
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
return PyInt_FromLong(sid);
|
||||
}
|
||||
|
||||
static PyObject *pyflask_sid_to_context(PyObject *self, PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
xc_interface *xc_handle;
|
||||
uint32_t sid;
|
||||
char ctx[CTX_LEN];
|
||||
uint32_t ctx_len = CTX_LEN;
|
||||
int ret;
|
||||
|
||||
static char *kwd_list[] = { "sid", NULL };
|
||||
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
|
||||
&sid) )
|
||||
return NULL;
|
||||
|
||||
xc_handle = xc_interface_open(0,0,0);
|
||||
if (!xc_handle) {
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
ret = xc_flask_sid_to_context(xc_handle, sid, ctx, ctx_len);
|
||||
|
||||
xc_interface_close(xc_handle);
|
||||
|
||||
if ( ret != 0 ) {
|
||||
errno = -ret;
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
return Py_BuildValue("s", ctx, ctx_len);
|
||||
}
|
||||
|
||||
static PyObject *pyflask_load(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
xc_interface *xc_handle;
|
||||
char *policy;
|
||||
uint32_t len;
|
||||
int ret;
|
||||
|
||||
static char *kwd_list[] = { "policy", NULL };
|
||||
|
||||
if( !PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwd_list, &policy, &len) )
|
||||
return NULL;
|
||||
|
||||
xc_handle = xc_interface_open(0,0,0);
|
||||
if (!xc_handle) {
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
ret = xc_flask_load(xc_handle, policy, len);
|
||||
|
||||
xc_interface_close(xc_handle);
|
||||
|
||||
if ( ret != 0 ) {
|
||||
errno = -ret;
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
return Py_BuildValue("i", ret);
|
||||
}
|
||||
|
||||
static PyObject *pyflask_getenforce(PyObject *self)
|
||||
{
|
||||
xc_interface *xc_handle;
|
||||
int ret;
|
||||
|
||||
xc_handle = xc_interface_open(0,0,0);
|
||||
if (!xc_handle) {
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
ret = xc_flask_getenforce(xc_handle);
|
||||
|
||||
xc_interface_close(xc_handle);
|
||||
|
||||
if ( ret < 0 ) {
|
||||
errno = -ret;
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
return Py_BuildValue("i", ret);
|
||||
}
|
||||
|
||||
static PyObject *pyflask_setenforce(PyObject *self, PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
xc_interface *xc_handle;
|
||||
int mode;
|
||||
int ret;
|
||||
|
||||
static char *kwd_list[] = { "mode", NULL };
|
||||
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
|
||||
&mode) )
|
||||
return NULL;
|
||||
|
||||
xc_handle = xc_interface_open(0,0,0);
|
||||
if (!xc_handle) {
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
ret = xc_flask_setenforce(xc_handle, mode);
|
||||
|
||||
xc_interface_close(xc_handle);
|
||||
|
||||
if ( ret != 0 ) {
|
||||
errno = -ret;
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
return Py_BuildValue("i", ret);
|
||||
}
|
||||
|
||||
static PyObject *pyflask_access(PyObject *self, PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
xc_interface *xc_handle;
|
||||
char *tcon, *scon;
|
||||
uint16_t tclass;
|
||||
uint32_t req, allowed, decided, auditallow, auditdeny, seqno;
|
||||
int ret;
|
||||
|
||||
static char *kwd_list[] = { "src_context", "tar_context",
|
||||
"tar_class", "req_permissions",
|
||||
"decided", "auditallow","auditdeny",
|
||||
"seqno", NULL };
|
||||
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ssil|llll", kwd_list,
|
||||
&scon, &tcon, &tclass, &req, &decided,
|
||||
&auditallow, &auditdeny, &seqno) )
|
||||
return NULL;
|
||||
|
||||
xc_handle = xc_interface_open(0,0,0);
|
||||
if (!xc_handle) {
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
ret = xc_flask_access(xc_handle, scon, tcon, tclass, req, &allowed, &decided,
|
||||
&auditallow, &auditdeny, &seqno);
|
||||
|
||||
xc_interface_close(xc_handle);
|
||||
|
||||
if ( ret != 0 ) {
|
||||
errno = -ret;
|
||||
return PyErr_SetFromErrno(xc_error_obj);
|
||||
}
|
||||
|
||||
return Py_BuildValue("i",ret);
|
||||
}
|
||||
|
||||
static PyMethodDef pyflask_methods[] = {
|
||||
{ "flask_context_to_sid",
|
||||
(PyCFunction)pyflask_context_to_sid,
|
||||
METH_KEYWORDS, "\n"
|
||||
"Convert a context string to a dynamic SID.\n"
|
||||
" context [str]: String specifying context to be converted\n"
|
||||
"Returns: [int]: Numeric SID on success; -1 on error.\n" },
|
||||
|
||||
{ "flask_sid_to_context",
|
||||
(PyCFunction)pyflask_sid_to_context,
|
||||
METH_KEYWORDS, "\n"
|
||||
"Convert a dynamic SID to context string.\n"
|
||||
" context [int]: SID to be converted\n"
|
||||
"Returns: [str]: Numeric SID on success; -1 on error.\n" },
|
||||
|
||||
{ "flask_load",
|
||||
(PyCFunction)pyflask_load,
|
||||
METH_KEYWORDS, "\n"
|
||||
"Loads a policy into the hypervisor.\n"
|
||||
" policy [str]: policy to be load\n"
|
||||
"Returns: [int]: 0 on success; -1 on failure.\n" },
|
||||
|
||||
{ "flask_getenforce",
|
||||
(PyCFunction)pyflask_getenforce,
|
||||
METH_NOARGS, "\n"
|
||||
"Returns the current mode of the Flask XSM module.\n"
|
||||
"Returns: [int]: 0 for permissive; 1 for enforcing; -1 on failure.\n" },
|
||||
|
||||
{ "flask_setenforce",
|
||||
(PyCFunction)pyflask_setenforce,
|
||||
METH_KEYWORDS, "\n"
|
||||
"Modifies the current mode for the Flask XSM module.\n"
|
||||
" mode [int]: mode to change to\n"
|
||||
"Returns: [int]: 0 on success; -1 on failure.\n" },
|
||||
|
||||
{ "flask_access",
|
||||
(PyCFunction)pyflask_access,
|
||||
METH_KEYWORDS, "\n"
|
||||
"Returns whether a source context has access to target context based on \
|
||||
class and permissions requested.\n"
|
||||
" scon [str]: source context\n"
|
||||
" tcon [str]: target context\n"
|
||||
" tclass [int]: target security class\n"
|
||||
" req [int] requested permissions\n"
|
||||
" allowed [int] permissions allow for the target class between the source \
|
||||
and target context\n"
|
||||
" decided [int] the permissions that were returned in the allowed \
|
||||
parameter\n"
|
||||
" auditallow [int] permissions set to audit on allow\n"
|
||||
" auditdeny [int] permissions set to audit on deny\n"
|
||||
" seqno [int] not used\n"
|
||||
"Returns: [int]: 0 on all permission granted; -1 if any permissions are \
|
||||
denied\n" },
|
||||
{ NULL, NULL, 0, NULL }
|
||||
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC initflask(void)
|
||||
{
|
||||
Py_InitModule("flask", pyflask_methods);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
*/
|
||||
@@ -1,585 +0,0 @@
|
||||
/*
|
||||
* libnetlink.c RTnetlink service routines.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <fcntl.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "libnetlink.h"
|
||||
|
||||
void rtnl_close(struct rtnl_handle *rth)
|
||||
{
|
||||
close(rth->fd);
|
||||
}
|
||||
|
||||
int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions,
|
||||
int protocol)
|
||||
{
|
||||
socklen_t addr_len;
|
||||
int sndbuf = 32768;
|
||||
int rcvbuf = 32768;
|
||||
|
||||
memset(rth, 0, sizeof(*rth));
|
||||
|
||||
rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
|
||||
if (rth->fd < 0) {
|
||||
perror("Cannot open netlink socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) {
|
||||
perror("SO_SNDBUF");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) {
|
||||
perror("SO_RCVBUF");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&rth->local, 0, sizeof(rth->local));
|
||||
rth->local.nl_family = AF_NETLINK;
|
||||
rth->local.nl_groups = subscriptions;
|
||||
|
||||
if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
|
||||
perror("Cannot bind netlink socket");
|
||||
return -1;
|
||||
}
|
||||
addr_len = sizeof(rth->local);
|
||||
if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
|
||||
perror("Cannot getsockname");
|
||||
return -1;
|
||||
}
|
||||
if (addr_len != sizeof(rth->local)) {
|
||||
fprintf(stderr, "Wrong address length %d\n", addr_len);
|
||||
return -1;
|
||||
}
|
||||
if (rth->local.nl_family != AF_NETLINK) {
|
||||
fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family);
|
||||
return -1;
|
||||
}
|
||||
rth->seq = time(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
|
||||
{
|
||||
return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE);
|
||||
}
|
||||
|
||||
int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr nlh;
|
||||
struct rtgenmsg g;
|
||||
} req;
|
||||
struct sockaddr_nl nladdr;
|
||||
|
||||
memset(&nladdr, 0, sizeof(nladdr));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.nlh.nlmsg_len = sizeof(req);
|
||||
req.nlh.nlmsg_type = type;
|
||||
req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
|
||||
req.nlh.nlmsg_pid = 0;
|
||||
req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
|
||||
req.g.rtgen_family = family;
|
||||
|
||||
return sendto(rth->fd, (void*)&req, sizeof(req), 0,
|
||||
(struct sockaddr*)&nladdr, sizeof(nladdr));
|
||||
}
|
||||
|
||||
int rtnl_send(struct rtnl_handle *rth, const char *buf, int len)
|
||||
{
|
||||
struct sockaddr_nl nladdr;
|
||||
|
||||
memset(&nladdr, 0, sizeof(nladdr));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
|
||||
return sendto(rth->fd, buf, len, 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
|
||||
}
|
||||
|
||||
int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
|
||||
{
|
||||
struct nlmsghdr nlh;
|
||||
struct sockaddr_nl nladdr;
|
||||
struct iovec iov[2] = {
|
||||
{ .iov_base = &nlh, .iov_len = sizeof(nlh) },
|
||||
{ .iov_base = req, .iov_len = len }
|
||||
};
|
||||
struct msghdr msg = {
|
||||
.msg_name = &nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = iov,
|
||||
.msg_iovlen = 2,
|
||||
};
|
||||
|
||||
memset(&nladdr, 0, sizeof(nladdr));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
|
||||
nlh.nlmsg_len = NLMSG_LENGTH(len);
|
||||
nlh.nlmsg_type = type;
|
||||
nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
|
||||
nlh.nlmsg_pid = 0;
|
||||
nlh.nlmsg_seq = rth->dump = ++rth->seq;
|
||||
|
||||
return sendmsg(rth->fd, &msg, 0);
|
||||
}
|
||||
|
||||
int rtnl_dump_filter(struct rtnl_handle *rth,
|
||||
rtnl_filter_t filter,
|
||||
void *arg1,
|
||||
rtnl_filter_t junk,
|
||||
void *arg2)
|
||||
{
|
||||
struct sockaddr_nl nladdr;
|
||||
struct iovec iov;
|
||||
struct msghdr msg = {
|
||||
.msg_name = &nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
char buf[16384];
|
||||
|
||||
iov.iov_base = buf;
|
||||
while (1) {
|
||||
int status;
|
||||
struct nlmsghdr *h;
|
||||
|
||||
iov.iov_len = sizeof(buf);
|
||||
status = recvmsg(rth->fd, &msg, 0);
|
||||
|
||||
if (status < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
perror("OVERRUN");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
fprintf(stderr, "EOF on netlink\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
h = (struct nlmsghdr*)buf;
|
||||
while (NLMSG_OK(h, status)) {
|
||||
int err;
|
||||
|
||||
if (nladdr.nl_pid != 0 ||
|
||||
h->nlmsg_pid != rth->local.nl_pid ||
|
||||
h->nlmsg_seq != rth->dump) {
|
||||
if (junk) {
|
||||
err = junk(&nladdr, h, arg2);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
goto skip_it;
|
||||
}
|
||||
|
||||
if (h->nlmsg_type == NLMSG_DONE)
|
||||
return 0;
|
||||
if (h->nlmsg_type == NLMSG_ERROR) {
|
||||
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
|
||||
if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
|
||||
fprintf(stderr, "ERROR truncated\n");
|
||||
} else {
|
||||
errno = -err->error;
|
||||
perror("RTNETLINK answers");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
err = filter(&nladdr, h, arg1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
skip_it:
|
||||
h = NLMSG_NEXT(h, status);
|
||||
}
|
||||
if (msg.msg_flags & MSG_TRUNC) {
|
||||
fprintf(stderr, "Message truncated\n");
|
||||
continue;
|
||||
}
|
||||
if (status) {
|
||||
fprintf(stderr, "!!!Remnant of size %d\n", status);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
|
||||
unsigned groups, struct nlmsghdr *answer,
|
||||
rtnl_filter_t junk,
|
||||
void *jarg)
|
||||
{
|
||||
int status;
|
||||
unsigned seq;
|
||||
struct nlmsghdr *h;
|
||||
struct sockaddr_nl nladdr;
|
||||
struct iovec iov = {
|
||||
.iov_base = (void*) n,
|
||||
.iov_len = n->nlmsg_len
|
||||
};
|
||||
struct msghdr msg = {
|
||||
.msg_name = &nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
char buf[16384];
|
||||
|
||||
memset(&nladdr, 0, sizeof(nladdr));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
nladdr.nl_pid = peer;
|
||||
nladdr.nl_groups = groups;
|
||||
|
||||
n->nlmsg_seq = seq = ++rtnl->seq;
|
||||
|
||||
if (answer == NULL)
|
||||
n->nlmsg_flags |= NLM_F_ACK;
|
||||
|
||||
status = sendmsg(rtnl->fd, &msg, 0);
|
||||
|
||||
if (status < 0) {
|
||||
perror("Cannot talk to rtnetlink");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buf,0,sizeof(buf));
|
||||
|
||||
iov.iov_base = buf;
|
||||
|
||||
while (1) {
|
||||
iov.iov_len = sizeof(buf);
|
||||
status = recvmsg(rtnl->fd, &msg, 0);
|
||||
|
||||
if (status < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
perror("OVERRUN");
|
||||
continue;
|
||||
}
|
||||
if (status == 0) {
|
||||
fprintf(stderr, "EOF on netlink\n");
|
||||
return -1;
|
||||
}
|
||||
if (msg.msg_namelen != sizeof(nladdr)) {
|
||||
fprintf(stderr, "sender address length == %d\n", msg.msg_namelen);
|
||||
exit(1);
|
||||
}
|
||||
for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
|
||||
int err;
|
||||
int len = h->nlmsg_len;
|
||||
int l = len - sizeof(*h);
|
||||
|
||||
if (l<0 || len>status) {
|
||||
if (msg.msg_flags & MSG_TRUNC) {
|
||||
fprintf(stderr, "Truncated message\n");
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "!!!malformed message: len=%d\n", len);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (nladdr.nl_pid != peer ||
|
||||
h->nlmsg_pid != rtnl->local.nl_pid ||
|
||||
h->nlmsg_seq != seq) {
|
||||
if (junk) {
|
||||
err = junk(&nladdr, h, jarg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (h->nlmsg_type == NLMSG_ERROR) {
|
||||
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
|
||||
if (l < sizeof(struct nlmsgerr)) {
|
||||
fprintf(stderr, "ERROR truncated\n");
|
||||
} else {
|
||||
errno = -err->error;
|
||||
if (errno == 0) {
|
||||
if (answer)
|
||||
memcpy(answer, h, h->nlmsg_len);
|
||||
return 0;
|
||||
}
|
||||
perror("RTNETLINK answers");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (answer) {
|
||||
memcpy(answer, h, h->nlmsg_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Unexpected reply!!!\n");
|
||||
|
||||
status -= NLMSG_ALIGN(len);
|
||||
h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
|
||||
}
|
||||
if (msg.msg_flags & MSG_TRUNC) {
|
||||
fprintf(stderr, "Message truncated\n");
|
||||
continue;
|
||||
}
|
||||
if (status) {
|
||||
fprintf(stderr, "!!!Remnant of size %d\n", status);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rtnl_listen(struct rtnl_handle *rtnl,
|
||||
rtnl_filter_t handler,
|
||||
void *jarg)
|
||||
{
|
||||
int status;
|
||||
struct nlmsghdr *h;
|
||||
struct sockaddr_nl nladdr;
|
||||
struct iovec iov;
|
||||
struct msghdr msg = {
|
||||
.msg_name = &nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
char buf[8192];
|
||||
|
||||
memset(&nladdr, 0, sizeof(nladdr));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
nladdr.nl_pid = 0;
|
||||
nladdr.nl_groups = 0;
|
||||
|
||||
iov.iov_base = buf;
|
||||
while (1) {
|
||||
iov.iov_len = sizeof(buf);
|
||||
status = recvmsg(rtnl->fd, &msg, 0);
|
||||
|
||||
if (status < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
perror("OVERRUN");
|
||||
continue;
|
||||
}
|
||||
if (status == 0) {
|
||||
fprintf(stderr, "EOF on netlink\n");
|
||||
return -1;
|
||||
}
|
||||
if (msg.msg_namelen != sizeof(nladdr)) {
|
||||
fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen);
|
||||
exit(1);
|
||||
}
|
||||
for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
|
||||
int err;
|
||||
int len = h->nlmsg_len;
|
||||
int l = len - sizeof(*h);
|
||||
|
||||
if (l<0 || len>status) {
|
||||
if (msg.msg_flags & MSG_TRUNC) {
|
||||
fprintf(stderr, "Truncated message\n");
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "!!!malformed message: len=%d\n", len);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
err = handler(&nladdr, h, jarg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
status -= NLMSG_ALIGN(len);
|
||||
h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
|
||||
}
|
||||
if (msg.msg_flags & MSG_TRUNC) {
|
||||
fprintf(stderr, "Message truncated\n");
|
||||
continue;
|
||||
}
|
||||
if (status) {
|
||||
fprintf(stderr, "!!!Remnant of size %d\n", status);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler,
|
||||
void *jarg)
|
||||
{
|
||||
int status;
|
||||
struct sockaddr_nl nladdr;
|
||||
char buf[8192];
|
||||
struct nlmsghdr *h = (void*)buf;
|
||||
|
||||
memset(&nladdr, 0, sizeof(nladdr));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
nladdr.nl_pid = 0;
|
||||
nladdr.nl_groups = 0;
|
||||
|
||||
while (1) {
|
||||
int err, len, type;
|
||||
int l;
|
||||
|
||||
status = fread(&buf, 1, sizeof(*h), rtnl);
|
||||
|
||||
if (status < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
perror("rtnl_from_file: fread");
|
||||
return -1;
|
||||
}
|
||||
if (status == 0)
|
||||
return 0;
|
||||
|
||||
len = h->nlmsg_len;
|
||||
type= h->nlmsg_type;
|
||||
l = len - sizeof(*h);
|
||||
|
||||
if (l<0 || len>sizeof(buf)) {
|
||||
fprintf(stderr, "!!!malformed message: len=%d @%lu\n",
|
||||
len, ftell(rtnl));
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl);
|
||||
|
||||
if (status < 0) {
|
||||
perror("rtnl_from_file: fread");
|
||||
return -1;
|
||||
}
|
||||
if (status < l) {
|
||||
fprintf(stderr, "rtnl-from_file: truncated message\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = handler(&nladdr, h, jarg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data)
|
||||
{
|
||||
int len = RTA_LENGTH(4);
|
||||
struct rtattr *rta;
|
||||
if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
|
||||
fprintf(stderr,"addattr32: Error! max allowed bound %d exceeded\n",maxlen);
|
||||
return -1;
|
||||
}
|
||||
rta = NLMSG_TAIL(n);
|
||||
rta->rta_type = type;
|
||||
rta->rta_len = len;
|
||||
memcpy(RTA_DATA(rta), &data, 4);
|
||||
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
||||
int alen)
|
||||
{
|
||||
int len = RTA_LENGTH(alen);
|
||||
struct rtattr *rta;
|
||||
|
||||
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
|
||||
fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen);
|
||||
return -1;
|
||||
}
|
||||
rta = NLMSG_TAIL(n);
|
||||
rta->rta_type = type;
|
||||
rta->rta_len = len;
|
||||
memcpy(RTA_DATA(rta), data, alen);
|
||||
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len)
|
||||
{
|
||||
if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) {
|
||||
fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(NLMSG_TAIL(n), data, len);
|
||||
memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len);
|
||||
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data)
|
||||
{
|
||||
int len = RTA_LENGTH(4);
|
||||
struct rtattr *subrta;
|
||||
|
||||
if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
|
||||
fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen);
|
||||
return -1;
|
||||
}
|
||||
subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
|
||||
subrta->rta_type = type;
|
||||
subrta->rta_len = len;
|
||||
memcpy(RTA_DATA(subrta), &data, 4);
|
||||
rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rta_addattr_l(struct rtattr *rta, int maxlen, int type,
|
||||
const void *data, int alen)
|
||||
{
|
||||
struct rtattr *subrta;
|
||||
int len = RTA_LENGTH(alen);
|
||||
|
||||
if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) {
|
||||
fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen);
|
||||
return -1;
|
||||
}
|
||||
subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
|
||||
subrta->rta_type = type;
|
||||
subrta->rta_len = len;
|
||||
memcpy(RTA_DATA(subrta), data, alen);
|
||||
rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
|
||||
{
|
||||
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
|
||||
while (RTA_OK(rta, len)) {
|
||||
if (rta->rta_type <= max)
|
||||
tb[rta->rta_type] = rta;
|
||||
rta = RTA_NEXT(rta,len);
|
||||
}
|
||||
if (len)
|
||||
fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
memset(tb, 0, sizeof(struct rtattr *) * max);
|
||||
while (RTA_OK(rta, len)) {
|
||||
if (rta->rta_type <= max && i < max)
|
||||
tb[i++] = rta;
|
||||
rta = RTA_NEXT(rta,len);
|
||||
}
|
||||
if (len)
|
||||
fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
|
||||
return i;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
#ifndef __LIBNETLINK_H__
|
||||
#define __LIBNETLINK_H__ 1
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <asm/types.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
struct rtnl_handle
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_nl local;
|
||||
struct sockaddr_nl peer;
|
||||
__u32 seq;
|
||||
__u32 dump;
|
||||
};
|
||||
|
||||
extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions);
|
||||
extern int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, int protocol);
|
||||
extern void rtnl_close(struct rtnl_handle *rth);
|
||||
extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type);
|
||||
extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len);
|
||||
|
||||
typedef int (*rtnl_filter_t)(const struct sockaddr_nl *,
|
||||
struct nlmsghdr *n, void *);
|
||||
extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter,
|
||||
void *arg1,
|
||||
rtnl_filter_t junk,
|
||||
void *arg2);
|
||||
extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
|
||||
unsigned groups, struct nlmsghdr *answer,
|
||||
rtnl_filter_t junk,
|
||||
void *jarg);
|
||||
extern int rtnl_send(struct rtnl_handle *rth, const char *buf, int);
|
||||
|
||||
|
||||
extern int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data);
|
||||
extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen);
|
||||
extern int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len);
|
||||
extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
|
||||
extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen);
|
||||
|
||||
extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
|
||||
extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len);
|
||||
|
||||
#define parse_rtattr_nested(tb, max, rta) \
|
||||
(parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))
|
||||
|
||||
extern int rtnl_listen(struct rtnl_handle *, rtnl_filter_t handler,
|
||||
void *jarg);
|
||||
extern int rtnl_from_file(FILE *, rtnl_filter_t handler,
|
||||
void *jarg);
|
||||
|
||||
#define NLMSG_TAIL(nmsg) \
|
||||
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
||||
|
||||
#endif /* __LIBNETLINK_H__ */
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
/* python binding to libnetlink */
|
||||
|
||||
#include <Python.h>
|
||||
#include "libnetlink.h"
|
||||
|
||||
#define PKG "xen.lowlevel.netlink"
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
int opened;
|
||||
struct rtnl_handle rth;
|
||||
} PyRtnlObject;
|
||||
|
||||
/* todo: subscriptions? */
|
||||
static PyObject* PyRtnl_new(PyTypeObject* type, PyObject* args,
|
||||
PyObject* kwargs)
|
||||
{
|
||||
return type->tp_alloc(type, 0);
|
||||
}
|
||||
|
||||
static int PyRtnl_init(PyObject* obj, PyObject* args, PyObject* kwargs)
|
||||
{
|
||||
PyRtnlObject* self = (PyRtnlObject*)obj;
|
||||
|
||||
if (rtnl_open(&self->rth, 0) < 0) {
|
||||
PyErr_SetString(PyExc_IOError, "could not open rtnl handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void PyRtnl_dealloc(PyRtnlObject* obj)
|
||||
{
|
||||
PyRtnlObject* self = (PyRtnlObject*)obj;
|
||||
|
||||
rtnl_close(&self->rth);
|
||||
}
|
||||
|
||||
static PyObject* pyrtnl_talk(PyObject* obj, PyObject* args)
|
||||
{
|
||||
PyRtnlObject* self = (PyRtnlObject*)obj;
|
||||
char* msg;
|
||||
int len;
|
||||
int peer = 0;
|
||||
int groups = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s#|ii", &msg, &len, &peer, &groups))
|
||||
return NULL;
|
||||
|
||||
if (rtnl_talk(&self->rth, (struct nlmsghdr*)msg, peer, groups, NULL, NULL,
|
||||
NULL) < 0)
|
||||
{
|
||||
PyErr_SetString(PyExc_IOError, "error sending message");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject* pyrtnl_wilddump_request(PyObject* obj, PyObject* args)
|
||||
{
|
||||
PyRtnlObject* self = (PyRtnlObject*)obj;
|
||||
int family, type;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii", &family, &type))
|
||||
return NULL;
|
||||
|
||||
if (rtnl_wilddump_request(&self->rth, family, type) < 0) {
|
||||
PyErr_SetString(PyExc_IOError, "could not send dump request");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject* pyrtnl_dump_request(PyObject* obj, PyObject* args)
|
||||
{
|
||||
PyRtnlObject* self = (PyRtnlObject*)obj;
|
||||
int type;
|
||||
char* req;
|
||||
int len;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "is#", &type, &req, &len))
|
||||
return NULL;
|
||||
|
||||
if (rtnl_dump_request(&self->rth, type, req, len) < 0) {
|
||||
PyErr_SetString(PyExc_IOError, "could not send dump request");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
/* translate args to python and call python callback */
|
||||
static int dump_filter_helper(const struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
PyObject* filter = arg;
|
||||
PyObject* args;
|
||||
PyObject* result;
|
||||
|
||||
args = Py_BuildValue("s#s#", who, sizeof(*who), n, n->nlmsg_len);
|
||||
result = PyObject_CallObject(filter, args);
|
||||
Py_DECREF(args);
|
||||
if (!result)
|
||||
return -1;
|
||||
|
||||
/* result is ignored as long as an exception isn't raised */
|
||||
Py_DECREF(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject* pyrtnl_dump_filter(PyObject* obj, PyObject* args)
|
||||
{
|
||||
PyRtnlObject* self = (PyRtnlObject*)obj;
|
||||
PyObject *filter;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O:dump_filter", &filter))
|
||||
return NULL;
|
||||
|
||||
if (!PyCallable_Check(filter)) {
|
||||
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(filter);
|
||||
if (rtnl_dump_filter(&self->rth, dump_filter_helper, filter, NULL,
|
||||
NULL) < 0)
|
||||
{
|
||||
Py_DECREF(filter);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(filter);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyMethodDef PyRtnl_methods[] = {
|
||||
{ "talk", pyrtnl_talk, METH_VARARGS,
|
||||
"send a message to rtnetlink and receive a response.\n" },
|
||||
{ "wilddump_request", pyrtnl_wilddump_request, METH_VARARGS,
|
||||
"dump objects.\n" },
|
||||
{ "dump_request", pyrtnl_dump_request, METH_VARARGS,
|
||||
"start a dump of a particular netlink type.\n" },
|
||||
{ "dump_filter", pyrtnl_dump_filter, METH_VARARGS,
|
||||
"iterate over an rtnl dump.\n" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static PyTypeObject PyRtnlType = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
PKG ".rtnl", /* tp_name */
|
||||
sizeof(PyRtnlObject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)PyRtnl_dealloc, /* tp_dealloc */
|
||||
NULL, /* tp_print */
|
||||
NULL, /* tp_getattr */
|
||||
NULL, /* tp_setattr */
|
||||
NULL, /* tp_compare */
|
||||
NULL, /* tp_repr */
|
||||
NULL, /* tp_as_number */
|
||||
NULL, /* tp_as_sequence */
|
||||
NULL, /* tp_as_mapping */
|
||||
NULL, /* tp_hash */
|
||||
NULL, /* tp_call */
|
||||
NULL, /* tp_str */
|
||||
NULL, /* tp_getattro */
|
||||
NULL, /* tp_setattro */
|
||||
NULL, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
"rtnetlink handle", /* tp_doc */
|
||||
NULL, /* tp_traverse */
|
||||
NULL, /* tp_clear */
|
||||
NULL, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
NULL, /* tp_iter */
|
||||
NULL, /* tp_iternext */
|
||||
PyRtnl_methods, /* tp_methods */
|
||||
NULL, /* tp_members */
|
||||
NULL, /* tp_getset */
|
||||
NULL, /* tp_base */
|
||||
NULL, /* tp_dict */
|
||||
NULL, /* tp_descr_get */
|
||||
NULL, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
PyRtnl_init, /* tp_init */
|
||||
NULL, /* tp_alloc */
|
||||
PyRtnl_new, /* tp_new */
|
||||
};
|
||||
|
||||
static PyMethodDef methods[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static char doc[] = "libnetlink wrapper";
|
||||
|
||||
PyMODINIT_FUNC initnetlink(void)
|
||||
{
|
||||
PyObject *mod;
|
||||
|
||||
if (PyType_Ready(&PyRtnlType) == -1)
|
||||
return;
|
||||
|
||||
if (!(mod = Py_InitModule3(PKG, methods, doc)))
|
||||
return;
|
||||
|
||||
Py_INCREF(&PyRtnlType);
|
||||
PyModule_AddObject(mod, "rtnl", (PyObject *)&PyRtnlType);
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include <libcontract.h>
|
||||
#include <sys/contract/process.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* On Solaris, xend runs under a contract as an smf(5) service. As a
|
||||
* result, when spawning long-running children such as a domain's
|
||||
* qemu-dm instantiation, we have to make sure it's in a separate
|
||||
* contract. Before we fork, we must activate a separate process
|
||||
* contract template to place the child processes in a new contract.
|
||||
*/
|
||||
|
||||
static PyObject *
|
||||
pyprocess_activate(PyObject *o, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "name", NULL };
|
||||
char *name = NULL;
|
||||
int flags;
|
||||
int cfd;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &name))
|
||||
return (NULL);
|
||||
|
||||
cfd = open64("/system/contract/process/template", O_RDWR);
|
||||
|
||||
if (cfd == -1)
|
||||
goto err;
|
||||
|
||||
if ((flags = fcntl(cfd, F_GETFD, 0)) == -1)
|
||||
goto err;
|
||||
|
||||
if (fcntl(cfd, F_SETFD, flags | FD_CLOEXEC) == -1)
|
||||
goto err;
|
||||
|
||||
if (name != NULL)
|
||||
ct_pr_tmpl_set_svc_aux(cfd, name);
|
||||
|
||||
if (ct_tmpl_activate(cfd))
|
||||
goto err;
|
||||
|
||||
return (PyInt_FromLong((long)cfd));
|
||||
|
||||
err:
|
||||
if (cfd != -1)
|
||||
close(cfd);
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyprocess_clear(PyObject *o, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "contract", NULL };
|
||||
int cfd;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &cfd))
|
||||
return (NULL);
|
||||
|
||||
if (ct_tmpl_clear(cfd) != 0) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
close(cfd);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyprocess_abandon_latest(PyObject *o, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { NULL };
|
||||
static char path[PATH_MAX];
|
||||
ct_stathdl_t st;
|
||||
ctid_t latest;
|
||||
int cfd;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
|
||||
return (NULL);
|
||||
|
||||
cfd = open64("/system/contract/process/latest", O_RDONLY);
|
||||
if (cfd == -1)
|
||||
goto err;
|
||||
|
||||
ct_status_read(cfd, CTD_COMMON, &st);
|
||||
latest = ct_status_get_id(st);
|
||||
ct_status_free(st);
|
||||
close(cfd);
|
||||
|
||||
snprintf(path, PATH_MAX, "/system/contract/process/%ld/ctl",
|
||||
(long)latest);
|
||||
|
||||
if ((cfd = open64(path, O_WRONLY)) < 0)
|
||||
goto err;
|
||||
if (ct_ctl_abandon(cfd))
|
||||
goto err;
|
||||
close(cfd);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
err:
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(pyprocess_activate__doc__,
|
||||
"activate(name)\n"
|
||||
"\n"
|
||||
"Activate a new process contract template. If name is given,\n"
|
||||
"it is used as the template's auxiliary value.\n"
|
||||
"Returns the new contract template.\n");
|
||||
|
||||
PyDoc_STRVAR(pyprocess_clear__doc__,
|
||||
"clear(contract)\n"
|
||||
"\n"
|
||||
"Clear and close the given contract template.\n");
|
||||
|
||||
PyDoc_STRVAR(pyprocess_abandon_latest__doc__,
|
||||
"abandon_latest()\n"
|
||||
"\n"
|
||||
"Abandon the latest contract created by this thread.\n");
|
||||
|
||||
static struct PyMethodDef pyprocess_module_methods[] = {
|
||||
{ "activate", (PyCFunction) pyprocess_activate,
|
||||
METH_VARARGS|METH_KEYWORDS, pyprocess_activate__doc__ },
|
||||
{ "clear", (PyCFunction) pyprocess_clear,
|
||||
METH_VARARGS|METH_KEYWORDS, pyprocess_clear__doc__ },
|
||||
{ "abandon_latest", (PyCFunction) pyprocess_abandon_latest,
|
||||
METH_VARARGS|METH_KEYWORDS, pyprocess_abandon_latest__doc__ },
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initprocess(void)
|
||||
{
|
||||
Py_InitModule("process", pyprocess_module_methods);
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include <libscf.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define XEND_FMRI "svc:/system/xvm/xend:default"
|
||||
#define XEND_PG "config"
|
||||
|
||||
static PyObject *scf_exc;
|
||||
|
||||
static void *
|
||||
scf_exception(const char *err, const char *value)
|
||||
{
|
||||
int scferr = scf_error();
|
||||
const char *scfstrerr = scf_strerror(scferr);
|
||||
PyObject *obj = Py_BuildValue("(isss)", scferr, err, scfstrerr, value);
|
||||
PyErr_SetObject(scf_exc, obj);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyscf_get_bool(PyObject *o, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "name", NULL };
|
||||
scf_simple_prop_t *prop;
|
||||
uint8_t *val;
|
||||
char *name;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
|
||||
return (NULL);
|
||||
|
||||
prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
|
||||
|
||||
if (prop == NULL)
|
||||
return (scf_exception("scf_simple_prop_get() failed", name));
|
||||
|
||||
if ((val = scf_simple_prop_next_boolean(prop)) == NULL)
|
||||
return (scf_exception("scf_simple_prop_next_boolean() failed",
|
||||
name));
|
||||
|
||||
if (*val) {
|
||||
scf_simple_prop_free(prop);
|
||||
Py_INCREF(Py_True);
|
||||
return (Py_True);
|
||||
}
|
||||
|
||||
scf_simple_prop_free(prop);
|
||||
Py_INCREF(Py_False);
|
||||
return (Py_False);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyscf_get_int(PyObject *o, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "name", NULL };
|
||||
scf_simple_prop_t *prop;
|
||||
PyObject *obj;
|
||||
int64_t *val;
|
||||
char *name;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
|
||||
return (NULL);
|
||||
|
||||
prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
|
||||
|
||||
if (prop == NULL)
|
||||
return (scf_exception("scf_simple_prop_get() failed", name));
|
||||
|
||||
if ((val = scf_simple_prop_next_integer(prop)) == NULL)
|
||||
return (scf_exception("scf_simple_prop_next_integer() failed",
|
||||
name));
|
||||
|
||||
obj = PyInt_FromLong((long)*val);
|
||||
scf_simple_prop_free(prop);
|
||||
return (obj);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyscf_get_string(PyObject *o, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "name", NULL };
|
||||
scf_simple_prop_t *prop;
|
||||
PyObject *obj;
|
||||
char *name;
|
||||
char *str;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
|
||||
return (NULL);
|
||||
|
||||
prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
|
||||
|
||||
if (prop == NULL)
|
||||
return (scf_exception("scf_simple_prop_get() failed", name));
|
||||
|
||||
if ((str = scf_simple_prop_next_astring(prop)) == NULL) {
|
||||
scf_simple_prop_free(prop);
|
||||
return (scf_exception("scf_simple_prop_next_astring() failed",
|
||||
name));
|
||||
}
|
||||
|
||||
obj = PyString_FromString(str);
|
||||
scf_simple_prop_free(prop);
|
||||
return (obj);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(pyscf_get_bool__doc__,
|
||||
"get_bool(name) - get the value of the named boolean property");
|
||||
PyDoc_STRVAR(pyscf_get_int__doc__,
|
||||
"get_int(name) - get the value of the named integer property");
|
||||
PyDoc_STRVAR(pyscf_get_string__doc__,
|
||||
"get_string(name) - get the value of the named string property");
|
||||
|
||||
static struct PyMethodDef pyscf_module_methods[] = {
|
||||
{ "get_bool", (PyCFunction) pyscf_get_bool,
|
||||
METH_VARARGS|METH_KEYWORDS, pyscf_get_bool__doc__ },
|
||||
{ "get_int", (PyCFunction) pyscf_get_int,
|
||||
METH_VARARGS|METH_KEYWORDS, pyscf_get_int__doc__ },
|
||||
{ "get_string", (PyCFunction) pyscf_get_string,
|
||||
METH_VARARGS|METH_KEYWORDS, pyscf_get_string__doc__ },
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initscf(void)
|
||||
{
|
||||
PyObject *m;
|
||||
m = Py_InitModule("scf", pyscf_module_methods);
|
||||
|
||||
scf_exc = PyErr_NewException("scf.error", NULL, NULL);
|
||||
Py_INCREF(scf_exc);
|
||||
PyModule_AddObject(m, "error", scf_exc);
|
||||
PyModule_AddIntConstant(m, "SCF_ERROR_NOT_FOUND", SCF_ERROR_NOT_FOUND);
|
||||
}
|
||||
Whitespace-only changes.
@@ -1,31 +0,0 @@
|
||||
handlers = []
|
||||
|
||||
class BlkDevException(Exception): pass
|
||||
|
||||
class BlkDev(object):
|
||||
"Object representing a VM block device"
|
||||
def __init__(self, **props):
|
||||
self.uname = ''
|
||||
if 'dev' not in props:
|
||||
raise BlkDevException('no device')
|
||||
#if 'uname' not in props:
|
||||
#raise BlkDevException('no uname')
|
||||
if 'mode' not in props:
|
||||
raise BlkDevException('no mode')
|
||||
self.__dict__.update(props)
|
||||
self.dev = props['dev'].rstrip(':disk')
|
||||
|
||||
def __str__(self):
|
||||
return '%s,%s,%s' % (self.uname, self.dev, self.mode)
|
||||
|
||||
def register(handler):
|
||||
"register a block device class with parser"
|
||||
if handler not in handlers:
|
||||
handlers.insert(0, handler)
|
||||
|
||||
def parse(props):
|
||||
"turn a vm device dictionary into a blkdev object"
|
||||
for handler in handlers:
|
||||
if handler.handles(**props):
|
||||
return handler(**props)
|
||||
return BlkDev(**props)
|
||||
@@ -1,397 +0,0 @@
|
||||
# Remus device interface
|
||||
#
|
||||
# Coordinates with devices at suspend, resume, and commit hooks
|
||||
|
||||
import os, re, fcntl
|
||||
|
||||
import netlink, qdisc, util
|
||||
|
||||
class ReplicatedDiskException(Exception): pass
|
||||
class BufferedNICException(Exception): pass
|
||||
|
||||
class CheckpointedDevice(object):
|
||||
'Base class for buffered devices'
|
||||
|
||||
def postsuspend(self):
|
||||
'called after guest has suspended'
|
||||
pass
|
||||
|
||||
def preresume(self):
|
||||
'called before guest resumes'
|
||||
pass
|
||||
|
||||
def commit(self):
|
||||
'called when backup has acknowledged checkpoint reception'
|
||||
pass
|
||||
|
||||
class ReplicatedDisk(CheckpointedDevice):
|
||||
"""
|
||||
Send a checkpoint message to a replicated disk while the domain
|
||||
is paused between epochs.
|
||||
"""
|
||||
FIFODIR = '/var/run/tap'
|
||||
SEND_CHECKPOINT = 20
|
||||
WAIT_CHECKPOINT_ACK = 30
|
||||
|
||||
def __init__(self, disk):
|
||||
# look up disk, make sure it is tap:buffer, and set up socket
|
||||
# to request commits.
|
||||
self.ctlfd = None
|
||||
self.msgfd = None
|
||||
self.is_drbd = False
|
||||
self.ackwait = False
|
||||
|
||||
if disk.uname.startswith('tap:remus:') or disk.uname.startswith('tap:tapdisk:remus:'):
|
||||
fifo = re.match("tap:.*(remus.*)\|", disk.uname).group(1).replace(':', '_')
|
||||
absfifo = os.path.join(self.FIFODIR, fifo)
|
||||
absmsgfifo = absfifo + '.msg'
|
||||
|
||||
self.installed = False
|
||||
self.ctlfd = open(absfifo, 'w+b')
|
||||
self.msgfd = open(absmsgfifo, 'r+b')
|
||||
elif disk.uname.startswith('drbd:'):
|
||||
#get the drbd device associated with this resource
|
||||
drbdres = re.match("drbd:(.*)", disk.uname).group(1)
|
||||
drbddev = util.runcmd("drbdadm sh-dev %s" % drbdres).rstrip()
|
||||
|
||||
#check for remus supported drbd installation
|
||||
rconf = util.runcmd("drbdsetup %s show" % drbddev)
|
||||
if rconf.find('protocol D;') == -1:
|
||||
raise ReplicatedDiskException('Remus support for DRBD disks requires the '
|
||||
'resources to operate in protocol D. Please make '
|
||||
'sure that you have installed the remus supported DRBD '
|
||||
'version from git://aramis.nss.cs.ubc.ca/drbd-8.3-remus '
|
||||
'and enabled protocol D in the resource config')
|
||||
|
||||
#check if resource is in connected state
|
||||
cstate = util.runcmd("drbdadm cstate %s" % drbdres).rstrip()
|
||||
if cstate != 'Connected':
|
||||
raise ReplicatedDiskException('DRBD resource %s is not in connected state!'
|
||||
% drbdres)
|
||||
|
||||
#open a handle to the resource so that we could issue chkpt ioctls
|
||||
self.ctlfd = open(drbddev, 'r')
|
||||
self.is_drbd = True
|
||||
else:
|
||||
raise ReplicatedDiskException('Disk is not replicated: %s' %
|
||||
str(disk))
|
||||
|
||||
def __del__(self):
|
||||
self.uninstall()
|
||||
|
||||
def uninstall(self):
|
||||
if self.ctlfd:
|
||||
self.ctlfd.close()
|
||||
self.ctlfd = None
|
||||
|
||||
def postsuspend(self):
|
||||
if not self.is_drbd:
|
||||
os.write(self.ctlfd.fileno(), 'flush')
|
||||
elif not self.ackwait:
|
||||
if (fcntl.ioctl(self.ctlfd.fileno(), self.SEND_CHECKPOINT, 0) > 0):
|
||||
self.ackwait = False
|
||||
else:
|
||||
self.ackwait = True
|
||||
|
||||
def preresume(self):
|
||||
if self.is_drbd and self.ackwait:
|
||||
fcntl.ioctl(self.ctlfd.fileno(), self.WAIT_CHECKPOINT_ACK, 0)
|
||||
self.ackwait = False
|
||||
|
||||
def commit(self):
|
||||
if not self.is_drbd:
|
||||
msg = os.read(self.msgfd.fileno(), 4)
|
||||
if msg != 'done':
|
||||
print 'Unknown message: %s' % msg
|
||||
|
||||
### Network
|
||||
|
||||
# shared rtnl handle
|
||||
_rth = None
|
||||
def getrth():
|
||||
global _rth
|
||||
|
||||
if not _rth:
|
||||
_rth = netlink.rtnl()
|
||||
return _rth
|
||||
|
||||
class Netbuf(object):
|
||||
"Proxy for netdev with a queueing discipline"
|
||||
|
||||
@staticmethod
|
||||
def devclass():
|
||||
"returns the name of this device class"
|
||||
return 'unknown'
|
||||
|
||||
@classmethod
|
||||
def available(cls):
|
||||
"returns True if this module can proxy the device"
|
||||
return cls._hasdev(cls.devclass())
|
||||
|
||||
def __init__(self, devname):
|
||||
self.devname = devname
|
||||
self.vif = None
|
||||
|
||||
# override in subclasses
|
||||
def install(self, vif):
|
||||
"set up proxy on device"
|
||||
raise BufferedNICException('unimplemented')
|
||||
|
||||
def uninstall(self):
|
||||
"remove proxy on device"
|
||||
raise BufferedNICException('unimplemented')
|
||||
|
||||
# protected
|
||||
@staticmethod
|
||||
def _hasdev(devclass):
|
||||
"""check for existence of device, attempting to load kernel
|
||||
module if not present"""
|
||||
devname = '%s0' % devclass
|
||||
rth = getrth()
|
||||
|
||||
if rth.getlink(devname):
|
||||
return True
|
||||
if util.modprobe(devclass) and rth.getlink(devname):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
class IFBBuffer(Netbuf):
|
||||
"""Capture packets arriving on a VIF using an ingress filter and tc
|
||||
mirred action to forward them to an IFB device.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def devclass():
|
||||
return 'ifb'
|
||||
|
||||
def install(self, vif):
|
||||
self.vif = vif
|
||||
# voodoo from http://www.linuxfoundation.org/collaborate/workgroups/networking/ifb#Typical_Usage
|
||||
util.runcmd('ip link set %s up' % self.devname)
|
||||
try:
|
||||
util.runcmd('tc qdisc add dev %s ingress' % vif.dev)
|
||||
except util.PipeException, e:
|
||||
# check if error indicates that ingress qdisc
|
||||
# already exists on the vif. If so, ignore it.
|
||||
ignoreme = 'RTNETLINK answers: File exists'
|
||||
if ignoreme in str(e):
|
||||
pass
|
||||
else:
|
||||
raise e
|
||||
util.runcmd('tc filter add dev %s parent ffff: proto ip pref 10 '
|
||||
'u32 match u32 0 0 action mirred egress redirect '
|
||||
'dev %s' % (vif.dev, self.devname))
|
||||
|
||||
def uninstall(self):
|
||||
try:
|
||||
util.runcmd('tc qdisc del dev %s ingress' % self.vif.dev)
|
||||
except util.PipeException, e:
|
||||
pass
|
||||
util.runcmd('ip link set %s down' % self.devname)
|
||||
|
||||
class IMQBuffer(Netbuf):
|
||||
"""Redirect packets coming in on vif to an IMQ device."""
|
||||
|
||||
imqebt = '/usr/lib/xen/bin/imqebt'
|
||||
|
||||
@staticmethod
|
||||
def devclass():
|
||||
return 'imq'
|
||||
|
||||
def install(self, vif):
|
||||
# stopgap hack to set up IMQ for an interface. Wrong in many ways.
|
||||
self.vif = vif
|
||||
|
||||
for mod in ['imq', 'ebt_imq']:
|
||||
util.runcmd(['modprobe', mod])
|
||||
util.runcmd("ip link set %s up" % self.devname)
|
||||
util.runcmd("%s -F FORWARD" % self.imqebt)
|
||||
util.runcmd("%s -A FORWARD -i %s -j imq --todev %s" % (self.imqebt, vif.dev, self.devname))
|
||||
|
||||
def uninstall(self):
|
||||
util.runcmd("%s -F FORWARD" % self.imqebt)
|
||||
util.runcmd('ip link set %s down' % self.devname)
|
||||
|
||||
# in order of desirability
|
||||
netbuftypes = [IFBBuffer, IMQBuffer]
|
||||
|
||||
def selectnetbuf():
|
||||
"Find the best available buffer type"
|
||||
for driver in netbuftypes:
|
||||
if driver.available():
|
||||
return driver
|
||||
|
||||
raise BufferedNICException('no net buffer available')
|
||||
|
||||
class Netbufpool(object):
|
||||
"""Allocates/releases proxy netdevs (IMQ/IFB)
|
||||
|
||||
A file contains a list of entries of the form <pid>:<device>\n
|
||||
To allocate a device, lock the file, then claim a new device if
|
||||
one is free. If there are no free devices, check each PID for liveness
|
||||
and take a device if the PID is dead, otherwise return failure.
|
||||
Add an entry to the file before releasing the lock.
|
||||
"""
|
||||
def __init__(self, netbufclass):
|
||||
"Create a pool of Device"
|
||||
self.netbufclass = netbufclass
|
||||
self.path = '/var/run/remus/' + self.netbufclass.devclass()
|
||||
|
||||
self.devices = self.getdevs()
|
||||
|
||||
pooldir = os.path.dirname(self.path)
|
||||
if not os.path.exists(pooldir):
|
||||
os.makedirs(pooldir, 0755)
|
||||
|
||||
def get(self):
|
||||
"allocate a free device"
|
||||
def getfreedev(table):
|
||||
for dev in self.devices:
|
||||
if dev not in table or not util.checkpid(table[dev]):
|
||||
return dev
|
||||
|
||||
return None
|
||||
|
||||
lock = util.Lock(self.path)
|
||||
table = self.load()
|
||||
|
||||
dev = getfreedev(table)
|
||||
if not dev:
|
||||
lock.unlock()
|
||||
raise BufferedNICException('no free devices')
|
||||
dev = self.netbufclass(dev)
|
||||
|
||||
table[dev.devname] = os.getpid()
|
||||
|
||||
self.save(table)
|
||||
lock.unlock()
|
||||
|
||||
return dev
|
||||
|
||||
def put(self, dev):
|
||||
"release claim on device"
|
||||
lock = util.Lock(self.path)
|
||||
table = self.load()
|
||||
|
||||
del table[dev.devname]
|
||||
|
||||
self.save(table)
|
||||
lock.unlock()
|
||||
|
||||
# private
|
||||
def load(self):
|
||||
"""load and parse allocation table"""
|
||||
table = {}
|
||||
if not os.path.exists(self.path):
|
||||
return table
|
||||
|
||||
fd = open(self.path)
|
||||
for line in fd.readlines():
|
||||
iface, pid = line.strip().split()
|
||||
table[iface] = int(pid)
|
||||
fd.close()
|
||||
return table
|
||||
|
||||
def save(self, table):
|
||||
"""write table to disk"""
|
||||
lines = ['%s %d\n' % (iface, table[iface]) for iface in sorted(table)]
|
||||
fd = open(self.path, 'w')
|
||||
fd.writelines(lines)
|
||||
fd.close()
|
||||
|
||||
def getdevs(self):
|
||||
"""find all available devices of our device type"""
|
||||
ifaces = []
|
||||
for line in util.runcmd('ifconfig -a -s').splitlines():
|
||||
iface = line.split()[0]
|
||||
if iface.startswith(self.netbufclass.devclass()):
|
||||
ifaces.append(iface)
|
||||
|
||||
return ifaces
|
||||
|
||||
class BufferedNIC(CheckpointedDevice):
|
||||
"""
|
||||
Buffer a protected domain's network output between rounds so that
|
||||
nothing is issued that a failover might not know about.
|
||||
"""
|
||||
|
||||
def __init__(self, vif):
|
||||
self.installed = False
|
||||
self.vif = vif
|
||||
|
||||
self.pool = Netbufpool(selectnetbuf())
|
||||
self.rth = getrth()
|
||||
|
||||
self.setup()
|
||||
|
||||
def __del__(self):
|
||||
self.uninstall()
|
||||
|
||||
def postsuspend(self):
|
||||
if not self.installed:
|
||||
self.install()
|
||||
|
||||
self._sendqmsg(qdisc.TC_PLUG_BUFFER)
|
||||
|
||||
def commit(self):
|
||||
'''Called when checkpoint has been acknowledged by
|
||||
the backup'''
|
||||
self._sendqmsg(qdisc.TC_PLUG_RELEASE_ONE)
|
||||
|
||||
# private
|
||||
def _sendqmsg(self, action):
|
||||
self.q.action = action
|
||||
req = qdisc.changerequest(self.bufdevno, self.handle, self.q)
|
||||
self.rth.talk(req.pack())
|
||||
return True
|
||||
|
||||
def setup(self):
|
||||
"""install Remus plug on VIF outbound traffic"""
|
||||
self.bufdev = self.pool.get()
|
||||
|
||||
devname = self.bufdev.devname
|
||||
bufdev = self.rth.getlink(devname)
|
||||
if not bufdev:
|
||||
raise BufferedNICException('could not find device %s' % devname)
|
||||
|
||||
self.bufdev.install(self.vif)
|
||||
|
||||
self.bufdevno = bufdev['index']
|
||||
self.handle = qdisc.TC_H_ROOT
|
||||
self.q = qdisc.PlugQdisc()
|
||||
|
||||
if not util.modprobe('sch_plug'):
|
||||
raise BufferedNICException('could not load sch_plug module')
|
||||
|
||||
def install(self):
|
||||
devname = self.bufdev.devname
|
||||
q = self.rth.getqdisc(self.bufdevno)
|
||||
if q:
|
||||
if q['kind'] == 'plug':
|
||||
self.installed = True
|
||||
return
|
||||
if q['kind'] not in ('ingress', 'pfifo_fast', 'mq'):
|
||||
raise BufferedNICException('there is already a queueing '
|
||||
'discipline %s on %s' % (q['kind'], devname))
|
||||
|
||||
print ('installing buffer on %s... ' % devname),
|
||||
req = qdisc.addrequest(self.bufdevno, self.handle, self.q)
|
||||
self.rth.talk(req.pack())
|
||||
self.installed = True
|
||||
print 'done.'
|
||||
|
||||
def uninstall(self):
|
||||
if self.installed:
|
||||
try:
|
||||
req = qdisc.delrequest(self.bufdevno, self.handle)
|
||||
self.rth.talk(req.pack())
|
||||
except IOError, e:
|
||||
pass
|
||||
self.installed = False
|
||||
|
||||
try:
|
||||
self.bufdev.uninstall()
|
||||
except util.PipeException, e:
|
||||
pass
|
||||
self.pool.put(self.bufdev)
|
||||
@@ -1,227 +0,0 @@
|
||||
# VM image file manipulation
|
||||
|
||||
import logging, struct
|
||||
|
||||
import vm
|
||||
|
||||
SIGNATURE = 'LinuxGuestRecord'
|
||||
LONGLEN = struct.calcsize('L')
|
||||
INTLEN = struct.calcsize('i')
|
||||
PAGE_SIZE = 4096
|
||||
# ~0L
|
||||
P2M_EXT_SIG = 4294967295L
|
||||
# frames per page
|
||||
FPP = 1024
|
||||
LTAB_MASK = 0xf << 28
|
||||
BATCH_SIZE = 1024
|
||||
IDXLEN = INTLEN + BATCH_SIZE * LONGLEN
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
log = logging.getLogger()
|
||||
|
||||
class VMParseException(Exception): pass
|
||||
|
||||
class VMImage(object):
|
||||
def __init__(self, img=None):
|
||||
"""img may be a path or a file object.
|
||||
If compact is True, apply checkpoints to base image instead
|
||||
of simply concatenating them.
|
||||
"""
|
||||
self.img = img
|
||||
|
||||
self.dom = None
|
||||
self.fd = None
|
||||
self.header = None
|
||||
self.nr_pfns = 0
|
||||
# p2m extension header (unparsed)
|
||||
self.p2mext = None
|
||||
|
||||
if self.img:
|
||||
self.open(self.img)
|
||||
|
||||
def open(self, img):
|
||||
if isinstance(img, str):
|
||||
self.fd = file(img, 'rb')
|
||||
else:
|
||||
self.fd = img
|
||||
|
||||
self.readheader()
|
||||
|
||||
def readheader(self):
|
||||
sig = self.fd.read(len(SIGNATURE))
|
||||
if sig != SIGNATURE:
|
||||
raise VMParseException("Bad signature in image")
|
||||
|
||||
hlen = self.fd.read(INTLEN)
|
||||
hlen, = struct.unpack('!i', hlen)
|
||||
|
||||
self.header = self.fd.read(hlen)
|
||||
self.dom = parseheader(self.header)
|
||||
|
||||
def readp2mfl(self):
|
||||
"read the P2M frame list"
|
||||
pfnlen = self.fd.read(LONGLEN)
|
||||
self.nr_pfns, = struct.unpack('L', pfnlen)
|
||||
p2m0 = self.fd.read(LONGLEN)
|
||||
|
||||
p2mhdr = p2m0
|
||||
p2m0, = struct.unpack('L', p2m0)
|
||||
if p2m0 == P2M_EXT_SIG:
|
||||
elen = self.fd.read(INTLEN)
|
||||
elen, = struct.unpack('I', elen)
|
||||
|
||||
self.p2mext = self.fd.read(elen)
|
||||
|
||||
p2m0 = self.fd.read(LONGLEN)
|
||||
p2m0, = struct.unpack('L', p2m0)
|
||||
p2mfl = [p2m0]
|
||||
|
||||
p2mfle = (self.nr_pfns + FPP - 1)/FPP - 1
|
||||
p2ms = self.fd.read(LONGLEN * p2mfle)
|
||||
p2mfl.extend(struct.unpack('%dL' % p2mfle, p2ms))
|
||||
|
||||
self.p2mfl = p2mfl
|
||||
|
||||
def flush(self):
|
||||
self.ofd.write(self.tail)
|
||||
|
||||
class Writer(object):
|
||||
"""compress a stream of checkpoints into a single image of the
|
||||
last checkpoint"""
|
||||
def __init__(self, fd, compact=False):
|
||||
self.fd = fd
|
||||
self.compact = compact
|
||||
|
||||
self.vm = None
|
||||
self.tail = None
|
||||
# offset to first batch of pages
|
||||
self.imgstart = 0
|
||||
# PFN mappings
|
||||
self.pfns = []
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
def writeheader(self):
|
||||
hlen = struct.pack('!i', len(self.vm.header))
|
||||
header = ''.join([SIGNATURE, hlen, self.vm.header])
|
||||
self.fd.write(header)
|
||||
|
||||
def writep2mfl(self):
|
||||
p2m = [struct.pack('L', self.vm.nr_pfns)]
|
||||
if self.vm.p2mext:
|
||||
p2m.extend([struct.pack('L', P2M_EXT_SIG), self.vm.p2mext])
|
||||
p2m.append(struct.pack('%dL' % len(self.vm.p2mfl), *self.vm.p2mfl))
|
||||
self.fd.write(''.join(p2m))
|
||||
|
||||
def writebatch(self, batch):
|
||||
def offset(pfn):
|
||||
isz = (pfn / BATCH_SIZE + 1) * IDXLEN
|
||||
return self.imgstart + isz + pfn * PAGE_SIZE
|
||||
|
||||
if not self.compact:
|
||||
return self.fd.write(batch)
|
||||
|
||||
batch = parsebatch(batch)
|
||||
# sort pages for better disk seek behaviour
|
||||
batch.sort(lambda x, y: cmp(x[0] & ~LTAB_MASK, y[0] & ~LTAB_MASK))
|
||||
|
||||
for pfndesc, page in batch:
|
||||
pfn = pfndesc & ~LTAB_MASK
|
||||
if pfn > self.vm.nr_pfns:
|
||||
log.error('INVALID PFN: %d' % pfn)
|
||||
if len(self.pfns) <= pfn:
|
||||
self.pfns.extend([0] * (pfn - len(self.pfns) + 1))
|
||||
self.pfns[pfn] = pfndesc
|
||||
self.fd.seek(offset(pfn))
|
||||
self.fd.write(page)
|
||||
|
||||
#print "max offset: %d, %d" % (len(self.pfns), offset(self.pfns[-1]))
|
||||
|
||||
def writeindex(self):
|
||||
"Write batch header in front of each page"
|
||||
hdrlen = INTLEN + BATCH_SIZE * LONGLEN
|
||||
batches = (len(self.pfns) + BATCH_SIZE - 1) / BATCH_SIZE
|
||||
|
||||
for i in xrange(batches):
|
||||
offset = self.imgstart + i * (hdrlen + (PAGE_SIZE * BATCH_SIZE))
|
||||
pfnoff = i * BATCH_SIZE
|
||||
# python auto-clamps overreads
|
||||
pfns = self.pfns[pfnoff:pfnoff + BATCH_SIZE]
|
||||
|
||||
self.fd.seek(offset)
|
||||
self.fd.write(struct.pack('i', len(pfns)))
|
||||
self.fd.write(struct.pack('%dL' % len(pfns), *pfns))
|
||||
|
||||
def slurp(self, ifd):
|
||||
"""Apply an incremental checkpoint to a loaded image.
|
||||
accepts a path or a file object."""
|
||||
if isinstance(ifd, str):
|
||||
ifd = file(ifd, 'rb')
|
||||
|
||||
if not self.vm:
|
||||
self.vm = VMImage(ifd)
|
||||
self.writeheader()
|
||||
|
||||
self.vm.readp2mfl()
|
||||
self.writep2mfl()
|
||||
self.imgstart = self.fd.tell()
|
||||
|
||||
while True:
|
||||
l, batch = readbatch(ifd)
|
||||
if l <= 0:
|
||||
break
|
||||
self.writebatch(batch)
|
||||
self.tail = batch + ifd.read()
|
||||
|
||||
def flush(self):
|
||||
if self.tail:
|
||||
self.fd.seek(0, 2)
|
||||
self.fd.write(self.tail)
|
||||
if self.compact:
|
||||
self.writeindex()
|
||||
self.tail = None
|
||||
|
||||
def close(self):
|
||||
self.flush()
|
||||
|
||||
def parseheader(header):
|
||||
"parses a header sexpression"
|
||||
return vm.parsedominfo(vm.strtosxpr(header))
|
||||
|
||||
def makeheader(dominfo):
|
||||
"create an image header from a VM dominfo sxpr"
|
||||
items = [SIGNATURE]
|
||||
sxpr = vm.sxprtostr(dominfo)
|
||||
items.append(struct.pack('!i', len(sxpr)))
|
||||
items.append(sxpr)
|
||||
return ''.join(items)
|
||||
|
||||
def readbatch(fd):
|
||||
batch = []
|
||||
batchlen = fd.read(INTLEN)
|
||||
batch.append(batchlen)
|
||||
batchlen, = struct.unpack('i', batchlen)
|
||||
log.info("batch length: %d" % batchlen)
|
||||
if batchlen <= 0:
|
||||
return (batchlen, batch[0])
|
||||
|
||||
batchfns = fd.read(LONGLEN * batchlen)
|
||||
batch.append(batchfns)
|
||||
pages = fd.read(PAGE_SIZE * batchlen)
|
||||
if len(pages) != PAGE_SIZE * batchlen:
|
||||
log.error('SHORT READ: %d' % len(pages))
|
||||
batch.append(pages)
|
||||
|
||||
return (batchlen, ''.join(batch))
|
||||
|
||||
def parsebatch(batch):
|
||||
"parse a batch string into pages"
|
||||
batchlen, batch = batch[:INTLEN], batch[INTLEN:]
|
||||
batchlen, = struct.unpack('i', batchlen)
|
||||
#print 'batch length: %d' % batchlen
|
||||
pfnlen = batchlen * LONGLEN
|
||||
pfns = struct.unpack('%dL' % batchlen, batch[:pfnlen])
|
||||
pagebuf = batch[pfnlen:]
|
||||
pages = [pagebuf[i*PAGE_SIZE:(i+1)*PAGE_SIZE] for i in xrange(batchlen)]
|
||||
return zip(pfns, pages)
|
||||
@@ -1,318 +0,0 @@
|
||||
# netlink wrappers
|
||||
|
||||
# See include/linux/netlink.h and rtnetlink.h
|
||||
|
||||
import socket, struct
|
||||
import xen.lowlevel.netlink
|
||||
|
||||
NETLINK_ROUTE = 0
|
||||
|
||||
NLM_F_REQUEST = 1 # It is request message.
|
||||
NLM_F_MULTI = 2 # Multipart message, terminated by NLMSG_DONE
|
||||
NLM_F_ACK = 4 # Reply with ack, with zero or error code
|
||||
NLM_F_ECHO = 8 # Echo this request
|
||||
|
||||
# Modifiers to GET request
|
||||
NLM_F_ROOT = 0x100 # specify tree root
|
||||
NLM_F_MATCH = 0x200 # return all matching
|
||||
NLM_F_ATOMIC = 0x400 # atomic GET
|
||||
NLM_F_DUMP = NLM_F_ROOT|NLM_F_MATCH
|
||||
|
||||
# Modifiers to NEW request
|
||||
NLM_F_REPLACE = 0x100 # Override existing
|
||||
NLM_F_EXCL = 0x200 # Do not touch, if it exists
|
||||
NLM_F_CREATE = 0x400 # Create, if it does not exist
|
||||
NLM_F_APPEND = 0x800 # Add to end of list
|
||||
|
||||
RTM_NEWLINK = 16
|
||||
RTM_GETLINK = 18
|
||||
RTM_NEWQDISC = 36
|
||||
RTM_DELQDISC = 37
|
||||
RTM_GETQDISC = 38
|
||||
|
||||
IFLA_UNSPEC = 0
|
||||
IFLA_ADDRESS = 1
|
||||
IFLA_BROADCAST = 2
|
||||
IFLA_IFNAME = 3
|
||||
IFLA_MTU = 4
|
||||
IFLA_LINK = 5
|
||||
IFLA_QDISC = 6
|
||||
IFLA_STATS = 7
|
||||
IFLA_COST = 8
|
||||
IFLA_PRIORITY = 9
|
||||
IFLA_MASTER = 10
|
||||
IFLA_WIRELESS = 11
|
||||
IFLA_PROTINFO = 12
|
||||
IFLA_TXQLEN = 13
|
||||
IFLA_MAP = 14
|
||||
IFLA_WEIGHT = 15
|
||||
|
||||
TCA_UNSPEC = 0
|
||||
TCA_KIND = 1
|
||||
TCA_OPTIONS = 2
|
||||
TCA_STATS = 3
|
||||
TCA_XSTATS = 4
|
||||
TCA_RATE = 5
|
||||
TCA_FCNT = 6
|
||||
TCA_STATS2 = 7
|
||||
|
||||
class RTNLException(Exception): pass
|
||||
|
||||
def align(l, alignto=4):
|
||||
return (l + alignto - 1) & ~(alignto - 1)
|
||||
|
||||
class rtattr(object):
|
||||
"rtattribute"
|
||||
fmt = "HH"
|
||||
fmtlen = struct.calcsize(fmt)
|
||||
|
||||
def __init__(self, msg=None):
|
||||
if msg:
|
||||
self.unpack(msg)
|
||||
else:
|
||||
self.rta_len = 0
|
||||
self.rta_type = 0
|
||||
|
||||
self.body = ''
|
||||
|
||||
def __len__(self):
|
||||
return align(self.rta_len)
|
||||
|
||||
def pack(self):
|
||||
self.rta_len = self.fmtlen + len(self.body)
|
||||
s = struct.pack(self.fmt, self.rta_len, self.rta_type) + self.body
|
||||
pad = align(self.rta_len) - len(s)
|
||||
if pad:
|
||||
s += '\0' * pad
|
||||
return s
|
||||
|
||||
def unpack(self, msg):
|
||||
args = struct.unpack(self.fmt, msg[:self.fmtlen])
|
||||
self.rta_len, self.rta_type = args
|
||||
|
||||
self.body = msg[self.fmtlen:self.rta_len]
|
||||
|
||||
class rtattrlist(object):
|
||||
def __init__(self, msg):
|
||||
self.start = msg
|
||||
|
||||
def __iter__(self):
|
||||
body = self.start
|
||||
while len(body) > rtattr.fmtlen:
|
||||
rta = rtattr(body)
|
||||
yield rta
|
||||
body = body[len(rta):]
|
||||
|
||||
class nlmsg(object):
|
||||
"netlink message header"
|
||||
fmt = "IHHII"
|
||||
fmtlen = struct.calcsize(fmt)
|
||||
|
||||
def __init__(self, msg=None):
|
||||
if msg:
|
||||
self.unpack(msg)
|
||||
else:
|
||||
self.nlmsg_len = 0
|
||||
self.nlmsg_type = 0
|
||||
self.nlmsg_flags = 0
|
||||
self.nlmsg_seq = 0
|
||||
self.nlmsg_pid = 0
|
||||
|
||||
self.rta = ''
|
||||
self.body = ''
|
||||
|
||||
def __len__(self):
|
||||
return align(self.fmtlen + len(self.body) + len(self.rta))
|
||||
|
||||
def addattr(self, type, data):
|
||||
attr = rtattr()
|
||||
attr.rta_type = type
|
||||
attr.body = data
|
||||
self.rta += attr.pack()
|
||||
self.nlmsg_len = len(self)
|
||||
|
||||
def settype(self, cmd):
|
||||
self.nlmsg_type = cmd
|
||||
|
||||
def pack(self):
|
||||
s = struct.pack(self.fmt, len(self), self.nlmsg_type,
|
||||
self.nlmsg_flags, self.nlmsg_seq,
|
||||
self.nlmsg_pid) + self.body + self.rta
|
||||
return s
|
||||
|
||||
def unpack(self, msg):
|
||||
args = struct.unpack(self.fmt, msg[:self.fmtlen])
|
||||
self.nlmsg_len, self.nlmsg_type, self.nlmsg_flags = args[:3]
|
||||
self.nlmsg_seq, self.nlmsg_pid = args[3:]
|
||||
|
||||
self.body = msg[align(self.fmtlen):]
|
||||
self.rta = ''
|
||||
|
||||
def __str__(self):
|
||||
return '<netlink message, len %d, type %d>' % \
|
||||
(self.nlmsg_len, self.nlmsg_type)
|
||||
|
||||
class ifinfomsg(object):
|
||||
"interface info message"
|
||||
fmt = "BxHiII"
|
||||
fmtlen = struct.calcsize(fmt)
|
||||
|
||||
def __init__(self, msg=None):
|
||||
if msg:
|
||||
self.unpack(msg)
|
||||
else:
|
||||
self.ifi_family = 0
|
||||
self.ifi_type = 0
|
||||
self.ifi_index = 0
|
||||
self.ifi_flags = 0
|
||||
self.ifi_change = 0
|
||||
|
||||
self.body = ''
|
||||
|
||||
def unpack(self, msg):
|
||||
args = struct.unpack(self.fmt, msg[:self.fmtlen])
|
||||
self.ifi_family, self.ifi_type, self.ifi_index= args[:3]
|
||||
self.ifi_flags, self.ifi_change = args[3:]
|
||||
|
||||
self.body = msg[align(self.fmtlen):]
|
||||
|
||||
def __str__(self):
|
||||
return '<ifinfo message, family %d, type %d, index %d>' % \
|
||||
(self.ifi_family, self.ifi_type, self.ifi_index)
|
||||
|
||||
class tcmsg(object):
|
||||
"TC message"
|
||||
fmt = "BxxxiIII"
|
||||
fmtlen = struct.calcsize(fmt)
|
||||
|
||||
def __init__(self, msg=None):
|
||||
if msg:
|
||||
self.unpack(msg)
|
||||
else:
|
||||
self.tcm_family = socket.AF_UNSPEC
|
||||
self.tcm_ifindex = 0
|
||||
self.tcm_handle = 0
|
||||
self.tcm_parent = 0
|
||||
self.tcm_info = 0
|
||||
|
||||
self.rta = ''
|
||||
|
||||
def unpack(self, msg):
|
||||
args = struct.unpack(self.fmt, msg[:self.fmtlen])
|
||||
self.tcm_family, self.tcm_ifindex, self.tcm_handle = args[:3]
|
||||
self.tcm_parent, self.tcm_info = args[3:]
|
||||
|
||||
self.rta = msg[align(self.fmtlen):]
|
||||
|
||||
def pack(self):
|
||||
return struct.pack(self.fmt, self.tcm_family, self.tcm_ifindex,
|
||||
self.tcm_handle, self.tcm_parent, self.tcm_info)
|
||||
|
||||
def __str__(self):
|
||||
return '<tc message, family %d, index %d>' % \
|
||||
(self.tcm_family, self.tcm_ifindex)
|
||||
|
||||
class newlinkmsg(object):
|
||||
def __init__(self, nlmsg):
|
||||
if nlmsg.nlmsg_type != RTM_NEWLINK:
|
||||
raise RTNLException("wrong message type")
|
||||
self.nlmsg = nlmsg
|
||||
self.ifi = ifinfomsg(self.nlmsg.body)
|
||||
|
||||
self.rtattrs = {}
|
||||
for rta in rtattrlist(self.ifi.body):
|
||||
self.rtattrs[rta.rta_type] = rta.body
|
||||
|
||||
class newqdiscmsg(object):
|
||||
def __init__(self, nlmsg):
|
||||
if nlmsg.nlmsg_type != RTM_NEWQDISC:
|
||||
raise RTNLException("wrong message type")
|
||||
self.nlmsg = nlmsg
|
||||
self.t = tcmsg(self.nlmsg.body)
|
||||
|
||||
self.rtattrs = {}
|
||||
for rta in rtattrlist(self.t.rta):
|
||||
self.rtattrs[rta.rta_type] = rta.body
|
||||
|
||||
class rtnl(object):
|
||||
def __init__(self):
|
||||
self._rth = xen.lowlevel.netlink.rtnl()
|
||||
self._linkcache = None
|
||||
|
||||
def getlink(self, key, cached=False):
|
||||
"""returns the interface object corresponding to the key, which
|
||||
may be an index number or device name."""
|
||||
if not cached:
|
||||
self._linkcache = None
|
||||
if self._linkcache is None:
|
||||
self._linkcache = self.getlinks()
|
||||
|
||||
if isinstance(key, int):
|
||||
return self._linkcache.get(key)
|
||||
|
||||
for k, v in self._linkcache.iteritems():
|
||||
if v['name'] == key:
|
||||
return v
|
||||
|
||||
return None
|
||||
|
||||
def getlinks(self):
|
||||
"""returns a dictionary of interfaces keyed by kernel
|
||||
interface index"""
|
||||
links = {}
|
||||
def dumpfilter(addr, msgstr):
|
||||
msg = newlinkmsg(nlmsg(msgstr))
|
||||
idx = msg.ifi.ifi_index
|
||||
ifname = msg.rtattrs[IFLA_IFNAME].strip('\0')
|
||||
address = msg.rtattrs.get(IFLA_ADDRESS)
|
||||
|
||||
link = {'index': idx,
|
||||
'type': msg.ifi.ifi_type,
|
||||
'name': ifname,
|
||||
'address': address}
|
||||
links[idx] = link
|
||||
|
||||
self._rth.wilddump_request(socket.AF_UNSPEC, RTM_GETLINK)
|
||||
self._rth.dump_filter(dumpfilter)
|
||||
|
||||
return links
|
||||
|
||||
def getqdisc(self, dev):
|
||||
"""returns the queueing discipline on device dev, which may be
|
||||
specified by kernel index or device name"""
|
||||
qdiscs = self.getqdiscs(dev)
|
||||
if qdiscs:
|
||||
return qdiscs.values()[0]
|
||||
return None
|
||||
|
||||
def getqdiscs(self, dev=None):
|
||||
"""returns a dictionary of queueing disciplines keyed by kernel
|
||||
interface index"""
|
||||
qdiscs = {}
|
||||
def dumpfilter(addr, msgstr):
|
||||
msg = newqdiscmsg(nlmsg(msgstr))
|
||||
idx = msg.t.tcm_ifindex
|
||||
handle = msg.t.tcm_handle
|
||||
kind = msg.rtattrs[TCA_KIND].strip('\0')
|
||||
opts = msg.rtattrs.get(TCA_OPTIONS)
|
||||
|
||||
qdisc = {'index': idx,
|
||||
'handle': handle,
|
||||
'kind': kind,
|
||||
'options': opts}
|
||||
qdiscs[idx] = qdisc
|
||||
|
||||
tcm = tcmsg()
|
||||
if dev:
|
||||
link = self.getlink(dev)
|
||||
if not link:
|
||||
raise QdiscException('device %s not found' % dev)
|
||||
tcm.tcm_ifindex = link['index']
|
||||
|
||||
msg = tcm.pack()
|
||||
self._rth.dump_request(RTM_GETQDISC, msg)
|
||||
self._rth.dump_filter(dumpfilter)
|
||||
return qdiscs
|
||||
|
||||
def talk(self, req):
|
||||
self._rth.talk(req)
|
||||
@@ -1,56 +0,0 @@
|
||||
"""Simple profiling module
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
class ProfileBlock(object):
|
||||
"""A section of code to be profiled"""
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def enter(self):
|
||||
print "PROF: entered %s at %f" % (self.name, time.time())
|
||||
|
||||
def exit(self):
|
||||
print "PROF: exited %s at %f" % (self.name, time.time())
|
||||
|
||||
class NullProfiler(object):
|
||||
def enter(self, name):
|
||||
pass
|
||||
|
||||
def exit(self, name=None):
|
||||
pass
|
||||
|
||||
class Profiler(object):
|
||||
def __init__(self):
|
||||
self.blocks = {}
|
||||
self.running = []
|
||||
|
||||
def enter(self, name):
|
||||
try:
|
||||
block = self.blocks[name]
|
||||
except KeyError:
|
||||
block = ProfileBlock(name)
|
||||
self.blocks[name] = block
|
||||
|
||||
block.enter()
|
||||
self.running.append(block)
|
||||
|
||||
def exit(self, name=None):
|
||||
if name is not None:
|
||||
block = None
|
||||
while self.running:
|
||||
tmp = self.running.pop()
|
||||
if tmp.name == name:
|
||||
block = tmp
|
||||
break
|
||||
tmp.exit()
|
||||
if not block:
|
||||
raise KeyError('block %s not running' % name)
|
||||
else:
|
||||
try:
|
||||
block = self.running.pop()
|
||||
except IndexError:
|
||||
raise KeyError('no block running')
|
||||
|
||||
block.exit()
|
||||
@@ -1,189 +0,0 @@
|
||||
import socket, struct
|
||||
|
||||
import netlink
|
||||
import platform
|
||||
|
||||
kernelversion = platform.platform(terse=True).split("-")[1].split(".")
|
||||
|
||||
qdisc_kinds = {}
|
||||
|
||||
TC_H_ROOT = 0xFFFFFFFF
|
||||
|
||||
class QdiscException(Exception): pass
|
||||
|
||||
class request(object):
|
||||
"qdisc request message"
|
||||
def __init__(self, cmd, flags=0, dev=None, handle=0):
|
||||
self.n = netlink.nlmsg()
|
||||
self.t = netlink.tcmsg()
|
||||
|
||||
self.n.nlmsg_flags = netlink.NLM_F_REQUEST|flags
|
||||
self.n.nlmsg_type = cmd
|
||||
self.t.tcm_family = socket.AF_UNSPEC
|
||||
|
||||
if not handle:
|
||||
handle = TC_H_ROOT
|
||||
self.t.tcm_parent = handle
|
||||
|
||||
if dev:
|
||||
self.t.tcm_ifindex = dev
|
||||
|
||||
def pack(self):
|
||||
t = self.t.pack()
|
||||
self.n.body = t
|
||||
return self.n.pack()
|
||||
|
||||
class addrequest(request):
|
||||
def __init__(self, dev, handle, qdisc):
|
||||
flags = netlink.NLM_F_EXCL|netlink.NLM_F_CREATE
|
||||
super(addrequest, self).__init__(netlink.RTM_NEWQDISC, flags=flags,
|
||||
dev=dev, handle=handle)
|
||||
self.n.addattr(netlink.TCA_KIND, qdisc.kind + '\0')
|
||||
opts = qdisc.pack()
|
||||
if opts:
|
||||
self.n.addattr(netlink.TCA_OPTIONS, opts)
|
||||
|
||||
class delrequest(request):
|
||||
def __init__(self, dev, handle):
|
||||
super(delrequest, self).__init__(netlink.RTM_DELQDISC, dev=dev,
|
||||
handle=handle)
|
||||
|
||||
class changerequest(request):
|
||||
def __init__(self, dev, handle, qdisc):
|
||||
super(changerequest, self).__init__(netlink.RTM_NEWQDISC,
|
||||
dev=dev, handle=handle)
|
||||
self.n.addattr(netlink.TCA_KIND, qdisc.kind + '\0')
|
||||
opts = qdisc.pack()
|
||||
if opts:
|
||||
self.n.addattr(netlink.TCA_OPTIONS, opts)
|
||||
|
||||
class Qdisc(object):
|
||||
def __new__(cls, qdict=None, *args, **opts):
|
||||
if qdict:
|
||||
kind = qdict.get('kind')
|
||||
cls = qdisc_kinds.get(kind, cls)
|
||||
obj = super(Qdisc, cls).__new__(cls)
|
||||
return obj
|
||||
|
||||
def __init__(self, qdict):
|
||||
self._qdict = qdict
|
||||
self.kind = qdict['kind']
|
||||
self.handle = qdict['handle'] >> 16
|
||||
|
||||
def parse(self, opts):
|
||||
if opts:
|
||||
raise QdiscException('cannot parse qdisc parameters')
|
||||
|
||||
def optstr(self):
|
||||
if self.qdict['options']:
|
||||
return '[cannot parse qdisc parameters]'
|
||||
else:
|
||||
return ''
|
||||
|
||||
def pack(self):
|
||||
return ''
|
||||
|
||||
TC_PRIO_MAX = 15
|
||||
class PrioQdisc(Qdisc):
|
||||
fmt = 'i%sB' % (TC_PRIO_MAX + 1)
|
||||
|
||||
def __init__(self, qdict):
|
||||
super(PrioQdisc, self).__init__(qdict)
|
||||
|
||||
if qdict.get('options'):
|
||||
self.unpack(qdict['options'])
|
||||
else:
|
||||
self.bands = 3
|
||||
self.priomap = [1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
|
||||
def pack(self):
|
||||
#return struct.pack(self.fmt, self.bands, *self.priomap)
|
||||
return ''
|
||||
|
||||
def unpack(self, opts):
|
||||
args = struct.unpack(self.fmt, opts)
|
||||
self.bands = args[0]
|
||||
self.priomap = args[1:]
|
||||
|
||||
def optstr(self):
|
||||
mapstr = ' '.join([str(p) for p in self.priomap])
|
||||
return 'bands %d priomap %s' % (self.bands, mapstr)
|
||||
|
||||
qdisc_kinds['prio'] = PrioQdisc
|
||||
qdisc_kinds['pfifo_fast'] = PrioQdisc
|
||||
|
||||
class CfifoQdisc(Qdisc):
|
||||
fmt = 'II'
|
||||
|
||||
def __init__(self, qdict):
|
||||
super(CfifoQdisc, self).__init__(qdict)
|
||||
|
||||
if qdict.get('options'):
|
||||
self.unpack(qdict['options'])
|
||||
else:
|
||||
self.epoch = 0
|
||||
self.vmid = 0
|
||||
|
||||
def pack(self):
|
||||
return struct.pack(self.fmt, self.epoch, self.vmid)
|
||||
|
||||
def unpack(self, opts):
|
||||
self.epoch, self.vmid = struct.unpack(self.fmt, opts)
|
||||
|
||||
def parse(self, opts):
|
||||
args = list(opts)
|
||||
try:
|
||||
while args:
|
||||
arg = args.pop(0)
|
||||
if arg == 'epoch':
|
||||
self.epoch = int(args.pop(0))
|
||||
continue
|
||||
if arg.lower() == 'vmid':
|
||||
self.vmid = int(args.pop(0))
|
||||
continue
|
||||
except Exception, inst:
|
||||
raise QdiscException(str(inst))
|
||||
|
||||
def optstr(self):
|
||||
return 'epoch %d vmID %d' % (self.epoch, self.vmid)
|
||||
|
||||
qdisc_kinds['cfifo'] = CfifoQdisc
|
||||
|
||||
TC_PLUG_BUFFER = 0
|
||||
TC_PLUG_RELEASE_ONE = 1
|
||||
|
||||
class PlugQdisc(Qdisc):
|
||||
|
||||
def __init__(self, qdict=None):
|
||||
if int(kernelversion[0]) >= 3 and int(kernelversion[1]) >= 4:
|
||||
self.fmt = 'iI'
|
||||
self.limit = 10000
|
||||
else:
|
||||
self.fmt = 'I'
|
||||
|
||||
if not qdict:
|
||||
qdict = {'kind': 'plug',
|
||||
'handle': TC_H_ROOT}
|
||||
super(PlugQdisc, self).__init__(qdict)
|
||||
|
||||
self.action = 0
|
||||
|
||||
def pack(self):
|
||||
if int(kernelversion[0]) >= 3 and int(kernelversion[1]) >= 4:
|
||||
return struct.pack(self.fmt, self.action, self.limit)
|
||||
else:
|
||||
return struct.pack(self.fmt, self.action)
|
||||
|
||||
def parse(self, args):
|
||||
if not args:
|
||||
raise QdiscException('no action given')
|
||||
arg = args[0]
|
||||
|
||||
if arg == 'checkpoint':
|
||||
self.action = TC_PLUG_BUFFER
|
||||
elif arg == 'release':
|
||||
self.action = TC_PLUG_RELEASE_ONE
|
||||
else:
|
||||
raise QdiscException('unknown action')
|
||||
|
||||
qdisc_kinds['plug'] = PlugQdisc
|
||||
@@ -1,186 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os, select, socket, threading, time, signal, xmlrpclib
|
||||
|
||||
from xen.xend.XendClient import server
|
||||
from xen.xend.xenstore.xswatch import xswatch
|
||||
|
||||
import xen.lowlevel.xc
|
||||
from xen.xend.xenstore import xsutil
|
||||
xc = xen.lowlevel.xc.xc()
|
||||
|
||||
import xen.lowlevel.checkpoint
|
||||
|
||||
import vm, image
|
||||
|
||||
XCFLAGS_LIVE = 1
|
||||
|
||||
xcsave = '/usr/lib/xen/bin/xc_save'
|
||||
|
||||
class _proxy(object):
|
||||
"proxy simulates an object without inheritance"
|
||||
def __init__(self, obj):
|
||||
self._obj = obj
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self._obj, name)
|
||||
|
||||
def proxy(self, obj):
|
||||
self._obj = obj
|
||||
|
||||
class CheckpointError(Exception): pass
|
||||
|
||||
class CheckpointingFile(_proxy):
|
||||
"""Tee writes into separate file objects for each round.
|
||||
This is necessary because xc_save gets a single file descriptor
|
||||
for the duration of checkpointing.
|
||||
"""
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
|
||||
self.round = 0
|
||||
self.rfd, self.wfd = os.pipe()
|
||||
self.fd = file(path, 'wb')
|
||||
|
||||
# this pipe is used to notify the writer thread of checkpoints
|
||||
self.cprfd, self.cpwfd = os.pipe()
|
||||
|
||||
super(CheckpointingFile, self).__init__(self.fd)
|
||||
|
||||
wt = threading.Thread(target=self._wrthread, name='disk-write-thread')
|
||||
wt.setDaemon(True)
|
||||
wt.start()
|
||||
self.wt = wt
|
||||
|
||||
def fileno(self):
|
||||
return self.wfd
|
||||
|
||||
def close(self):
|
||||
os.close(self.wfd)
|
||||
# closing wfd should signal writer to stop
|
||||
self.wt.join()
|
||||
os.close(self.rfd)
|
||||
os.close(self.cprfd)
|
||||
os.close(self.cpwfd)
|
||||
self.fd.close()
|
||||
self.wt = None
|
||||
|
||||
def checkpoint(self):
|
||||
os.write(self.cpwfd, '1')
|
||||
|
||||
def _wrthread(self):
|
||||
while True:
|
||||
r, o, e = select.select((self.rfd, self.cprfd), (), ())
|
||||
if self.rfd in r:
|
||||
data = os.read(self.rfd, 256 * 1024)
|
||||
if not data:
|
||||
break
|
||||
self.fd.write(data)
|
||||
if self.cprfd in r:
|
||||
junk = os.read(self.cprfd, 1)
|
||||
self.round += 1
|
||||
self.fd = file('%s.%d' % (self.path, self.round), 'wb')
|
||||
self.proxy(self.fd)
|
||||
|
||||
class MigrationSocket(_proxy):
|
||||
def __init__(self, address):
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect(address)
|
||||
|
||||
sock.send("receive\n")
|
||||
sock.recv(80)
|
||||
|
||||
fd = os.fdopen(sock.fileno(), 'w+')
|
||||
|
||||
self.sock = sock
|
||||
super(MigrationSocket, self).__init__(fd)
|
||||
|
||||
class NullSocket(_proxy):
|
||||
def __init__(self, address):
|
||||
filedesc = os.open('/dev/null', 0666)
|
||||
fd = os.fdopen(filedesc, 'w+')
|
||||
super(NullSocket, self).__init__(fd)
|
||||
|
||||
class Keepalive(object):
|
||||
"Call a keepalive method at intervals"
|
||||
def __init__(self, method, interval=0.1):
|
||||
self.keepalive = method
|
||||
self.interval = interval
|
||||
|
||||
self.thread = None
|
||||
self.running = False
|
||||
|
||||
def start(self):
|
||||
if not self.interval:
|
||||
return
|
||||
self.thread = threading.Thread(target=self.run, name='keepalive-thread')
|
||||
self.thread.setDaemon(True)
|
||||
self.running = True
|
||||
self.thread.start()
|
||||
|
||||
def stop(self):
|
||||
if not self.thread:
|
||||
return
|
||||
self.running = False
|
||||
self.thread.join()
|
||||
self.thread = None
|
||||
|
||||
def run(self):
|
||||
while self.running:
|
||||
self.keepalive()
|
||||
time.sleep(self.interval)
|
||||
self.keepalive(stop=True)
|
||||
|
||||
class Saver(object):
|
||||
def __init__(self, domid, fd, suspendcb=None, resumecb=None,
|
||||
checkpointcb=None, interval=0, flags=0):
|
||||
"""Create a Saver object for taking guest checkpoints.
|
||||
domid: name, number or UUID of a running domain
|
||||
fd: a stream to which checkpoint data will be written.
|
||||
suspendcb: callback invoked after guest is suspended
|
||||
resumecb: callback invoked before guest resumes
|
||||
checkpointcb: callback invoked when a checkpoint is complete. Return
|
||||
True to take another checkpoint, or False to stop.
|
||||
flags: Remus flags to be passed to xc_domain_save
|
||||
"""
|
||||
self.fd = fd
|
||||
self.suspendcb = suspendcb
|
||||
self.resumecb = resumecb
|
||||
self.checkpointcb = checkpointcb
|
||||
self.interval = interval
|
||||
self.flags = flags
|
||||
|
||||
self.vm = vm.VM(domid)
|
||||
|
||||
self.checkpointer = None
|
||||
|
||||
def start(self):
|
||||
vm.getshadowmem(self.vm)
|
||||
|
||||
hdr = image.makeheader(self.vm.dominfo)
|
||||
self.fd.write(hdr)
|
||||
self.fd.flush()
|
||||
|
||||
self.checkpointer = xen.lowlevel.checkpoint.checkpointer()
|
||||
try:
|
||||
try:
|
||||
self.checkpointer.open(self.vm.domid)
|
||||
self.checkpointer.start(self.fd, self.suspendcb, self.resumecb,
|
||||
self.checkpointcb, self.interval,
|
||||
self.flags)
|
||||
except xen.lowlevel.checkpoint.error, e:
|
||||
raise CheckpointError(e)
|
||||
finally:
|
||||
try: #errors in checkpoint close are not critical atm.
|
||||
self.checkpointer.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
def _resume(self):
|
||||
"""low-overhead version of XendDomainInfo.resumeDomain"""
|
||||
# TODO: currently assumes SUSPEND_CANCEL is available
|
||||
if True:
|
||||
xc.domain_resume(self.vm.domid, 1)
|
||||
xsutil.ResumeDomain(self.vm.domid)
|
||||
else:
|
||||
server.xend.domain.resumeDomain(self.vm.domid)
|
||||
@@ -1,4 +0,0 @@
|
||||
import blkdev
|
||||
|
||||
class TapDisk(BlkDev):
|
||||
pass
|
||||
Loaded 100 of 503 files, more files were not shown because too many files have changed in this diff.
Show more