Add support for Citrix XenServer.
authorBen Pfaff <blp@nicira.com>
Wed, 13 May 2009 21:01:32 +0000 (14:01 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 13 May 2009 21:01:32 +0000 (14:01 -0700)
This was previously in openflowext.  Now we are adding it to openvswitch.

20 files changed:
COPYING
Makefile.am
vswitchd/automake.mk
vswitchd/etc/README [deleted file]
vswitchd/etc/init.d/vswitch [deleted file]
vswitchd/etc/logrotate.d/vswitch [deleted file]
vswitchd/etc/profile.d/vswitch.sh [deleted file]
vswitchd/etc/sysconfig/vswitch.example [deleted file]
xenserver/README [new file with mode: 0644]
xenserver/automake.mk [new file with mode: 0644]
xenserver/etc_init.d_vswitch [new file with mode: 0755]
xenserver/etc_init.d_vswitch-xapi-update [new file with mode: 0755]
xenserver/etc_logrotate.d_vswitch [new file with mode: 0644]
xenserver/etc_profile.d_vswitch.sh [new file with mode: 0644]
xenserver/etc_sysconfig_vswitch.example [new file with mode: 0644]
xenserver/etc_xapi.d_plugins_vswitch-cfg-update [new file with mode: 0755]
xenserver/etc_xensource_scripts_vif [new file with mode: 0755]
xenserver/opt_xensource_libexec_interface-reconfigure [new file with mode: 0755]
xenserver/usr_lib_xsconsole_plugins-base_XSFeatureNiciraVSwitch.py [new file with mode: 0644]
xenserver/vswitch-xen.spec [new file with mode: 0644]

diff --git a/COPYING b/COPYING
index ab5f3705a828880673fce9e0c556ff6cc2ab3ee5..2345fa31bac415d140fba0622baa4a2a692f294b 100644 (file)
--- a/COPYING
+++ b/COPYING
-Source file copyrights are indicated at the top of each file.
-
-Files not in the datapath/ and vswitchd/ directories or associated
-subdirectories are covered under the OpenFlow license included below:
-
-We are making the OpenFlow specification and associated documentation
-(Software) available for public use and benefit with the expectation
-that others will use, modify and enhance the Software and contribute
-those enhancements back to the community. However, since we would like
-to make the Software available for broadest use, with as few
-restrictions as possible permission is hereby granted, free of charge,
-to any person obtaining a copy of this Software to deal in the Software
-under the copyrights 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.
-
-The name and trademarks of copyright holder(s) may NOT be used in
-advertising or publicity pertaining to the Software or any derivatives
-without specific, written prior permission.
-
-Files in the datapath/ and its sub-directories are covered under the GNU
-General Public License Version 2. Included below:
-
-
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-\f
-                   GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-\f
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-\f
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-\f
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                           NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-\f
-           How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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.
-
-    This program 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 General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year  name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-
-Files in vswitchd/ and its sub-directories are covered under the GNU
-General Public License Version 3. Included below:
-
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.  We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors.  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights.  Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received.  You must make sure that they, too, receive
-or can get the source code.  And you must show them these terms so they
-know their rights.
-
-  Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
-  For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software.  For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
-  Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so.  This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software.  The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable.  Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products.  If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
-  Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary.  To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Use with the GNU Affero General Public License.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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 3 of the License, or
-    (at your option) any later version.
-
-    This program 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 General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
-    <program>  Copyright (C) <year>  <name of author>
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
-  The GNU General Public License does not permit incorporating your program
-into proprietary programs.  If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.  But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+This file is a summary of the licensing of files in this distribution.
+Some files may be marked specifically with a different license, in
+which case that license applies to the file in question.
+
+Files under the controller, debian, doc, include, lib, m4, secchan,
+tests, third-party, and utilities directories are licensed under the
+following "OpenFlow license":
+
+    We are making the OpenFlow specification and associated documentation
+    (Software) available for public use and benefit with the expectation
+    that others will use, modify and enhance the Software and contribute
+    those enhancements back to the community. However, since we would like
+    to make the Software available for broadest use, with as few
+    restrictions as possible permission is hereby granted, free of charge,
+    to any person obtaining a copy of this Software to deal in the Software
+    under the copyrights 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.
+
+    The name and trademarks of copyright holder(s) may NOT be used in
+    advertising or publicity pertaining to the Software or any derivatives
+    without specific, written prior permission.
+
+Files under the datapath directory are licensed under the GNU General
+Public License, version 2.
+
+Files under the vswitchd directory are licensed under the GNU General
+Public License, version 3 or later.
+
+Files under the xenserver directory are licensed on a file-by-file
+basis.  Some files are under an uncertain license that may not be
+DFSG-compliant or GPL-compatible.  Refer to each file for details.
index c38471781bfe27087ec517a27a44cdda5305d03b..ce3b72c570cf72891ab75991e775f24a010af787 100644 (file)
@@ -68,4 +68,5 @@ include include/automake.mk
 include third-party/automake.mk
 include debian/automake.mk
 include vswitchd/automake.mk
+include xenserver/automake.mk
 include ext.mk
index 4b31be296ab7936bd9be262ee98936526eea001e..e16d9578d1c0261e10a0cbf59fb03eb4649fb1bc 100644 (file)
@@ -34,5 +34,4 @@ vswitchd_brcompatd_LDADD = \
 
 EXTRA_DIST += vswitchd/vswitchd.conf.5.in \
        vswitchd/vswitchd.8.in \
-       vswitchd/brcompatd.8.in \
-       vswitchd/etc
+       vswitchd/brcompatd.8.in
diff --git a/vswitchd/etc/README b/vswitchd/etc/README
deleted file mode 100644 (file)
index 0717652..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-The files in this subdirectory are intended to be installed into the
-/etc directory of a XenServer.  They are added to the XenServer
-distribution tarball by the automatic build system.
diff --git a/vswitchd/etc/init.d/vswitch b/vswitchd/etc/init.d/vswitch
deleted file mode 100755 (executable)
index bee066c..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-#!/bin/bash
-#
-# vswitch
-#
-# chkconfig: 2345 09 91
-# description: Manage vswitch kernel modules and user-space daemon
-#
-
-. /etc/init.d/functions
-
-test -e /etc/sysconfig/vswitch && . /etc/sysconfig/vswitch
-
-# General config variables in /etc/sysconfig/vswitch
-VSWITCH_BASE="${VSWITCH_BASE:-/root/vswitch}"
-ENABLE_BRCOMPAT="${ENABLE_BRCOMPAT:-y}"
-ENABLE_FAKE_PROC_NET="${ENABLE_FAKE_PROC_NET:-y}"
-FORCE_COREFILES="${FORCE_COREFILES:-n}"
-COREFILE_PATTERN="${COREFILE_PATTERN:-/var/log/%e-%t}"
-
-# Config variables specific to vswitchd
-VSWITCHD_CONF="${VSWITCHD_CONF:-/etc/vswitchd.conf}"
-VSWITCHD_PIDFILE="${VSWITCHD_PIDFILE:-/var/run/vswitchd.pid}"
-VSWITCHD_PRIORITY="${VSWITCHD_PRIORITY:--5}"
-VSWITCHD_LOGFILE="${VSWITCHD_LOGFILE:-/var/log/vswitchd.log}"
-VSWITCHD_FILE_LOGLEVEL="${VSWITCHD_FILE_LOGLEVEL:-}"
-VSWITCHD_SYSLOG_LOGLEVEL="${VSWITCHD_SYSLOG_LOGLEVEL:-WARN}"
-VSWITCHD_MEMLEAK_LOGFILE="${VSWITCHD_MEMLEAK_LOGFILE:-}"
-VSWITCHD_STRACE_LOG="${VSWITCHD_STRACE_LOG:-}"
-VSWITCHD_STRACE_OPT="${VSWITCHD_STRACE_OPT:-}"
-VSWITCHD_VALGRIND_LOG="${VSWITCHD_VALGRIND_LOG:-}"
-VSWITCHD_VALGRIND_OPT="${VSWITCHD_VALGRIND_OPT:-}"
-
-# Config variables specific brcompatd
-BRCOMPATD_PIDFILE="${BRCOMPATD_PIDFILE:-/var/run/brcompatd.pid}"
-BRCOMPATD_PRIORITY="${BRCOMPATD_PRIORITY:--5}"
-BRCOMPATD_LOGFILE="${BRCOMPATD_LOGFILE:-/var/log/brcompatd.log}"
-BRCOMPATD_FILE_LOGLEVEL="${BRCOMPATD_FILE_LOGLEVEL:-}"
-BRCOMPATD_SYSLOG_LOGLEVEL="${BRCOMPATD_SYSLOG_LOGLEVEL:-WARN}"
-BRCOMPATD_MEMLEAK_LOGFILE="${BRCOMPATD_MEMLEAK_LOGFILE:-}"
-BRCOMPATD_STRACE_LOG="${BRCOMPATD_STRACE_LOG:-}"
-BRCOMPATD_STRACE_OPT="${BRCOMPATD_STRACE_OPT:-}"
-BRCOMPATD_VALGRIND_LOG="${BRCOMPATD_VALGRIND_LOG:-}"
-BRCOMPATD_VALGRIND_OPT="${BRCOMPATD_VALGRIND_OPT:-}"
-
-
-
-
-# Full paths to executables & modules
-vswitchd="$VSWITCH_BASE/sbin/vswitchd"
-brcompatd="$VSWITCH_BASE/sbin/brcompatd"
-dpctl="$VSWITCH_BASE/bin/dpctl"
-vlogconf="$VSWITCH_BASE/bin/vlogconf"
-
-
-if [ "$ENABLE_FAKE_PROC_NET" == "y" ]; then
-    if [ "$ENABLE_BRCOMPAT" != "y" ]; then
-        warning "FAKE_PROC_NET required BRCOMPAT which was disabled.  Force enabling."
-        ENABLE_BRCOMPAT="y"
-    fi
-fi
-
-function dp_list {
-    "$dpctl" dp-show | grep '^dp[0-9]\+:' | cut -d':' -f 1
-}
-
-function dp_intf {
-    local dp=$1
-    # Currently port0 is hardcoded to be the local port.
-    "$dpctl" dp-show $dp | grep 'port 0:' | cut -d' ' -f 3
-}
-
-function ifdown_dp_intf {
-    for dp in $(dp_list); do
-        local intf=$(dp_intf $dp)
-        if [ -e "/etc/sysconfig/network-scripts/ifcfg-$intf" ]; then
-            action "Bringing down datapath interface: $intf" ifdown "$intf"
-        fi
-    done
-}
-
-function xen_mgmt_intf {
-    ( test -e /etc/xensource-inventory \
-        && source /etc/xensource-inventory \
-        && echo "$MANAGEMENT_INTERFACE" )
-}
-
-function xen_mgmt_pifdev {
-    ( test -e "/etc/sysconfig/network-scripts/ifcfg-$1" \
-        && source "/etc/sysconfig/network-scripts/ifcfg-$1" \
-        && echo "$PIFDEV" )
-}
-
-function xen_pifdev_hwaddr {
-    ( test -e "/etc/sysconfig/network-scripts/ifcfg-$1" \
-        && source "/etc/sysconfig/network-scripts/ifcfg-$1" \
-        && echo "$HWADDR" )
-}
-
-function allow_xen_mgmt_traffic {
-    local mgmt_intf=$(xen_mgmt_intf)
-    test -n "$mgmt_intf" || return
-    # TBD: This needs to be extended to deal with VLANs, etc.
-    local mgmt_pifdev=$(xen_mgmt_pifdev "$mgmt_intf")
-    test -n "$mgmt_pifdev" || return
-    local mgmt_hwaddr=$(xen_pifdev_hwaddr "$mgmt_pifdev")
-    test -n "$mgmt_hwaddr" || return
-    action "Inserting dl_addr $mgmt_hwaddr flows for mgmt intf" true
-    "$dpctl" add-flow "$mgmt_intf" dl_src="$mgmt_hwaddr",idle_timeout=0,priority=0,action=normal
-    "$dpctl" add-flow "$mgmt_intf" dl_dst="$mgmt_hwaddr",idle_timeout=0,priority=0,action=normal
-}
-
-function ifup_dp_intf {
-    for dp in $(dp_list); do
-        local intf=$(dp_intf $dp)
-        if [ -e "/etc/sysconfig/network-scripts/ifcfg-$intf" ]; then
-            action "Bringing up datapath interface: $intf" ifup "$intf"
-        fi
-    done
-}
-
-function turn_on_corefiles {
-    # This has global effect so should not normally be used...
-    ulimit -c unlimited
-    echo "$COREFILE_PATTERN" > /proc/sys/kernel/core_pattern
-}
-
-function remove_all_dp {
-    for dp in $(dp_list); do
-        action "Removing datapath: $dp" "$dpctl" deldp "$dp"
-    done
-}
-
-function insert_modules_if_required {
-    if ! lsmod | grep -q "openvswitch_mod"; then
-        action "Inserting openvswitch module" insmod $VSWITCH_BASE/kernel_modules/openvswitch_mod.ko
-    fi
-    if [ -n "$BRCOMPATD_PIDFILE" ] && ! lsmod | grep -q "brcompat_mod"; then
-        action "Inserting brcompat module" insmod $VSWITCH_BASE/kernel_modules/brcompat_mod.ko
-    fi
-}
-
-function remove_modules {
-    if lsmod | grep -q "brcompat_mod"; then
-        action "Removing brcompat module" rmmod brcompat_mod.ko
-    fi
-    if lsmod | grep -q "openvswitch_mod"; then
-        action "Removing openvswitch module" rmmod openvswitch_mod.ko
-    fi
-}
-
-function reload_vswitchd {
-    if [ -f "$VSWITCHD_PIDFILE" ]; then
-        "$vlogconf" \
-            --target=vswitchd.$(cat "$VSWITCHD_PIDFILE").ctl \
-            --execute=vswitchd/reload
-    fi
-}
-
-function start_vswitchd {
-    local syslog_opt="-vANY:SYSLOG:${VSWITCHD_SYSLOG_LOGLEVEL}"
-    local logfile_file_opt=""
-    local logfile_level_opt=""
-    if [ -n "$VSWITCHD_FILE_LOGLEVEL" ]; then
-        logfile_level_opt="-vANY:FILE:${VSWITCHD_FILE_LOGLEVEL}"
-        logfile_file_opt="--log-file=$VSWITCHD_LOGFILE"
-    fi
-    local leak_opt=""
-    if [ -n "$VSWITCHD_MEMLEAK_LOGFILE" ]; then
-        leak_opt="--check-leaks=$VSWITCHD_MEMLEAK_LOGFILE"
-        if [ -e "$VSWITCHD_MEMLEAK_LOGFILE" ]; then
-            mv "$VSWITCHD_MEMLEAK_LOGFILE" "$VSWITCHD_MEMLEAK_LOGFILE.prev"
-        fi
-    fi
-    local strace_opt=""
-    local daemonize="y"
-    if [ -n "$VSWITCHD_STRACE_LOG" ] && [ -n "$VSWITCHD_VALGRIND_LOG" ]; then
-        printf "Can not start with both VALGRIND and STRACE\n"
-        exit 1
-    fi
-    if [ -n "$VSWITCHD_STRACE_LOG" ]; then
-        strace_opt="strace -o $VSWITCHD_STRACE_LOG $VSWITCHD_STRACE_OPT"
-        daemonize="n"
-    fi
-    if [ -n "$VSWITCHD_VALGRIND_LOG" ]; then
-        valgrind_opt="valgrind --log-file=$VSWITCHD_VALGRIND_LOG $VSWITCHD_VALGRIND_OPT"
-        daemonize="n"
-    fi
-    local fake_proc_net_opt=""
-    if [ "$ENABLE_FAKE_PROC_NET" == "y" ]; then
-        fake_proc_net_opt="--fake-proc-net"
-    fi
-    if [ "$daemonize" != "y" ]; then
-        # Start in background and force a "success" message
-        action "Starting vswitchd ($strace_opt$valgrind_opt)" true
-        (nice -n "$VSWITCHD_PRIORITY" $strace_opt $valgrind_opt "$vswitchd" -P"$VSWITCHD_PIDFILE" -D $fake_proc_net_opt -vANY:CONSOLE:EMER $syslog_opt $logfile_level_opt $logfile_file_opt $leak_opt "$VSWITCHD_CONF") &
-    else
-        action "Starting vswitchd" nice -n "$VSWITCHD_PRIORITY" "$vswitchd" -P"$VSWITCHD_PIDFILE" -D $fake_proc_net_opt -vANY:CONSOLE:EMER $syslog_opt $logfile_level_opt $logfile_file_opt $leak_opt "$VSWITCHD_CONF"
-    fi
-}
-
-function start_brcompatd {
-    local syslog_opt="-vANY:SYSLOG:${BRCOMPATD_SYSLOG_LOGLEVEL}"
-    local logfile_file_opt=""
-    local logfile_level_opt=""
-    if [ -n "$BRCOMPATD_FILE_LOGLEVEL" ]; then
-        logfile_level_opt="-vANY:FILE:${BRCOMPATD_FILE_LOGLEVEL}"
-        logfile_file_opt="--log-file=$BRCOMPATD_LOGFILE"
-    fi
-    local leak_opt=""
-    if [ -n "$BRCOMPATD_MEMLEAK_LOG" ]; then
-        leak_opt="--check-leaks=$BRCOMPATD_MEMLEAK_LOGFILE"
-        if [ -e "$BRCOMPATD_MEMLEAK_LOGFILE" ]; then
-            mv "$BRCOMPATD_MEMLEAK_LOGFILE" "$BRCOMPATD_MEMLEAK_LOGFILE.prev"
-        fi
-    fi
-    local strace_opt=""
-    local daemonize="y"
-    if [ -n "$BRCOMPATD_STRACE_LOG" ] && [ -n "$BRCOMPATD_VALGRIND_LOG" ]; then
-        printf "Can not start with both VALGRIND and STRACE\n"
-        exit 1
-    fi
-    if [ -n "$BRCOMPATD_STRACE_LOG" ]; then
-        strace_opt="strace -o $BRCOMPATD_STRACE_LOG $BRCOMPATD_STRACE_OPT"
-        daemonize="n"
-    fi
-    if [ -n "$VALGRIND_LOG" ]; then
-        valgrind_opt="valgrind --log-file=$BRCOMPATD_VALGRIND_LOG $BRCOMPATD_VALGRIND_OPT"
-        daemonize="n"
-    fi
-    if [ "$daemonize" != "y" ]; then
-        # Start in background and force a "success" message
-        action "Starting brcompatd ($strace_opt$valgrind_opt)" true
-        (nice -n "$VSWITCHD_PRIORITY" $strace_opt $valgrind_opt "$brcompatd" -P$BRCOMPATD_PIDFILE --vswitchd-pidfile=$VSWITCHD_PIDFILE -vANY:CONSOLE:EMER $syslog_opt $logfile_level_opt $logfile_file_opt $leak_opt "$VSWITCHD_CONF") &
-    else
-        action "Starting brcompatd" nice -n "$BRCOMPATD_PRIORITY" $strace_opt $valgrind_opt "$brcompatd" -P$BRCOMPATD_PIDFILE --vswitchd-pidfile=$VSWITCHD_PIDFILE -D -vANY:CONSOLE:EMER $syslog_opt $logfile_level_opt $logfile_file_opt $leak_opt "$VSWITCHD_CONF"
-    fi
-}
-
-function stop_vswitchd {
-    if [ -f "$VSWITCHD_PIDFILE" ]; then
-        local pid=$(cat "$VSWITCHD_PIDFILE")
-        action "Killing vswitchd ($pid)" kill -TERM $pid
-        rm -f "$VSWITCHD_PIDFILE"
-    fi
-}
-
-function stop_brcompatd {
-    if [ -f "$BRCOMPATD_PIDFILE" ]; then
-        local pid=$(cat "$BRCOMPATD_PIDFILE")
-        action "Killing brcompatd ($pid)" kill -TERM $pid
-        rm -f "$BRCOMPATD_PIDFILE"
-    fi
-}
-
-function restart_approval {
-    cat <<EOF
-
-WARNING!!!
-
-Restarting vswitch on a live server is not guaranteed to work.  It is
-provided as a convenience for those situations in which it does work.
-If you just want to reload the configuration file, use "reload"
-instead of restart.
-
-EOF
-    read -s -r -n 1 -p "Countinue with restart (y/N): " response
-    printf "\n"
-    case "$response" in
-        y|Y)
-            return 0
-            ;;
-        *)
-            return 1
-            ;;
-    esac
-}
-
-function start {
-    insert_modules_if_required
-    start_vswitchd
-    start_brcompatd
-    reload_vswitchd  # ensures vswitchd has fully read config file.
-    #allow_xen_mgmt_traffic   # Seems to work okay without...
-}
-
-function stop_unload {
-    stop_brcompatd
-    ifdown_dp_intf
-    remove_all_dp
-    stop_vswitchd
-    remove_modules
-}
-
-function stop {
-    stop_brcompatd
-    stop_vswitchd
-}
-
-function restart_unload {
-    if restart_approval; then
-        stop_unload
-        insert_modules_if_required
-        start_vswitchd
-        reload_vswitchd
-        ifup_dp_intf
-        start_brcompatd
-    fi
-}
-
-function restart {
-    if restart_approval; then
-        stop
-        start
-    fi
-}
-
-case "$1" in
-    start)
-        if [ "$FORCE_COREFILES" == "y" ]; then
-            turn_on_corefiles
-        fi
-        start
-        ;;
-    stop)
-        stop
-        ;;
-    restart)
-        restart
-        ;;
-    reload)
-        reload_vswitchd
-        ;;
-    strace-vswitchd)
-        shift
-        strace -p $(cat "$VSWITCHD_PIDFILE") "$@"
-        ;;
-    strace-brcompatd)
-        shift
-        strace -p $(cat "$BRCOMPATD_PIDFILE") "$@"
-        ;;
-    unload)
-        stop_unload
-        ;;
-    update-modules)
-        restart_unload
-        ;;
-    status)
-        status -p vswitchd.pid vswitchd
-        status -p brcompatd.pid brcompatd
-        ;;
-    version)
-        "$VSWITCH_BASE"/sbin/vswitchd -V
-        "$VSWITCH_BASE"/sbin/brcompatd -V
-        ;;
-    help)
-        printf "vswitch [start|stop|restart|reload|unload|status|version]\n"
-        ;;
-    *)
-        printf "Unknown command: $1\n"
-        exit 1
-        ;;
-esac
diff --git a/vswitchd/etc/logrotate.d/vswitch b/vswitchd/etc/logrotate.d/vswitch
deleted file mode 100644 (file)
index 97e0e79..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/var/log/vswitchd.log {
-       sharedscripts
-       postrotate
-        # Send sighup to vswitch which will cause it to reopen its log files.
-        /sbin/service vswitch reload
-       endscript
-}
diff --git a/vswitchd/etc/profile.d/vswitch.sh b/vswitchd/etc/profile.d/vswitch.sh
deleted file mode 100644 (file)
index 79f57c3..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-PATH=/root/vswitch/bin:$PATH
-export PATH
-MANPATH=/root/vswitch/share/man:$MANPATH
-export MANPATH
-
-alias vswitch='service vswitch'
-
-function watchconf {
-    watch cat /etc/vswitchd.conf
-}
-
-function watchdp {
-       watch dpctl dp-show "$@"
-}
-
-function watchdpflows {
-       local grep=""
-       local dp=$1
-       shift
-       if [ $# -gt 0 ]; then
-               grep="| grep $@"
-       fi
-       watch "dpctl dp-dump-flows $dp $grep"
-}
-
-function watchflows {
-       local grep=""
-       local dp=$1
-       shift
-       bridge=$(dpctl dp-show $dp | grep 'port 0:' | cut -d' ' -f 3)
-       if [ $# -gt 0 ]; then
-               grep="| grep $@"
-       fi
-       watch "dpctl dump-flows unix:/var/run/$bridge.mgmt $grep"
-}
-
-function monitorlogs {
-    local grep=""
-    if [ $# -gt 0 ]; then
-        grep="| grep --line-buffered '^==> .* <==$"
-        for i in "$@"; do
-            grep="$grep\|$i"
-        done
-        grep="$grep'"
-    fi
-    cmd="tail -F /var/log/messages /var/log/vswitchd.log /var/log/xensource.log $grep | tee /var/log/monitorlogs.out"
-    printf "cmd: $cmd\n"
-    eval "$cmd"
-}
diff --git a/vswitchd/etc/sysconfig/vswitch.example b/vswitchd/etc/sysconfig/vswitch.example
deleted file mode 100644 (file)
index 6600d15..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-### Configuration options for vswitch
-
-# VSWITCH_BASE: Root directory where vswitch binaries are installed
-# VSWITCH_BASE=/root/vswitch/openvswitch/build
-
-# ENABLE_BRCOMPAT: If 'y' than emulate linux bridging interfaces
-#    using the brcompat kernel module and brcompatd daemon
-# ENABLE_BRCOMPAT=y
-
-# ENABLE_FAKE_PROC_NET: If 'y' then emulate linux bonding and vlan
-#    files in /proc as if the bonding and vlan demultiplexing done in
-#    vswitchd were being implemented using existing Linux mechanisms.
-#    This is useful in some cases when replacing existing solutions.
-# ENABLE_FAKE_PROC_NET=y
-
-# FORCE_COREFILES: If 'y' then core files will be enabled.
-# FORCE_COREFILES=n
-
-# COREFILE_PATTERN: Pattern used to determine path and filename for
-#     core files when FORCE_COREFILES is 'y'.  This is Linux specific.
-#     See the manpage for "core".
-# COREFILE_PATTERN="/var/log/%e-%t"
-
-# VSWITCHD_CONF: File in which vswitchd stores its configuration.
-# VSWITCHD_CONF=/etc/vswitchd.conf
-
-# VSWITCHD_PIDFILE: File in which to store the pid of the running
-#     vswitchd.
-# VSWITCHD_PIDFILE=/var/run/vswitchd.pid
-
-# VSWITCHD_PRIORITY: "nice" priority at which to run vswitchd and related
-#     processes.
-# VSWITCHD_PRIORITY=-5
-
-# VSWITCHD_LOGFILE: File to send the FILE_LOGLEVEL log messages to.
-# VSWITCHD_LOGFILE=/var/log/vswitchd.log
-
-# VSWITCHD_FILE_LOGLEVEL: Log level at which to log into the
-#     VSWITCHD_LOG file.  If this is null or not set the logfile will
-#     not be created and nothing will be sent to it.  This is the
-#     default.  The available options are: EMER, WARN, INFO and DBG.
-# VSWITCHD_FILE_LOGLEVEL=""
-
-# VSWITCHD_SYSLOG_LOGLEVEL: Log level at which to log into syslog.  If
-#     this is null or not set the default is to log to syslog
-#     emergency and warning level messages only.
-# VSWITCHD_SYSLOG_LOGLEVEL="WARN"
-
-# BRCOMPATD_PIDFILE: File in which to store the pid of the running
-#     brcompatd (the Linux bridge compatibility daemon for vswitchd).
-#     If this is the empty string, brcompatd will not be started and
-#     the brcompat_mod kernel module will not be inserted.  Note that
-#     the default is to use brcompat!
-# BRCOMPATD_PIDFILE=/var/run/brcompatd.pid
-
-# BRCOMPATD_PRIORITY: "nice" priority at which to run vswitchd and related
-#     processes.
-# BRCOMPATD_PRIORITY=-5
-
-# BRCOMPATD_LOGFILE: File to send the FILE_LOGLEVEL log messages to.
-# BRCOMPATD_LOGFILE=/var/log/brcompatd.log
-
-# BRCOMPATD_FILE_LOGLEVEL: Log level at which to log into the
-#     BRCOMPATD_LOG file.  If this is null or not set the logfile will
-#     not be created and nothing will be sent to it.  This is the
-#     default.  The available options are: EMER, WARN, INFO and DBG.
-# BRCOMPATD_FILE_LOGLEVEL=""
-
-# BRCOMPATD_SYSLOG_LOGLEVEL: Log level at which to log into syslog.  If
-#     this is null or not set the default is to log to syslog
-#     emergency and warning level messages only.
-# BRCOMPATD_SYSLOG_LOGLEVEL="WARN"
diff --git a/xenserver/README b/xenserver/README
new file mode 100644 (file)
index 0000000..7088e27
--- /dev/null
@@ -0,0 +1,78 @@
+This directory contains files for seamless integration of vswitch on
+Citrix XenServer hosts managed by the Citrix management tools.
+
+Some of these files are modifications of Citrix's proprietary code.
+Citrix has given permission to distribute these modified files.
+Citrix has not specified a particular license for them.  There is no
+guarantee that, should Citrix specify a license, that it would be
+DFSG-compliant or GPL-compatible.
+
+Most of the files in this directory is installed on a XenServer system
+under the same name, if underscores are replaced by slashes.  The
+files are:
+
+    etc_init.d_vswitch
+
+        Initializes the vswitch at boot and shuts it down at shutdown.
+
+    etc_init.d_vswitch-xapi-update
+
+        Init script to ensure vswitch-cfg-update is called for the
+        current host at boot.
+
+    etc_logrotate.d_vswitch
+
+        Ensures that /var/log/vswitchd.log is rotated periodically and
+        that vswitch reopens its log file at that point.
+
+    etc_profile.d_vswitch.sh
+
+        vswitch-related shell functions for the administrator's
+        convenience.
+
+    etc_sysconfig_vswitch.example
+
+        Example configuration options for vswitch.
+
+    etc_xapi.d_plugins_vswitch-cfg-update
+
+        xapi plugin script to update the cache of configuration items
+        in the vswitchd configuration file that are managed in the
+        xapi database when integrated with Citrix management tools.
+
+    etc_xensource_scripts_vif
+
+        vswitch-aware replacement for Citrix script of the same name.
+
+    opt_xensource_libexec_interface-reconfigure
+
+        vswitch-aware replacement for Citrix script of the same name.
+
+    usr_lib_xsconsole_plugins-base_XSFeatureNiciraVSwitch.py
+
+        xsconsole plugin to configure the pool-wide configuration keys
+        used to control vswitch when integrated with Citrix management
+        tools.
+
+    vswitch-xen.spec
+
+        spec file for building RPMs to install on a XenServer host.
+
+To install, build the vswitch RPM with a command like this:
+
+        rpmbuild -D "vswitch_version $full_version" \
+                -D "xen_version $XENKERNEL" \
+                -D "build_number --with-build-number=$buildnr" \
+                -bb vswitch-xen.spec
+
+Then, "rpm -U" the resulting vswitch package on the XenServer hosts in
+question and reboot them.  (The vswitch-dbg package that is also
+produced need not be installed, but it is harmless to do so.)
+
+----------------------------------------------------------------------
+Copyright (C) 2009 Nicira Networks, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.  This file is offered as-is,
+without warranty of any kind.
diff --git a/xenserver/automake.mk b/xenserver/automake.mk
new file mode 100644 (file)
index 0000000..e7a1340
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright (C) 2009 Nicira Networks, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.  This file is offered as-is,
+# without warranty of any kind.
+
+EXTRA_DIST += \
+       xenserver/README \
+       xenserver/etc_init.d_vswitch \
+       xenserver/etc_init.d_vswitch-xapi-update \
+       xenserver/etc_logrotate.d_vswitch \
+       xenserver/etc_profile.d_vswitch.sh \
+       xenserver/etc_sysconfig_vswitch.example \
+       xenserver/etc_xapi.d_plugins_vswitch-cfg-update \
+       xenserver/etc_xensource_scripts_vif \
+       xenserver/opt_xensource_libexec_interface-reconfigure \
+       xenserver/usr_lib_xsconsole_plugins-base_XSFeatureNiciraVSwitch.py \
+       xenserver/vswitch-xen.spec
diff --git a/xenserver/etc_init.d_vswitch b/xenserver/etc_init.d_vswitch
new file mode 100755 (executable)
index 0000000..19fd2cd
--- /dev/null
@@ -0,0 +1,376 @@
+#!/bin/bash
+#
+# vswitch
+#
+# chkconfig: 2345 09 91
+# description: Manage vswitch kernel modules and user-space daemon
+
+# Copyright (C) 2009 Nicira Networks, Inc.
+#
+# 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. /etc/init.d/functions
+
+test -e /etc/sysconfig/vswitch && . /etc/sysconfig/vswitch
+
+# General config variables in /etc/sysconfig/vswitch
+VSWITCH_BASE="${VSWITCH_BASE:-/root/vswitch}"
+ENABLE_BRCOMPAT="${ENABLE_BRCOMPAT:-y}"
+ENABLE_FAKE_PROC_NET="${ENABLE_FAKE_PROC_NET:-y}"
+FORCE_COREFILES="${FORCE_COREFILES:-n}"
+COREFILE_PATTERN="${COREFILE_PATTERN:-/var/log/%e-%t}"
+
+# Config variables specific to vswitchd
+VSWITCHD_CONF="${VSWITCHD_CONF:-/etc/vswitchd.conf}"
+VSWITCHD_PIDFILE="${VSWITCHD_PIDFILE:-/var/run/vswitchd.pid}"
+VSWITCHD_PRIORITY="${VSWITCHD_PRIORITY:--5}"
+VSWITCHD_LOGFILE="${VSWITCHD_LOGFILE:-/var/log/vswitchd.log}"
+VSWITCHD_FILE_LOGLEVEL="${VSWITCHD_FILE_LOGLEVEL:-}"
+VSWITCHD_SYSLOG_LOGLEVEL="${VSWITCHD_SYSLOG_LOGLEVEL:-WARN}"
+VSWITCHD_MEMLEAK_LOGFILE="${VSWITCHD_MEMLEAK_LOGFILE:-}"
+VSWITCHD_STRACE_LOG="${VSWITCHD_STRACE_LOG:-}"
+VSWITCHD_STRACE_OPT="${VSWITCHD_STRACE_OPT:-}"
+VSWITCHD_VALGRIND_LOG="${VSWITCHD_VALGRIND_LOG:-}"
+VSWITCHD_VALGRIND_OPT="${VSWITCHD_VALGRIND_OPT:-}"
+
+# Config variables specific brcompatd
+BRCOMPATD_PIDFILE="${BRCOMPATD_PIDFILE:-/var/run/brcompatd.pid}"
+BRCOMPATD_PRIORITY="${BRCOMPATD_PRIORITY:--5}"
+BRCOMPATD_LOGFILE="${BRCOMPATD_LOGFILE:-/var/log/brcompatd.log}"
+BRCOMPATD_FILE_LOGLEVEL="${BRCOMPATD_FILE_LOGLEVEL:-}"
+BRCOMPATD_SYSLOG_LOGLEVEL="${BRCOMPATD_SYSLOG_LOGLEVEL:-WARN}"
+BRCOMPATD_MEMLEAK_LOGFILE="${BRCOMPATD_MEMLEAK_LOGFILE:-}"
+BRCOMPATD_STRACE_LOG="${BRCOMPATD_STRACE_LOG:-}"
+BRCOMPATD_STRACE_OPT="${BRCOMPATD_STRACE_OPT:-}"
+BRCOMPATD_VALGRIND_LOG="${BRCOMPATD_VALGRIND_LOG:-}"
+BRCOMPATD_VALGRIND_OPT="${BRCOMPATD_VALGRIND_OPT:-}"
+
+
+
+
+# Full paths to executables & modules
+vswitchd="$VSWITCH_BASE/sbin/vswitchd"
+brcompatd="$VSWITCH_BASE/sbin/brcompatd"
+dpctl="$VSWITCH_BASE/bin/dpctl"
+vlogconf="$VSWITCH_BASE/bin/vlogconf"
+
+
+if [ "$ENABLE_FAKE_PROC_NET" == "y" ]; then
+    if [ "$ENABLE_BRCOMPAT" != "y" ]; then
+        warning "FAKE_PROC_NET required BRCOMPAT which was disabled.  Force enabling."
+        ENABLE_BRCOMPAT="y"
+    fi
+fi
+
+function dp_list {
+    "$dpctl" dp-show | grep '^dp[0-9]\+:' | cut -d':' -f 1
+}
+
+function dp_intf {
+    local dp=$1
+    # Currently port0 is hardcoded to be the local port.
+    "$dpctl" dp-show $dp | grep 'port 0:' | cut -d' ' -f 3
+}
+
+function ifdown_dp_intf {
+    for dp in $(dp_list); do
+        local intf=$(dp_intf $dp)
+        if [ -e "/etc/sysconfig/network-scripts/ifcfg-$intf" ]; then
+            action "Bringing down datapath interface: $intf" ifdown "$intf"
+        fi
+    done
+}
+
+function xen_mgmt_intf {
+    ( test -e /etc/xensource-inventory \
+        && source /etc/xensource-inventory \
+        && echo "$MANAGEMENT_INTERFACE" )
+}
+
+function xen_mgmt_pifdev {
+    ( test -e "/etc/sysconfig/network-scripts/ifcfg-$1" \
+        && source "/etc/sysconfig/network-scripts/ifcfg-$1" \
+        && echo "$PIFDEV" )
+}
+
+function xen_pifdev_hwaddr {
+    ( test -e "/etc/sysconfig/network-scripts/ifcfg-$1" \
+        && source "/etc/sysconfig/network-scripts/ifcfg-$1" \
+        && echo "$HWADDR" )
+}
+
+function allow_xen_mgmt_traffic {
+    local mgmt_intf=$(xen_mgmt_intf)
+    test -n "$mgmt_intf" || return
+    # TBD: This needs to be extended to deal with VLANs, etc.
+    local mgmt_pifdev=$(xen_mgmt_pifdev "$mgmt_intf")
+    test -n "$mgmt_pifdev" || return
+    local mgmt_hwaddr=$(xen_pifdev_hwaddr "$mgmt_pifdev")
+    test -n "$mgmt_hwaddr" || return
+    action "Inserting dl_addr $mgmt_hwaddr flows for mgmt intf" true
+    "$dpctl" add-flow "$mgmt_intf" dl_src="$mgmt_hwaddr",idle_timeout=0,priority=0,action=normal
+    "$dpctl" add-flow "$mgmt_intf" dl_dst="$mgmt_hwaddr",idle_timeout=0,priority=0,action=normal
+}
+
+function ifup_dp_intf {
+    for dp in $(dp_list); do
+        local intf=$(dp_intf $dp)
+        if [ -e "/etc/sysconfig/network-scripts/ifcfg-$intf" ]; then
+            action "Bringing up datapath interface: $intf" ifup "$intf"
+        fi
+    done
+}
+
+function turn_on_corefiles {
+    # This has global effect so should not normally be used...
+    ulimit -c unlimited
+    echo "$COREFILE_PATTERN" > /proc/sys/kernel/core_pattern
+}
+
+function remove_all_dp {
+    for dp in $(dp_list); do
+        action "Removing datapath: $dp" "$dpctl" deldp "$dp"
+    done
+}
+
+function insert_modules_if_required {
+    if ! lsmod | grep -q "openvswitch_mod"; then
+        action "Inserting openvswitch module" insmod $VSWITCH_BASE/kernel_modules/openvswitch_mod.ko
+    fi
+    if [ -n "$BRCOMPATD_PIDFILE" ] && ! lsmod | grep -q "brcompat_mod"; then
+        action "Inserting brcompat module" insmod $VSWITCH_BASE/kernel_modules/brcompat_mod.ko
+    fi
+}
+
+function remove_modules {
+    if lsmod | grep -q "brcompat_mod"; then
+        action "Removing brcompat module" rmmod brcompat_mod.ko
+    fi
+    if lsmod | grep -q "openvswitch_mod"; then
+        action "Removing openvswitch module" rmmod openvswitch_mod.ko
+    fi
+}
+
+function reload_vswitchd {
+    if [ -f "$VSWITCHD_PIDFILE" ]; then
+        "$vlogconf" \
+            --target=vswitchd.$(cat "$VSWITCHD_PIDFILE").ctl \
+            --execute=vswitchd/reload
+    fi
+}
+
+function start_vswitchd {
+    local syslog_opt="-vANY:SYSLOG:${VSWITCHD_SYSLOG_LOGLEVEL}"
+    local logfile_file_opt=""
+    local logfile_level_opt=""
+    if [ -n "$VSWITCHD_FILE_LOGLEVEL" ]; then
+        logfile_level_opt="-vANY:FILE:${VSWITCHD_FILE_LOGLEVEL}"
+        logfile_file_opt="--log-file=$VSWITCHD_LOGFILE"
+    fi
+    local leak_opt=""
+    if [ -n "$VSWITCHD_MEMLEAK_LOGFILE" ]; then
+        leak_opt="--check-leaks=$VSWITCHD_MEMLEAK_LOGFILE"
+        if [ -e "$VSWITCHD_MEMLEAK_LOGFILE" ]; then
+            mv "$VSWITCHD_MEMLEAK_LOGFILE" "$VSWITCHD_MEMLEAK_LOGFILE.prev"
+        fi
+    fi
+    local strace_opt=""
+    local daemonize="y"
+    if [ -n "$VSWITCHD_STRACE_LOG" ] && [ -n "$VSWITCHD_VALGRIND_LOG" ]; then
+        printf "Can not start with both VALGRIND and STRACE\n"
+        exit 1
+    fi
+    if [ -n "$VSWITCHD_STRACE_LOG" ]; then
+        strace_opt="strace -o $VSWITCHD_STRACE_LOG $VSWITCHD_STRACE_OPT"
+        daemonize="n"
+    fi
+    if [ -n "$VSWITCHD_VALGRIND_LOG" ]; then
+        valgrind_opt="valgrind --log-file=$VSWITCHD_VALGRIND_LOG $VSWITCHD_VALGRIND_OPT"
+        daemonize="n"
+    fi
+    local fake_proc_net_opt=""
+    if [ "$ENABLE_FAKE_PROC_NET" == "y" ]; then
+        fake_proc_net_opt="--fake-proc-net"
+    fi
+    if [ "$daemonize" != "y" ]; then
+        # Start in background and force a "success" message
+        action "Starting vswitchd ($strace_opt$valgrind_opt)" true
+        (nice -n "$VSWITCHD_PRIORITY" $strace_opt $valgrind_opt "$vswitchd" -P"$VSWITCHD_PIDFILE" -D $fake_proc_net_opt -vANY:CONSOLE:EMER $syslog_opt $logfile_level_opt $logfile_file_opt $leak_opt "$VSWITCHD_CONF") &
+    else
+        action "Starting vswitchd" nice -n "$VSWITCHD_PRIORITY" "$vswitchd" -P"$VSWITCHD_PIDFILE" -D $fake_proc_net_opt -vANY:CONSOLE:EMER $syslog_opt $logfile_level_opt $logfile_file_opt $leak_opt "$VSWITCHD_CONF"
+    fi
+}
+
+function start_brcompatd {
+    local syslog_opt="-vANY:SYSLOG:${BRCOMPATD_SYSLOG_LOGLEVEL}"
+    local logfile_file_opt=""
+    local logfile_level_opt=""
+    if [ -n "$BRCOMPATD_FILE_LOGLEVEL" ]; then
+        logfile_level_opt="-vANY:FILE:${BRCOMPATD_FILE_LOGLEVEL}"
+        logfile_file_opt="--log-file=$BRCOMPATD_LOGFILE"
+    fi
+    local leak_opt=""
+    if [ -n "$BRCOMPATD_MEMLEAK_LOG" ]; then
+        leak_opt="--check-leaks=$BRCOMPATD_MEMLEAK_LOGFILE"
+        if [ -e "$BRCOMPATD_MEMLEAK_LOGFILE" ]; then
+            mv "$BRCOMPATD_MEMLEAK_LOGFILE" "$BRCOMPATD_MEMLEAK_LOGFILE.prev"
+        fi
+    fi
+    local strace_opt=""
+    local daemonize="y"
+    if [ -n "$BRCOMPATD_STRACE_LOG" ] && [ -n "$BRCOMPATD_VALGRIND_LOG" ]; then
+        printf "Can not start with both VALGRIND and STRACE\n"
+        exit 1
+    fi
+    if [ -n "$BRCOMPATD_STRACE_LOG" ]; then
+        strace_opt="strace -o $BRCOMPATD_STRACE_LOG $BRCOMPATD_STRACE_OPT"
+        daemonize="n"
+    fi
+    if [ -n "$VALGRIND_LOG" ]; then
+        valgrind_opt="valgrind --log-file=$BRCOMPATD_VALGRIND_LOG $BRCOMPATD_VALGRIND_OPT"
+        daemonize="n"
+    fi
+    if [ "$daemonize" != "y" ]; then
+        # Start in background and force a "success" message
+        action "Starting brcompatd ($strace_opt$valgrind_opt)" true
+        (nice -n "$VSWITCHD_PRIORITY" $strace_opt $valgrind_opt "$brcompatd" -P$BRCOMPATD_PIDFILE --vswitchd-pidfile=$VSWITCHD_PIDFILE -vANY:CONSOLE:EMER $syslog_opt $logfile_level_opt $logfile_file_opt $leak_opt "$VSWITCHD_CONF") &
+    else
+        action "Starting brcompatd" nice -n "$BRCOMPATD_PRIORITY" $strace_opt $valgrind_opt "$brcompatd" -P$BRCOMPATD_PIDFILE --vswitchd-pidfile=$VSWITCHD_PIDFILE -D -vANY:CONSOLE:EMER $syslog_opt $logfile_level_opt $logfile_file_opt $leak_opt "$VSWITCHD_CONF"
+    fi
+}
+
+function stop_vswitchd {
+    if [ -f "$VSWITCHD_PIDFILE" ]; then
+        local pid=$(cat "$VSWITCHD_PIDFILE")
+        action "Killing vswitchd ($pid)" kill -TERM $pid
+        rm -f "$VSWITCHD_PIDFILE"
+    fi
+}
+
+function stop_brcompatd {
+    if [ -f "$BRCOMPATD_PIDFILE" ]; then
+        local pid=$(cat "$BRCOMPATD_PIDFILE")
+        action "Killing brcompatd ($pid)" kill -TERM $pid
+        rm -f "$BRCOMPATD_PIDFILE"
+    fi
+}
+
+function restart_approval {
+    cat <<EOF
+
+WARNING!!!
+
+Restarting vswitch on a live server is not guaranteed to work.  It is
+provided as a convenience for those situations in which it does work.
+If you just want to reload the configuration file, use "reload"
+instead of restart.
+
+EOF
+    read -s -r -n 1 -p "Countinue with restart (y/N): " response
+    printf "\n"
+    case "$response" in
+        y|Y)
+            return 0
+            ;;
+        *)
+            return 1
+            ;;
+    esac
+}
+
+function start {
+    insert_modules_if_required
+    start_vswitchd
+    start_brcompatd
+    reload_vswitchd  # ensures vswitchd has fully read config file.
+    #allow_xen_mgmt_traffic   # Seems to work okay without...
+}
+
+function stop_unload {
+    stop_brcompatd
+    ifdown_dp_intf
+    remove_all_dp
+    stop_vswitchd
+    remove_modules
+}
+
+function stop {
+    stop_brcompatd
+    stop_vswitchd
+}
+
+function restart_unload {
+    if restart_approval; then
+        stop_unload
+        insert_modules_if_required
+        start_vswitchd
+        reload_vswitchd
+        ifup_dp_intf
+        start_brcompatd
+    fi
+}
+
+function restart {
+    if restart_approval; then
+        stop
+        start
+    fi
+}
+
+case "$1" in
+    start)
+        if [ "$FORCE_COREFILES" == "y" ]; then
+            turn_on_corefiles
+        fi
+        start
+        ;;
+    stop)
+        stop
+        ;;
+    restart)
+        restart
+        ;;
+    reload)
+        reload_vswitchd
+        ;;
+    strace-vswitchd)
+        shift
+        strace -p $(cat "$VSWITCHD_PIDFILE") "$@"
+        ;;
+    strace-brcompatd)
+        shift
+        strace -p $(cat "$BRCOMPATD_PIDFILE") "$@"
+        ;;
+    unload)
+        stop_unload
+        ;;
+    update-modules)
+        restart_unload
+        ;;
+    status)
+        status -p vswitchd.pid vswitchd
+        status -p brcompatd.pid brcompatd
+        ;;
+    version)
+        "$VSWITCH_BASE"/sbin/vswitchd -V
+        "$VSWITCH_BASE"/sbin/brcompatd -V
+        ;;
+    help)
+        printf "vswitch [start|stop|restart|reload|unload|status|version]\n"
+        ;;
+    *)
+        printf "Unknown command: $1\n"
+        exit 1
+        ;;
+esac
diff --git a/xenserver/etc_init.d_vswitch-xapi-update b/xenserver/etc_init.d_vswitch-xapi-update
new file mode 100755 (executable)
index 0000000..cd6e7d1
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/bash
+#
+# vswitch-xapi-update
+#
+# chkconfig: 2345 95 01
+# description: Update vswitch configuration from XAPI database at boot
+
+# Copyright (C) 2009 Nicira Networks, Inc.
+#
+# 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. /etc/init.d/functions
+
+test -e /etc/sysconfig/vswitch && . /etc/sysconfig/vswitch
+VSWITCH_BASE="${VSWITCH_BASE:-/root/vswitch}"
+VSWITCHD_CONF="${VSWITCHD_CONF:-/etc/vswitchd.conf}"
+VSWITCHD_PIDFILE="${VSWITCHD_PIDFILE:-/var/run/vswitchd.pid}"
+VSWITCHD_PRIORITY="${VSWITCHD_PRIORITY:--5}"
+VSWITCHD_LOGFILE="${VSWITCHD_LOGFILE:-/var/log/vswitchd.log}"
+VSWITCHD_FILE_LOGLEVEL="${VSWITCHD_FILE_LOGLEVEL:-}"
+VSWITCHD_SYSLOG_LOGLEVEL="${VSWITCHD_SYSLOG_LOGLEVEL:-WARN}"
+VSWITCHD_MEMLEAK_LOGFILE="${VSWITCHD_MEMLEAK_LOGFILE:-}"
+BRCOMPATD_PIDFILE="${BRCOMPATD_PIDFILE:-/var/run/brcompatd.pid}"
+BRCOMPATD_PRIORITY="${BRCOMPATD_PRIORITY:--5}"
+BRCOMPATD_LOGFILE="${BRCOMPATD_LOGFILE:-/var/log/brcompatd.log}"
+BRCOMPATD_FILE_LOGLEVEL="${BRCOMPATD_FILE_LOGLEVEL:-}"
+BRCOMPATD_SYSLOG_LOGLEVEL="${BRCOMPATD_SYSLOG_LOGLEVEL:-WARN}"
+BRCOMPATD_MEMLEAK_LOGFILE="${BRCOMPATD_MEMLEAK_LOGFILE:-}"
+
+function do_host_call {
+    xe host-call-plugin host-uuid="$INSTALLATION_UUID" plugin="vswitch-cfg-update" fn="update" >/dev/null
+}
+
+function start {
+    if [ ! -f /etc/xensource-inventory ]; then
+        printf "vxwitch-xapi-update ERROR: XenSource inventory not present in /etc/xensource-inventory\n"
+        exit 1
+    fi
+    source /etc/xensource-inventory
+    action "Updating configuration" do_host_call
+}
+
+case "$1" in
+    start)
+        start
+        ;;
+    stop)
+        # Nothing to do here.
+        ;;
+    restart)
+        start
+        ;;
+    help)
+        printf "vswitch [start|stop|restart]\n"
+        ;;
+    *)
+        printf "Unknown command: $1\n"
+        exit 1
+        ;;
+esac
diff --git a/xenserver/etc_logrotate.d_vswitch b/xenserver/etc_logrotate.d_vswitch
new file mode 100644 (file)
index 0000000..13586ce
--- /dev/null
@@ -0,0 +1,14 @@
+# Copyright (C) 2009 Nicira Networks, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.  This file is offered as-is,
+# without warranty of any kind.
+
+/var/log/vswitchd.log {
+       sharedscripts
+       postrotate
+        # Send sighup to vswitch which will cause it to reopen its log files.
+        /sbin/service vswitch reload
+       endscript
+}
diff --git a/xenserver/etc_profile.d_vswitch.sh b/xenserver/etc_profile.d_vswitch.sh
new file mode 100644 (file)
index 0000000..1b69179
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright (C) 2009 Nicira Networks, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.  This file is offered as-is,
+# without warranty of any kind.
+
+PATH=/root/vswitch/bin:$PATH
+export PATH
+MANPATH=/root/vswitch/share/man:$MANPATH
+export MANPATH
+
+alias vswitch='service vswitch'
+
+function watchconf {
+    watch cat /etc/vswitchd.conf
+}
+
+function watchdp {
+       watch dpctl dp-show "$@"
+}
+
+function watchdpflows {
+       local grep=""
+       local dp=$1
+       shift
+       if [ $# -gt 0 ]; then
+               grep="| grep $@"
+       fi
+       watch "dpctl dp-dump-flows $dp $grep"
+}
+
+function watchflows {
+       local grep=""
+       local dp=$1
+       shift
+       bridge=$(dpctl dp-show $dp | grep 'port 0:' | cut -d' ' -f 3)
+       if [ $# -gt 0 ]; then
+               grep="| grep $@"
+       fi
+       watch "dpctl dump-flows unix:/var/run/$bridge.mgmt $grep"
+}
+
+function monitorlogs {
+    local grep=""
+    if [ $# -gt 0 ]; then
+        grep="| grep --line-buffered '^==> .* <==$"
+        for i in "$@"; do
+            grep="$grep\|$i"
+        done
+        grep="$grep'"
+    fi
+    cmd="tail -F /var/log/messages /var/log/vswitchd.log /var/log/xensource.log $grep | tee /var/log/monitorlogs.out"
+    printf "cmd: $cmd\n"
+    eval "$cmd"
+}
diff --git a/xenserver/etc_sysconfig_vswitch.example b/xenserver/etc_sysconfig_vswitch.example
new file mode 100644 (file)
index 0000000..bdebf84
--- /dev/null
@@ -0,0 +1,79 @@
+### Configuration options for vswitch
+
+# Copyright (C) 2009 Nicira Networks, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.  This file is offered as-is,
+# without warranty of any kind.
+
+# VSWITCH_BASE: Root directory where vswitch binaries are installed
+# VSWITCH_BASE=/root/vswitch/openvswitch/build
+
+# ENABLE_BRCOMPAT: If 'y' than emulate linux bridging interfaces
+#    using the brcompat kernel module and brcompatd daemon
+# ENABLE_BRCOMPAT=y
+
+# ENABLE_FAKE_PROC_NET: If 'y' then emulate linux bonding and vlan
+#    files in /proc as if the bonding and vlan demultiplexing done in
+#    vswitchd were being implemented using existing Linux mechanisms.
+#    This is useful in some cases when replacing existing solutions.
+# ENABLE_FAKE_PROC_NET=y
+
+# FORCE_COREFILES: If 'y' then core files will be enabled.
+# FORCE_COREFILES=n
+
+# COREFILE_PATTERN: Pattern used to determine path and filename for
+#     core files when FORCE_COREFILES is 'y'.  This is Linux specific.
+#     See the manpage for "core".
+# COREFILE_PATTERN="/var/log/%e-%t"
+
+# VSWITCHD_CONF: File in which vswitchd stores its configuration.
+# VSWITCHD_CONF=/etc/vswitchd.conf
+
+# VSWITCHD_PIDFILE: File in which to store the pid of the running
+#     vswitchd.
+# VSWITCHD_PIDFILE=/var/run/vswitchd.pid
+
+# VSWITCHD_PRIORITY: "nice" priority at which to run vswitchd and related
+#     processes.
+# VSWITCHD_PRIORITY=-5
+
+# VSWITCHD_LOGFILE: File to send the FILE_LOGLEVEL log messages to.
+# VSWITCHD_LOGFILE=/var/log/vswitchd.log
+
+# VSWITCHD_FILE_LOGLEVEL: Log level at which to log into the
+#     VSWITCHD_LOG file.  If this is null or not set the logfile will
+#     not be created and nothing will be sent to it.  This is the
+#     default.  The available options are: EMER, WARN, INFO and DBG.
+# VSWITCHD_FILE_LOGLEVEL=""
+
+# VSWITCHD_SYSLOG_LOGLEVEL: Log level at which to log into syslog.  If
+#     this is null or not set the default is to log to syslog
+#     emergency and warning level messages only.
+# VSWITCHD_SYSLOG_LOGLEVEL="WARN"
+
+# BRCOMPATD_PIDFILE: File in which to store the pid of the running
+#     brcompatd (the Linux bridge compatibility daemon for vswitchd).
+#     If this is the empty string, brcompatd will not be started and
+#     the brcompat_mod kernel module will not be inserted.  Note that
+#     the default is to use brcompat!
+# BRCOMPATD_PIDFILE=/var/run/brcompatd.pid
+
+# BRCOMPATD_PRIORITY: "nice" priority at which to run vswitchd and related
+#     processes.
+# BRCOMPATD_PRIORITY=-5
+
+# BRCOMPATD_LOGFILE: File to send the FILE_LOGLEVEL log messages to.
+# BRCOMPATD_LOGFILE=/var/log/brcompatd.log
+
+# BRCOMPATD_FILE_LOGLEVEL: Log level at which to log into the
+#     BRCOMPATD_LOG file.  If this is null or not set the logfile will
+#     not be created and nothing will be sent to it.  This is the
+#     default.  The available options are: EMER, WARN, INFO and DBG.
+# BRCOMPATD_FILE_LOGLEVEL=""
+
+# BRCOMPATD_SYSLOG_LOGLEVEL: Log level at which to log into syslog.  If
+#     this is null or not set the default is to log to syslog
+#     emergency and warning level messages only.
+# BRCOMPATD_SYSLOG_LOGLEVEL="WARN"
diff --git a/xenserver/etc_xapi.d_plugins_vswitch-cfg-update b/xenserver/etc_xapi.d_plugins_vswitch-cfg-update
new file mode 100755 (executable)
index 0000000..dc7b4a1
--- /dev/null
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+#
+# xapi plugin script to update the cache of configuration items in the
+# vswitchd configuration file that are managed in the xapi database
+# when integrated with Citrix management tools.
+
+# Copyright (C) 2009 Nicira Networks, Inc.
+#
+# 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# TBD: - error handling needs to be improved.  Currently this can leave
+# TBD:   the system in a bad state if anything goes wrong.
+
+import logging
+log = logging.getLogger("vswitch-cfg-update")
+logging.basicConfig(filename="/var/log/vswitch-cfg-update.log", level=logging.DEBUG)
+
+import XenAPIPlugin
+import XenAPI
+import subprocess
+
+cfg_mod="/root/vswitch/bin/cfg-mod"
+vswitchd_cfg_filename="/etc/vswitchd.conf"
+
+def update(session, args):
+    pools = session.xenapi.pool.get_all()
+    # We assume there is only ever one pool...
+    if len(pools) == 0:
+        log.error("No pool for host.")
+        raise XenAPIPlugin.Failure("NO_POOL_FOR_HOST", [])
+    if len(pools) > 1:
+        log.error("More than one pool for host.")
+        raise XenAPIPlugin.Failure("MORE_THAN_ONE_POOL_FOR_HOST", [])
+    pool = session.xenapi.pool.get_record(pools[0])
+    try:
+        controller = pool["other_config"]["niciraController"]
+    except KeyError, e:
+        controller = ""
+    currentController = vswitchCurrentController()
+    if controller == "" and currentController != "":
+        log.debug("Removing controller configuration.")
+        removeControllerCfg()
+        return "Successfully removed controller config"
+    elif controller != currentController:
+        if len(controller) == 0:
+            log.debug("Setting controller to: %s" % (controller))
+        else:
+            log.debug("Changing controller from %s to %s" % (currentController, controller))
+        setControllerCfg(controller)
+        return "Successfully set controller to " + controller
+    else:
+        log.debug("No change to controller configuration required.")
+    return "No change to configuration"
+        
+def vswitchCurrentController():
+    controller = vswitchCfgQuery("mgmt.controller")
+    if controller == "":
+        return controller
+    if len(controller) < 4 or controller[0:4] != "ssl:":
+        log.warning("Controller does not specify ssl connection type, returning entire string.")
+        return controller
+    else:
+        return controller[4:]
+
+def removeControllerCfg():
+    vswitchCfgMod(["--del-match", "mgmt.controller=*",
+                   "--del-match", "ssl.bootstrap-ca-cert=*",
+                   "--del-match", "ssl.ca-cert=*",
+                   "--del-match", "ssl.private-key=*",
+                   "--del-match", "ssl.certificate=*"])
+                                       
+def setControllerCfg(controller):
+    vswitchCfgMod(["--del-match", "mgmt.controller=*",
+                   "--del-match", "ssl.bootstrap-ca-cert=*",
+                   "--del-match", "ssl.ca-cert=*",
+                   "--del-match", "ssl.private-key=*",
+                   "--del-match", "ssl.certificate=*",
+                   "-a", "mgmt.controller=ssl:" + controller,
+                   "-a", "ssl.bootstrap-ca-cert=true",
+                   "-a", "ssl.ca-cert=/etc/vswitchd.cacert",
+                   "-a", "ssl.private-key=/etc/xensource/xapi-ssl.pem",
+                   "-a", "ssl.certificate=/etc/xensource/xapi-ssl.pem"])
+
+def vswitchCfgQuery(key):
+    cmd = [cfg_mod, "--config-file=" + vswitchd_cfg_filename, "-q", key]
+    output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()
+    if len(output) == 0 or output[0] == None:
+        output = ""
+    else:
+        output = output[0].strip()
+    return output
+
+def vswitchCfgMod(action_args):
+    cmd = [cfg_mod, "--config-file=" + vswitchd_cfg_filename] + action_args
+    exitcode = subprocess.call(cmd)
+    if exitcode != 0:
+        log.error("cfg-mod failed with exit code "
+                  + str(exitcode) + " for " + repr(action_args))
+        raise XenAPIPlugin.Failure("VSWITCH_CONFIG_MOD_FAILURE",
+                                   [ str(exitcode) , str(action_args) ])
+    vswitchReload()
+    
+def vswitchReload():
+    exitcode = subprocess.call(["/sbin/service", "vswitch", "reload"])
+    if exitcode != 0:
+        log.error("vswitch reload failed with exit code " + str(exitcode))
+        raise XenAPIPlugin.Failure("VSWITCH_CFG_RELOAD_FAILURE", [ str(exitcode) ])
+    
+
+if __name__ == "__main__":
+    XenAPIPlugin.dispatch({"update": update})
diff --git a/xenserver/etc_xensource_scripts_vif b/xenserver/etc_xensource_scripts_vif
new file mode 100755 (executable)
index 0000000..670c22f
--- /dev/null
@@ -0,0 +1,127 @@
+#!/bin/sh
+
+# This file is based on /etc/xensource/script/vif from Citrix XenServer 5.0.0.
+# The original file did not contain a copyright notice or license statement.
+#
+# Copyright (C) 2009 Nicira Networks, Inc.
+
+# CA-23900: Warning: when VIFs are added to windows guests with PV drivers the backend vif device is registered,
+# unregistered and then registered again. This causes the udev event to fire twice and this script runs twice.
+# Since the first invocation of the script races with the device unregistration, spurious errors are possible
+# which will be logged but are safe to ignore since the second script invocation should complete the operation.
+# Note that each script invocation is run synchronously from udev and so the scripts don't race with each other.
+
+# Keep other-config/ keys in sync with device.ml:vif_udev_keys
+
+cfg_mod="/root/vswitch/bin/cfg-mod"
+service="/sbin/service"
+
+TYPE=`echo ${XENBUS_PATH} | cut -f 2 -d '/'`
+DOMID=`echo ${XENBUS_PATH} | cut -f 3 -d '/'`
+DEVID=`echo ${XENBUS_PATH} | cut -f 4 -d '/'`
+
+XAPI=/xapi/${DOMID}/hotplug/${TYPE}/${DEVID}
+HOTPLUG=/xapi/${DOMID}/hotplug/${TYPE}/${DEVID}
+PRIVATE=/xapi/${DOMID}/private/${TYPE}/${DEVID}
+BRCTL=/usr/sbin/brctl
+IP=/sbin/ip
+
+
+handle_promiscuous()
+{
+    local arg=$(xenstore-read "${PRIVATE}/other-config/promiscuous")
+    if [ $? -eq 0 -a -n "${arg}" ] ; then
+        case "${arg}" in 
+            true|on) echo 1 > /sys/class/net/${vif}/brport/promisc ;;
+            *) echo 0 > /sys/class/net/${vif}/brport/promisc ;;
+        esac
+    fi
+}
+
+handle_ethtool()
+{
+    local opt=$1
+    local arg=$(xenstore-read "${PRIVATE}/other-config/ethtool-${opt}")
+    if [ $? -eq 0 -a -n "${arg}" ] ; then
+        case "${arg}" in
+            true|on)   /sbin/ethtool -K "${vif}" "${opt}" on ;;
+            false|off) /sbin/ethtool -K "${vif}" "${opt}" off ;;
+            *) logger -t scripts-vif "Unknown ethtool argument ${opt}=${arg} on ${vif}/${VIFUUID}" ;;
+        esac
+    fi
+}
+
+handle_mtu()
+{
+    local mtu=$(xenstore-read "${PRIVATE}/MTU")
+    if [ $? -eq 0 -a -n "${mtu}" ]; then
+       echo "${mtu}" > /sys/class/net/${vif}/mtu
+    fi
+}
+
+add_to_bridge()
+{
+    local address=$(xenstore-read "${PRIVATE}/bridge-MAC")
+    if [ $? -ne 0 -o -z "${address}" ]; then
+       logger -t scripts-vif "Failed to read ${PRIVATE}/bridge-MAC from xenstore"
+    fi
+    local bridge=$(xenstore-read "${PRIVATE}/bridge")
+    if [ $? -ne 0 -o -z "${bridge}" ]; then
+       logger -t scripts-vif "Failed to read ${PRIVATE}/bridge from xenstore"
+    fi
+    logger -t scripts-vif "Adding ${vif} to ${bridge} with address ${address}"
+
+    vid=
+    if [ -e "/etc/sysconfig/network-scripts/ifcfg-$bridge" ]; then
+       . "/etc/sysconfig/network-scripts/ifcfg-$bridge"
+       if [ -n "$VLAN_SLAVE" -a -n "$VLAN_VID" ]; then
+           bridge=$VLAN_SLAVE
+           vid="--add=vlan.$vif.tag=$VLAN_VID"
+       fi
+    fi
+
+    ${IP} link set "${vif}" down                        || logger -t scripts-vif "Failed to ip link set ${vif} down"
+    ${IP} link set "${vif}" arp off                     || logger -t scripts-vif "Failed to ip link set ${vif} arp off"
+    ${IP} link set "${vif}" multicast off               || logger -t scripts-vif "Failed to ip link set ${vif} multicast off"
+    ${IP} link set "${vif}" address "${address}"        || logger -t scripts-vif "Failed to ip link set ${vif} address ${address}"
+    ${IP} addr flush "${vif}"                           || logger -t scripts-vif "Failed to ip addr flush ${vif}"
+
+    $cfg_mod -F /etc/vswitchd.conf \
+        --del-match="bridge.*.port=$vif" \
+        --del-match="vlan.$vif.[!0-9]*" \
+        --add="bridge.$bridge.port=$vif" \
+        $vid
+    $service vswitch reload
+
+    ${IP} link set "${vif}" up                          || logger -t scripts-vif "Failed to ip link set ${vif} up"
+}
+
+echo Called as "$@" "$TYPE" "$DOMID" "$DEVID" | logger -t scripts-vif
+case "$1" in
+online)
+       handle_ethtool rx
+       handle_ethtool tx
+       handle_ethtool sg
+       handle_ethtool tso
+       handle_ethtool ufo
+       handle_ethtool gso
+
+       handle_mtu
+       add_to_bridge
+       handle_promiscuous
+
+       xenstore-write "${HOTPLUG}/vif" "${vif}"
+       xenstore-write "${HOTPLUG}/hotplug" "online"
+
+       # xs-xen.pq.hq:91e986b8e49f netback-wait-for-hotplug
+       xenstore-write "/local/domain/0/backend/vif/${DOMID}/${DEVID}/hotplug-status" "connected"
+
+       ;;
+remove)
+       xenstore-rm "${HOTPLUG}/hotplug"
+       vif=vif${DOMID}.${DEVID}
+       logger -t scripts-vif "${vif} has been removed"
+       $cfg-mod -F /etc/vswitchd.conf --del-match="bridge.*.port=${vif}" \
+           --del-match="vlan.${vif}.[!0-9]*"
+       ;;
+esac
diff --git a/xenserver/opt_xensource_libexec_interface-reconfigure b/xenserver/opt_xensource_libexec_interface-reconfigure
new file mode 100755 (executable)
index 0000000..7012537
--- /dev/null
@@ -0,0 +1,1063 @@
+#!/usr/bin/python
+#
+# Copyright (c) Citrix Systems 2008. All rights reserved.
+# Copyright (c) Nicira Networks 2009.
+#
+"""Usage:
+
+    %(command-name)s --session <SESSION-REF> --pif <PIF-REF> [up|down|rewrite]
+    %(command-name)s --force <BRIDGE> [up|down|rewrite <CONFIG>]
+    %(command-name)s --force all down
+
+    where,
+          <CONFIG> = --device=<INTERFACE> --mode=dhcp
+          <CONFIG> = --device=<INTERFACE> --mode=static --ip=<IPADDR> --netmask=<NM> [--gateway=<GW>]
+
+  Options:
+    --session          A session reference to use to access the xapi DB
+    --pif               A PIF reference.
+    --force-interface  An interface name. Mutually exclusive with --session/--pif.
+
+  Either both --session and --pif  or just --pif-uuid.
+  
+  <ACTION> is either "up" or "down" or "rewrite"
+"""
+
+#
+# Undocumented parameters for test & dev:
+#
+#  --output-directory=<DIR>    Write configuration to <DIR>. Also disables actually
+#                               raising/lowering the interfaces
+#  --pif-uuid                  A PIF UUID, use instead of --session/--pif.
+#
+#
+#
+# Notes:
+# 1. Every pif belongs to exactly one network
+# 2. Every network has zero or one pifs
+# 3. A network may have an associated bridge, allowing vifs to be attached
+# 4. A network may be bridgeless (there's no point having a bridge over a storage pif)
+
+# XXX: --force-interface=all down
+
+import XenAPI
+import os, sys, getopt, time, signal
+import syslog
+import traceback
+import time
+import re
+import pickle
+
+output_directory = None
+
+db = None
+management_pif = None
+
+dbcache_file = "/etc/vswitch.dbcache"
+
+class Usage(Exception):
+    def __init__(self, msg):
+        Exception.__init__(self)
+        self.msg = msg
+
+class Error(Exception):
+    def __init__(self, msg):
+        Exception.__init__(self)
+        self.msg = msg
+
+class ConfigurationFile(object):
+    """Write a file, tracking old and new versions.
+
+    Supports writing a new version of a file and applying and
+    reverting those changes.
+    """
+
+    __STATE = {"OPEN":"OPEN",
+               "NOT-APPLIED":"NOT-APPLIED", "APPLIED":"APPLIED",
+               "REVERTED":"REVERTED", "COMMITTED": "COMMITTED"}
+    
+    def __init__(self, fname, path):
+
+        self.__state = self.__STATE['OPEN']
+        self.__fname = fname
+        self.__children = []
+        
+        if debug_mode():
+            dirname = output_directory
+        else:
+            dirname = path
+            
+        self.__path    = os.path.join(dirname, fname)
+        self.__oldpath = os.path.join(dirname, "." + fname + ".xapi-old")
+        self.__newpath = os.path.join(dirname, "." + fname + ".xapi-new")
+        self.__unlink = False
+        
+        self.__f = open(self.__newpath, "w")
+
+    def attach_child(self, child):
+        self.__children.append(child)
+
+    def path(self):
+        return self.__path
+
+    def readlines(self):
+        try:
+            return open(self.path()).readlines()
+        except:
+            return ""
+        
+    def write(self, args):
+        if self.__state != self.__STATE['OPEN']:
+            raise Error("Attempt to write to file in state %s" % self.__state)
+        self.__f.write(args)
+
+    def unlink(self):
+        if self.__state != self.__STATE['OPEN']:
+            raise Error("Attempt to unlink file in state %s" % self.__state)
+        self.__unlink = True
+        self.__f.close()
+        self.__state = self.__STATE['NOT-APPLIED']
+    
+    def close(self):
+        if self.__state != self.__STATE['OPEN']:
+            raise Error("Attempt to close file in state %s" % self.__state)
+        
+        self.__f.close()
+        self.__state = self.__STATE['NOT-APPLIED']
+
+    def changed(self):
+        if self.__state != self.__STATE['NOT-APPLIED']:
+            raise Error("Attempt to compare file in state %s" % self.__state)
+
+        return True
+
+    def apply(self):
+        if self.__state != self.__STATE['NOT-APPLIED']:
+            raise Error("Attempt to apply configuration from state %s" % self.__state)
+
+        for child in self.__children:
+            child.apply()
+
+        log("Applying changes to %s configuration" % self.__fname)
+
+        # Remove previous backup.
+        if os.access(self.__oldpath, os.F_OK):
+            os.unlink(self.__oldpath)
+
+        # Save current configuration.
+        if os.access(self.__path, os.F_OK):
+            os.link(self.__path, self.__oldpath)
+            os.unlink(self.__path)
+
+        # Apply new configuration.
+        assert(os.path.exists(self.__newpath))
+        if not self.__unlink:
+            os.link(self.__newpath, self.__path)
+        else:
+            pass # implicit unlink of original file 
+
+        # Remove temporary file.
+        os.unlink(self.__newpath)
+
+        self.__state = self.__STATE['APPLIED']
+
+    def revert(self):
+        if self.__state != self.__STATE['APPLIED']:
+            raise Error("Attempt to revert configuration from state %s" % self.__state)
+
+        for child in self.__children:
+            child.revert()
+
+        log("Reverting changes to %s configuration" % self.__fname)
+
+        # Remove existing new configuration
+        if os.access(self.__newpath, os.F_OK):
+            os.unlink(self.__newpath)
+
+        # Revert new configuration.
+        if os.access(self.__path, os.F_OK):
+            os.link(self.__path, self.__newpath)
+            os.unlink(self.__path)
+
+        # Revert to old configuration.
+        if os.access(self.__oldpath, os.F_OK):
+            os.link(self.__oldpath, self.__path)
+            os.unlink(self.__oldpath)
+
+        # Leave .*.xapi-new as an aid to debugging.
+        
+        self.__state = self.__STATE['REVERTED']
+    
+    def commit(self):
+        if self.__state != self.__STATE['APPLIED']:
+            raise Error("Attempt to commit configuration from state %s" % self.__state)
+
+        for child in self.__children:
+            child.commit()
+
+        log("Committing changes to %s configuration" % self.__fname)
+        
+        if os.access(self.__oldpath, os.F_OK):
+            os.unlink(self.__oldpath)
+        if os.access(self.__newpath, os.F_OK):
+            os.unlink(self.__newpath)
+
+        self.__state = self.__STATE['COMMITTED']
+
+def debug_mode():
+    return output_directory is not None
+
+def log(s):
+    if debug_mode():
+        print >>sys.stderr, s
+    else:
+        syslog.syslog(s)
+
+def check_allowed(pif):
+    pifrec = db.get_pif_record(pif)
+    try:
+        f = open("/proc/ardence")
+        macline = filter(lambda x: x.startswith("HWaddr:"), f.readlines())
+        f.close()
+        if len(macline) == 1:
+            p = re.compile(".*\s%(MAC)s\s.*" % pifrec, re.IGNORECASE)
+            if p.match(macline[0]):
+                log("Skipping PVS device %(device)s (%(MAC)s)" % pifrec)
+                return False
+    except IOError:
+        pass
+    return True
+
+def interface_exists(i):
+    return os.path.exists("/sys/class/net/" + i)
+
+class DatabaseCache(object):
+    def __init__(self, session_ref=None, cache_file=None):
+        if session_ref and cache_file:
+            raise Error("can't specify session reference and cache file")
+
+        if cache_file == None:
+            session = XenAPI.xapi_local()
+
+            if not session_ref:
+                log("No session ref given on command line, logging in.")
+                session.xenapi.login_with_password("root", "")
+            else:
+                session._session = session_ref
+
+            try:
+                self.__vlans = session.xenapi.VLAN.get_all_records()
+                self.__bonds = session.xenapi.Bond.get_all_records()
+                self.__pifs = session.xenapi.PIF.get_all_records()
+                self.__networks = session.xenapi.network.get_all_records()
+            finally:
+                if not session_ref:
+                    session.xenapi.session.logout()
+        else:
+            log("Loading xapi database cache from %s" % cache_file)
+            f = open(cache_file, 'r')
+            members = pickle.load(f)
+            self.extras = pickle.load(f)
+            f.close()
+
+            self.__vlans = members['vlans']
+            self.__bonds = members['bonds']
+            self.__pifs = members['pifs']
+            self.__networks = members['networks']
+
+    def save(self, cache_file, extras):
+        f = open(cache_file, 'w')
+        pickle.dump({'vlans': self.__vlans,
+                     'bonds': self.__bonds,
+                     'pifs': self.__pifs,
+                     'networks': self.__networks}, f)
+        pickle.dump(extras, f)
+        f.close()
+
+    def get_pif_by_uuid(self, uuid):
+        pifs = map(lambda (ref,rec): ref,
+                  filter(lambda (ref,rec): uuid == rec['uuid'],
+                         self.__pifs.items()))
+        if len(pifs) == 0:
+            raise Error("Unknown PIF \"%s\"" % uuid)
+        elif len(pifs) > 1:
+            raise Error("Non-unique PIF \"%s\"" % uuid)
+
+        return pifs[0]
+
+    def get_pif_by_record(self, record):
+        """record is partial pif record.
+        Get the pif whose record matches.
+        """
+        def match(pifrec):
+            for key in record:
+                if record[key] != pifrec[key]:
+                    return False
+            return True
+            
+        pifs = map(lambda (ref,rec): ref,
+                  filter(lambda (ref,rec): match(rec),
+                         self.__pifs.items()))
+        if len(pifs) == 0:
+            raise Error("No matching PIF \"%s\"" % str(record))
+        elif len(pifs) > 1:
+            raise Error("Multiple matching PIFs \"%s\"" % str(record))
+
+        return pifs[0]
+
+    def get_pif_by_bridge(self, host, bridge):
+        networks = map(lambda (ref,rec): ref,
+                       filter(lambda (ref,rec): rec['bridge'] == bridge,
+                              self.__networks.items()))
+        if len(networks) == 0:
+            raise Error("No matching network \"%s\"")
+
+        answer = None
+        for network in networks:
+            nwrec = self.get_network_record(network)
+            pif_uuids = nwrec['PIFs']
+            if len(pif_uuids) != 1:
+                continue
+            pif = pif_uuids[0]
+            pifrec = self.get_pif_record(pif)
+            if pifrec['host'] != host:
+                continue
+            if answer:
+                raise Error("Multiple PIFs on %s for network %s" % (host, bridge))
+            answer = pif
+        if not answer:
+            raise Error("No PIF on %s for network %s" % (host, bridge))
+        return answer
+
+    def get_pif_record(self, pif):
+        if self.__pifs.has_key(pif):
+            return self.__pifs[pif]
+        raise Error("Unknown PIF \"%s\"" % pif)
+    def get_all_pifs(self):
+        return self.__pifs
+    def pif_exists(self, pif):
+        return self.__pifs.has_key(pif)
+    
+    def get_management_pif(self, host):
+        """ Returns the management pif on host
+        """
+        all = self.get_all_pifs()
+        for pif in all: 
+            pifrec = self.get_pif_record(pif)
+            if pifrec['management'] and pifrec['host'] == host :
+                return pif
+        return None
+
+    def get_network_record(self, network):
+        if self.__networks.has_key(network):
+            return self.__networks[network]
+        raise Error("Unknown network \"%s\"" % network)
+
+    def get_bond_record(self, bond):
+        if self.__bonds.has_key(bond):
+            return self.__bonds[bond]
+        else:
+            return None
+        
+    def get_vlan_record(self, vlan):
+        if self.__vlans.has_key(vlan):
+            return self.__vlans[vlan]
+        else:
+            return None
+            
+def bridge_name(pif):
+    """Return the bridge name associated with pif, or None if network is bridgeless"""
+    pifrec = db.get_pif_record(pif)
+    nwrec = db.get_network_record(pifrec['network'])
+
+    if nwrec['bridge']:
+        # TODO: sanity check that nwrec['bridgeless'] != 'true'
+        return nwrec['bridge']
+    else:
+        # TODO: sanity check that nwrec['bridgeless'] == 'true'
+        return None
+
+def interface_name(pif):
+    """Construct an interface name from the given PIF record."""
+
+    pifrec = db.get_pif_record(pif)
+
+    if pifrec['VLAN'] == '-1':
+        return pifrec['device']
+    else:
+        return "%(device)s.%(VLAN)s" % pifrec
+
+def datapath_name(pif):
+    """Return the OpenFlow datapath name associated with pif.
+For a non-VLAN PIF, the datapath name is the bridge name.
+For a VLAN PIF, the datapath name is the bridge name for the PIF's VLAN slave.
+(xapi will create a datapath named with the bridge name even though we won't
+use it.)
+"""
+
+    pifrec = db.get_pif_record(pif)
+
+    if pifrec['VLAN'] == '-1':
+        return bridge_name(pif)
+    else:
+        return bridge_name(get_vlan_slave_of_pif(pif))
+
+def ipdev_name(pif):
+    """Return the the name of the network device that carries the
+IP configuration (if any) associated with pif.
+For a non-VLAN PIF, the ipdev name is the bridge name.
+For a VLAN PIF, the ipdev name is the interface name.
+"""
+
+    pifrec = db.get_pif_record(pif)
+
+    if pifrec['VLAN'] == '-1':
+        return bridge_name(pif)
+    else:
+        return interface_name(pif)
+
+def physdev_names(pif):
+    """Return the name(s) of the physical network device(s) associated with pif.
+For a VLAN PIF, the physical devices are the VLAN slave's physical devices.
+For a bond master PIF, the physical devices are the bond slaves.
+For a non-VLAN, non-bond master PIF, the physical device is the PIF itself.
+"""
+
+    pifrec = db.get_pif_record(pif)
+
+    if pifrec['VLAN'] != '-1':
+        return physdev_names(get_vlan_slave_of_pif(pif))
+    elif len(pifrec['bond_master_of']) != 0:
+        physdevs = []
+        for slave in get_bond_slaves_of_pif(pif):
+            physdevs += physdev_names(slave)
+        return physdevs
+    else:
+        return [pifrec['device']]
+
+def log_pif_action(action, pif):
+    pifrec = db.get_pif_record(pif)
+    pifrec['action'] = action
+    pifrec['interface-name'] = interface_name(pif)
+    if action == "rewrite":
+        pifrec['message'] = "Rewrite PIF %(uuid)s configuration" % pifrec
+    else:
+        pifrec['message'] = "Bring %(action)s PIF %(uuid)s" % pifrec
+    log("%(message)s: %(interface-name)s configured as %(ip_configuration_mode)s" % pifrec)
+
+def get_bond_masters_of_pif(pif):
+    """Returns a list of PIFs which are bond masters of this PIF"""
+
+    pifrec = db.get_pif_record(pif)
+
+    bso = pifrec['bond_slave_of']
+
+    # bond-slave-of is currently a single reference but in principle a
+    # PIF could be a member of several bonds which are not
+    # concurrently attached. Be robust to this possibility.
+    if not bso or bso == "OpaqueRef:NULL":
+        bso = []
+    elif not type(bso) == list:
+        bso = [bso]
+
+    bondrecs = [db.get_bond_record(bond) for bond in bso]
+    bondrecs = [rec for rec in bondrecs if rec]
+
+    return [bond['master'] for bond in bondrecs]
+
+def get_bond_slaves_of_pif(pif):
+    """Returns a list of PIFs which make up the given bonded pif."""
+    
+    pifrec = db.get_pif_record(pif)
+    host = pifrec['host']
+
+    bmo = pifrec['bond_master_of']
+    if len(bmo) > 1:
+        raise Error("Bond-master-of contains too many elements")
+    
+    if len(bmo) == 0:
+        return []
+    
+    bondrec = db.get_bond_record(bmo[0])
+    if not bondrec:
+        raise Error("No bond record for bond master PIF")
+
+    # build a list of slave's pifs
+    slave_pifs = bondrec['slaves']
+
+    # Ensure any currently attached slaves are listed in the opposite order to the order in 
+    # which they were attached.  The first slave attached must be the last detached since
+    # the bond is using its MAC address.
+    try:
+        attached_slaves = open("/sys/class/net/%s/bonding/slaves" % pifrec['device']).readline().split()
+        for slave in attached_slaves:
+            partial_pifrec = {'host':host, 'device':slave}
+            slave_pif = db.get_pif_by_record(partial_pifrec)
+            slave_pifs.remove(slave_pif)
+            slave_pifs.insert(0, slave_pif)
+    except IOError:
+        pass 
+
+    return slave_pifs
+
+def get_vlan_slave_of_pif(pif):
+    """Find the PIF which is the VLAN slave of pif.
+
+Returns the 'physical' PIF underneath the a VLAN PIF @pif."""
+    
+    pifrec = db.get_pif_record(pif)
+
+    vlan = pifrec['VLAN_master_of']
+    if not vlan or vlan == "OpaqueRef:NULL":
+        raise Error("PIF is not a VLAN master")
+
+    vlanrec = db.get_vlan_record(vlan)
+    if not vlanrec:
+        raise Error("No VLAN record found for PIF")
+
+    return vlanrec['tagged_PIF']
+
+def get_vlan_masters_of_pif(pif):
+    """Returns a list of PIFs which are VLANs on top of the given pif."""
+    
+    pifrec = db.get_pif_record(pif)
+    vlans = [db.get_vlan_record(v) for v in pifrec['VLAN_slave_of']]
+    return [v['untagged_PIF'] for v in vlans if v and db.pif_exists(v['untagged_PIF'])]
+
+def interface_deconfigure_commands(interface):
+    # The use of [!0-9] keeps an interface of 'eth0' from matching
+    # VLANs attached to eth0 (such as 'eth0.123'), which are distinct
+    # interfaces.
+    return ['--del-match=bridge.*.port=%s' % interface,
+            '--del-match=bonding.%s.[!0-9]*' % interface,
+            '--del-match=bonding.*.slave=%s' % interface,
+            '--del-match=vlan.%s.[!0-9]*' % interface,
+            '--del-match=iface.%s.[!0-9]*' % interface]
+
+def run_command(command):
+    log("Running command: " + ' '.join(command))
+    #return
+    if os.spawnl(os.P_WAIT, command[0], *command) != 0:
+        log("Command failed: " + ' '.join(command))
+        return False
+    return True
+
+def down_netdev(interface, deconfigure=True):
+    if not interface_exists(interface):
+        log("down_netdev: interface %s does not exist, ignoring" % interface)
+        return
+    argv = ["/sbin/ifconfig", interface, 'down']
+    if deconfigure:
+        argv += ['0.0.0.0']
+
+        # Kill dhclient.
+        pidfile_name = '/var/run/dhclient-%s.pid' % interface
+        pidfile = None
+        try:
+            pidfile = open(pidfile_name, 'r')
+            os.kill(int(pidfile.readline()), signal.SIGTERM)
+        except:
+            pass
+        if pidfile != None:
+            pidfile.close()
+
+        # Remove dhclient pidfile.
+        try:
+            os.remove(pidfile_name)
+        except:
+            pass
+    run_command(argv)
+
+def up_netdev(interface):
+    run_command(["/sbin/ifconfig", interface, 'up'])
+
+def find_distinguished_pifs(pif):
+    """Returns the PIFs on host that own DNS and the default route.
+The peerdns pif will be the one with pif::other-config:peerdns=true, or the mgmt pif if none have this set.
+The gateway pif will be the one with pif::other-config:defaultroute=true, or the mgmt pif if none have this set.
+
+Note: we prune out the bond master pif (if it exists).
+This is because when we are called to bring up an interface with a bond master, it is implicit that
+we should bring down that master."""
+
+    pifrec = db.get_pif_record(pif)
+    host = pifrec['host']
+
+    pifs_on_host = [ __pif for __pif in db.get_all_pifs() if
+                     db.get_pif_record(__pif)['host'] == host and 
+                     (not  __pif in get_bond_masters_of_pif(pif)) ]
+    other_pifs_on_host = [ __pif for __pif in pifs_on_host if __pif != pif ]
+
+    peerdns_pif = None
+    defaultroute_pif = None
+    
+    # loop through all the pifs on this host looking for one with
+    #   other-config:peerdns = true, and one with
+    #   other-config:default-route=true
+    for __pif in pifs_on_host:
+        __pifrec = db.get_pif_record(__pif)
+        __oc = __pifrec['other_config']
+        if __oc.has_key('peerdns') and __oc['peerdns'] == 'true':
+            if peerdns_pif == None:
+                peerdns_pif = __pif
+            else:
+                log('Warning: multiple pifs with "peerdns=true" - choosing %s and ignoring %s' % \
+                        (db.get_pif_record(peerdns_pif)['device'], __pifrec['device']))
+        if __oc.has_key('defaultroute') and __oc['defaultroute'] == 'true':
+            if defaultroute_pif == None:
+                defaultroute_pif = __pif
+            else:
+                log('Warning: multiple pifs with "defaultroute=true" - choosing %s and ignoring %s' % \
+                        (db.get_pif_record(defaultroute_pif)['device'], __pifrec['device']))
+    
+    # If no pif is explicitly specified then use the mgmt pif for peerdns/defaultroute
+    if peerdns_pif == None:
+        peerdns_pif = management_pif
+    if defaultroute_pif == None:
+        defaultroute_pif = management_pif
+
+    return peerdns_pif, defaultroute_pif
+
+def ethtool_settings(oc):
+    # Options for "ethtool -s"
+    settings = []
+    if oc.has_key('ethtool-speed'):
+        val = oc['ethtool-speed']
+        if val in ["10", "100", "1000"]:
+            settings += ['speed', val]
+        else:
+            log("Invalid value for ethtool-speed = %s. Must be 10|100|1000." % val)
+    if oc.has_key('ethtool-duplex'):
+        val = oc['ethtool-duplex']
+        if val in ["10", "100", "1000"]:
+            settings += ['duplex', 'val']
+        else:
+            log("Invalid value for ethtool-duplex = %s. Must be half|full." % val)
+    if oc.has_key('ethtool-autoneg'):
+        val = oc['ethtool-autoneg']
+        if val in ["true", "on"]:
+            settings += ['autoneg', 'on']
+        elif val in ["false", "off"]:
+            settings += ['autoneg', 'off']
+        else:
+            log("Invalid value for ethtool-autoneg = %s. Must be on|true|off|false." % val)
+
+    # Options for "ethtool -K"
+    offload = []
+    for opt in ("rx", "tx", "sg", "tso", "ufo", "gso"):
+        if oc.has_key("ethtool-" + opt):
+            val = oc["ethtool-" + opt]
+            if val in ["true", "on"]:
+                offload += [opt, 'on']
+            elif val in ["false", "off"]:
+                offload += [opt, 'off']
+            else:
+                log("Invalid value for ethtool-%s = %s. Must be on|true|off|false." % (opt, val))
+
+    return settings, offload
+
+def configure_netdev(pif):
+    pifrec = db.get_pif_record(pif)
+    datapath = datapath_name(pif)
+    ipdev = ipdev_name(pif)
+
+    host = pifrec['host']
+    nw = pifrec['network']
+    nwrec = db.get_network_record(nw)
+
+    ifconfig_argv = ['/sbin/ifconfig', ipdev, 'up']
+    gateway = ''
+    if pifrec['ip_configuration_mode'] == "DHCP":
+        pass
+    elif pifrec['ip_configuration_mode'] == "Static":
+        ifconfig_argv += [pifrec['IP']]
+        ifconfig_argv += ['netmask', pifrec['netmask']]
+        gateway = pifrec['gateway']
+    elif pifrec['ip_configuration_mode'] == "None":
+        # Nothing to do.
+        pass
+    else:
+        raise Error("Unknown IP-configuration-mode %s" % pifrec['ip_configuration_mode'])
+
+    oc = {}
+    if pifrec.has_key('other_config'):
+        oc = pifrec['other_config']
+        if oc.has_key('mtu'):
+            int(oc['mtu'])      # Check that the value is an integer
+            ifconfig_argv += ['mtu', oc['mtu']]
+
+    run_command(ifconfig_argv)
+    
+    (peerdns_pif, defaultroute_pif) = find_distinguished_pifs(pif)
+
+    if peerdns_pif == pif:
+        f = ConfigurationFile('resolv.conf', "/etc")
+        if oc.has_key('domain'):
+            f.write("search %s\n" % oc['domain'])
+        for dns in pifrec['DNS'].split(","): 
+            f.write("nameserver %s\n" % dns)
+        f.close()
+        f.apply()
+        f.commit()
+
+    if defaultroute_pif == pif and gateway != '':
+        run_command(['/sbin/ip', 'route', 'replace', 'default',
+                     'via', gateway, 'dev', ipdev])
+    
+    if oc.has_key('static-routes'):
+        for line in oc['static-routes'].split(','):
+            network, masklen, gateway = line.split('/')
+            run_command(['/sbin/ip', 'route', 'add',
+                         '%s/%s' % (netmask, masklen), 'via', gateway,
+                         'dev', ipdev])
+
+    settings, offload = ethtool_settings(oc)
+    if settings:
+        run_command(['/sbin/ethtool', '-s', ipdev] + settings)
+    if offload:
+        run_command(['/sbin/ethtool', '-K', ipdev] + offload)
+
+    if pifrec['ip_configuration_mode'] == "DHCP":
+        print
+        print "Determining IP information for %s..." % ipdev,
+        argv = ['/sbin/dhclient', '-q',
+                '-lf', '/var/lib/dhclient/dhclient-%s.leases' % ipdev,
+                '-pf', '/var/run/dhclient-%s.pid' % ipdev,
+                ipdev]
+        if run_command(argv):
+            print 'done.'
+        else:
+            print 'failed.'
+
+def modify_config(commands):
+    run_command(['/root/vswitch/bin/cfg-mod', '-F', '/etc/vswitchd.conf']
+                + commands + ['-c'])
+    run_command(['/sbin/service', 'vswitch', 'reload'])
+
+def is_bond_pif(pif):
+    pifrec = db.get_pif_record(pif)
+    return len(pifrec['bond_master_of']) != 0
+
+def configure_bond(pif):
+    pifrec = db.get_pif_record(pif)
+    interface = interface_name(pif)
+    ipdev = ipdev_name(pif)
+    datapath = datapath_name(pif)
+    physdevs = physdev_names(pif)
+
+    argv = ['--del-match=bonding.%s.[!0-9]*' % interface]
+    argv += ["--add=bonding.%s.slave=%s" % (interface, slave)
+             for slave in physdevs]
+
+    # Bonding options.
+    bond_options = { 
+        "mode":   "balance-slb",
+        "miimon": "100",
+        "downdelay": "200",
+        "updelay": "31000",
+        "use_carrier": "1",
+        }
+    # override defaults with values from other-config whose keys
+    # being with "bond-"
+    oc = pifrec['other_config']
+    overrides = filter(lambda (key,val):
+                           key.startswith("bond-"), oc.items())
+    overrides = map(lambda (key,val): (key[5:], val), overrides)
+    bond_options.update(overrides)
+    for (name,val) in bond_options.items():
+        argv += ["--add=bonding.%s.%s=%s" % (interface, name, val)]
+    return argv
+
+def action_up(pif):
+    pifrec = db.get_pif_record(pif)
+
+    interface = interface_name(pif)
+    ipdev = ipdev_name(pif)
+    datapath = datapath_name(pif)
+    physdevs = physdev_names(pif)
+    vlan_slave = None
+    if pifrec['VLAN'] != '-1':
+        vlan_slave = get_vlan_slave_of_pif(pif)
+    if vlan_slave and is_bond_pif(vlan_slave):
+        bond_master = vlan_slave
+    elif is_bond_pif(pif):
+        bond_master = pif
+    else:
+        bond_master = None
+
+    # "ifconfig down" the network device and delete its IP address, etc.
+    down_netdev(ipdev)
+    #if datapath != ipdev:
+    #    down_netdev(datapath)
+    if vlan_slave:
+        down_netdev(ipdev_name(vlan_slave), False)
+    for physdev in physdevs:
+        down_netdev(physdev)
+
+    # Remove all keys related to pif and any bond masters linked to PIF.
+    del_ports = [ipdev] + physdevs + get_bond_masters_of_pif(pif)
+    if vlan_slave and bond_master:
+        del_ports += [interface_name(bond_master)]
+    
+    # What ports do we need to add to the datapath?
+    #
+    # We definitely need the ipdev, and ordinarily we want the
+    # physical devices too, but for bonds we need the bond as bridge
+    # port.
+    add_ports = [ipdev, datapath]
+    if not bond_master:
+        add_ports += physdevs
+    else:
+        add_ports += [interface_name(bond_master)]
+
+    # What ports do we need to delete first?
+    #
+    #  - All the ports that we add, to avoid duplication and to drop
+    #    them from another datapath in case they're misassigned.
+    #    
+    #  - The physical devices, since they will either be in add_ports
+    #    or added to the bonding device (see below).
+    #
+    #  - The bond masters for pif.  (Ordinarily pif shouldn't have any
+    #    bond masters.  If it does then interface-reconfigure is
+    #    implicitly being asked to take them down.)
+    del_ports = add_ports + physdevs + get_bond_masters_of_pif(pif)
+
+    # Now modify the vswitchd config file.
+    argv = []
+    for port in set(del_ports):
+        argv += interface_deconfigure_commands(port)
+    for port in set(add_ports):
+        argv += ['--add=bridge.%s.port=%s' % (datapath, port)]
+    if vlan_slave:
+        argv += ['--add=vlan.%s.tag=%s' % (ipdev, pifrec['VLAN'])]
+        argv += ['--add=iface.%s.internal=true' % (ipdev)]
+    if bond_master:
+        argv += configure_bond(bond_master)
+    modify_config(argv)
+
+    # Configure network devices.
+    configure_netdev(pif)
+
+    # Bring up VLAN slave and bond slaves.
+    if vlan_slave:
+        up_netdev(ipdev_name(vlan_slave))
+    for physdev in physdevs:
+        up_netdev(physdev)
+
+    # Update /etc/issue (which contains the IP address of the management interface)
+    os.system("/sbin/update-issue")
+        
+def action_down(pif):
+    rec = db.get_pif_record(pif)    
+    interface = interface_name(pif)
+    bridge = bridge_name(pif)
+    ipdev = ipdev_name(pif)
+
+    argv = []
+    if rec['VLAN'] != '-1':
+        # Get rid of the VLAN device itself.
+        down_netdev(ipdev)
+        argv += interface_deconfigure_commands(ipdev)
+
+        # If the VLAN's slave is attached, stop here.
+        slave = get_vlan_slave_of_pif(pif)
+        if db.get_pif_record(slave)['currently_attached']:
+            log("VLAN slave is currently attached")
+            modify_config(argv)
+            return
+        
+        # If the VLAN's slave has other VLANs that are attached, stop here.
+        masters = get_vlan_masters_of_pif(slave)
+        for m in masters:
+            if m != pif and db.get_pif_record(m)['currently_attached']:
+                log("VLAN slave has other master %s" % interface_naem(m))
+                modify_config(argv)
+                return
+
+        # Otherwise, take down the VLAN's slave too.
+        log("No more masters, bring down vlan slave %s" % interface_name(slave))
+        pif = slave
+    else:
+        # Stop here if this PIF has attached VLAN masters.
+        vlan_masters = get_vlan_masters_of_pif(pif)
+        log("VLAN masters of %s - %s" % (rec['device'], [interface_name(m) for m in vlan_masters]))
+        for m in vlan_masters:
+            if db.get_pif_record(m)['currently_attached']:
+                log("Leaving %s up due to currently attached VLAN master %s" % (interface, interface_name(m)))
+                return
+
+    # pif is now either a bond or a physical device which needs to be
+    # brought down.  pif might have changed so re-check all its attributes.
+    rec = db.get_pif_record(pif)
+    interface = interface_name(pif)
+    bridge = bridge_name(pif)
+    ipdev = ipdev_name(pif)
+
+
+    bond_slaves = get_bond_slaves_of_pif(pif)
+    log("bond slaves of %s - %s" % (rec['device'], [interface_name(s) for s in bond_slaves]))
+    for slave in bond_slaves:
+        slave_interface = interface_name(slave)
+        log("bring down bond slave %s" % slave_interface)
+        argv += interface_deconfigure_commands(slave_interface)
+        down_netdev(slave_interface)
+
+    argv += interface_deconfigure_commands(ipdev)
+    down_netdev(ipdev)
+
+    argv += ['--del-match', 'bridge.%s.*' % datapath_name(pif)]
+    argv += ['--del-match', 'bonding.%s.[!0-9]*' % interface]
+    modify_config(argv)
+
+def action_rewrite(pif):
+    pifrec = db.get_pif_record(pif)
+    db.save(dbcache_file, {'host': pifrec['host']})
+
+def main(argv=None):
+    global output_directory, management_pif
+    
+    session = None
+    pif_uuid = None
+    pif = None
+
+    force_interface = None
+    force_management = False
+    
+    if argv is None:
+        argv = sys.argv
+
+    try:
+        try:
+            shortops = "h"
+            longops = [ "output-directory=",
+                        "pif=", "pif-uuid=",
+                        "session=",
+                        "force=",
+                        "force-interface=",
+                        "management",
+                        "test-mode",
+                        "device=", "mode=", "ip=", "netmask=", "gateway=",
+                        "help" ]
+            arglist, args = getopt.gnu_getopt(argv[1:], shortops, longops)
+        except getopt.GetoptError, msg:
+            raise Usage(msg)
+
+        force_rewrite_config = {}
+        
+        for o,a in arglist:
+            if o == "--output-directory":
+                output_directory = a
+            elif o == "--pif":
+                pif = a
+            elif o == "--pif-uuid":
+                pif_uuid = a
+            elif o == "--session":
+                session = a
+            elif o == "--force-interface" or o == "--force":
+                force_interface = a
+            elif o == "--management":
+                force_management = True
+            elif o in ["--device", "--mode", "--ip", "--netmask", "--gateway"]:
+                force_rewrite_config[o[2:]] = a
+            elif o == "-h" or o == "--help":
+                print __doc__ % {'command-name': os.path.basename(argv[0])}
+                return 0
+
+        if not debug_mode():
+            syslog.openlog(os.path.basename(argv[0]))
+            log("Called as " + str.join(" ", argv))
+        if len(args) < 1:
+            raise Usage("Required option <action> not present")
+        if len(args) > 1:
+            raise Usage("Too many arguments")
+
+        action = args[0]
+        # backwards compatibility
+        if action == "rewrite-configuration": action = "rewrite"
+        
+        if output_directory and ( session or pif ):
+            raise Usage("--session/--pif cannot be used with --output-directory")
+        if ( session or pif ) and pif_uuid:
+            raise Usage("--session/--pif and --pif-uuid are mutually exclusive.")
+        if ( session and not pif ) or ( not session and pif ):
+            raise Usage("--session and --pif must be used together.")
+        if force_interface and ( session or pif or pif_uuid ):
+            raise Usage("--force is mutually exclusive with --session, --pif and --pif-uuid")
+        if len(force_rewrite_config) and not (force_interface and action == "rewrite"):
+            raise Usage("\"--force rewrite\" needed for --device, --mode, --ip, --netmask, and --gateway")
+
+        global db
+        if force_interface:
+            log("Force interface %s %s" % (force_interface, action))
+
+            if action == "rewrite":
+                action_force_rewrite(force_interface, force_rewrite_config)
+            else:
+                db = DatabaseCache(cache_file=dbcache_file)
+                host = db.extras['host']
+                pif = db.get_pif_by_bridge(host, force_interface)
+
+                if action == "up":
+                    action_up(pif)
+                elif action == "down":
+                    action_down(pif)
+                else:
+                    raise Usage("Unknown action %s"  % action)
+        else:
+            db = DatabaseCache(session_ref=session)
+
+            if pif_uuid:
+                pif = db.get_pif_by_uuid(pif_uuid)
+        
+            if not pif:
+                raise Usage("No PIF given")
+
+            if force_management:
+                # pif is going to be the management pif 
+                management_pif = pif
+            else:
+                # pif is not going to be the management pif.
+                # Search DB cache for pif on same host with management=true
+                pifrec = db.get_pif_record(pif)
+                host = pifrec['host']
+                management_pif = db.get_management_pif(host)
+
+            log_pif_action(action, pif)
+
+            if not check_allowed(pif):
+                return 0
+
+            if action == "up":
+                action_up(pif)
+            elif action == "down":
+                action_down(pif)
+            elif action == "rewrite":
+                action_rewrite(pif)
+            else:
+                raise Usage("Unknown action %s"  % action)
+        
+    except Usage, err:
+        print >>sys.stderr, err.msg
+        print >>sys.stderr, "For help use --help."
+        return 2
+    except Error, err:
+        log(err.msg)
+        return 1
+    
+    return 0
+
+if __name__ == "__main__":
+    rc = 1
+    try:
+        rc = main()
+    except:
+        ex = sys.exc_info()
+        err = traceback.format_exception(*ex)
+        for exline in err:
+            log(exline)
+
+    if not debug_mode():
+        syslog.closelog()
+        
+    sys.exit(rc)
diff --git a/xenserver/usr_lib_xsconsole_plugins-base_XSFeatureNiciraVSwitch.py b/xenserver/usr_lib_xsconsole_plugins-base_XSFeatureNiciraVSwitch.py
new file mode 100644 (file)
index 0000000..eef2af9
--- /dev/null
@@ -0,0 +1,303 @@
+# Copyright (c) Citrix Systems 2008. All rights reserved.
+# xsconsole is proprietary software.
+#
+# Xen, the Xen logo, XenCenter, XenMotion are trademarks or registered
+# trademarks of Citrix Systems, Inc., in the United States and other
+# countries.
+
+# Copyright (c) 2009 Nicira Networks.
+
+import logging
+log = logging.getLogger("vswitch-cfg-update")
+logging.basicConfig(filename="/var/log/vswitch-xsplugin.log", level=logging.DEBUG)
+
+import os
+import subprocess
+
+cfg_mod="/root/vswitch/bin/cfg-mod"
+vswitchd_cfg_filename="/etc/vswitchd.conf"
+
+if __name__ == "__main__":
+    raise Exception("This script is a plugin for xsconsole and cannot run independently")
+
+from XSConsoleStandard import *
+
+class NiciraService:
+    service = {}
+
+    def __init__(self, name, processname=None):
+        self.name = name
+        self.processname = processname
+        if self.processname == None:
+            self.processname = name
+
+    def _execCmd(self, cmd):
+        pipe = subprocess.PIPE
+        return subprocess.Popen(cmd, stdin=pipe, stdout=pipe, stderr=pipe)
+
+    def status(self):
+        cmd = [ "service", self.name, "status" ]
+        try:
+            p = self._execCmd(cmd)
+            output = p.communicate()[0]
+        except StandardError, e:
+            log.error("Subprocess error: " + str(e))
+            return "<unknown>"
+        if output == None:
+            return "<unknown>"
+        for l in output.split("\n"):
+            if self.processname not in l:
+                continue
+            elif "running" in l:
+                return "Running"
+            elif "stop" in l:
+                return "Stopped"
+            else:
+                return "<unknown>"
+        return "<unknown>"
+
+    def restart(self):
+        cmd = [ "service", self.name, "restart" ]
+        try:
+            p = self._execCmd(cmd)
+            p.communicate()
+        except StandardError, e:
+            log.error("Subprocess error: ", str(e))
+
+    @classmethod
+    def Inst(cls, name, processname=None):
+        key = name
+        if processname != None:
+            key = key + "-" + processname
+        if name not in cls.service:
+            cls.service[key] = NiciraService(name, processname)
+        return cls.service[key]
+
+class VSwitchConfig:
+
+    @staticmethod
+    def Get(key):
+        cmd = [cfg_mod, "--config-file=" + vswitchd_cfg_filename, "-q", key]
+        output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()
+        if len(output) == 0 or output[0] == None:
+            output = ""
+        else:
+            output = output[0].strip()
+        return output
+
+
+class NiciraControllerDialogue(Dialogue):
+    def __init__(self):
+        Dialogue.__init__(self)
+        data=Data.Inst()
+
+        self.hostsInPool = 0
+        self.hostsUpdated = 0
+
+        pool = data.pools().values()[0]
+        try:
+            self.controller = pool["other_config"]["niciraController"]
+        except KeyError, e:
+            self.controller = ""
+
+        choiceDefs = [
+            ChoiceDef(Lang("Set pool-wide controller"),
+                      lambda: self.getController()),
+            ChoiceDef(Lang("Delete pool-wide controller"),
+                      lambda: self.deleteController()),
+            ChoiceDef(Lang("Resync server controller config"),
+                      lambda: self.syncController()),
+#             ChoiceDef(Lang("Restart vswitchd"),
+#                       lambda: self.restartService("vswitch")),
+#             ChoiceDef(Lang("Restart brcompatd"),
+#                       lambda: self.restartService("vswitch-brcompatd"))
+            ]
+        self.menu = Menu(self, None, Lang("Configure Nicira VSwitch"), choiceDefs)
+
+        self.ChangeState("INITIAL")
+
+    def BuildPane(self):
+        pane = self.NewPane(DialoguePane(self.parent))
+        pane.TitleSet(Lang("Configure Nicira VSwitch"))
+        pane.AddBox()
+
+    def ChangeState(self, inState):
+        self.state = inState
+        self.BuildPane()
+        self.UpdateFields()
+
+    def UpdateFields(self):
+        self.Pane().ResetPosition()
+        getattr(self, "UpdateFields" + self.state)() # Dispatch method named 'UpdateFields'+self.state
+
+    def UpdateFieldsINITIAL(self):
+        pane = self.Pane()
+        pane.AddTitleField(Lang("Select an action"))
+        pane.AddMenuField(self.menu)
+        pane.AddKeyHelpField( { Lang("<Enter>") : Lang("OK"), Lang("<Esc>") : Lang("Cancel") } )
+
+    def UpdateFieldsGETCONTROLLER(self):
+        pane = self.Pane()
+        pane.ResetFields()
+
+        pane.AddTitleField(Lang("Enter IP address of controller"))
+        pane.AddInputField(Lang("Address", 16), self.controller, "address")
+        pane.AddKeyHelpField( { Lang("<Enter>") : Lang("OK"), Lang("<Esc>") : Lang("Exit") } )
+        if pane.CurrentInput() is None:
+            pane.InputIndexSet(0)
+
+    def UpdateFieldsCALLPLUGIN(self):
+        pane = self.Pane()
+        pane.ResetFields()
+        pane.AddTitleField(Lang("Updating members of pool"))
+        progress = "%d / %d" % (self.hostsUpdated, self.hostsInPool)
+        pane.AddWrappedTextField(Lang("Progress", 16) + progress)
+
+    def HandleKey(self, inKey):
+        handled = False
+        if hasattr(self, "HandleKey" + self.state):
+            handled = getattr(self, "HandleKey" + self.state)(inKey)
+        if not handled and inKey == 'KEY_ESCAPE':
+            Layout.Inst().PopDialogue()
+            handled = True
+        return handled
+
+    def HandleKeyINITIAL(self, inKey):
+        return self.menu.HandleKey(inKey)
+
+    def HandleKeyGETCONTROLLER(self, inKey):
+        pane = self.Pane()
+        if pane.CurrentInput() is None:
+            pane.InputIndexSet(0)
+        if inKey == 'KEY_ENTER':
+            inputValues = pane.GetFieldValues()
+            self.controller = inputValues['address']
+            self.SetController(self.controller)
+            Layout.Inst().PopDialogue()
+            self.ChangeState("INITIAL")
+            return True
+        else:
+            return pane.CurrentInput().HandleKey(inKey)
+
+    def restartService(self, name):
+        s = NiciraService.Inst(name)
+        s.restart()
+        Layout.Inst().PopDialogue()
+
+    def getController(self):
+        self.ChangeState("GETCONTROLLER")
+        self.Pane().InputIndexSet(0)
+
+    def deleteController(self):
+        self.controller = ""
+        self.SetController(None)
+        Layout.Inst().PopDialogue()
+
+    def syncController(self):
+        Task.Sync(lambda s: self._updateThisServer(s))
+        Layout.Inst().PopDialogue()
+
+    def SetController(self, ip):
+        self.hostsInPool = 0
+        self.hostsUpdated = 0
+        self.ChangeState("CALLPLUGIN")
+        Task.Sync(lambda s: self._modifyPoolConfig(s, "niciraController", ip))
+        # Should be done asynchronously, maybe with an external script?
+        Task.Sync(lambda s: self._updateActiveServers(s))
+
+    def _modifyPoolConfig(self, session, key, value):
+        """Modify pool configuration.
+
+        If value == None then delete key, otherwise set key to value."""
+        pools = session.xenapi.pool.get_all()
+        # We assume there is only ever one pool...
+        if len(pools) == 0:
+            log.error("No pool for host.")
+            raise XenAPIPlugin.Failure("NO_POOL_FOR_HOST", [])
+        if len(pools) > 1:
+            log.error("More than one pool for host.")
+            raise XenAPIPlugin.Failure("MORE_THAN_ONE_POOL_FOR_HOST", [])
+        session.xenapi.pool.remove_from_other_config(pools[0], key)
+        if value != None:
+            session.xenapi.pool.add_to_other_config(pools[0], key, value)
+        Data.Inst().Update()
+
+    def _updateActiveServers(self, session):
+        hosts = session.xenapi.host.get_all()
+        self.hostsUpdated = 0
+        self.hostsInPool = len(hosts)
+        self.UpdateFields()
+        for host in hosts:
+            session.xenapi.host.call_plugin(host, "vswitch-cfg-update", "update", {})
+            self.hostsUpdated = self.hostsUpdated + 1
+            self.UpdateFields()
+
+    def _updateThisServer(self, session):
+        data = Data.Inst()
+        host = data.host.opaqueref()
+        session.xenapi.host.call_plugin(host, "vswitch-cfg-update", "update", {})
+
+
+class XSFeatureNiciraVSwitch:
+
+    @classmethod
+    def StatusUpdateHandler(cls, inPane):
+        data = Data.Inst()
+
+        inPane.AddTitleField(Lang("Nicira VSwitch"))
+
+        inPane.NewLine()
+
+        host = data.host()
+        try:
+            versionStr = host["other_config"]["niciraSwitchVersion"]
+        except KeyError, e:
+            versionStr = "<Unknown>"
+        inPane.AddStatusField(Lang("Version", 20), versionStr)
+
+        inPane.NewLine()
+        pool = data.pools().values()[0]
+        try:
+            dbController = pool["other_config"]["niciraController"]
+        except KeyError, e:
+            dbController = ""
+        if dbController == "":
+            dbController = Lang("<None>")
+        inPane.AddStatusField(Lang("Controller (config)", 20), dbController)
+        controller = VSwitchConfig.Get("mgmt.controller")
+        if controller == "":
+            controller = Lang("<None>")
+        elif controller[0:4] == "ssl:":
+            controller = controller[4:]
+        inPane.AddStatusField(Lang("Controller (in-use)", 20), controller)
+
+        inPane.NewLine()
+        inPane.AddStatusField(Lang("vswitchd status", 20),
+                              NiciraService.Inst("vswitch", "vswitchd").status())
+        inPane.AddStatusField(Lang("brcompatd status", 20),
+                              NiciraService.Inst("vswitch", "brcompatd").status())
+
+        inPane.AddKeyHelpField( {
+            Lang("<Enter>") : Lang("Reconfigure"),
+            Lang("<F5>") : Lang("Refresh")
+        })
+
+    @classmethod
+    def ActivateHandler(cls):
+        DialogueUtils.AuthenticatedOnly(lambda: Layout.Inst().PushDialogue(NiciraControllerDialogue()))
+
+    def Register(self):
+        Importer.RegisterNamedPlugIn(
+            self,
+            'NiciraVSwitch', # Key of this plugin for replacement, etc.
+            {
+                'menuname' : 'MENU_NETWORK',
+                'menupriority' : 800,
+                'menutext' : Lang('Nicira VSwitch') ,
+                'statusupdatehandler' : self.StatusUpdateHandler,
+                'activatehandler' : self.ActivateHandler
+            }
+        )
+
+# Register this plugin when module is imported
+XSFeatureNiciraVSwitch().Register()
diff --git a/xenserver/vswitch-xen.spec b/xenserver/vswitch-xen.spec
new file mode 100644 (file)
index 0000000..eb5049d
--- /dev/null
@@ -0,0 +1,263 @@
+# Spec file for vswitch and related programs.
+
+# Copyright (C) 2009 Nicira Networks, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.  This file is offered as-is,
+# without warranty of any kind.
+
+# When building, the rpmbuild command line should define
+# vswitch_version, xen_version, and build_number using -D arguments.
+# for example:
+#
+#    rpmbuild -D "vswitch_version 0.8.9~1+build123" -D "xen_version 2.6.18-128.1.1.el5.xs5.1.0.483.1000xen" -D "build_number --with-build-number=123" -bb /usr/src/redhat/SPECS/vswitch-xen.spec
+#
+%define version %{vswitch_version}-%{xen_version}
+%define _prefix /root/vswitch
+
+Name: vswitch
+Summary: Virtual switch
+Group: System Environment/Daemons
+URL: http://www.vswitch.org/
+Version: %{vswitch_version}
+License: GPL3
+Release: 1
+Source: openvswitch+ext-%{vswitch_version}.tar.gz
+Buildroot: /tmp/vswitch-xen-rpm
+
+%description
+The vswitch provides standard network briding functions augmented with
+support for the OpenFlow protocol for remote per-flow control of
+traffic.
+
+%prep
+%setup -q -n openvswitch+ext-%{vswitch_version}
+
+%build
+./configure --prefix=%{_prefix} --localstatedir=%{_localstatedir} --with-l26=/lib/modules/%{xen_version}/build --enable-ssl %{build_number}
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT prefix=%{_prefix}
+install -d -m 755 $RPM_BUILD_ROOT/etc
+install -d -m 755 $RPM_BUILD_ROOT/etc/init.d
+install -m 755 xenserver/etc_init.d_vswitch \
+         $RPM_BUILD_ROOT/etc/init.d/vswitch
+install -m 755 xenserver/etc_init.d_vswitch-xapi-update \
+         $RPM_BUILD_ROOT/etc/init.d/vswitch-xapi-update
+install -d -m 755 $RPM_BUILD_ROOT/etc/sysconfig
+install -m 755 xenserver/etc_sysconfig_vswitch.example \
+         $RPM_BUILD_ROOT/etc/sysconfig/vswitch.example
+install -d -m 755 $RPM_BUILD_ROOT/etc/logrotate.d
+install -m 755 xenserver/etc_logrotate.d_vswitch \
+         $RPM_BUILD_ROOT/etc/logrotate.d/vswitch
+install -d -m 755 $RPM_BUILD_ROOT/etc/profile.d
+install -m 755 xenserver/etc_profile.d_vswitch.sh \
+         $RPM_BUILD_ROOT/etc/profile.d/vswitch.sh
+install -d -m 755 $RPM_BUILD_ROOT/etc/xapi.d/plugins
+install -m 755 xenserver/etc_xapi.d_plugins_vswitch-cfg-update \
+         $RPM_BUILD_ROOT/etc/xapi.d/plugins/vswitch-cfg-update
+install -d -m 755 $RPM_BUILD_ROOT%{_prefix}/scripts
+install -m 755 xenserver/opt_xensource_libexec_interface-reconfigure \
+             $RPM_BUILD_ROOT%{_prefix}/scripts/interface-reconfigure
+install -m 755 xenserver/etc_xensource_scripts_vif \
+             $RPM_BUILD_ROOT%{_prefix}/scripts/vif
+install -m 755 \
+        xenserver/usr_lib_xsconsole_plugins-base_XSFeatureNiciraVSwitch.py \
+               $RPM_BUILD_ROOT%{_prefix}/scripts/XSFeatureNiciraVSwitch.py
+
+install -d -m 755 $RPM_BUILD_ROOT%{_prefix}/kernel_modules
+find datapath/linux-2.6 -name *.ko -exec install -m 755  \{\} $RPM_BUILD_ROOT%{_prefix}/kernel_modules/ \;
+
+# Get rid of stuff we don't want to make RPM happy.
+rm -rf $RPM_BUILD_ROOT/root/vswitch/bin/controller \
+    $RPM_BUILD_ROOT/root/vswitch/bin/ovs-* \
+    $RPM_BUILD_ROOT/root/vswitch/bin/secchan \
+    $RPM_BUILD_ROOT/root/vswitch/bin/wdt \
+    $RPM_BUILD_ROOT/root/vswitch/sbin/ovs-monitor \
+    $RPM_BUILD_ROOT/root/vswitch/share/man/man8/controller.8 \
+    $RPM_BUILD_ROOT/root/vswitch/share/man/man8/ovs-*.8 \
+    $RPM_BUILD_ROOT/root/vswitch/share/man/man8/secchan.8 \
+    $RPM_BUILD_ROOT/root/vswitch/share/openvswitch
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%pre
+if [ ! -f /etc/xensource-inventory ]; then
+    printf "XenSource inventory not present in /etc/xensource-inventory"
+    exit 1
+fi
+
+if [ "$1" = "1" ]; then
+    if ! md5sum -c --status <<EOF
+b8e9835862ef1a9cec2a3f477d26c989  /etc/xensource/scripts/vif
+51970ad613a3996d5997e18e44db47da  /opt/xensource/libexec/interface-reconfigure
+EOF
+    then
+        printf "\nThe original XenServer scripts replaced by this package\n"
+        printf "are different than expected.  This could lead to unexpected\n"
+        printf "behavior of your server.  Unless you are sure you know what\n"
+        printf "you are doing, it is highly recomended that you remove this\n"
+        printf "package immediately after the install completes, which\n"
+        printf "will restore the XenServer scripts that you were previously\n"
+        printf "using.\n\n"
+    fi
+fi
+
+
+%post
+source /etc/xensource-inventory
+
+xe host-param-set \
+    "other-config:niciraSwitchVersion=%{version}" uuid="$INSTALLATION_UUID"
+
+# Ensure vswitchd.conf exists
+touch /etc/vswitchd.conf
+
+# Replace original XenServer files
+mkdir -p %{_prefix}/xs-original \
+    || printf "Could not create script backup directory.\n"
+for f in \
+    /opt/xensource/libexec/interface-reconfigure \
+    /etc/xensource/scripts/vif
+do
+    s=$(basename "$f")
+    t=$(readlink "$f")
+    if [ "$t" != "%{_prefix}/scripts/$s" ]; then
+        mv "$f" %{_prefix}/xs-original/ \
+            || printf "Could not save original XenServer $s script\n"
+        ln -s "%{_prefix}/scripts/$s" "$f" \
+            || printf "Could not link to Nicira $s script\n"
+    fi
+done
+
+# Install xsconsole plugin
+plugin=$(readlink /usr/lib/xsconsole/plugins-base/XSFeatureNiciraVSwitch.py)
+if [ "$plugin" != "/root/vswitch/scripts/XSFeatureNiciraVSwitch.py" ]; then
+    rm -f /usr/lib/xsconsole/plugins-base/XSFeatureNiciraVSwitch.py
+    ln -s /root/vswitch/scripts/XSFeatureNiciraVSwitch.py /usr/lib/xsconsole/plugins-base/ || printf "Could not link to Nicira xsconsole plugin.\n"
+fi
+
+# Modify conf files for compatibility with our interface-reconfigure
+for pif in $(xe pif-list host-uuid=$INSTALLATION_UUID params=uuid | awk '{print $5}'); do
+    /opt/xensource/libexec/interface-reconfigure --pif-uuid $pif rewrite
+done
+
+# Ensure all required services are set to run
+for s in vswitch vswitch-xapi-update; do
+    if chkconfig --list $s >/dev/null 2>&1; then
+        chkconfig --del $s || printf "Could not remove $s init script."
+    fi
+    chkconfig --add $s || printf "Could not add $s init script."
+    chkconfig $s on || printf "Could not enable $s init script."
+done
+
+if [ "$1" = "1" ]; then    # $1 = 2 for upgrade
+    printf "\nYou MUST reboot the server NOW to complete the change to the\n"
+    printf "the Nicira vswitch.  Attmepts to modify networking on the server\n"
+    printf "or any hosted VM will fail until after the reboot and could\n"
+    printf "leave the server in an state requiring manual recovery.\n\n"
+else
+    printf "\nTo use the new Nicira vswitch, you should reboot the server\n"
+    printf "now.  Failure to do so may result in incorrect operation.\n\n"
+fi
+
+%preun
+if [ "$1" = "0" ]; then     # $1 = 1 for upgrade
+    for s in vswitch vswitch-xapi-update; do
+        chkconfig --del $s || printf "Could not remove $s init script."
+    done
+    # Restore standard Xen interface-reconfigure compatible conf files
+    source /etc/xensource-inventory
+    for pif in $(xe pif-list host-uuid=$INSTALLATION_UUID params=uuid | awk '{print $5}'); do
+        %{_prefix}/xs-original/interface-reconfigure --pif-uuid $pif rewrite
+    done
+fi
+
+
+%postun
+if [ "$1" = "0" ]; then     # $1 = 1 for upgrade
+
+    rm -f /usr/lib/xsconsole/plugins-base/XSFeatureNiciraVSwitch.py \
+        /usr/lib/xsconsole/plugins-base/XSFeatureNiciraVSwitch.pyc \
+        /usr/lib/xsconsole/plugins-base/XSFeatureNiciraVSwitch.pyo \
+        || printf "Could not remove Nicira xsconsole plugin.\n"
+
+    # Restore original XenServer scripts
+    for f in \
+        /opt/xensource/libexec/interface-reconfigure \
+        /etc/xensource/scripts/vif
+    do
+        s=$(basename "$f")
+        if [ ! -f "%{_prefix}/xs-original/$s" ]; then
+            printf "Original XenServer $s script not present in %{_prefix}/xs-original\n"
+            printf "Could not restore original XenServer script.\n"
+        else
+            (rm -f "$f" \
+                && mv "%{_prefix}/xs-original/$s" "$f") \
+                || printf "Could not restore original XenServer $s script.\n"
+        fi
+    done
+
+    find  %{_prefix} -type d -depth -exec rmdir \{\} \; \
+        || printf "Could not remove Nicira vswitch install directory.\n"
+
+    # Remove all configuration and log files
+    rm -f /etc/vswitchd.conf
+    rm -f /etc/sysconfig/vswitch
+    rm -f /var/log/vswitch*
+    rm -f /etc/vswitchd.cacert
+
+    if [ ! -f /etc/xensource-inventory ]; then
+        printf "XenSource inventory not present in /etc/xensource-inventory\n"
+        printf "Could not remove niciraSwitchVersion from XAPI database.\n"
+        exit 1
+    else
+        source /etc/xensource-inventory
+        xe host-param-remove \
+            param-name=other-config param-key=niciraSwitchVersion \
+            uuid="$INSTALLATION_UUID"
+    fi
+
+    printf "\nYou MUST reboot the server now to complete the change to\n"
+    printf "standard Xen networking.  Attempts to modify networking on the\n"
+    printf "server or any hosted VM will fail until after the reboot and\n"
+    printf "could leave the server in a state requiring manual recovery.\n\n"
+fi
+
+
+%files
+%defattr(-,root,root)
+/etc/init.d/vswitch
+/etc/init.d/vswitch-xapi-update
+/etc/xapi.d/plugins/vswitch-cfg-update
+/etc/sysconfig/vswitch.example
+/etc/logrotate.d/vswitch
+/etc/profile.d/vswitch.sh
+/root/vswitch/kernel_modules/brcompat_mod.ko
+/root/vswitch/kernel_modules/openvswitch_mod.ko
+/root/vswitch/kernel_modules/veth_mod.ko
+/root/vswitch/scripts/interface-reconfigure
+/root/vswitch/scripts/vif
+/root/vswitch/scripts/XSFeatureNiciraVSwitch.py
+# Following two files are generated automatically by rpm.  We don't
+# really need them and they won't be used on the XenServer, but there
+# isn't an obvious place to get rid of them since they are generated
+# after the install script runs.  Since they are small, we just
+# include them.
+/root/vswitch/scripts/XSFeatureNiciraVSwitch.pyc
+/root/vswitch/scripts/XSFeatureNiciraVSwitch.pyo
+/root/vswitch/sbin/brcompatd
+/root/vswitch/sbin/vswitchd
+/root/vswitch/bin/cfg-mod
+/root/vswitch/bin/dpctl
+/root/vswitch/bin/vlogconf
+/root/vswitch/share/man/man5/vswitchd.conf.5
+/root/vswitch/share/man/man8/brcompatd.8
+/root/vswitch/share/man/man8/cfg-mod.8
+/root/vswitch/share/man/man8/dpctl.8
+/root/vswitch/share/man/man8/vlogconf.8
+/root/vswitch/share/man/man8/vswitchd.8