debuggers.hg

changeset 19999:e34975d7d8f1

xend: Add support for URI ('file:' and 'data:' scheme) for PV/kernel and PV/ramdisk

Add support for 'file:' and 'data:' URI schemes for the parameters
'PV/kernel' and 'PV/ramdisk' in the VM.create() call. The 'data:'
scheme handling enables using a file which is stored inside the
management system (from where the XenAPI call is send) as kernel or
ramdisk.

Notes:
o all included: a detailed description can be found in the xenapi
documentation
o bumped up the version of the API document to 1.0.8 (because of
(minimal) interface extension)
o Future enhancements (like http:, ftp: schemes) fit seamlessly into
the current design / classes

Signed-off-by: Andreas Florath <xen@flonatel.org>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Jul 20 10:12:38 2009 +0100 (2009-07-20)
parents 62b7fc245d1f
children 6d41644623de
files docs/xen-api/bibliography.tex docs/xen-api/revision-history.tex docs/xen-api/xenapi-coversheet.tex docs/xen-api/xenapi-datamodel.tex docs/xen-api/xenapi.tex tools/python/xen/util/fileuri.py tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/image.py
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/docs/xen-api/bibliography.tex	Mon Jul 20 10:12:38 2009 +0100
     1.3 @@ -0,0 +1,5 @@
     1.4 +\begin{thebibliography}{9}
     1.5 +\bibitem[RFC2397]{RFC2397}
     1.6 +Masinter L., \textbf{The "data" URL scheme}, RFC 2397, August 1998,
     1.7 +Network Working Group, http://www.ietf.org/rfc/rfc2397.txt
     1.8 +\end{thebibliography}
     2.1 --- a/docs/xen-api/revision-history.tex	Mon Jul 20 10:10:15 2009 +0100
     2.2 +++ b/docs/xen-api/revision-history.tex	Mon Jul 20 10:12:38 2009 +0100
     2.3 @@ -1,69 +1,49 @@
     2.4  { \bf Revision History}
     2.5  
     2.6 +% Please do not use minipages in a tabular environment; this results
     2.7 +% in bad vertical alignment. 
     2.8 +
     2.9 +\begin{flushleft}
    2.10  \begin{center}
    2.11 - \begin{tabular}{|l|l|l|l|}
    2.12 + \begin{tabular}{|l|l|l|>{\raggedright}p{7cm}|}
    2.13    \hline
    2.14    1.0.0 & 27th April 07 & Xensource et al. &
    2.15 -   \begin{minipage}[t][.7cm]{7cm}
    2.16 -     Initial Revision
    2.17 -   \end{minipage}\\
    2.18 +     Initial Revision\tabularnewline
    2.19    \hline
    2.20    1.0.1 & 10th Dec. 07 & S. Berger &
    2.21 -   \begin{minipage}[t]{7cm}
    2.22 -    \begin{flushleft}
    2.23       Added XSPolicy.reset\_xspolicy, VTPM.get\_other\_config,
    2.24 -     VTPM.set\_otherconfig. ACMPolicy.get\_enforced\_binary methods.
    2.25 -    \end{flushleft}
    2.26 -   \end{minipage}\\
    2.27 +     VTPM.set\_otherconfig. ACMPolicy.get\_enforced\_binary methods.\tabularnewline
    2.28    \hline
    2.29    1.0.2 & 25th Jan. 08 & J. Fehlig &
    2.30 -   \begin{minipage}[t]{7cm}
    2.31 -    \begin{flushleft}
    2.32 -     Added Crashed VM power state.
    2.33 -    \end{flushleft}
    2.34 -   \end{minipage}\\
    2.35 +     Added Crashed VM power state.\tabularnewline
    2.36    \hline
    2.37    1.0.3 & 11th Feb. 08 & S. Berger &
    2.38 -   \begin{minipage}[t]{7cm}
    2.39 -    \begin{flushleft}
    2.40 -     Added table of contents and hyperlink cross reference.
    2.41 -    \end{flushleft}
    2.42 -   \end{minipage}\\
    2.43 +     Added table of contents and hyperlink cross reference.\tabularnewline
    2.44    \hline
    2.45    1.0.4 & 23rd March 08 & S. Berger &
    2.46 -   \begin{minipage}[t]{7cm}
    2.47 -    \begin{flushleft}
    2.48 -     Added XSPolicy.can\_run
    2.49 -    \end{flushleft}
    2.50 -   \end{minipage}\\
    2.51 +     Added XSPolicy.can\_run\tabularnewline
    2.52    \hline
    2.53    1.0.5 & 17th Apr. 08 & S. Berger &
    2.54 -   \begin{minipage}[t]{7cm}
    2.55 -    \begin{flushleft}
    2.56       Added undocumented fields and methods for default\_netmask and
    2.57       default\_gateway to the Network class. Removed an unimplemented
    2.58       method from the XSPolicy class and removed the 'optional' from
    2.59 -     'oldlabel' parameters.
    2.60 -    \end{flushleft}
    2.61 -   \end{minipage}\\
    2.62 +     'oldlabel' parameters.\tabularnewline
    2.63    \hline
    2.64    1.0.6 & 24th Jul. 08 & Y. Iwamatsu &
    2.65 -   \begin{minipage}[t]{7cm}
    2.66 -    \begin{flushleft}
    2.67       Added definitions of new classes DPCI and PPCI. Updated the table
    2.68       and the diagram representing relationships between classes.
    2.69 -     Added host.PPCIs and VM.DPCIs fields.
    2.70 -    \end{flushleft}
    2.71 -   \end{minipage}\\
    2.72 +     Added host.PPCIs and VM.DPCIs fields.\tabularnewline
    2.73    \hline
    2.74    1.0.7 & 20th Oct. 08 & M. Kanno &
    2.75 -   \begin{minipage}[t]{7cm}
    2.76 -    \begin{flushleft}
    2.77       Added definitions of new classes DSCSI and PSCSI. Updated the table
    2.78       and the diagram representing relationships between classes.
    2.79 -     Added host.PSCSIs and VM.DSCSIs fields.
    2.80 -    \end{flushleft}
    2.81 -   \end{minipage}\\
    2.82 +     Added host.PSCSIs and VM.DSCSIs fields.\tabularnewline
    2.83 +  \hline
    2.84 +  1.0.8 & 17th Jun. 09 & A. Florath &
    2.85 +     Updated interactive session example.
    2.86 +     Added description for \texttt{PV/kernel} and \texttt{PV/ramdisk}
    2.87 +     parameters using URIs.\tabularnewline
    2.88    \hline
    2.89   \end{tabular}
    2.90  \end{center}
    2.91 +\end{flushleft}
     3.1 --- a/docs/xen-api/xenapi-coversheet.tex	Mon Jul 20 10:10:15 2009 +0100
     3.2 +++ b/docs/xen-api/xenapi-coversheet.tex	Mon Jul 20 10:12:38 2009 +0100
     3.3 @@ -17,12 +17,12 @@
     3.4  \newcommand{\coversheetlogo}{xen.eps}
     3.5  
     3.6  %% Document date
     3.7 -\newcommand{\datestring}{20th October 2008}
     3.8 +\newcommand{\datestring}{17th June 2009}
     3.9  
    3.10  \newcommand{\releasestatement}{Stable Release}
    3.11  
    3.12  %% Document revision
    3.13 -\newcommand{\revstring}{API Revision 1.0.7}
    3.14 +\newcommand{\revstring}{API Revision 1.0.8}
    3.15  
    3.16  %% Document authors
    3.17  \newcommand{\docauthors}{
     4.1 --- a/docs/xen-api/xenapi-datamodel.tex	Mon Jul 20 10:10:15 2009 +0100
     4.2 +++ b/docs/xen-api/xenapi-datamodel.tex	Mon Jul 20 10:12:38 2009 +0100
     4.3 @@ -1,5 +1,6 @@
     4.4  %
     4.5  % Copyright (c) 2006-2007 XenSource, Inc.
     4.6 +% Copyright (c) 2009 flonatel GmbH & Co. KG
     4.7  %
     4.8  % Permission is granted to copy, distribute and/or modify this document under
     4.9  % the terms of the GNU Free Documentation License, Version 1.2 or any later
    4.10 @@ -9,6 +10,7 @@
    4.11  % "GNU Free Documentation License" or the file fdl.tex.
    4.12  %
    4.13  % Authors: Ewan Mellor, Richard Sharp, Dave Scott, Jon Harrop.
    4.14 +% Contributor: Andreas Florath
    4.15  %
    4.16  
    4.17  \chapter{API Reference}
    4.18 @@ -1378,10 +1380,10 @@ the batch of events
    4.19  \newpage
    4.20  \section{Class: VM}
    4.21  \subsection{Fields for class: VM}
    4.22 -\begin{longtable}{|lllp{0.38\textwidth}|}
    4.23 +\begin{longtable}{|llp{0.21\textwidth}p{0.33\textwidth}|}
    4.24  \hline
    4.25  \multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf VM} \\
    4.26 -\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em A
    4.27 +\multicolumn{4}{|l|}{\parbox{11cm}{\em Description: A
    4.28  virtual machine (or 'guest').}} \\
    4.29  \hline
    4.30  Quals & Field & Type & Description \\
    4.31 @@ -1413,8 +1415,8 @@ Quals & Field & Type & Description \\
    4.32  $\mathit{RO}_\mathit{run}$ &  {\tt DPCIs} & (DPCI ref) Set & pass-through PCI devices \\
    4.33  $\mathit{RO}_\mathit{run}$ &  {\tt DSCSIs} & (DSCSI ref) Set & half-virtualized SCSI devices \\
    4.34  $\mathit{RW}$ &  {\tt PV/bootloader} & string & name of or path to bootloader \\
    4.35 -$\mathit{RW}$ &  {\tt PV/kernel} & string & path to the kernel \\
    4.36 -$\mathit{RW}$ &  {\tt PV/ramdisk} & string & path to the initrd \\
    4.37 +$\mathit{RW}$ &  {\tt PV/kernel} & string & URI of kernel \\
    4.38 +$\mathit{RW}$ &  {\tt PV/ramdisk} & string & URI of initrd \\
    4.39  $\mathit{RW}$ &  {\tt PV/args} & string & kernel command-line arguments \\
    4.40  $\mathit{RW}$ &  {\tt PV/bootloader\_args} & string & miscellaneous arguments for the bootloader \\
    4.41  $\mathit{RW}$ &  {\tt HVM/boot\_policy} & string & HVM boot policy \\
    4.42 @@ -1429,6 +1431,87 @@ Quals & Field & Type & Description \\
    4.43  $\mathit{RO}_\mathit{run}$ &  {\tt security/label} & string & the VM's security label \\
    4.44  \hline
    4.45  \end{longtable}
    4.46 +\subsection{Parameter Details}
    4.47 +\subsubsection{PV/kernel and PV/ramdisk}
    4.48 +The \texttt{PV/kernel} and \texttt{PV/ramdisk} parameters should be
    4.49 +specified as URIs with either a \texttt{file} or \texttt{data} scheme.
    4.50 +
    4.51 +The \texttt{file} scheme must be used when a file on the remote dom0
    4.52 +should be used.  The remote dom0 is the one where the guest system
    4.53 +should be started on. Only absolute filenames are supported, i.e. the
    4.54 +string must start with \texttt{file://} appended with the absolute
    4.55 +path.  This is typically used when the guest system use the same
    4.56 +operating systems as the dom0 or there is some kind of shared storage
    4.57 +for the images inside the dom0s.
    4.58 +
    4.59 +Note that for compatibility reasons it is possible --- but not
    4.60 +recommended --- to leave out the scheme specification for
    4.61 +\texttt{file}, i.e. \texttt{file:///some/path} and \texttt{/some/path}
    4.62 +is equivalent.
    4.63 +
    4.64 +Examples (in python):
    4.65 +
    4.66 +Use kernel image which resides in the \texttt{/boot} directory:
    4.67 +\begin{verbatim}
    4.68 +xenapi.VM.create({ ...
    4.69 +   'PV_kernel': 'file:///boot/vmlinuz-2.6.26-2-xen-686',
    4.70 +   ... })
    4.71 +\end{verbatim}
    4.72 +
    4.73 +Use ramdisk image which resides on a (shared) nfs directory:
    4.74 +\begin{verbatim}
    4.75 +xenapi.VM.create({ ...
    4.76 +   'PV_ramdisk': 'file:///nfs/xen/debian/5.0.1/initrd.img-2.6.26-2-xen-686'
    4.77 +   ... })
    4.78 +\end{verbatim}
    4.79 +
    4.80 +When an image should be used which resides on the local system,
    4.81 +i.e. the system where the XenAPI call is send from, it is possible to
    4.82 +use the \texttt{data} URI scheme as described in \cite{RFC2397}.  The
    4.83 +media-type must be set to \texttt{application/octet-stream}.
    4.84 +Currently only base64 encoding is supported.  The URI must therefore
    4.85 +start with \texttt{data:application/octet-stream;base64,} followed by
    4.86 +the base64 encoded image.
    4.87 +
    4.88 +The \texttt{xen/util/fileuri.py} provides a helper function which
    4.89 +takes a local filename as parameter and build up the correct URI from
    4.90 +this.
    4.91 +
    4.92 +Examples (in python):
    4.93 +
    4.94 +Use kernel image specified inline:
    4.95 +\begin{verbatim}
    4.96 +xenapi.VM.create({ ...
    4.97 +   'PV_kernel': 'data:application/octet-stream;base64,H4Zu....'
    4.98 +      # most of base64 encoded data is omitted 
    4.99 +   ... })
   4.100 +\end{verbatim}
   4.101 +
   4.102 +Using the utility function:
   4.103 +\begin{verbatim}
   4.104 +from xen.util.fileuri import scheme_data
   4.105 +xenapi.VM.create({ ...
   4.106 +   'PV_kernel': scheme_data.create_from_file(
   4.107 +       "/xen/guests/images/debian/5.0.1/vmlinuz-2.6.26-2-xen-686"),
   4.108 +   ... })
   4.109 +\end{verbatim}
   4.110 +
   4.111 +Currently when using the \texttt{data} URI scheme, a temporary file is
   4.112 +created on the remote dom0 in the directory
   4.113 +\texttt{/var/run/xend/boot} which is then used for booting. When not
   4.114 +used any longer the file is deleted.  (Therefore reading of the
   4.115 +\texttt{PV/kernel} or \texttt{PV/ramdisk} parameters when created with
   4.116 +a \texttt{data} URI scheme returns a filename to a temporary file ---
   4.117 +which might even not exists when querying.)  This implementation might
   4.118 +change in the way that the data is directly used --- without the
   4.119 +indirection using a file.  Therefore do not rely on the data resulting
   4.120 +from a read of a variables which was set using the \texttt{data}
   4.121 +scheme.
   4.122 +
   4.123 +Note: a mix of different schemes for the parameters is possible; e.g.
   4.124 +the kernel can be specified with a \texttt{file} and the ramdisk with
   4.125 +the \texttt{data} URI scheme.
   4.126 +
   4.127  \subsection{RPCs associated with class: VM}
   4.128  \subsubsection{RPC name:~clone}
   4.129  
     5.1 --- a/docs/xen-api/xenapi.tex	Mon Jul 20 10:10:15 2009 +0100
     5.2 +++ b/docs/xen-api/xenapi.tex	Mon Jul 20 10:12:38 2009 +0100
     5.3 @@ -18,6 +18,7 @@
     5.4  \usepackage{longtable}
     5.5  \usepackage{fancyhdr}
     5.6  \usepackage{hyperref}
     5.7 +\usepackage{array}
     5.8  
     5.9  \setlength\topskip{0cm}
    5.10  \setlength\topmargin{0cm}
    5.11 @@ -54,5 +55,6 @@ Xen-enabled host.
    5.12  \include{vm-lifecycle}
    5.13  \include{xenapi-datamodel}
    5.14  \include{fdl}
    5.15 +\include{bibliography}
    5.16  
    5.17  \end{document}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/python/xen/util/fileuri.py	Mon Jul 20 10:12:38 2009 +0100
     6.3 @@ -0,0 +1,273 @@
     6.4 +#============================================================================
     6.5 +# This library is free software; you can redistribute it and/or
     6.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
     6.7 +# License as published by the Free Software Foundation.
     6.8 +#
     6.9 +# This library is distributed in the hope that it will be useful,
    6.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    6.12 +# Lesser General Public License for more details.
    6.13 +#
    6.14 +# You should have received a copy of the GNU Lesser General Public
    6.15 +# License along with this library; if not, write to the Free Software
    6.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    6.17 +#============================================================================
    6.18 +# Copyright (C) 2009 flonatel GmbH & Co. KG
    6.19 +#============================================================================
    6.20 +
    6.21 +import logging
    6.22 +import os
    6.23 +import base64
    6.24 +import tempfile
    6.25 +import stat
    6.26 +from xen.xend.XendLogging import log
    6.27 +from xen.util import mkdir
    6.28 +# The following are needed for unit-testing only
    6.29 +import unittest
    6.30 +
    6.31 +#
    6.32 +# This functions and classes can be used where a filename is expected -
    6.33 +# especially in the xenapi.VM.create() for PV_kernel and PV_ramdisk.
    6.34 +#
    6.35 +# The functions have a backward compatibility mode, i.e. when there is
    6.36 +# no appropriate scheme detected, the data is seens as a path to a
    6.37 +# (local) file.
    6.38 +#
    6.39 +
    6.40 +class scheme_error(Exception):
    6.41 +    def __init__(self, value):
    6.42 +        self.value = value
    6.43 +    def __str__(self):
    6.44 +        return repr(self.value)
    6.45 +
    6.46 +# Data scheme (as defined in RFC 2397):
    6.47 +#  data:application/octet-stream;base64,<base64 encoded data>
    6.48 +# It looks that there is currently no general purpose implementation
    6.49 +# available (in python) for this URL scheme - so the very basic is
    6.50 +# done here.
    6.51 +#
    6.52 +# Limitations
    6.53 +# o Only base64 is currently supported
    6.54 +class scheme_data:
    6.55 +
    6.56 +    @staticmethod
    6.57 +    def encode(data, mediatype = 'application/octet-stream', 
    6.58 +               encoding = 'base64'):
    6.59 +        # XXX Limit this to base64 for current implementation
    6.60 +        if encoding!='base64':
    6.61 +            raise scheme_error("invalid encoding")
    6.62 +        return 'data:' + mediatype + ";" + encoding \
    6.63 +            + "," + base64.b64encode(data)
    6.64 +
    6.65 +    # Private method: parse encoded data
    6.66 +    @staticmethod
    6.67 +    def parse(encoded_data):
    6.68 +        if not isinstance(encoded_data, str):
    6.69 +            raise scheme_error("encoded data has wrong type")
    6.70 +        if not encoded_data.startswith('data:'):
    6.71 +            raise scheme_error("'data:' scheme declaration missing")
    6.72 +        comma = encoded_data.find(',', 5)
    6.73 +        if comma == -1:
    6.74 +            raise scheme_error("data separator (comma) is missing")
    6.75 +        # Cut off the media type and encoding
    6.76 +        mtenc = encoded_data[5:comma]
    6.77 +        if len(mtenc)==0:
    6.78 +            raise scheme_error("encoding is empty")
    6.79 +        # XXX Limit to base64 encoding
    6.80 +        if not mtenc.endswith(';base64'):
    6.81 +            raise scheme_error("encoding is not base64")
    6.82 +        mediatype = mtenc[:-7]
    6.83 +        return (mediatype, 'base64', comma+1)
    6.84 +
    6.85 +    # Stores the data in a local file and returns the filename
    6.86 +    # and a flag if this file in temporary only and must be deleted
    6.87 +    # after starting the VM.
    6.88 +    @staticmethod
    6.89 +    def decode(encoded_data):
    6.90 +        mkdir.parents("/var/run/xend/boot/", stat.S_IRWXU)
    6.91 +        mediatype, encoding, data_start = scheme_data.parse(encoded_data)
    6.92 +        fd, filename = tempfile.mkstemp(
    6.93 +            prefix="data_uri_file.", dir="/var/run/xend/boot")
    6.94 +        os.write(fd, base64.b64decode(encoded_data[data_start:]))
    6.95 +        os.close(fd)
    6.96 +        return filename, True
    6.97 +
    6.98 +    # Utility function which reads in the given (local) file and
    6.99 +    # creates a data scheme from this.
   6.100 +    @staticmethod
   6.101 +    def create_from_file(filename):
   6.102 +        try:
   6.103 +            f = open(filename, "r")
   6.104 +            d = f.read()
   6.105 +            f.close()
   6.106 +            return scheme_data.encode(d)
   6.107 +        except IOError:
   6.108 +            raise scheme_error("file does not exists")
   6.109 +
   6.110 +class scheme_data_unit_tests(unittest.TestCase):
   6.111 +
   6.112 +    def check_basic_encoding(self):
   6.113 +        "scheme_data - basic encoding"
   6.114 +        sd = scheme_data.encode('Hello!')
   6.115 +        self.assertEqual(sd, 'data:application/octet-stream;base64,SGVsbG8h')
   6.116 +
   6.117 +    def check_encoding_with_given_mediatype(self):
   6.118 +        "scheme_data - encoding with given media name"
   6.119 +        sd = scheme_data.encode('Hello!', 'application/x-my-linux-kernel')
   6.120 +        self.assertEqual(sd,
   6.121 +              'data:application/x-my-linux-kernel;base64,SGVsbG8h')
   6.122 +
   6.123 +    def check_parse_01(self):
   6.124 +        "scheme_data - parsing of None"
   6.125 +        self.assertRaises(scheme_error, scheme_data.parse, None)
   6.126 +
   6.127 +    def check_parse_02(self):
   6.128 +        "scheme_data - parsing of empty string"
   6.129 +        self.assertRaises(scheme_error, scheme_data.parse, "")
   6.130 +
   6.131 +    def check_parse_03(self):
   6.132 +        "scheme_data - parsing of unstructured data"
   6.133 +        self.assertRaises(scheme_error, scheme_data.parse, "akskdjdfhezezu")
   6.134 +
   6.135 +    def check_parse_04(self):
   6.136 +        "scheme_data - data: is not at the first place"
   6.137 +        self.assertRaises(scheme_error, scheme_data.parse, 'ggdata:sossm')
   6.138 +
   6.139 +    def check_parse_05(self):
   6.140 +        "scheme_data - no comma in data"
   6.141 +        self.assertRaises(scheme_error, scheme_data.parse, 'data:sossm')
   6.142 +
   6.143 +    def check_parse_06(self):
   6.144 +        "scheme_data - encoding is empty"
   6.145 +        self.assertRaises(scheme_error, scheme_data.parse, 'data:,')
   6.146 +
   6.147 +    def check_parse_07(self):
   6.148 +        "scheme_data - unknown encoding"
   6.149 +        self.assertRaises(scheme_error, scheme_data.parse,
   6.150 +                          'data:somemediatype;unknown,')
   6.151 +
   6.152 +    def check_parse_08(self):
   6.153 +        "scheme_data - parse ok - empty data"
   6.154 +        mediatype, encoding, data_start = scheme_data.parse(
   6.155 +            'data:somemedia;base64,')
   6.156 +        self.assertEqual(mediatype, 'somemedia')
   6.157 +        self.assertEqual(encoding, 'base64')
   6.158 +        self.assertEqual(data_start, 22)
   6.159 +
   6.160 +    def check_parse_09(self):
   6.161 +        "scheme_data - parse ok - some data"
   6.162 +        mediatype, encoding, data_start = scheme_data.parse(
   6.163 +            'data:somemedia;base64,HereComesTheSun')
   6.164 +        self.assertEqual(mediatype, 'somemedia')
   6.165 +        self.assertEqual(encoding, 'base64')
   6.166 +        self.assertEqual(data_start, 22)
   6.167 +
   6.168 +    def check_cff_file_does_not_exist(self):
   6.169 +        "scheme_data - create from file - non existent file"
   6.170 +        self.assertRaises(scheme_error, scheme_data.create_from_file,
   6.171 +                          "/there/is/hopefully/no/file/like/this")
   6.172 +
   6.173 +    def check_cff_ok(self):
   6.174 +        "scheme_data - create from file - ok"
   6.175 +        tmppath = "/tmp/scheme_data_check_cff_ok"
   6.176 +        f = open(tmppath, "w")
   6.177 +        f.write("huhuhu")
   6.178 +        f.close()
   6.179 +        d = scheme_data.create_from_file(tmppath)
   6.180 +        os.unlink(tmppath)
   6.181 +        self.assertEqual(d, "data:application/octet-stream;base64,aHVodWh1")
   6.182 +
   6.183 +# File Scheme
   6.184 +# This class supports absolut paths only.
   6.185 +class scheme_file:
   6.186 +
   6.187 +    @staticmethod
   6.188 +    def encode(filename):
   6.189 +        if len(filename) == 0:
   6.190 +            raise scheme_error("filename is empty")
   6.191 +        if filename[0] != '/':
   6.192 +            raise scheme_error("filename is not absolut")
   6.193 +        return 'file://' + filename
   6.194 +
   6.195 +    @staticmethod
   6.196 +    def decode(encoded_data):
   6.197 +        if not encoded_data.startswith("file://"):
   6.198 +            raise scheme_error("no file:// scheme found")
   6.199 +        path = encoded_data[7:]
   6.200 +        if len(path)==0:
   6.201 +            raise scheme_error("path is empty")
   6.202 +        if path[0]!='/':
   6.203 +            raise scheme_error("path is not absolute")
   6.204 +        return path, False
   6.205 +
   6.206 +class scheme_file_unit_tests(unittest.TestCase):
   6.207 +
   6.208 +    def check_encode_empty_filename(self):
   6.209 +        "scheme_file - encode empty filename"
   6.210 +        self.assertRaises(scheme_error, scheme_file.encode, "")
   6.211 +
   6.212 +    def check_encode_relative_filename(self):
   6.213 +        "scheme_file - encode relative filename"
   6.214 +        self.assertRaises(scheme_error, scheme_file.encode, "../there")
   6.215 +
   6.216 +    def check_encode_absolut_filename(self):
   6.217 +        "scheme_file - encode absolut filename"
   6.218 +        self.assertEqual(
   6.219 +            scheme_file.encode("/here/and/there/again"),
   6.220 +            'file:///here/and/there/again')
   6.221 +
   6.222 +    def check_decode_01(self):
   6.223 +        "scheme_file - decode empty data"
   6.224 +        self.assertRaises(scheme_error, scheme_file.decode, "")
   6.225 +
   6.226 +    def check_decode_02(self):
   6.227 +        "scheme_file - decode data with no file:// at the beginning (1)"
   6.228 +        self.assertRaises(scheme_error, scheme_file.decode,
   6.229 +                          "phonehome://bbbb")
   6.230 +
   6.231 +    def check_decode_03(self):
   6.232 +        "scheme_file - decode data with no file:// at the beginning (2)"
   6.233 +        self.assertRaises(scheme_error, scheme_file.decode,
   6.234 +                          "file:/bbbb")
   6.235 +
   6.236 +    def check_decode_04(self):
   6.237 +        "scheme_file - decode empty path"
   6.238 +        self.assertRaises(scheme_error, scheme_file.decode,
   6.239 +                          "file://")
   6.240 +
   6.241 +    def check_decode_05(self):
   6.242 +        "scheme_file - decode empty relative path"
   6.243 +        self.assertRaises(scheme_error, scheme_file.decode,
   6.244 +                          "file://somewhere")
   6.245 +
   6.246 +    def check_decode_06(self):
   6.247 +        "scheme_file - decode ok"
   6.248 +        path, tmp_file = scheme_file.decode("file:///boot/vmlinuz")
   6.249 +        self.assertEqual(path, "/boot/vmlinuz")
   6.250 +        self.assertEqual(tmp_file, False)
   6.251 +
   6.252 +class scheme_set:
   6.253 +
   6.254 +    def __init__(self):
   6.255 +        self.schemes = [scheme_data, scheme_file]
   6.256 +
   6.257 +    def decode(self, uri):
   6.258 +        for scheme in self.schemes:
   6.259 +            try:
   6.260 +                # If this passes, it is the correct scheme
   6.261 +                return scheme.decode(uri)
   6.262 +            except scheme_error, se:
   6.263 +                log.debug("Decode throws an error: '%s'" % se)
   6.264 +        return uri, False
   6.265 +        
   6.266 +schemes = scheme_set()
   6.267 +
   6.268 +
   6.269 +def suite():
   6.270 +    return unittest.TestSuite(
   6.271 +        [unittest.makeSuite(scheme_data_unit_tests, 'check_'),
   6.272 +         unittest.makeSuite(scheme_file_unit_tests, 'check_'),])
   6.273 +
   6.274 +if __name__ == "__main__":
   6.275 +    testresult = unittest.TextTestRunner(verbosity=3).run(suite())
   6.276 +
     7.1 --- a/tools/python/xen/xend/XendConfig.py	Mon Jul 20 10:10:15 2009 +0100
     7.2 +++ b/tools/python/xen/xend/XendConfig.py	Mon Jul 20 10:12:38 2009 +0100
     7.3 @@ -41,6 +41,7 @@ from xen.util.pci import pci_opts_list_f
     7.4  from xen.xend.XendSXPDev import dev_dict_to_sxp
     7.5  from xen.util import xsconstants
     7.6  from xen.util import auxbin
     7.7 +import xen.util.fileuri
     7.8  
     7.9  log = logging.getLogger("xend.XendConfig")
    7.10  log.setLevel(logging.WARN)
    7.11 @@ -338,6 +339,8 @@ class XendConfig(dict):
    7.12              # output from xc.domain_getinfo
    7.13              self._dominfo_to_xapi(dominfo, update_mem = True)
    7.14  
    7.15 +        self.handle_fileuris()
    7.16 +
    7.17          log.debug('XendConfig.init: %s' % scrub_password(self))
    7.18  
    7.19          # validators go here
    7.20 @@ -1999,10 +2002,14 @@ class XendConfig(dict):
    7.21              self['_temp_kernel'] = sxp.child_value(image_sxp, 'kernel','')
    7.22              self['_temp_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','')
    7.23              self['_temp_args'] = kernel_args
    7.24 +            self['use_tmp_kernel'] = True
    7.25 +            self['use_tmp_ramdisk'] = True
    7.26          else:
    7.27              self['PV_kernel'] = sxp.child_value(image_sxp, 'kernel','')
    7.28              self['PV_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','')
    7.29              self['PV_args'] = kernel_args
    7.30 +            self['use_tmp_kernel'] = False
    7.31 +            self['use_tmp_ramdisk'] = False
    7.32  
    7.33          self['superpages'] = sxp.child_value(image_sxp, 'superpages',0)
    7.34  
    7.35 @@ -2076,3 +2083,11 @@ class XendConfig(dict):
    7.36                  pci.append([domain, bus, slot, func, vdevfn, opts])
    7.37          self['platform']['pci'] = pci
    7.38  
    7.39 + 
    7.40 +    def handle_fileuris(self):
    7.41 +        for arg in [('PV_kernel', 'use_tmp_kernel'), 
    7.42 +                    ('PV_ramdisk', 'use_tmp_ramdisk')]:
    7.43 +            if self[arg[0]] != None:
    7.44 +                self[arg[0]], self[arg[1]] \
    7.45 +                    = xen.util.fileuri.schemes.decode(self[arg[0]])
    7.46 +                log.debug("fileuri '%s' = '%s'" % (arg[0], self[arg[0]][:100]))
     8.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Mon Jul 20 10:10:15 2009 +0100
     8.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Mon Jul 20 10:12:38 2009 +0100
     8.3 @@ -2634,7 +2634,7 @@ class XendDomainInfo:
     8.4  
     8.5              self._createDevices()
     8.6  
     8.7 -            self.image.cleanupBootloading()
     8.8 +            self.image.cleanupTmpImages()
     8.9  
    8.10              self.info['start_time'] = time.time()
    8.11  
    8.12 @@ -2642,12 +2642,12 @@ class XendDomainInfo:
    8.13          except VmError, exn:
    8.14              log.exception("XendDomainInfo.initDomain: exception occurred")
    8.15              if self.image:
    8.16 -                self.image.cleanupBootloading()
    8.17 +                self.image.cleanupTmpImages()
    8.18              raise exn
    8.19          except RuntimeError, exn:
    8.20              log.exception("XendDomainInfo.initDomain: exception occurred")
    8.21              if self.image:
    8.22 -                self.image.cleanupBootloading()
    8.23 +                self.image.cleanupTmpImages()
    8.24              raise VmError(str(exn))
    8.25  
    8.26  
     9.1 --- a/tools/python/xen/xend/image.py	Mon Jul 20 10:10:15 2009 +0100
     9.2 +++ b/tools/python/xen/xend/image.py	Mon Jul 20 10:12:38 2009 +0100
     9.3 @@ -89,6 +89,8 @@ class ImageHandler:
     9.4          self.vm = vm
     9.5  
     9.6          self.bootloader = False
     9.7 +        self.use_tmp_kernel = False
     9.8 +        self.use_tmp_ramdisk = False
     9.9          self.kernel = None
    9.10          self.ramdisk = None
    9.11          self.cmdline = None
    9.12 @@ -106,6 +108,10 @@ class ImageHandler:
    9.13              self.kernel = vmConfig['PV_kernel']
    9.14              self.cmdline = vmConfig['PV_args']
    9.15              self.ramdisk = vmConfig['PV_ramdisk']
    9.16 +        if vmConfig['use_tmp_kernel']:
    9.17 +            self.use_tmp_ramdisk = True
    9.18 +        if vmConfig['use_tmp_ramdisk']:
    9.19 +            self.use_tmp_kernel = True
    9.20          self.vm.storeVm(("image/ostype", self.ostype),
    9.21                          ("image/kernel", self.kernel),
    9.22                          ("image/cmdline", self.cmdline),
    9.23 @@ -135,9 +141,10 @@ class ImageHandler:
    9.24          if 'cpuid_check' in vmConfig:
    9.25              self.cpuid_check = vmConfig['cpuid_check']
    9.26  
    9.27 -    def cleanupBootloading(self):
    9.28 -        if self.bootloader:
    9.29 +    def cleanupTmpImages(self):
    9.30 +        if self.use_tmp_kernel:
    9.31              self.unlink(self.kernel)
    9.32 +        if self.use_tmp_ramdisk:
    9.33              self.unlink(self.ramdisk)
    9.34  
    9.35