diff options
author | Greg Rose <gvrose8192@gmail.com> | 2022-08-08 13:36:02 -0700 |
---|---|---|
committer | Ilya Maximets <i.maximets@ovn.org> | 2022-08-15 13:07:13 +0200 |
commit | 83c9518e7c67fb73ab17f6db50f398dc78403814 (patch) | |
tree | 7290abe2d043c4f30d55975f6f2d25608a9feadc /xenserver | |
parent | ac1332216eb3a1857b942457e1b44a22512b092d (diff) | |
download | openvswitch-83c9518e7c67fb73ab17f6db50f398dc78403814.tar.gz |
xenserver: Remove xenserver.
Remove the current xenserver implementation - it is obsolete and
since 3.0 we do not support kernel module builds [1].
1. https://mail.openvswitch.org/pipermail/ovs-dev/2022-July/395789.html
[i.maximets]
Can be added back if people willing to maintain it will be found.
Signed-off-by: Greg Rose <gvrose8192@gmail.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'xenserver')
19 files changed, 0 insertions, 6087 deletions
diff --git a/xenserver/.gitignore b/xenserver/.gitignore deleted file mode 100644 index 3679eea07..000000000 --- a/xenserver/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/openvswitch-xen.spec diff --git a/xenserver/GPLv2 b/xenserver/GPLv2 deleted file mode 100644 index d511905c1..000000000 --- a/xenserver/GPLv2 +++ /dev/null @@ -1,339 +0,0 @@ - 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 Lesser 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. - - 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.) - -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. - - 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. - - 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 - - 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 Lesser General -Public License instead of this License. diff --git a/xenserver/LICENSE b/xenserver/LICENSE deleted file mode 100644 index 00fc4d8cb..000000000 --- a/xenserver/LICENSE +++ /dev/null @@ -1,518 +0,0 @@ -As a special exception to the GNU Lesser General Public License, you -may link, statically or dynamically, a "work that uses the Library" -with a publicly distributed version of the Library to produce an -executable file containing portions of the Library, and distribute -that executable file under terms of your choice, without any of the -additional requirements listed in clause 6 of the GNU Lesser General -Public License. By "a publicly distributed version of the Library", -we mean either the unmodified Library as distributed, or a -modified version of the Library that is distributed under the -conditions defined in clause 3 of the GNU Library General Public -License. This exception does not however invalidate any other reasons -why the executable file might be covered by the GNU Lesser General -Public License. - ------------- - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 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. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -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 and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, 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 library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete 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 distribute a copy of this License along with the -Library. - - 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 Library or any portion -of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -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 Library, 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 Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you 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. - - If distribution of 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 satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be 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. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library 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. - - 9. 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 Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -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 with -this License. - - 11. 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 Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library 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 Library. - -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. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library 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. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser 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 Library -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 Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -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 - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "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 -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. 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 LIBRARY 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 -LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/xenserver/README.rst b/xenserver/README.rst deleted file mode 100644 index c30805fc3..000000000 --- a/xenserver/README.rst +++ /dev/null @@ -1,175 +0,0 @@ -.. - Copyright (C) 2009, 2010, 2011 Nicira, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); you may - not use this file except in compliance with the License. You may obtain - a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - License for the specific language governing permissions and limitations - under the License. - - Convention for heading levels in Open vSwitch documentation: - - ======= Heading 0 (reserved for the title in a document) - ------- Heading 1 - ~~~~~~~ Heading 2 - +++++++ Heading 3 - ''''''' Heading 4 - - Avoid deeper levels because they do not render well. - -================ -XenServer README -================ - -This directory contains files for seamless integration of Open vSwitch on -Citrix XenServer hosts managed by the Citrix management tools. - -Files in this directory are licensed on a file-by-file basis. Refer to each -file for details. - -Most of the files in this directory are installed on a XenServer system under -the same name; underscores are replaced by slashes. The files are: - -etc_init.d_openvswitch - Initializes Open vSwitch at boot and shuts it down at shutdown. - -etc_init.d_openvswitch-xapi-update - Init script to ensure openvswitch-cfg-update is called for the current host - at boot. - -etc_logrotate.d_openvswitch - Ensures that logs in /var/log/openvswitch are rotated periodically and that - appropriate daemons reopen their log files at that point. - -etc_profile.d_openvswitch.sh - Open vSwitch-related shell functions for the administrator's convenience. - -etc_xapi.d_plugins_openvswitch-cfg-update - xapi plugin script to update the cache of configuration items in the - ovs-vswitchd configuration that are managed in the xapi database when - integrated with Citrix management tools. - -etc_xensource_scripts_vif - Open vSwitch-aware replacement for Citrix script of the same name. - -openvswitch-xen.spec - spec file for building RPMs to install on a XenServer host. - -opt_xensource_libexec_interface-reconfigure - Open vSwitch-aware replacements for Citrix script of the same names. - -opt_xensource_libexec_InterfaceReconfigureBridge.py - See above. - -opt_xensource_libexec_InterfaceReconfigure.py - See above. - -opt_xensource_libexec_InterfaceReconfigureVswitch.py - See above. - -usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py - xsconsole plugin to configure the pool-wide configuration keys used to - control Open vSwitch when integrated with Citrix management tools. - -usr_share_openvswitch_scripts_ovs-xapi-sync - Daemon to monitor the external_ids columns of the Bridge and Interface OVSDB - tables for changes that require interrogating XAPI. - -usr_share_openvswitch_scripts_sysconfig.template - Template for Open vSwitch's /etc/sysconfig/openvswitch configuration file. - -Open vSwitch installs a number of xen-bugtool extensions in -``/etc/xensource/bugtool`` to gather additional information useful for -debugging. The sources for the extensions are in -``../utilities/bugtool/plugins``: - -kernel-info/openvswitch.xml - Collect kernel information relevant to Open vSwitch, such as slabinfo. - -network-status/openvswitch.xml - Collect networking information relevant to Open vSwitch. Runs the following - scripts, which are described below: - - * ovs-bugtool-bfd-show - * ovs-bugtool-cfm-show - * ovs-bugtool-fdb-show - * ovs-bugtool-lacp-show - * ovs-bugtool-list-dbs - * ovs-bugtool-ovsdb-dump - * ovs-bugtool-tc-class-show - * ovs-bugtool-bond-show - * ovs-bugtool-ovs-ofctl-show - * ovs-bugtool-ovs-ofctl-dump-flows - * ovs-bugtool-ovs-appctl-dpif - * ovs-bugtool-coverage-show - * ovs-bugtool-memory-show - * ovs-bugtool-vsctl-show - * ovs-bugtool-conntrack-dump - -system-configuration/openvswitch.xml - Collect system configuration information relevant to Open vSwitch, including - timezone. Runs the following script which is described below: - - * ovs-bugtool-daemons-ver - -system-configuration.xml - Collect system configuration data. This category is configured to collect up - to 1Mb of data, take up to 60 seconds to collect data, run every time and is - hidden from display in XenCenter. - -A number of scripts are installed in ``/usr/share/openvswitch/scripts`` to -assist Open vSwitch's xen-bugtool extensions. The sources for the scripts are -located in ``../utilities/bugtool``: - -ovs-bugtool-bfd-show - Script to dump detailed BFD information for all enabled interfaces. - -ovs-bugtool-cfm-show - Script to dump detailed CFM information for all enabled interfaces. - -ovs-bugtool-fdb-show - Script to collect a summary of learned MACs for each bridge. - -ovs-bugtool-lacp-show - Script to dump detailed LACP information for all enabled ports. - -ovs-bugtool-list-dbs - Script to list the databases controlled by ovsdb-server. - -ovs-bugtool-ovsdb-dump - Script to dump contents of Open vSwitch configuration database in - comma-separated value format. - -ovs-bugtool-tc-class-show - Script to dump tc class configuration for all network interfaces. - -ovs-bugtool-ovs-ofctl-show - Script to dump information about flow tables and ports of each bridge. - -ovs-bugtool-ovs-ofctl-dump-flows - Script to dump openflow flows of each bridge. - -ovs-bugtool-ovs-appctl-dpif - Script to collect a summary of configured datapaths and datapath flows. - -ovs-bugtool-coverage-show - Script to count the number of times particular events occur during - ovs-vswitchd's runtime. - -ovs-bugtool-memory-show - Script to show some basic statistics about ovs-vswitchd's memory usage. - -ovs-bugtool-vsctl-show - Script to show a brief overview of the database contents. - -ovs-bugtool-conntrack-dump - Script to show all the connection entries in the tracker. - -ovs-bugtool-daemons-ver - Script to dump version information for all Open vSwitch daemons. diff --git a/xenserver/automake.mk b/xenserver/automake.mk deleted file mode 100644 index ead0f4a7c..000000000 --- a/xenserver/automake.mk +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 2009, 2010, 2011, 2012, 2014 Nicira, 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/GPLv2 \ - xenserver/LICENSE \ - xenserver/README.rst \ - xenserver/automake.mk \ - xenserver/etc_init.d_openvswitch \ - xenserver/etc_init.d_openvswitch-xapi-update \ - xenserver/etc_logrotate.d_openvswitch \ - xenserver/etc_profile.d_openvswitch.sh \ - xenserver/etc_xapi.d_plugins_openvswitch-cfg-update \ - xenserver/etc_xensource_scripts_vif \ - xenserver/openvswitch-xen.spec \ - xenserver/openvswitch-xen.spec.in \ - xenserver/opt_xensource_libexec_InterfaceReconfigure.py \ - xenserver/opt_xensource_libexec_InterfaceReconfigureBridge.py \ - xenserver/opt_xensource_libexec_InterfaceReconfigureVswitch.py \ - xenserver/opt_xensource_libexec_interface-reconfigure \ - xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py \ - xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync \ - xenserver/usr_share_openvswitch_scripts_sysconfig.template - -FLAKE8_PYFILES += \ - xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync - -$(srcdir)/xenserver/openvswitch-xen.spec: xenserver/openvswitch-xen.spec.in $(top_builddir)/config.status - $(AM_V_GEN)($(ro_shell) && sed -e 's,[@]VERSION[@],$(VERSION),g') \ - < $(srcdir)/xenserver/$(@F).in > $(@F).tmp || exit 1; \ - if cmp -s $(@F).tmp $@; then touch $@; rm $(@F).tmp; else mv $(@F).tmp $@; fi diff --git a/xenserver/etc_init.d_openvswitch b/xenserver/etc_init.d_openvswitch deleted file mode 100755 index 7d2103fa2..000000000 --- a/xenserver/etc_init.d_openvswitch +++ /dev/null @@ -1,154 +0,0 @@ -#!/bin/sh -# -# openvswitch -# -# chkconfig: 2345 09 91 -# description: Manage Open vSwitch kernel modules and user-space daemons - -# Copyright (C) 2009, 2010, 2011 Nicira, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -### BEGIN INIT INFO -# Provides: openvswitch-switch -# Required-Start: -# Required-Stop: -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Open vSwitch switch -### END INIT INFO - -. /usr/share/openvswitch/scripts/ovs-lib || exit 1 -. /etc/xensource-inventory -test -e /etc/sysconfig/openvswitch && . /etc/sysconfig/openvswitch - -case `cat /etc/xensource/network.conf` in - vswitch|openvswitch) - ;; - bridge) - exit 0 - ;; - *) - echo "Open vSwitch disabled (/etc/xensource/network.conf is invalid)" >&2 - exit 0 - ;; -esac - -start_ovs_xapi_sync () { - if daemon_is_running ovs-xapi-sync; then - log_success_msg "ovs-xapi-sync is already running" - else - PYTHONPATH=/usr/share/openvswitch/python \ - /usr/share/openvswitch/scripts/ovs-xapi-sync \ - --log-file --pidfile --detach --monitor unix:/var/run/openvswitch/db.sock - fi -} - -start () { - set ovs_ctl ${1-start} - set "$@" --system-id="$INSTALLATION_UUID" - set "$@" --system-type="$PRODUCT_BRAND" - set "$@" --system-version="$PRODUCT_VERSION-$BUILD_NUMBER" - set "$@" --external-id=xs-system-uuid="$INSTALLATION_UUID" - set "$@" --daemon-cwd=/var/xen/openvswitch - if test X"$FORCE_COREFILES" != X; then - set "$@" --force-corefiles="$FORCE_COREFILES" - fi - if test X"$OVSDB_SERVER_PRIORITY" != X; then - set "$@" --ovsdb-server-priority="$OVSDB_SERVER_PRIORITY" - fi - if test X"$VSWITCHD_PRIORITY" != X; then - set "$@" --ovs-vswitchd-priority="$VSWITCHD_PRIORITY" - fi - if test X"$VSWITCHD_MLOCKALL" != X; then - set "$@" --mlockall="$VSWITCHD_MLOCKALL" - fi - if test ! -e /var/run/openvswitch.booted; then - touch /var/run/openvswitch.booted - set "$@" --delete-bridges - fi - set "$@" $OVS_CTL_OPTS - "$@" - - start_ovs_xapi_sync - - ovs_ctl --protocol=gre enable-protocol - - touch /var/lock/subsys/openvswitch -} - -force_reload_kmod () { - start force-reload-kmod - - # Restart the high-availability daemon if it is running. Otherwise - # it loses its heartbeat and reboots the system after a few minutes. - if pidof xhad >/dev/null && test -e /etc/xensource/xhad.conf; then - PATH=$PATH:/opt/xensource/xha - action "Stopping HA daemon" ha_stop_daemon - action "Starting HA daemon" ha_start_daemon - fi - - action "Stopping ovs-xapi-sync" stop_daemon ovs-xapi-sync - action "Starting ovs-xapi-sync" start_ovs_xapi_sync -} - -stop () { - ovs_ctl stop - stop_daemon ovs-xapi-sync - rm -f /var/lock/subsys/openvswitch -} - -restart () { - if [ "$1" = "--save-flows=yes" ]; then - stop_daemon ovs-xapi-sync - start restart - else - stop - start - fi -} - -case $1 in - start) - start - ;; - stop) - stop - ;; - restart) - shift - restart "$@" - ;; - reload|force-reload) - # The main OVS daemons keep up-to-date, but ovs-xapi-sync needs help. - if daemon_is_running ovs-xapi-sync; then - action "Configuring Open vSwitch external IDs" \ - ovs-appctl -t ovs-xapi-sync flush-cache - fi - ;; - status) - ovs_ctl status && daemon_status ovs-xapi-sync - ;; - version) - ovs_ctl version - ;; - force-reload-kmod) - force_reload_kmod - ;; - help) - printf "openvswitch [start|stop|restart|reload|force-reload|status|version]\n" - ;; - *) - printf "Unknown command: $1\n" - exit 1 - ;; -esac diff --git a/xenserver/etc_init.d_openvswitch-xapi-update b/xenserver/etc_init.d_openvswitch-xapi-update deleted file mode 100755 index 12a9db2a1..000000000 --- a/xenserver/etc_init.d_openvswitch-xapi-update +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/bash -# -# openvswitch-xapi-update -# -# chkconfig: 2345 95 01 -# description: Update Open vSwitch configuration from XAPI database at boot - -# Copyright (C) 2009, 2010 Nicira, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -### BEGIN INIT INFO -# Provides: openvswitch-xapi-update -# Required-Start: $network $remote_fs -# Required-Stop: $network -# Default-Start: 3 5 -# Default-Stop: -# Short-Description: openvswitch-xapi-update -# Description: reconfigures Open vSwitch based on XAPI configuration -### END INIT INFO - -. /etc/init.d/functions - -function do_host_call { - xe host-call-plugin host-uuid="$INSTALLATION_UUID" plugin="openvswitch-cfg-update" fn="update" >/dev/null -} - -function start { - if [ ! -f /etc/xensource-inventory ]; then - printf "openvswitch-xapi-update ERROR: XenSource inventory not present in /etc/xensource-inventory\n" - exit 1 - fi - - if test -e /etc/xensource/network.conf; then - NETWORK_MODE=$(cat /etc/xensource/network.conf) - fi - - case ${NETWORK_MODE:=openvswitch} in - vswitch|openvswitch) - ;; - bridge) - exit 0 - ;; - *) - echo "Open vSwitch disabled (/etc/xensource/network.conf is invalid)" >&2 - exit 0 - ;; - esac - - source /etc/xensource-inventory - action "Updating configuration" do_host_call -} - -case "$1" in - start) - start - ;; - stop) - # Nothing to do here. - ;; - restart) - start - ;; - help) - printf "openvswitch-xapi-update [start|stop|restart]\n" - ;; - *) - printf "Unknown command: $1\n" - exit 1 - ;; -esac diff --git a/xenserver/etc_logrotate.d_openvswitch b/xenserver/etc_logrotate.d_openvswitch deleted file mode 100644 index cd7b3a9d5..000000000 --- a/xenserver/etc_logrotate.d_openvswitch +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (C) 2009, 2010, 2011, 2012, 2017 Nicira, 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/openvswitch/*.log { - daily - compress - sharedscripts - missingok - postrotate - # Tell Open vSwitch daemons to reopen their log files - if [ -d /var/run/openvswitch ]; then - for pidfile in `cd /var/run/openvswitch && echo *.pid`; do - ovs-appctl -t "${pidfile%%.pid}" vlog/reopen 2>/dev/null || : - done - fi - endscript -} diff --git a/xenserver/etc_profile.d_openvswitch.sh b/xenserver/etc_profile.d_openvswitch.sh deleted file mode 100644 index 63b254359..000000000 --- a/xenserver/etc_profile.d_openvswitch.sh +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (C) 2009, 2010, 2011 Nicira, 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. - -alias vswitch='service openvswitch' -alias openvswitch='service openvswitch' - -function watchdp { - watch ovs-dpctl show "$@" -} - -function watchdpflows { - local grep="" - local dp=$1 - shift - if [ $# -gt 0 ]; then - grep="| grep $@" - fi - watch "ovs-dpctl dump-flows $dp $grep" -} - -function watchflows { - local grep="" - local dp=$1 - shift - bridge=$(ovs-dpctl show $dp | grep 'port 0:' | cut -d' ' -f 3) - if [ $# -gt 0 ]; then - grep="| grep $@" - fi - watch "ovs-ofctl 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/openvswitch/ovs-vswitchd.log /var/log/openvswitch/ovsdb-server /var/log/xensource.log $grep | tee /var/log/monitorlogs.out" - printf "cmd: $cmd\n" - eval "$cmd" -} diff --git a/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update b/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update deleted file mode 100755 index b8db88194..000000000 --- a/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/env python3 -# -# xapi plugin script to update the cache of configuration items in the -# ovs-vswitchd configuration that are managed in the xapi database when -# integrated with Citrix management tools. - -# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2020 Nicira, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# TBD: - error handling needs to be improved. Currently this can leave -# TBD: the system in a bad state if anything goes wrong. - -import XenAPIPlugin -import os -import subprocess -import syslog -import re - -vsctl = '/usr/bin/ovs-vsctl' -ofctl = '/usr/bin/ovs-ofctl' -cacert_filename = '/etc/openvswitch/vswitchd.cacert' -ovsdb_port = '6640' - - -# Delete the CA certificate, so that we go back to boot-strapping mode -def delete_cacert(): - try: - os.remove(cacert_filename) - except OSError: - # Ignore error if file doesn't exist - pass - - -def update(session, args): - # Refresh bridge network UUIDs in case this host joined or left a pool. - script = '/opt/xensource/libexec/interface-reconfigure' - try: - retval = subprocess.call([script, 'rewrite']) - if retval != 0: - syslog.syslog('%s exited with status %d' % (script, retval)) - except OSError, e: - syslog.syslog('%s: failed to execute (%s)' % (script, e.strerror)) - - pools = session.xenapi.pool.get_all() - # We assume there is only ever one pool... - if len(pools) == 0: - raise XenAPIPlugin.Failure('NO_POOL_FOR_HOST', []) - if len(pools) > 1: - raise XenAPIPlugin.Failure('MORE_THAN_ONE_POOL_FOR_HOST', []) - new_controller = False - pool = session.xenapi.pool.get_record(pools[0]) - controller = pool.get('vswitch_controller') - ret_str = '' - currentControllers = vswitchCurrentControllers() - - if not controller and currentControllers: - delete_cacert() - try: - emergency_reset(session, None) - except: - pass - removeControllerCfg() - ret_str += 'Successfully removed controller config. ' - # controller cannot be empty, otherwise, this will always be True. - elif controller and controller not in currentControllers: - delete_cacert() - try: - emergency_reset(session, None) - except: - pass - setControllerCfg(controller) - new_controller = True - ret_str += 'Successfully set controller to %s. ' % controller - - try: - pool_fail_mode = pool['other_config']['vswitch-controller-fail-mode'] - except KeyError, e: - pool_fail_mode = None - - bton = {} - - for rec in session.xenapi.network.get_all_records().values(): - try: - bton[rec['bridge']] = rec - except KeyError: - pass - - # If new controller, get management MAC addresses from XAPI now - # in case fail_mode set to secure which may affect XAPI access - mgmt_bridge = None - host_mgmt_mac = None - host_mgmt_device = None - pool_mgmt_macs = {} - if new_controller: - query = 'field "management"="true"' - recs = session.xenapi.PIF.get_all_records_where(query) - for rec in recs.itervalues(): - pool_mgmt_macs[rec.get('MAC')] = rec.get('device') - - dib_changed = False - fail_mode_changed = False - for bridge in vswitchCfgQuery(['list-br']).split(): - network = bton[bridge] - bridge = vswitchCfgQuery(['br-to-parent', bridge]) - - xapi_dib = network['other_config'].get('vswitch-disable-in-band') - if not xapi_dib: - xapi_dib = '' - - ovs_dib = vswitchCfgQuery(['--', '--if-exists', 'get', 'Bridge', - bridge, - 'other_config:disable-in-band']).strip('"') - - # Do nothing if setting is invalid, and warn the user. - if xapi_dib not in ['true', 'false', '']: - ret_str += '"' + xapi_dib + '"' + \ - ' is an invalid value for vswitch-disable-in-band on ' + \ - bridge + ' ' - - # Change bridge disable-in-band option if XAPI and OVS states differ. - elif xapi_dib != ovs_dib: - # 'true' or 'false' - if xapi_dib: - vswitchCfgMod(['--', 'set', 'Bridge', bridge, - 'other_config:disable-in-band=' + xapi_dib]) - # '' or None - else: - vswitchCfgMod(['--', 'remove', 'Bridge', bridge, - 'other_config', 'disable-in-band']) - dib_changed = True - - # Change bridge fail_mode if XAPI state differs from OVS state. - bridge_fail_mode = vswitchCfgQuery(['get', 'Bridge', - bridge, 'fail_mode']).strip('[]"') - - try: - other_config = bton[bridge]['other_config'] - fail_mode = other_config['vswitch-controller-fail-mode'] - except KeyError, e: - fail_mode = None - - if fail_mode not in ['secure', 'standalone']: - fail_mode = pool_fail_mode - - if fail_mode != 'secure': - fail_mode = 'standalone' - - if bridge_fail_mode != fail_mode: - vswitchCfgMod(['--', 'set', 'Bridge', bridge, - 'fail_mode=%s' % fail_mode]) - fail_mode_changed = True - - # Determine local mgmt MAC address if host being added to secure - # pool so we can add default flows to allow management traffic - if new_controller and fail_mode_changed and pool_fail_mode == 'secure': - oc = vswitchCfgQuery(['get', 'Bridge', bridge, 'other-config']) - m = re.match('.*hwaddr="([0-9a-fA-F:].*)".*', oc) - if m and m.group(1) in pool_mgmt_macs.keys(): - mgmt_bridge = bridge - host_mgmt_mac = m.group(1) - host_mgmt_device = pool_mgmt_macs[host_mgmt_mac] - - if (host_mgmt_mac is not None and mgmt_bridge is not None and - host_mgmt_device is not None): - tp = 'idle_timeout=0,priority=0' - port = vswitchCfgQuery(['get', 'interface', host_mgmt_device, - 'ofport']) - - addFlow(mgmt_bridge, '%s,in_port=%s,arp,nw_proto=1,actions=local' % - (tp, port)) - addFlow(mgmt_bridge, '%s,in_port=local,arp,dl_src=%s,actions=%s' % - (tp, host_mgmt_mac, port)) - addFlow(mgmt_bridge, '%s,in_port=%s,dl_dst=%s,actions=local' % - (tp, port, host_mgmt_mac)) - addFlow(mgmt_bridge, '%s,in_port=local,dl_src=%s,actions=%s' % - (tp, host_mgmt_mac, port)) - - if dib_changed: - ret_str += 'Updated in-band management. ' - if fail_mode_changed: - ret_str += 'Updated fail_mode. ' - - if ret_str != '': - return ret_str - else: - return 'No change to configuration' - - -def vswitchCurrentControllers(): - controllers = vswitchCfgQuery(['get-manager']) - - def parse_controller(controller): - if controller.startswith('ssl:'): - return controller.split(':')[1] - - return controller.split(':')[0] - - return [parse_controller(controller) - for controller in controllers.split('\n') - if controller] - - -def removeControllerCfg(): - vswitchCfgMod(['--', 'del-manager', - '--', 'del-ssl']) - - -def setControllerCfg(controller): - # /etc/xensource/xapi-ssl.pem is mentioned twice below because it - # contains both the private key and the certificate. - vswitchCfgMod(['--', 'del-manager', - '--', 'del-ssl', - '--', '--bootstrap', 'set-ssl', - '/etc/xensource/xapi-ssl.pem', - '/etc/xensource/xapi-ssl.pem', - cacert_filename, - '--', 'set-manager', 'ssl:' + controller + ':' + ovsdb_port]) - - -def vswitchCfgQuery(action_args): - cmd = [vsctl, '-vconsole:off'] + action_args - output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate() - if len(output) == 0 or output[0] is None: - output = '' - else: - output = output[0].strip() - return output - - -def vswitchCfgMod(action_args): - cmd = [vsctl, '--timeout=5', '-vconsole:off'] + action_args - exitcode = subprocess.call(cmd) - if exitcode != 0: - raise XenAPIPlugin.Failure('VSWITCH_CONFIG_MOD_FAILURE', - [str(exitcode), str(action_args)]) - - -def emergency_reset(session, args): - cmd = [vsctl, '--timeout=5', 'emer-reset'] - exitcode = subprocess.call(cmd) - if exitcode != 0: - raise XenAPIPlugin.Failure('VSWITCH_EMER_RESET_FAILURE', - [str(exitcode)]) - - return 'Successfully reset configuration' - - -def addFlow(switch, flow): - cmd = [ofctl, 'add-flow', switch, flow] - exitcode = subprocess.call(cmd) - if exitcode != 0: - raise XenAPIPlugin.Failure('VSWITCH_ADD_FLOW_FAILURE', - [str(exitcode), str(switch), str(flow)]) - - -if __name__ == '__main__': - XenAPIPlugin.dispatch({'update': update, - 'emergency_reset': emergency_reset}) diff --git a/xenserver/etc_xensource_scripts_vif b/xenserver/etc_xensource_scripts_vif deleted file mode 100755 index 78434fb6c..000000000 --- a/xenserver/etc_xensource_scripts_vif +++ /dev/null @@ -1,265 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2008,2009 Citrix Systems, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation; version 2.1 only. with the special -# exception on linking described in file LICENSE. -# -# 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 Lesser General Public License for more details. - -# 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 - -BRCTL="/usr/sbin/brctl" -IP="/sbin/ip" - -vsctl="/usr/bin/ovs-vsctl" - -handle_promiscuous() -{ - local arg=$(xenstore-read "${PRIVATE}/other-config/promiscuous" 2>/dev/null) - if [ $? -eq 0 -a -n "${arg}" ] ; then - case $NETWORK_MODE in - bridge) - case "${arg}" in - true|on) echo 1 > /sys/class/net/${dev}/brport/promisc ;; - *) echo 0 > /sys/class/net/${dev}/brport/promisc ;; - esac - ;; - openvswitch) - logger -t script-vif "${dev}: Promiscuous ports are not supported via Open vSwitch." - ;; - esac - fi -} - -handle_ethtool() -{ - local opt=$1 - local arg=$(xenstore-read "${PRIVATE}/other-config/ethtool-${opt}" 2>/dev/null) - if [ $? -eq 0 -a -n "${arg}" ] ; then - case "${arg}" in - true|on) /sbin/ethtool -K "${dev}" "${opt}" on ;; - false|off) /sbin/ethtool -K "${dev}" "${opt}" off ;; - *) logger -t scripts-vif "Unknown ethtool argument ${opt}=${arg} on ${dev}/${VIFUUID}" ;; - esac - fi -} - -handle_mtu() -{ - local mtu=$(xenstore-read "${PRIVATE}/MTU" 2>/dev/null) - if [ $? -eq 0 -a -n "${mtu}" ]; then - logger -t scripts-vif "Setting ${dev} MTU ${mtu}" - ${IP} link set "${dev}" mtu ${mtu} || logger -t scripts-vif "Failed to ip link set ${dev} mtu ${mtu}. Error code $?" - fi -} - -set_vif_external_id() -{ - local key=$1 - local value=$2 - - logger -t scripts-vif "vif${DOMID}.${DEVID} external-ids:\"${key}\"=\"${value}\"" - - echo "-- set interface vif${DOMID}.${DEVID} external-ids:\"${key}\"=\"${value}\"" -} - -handle_vswitch_vif_details() -{ - local vm=$(xenstore-read "/local/domain/$DOMID/vm" 2>/dev/null) - if [ $? -eq 0 -a -n "${vm}" ] ; then - local vm_uuid=$(xenstore-read "$vm/uuid" 2>/dev/null) - fi - if [ -n "${vm_uuid}" ] ; then - set_vif_external_id "xs-vm-uuid" "${vm_uuid}" - fi - - local vif_uuid=$(xenstore-read "${PRIVATE}/vif-uuid" 2>/dev/null) - if [ -n "${vif_uuid}" ] ; then - set_vif_external_id "xs-vif-uuid" "${vif_uuid}" - fi - - local vif_details= - local net_uuid=$(xenstore-read "${PRIVATE}/network-uuid" 2>/dev/null) - if [ -n "${net_uuid}" ] ; then - set_vif_external_id "xs-network-uuid" "${net_uuid}" - fi - local address=$(xenstore-read "/local/domain/$DOMID/device/vif/$DEVID/mac" 2>/dev/null) - if [ -n "${address}" ] ; then - set_vif_external_id "attached-mac" "${address}" - 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" - exit 1 - 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" - exit 1 - fi - logger -t scripts-vif "Adding ${dev} to ${bridge} with address ${address}" - - ${IP} link set "${dev}" down || logger -t scripts-vif "Failed to ip link set ${dev} down" - ${IP} link set "${dev}" arp off || logger -t scripts-vif "Failed to ip link set ${dev} arp off" - ${IP} link set "${dev}" multicast off || logger -t scripts-vif "Failed to ip link set ${dev} multicast off" - ${IP} link set "${dev}" address "${address}" || logger -t scripts-vif "Failed to ip link set ${dev} address ${address}" - ${IP} addr flush "${dev}" || logger -t scripts-vif "Failed to ip addr flush ${dev}" - - case $NETWORK_MODE in - bridge) - ${BRCTL} setfd "${bridge}" 0 || logger -t scripts-vif "Failed to brctl setfd ${bridge} 0" - ${BRCTL} addif "${bridge}" "${dev}" || logger -t scripts-vif "Failed to brctl addif ${bridge} ${dev}" - ;; - openvswitch) - if [ "$TYPE" = "vif" ] ; then - local vif_details=$(handle_vswitch_vif_details $bridge) - fi - - $vsctl --timeout=30 -- --if-exists del-port $dev -- add-port $bridge $dev $vif_details - ;; - esac - - ${IP} link set "${dev}" up || logger -t scripts-vif "Failed to ip link set ${dev} up" -} - -remove_from_bridge() -{ - case $NETWORK_MODE in - bridge) - # Nothing to do - ;; - openvswitch) - $vsctl --timeout=30 -- del-port $dev - ;; - esac -} - -call_hook_script() { - local domid=$1 - local action=$2 - # Call the VIF hotplug hook if present - if [ -x /etc/xapi.d/vif-hotplug ]; then - local vm=$(xenstore-read "/local/domain/$domid/vm" 2>/dev/null) - if [ $? -eq 0 -a -n "${vm}" ] ; then - local vm_uuid=$(xenstore-read "$vm/uuid" 2>/dev/null) - fi - if [ -n "${vm_uuid}" ] ; then - logger -t scripts-vif "VM UUID ${vm_uuid}" - fi - - local vif_uuid=$(xenstore-read "${PRIVATE}/vif-uuid" 2>/dev/null) - if [ -n "${vif_uuid}" ] ; then - logger -t scripts-vif "VIF UUID ${vif_uuid}" - fi - if [ -n "${vif_uuid}" -a -n "${vm_uuid}" ] ; then - logger -t scripts-vif "Calling VIF hotplug hook for VM ${vm_uuid}, VIF ${vif_uuid}" - /etc/xapi.d/vif-hotplug -action "${action}" -vifuuid "${vif_uuid}" -vmuuid "${vm_uuid}" - fi - fi -} - -NETWORK_MODE=$(cat /etc/xensource/network.conf) -ACTION=$1 - -# Older versions of XenServer do not pass in the type as an argument -if [[ $# -lt 2 ]]; then - TYPE=vif -else - TYPE=$2 -fi - -case $NETWORK_MODE in - bridge|openvswitch) ;; - vswitch) NETWORK_MODE=openvswitch ;; - *) - logger -t scripts-vif "Unknown network mode $NETWORK_MODE" - exit 1 - ;; -esac - -case ${TYPE} in - vif) - if [ -z ${XENBUS_PATH} ]; then - DOMID=$3 - DEVID=$4 - else - DOMID=`echo ${XENBUS_PATH} | cut -f 3 -d '/'` - DEVID=`echo ${XENBUS_PATH} | cut -f 4 -d '/'` - fi - dev=vif${DOMID}.${DEVID} - ;; - tap) - dev=$INTERFACE - DOMID=`echo ${dev#tap} | cut -f 1 -d '.'` - DEVID=`echo ${dev#tap} | cut -f 2 -d '.'` - ;; - *) - logger -t scripts-vif "unknown interface type ${TYPE}" - exit 1 - ;; -esac - -XAPI=/xapi/${DOMID}/hotplug/vif/${DEVID} -HOTPLUG=/xapi/${DOMID}/hotplug/vif/${DEVID} -PRIVATE=/xapi/${DOMID}/private/vif/${DEVID} - -logger -t scripts-vif "Called as \"$@\" domid:$DOMID devid:$DEVID mode:$NETWORK_MODE" -case "${ACTION}" in -online) - if [ "${TYPE}" = "vif" ] ; then - 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" "${dev}" - 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" - call_hook_script $DOMID "${ACTION}" - fi - ;; - -add) - if [ "${TYPE}" = "tap" ] ; then - add_to_bridge - fi - ;; - -remove) - if [ "${TYPE}" = "vif" ] ;then - xenstore-rm "${HOTPLUG}/hotplug" - call_hook_script $DOMID "${ACTION}" - fi - logger -t scripts-vif "${dev} has been removed" - remove_from_bridge - ;; - -move) - if [ "${TYPE}" = "vif" ] ;then - add_to_bridge - fi -esac diff --git a/xenserver/openvswitch-xen.spec.in b/xenserver/openvswitch-xen.spec.in deleted file mode 100644 index ae22f2f5c..000000000 --- a/xenserver/openvswitch-xen.spec.in +++ /dev/null @@ -1,512 +0,0 @@ -# Spec file for Open vSwitch. - -# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, 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. - -# For XenServer version < 6.5, when building, the rpmbuild command line -# should define openvswitch_version, kernel_name, kernel_version and -# kernel_flavor using -D arguments. -# for example: -# -# rpmbuild -D "openvswitch_version 1.1.0+build123" -# -D "kernel_name NAME-xen" -# -D "kernel_version 2.6.32.12-0.7.1.xs5.6.100.323.170596" -# -D "kernel_flavor xen" -# -bb /usr/src/redhat/SPECS/openvswitch-xen.spec -# -# For XenServer version >= 6.5, use kernel_uname which should be -# the `uname -r` output. -# for example: -# -# rpmbuild -D "openvswitch_version 2.3.0+build123" -# -D "kernel_uname 3.10.0+2" -# -bb /usr/src/redhat/SPECS/openvswitch-xen.spec -# -# If tests have to be skipped while building, specify the '--without check' -# option. For example: -# rpmbuild -bb --without check xenserver/openvswitch-xen.spec - -%if %{?openvswitch_version:0}%{!?openvswitch_version:1} -%define openvswitch_version @VERSION@ -%endif - -%if %{?kernel_uname:1}%{!?kernel_uname:0} -%define kernel_name kernel -%define kernel_version %{kernel_uname} -%endif - -%if %{?kernel_name:0}%{!?kernel_name:1} -%define kernel %(rpm -qa 'kernel*xen-devel' | head -1) -%define kernel_name %(rpm -q --queryformat "%%{Name}" %{kernel} | sed 's/-devel//' | sed 's/kernel-//') -%define kernel_version %(rpm -q --queryformat "%%{Version}-%%{Release}" %{kernel}) -%define kernel_flavor xen -%endif - -%if %{?xen_version:0}%{!?xen_version:1} -%define xen_version %{kernel_version}%{?kernel_flavor:%{kernel_flavor}} -%endif - -# bump this when breaking compatibility with userspace -%define module_abi_version 0 - -# build-supplemental-pack.sh requires this naming for kernel module packages -%define module_package modules%{?kernel_flavor:-%{kernel_flavor}}-%{kernel_version} - -%bcond_without check - -Name: openvswitch -Summary: Open vSwitch daemon/database/utilities -Group: System Environment/Daemons -URL: http://www.openvswitch.org/ -Vendor: Nicira, Inc. -Version: %{openvswitch_version} - -License: ASL 2.0 -Release: 1 -Source: openvswitch-%{openvswitch_version}.tar.gz -Buildroot: /tmp/openvswitch-xen-rpm -Requires: openvswitch.ko.%{module_abi_version} - -%description -Open vSwitch provides standard network bridging functions augmented with -support for the OpenFlow protocol for remote per-flow control of -traffic. - -%package %{module_package} -Summary: Open vSwitch kernel module -Group: System Environment/Kernel -License: GPLv2 -Provides: %{name}-modules%{?kernel_flavor:-%{kernel_flavor}} = %{kernel_version}, openvswitch.ko.%{module_abi_version} -%if %{?kernel_uname:0}%{!?kernel_uname:1} -Requires: kernel%{?kernel_flavor:-%{kernel_flavor}} = %{kernel_version} -%endif -%if %{?kernel_uname:1}%{!?kernel_uname:0} -Requires: kernel-uname-r = %{kernel_version} -%endif - -%description %{module_package} -Open vSwitch Linux kernel module compiled against kernel version -%{kernel_version}%{?kernel_flavor:%{kernel_flavor}}. - -%prep -%setup -q -n openvswitch-%{openvswitch_version} - -%build -./configure --prefix=/usr --sysconfdir=/etc --localstatedir=%{_localstatedir} --with-linux=/lib/modules/%{xen_version}/build --enable-ssl CFLAGS='-g -O2 -msse -msse2' -make %{_smp_mflags} - -%install -rm -rf $RPM_BUILD_ROOT -make install DESTDIR=$RPM_BUILD_ROOT -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_openvswitch \ - $RPM_BUILD_ROOT/etc/init.d/openvswitch -install -m 755 xenserver/etc_init.d_openvswitch-xapi-update \ - $RPM_BUILD_ROOT/etc/init.d/openvswitch-xapi-update -install -d -m 755 $RPM_BUILD_ROOT/etc/sysconfig -install -d -m 755 $RPM_BUILD_ROOT/etc/logrotate.d -install -m 755 xenserver/etc_logrotate.d_openvswitch \ - $RPM_BUILD_ROOT/etc/logrotate.d/openvswitch -install -d -m 755 $RPM_BUILD_ROOT/etc/profile.d -install -m 755 xenserver/etc_profile.d_openvswitch.sh \ - $RPM_BUILD_ROOT/etc/profile.d/openvswitch.sh -install -d -m 755 $RPM_BUILD_ROOT/etc/xapi.d/plugins -install -m 755 xenserver/etc_xapi.d_plugins_openvswitch-cfg-update \ - $RPM_BUILD_ROOT/etc/xapi.d/plugins/openvswitch-cfg-update -install -d -m 755 $RPM_BUILD_ROOT/usr/share/openvswitch/scripts -install -m 755 xenserver/opt_xensource_libexec_interface-reconfigure \ - $RPM_BUILD_ROOT/usr/share/openvswitch/scripts/interface-reconfigure -install -m 644 xenserver/opt_xensource_libexec_InterfaceReconfigure.py \ - $RPM_BUILD_ROOT/usr/share/openvswitch/scripts/InterfaceReconfigure.py -install -m 644 xenserver/opt_xensource_libexec_InterfaceReconfigureBridge.py \ - $RPM_BUILD_ROOT/usr/share/openvswitch/scripts/InterfaceReconfigureBridge.py -install -m 644 xenserver/opt_xensource_libexec_InterfaceReconfigureVswitch.py \ - $RPM_BUILD_ROOT/usr/share/openvswitch/scripts/InterfaceReconfigureVswitch.py -install -m 755 xenserver/etc_xensource_scripts_vif \ - $RPM_BUILD_ROOT/usr/share/openvswitch/scripts/vif -install -m 755 xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync \ - $RPM_BUILD_ROOT/usr/share/openvswitch/scripts/ovs-xapi-sync -install -m 755 xenserver/usr_share_openvswitch_scripts_sysconfig.template \ - $RPM_BUILD_ROOT/usr/share/openvswitch/scripts/sysconfig.template -install -d -m 755 $RPM_BUILD_ROOT/usr/lib/xsconsole/plugins-base -install -m 644 \ - xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py \ - $RPM_BUILD_ROOT/usr/lib/xsconsole/plugins-base/XSFeatureVSwitch.py - -install -d -m 755 $RPM_BUILD_ROOT/lib/modules/%{xen_version}/extra/openvswitch -find datapath/linux -name *.ko -exec install -m 755 \{\} $RPM_BUILD_ROOT/lib/modules/%{xen_version}/extra/openvswitch \; - -install -d -m 755 $RPM_BUILD_ROOT/etc/xensource/bugtool -cp -rf $RPM_BUILD_ROOT/usr/share/openvswitch/bugtool-plugins/* $RPM_BUILD_ROOT/etc/xensource/bugtool - -# Get rid of stuff we don't want to make RPM happy. -rm \ - $RPM_BUILD_ROOT/usr/bin/ovs-testcontroller \ - $RPM_BUILD_ROOT/usr/bin/ovs-l3ping \ - $RPM_BUILD_ROOT/usr/bin/ovs-pki \ - $RPM_BUILD_ROOT/usr/bin/ovs-test \ - $RPM_BUILD_ROOT/usr/share/man/man8/ovs-testcontroller.8 \ - $RPM_BUILD_ROOT/usr/share/man/man8/ovs-l3ping.8 \ - $RPM_BUILD_ROOT/usr/share/man/man8/ovs-pki.8 \ - $RPM_BUILD_ROOT/usr/share/man/man8/ovs-test.8 -(cd "$RPM_BUILD_ROOT" && rm -f usr/lib/lib*) -(cd "$RPM_BUILD_ROOT" && rm -rf usr/include) -(cd "$RPM_BUILD_ROOT" && rm -rf usr/lib/pkgconfig) - -install -d -m 755 $RPM_BUILD_ROOT/var/lib/openvswitch - -%check -%if %{with check} - if make check TESTSUITEFLAGS='%{_smp_mflags}' RECHECK=yes; then :; - else - cat tests/testsuite.log - exit 1 - fi -%endif - -%clean -rm -rf $RPM_BUILD_ROOT - -%post -# A list of Citrix XenServer scripts that we might need to replace -# with our own versions. -scripts=" - /etc/xensource/scripts/vif - /opt/xensource/libexec/InterfaceReconfigure.py - /opt/xensource/libexec/InterfaceReconfigureBridge.py - /opt/xensource/libexec/InterfaceReconfigureVswitch.py - /opt/xensource/libexec/interface-reconfigure" - -# Calculate into $md5sums a comma-separated set of md5sums of the -# Citrix XenServer scripts that we might need to replace. We might be -# upgrading an older version of the package that moved the files out -# of the way, so we need to look for the files in those out-of-the-way -# locations first. -md5sums= -for script in $scripts; do - b=$(basename "$script") - if test -e /usr/lib/openvswitch/xs-saved/"$b"; then - f=/usr/lib/openvswitch/xs-saved/"$b" - elif test -e /usr/lib/openvswitch/xs-original/"$b"; then - f=/usr/lib/openvswitch/xs-original/"$b" - elif test -e "$script" && test ! -h "$script"; then - f=$script - else - printf "\n$script: not found\n" - f=/dev/null - fi - md5sums="$md5sums,$(md5sum $f | awk '{print $1}')" -done -md5sums=${md5sums#,} - -# Now check the md5sums against the known sets of md5sums: -# -# - If they are known to be a version of XenServer scripts that we should -# replace, we replace them (by putting $scripts into $replace_files). -# -# - Otherwise, we guess that it's better not to replace them, because the -# improvements that our versions of the scripts provide are minimal, so -# it's better to avoid possibly breaking any changes made upstream by -# Citrix. -case $md5sums in - cf09a68d9f8b434e79a4c83b01a3bb4b,395866df1b0b20c12c4dd2f7de0ecdb4,9d493545ae81463239d3162cbc798852,862d0939b441de9264a900628e950fe9,21f85db25599d7f026cd489385d58aa6) - keep_files= - replace_files=$scripts - printf "\nVerified host scripts from XenServer 6.0.0.\n" - ;; - - c5f48246577a17cf1b971fb5ce4e920b,2e2c912f86f9c536c89adc34ff3c2b2b,28d3ff72d72bdec4f37d70699f5edb76,67e1d0af16fc1ddf10009c5c063ad2ba,f3feff30aa3b3f8b514664a96a8dc0ab) - keep_files= - replace_files=$scripts - printf "\nVerified host scripts from XenServer 5.6-SP2.\n" - ;; - - c5f48246577a17cf1b971fb5ce4e920b,2e2c912f86f9c536c89adc34ff3c2b2b,28d3ff72d72bdec4f37d70699f5edb76,67e1d0af16fc1ddf10009c5c063ad2ba,24bae6906d182ba47668174f8e480cc6) - keep_files= - replace_files=$scripts - printf "\nVerified host scripts from XenServer 5.6-FP1.\n" - ;; - - *) - keep_files=$scripts - replace_files= - cat <<EOF - -The host scripts on this machine are not those of any supported -version of XenServer. On XenServer earlier than 5.6-FP1, your Open -vSwitch installation will not work. On XenServer 5.6-FP1 or later, -Open vSwitch is not verified to work, which could lead to unexpected -behavior. - -EOF - ;; -esac - -if grep -F net.ipv4.conf.all.arp_filter /etc/sysctl.conf >/dev/null 2>&1; then :; else - cat >>/etc/sysctl.conf <<EOF -# This works around an issue in xhad, which binds to a particular -# Ethernet device, which in turn causes ICMP port unreachable messages -# if packets are received are on the wrong interface, which in turn -# can happen if we send out ARP replies on every interface (as Linux -# does by default) instead of just on the interface that has the IP -# address being ARPed for, which this sysctl setting in turn works -# around. -# -# Bug #1378. -net.ipv4.conf.all.arp_filter = 1 -EOF -fi - -if test ! -e /etc/openvswitch/conf.db; then - install -d -m 755 -o root -g root /etc/openvswitch - - # Create ovs-vswitchd config database - ovsdb-tool -vconsole:off create /etc/openvswitch/conf.db \ - /usr/share/openvswitch/vswitch.ovsschema - - # Create initial table in config database - ovsdb-tool -vconsole:off transact /etc/openvswitch/conf.db \ - '[{"op": "insert", "table": "Open_vSwitch", "row": {}}]' \ - > /dev/null -fi - -# Create default or update existing /etc/sysconfig/openvswitch. -SYSCONFIG=/etc/sysconfig/openvswitch -TEMPLATE=/usr/share/openvswitch/scripts/sysconfig.template -if [ ! -e $SYSCONFIG ]; then - cp $TEMPLATE $SYSCONFIG -else - for var in $(awk -F'[ :]' '/^# [_A-Z0-9]+:/{print $2}' $TEMPLATE) - do - if ! grep $var $SYSCONFIG >/dev/null 2>&1; then - echo >> $SYSCONFIG - sed -n "/$var:/,/$var=/p" $TEMPLATE >> $SYSCONFIG - fi - done -fi - -# Deliberately break %postun in broken OVS builds that revert original -# XenServer scripts during rpm -U by moving the directory where it thinks -# they are saved. -if [ -d /usr/lib/openvswitch/xs-original ]; then - mkdir -p /usr/lib/openvswitch/xs-saved - mv /usr/lib/openvswitch/xs-original/* /usr/lib/openvswitch/xs-saved/ && - rmdir /usr/lib/openvswitch/xs-original -fi - -# Replace XenServer files by our versions. -mkdir -p /usr/lib/openvswitch/xs-saved \ - || printf "Could not create script backup directory.\n" -for f in $replace_files; do - s=$(basename "$f") - t=$(readlink "$f") - if [ -f "$f" ] && [ "$t" != "/usr/share/openvswitch/scripts/$s" ]; then - mv "$f" /usr/lib/openvswitch/xs-saved/ \ - || printf "Could not save original XenServer $s script\n" - ln -s "/usr/share/openvswitch/scripts/$s" "$f" \ - || printf "Could not link to Open vSwitch $s script\n" - fi -done - -# Clean up dangling symlinks to removed OVS replacement scripts no longer -# provided by OVS. Any time a replacement script is removed from OVS, -# it should be added here to ensure correct reversion from old versions of -# OVS that don't clean up dangling symlinks during the uninstall phase. -for orig in /usr/sbin/xen-bugtool $keep_files; do - saved=/usr/lib/openvswitch/xs-saved/$(basename "$orig") - [ -e "$saved" ] && mv -f "$saved" "$orig" -done - -# Ensure all required services are set to run -for s in openvswitch openvswitch-xapi-update; do - if chkconfig --list $s >/dev/null 2>&1; then - chkconfig --del $s || printf "Could not remove $s init script.\n" - fi - chkconfig --add $s || printf "Could not add $s init script.\n" - chkconfig $s on || printf "Could not enable $s init script.\n" -done - -if [ "$1" = "1" ]; then # $1 = 1 for install - # Configure system to use Open vSwitch - /opt/xensource/bin/xe-switch-network-backend vswitch -else # $1 = 2 for upgrade - - mode=$(cat /etc/xensource/network.conf) - if [ "$mode" != "vswitch" ] && [ "$mode" != "openvswitch" ]; then - printf "\nThe server is not configured to run Open vSwitch. To run in\n" - printf "vswitch mode, you must run the following command:\n\n" - printf " xe-switch-network-backend vswitch" - printf "\n\n" - fi -fi - -%posttrans %{module_package} -# Ensure that modprobe will find our modules. -# -# This has to be in %posttrans instead of %post because older versions -# installed modules into a different directory and "rpm -U" runs the -# new version's %post before removing the old version's files, so if -# we use %post then depmod may find the old versions that are about to -# be removed. -depmod %{xen_version} - -mode=$(cat /etc/xensource/network.conf) -if [ "$mode" = "vswitch" ] || [ "$mode" = "openvswitch" ]; then - printf "\nTo use the newly installed Open vSwitch kernel module, you\n" - printf "will either have to reboot the hypervisor or follow any\n" - printf "workarounds provided by your administration guide. Failure to do\n" - printf "so may result in incorrect operation." - printf "\n\n" -fi - -%preun -if [ "$1" = "0" ]; then # $1 = 0 for uninstall - # Configure system to use bridge - /opt/xensource/bin/xe-switch-network-backend bridge - - # The "openvswitch" service should have been removed from - # "xe-switch-network-backend bridge". - for s in openvswitch openvswitch-xapi-update; do - if chkconfig --list $s >/dev/null 2>&1; then - chkconfig --del $s || printf "Could not remove $s init script." - fi - done -fi - -%postun -# Restore original XenServer scripts if the OVS equivalent no longer exists. -# This works both in the upgrade and erase cases. -# This lists every file that every version of OVS has ever replaced. Never -# remove old files that OVS no longer replaces, or upgrades from old versions -# will fail to restore the XS originals, leaving the system in a broken state. -# Also be sure to add removed script paths to the %post scriptlet above to -# prevent the same problem when upgrading from old versions of OVS that lack -# this restore-on-upgrade logic. -for f in \ - /etc/xensource/scripts/vif \ - /usr/sbin/xen-bugtool \ - /opt/xensource/libexec/interface-reconfigure \ - /opt/xensource/libexec/InterfaceReconfigure.py \ - /opt/xensource/libexec/InterfaceReconfigureBridge.py \ - /opt/xensource/libexec/InterfaceReconfigureVswitch.py -do - # Only revert dangling symlinks. - if [ -h "$f" ] && [ ! -e "$f" ]; then - s=$(basename "$f") - if [ ! -f "/usr/lib/openvswitch/xs-saved/$s" ]; then - printf "Original XenServer $s script not present in /usr/lib/openvswitch/xs-saved\n" >&2 - printf "Could not restore original XenServer script.\n" >&2 - else - (rm -f "$f" \ - && mv "/usr/lib/openvswitch/xs-saved/$s" "$f") \ - || printf "Could not restore original XenServer $s script.\n" >&2 - fi - fi -done - -if [ "$1" = "0" ]; then # $1 = 0 for uninstall - rm -f /usr/lib/xsconsole/plugins-base/XSFeatureVSwitch.pyc \ - /usr/lib/xsconsole/plugins-base/XSFeatureVSwitch.pyo - - rm -f /usr/share/openvswitch/scripts/InterfaceReconfigure.pyc \ - /usr/share/openvswitch/scripts/InterfaceReconfigure.pyo \ - /usr/share/openvswitch/scripts/InterfaceReconfigureBridge.pyc \ - /usr/share/openvswitch/scripts/InterfaceReconfigureBridge.pyo \ - /usr/share/openvswitch/scripts/InterfaceReconfigureVSwitch.pyc \ - /usr/share/openvswitch/scripts/InterfaceReconfigureVSwitch.pyo - - # Remove all configuration files - rm -f /etc/openvswitch/conf.db - rm -f /etc/sysconfig/openvswitch - rm -f /etc/openvswitch/vswitchd.cacert - - # Remove saved XenServer scripts directory, but only if it's empty - rmdir -p /usr/lib/openvswitch/xs-saved 2>/dev/null -fi - -exit 0 - -%files -%defattr(-,root,root) -/etc/bash_completion.d/ovs-appctl-bashcomp.bash -/etc/bash_completion.d/ovs-vsctl-bashcomp.bash -/etc/init.d/openvswitch -/etc/init.d/openvswitch-xapi-update -/etc/xapi.d/plugins/openvswitch-cfg-update -/etc/xensource/bugtool/* -/etc/logrotate.d/openvswitch -/etc/profile.d/openvswitch.sh -/usr/share/openvswitch/python/ -/usr/share/openvswitch/bugtool-plugins/* -/usr/share/openvswitch/scripts/ovs-check-dead-ifs -/usr/share/openvswitch/scripts/ovs-xapi-sync -/usr/share/openvswitch/scripts/interface-reconfigure -/usr/share/openvswitch/scripts/InterfaceReconfigure.py -/usr/share/openvswitch/scripts/InterfaceReconfigureBridge.py -/usr/share/openvswitch/scripts/InterfaceReconfigureVswitch.py -/usr/share/openvswitch/scripts/vif -/usr/share/openvswitch/scripts/sysconfig.template -/usr/share/openvswitch/scripts/ovs-bugtool-* -/usr/share/openvswitch/scripts/ovs-save -/usr/share/openvswitch/scripts/ovs-ctl -/usr/share/openvswitch/scripts/ovs-lib -/usr/share/openvswitch/scripts/ovs-vtep -/usr/share/openvswitch/vswitch.ovsschema -/usr/share/openvswitch/local-config.ovsschema -/usr/share/openvswitch/vtep.ovsschema -/usr/sbin/ovs-bugtool -/usr/sbin/ovs-vswitchd -/usr/sbin/ovsdb-server -/usr/bin/ovs-appctl -/usr/bin/ovs-dpctl -/usr/bin/ovs-dpctl-top -/usr/bin/ovs-docker -/usr/bin/ovs-ofctl -/usr/bin/ovs-parse-backtrace -/usr/bin/ovs-pcap -/usr/bin/ovs-tcpundump -/usr/bin/ovs-vlan-test -/usr/bin/ovs-vsctl -/usr/bin/ovsdb-client -/usr/bin/ovsdb-tool -/usr/bin/vtep-ctl -/usr/bin/ovs-tcpdump -/usr/lib/xsconsole/plugins-base/XSFeatureVSwitch.py -/usr/share/man/man1/ovsdb-client.1.gz -/usr/share/man/man1/ovsdb-server.1.gz -/usr/share/man/man1/ovsdb-tool.1.gz -/usr/share/man/man5/ovsdb.local-config.5.gz -/usr/share/man/man5/ovsdb-server.5.gz -/usr/share/man/man5/ovs-vswitchd.conf.db.5.gz -/usr/share/man/man5/vtep.5.gz -/usr/share/man/man7/ovs-fields.7.gz -/usr/share/man/man8/ovs-appctl.8.gz -/usr/share/man/man8/ovs-bugtool.8.gz -/usr/share/man/man8/ovs-ctl.8.gz -/usr/share/man/man8/ovs-dpctl.8.gz -/usr/share/man/man8/ovs-dpctl-top.8.gz -/usr/share/man/man8/ovs-ofctl.8.gz -/usr/share/man/man8/ovs-parse-backtrace.8.gz -/usr/share/man/man1/ovs-pcap.1.gz -/usr/share/man/man1/ovs-tcpundump.1.gz -/usr/share/man/man8/ovs-vlan-test.8.gz -/usr/share/man/man8/ovs-vsctl.8.gz -/usr/share/man/man8/ovs-vswitchd.8.gz -/usr/share/man/man8/vtep-ctl.8.gz -/usr/share/man/man8/ovs-tcpdump.8.gz -/var/lib/openvswitch -/var/log/openvswitch -%exclude /usr/lib/xsconsole/plugins-base/*.py[co] -%exclude /usr/share/openvswitch/scripts/*.py[co] -%exclude /usr/share/openvswitch/python/*.py[co] -%exclude /usr/share/openvswitch/python/ovs/*.py[co] -%exclude /usr/share/openvswitch/python/ovs/db/*.py[co] - -%files %{module_package} -/lib/modules/%{xen_version}/extra/openvswitch/openvswitch.ko -/lib/modules/%{xen_version}/extra/openvswitch/vport-*.ko diff --git a/xenserver/opt_xensource_libexec_InterfaceReconfigure.py b/xenserver/opt_xensource_libexec_InterfaceReconfigure.py deleted file mode 100644 index 74b784d34..000000000 --- a/xenserver/opt_xensource_libexec_InterfaceReconfigure.py +++ /dev/null @@ -1,972 +0,0 @@ -# Copyright (c) 2008,2009 Citrix Systems, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation; version 2.1 only. with the special -# exception on linking described in file LICENSE. -# -# 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 Lesser General Public License for more details. -# -import sys -import syslog -import os - -from xml.dom.minidom import getDOMImplementation -from xml.dom.minidom import parse as parseXML - -the_root_prefix = "" -def root_prefix(): - """Returns a string to prefix to all file name references, which - is useful for testing.""" - return the_root_prefix -def set_root_prefix(prefix): - global the_root_prefix - the_root_prefix = prefix - -log_destination = "syslog" -def get_log_destination(): - """Returns the current log destination. - 'syslog' means "log to syslog". - 'stderr' means "log to stderr".""" - return log_destination -def set_log_destination(dest): - global log_destination - log_destination = dest - -# -# Logging. -# - -def log(s): - if get_log_destination() == 'syslog': - syslog.syslog(s) - else: - sys.stderr.write(s + '\n') - sys.stderr.flush() - -# -# Exceptions. -# - -class Error(Exception): - def __init__(self, msg): - Exception.__init__(self) - self.msg = msg - -# -# Run external utilities -# - -def run_command(command): - log("Running command: " + ' '.join(command)) - rc = os.spawnl(os.P_WAIT, root_prefix() + command[0], *command) - if rc != 0: - log("Command failed %d: " % rc + ' '.join(command)) - return False - return True - -# -# Configuration File Handling. -# - -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, path): - dirname,basename = os.path.split(path) - - self.__state = self.__STATE['OPEN'] - self.__children = [] - - self.__path = os.path.join(dirname, basename) - self.__oldpath = os.path.join(dirname, "." + basename + ".xapi-old") - self.__newpath = os.path.join(dirname, "." + basename + ".xapi-new") - - 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 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.__path) - - # 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)) - os.link(self.__newpath, self.__path) - - # 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.__path) - - # 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.__path) - - 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'] - -# -# Helper functions for encoding/decoding database attributes to/from XML. -# - -def _str_to_xml(xml, parent, tag, val): - e = xml.createElement(tag) - parent.appendChild(e) - v = xml.createTextNode(val) - e.appendChild(v) -def _str_from_xml(n): - def getText(nodelist): - rc = "" - for node in nodelist: - if node.nodeType == node.TEXT_NODE: - rc = rc + node.data - return rc - return getText(n.childNodes).strip() - -def _bool_to_xml(xml, parent, tag, val): - if val: - _str_to_xml(xml, parent, tag, "True") - else: - _str_to_xml(xml, parent, tag, "False") -def _bool_from_xml(n): - s = _str_from_xml(n) - if s == "True": - return True - elif s == "False": - return False - else: - raise Error("Unknown boolean value %s" % s) - -def _strlist_to_xml(xml, parent, ltag, itag, val): - e = xml.createElement(ltag) - parent.appendChild(e) - for v in val: - c = xml.createElement(itag) - e.appendChild(c) - cv = xml.createTextNode(v) - c.appendChild(cv) -def _strlist_from_xml(n, ltag, itag): - ret = [] - for n in n.childNodes: - if n.nodeName == itag: - ret.append(_str_from_xml(n)) - return ret - -def _map_to_xml(xml, parent, tag, val, attrs): - e = xml.createElement(tag) - parent.appendChild(e) - for n,v in val.items(): - if n in attrs: - _str_to_xml(xml, e, n, v) - else: - log("Unknown other-config attribute: %s" % n) - -def _map_from_xml(n, attrs): - ret = {} - for n in n.childNodes: - if n.nodeName in attrs: - ret[n.nodeName] = _str_from_xml(n) - return ret - -def _otherconfig_to_xml(xml, parent, val, attrs): - return _map_to_xml(xml, parent, "other_config", val, attrs) -def _otherconfig_from_xml(n, attrs): - return _map_from_xml(n, attrs) - -# -# Definitions of the database objects (and their attributes) used by interface-reconfigure. -# -# Each object is defined by a dictionary mapping an attribute name in -# the xapi database to a tuple containing two items: -# - a function which takes this attribute and encodes it as XML. -# - a function which takes XML and decocdes it into a value. -# -# other-config attributes are specified as a simple array of strings - -_PIF_XML_TAG = "pif" -_VLAN_XML_TAG = "vlan" -_TUNNEL_XML_TAG = "tunnel" -_BOND_XML_TAG = "bond" -_NETWORK_XML_TAG = "network" -_POOL_XML_TAG = "pool" - -_ETHTOOL_OTHERCONFIG_ATTRS = ['ethtool-%s' % x for x in ['autoneg', 'speed', 'duplex', 'rx', 'tx', 'sg', 'tso', 'ufo', 'gso', 'gro', 'lro'] ] - -_PIF_OTHERCONFIG_ATTRS = [ 'domain', 'peerdns', 'defaultroute', 'mtu', 'static-routes' ] + \ - [ 'bond-%s' % x for x in ['mode', 'miimon', 'downdelay', 'updelay', 'use_carrier', 'hashing-algorithm'] ] + \ - [ 'vlan-bug-workaround' ] + \ - _ETHTOOL_OTHERCONFIG_ATTRS - -_PIF_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml), - 'management': (_bool_to_xml,_bool_from_xml), - 'network': (_str_to_xml,_str_from_xml), - 'device': (_str_to_xml,_str_from_xml), - 'bond_master_of': (lambda x, p, t, v: _strlist_to_xml(x, p, 'bond_master_of', 'slave', v), - lambda n: _strlist_from_xml(n, 'bond_master_of', 'slave')), - 'bond_slave_of': (_str_to_xml,_str_from_xml), - 'VLAN': (_str_to_xml,_str_from_xml), - 'VLAN_master_of': (_str_to_xml,_str_from_xml), - 'VLAN_slave_of': (lambda x, p, t, v: _strlist_to_xml(x, p, 'VLAN_slave_of', 'master', v), - lambda n: _strlist_from_xml(n, 'VLAN_slave_Of', 'master')), - 'tunnel_access_PIF_of': (lambda x, p, t, v: _strlist_to_xml(x, p, 'tunnel_access_PIF_of', 'pif', v), - lambda n: _strlist_from_xml(n, 'tunnel_access_PIF_of', 'pif')), - 'tunnel_transport_PIF_of': (lambda x, p, t, v: _strlist_to_xml(x, p, 'tunnel_transport_PIF_of', 'pif', v), - lambda n: _strlist_from_xml(n, 'tunnel_transport_PIF_of', 'pif')), - 'ip_configuration_mode': (_str_to_xml,_str_from_xml), - 'IP': (_str_to_xml,_str_from_xml), - 'netmask': (_str_to_xml,_str_from_xml), - 'gateway': (_str_to_xml,_str_from_xml), - 'DNS': (_str_to_xml,_str_from_xml), - 'MAC': (_str_to_xml,_str_from_xml), - 'other_config': (lambda x, p, t, v: _otherconfig_to_xml(x, p, v, _PIF_OTHERCONFIG_ATTRS), - lambda n: _otherconfig_from_xml(n, _PIF_OTHERCONFIG_ATTRS)), - - # Special case: We write the current value - # PIF.currently-attached to the cache but since it will - # not be valid when we come to use the cache later - # (i.e. after a reboot) we always read it as False. - 'currently_attached': (_bool_to_xml, lambda n: False), - } - -_VLAN_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml), - 'tagged_PIF': (_str_to_xml,_str_from_xml), - 'untagged_PIF': (_str_to_xml,_str_from_xml), - } - -_TUNNEL_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml), - 'access_PIF': (_str_to_xml,_str_from_xml), - 'transport_PIF': (_str_to_xml,_str_from_xml), - } -_BOND_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml), - 'master': (_str_to_xml,_str_from_xml), - 'slaves': (lambda x, p, t, v: _strlist_to_xml(x, p, 'slaves', 'slave', v), - lambda n: _strlist_from_xml(n, 'slaves', 'slave')), - } - -_NETWORK_OTHERCONFIG_ATTRS = [ 'mtu', - 'static-routes', - 'vswitch-controller-fail-mode', - 'vswitch-disable-in-band' ] \ - + _ETHTOOL_OTHERCONFIG_ATTRS - -_NETWORK_ATTRS = { 'uuid': (_str_to_xml,_str_from_xml), - 'bridge': (_str_to_xml,_str_from_xml), - 'MTU': (_str_to_xml,_str_from_xml), - 'PIFs': (lambda x, p, t, v: _strlist_to_xml(x, p, 'PIFs', 'PIF', v), - lambda n: _strlist_from_xml(n, 'PIFs', 'PIF')), - 'other_config': (lambda x, p, t, v: _otherconfig_to_xml(x, p, v, _NETWORK_OTHERCONFIG_ATTRS), - lambda n: _otherconfig_from_xml(n, _NETWORK_OTHERCONFIG_ATTRS)), - } - -_POOL_OTHERCONFIG_ATTRS = ['vswitch-controller-fail-mode'] - -_POOL_ATTRS = { 'other_config': (lambda x, p, t, v: _otherconfig_to_xml(x, p, v, _POOL_OTHERCONFIG_ATTRS), - lambda n: _otherconfig_from_xml(n, _POOL_OTHERCONFIG_ATTRS)), - } - -# -# Database Cache object -# - -_db = None - -def db(): - assert(_db is not None) - return _db - -def db_init_from_cache(cache): - global _db - assert(_db is None) - _db = DatabaseCache(cache_file=cache) - -def db_init_from_xenapi(session): - global _db - assert(_db is None) - _db = DatabaseCache(session_ref=session) - -class DatabaseCache(object): - def __read_xensource_inventory(self): - filename = root_prefix() + "/etc/xensource-inventory" - f = open(filename, "r") - lines = [x.strip("\n") for x in f.readlines()] - f.close() - - defs = [ (l[:l.find("=")], l[(l.find("=") + 1):]) for l in lines ] - defs = [ (a, b.strip("'")) for (a,b) in defs ] - - return dict(defs) - - def __pif_on_host(self,pif): - return pif in self.__pifs - - def __get_pif_records_from_xapi(self, session, host): - self.__pifs = {} - for (p,rec) in session.xenapi.PIF.get_all_records().items(): - if rec['host'] != host: - continue - self.__pifs[p] = {} - for f in _PIF_ATTRS: - self.__pifs[p][f] = rec[f] - self.__pifs[p]['other_config'] = {} - for f in _PIF_OTHERCONFIG_ATTRS: - if f not in rec['other_config']: continue - self.__pifs[p]['other_config'][f] = rec['other_config'][f] - - def __get_vlan_records_from_xapi(self, session): - self.__vlans = {} - for (v,rec) in session.xenapi.VLAN.get_all_records().items(): - if not self.__pif_on_host(rec['untagged_PIF']): - continue - self.__vlans[v] = {} - for f in _VLAN_ATTRS: - self.__vlans[v][f] = rec[f] - - def __get_tunnel_records_from_xapi(self, session): - self.__tunnels = {} - for t in session.xenapi.tunnel.get_all(): - rec = session.xenapi.tunnel.get_record(t) - if not self.__pif_on_host(rec['transport_PIF']): - continue - self.__tunnels[t] = {} - for f in _TUNNEL_ATTRS: - self.__tunnels[t][f] = rec[f] - - def __get_bond_records_from_xapi(self, session): - self.__bonds = {} - for (b,rec) in session.xenapi.Bond.get_all_records().items(): - if not self.__pif_on_host(rec['master']): - continue - self.__bonds[b] = {} - for f in _BOND_ATTRS: - self.__bonds[b][f] = rec[f] - - def __get_network_records_from_xapi(self, session): - self.__networks = {} - for (n,rec) in session.xenapi.network.get_all_records().items(): - self.__networks[n] = {} - for f in _NETWORK_ATTRS: - if f == "PIFs": - # drop PIFs on other hosts - self.__networks[n][f] = [p for p in rec[f] if self.__pif_on_host(p)] - elif f == "MTU" and f not in rec: - # XenServer 5.5 network records did not have an - # MTU field, so allow this to be missing. - pass - else: - self.__networks[n][f] = rec[f] - self.__networks[n]['other_config'] = {} - for f in _NETWORK_OTHERCONFIG_ATTRS: - if f not in rec['other_config']: continue - self.__networks[n]['other_config'][f] = rec['other_config'][f] - - def __get_pool_records_from_xapi(self, session): - self.__pools = {} - for p in session.xenapi.pool.get_all(): - rec = session.xenapi.pool.get_record(p) - - self.__pools[p] = {} - - for f in _POOL_ATTRS: - self.__pools[p][f] = rec[f] - - for f in _POOL_OTHERCONFIG_ATTRS: - if f in rec['other_config']: - self.__pools[p]['other_config'][f] = rec['other_config'][f] - - def __to_xml(self, xml, parent, key, ref, rec, attrs): - """Encode a database object as XML""" - e = xml.createElement(key) - parent.appendChild(e) - if ref: - e.setAttribute('ref', ref) - - for n,v in rec.items(): - if n in attrs: - h,_ = attrs[n] - h(xml, e, n, v) - else: - raise Error("Unknown attribute %s" % n) - def __from_xml(self, e, attrs): - """Decode a database object from XML""" - ref = e.attributes['ref'].value - rec = {} - for n in e.childNodes: - if n.nodeName in attrs: - _,h = attrs[n.nodeName] - rec[n.nodeName] = h(n) - return (ref,rec) - - 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: - import XenAPI - 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: - - inventory = self.__read_xensource_inventory() - assert('INSTALLATION_UUID' in inventory) - log("host uuid is %s" % inventory['INSTALLATION_UUID']) - - host = session.xenapi.host.get_by_uuid(inventory['INSTALLATION_UUID']) - - self.__get_pif_records_from_xapi(session, host) - self.__get_pool_records_from_xapi(session) - self.__get_tunnel_records_from_xapi(session) - self.__get_vlan_records_from_xapi(session) - self.__get_bond_records_from_xapi(session) - self.__get_network_records_from_xapi(session) - finally: - if not session_ref: - session.xenapi.session.logout() - else: - log("Loading xapi database cache from %s" % cache_file) - - xml = parseXML(root_prefix() + cache_file) - - self.__pifs = {} - self.__bonds = {} - self.__vlans = {} - self.__pools = {} - self.__tunnels = {} - self.__networks = {} - - assert(len(xml.childNodes) == 1) - toplevel = xml.childNodes[0] - - assert(toplevel.nodeName == "xenserver-network-configuration") - - for n in toplevel.childNodes: - if n.nodeName == "#text": - pass - elif n.nodeName == _PIF_XML_TAG: - (ref,rec) = self.__from_xml(n, _PIF_ATTRS) - self.__pifs[ref] = rec - elif n.nodeName == _BOND_XML_TAG: - (ref,rec) = self.__from_xml(n, _BOND_ATTRS) - self.__bonds[ref] = rec - elif n.nodeName == _VLAN_XML_TAG: - (ref,rec) = self.__from_xml(n, _VLAN_ATTRS) - self.__vlans[ref] = rec - elif n.nodeName == _TUNNEL_XML_TAG: - (ref,rec) = self.__from_xml(n, _TUNNEL_ATTRS) - self.__vlans[ref] = rec - elif n.nodeName == _NETWORK_XML_TAG: - (ref,rec) = self.__from_xml(n, _NETWORK_ATTRS) - self.__networks[ref] = rec - elif n.nodeName == _POOL_XML_TAG: - (ref,rec) = self.__from_xml(n, _POOL_ATTRS) - self.__pools[ref] = rec - else: - raise Error("Unknown XML element %s" % n.nodeName) - - def save(self, cache_file): - - xml = getDOMImplementation().createDocument( - None, "xenserver-network-configuration", None) - for (ref,rec) in self.__pifs.items(): - self.__to_xml(xml, xml.documentElement, _PIF_XML_TAG, ref, rec, _PIF_ATTRS) - for (ref,rec) in self.__bonds.items(): - self.__to_xml(xml, xml.documentElement, _BOND_XML_TAG, ref, rec, _BOND_ATTRS) - for (ref,rec) in self.__vlans.items(): - self.__to_xml(xml, xml.documentElement, _VLAN_XML_TAG, ref, rec, _VLAN_ATTRS) - for (ref,rec) in self.__tunnels.items(): - self.__to_xml(xml, xml.documentElement, _TUNNEL_XML_TAG, ref, rec, _TUNNEL_ATTRS) - for (ref,rec) in self.__networks.items(): - self.__to_xml(xml, xml.documentElement, _NETWORK_XML_TAG, ref, rec, - _NETWORK_ATTRS) - for (ref,rec) in self.__pools.items(): - self.__to_xml(xml, xml.documentElement, _POOL_XML_TAG, ref, rec, _POOL_ATTRS) - - temp_file = cache_file + ".%d" % os.getpid() - f = open(temp_file, 'w') - f.write(xml.toprettyxml()) - f.close() - os.rename(temp_file, cache_file) - - def get_pif_by_uuid(self, uuid): - pifs = map(lambda ref_rec: ref_rec[0], - filter(lambda ref_rec: uuid == ref_rec[1]['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_pifs_by_device(self, device): - return list(map(lambda ref_rec: ref_rec[0], - list(filter(lambda ref_rec: ref_rec[1]['device'] == device, - self.__pifs.items())))) - - def get_networks_with_bridge(self, bridge): - return list(map(lambda ref_rec: ref_rec[0], - list(filter(lambda ref_rec: ref_rec[1]['bridge'] == bridge, - self.__networks.items())))) - - def get_network_by_bridge(self, bridge): - #Assumes one network has bridge. - try: - return self.get_networks_with_bridge(bridge)[0] - except KeyError: - return None - - def get_pif_by_bridge(self, bridge): - networks = self.get_networks_with_bridge(bridge) - - if len(networks) == 0: - raise Error("No matching network \"%s\"" % bridge) - - answer = None - for network in networks: - nwrec = self.get_network_record(network) - for pif in nwrec['PIFs']: - pifrec = self.get_pif_record(pif) - if answer: - raise Error("Multiple PIFs on host for network %s" % (bridge)) - answer = pif - if not answer: - raise Error("No PIF on host for network %s" % (bridge)) - return answer - - def get_pif_record(self, pif): - if pif in self.__pifs: - return self.__pifs[pif] - raise Error("Unknown PIF \"%s\"" % pif) - def get_all_pifs(self): - return self.__pifs - def pif_exists(self, pif): - return pif in self.__pifs - - def get_management_pif(self): - """ Returns the management pif on host - """ - all = self.get_all_pifs() - for pif in all: - pifrec = self.get_pif_record(pif) - if pifrec['management']: return pif - return None - - def get_network_record(self, network): - if network in self.__networks: - return self.__networks[network] - raise Error("Unknown network \"%s\"" % network) - - def get_bond_record(self, bond): - if bond in self.__bonds: - return self.__bonds[bond] - else: - return None - - def get_vlan_record(self, vlan): - if vlan in self.__vlans: - return self.__vlans[vlan] - else: - return None - - def get_pool_record(self): - if len(self.__pools) > 0: - return list(self.__pools.values())[0] - -# -# -# -PIF_OTHERCONFIG_DEFAULTS = {'gro': 'off', 'lro': 'off'} - -def ethtool_settings(oc, defaults = {}): - settings = [] - if 'ethtool-speed' in oc: - 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 'ethtool-duplex' in oc: - val = oc['ethtool-duplex'] - if val in ["half", "full"]: - settings += ['duplex', val] - else: - log("Invalid value for ethtool-duplex = %s. Must be half|full." % val) - if 'ethtool-autoneg' in oc: - 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) - offload = [] - for opt in ("rx", "tx", "sg", "tso", "ufo", "gso", "gro", "lro"): - if "ethtool-" + opt in oc: - 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)) - elif opt in defaults: - offload += [opt, defaults[opt]] - return settings,offload - -# By default the MTU is taken from the Network.MTU setting for VIF, -# PIF and Bridge. However it is possible to override this by using -# {VIF,PIF,Network}.other-config:mtu. -# -# type parameter is a string describing the object that the oc parameter -# is from. e.g. "PIF", "Network" -def mtu_setting(nw, type, oc): - mtu = None - - nwrec = db().get_network_record(nw) - if 'MTU' in nwrec: - mtu = nwrec['MTU'] - else: - mtu = "1500" - - if 'mtu' in oc: - log("Override Network.MTU setting on bridge %s from %s.MTU is %s" % \ - (nwrec['bridge'], type, mtu)) - mtu = oc['mtu'] - - if mtu is not None: - try: - int(mtu) # Check that the value is an integer - return mtu - except ValueError as x: - log("Invalid value for mtu = %s" % mtu) - - return None - -# -# IP Network Devices -- network devices with IP configuration -# -def pif_ipdev_name(pif): - """Return the ipdev name associated with pif""" - 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 pif_netdev_name(pif) - -# -# Bare Network Devices -- network devices without IP configuration -# - -def netdev_exists(netdev): - return os.path.exists(root_prefix() + "/sys/class/net/" + netdev) - - -def unicode_2to3(string): - if sys.version_info < (3,): - return string.encode() - return string - - -def pif_netdev_name(pif): - """Get the netdev name for a PIF.""" - - pifrec = db().get_pif_record(pif) - - if pif_is_vlan(pif): - return unicode_2to3("%(device)s.%(VLAN)s" % pifrec) - else: - return unicode_2to3(pifrec['device']) - -# -# Bridges -# - -def pif_is_bridged(pif): - pifrec = db().get_pif_record(pif) - nwrec = db().get_network_record(pifrec['network']) - - if nwrec['bridge']: - # TODO: sanity check that nwrec['bridgeless'] != 'true' - return True - else: - # TODO: sanity check that nwrec['bridgeless'] == 'true' - return False - -def pif_bridge_name(pif): - """Return the bridge name of a pif. - - PIF must be a bridged PIF.""" - pifrec = db().get_pif_record(pif) - - nwrec = db().get_network_record(pifrec['network']) - - if nwrec['bridge']: - return nwrec['bridge'] - else: - raise Error("PIF %(uuid)s does not have a bridge name" % pifrec) - -# -# Bonded PIFs -# -def pif_is_bond(pif): - pifrec = db().get_pif_record(pif) - - return len(pifrec['bond_master_of']) > 0 - -def pif_get_bond_masters(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 pif_get_bond_slaves(pif): - """Returns a list of PIFs which make up the given bonded pif.""" - - pifrec = db().get_pif_record(pif) - - 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") - - return bondrec['slaves'] - -# -# VLAN PIFs -# - -def pif_is_vlan(pif): - return db().get_pif_record(pif)['VLAN'] != '-1' - -def pif_get_vlan_slave(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 pif_get_vlan_masters(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'])] - -# -# Tunnel PIFs -# -def pif_is_tunnel(pif): - return len(db().get_pif_record(pif)['tunnel_access_PIF_of']) > 0 - -# -# Datapath base class -# - -class Datapath(object): - """Object encapsulating the actions necessary to (de)configure the - datapath for a given PIF. Does not include configuration of the - IP address on the ipdev. - """ - - def __init__(self, pif): - self._pif = pif - - @classmethod - def rewrite(cls): - """Class method called when write action is called. Can be used - to update any backend specific configuration.""" - pass - - def configure_ipdev(self, cfg): - """Write ifcfg TYPE field for an IPdev, plus any type specific - fields to cfg - """ - raise NotImplementedError - - def preconfigure(self, parent): - """Prepare datapath configuration for PIF, but do not actually - apply any changes. - - Any configuration files should be attached to parent. - """ - raise NotImplementedError - - def bring_down_existing(self): - """Tear down any existing network device configuration which - needs to be undone in order to bring this PIF up. - """ - raise NotImplementedError - - def configure(self): - """Apply the configuration prepared in the preconfigure stage. - - Should assume any configuration files changed attached in - the preconfigure stage are applied and bring up the - necessary devices to provide the datapath for the - PIF. - - Should not bring up the IPdev. - """ - raise NotImplementedError - - def post(self): - """Called after the IPdev has been brought up. - - Should do any final setup, including reinstating any - devices which were taken down in the bring_down_existing - hook. - """ - raise NotImplementedError - - def bring_down(self): - """Tear down and deconfigure the datapath. Should assume the - IPdev has already been brought down. - """ - raise NotImplementedError - -def DatapathFactory(): - # XXX Need a datapath object for bridgeless PIFs - - try: - network_conf = open(root_prefix() + "/etc/xensource/network.conf", 'r') - network_backend = network_conf.readline().strip() - network_conf.close() - except Exception as e: - raise Error("failed to determine network backend:" + e) - - if network_backend == "bridge": - from InterfaceReconfigureBridge import DatapathBridge - return DatapathBridge - elif network_backend in ["openvswitch", "vswitch"]: - from InterfaceReconfigureVswitch import DatapathVswitch - return DatapathVswitch - else: - raise Error("unknown network backend %s" % network_backend) diff --git a/xenserver/opt_xensource_libexec_InterfaceReconfigureBridge.py b/xenserver/opt_xensource_libexec_InterfaceReconfigureBridge.py deleted file mode 100644 index 5cc22319a..000000000 --- a/xenserver/opt_xensource_libexec_InterfaceReconfigureBridge.py +++ /dev/null @@ -1,476 +0,0 @@ -# Copyright (c) 2008,2009 Citrix Systems, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation; version 2.1 only. with the special -# exception on linking described in file LICENSE. -# -# 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 Lesser General Public License for more details. -# -from InterfaceReconfigure import * - -import sys -import time - -sysfs_bonding_masters = root_prefix() + "/sys/class/net/bonding_masters" - -def open_pif_ifcfg(pif): - pifrec = db().get_pif_record(pif) - - interface = pif_netdev_name(pif) - log("Configuring %s (%s)" % (interface, pifrec['MAC'])) - - f = ConfigurationFile("%s/etc/sysconfig/network-scripts/ifcfg-%s" % (root_prefix(), interface)) - - f.write("# DO NOT EDIT: This file (%s) was autogenerated by %s\n" % \ - (os.path.basename(f.path()), os.path.basename(sys.argv[0]))) - f.write("XEMANAGED=yes\n") - f.write("DEVICE=%s\n" % interface) - f.write("ONBOOT=no\n") - - return f - -# -# Bare Network Devices -- network devices without IP configuration -# - -def netdev_down(netdev): - """Bring down a bare network device""" - if not netdev_exists(netdev): - log("netdev: down: device %s does not exist, ignoring" % netdev) - return - run_command(["/sbin/ifdown", netdev]) - -def netdev_up(netdev, mtu=None): - """Bring up a bare network device""" - #if not netdev_exists(netdev): - # raise Error("netdev: up: device %s does not exist" % netdev) - - run_command(["/sbin/ifup", netdev]) - -# -# Bonding driver -# - -def load_bonding_driver(): - log("Loading bonding driver") - run_command(["/sbin/modprobe", "bonding"]) - try: - # bond_device_exists() uses the contents of sysfs_bonding_masters to work out which devices - # have already been created. Unfortunately the driver creates "bond0" automatically at - # modprobe init. Get rid of this now or our accounting will go wrong. - f = open(sysfs_bonding_masters, "w") - f.write("-bond0") - f.close() - except IOError as e: - log("Failed to load bonding driver: %s" % e) - -def bonding_driver_loaded(): - lines = open(root_prefix() + "/proc/modules").read().split("\n") - modules = [line.split(" ")[0] for line in lines] - return "bonding" in modules - -def bond_device_exists(name): - f = open(sysfs_bonding_masters, "r") - bonds = f.readline().split() - f.close() - return name in bonds - -def __create_bond_device(name): - - if not bonding_driver_loaded(): - load_bonding_driver() - - if bond_device_exists(name): - log("bond master %s already exists, not creating" % name) - else: - log("Creating bond master %s" % name) - try: - f = open(sysfs_bonding_masters, "w") - f.write("+" + name) - f.close() - except IOError as e: - log("Failed to create %s: %s" % (name, e)) - -def create_bond_device(pif): - """Ensures that a bond master device exists in the kernel.""" - - if not pif_is_bond(pif): - return - - __create_bond_device(pif_netdev_name(pif)) - -def __destroy_bond_device(name): - if bond_device_exists(name): - retries = 10 # 10 * 0.5 seconds - while retries > 0: - retries = retries - 1 - log("Destroying bond master %s (%d attempts remain)" % (name,retries)) - try: - f = open(sysfs_bonding_masters, "w") - f.write("-" + name) - f.close() - retries = 0 - except IOError as e: - time.sleep(0.5) - else: - log("bond master %s does not exist, not destroying" % name) - -def destroy_bond_device(pif): - """No, Mr. Bond, I expect you to die.""" - - pifrec = db().get_pif_record(pif) - - if not pif_is_bond(pif): - return - - # If the bonding module isn't loaded then do nothing. - if not os.access(sysfs_bonding_masters, os.F_OK): - return - - name = pif_netdev_name(pif) - - __destroy_bond_device(name) - -# -# Bring Interface up/down. -# - -def bring_down_interface(pif, destroy=False): - """Bring down the interface associated with PIF. - - Brings down the given interface as well as any physical interfaces - which are bond slaves of this one. This is because they will be - required when the bond is brought up.""" - - def destroy_bridge(pif): - """Bring down the bridge associated with a PIF.""" - #if not pif_is_bridged(pif): - # return - bridge = pif_bridge_name(pif) - if not netdev_exists(bridge): - log("destroy_bridge: bridge %s does not exist, ignoring" % bridge) - return - log("Destroy bridge %s" % bridge) - netdev_down(bridge) - run_command(["/usr/sbin/brctl", "delbr", bridge]) - - def destroy_vlan(pif): - vlan = pif_netdev_name(pif) - if not netdev_exists(vlan): - log("vconfig del: vlan %s does not exist, ignoring" % vlan) - return - log("Destroy vlan device %s" % vlan) - run_command(["/sbin/vconfig", "rem", vlan]) - - if pif_is_vlan(pif): - interface = pif_netdev_name(pif) - log("bring_down_interface: %s is a VLAN" % interface) - netdev_down(interface) - - if destroy: - destroy_vlan(pif) - destroy_bridge(pif) - else: - return - - slave = pif_get_vlan_slave(pif) - if db().get_pif_record(slave)['currently_attached']: - log("bring_down_interface: vlan slave is currently attached") - return - - masters = pif_get_vlan_masters(slave) - masters = [m for m in masters if m != pif and db().get_pif_record(m)['currently_attached']] - if len(masters) > 0: - log("bring_down_interface: vlan slave has other masters") - return - - log("bring_down_interface: no more masters, bring down vlan slave %s" % pif_netdev_name(slave)) - pif = slave - else: - vlan_masters = pif_get_vlan_masters(pif) - log("vlan masters of %s - %s" % (db().get_pif_record(pif)['device'], [pif_netdev_name(m) for m in vlan_masters])) - if len([m for m in vlan_masters if db().get_pif_record(m)['currently_attached']]) > 0: - log("Leaving %s up due to currently attached VLAN masters" % pif_netdev_name(pif)) - return - - # pif is now either a bond or a physical device which needs to be brought down - - # Need to bring down bond slaves first since the bond device - # must be up to enslave/unenslave. - bond_slaves = pif_get_bond_slaves_sorted(pif) - log("bond slaves of %s - %s" % (db().get_pif_record(pif)['device'], [pif_netdev_name(s) for s in bond_slaves])) - for slave in bond_slaves: - slave_interface = pif_netdev_name(slave) - if db().get_pif_record(slave)['currently_attached']: - log("leave bond slave %s up (currently attached)" % slave_interface) - continue - log("bring down bond slave %s" % slave_interface) - netdev_down(slave_interface) - # Also destroy the bridge associated with the slave, since - # it will carry the MAC address and possibly an IP address - # leading to confusion. - destroy_bridge(slave) - - interface = pif_netdev_name(pif) - log("Bring interface %s down" % interface) - netdev_down(interface) - - if destroy: - destroy_bond_device(pif) - destroy_bridge(pif) - -def interface_is_up(pif): - try: - interface = pif_netdev_name(pif) - state = open("%s/sys/class/net/%s/operstate" % (root_prefix(), interface)).read().strip() - return state == "up" - except: - return False # interface prolly doesn't exist - -def bring_up_interface(pif): - """Bring up the interface associated with a PIF. - - Also bring up the interfaces listed in additional. - """ - - # VLAN on bond seems to need bond brought up explicitly, but VLAN - # on normal device does not. Might as well always bring it up. - if pif_is_vlan(pif): - slave = pif_get_vlan_slave(pif) - if not interface_is_up(slave): - bring_up_interface(slave) - - interface = pif_netdev_name(pif) - - create_bond_device(pif) - - log("Bring interface %s up" % interface) - netdev_up(interface) - - -# -# Datapath topology configuration. -# - -def _configure_physical_interface(pif): - """Write the configuration for a physical interface. - - Writes the configuration file for the physical interface described by - the pif object. - - Returns the open file handle for the interface configuration file. - """ - - pifrec = db().get_pif_record(pif) - - log("Configuring physical interface %s" % pifrec['device']) - - f = open_pif_ifcfg(pif) - - f.write("TYPE=Ethernet\n") - f.write("HWADDR=%(MAC)s\n" % pifrec) - - settings,offload = ethtool_settings(pifrec['other_config'], - PIF_OTHERCONFIG_DEFAULTS) - if len(settings): - f.write("ETHTOOL_OPTS=\"%s\"\n" % str.join(" ", settings)) - if len(offload): - f.write("ETHTOOL_OFFLOAD_OPTS=\"%s\"\n" % str.join(" ", offload)) - - mtu = mtu_setting(pifrec['network'], "PIF", pifrec['other_config']) - if mtu: - f.write("MTU=%s\n" % mtu) - - return f - -def pif_get_bond_slaves_sorted(pif): - pifrec = db().get_pif_record(pif) - - # build a list of slave's pifs - slave_pifs = pif_get_bond_slaves(pif) - - # 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("%s/sys/class/net/%s/bonding/slaves" % (root_prefix(), pifrec['device'])).readline().split() - for slave in attached_slaves: - pifs = [p for p in db().get_pifs_by_device(slave) if not pif_is_vlan(p)] - slave_pif = pifs[0] - slave_pifs.remove(slave_pif) - slave_pifs.insert(0, slave_pif) - except IOError: - pass - - return slave_pifs - -def _configure_bond_interface(pif): - """Write the configuration for a bond interface. - - Writes the configuration file for the bond interface described by - the pif object. Handles writing the configuration for the slave - interfaces. - - Returns the open file handle for the bond interface configuration - file. - """ - - pifrec = db().get_pif_record(pif) - - f = open_pif_ifcfg(pif) - - if pifrec['MAC'] != "": - f.write("MACADDR=%s\n" % pifrec['MAC']) - - for slave in pif_get_bond_slaves(pif): - s = _configure_physical_interface(slave) - s.write("MASTER=%(device)s\n" % pifrec) - s.write("SLAVE=yes\n") - s.close() - f.attach_child(s) - - settings,offload = ethtool_settings(pifrec['other_config']) - if len(settings): - f.write("ETHTOOL_OPTS=\"%s\"\n" % str.join(" ", settings)) - if len(offload): - f.write("ETHTOOL_OFFLOAD_OPTS=\"%s\"\n" % str.join(" ", offload)) - - mtu = mtu_setting(pifrec['network'], "Bond-PIF", pifrec['other_config']) - if mtu: - f.write("MTU=%s\n" % mtu) - - # The bond option defaults - bond_options = { - "mode": "balance-slb", - "miimon": "100", - "downdelay": "200", - "updelay": "31000", - "use_carrier": "1", - "hashing-algorithm": "src_mac", - } - - # 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) - - # write the bond options to ifcfg-bondX - f.write('BONDING_OPTS="') - for (name,val) in bond_options.items(): - f.write("%s=%s " % (name,val)) - f.write('"\n') - return f - -def _configure_vlan_interface(pif): - """Write the configuration for a VLAN interface. - - Writes the configuration file for the VLAN interface described by - the pif object. Handles writing the configuration for the master - interface if necessary. - - Returns the open file handle for the VLAN interface configuration - file. - """ - - slave = _configure_pif(pif_get_vlan_slave(pif)) - - pifrec = db().get_pif_record(pif) - - f = open_pif_ifcfg(pif) - f.write("VLAN=yes\n") - - settings,offload = ethtool_settings(pifrec['other_config']) - if len(settings): - f.write("ETHTOOL_OPTS=\"%s\"\n" % str.join(" ", settings)) - if len(offload): - f.write("ETHTOOL_OFFLOAD_OPTS=\"%s\"\n" % str.join(" ", offload)) - - mtu = mtu_setting(pifrec['network'], "VLAN-PIF", pifrec['other_config']) - if mtu: - f.write("MTU=%s\n" % mtu) - - f.attach_child(slave) - - return f - -def _configure_pif(pif): - """Write the configuration for a PIF object. - - Writes the configuration file the PIF and all dependent - interfaces (bond slaves and VLAN masters etc). - - Returns the open file handle for the interface configuration file. - """ - - if pif_is_vlan(pif): - f = _configure_vlan_interface(pif) - elif pif_is_bond(pif): - f = _configure_bond_interface(pif) - else: - f = _configure_physical_interface(pif) - - f.write("BRIDGE=%s\n" % pif_bridge_name(pif)) - f.close() - - return f - -# -# -# - -class DatapathBridge(Datapath): - def __init__(self, pif): - if pif_is_tunnel(pif): - raise Error("Tunnel PIFs are not supported in Bridge mode") - - Datapath.__init__(self, pif) - log("Configured for Bridge datapath") - - def configure_ipdev(self, cfg): - if pif_is_bridged(self._pif): - cfg.write("TYPE=Bridge\n") - cfg.write("DELAY=0\n") - cfg.write("STP=off\n") - cfg.write("PIFDEV=%s\n" % pif_netdev_name(self._pif)) - else: - cfg.write("TYPE=Ethernet\n") - - def preconfigure(self, parent): - pf = _configure_pif(self._pif) - parent.attach_child(pf) - - def bring_down_existing(self): - # Bring down any VLAN masters so that we can reconfigure the slave. - for master in pif_get_vlan_masters(self._pif): - name = pif_netdev_name(master) - log("action_up: bring down vlan master %s" % (name)) - netdev_down(name) - - # interface-reconfigure is never explicitly called to down a bond master. - # However, when we are called to up a slave it is implicit that we are destroying the master. - bond_masters = pif_get_bond_masters(self._pif) - for master in bond_masters: - log("action_up: bring down bond master %s" % (pif_netdev_name(master))) - # bring down master - bring_down_interface(master, destroy=True) - - # No masters left - now its safe to reconfigure the slave. - bring_down_interface(self._pif) - - def configure(self): - bring_up_interface(self._pif) - - def post(self): - # Bring back any currently-attached VLAN masters - for master in [v for v in pif_get_vlan_masters(self._pif) if db().get_pif_record(v)['currently_attached']]: - name = pif_netdev_name(master) - log("action_up: bring up %s" % (name)) - netdev_up(name) - - def bring_down(self): - bring_down_interface(self._pif, destroy=True) diff --git a/xenserver/opt_xensource_libexec_InterfaceReconfigureVswitch.py b/xenserver/opt_xensource_libexec_InterfaceReconfigureVswitch.py deleted file mode 100644 index 9ada3776f..000000000 --- a/xenserver/opt_xensource_libexec_InterfaceReconfigureVswitch.py +++ /dev/null @@ -1,724 +0,0 @@ -# Copyright (c) 2008,2009,2011 Citrix Systems, Inc. -# Copyright (c) 2009,2010,2011,2012,2013,2017 Nicira, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation; version 2.1 only. with the special -# exception on linking described in file LICENSE. -# -# 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 Lesser General Public License for more details. -# -from InterfaceReconfigure import * -import os -import re -import subprocess - -# -# Bare Network Devices -- network devices without IP configuration -# - -def netdev_down(netdev): - """Bring down a bare network device""" - if not netdev_exists(netdev): - log("netdev: down: device %s does not exist, ignoring" % netdev) - return - run_command(["/sbin/ip", "link", "set", netdev, 'down']) - -def netdev_up(netdev, mtu=None): - """Bring up a bare network device""" - if not netdev_exists(netdev): - raise Error("netdev: up: device %s does not exist" % netdev) - - if mtu: - mtu = ["mtu", mtu] - else: - mtu = [] - - run_command(["/sbin/ip", "link", "set", netdev, 'up'] + mtu) - -# This is a list of drivers that do support VLAN tx or rx acceleration, but -# to which the VLAN bug workaround should not be applied. This could be -# because these are known-good drivers (that is, they do not have any of -# the bugs that the workaround avoids) or because the VLAN bug workaround -# will not work for them and may cause other problems. -# -# This is a very short list because few drivers have been tested. -NO_VLAN_WORKAROUND_DRIVERS = ( - "bonding", -) -def netdev_get_driver_name(netdev): - """Returns the name of the driver for network device 'netdev'""" - symlink = '%s/sys/class/net/%s/device/driver' % (root_prefix(), netdev) - try: - target = os.readlink(symlink) - except OSError as e: - log("%s: could not read netdev's driver name (%s)" % (netdev, e)) - return None - - slash = target.rfind('/') - if slash < 0: - log("target %s of symbolic link %s does not contain slash" - % (target, symlink)) - return None - - return target[slash + 1:] - -def netdev_get_features(netdev): - """Returns the features bitmap for the driver for 'netdev'. - The features bitmap is a set of NETIF_F_ flags supported by its driver.""" - try: - features = open("%s/sys/class/net/%s/features" % (root_prefix(), netdev)).read().strip() - return int(features, 0) - except: - return 0 # interface prolly doesn't exist - -def netdev_has_vlan_accel(netdev): - """Returns True if 'netdev' supports VLAN acceleration, False otherwise.""" - NETIF_F_HW_VLAN_TX = 128 - NETIF_F_HW_VLAN_RX = 256 - NETIF_F_VLAN = NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX - return (netdev_get_features(netdev) & NETIF_F_VLAN) != 0 - -# -# PIF miscellanea -# - -def pif_currently_in_use(pif): - """Determine if a PIF is currently in use. - - A PIF is determined to be currently in use if - - PIF.currently-attached is true - - Any bond master is currently attached - - Any VLAN master is currently attached - """ - rec = db().get_pif_record(pif) - if rec['currently_attached']: - log("configure_datapath: %s is currently attached" % (pif_netdev_name(pif))) - return True - for b in pif_get_bond_masters(pif): - if pif_currently_in_use(b): - log("configure_datapath: %s is in use by BOND master %s" % (pif_netdev_name(pif),pif_netdev_name(b))) - return True - for v in pif_get_vlan_masters(pif): - if pif_currently_in_use(v): - log("configure_datapath: %s is in use by VLAN master %s" % (pif_netdev_name(pif),pif_netdev_name(v))) - return True - return False - -# -# Datapath Configuration -# - -def pif_datapath(pif): - """Return the datapath PIF associated with PIF. -A non-VLAN PIF is its own datapath PIF, except that a bridgeless PIF has -no datapath PIF at all. -A VLAN PIF's datapath PIF is its VLAN slave's datapath PIF. -""" - if pif_is_vlan(pif): - return pif_datapath(pif_get_vlan_slave(pif)) - - pifrec = db().get_pif_record(pif) - nwrec = db().get_network_record(pifrec['network']) - if not nwrec['bridge']: - return None - else: - return pif - -def datapath_get_physical_pifs(pif): - """Return the PIFs for the physical network device(s) associated with a datapath PIF. -For a bond master PIF, these are the bond slave PIFs. -For a non-VLAN, non-bond master PIF, the PIF is its own physical device PIF. - -A VLAN PIF cannot be a datapath PIF. -""" - if pif_is_tunnel(pif): - return [] - elif pif_is_vlan(pif): - # Seems like overkill... - raise Error("get-physical-pifs should not get passed a VLAN") - elif pif_is_bond(pif): - return pif_get_bond_slaves(pif) - else: - return [pif] - -def datapath_deconfigure_physical(netdev): - return ['--', '--with-iface', '--if-exists', 'del-port', netdev] - -def vsctl_escape(s): - if s.isalnum(): - return s - - def escape(match): - c = match.group(0) - if c == '\0': - raise Error("strings may not contain null bytes") - elif c == '\\': - return r'\\' - elif c == '\n': - return r'\n' - elif c == '\r': - return r'\r' - elif c == '\t': - return r'\t' - elif c == '\b': - return r'\b' - elif c == '\a': - return r'\a' - else: - return r'\x%02x' % ord(c) - return '"' + re.sub(r'["\\\000-\037]', escape, s) + '"' - -def datapath_configure_tunnel(pif): - pass - -def datapath_configure_bond(pif,slaves): - bridge = pif_bridge_name(pif) - pifrec = db().get_pif_record(pif) - interface = pif_netdev_name(pif) - - argv = ['--', '--fake-iface', 'add-bond', bridge, interface] - for slave in slaves: - argv += [pif_netdev_name(slave)] - - # Bonding options. - bond_options = { - "mode": "balance-slb", - "miimon": "100", - "downdelay": "200", - "updelay": "31000", - "use_carrier": "1", - "hashing-algorithm": "src_mac", - } - # override defaults with values from other-config whose keys - # being with "bond-" - oc = pifrec['other_config'] - overrides = filter(lambda key_val: - key_val[0].startswith("bond-"), oc.items()) - overrides = map(lambda key_val: (key_val[0][5:], key_val[1]), overrides) - bond_options.update(overrides) - mode = None - halgo = None - - argv += ['--', 'set', 'Port', interface] - if pifrec['MAC'] != "": - argv += ['MAC=%s' % vsctl_escape(pifrec['MAC'])] - for (name,val) in sorted(bond_options.items()): - if name in ['updelay', 'downdelay']: - # updelay and downdelay have dedicated schema columns. - # The value must be a nonnegative integer. - try: - value = int(val) - if value < 0: - raise ValueError - - argv += ['bond_%s=%d' % (name, value)] - except ValueError: - log("bridge %s has invalid %s '%s'" % (bridge, name, value)) - elif name in ['miimon', 'use_carrier']: - try: - value = int(val) - if value < 0: - raise ValueError - - if name == 'use_carrier': - if value: - value = "carrier" - else: - value = "miimon" - argv += ["other-config:bond-detect-mode=%s" % value] - else: - argv += ["other-config:bond-miimon-interval=%d" % value] - except ValueError: - log("bridge %s has invalid %s '%s'" % (bridge, name, value)) - elif name == "mode": - mode = val - elif name == "hashing-algorithm": - halgo = val - else: - # Pass other bond options into other_config. - argv += ["other-config:%s=%s" % (vsctl_escape("bond-%s" % name), - vsctl_escape(val))] - - if mode == 'lacp': - argv += ['lacp=active'] - - if halgo == 'src_mac': - argv += ['bond_mode=balance-slb'] - elif halgo == "tcpudp_ports": - argv += ['bond_mode=balance-tcp'] - else: - log("bridge %s has invalid bond-hashing-algorithm '%s'" % (bridge, halgo)) - argv += ['bond_mode=balance-slb'] - elif mode in ['balance-slb', 'active-backup']: - argv += ['lacp=off', 'bond_mode=%s' % mode] - else: - log("bridge %s has invalid bond-mode '%s'" % (bridge, mode)) - argv += ['lacp=off', 'bond_mode=balance-slb'] - - return argv - -def datapath_deconfigure_bond(netdev): - return ['--', '--with-iface', '--if-exists', 'del-port', netdev] - -def datapath_deconfigure_ipdev(interface): - return ['--', '--with-iface', '--if-exists', 'del-port', interface] - -def datapath_modify_config(commands): - #log("modifying configuration:") - #for c in commands: - # log(" %s" % c) - - rc = run_command(['/usr/bin/ovs-vsctl'] + ['--timeout=20'] - + [c for c in commands if not c.startswith('#')]) - if not rc: - raise Error("Failed to modify vswitch configuration") - return True - -# -# Toplevel Datapath Configuration. -# - -def configure_datapath(pif): - """Bring up the configuration for 'pif', which must not be a VLAN PIF, by: - - Tearing down other PIFs that use the same physical devices as 'pif'. - - Ensuring that 'pif' itself is set up. - - *Not* tearing down any PIFs that are stacked on top of 'pif' (i.e. VLANs - on top of 'pif'. - - Returns a tuple containing - - A list containing the necessary vsctl command line arguments - - A list of additional devices which should be brought up after - the configuration is applied. - - A list containing flows to apply to the pif bridge, note that - port numbers may need to be substituted once ofport is known - """ - - vsctl_argv = [] - extra_up_ports = [] - bridge_flows = [] - - assert not pif_is_vlan(pif) - bridge = pif_bridge_name(pif) - - physical_devices = datapath_get_physical_pifs(pif) - - vsctl_argv += ['## configuring datapath %s' % bridge] - - # Determine additional devices to deconfigure. - # - # Given all physical devices which are part of this PIF we need to - # consider: - # - any additional bond which a physical device is part of. - # - any additional physical devices which are part of an additional bond. - # - # Any of these which are not currently in use should be brought - # down and deconfigured. - extra_down_bonds = [] - extra_down_ports = [] - for p in physical_devices: - for bond in pif_get_bond_masters(p): - if bond == pif: - log("configure_datapath: leaving bond %s up" % pif_netdev_name(bond)) - continue - if bond in extra_down_bonds: - continue - if db().get_pif_record(bond)['currently_attached']: - log("configure_datapath: implicitly tearing down currently-attached bond %s" % pif_netdev_name(bond)) - - extra_down_bonds += [bond] - - for s in pif_get_bond_slaves(bond): - if s in physical_devices: - continue - if s in extra_down_ports: - continue - if pif_currently_in_use(s): - continue - extra_down_ports += [s] - - log("configure_datapath: bridge - %s" % bridge) - log("configure_datapath: physical - %s" % [pif_netdev_name(p) for p in physical_devices]) - log("configure_datapath: extra ports - %s" % [pif_netdev_name(p) for p in extra_down_ports]) - log("configure_datapath: extra bonds - %s" % [pif_netdev_name(p) for p in extra_down_bonds]) - - # Need to fully deconfigure any bridge which any of the: - # - physical devices - # - bond devices - # - sibling devices - # refers to - for brpif in physical_devices + extra_down_ports + extra_down_bonds: - if brpif == pif: - continue - b = pif_bridge_name(brpif) - #ifdown(b) - # XXX - netdev_down(b) - vsctl_argv += ['# remove bridge %s' % b] - vsctl_argv += ['--', '--if-exists', 'del-br', b] - - for n in extra_down_ports: - dev = pif_netdev_name(n) - vsctl_argv += ['# deconfigure sibling physical device %s' % dev] - vsctl_argv += datapath_deconfigure_physical(dev) - netdev_down(dev) - - for n in extra_down_bonds: - dev = pif_netdev_name(n) - vsctl_argv += ['# deconfigure bond device %s' % dev] - vsctl_argv += datapath_deconfigure_bond(dev) - netdev_down(dev) - - for p in physical_devices: - dev = pif_netdev_name(p) - vsctl_argv += ['# deconfigure physical port %s' % dev] - vsctl_argv += datapath_deconfigure_physical(dev) - - vsctl_argv += ['--', '--may-exist', 'add-br', bridge] - - if len(physical_devices) > 1: - vsctl_argv += ['# deconfigure bond %s' % pif_netdev_name(pif)] - vsctl_argv += datapath_deconfigure_bond(pif_netdev_name(pif)) - vsctl_argv += ['# configure bond %s' % pif_netdev_name(pif)] - vsctl_argv += datapath_configure_bond(pif, physical_devices) - extra_up_ports += [pif_netdev_name(pif)] - elif len(physical_devices) == 1: - iface = pif_netdev_name(physical_devices[0]) - vsctl_argv += ['# add physical device %s' % iface] - vsctl_argv += ['--', '--may-exist', 'add-port', bridge, iface] - elif pif_is_tunnel(pif): - datapath_configure_tunnel(pif) - - vsctl_argv += ['# configure Bridge MAC'] - vsctl_argv += ['--', 'set', 'Bridge', bridge, - 'other-config:hwaddr=%s' % vsctl_escape(db().get_pif_record(pif)['MAC'])] - - pool = db().get_pool_record() - network = db().get_network_by_bridge(bridge) - network_rec = None - fail_mode = None - valid_fail_modes = ['standalone', 'secure'] - - if network: - network_rec = db().get_network_record(network) - fail_mode = network_rec['other_config'].get('vswitch-controller-fail-mode') - - if (fail_mode not in valid_fail_modes) and pool: - fail_mode = pool['other_config'].get('vswitch-controller-fail-mode') - # Add default flows to allow management traffic if fail-mode - # transitions to secure based on pool fail-mode setting - if fail_mode == 'secure' and db().get_pif_record(pif).get('management', False): - prev_fail_mode = vswitchCfgQuery(['get-fail-mode', bridge]) - if prev_fail_mode != 'secure': - tp = 'idle_timeout=0,priority=0' - host_mgmt_mac = db().get_pif_record(pif)['MAC'] - # account for bond as management interface - if len(physical_devices) > 1: - bridge_flows += ['%s,in_port=local,arp,dl_src=%s,actions=NORMAL' % (tp, host_mgmt_mac)] - bridge_flows += ['%s,in_port=local,dl_src=%s,actions=NORMAL' % (tp, host_mgmt_mac)] - # we don't know slave ofports yet, substitute later - bridge_flows += ['%s,in_port=%%s,arp,nw_proto=1,actions=local' % (tp)] - bridge_flows += ['%s,in_port=%%s,dl_dst=%s,actions=local' % (tp, host_mgmt_mac)] - else: - bridge_flows += ['%s,in_port=%%s,arp,nw_proto=1,actions=local' % (tp)] - bridge_flows += ['%s,in_port=local,arp,dl_src=%s,actions=%%s' % (tp, host_mgmt_mac)] - bridge_flows += ['%s,in_port=%%s,dl_dst=%s,actions=local' % (tp, host_mgmt_mac)] - bridge_flows += ['%s,in_port=local,dl_src=%s,actions=%%s' % (tp, host_mgmt_mac)] - - if fail_mode not in valid_fail_modes: - fail_mode = 'standalone' - - vsctl_argv += ['--', 'set', 'Bridge', bridge, 'fail_mode=%s' % fail_mode] - - if network_rec: - dib = network_rec['other_config'].get('vswitch-disable-in-band') - if not dib: - vsctl_argv += ['--', 'remove', 'Bridge', bridge, 'other_config', 'disable-in-band'] - elif dib in ['true', 'false']: - vsctl_argv += ['--', 'set', 'Bridge', bridge, 'other_config:disable-in-band=' + dib] - else: - log('"' + dib + '"' "isn't a valid setting for other_config:disable-in-band on " + bridge) - - vsctl_argv += set_br_external_ids(pif) - vsctl_argv += ['## done configuring datapath %s' % bridge] - - return vsctl_argv,extra_up_ports,bridge_flows - -def deconfigure_bridge(pif): - vsctl_argv = [] - - bridge = pif_bridge_name(pif) - - log("deconfigure_bridge: bridge - %s" % bridge) - - vsctl_argv += ['# deconfigure bridge %s' % bridge] - vsctl_argv += ['--', '--if-exists', 'del-br', bridge] - - return vsctl_argv - -def set_br_external_ids(pif): - pifrec = db().get_pif_record(pif) - dp = pif_datapath(pif) - dprec = db().get_pif_record(dp) - - xs_network_uuids = [] - for nwpif in db().get_pifs_by_device(pifrec['device']): - rec = db().get_pif_record(nwpif) - - # When state is read from dbcache PIF.currently_attached - # is always assumed to be false... Err on the side of - # listing even detached networks for the time being. - #if nwpif != pif and not rec['currently_attached']: - # log("Network PIF %s not currently attached (%s)" % (rec['uuid'],pifrec['uuid'])) - # continue - nwrec = db().get_network_record(rec['network']) - - uuid = nwrec['uuid'] - if pif_is_vlan(nwpif): - xs_network_uuids.append(uuid) - else: - xs_network_uuids.insert(0, uuid) - - vsctl_argv = [] - vsctl_argv += ['# configure xs-network-uuids'] - vsctl_argv += ['--', 'br-set-external-id', pif_bridge_name(pif), - 'xs-network-uuids', ';'.join(xs_network_uuids)] - - return vsctl_argv - -# -# -# - -class DatapathVswitch(Datapath): - def __init__(self, pif): - Datapath.__init__(self, pif) - self._dp = pif_datapath(pif) - self._ipdev = pif_ipdev_name(pif) - self._bridge_flows = [] - - if pif_is_vlan(pif) and not self._dp: - raise Error("Unbridged VLAN devices not implemented yet") - - log("Configured for Vswitch datapath") - - @classmethod - def rewrite(cls): - if not os.path.exists("/var/run/openvswitch/db.sock"): - # ovsdb-server is not running, so we can't update the database. - # Probably we are being called as part of system shutdown. Just - # skip the update, since the external-ids will be updated on the - # next boot anyhow. - return - - vsctl_argv = [] - for pif in db().get_all_pifs(): - pifrec = db().get_pif_record(pif) - if not pif_is_vlan(pif) and pifrec['currently_attached']: - vsctl_argv += set_br_external_ids(pif) - - if vsctl_argv != []: - datapath_modify_config(vsctl_argv) - - def configure_ipdev(self, cfg): - cfg.write("TYPE=Ethernet\n") - - def preconfigure(self, parent): - vsctl_argv = [] - extra_ports = [] - bridge_flows = [] - - pifrec = db().get_pif_record(self._pif) - dprec = db().get_pif_record(self._dp) - - ipdev = self._ipdev - c,e,f = configure_datapath(self._dp) - bridge = pif_bridge_name(self._pif) - vsctl_argv += c - extra_ports += e - bridge_flows += f - - dpname = pif_bridge_name(self._dp) - - if pif_is_vlan(self._pif): - # In some cases XAPI may misguidedly leave an instance of - # 'bridge' which should be deleted. - vsctl_argv += ['--', '--if-exists', 'del-br', bridge] - - # configure_datapath() set up the underlying datapath bridge. - # Stack a VLAN bridge on top of it. - vsctl_argv += ['--', '--may-exist', 'add-br', - bridge, dpname, pifrec['VLAN']] - - vsctl_argv += set_br_external_ids(self._pif) - - if ipdev != bridge: - vsctl_argv += ["# deconfigure ipdev %s" % ipdev] - vsctl_argv += datapath_deconfigure_ipdev(ipdev) - vsctl_argv += ["# reconfigure ipdev %s" % ipdev] - vsctl_argv += ['--', 'add-port', bridge, ipdev] - - if ipdev != dpname: - vsctl_argv += ['# configure Interface MAC'] - vsctl_argv += ['--', 'set', 'Interface', pif_ipdev_name(self._pif), - 'MAC=%s' % vsctl_escape(dprec['MAC'])] - - self._vsctl_argv = vsctl_argv - self._extra_ports = extra_ports - self._bridge_flows = bridge_flows - - def bring_down_existing(self): - # interface-reconfigure is never explicitly called to down a - # bond master. However, when we are called to up a slave it - # is implicit that we are destroying the master. Conversely, - # when we are called to up a bond is is implicit that we are - # taking down the slaves. - # - # This is (only) important in the case where the device being - # implicitly taken down uses DHCP. We need to kill the - # dhclient process, otherwise performing the inverse operation - # later later will fail because ifup will refuse to start a - # duplicate dhclient. - bond_masters = pif_get_bond_masters(self._pif) - for master in bond_masters: - log("action_up: bring down bond master %s" % (pif_netdev_name(master))) - run_command(["/sbin/ifdown", pif_bridge_name(master)]) - - bond_slaves = pif_get_bond_slaves(self._pif) - for slave in bond_slaves: - log("action_up: bring down bond slave %s" % (pif_netdev_name(slave))) - run_command(["/sbin/ifdown", pif_bridge_name(slave)]) - - def configure(self): - # Bring up physical devices. ovs-vswitchd initially enables or - # disables bond slaves based on whether carrier is detected - # when they are added, and a network device that is down - # always reports "no carrier". - physical_devices = datapath_get_physical_pifs(self._dp) - - if pif_is_bond(self._dp): - brec = db().get_pif_record(self._dp) - bond_mtu = mtu_setting(brec['network'], "PIF", brec['other_config']) - else: - bond_mtu = None - - for p in physical_devices: - prec = db().get_pif_record(p) - oc = prec['other_config'] - - dev = pif_netdev_name(p) - - if bond_mtu: - mtu = bond_mtu - else: - mtu = mtu_setting(prec['network'], "PIF", oc) - - netdev_up(dev, mtu) - - settings, offload = ethtool_settings(oc, PIF_OTHERCONFIG_DEFAULTS) - if len(settings): - run_command(['/sbin/ethtool', '-s', dev] + settings) - if len(offload): - run_command(['/sbin/ethtool', '-K', dev] + offload) - - driver = netdev_get_driver_name(dev) - if 'vlan-bug-workaround' in oc: - vlan_bug_workaround = oc['vlan-bug-workaround'] == 'true' - elif driver in NO_VLAN_WORKAROUND_DRIVERS: - vlan_bug_workaround = False - else: - vlan_bug_workaround = netdev_has_vlan_accel(dev) - - datapath_modify_config(self._vsctl_argv) - if self._bridge_flows: - ofports = [] - physical_devices = datapath_get_physical_pifs(self._dp) - if len(physical_devices) > 1: - for slave in physical_devices: - name = pif_netdev_name(slave) - ofport = vswitchCfgQuery(['get', 'interface', name, 'ofport']) - ofports.append(ofport) - else: - name = pif_netdev_name(self._dp) - ofport = vswitchCfgQuery(['get', 'interface', name, 'ofport']) - ofports.append(ofport) - dpname = pif_bridge_name(self._dp) - for flow in self._bridge_flows: - if flow.find('in_port=%s') != -1 or flow.find('actions=%s') != -1: - for port in ofports: - f = flow % (port.decode()) - run_command(['/usr/bin/ovs-ofctl', 'add-flow', dpname, f]) - else: - run_command(['/usr/bin/ovs-ofctl', 'add-flow', dpname, flow]) - - def post(self): - for p in self._extra_ports: - log("action_up: bring up %s" % p) - netdev_up(p) - - def bring_down(self): - vsctl_argv = [] - - dp = self._dp - ipdev = self._ipdev - - bridge = pif_bridge_name(dp) - - log("deconfigure ipdev %s on %s" % (ipdev,bridge)) - vsctl_argv += ["# deconfigure ipdev %s" % ipdev] - vsctl_argv += datapath_deconfigure_ipdev(ipdev) - - if pif_is_vlan(self._pif): - # Delete the VLAN bridge. - vsctl_argv += deconfigure_bridge(self._pif) - - # If the VLAN's slave is attached, leave datapath setup. - slave = pif_get_vlan_slave(self._pif) - if db().get_pif_record(slave)['currently_attached']: - log("action_down: vlan slave is currently attached") - dp = None - - # If the VLAN's slave has other VLANs that are attached, leave datapath setup. - for master in pif_get_vlan_masters(slave): - if master != self._pif and db().get_pif_record(master)['currently_attached']: - log("action_down: vlan slave has other master: %s" % pif_netdev_name(master)) - dp = None - - # Otherwise, take down the datapath too (fall through) - if dp: - log("action_down: no more masters, bring down slave %s" % bridge) - else: - # Stop here if this PIF has attached VLAN masters. - masters = [db().get_pif_record(m)['VLAN'] for m in pif_get_vlan_masters(self._pif) if db().get_pif_record(m)['currently_attached']] - if len(masters) > 0: - log("Leaving datapath %s up due to currently attached VLAN masters %s" % (bridge, masters)) - dp = None - - if dp: - vsctl_argv += deconfigure_bridge(dp) - - physical_devices = [pif_netdev_name(p) for p in datapath_get_physical_pifs(dp)] - - log("action_down: bring down physical devices - %s" % physical_devices) - - for p in physical_devices: - netdev_down(p) - - datapath_modify_config(vsctl_argv) - -# -# utility methods -# - -def vswitchCfgQuery(action_args): - cmd = ['%s/usr/bin/ovs-vsctl' % root_prefix(), - '-vconsole:off'] + action_args - output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate() - if len(output) == 0 or output[0] == None: - output = "" - else: - output = output[0].strip() - return output diff --git a/xenserver/opt_xensource_libexec_interface-reconfigure b/xenserver/opt_xensource_libexec_interface-reconfigure deleted file mode 100755 index 9c20725de..000000000 --- a/xenserver/opt_xensource_libexec_interface-reconfigure +++ /dev/null @@ -1,739 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (c) 2008,2009 Citrix Systems, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation; version 2.1 only. with the special -# exception on linking described in file LICENSE. -# -# 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 Lesser General Public License for more details. -# -"""Usage: - - %(command-name)s <PIF> up - %(command-name)s <PIF> down - %(command-name)s rewrite - %(command-name)s --force <BRIDGE> up - %(command-name)s --force <BRIDGE> down - %(command-name)s --force <BRIDGE> rewrite --device=<INTERFACE> --mac=<MAC-ADDRESS> <CONFIG> - - where <PIF> is one of: - --session <SESSION-REF> --pif <PIF-REF> - --pif-uuid <PIF-UUID> - and <CONFIG> is one of: - --mode=dhcp - --mode=static --ip=<IPADDR> --netmask=<NM> [--gateway=<GW>] - - Options: - --session A session reference to use to access the xapi DB - --pif A PIF reference within the session. - --pif-uuid The UUID of a PIF. - --force An interface name. - --root-prefix=DIR Use DIR as alternate root directory (for testing). - --no-syslog Write log messages to stderr instead of system log. -""" - -# 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) - -from InterfaceReconfigure import * - -import os, sys, getopt -import syslog -import traceback -import re -import random -import syslog - -management_pif = None - -dbcache_file = "/var/xapi/network.dbcache" - -# -# Logging. -# - -def log_pif_action(action, pif): - pifrec = db().get_pif_record(pif) - rec = {} - rec['uuid'] = pifrec['uuid'] - rec['ip_configuration_mode'] = pifrec['ip_configuration_mode'] - rec['action'] = action - rec['pif_netdev_name'] = pif_netdev_name(pif) - rec['message'] = "Bring %(action)s PIF %(uuid)s" % rec - log("%(message)s: %(pif_netdev_name)s configured as %(ip_configuration_mode)s" % rec) - -# -# Exceptions. -# - -class Usage(Exception): - def __init__(self, msg): - Exception.__init__(self) - self.msg = msg - -# -# Boot from Network filesystem or device. -# - -def check_allowed(pif): - """Determine whether interface-reconfigure should be manipulating this PIF. - - Used to prevent system PIFs (such as network root disk) from being interfered with. - """ - - pifrec = db().get_pif_record(pif) - try: - f = open(root_prefix() + "/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 - -# -# Bare Network Devices -- network devices without IP configuration -# - -def netdev_remap_name(pif, already_renamed=[]): - """Check whether 'pif' exists and has the correct MAC. - If not, try to find a device with the correct MAC and rename it. - 'already_renamed' is used to avoid infinite recursion. - """ - - def read1(name): - file = None - try: - file = open(name, 'r') - return file.readline().rstrip('\n') - finally: - if file != None: - file.close() - - def get_netdev_mac(device): - try: - return read1("%s/sys/class/net/%s/address" % (root_prefix(), device)) - except: - # Probably no such device. - return None - - def get_netdev_tx_queue_len(device): - try: - return int(read1("%s/sys/class/net/%s/tx_queue_len" % (root_prefix(), device))) - except: - # Probably no such device. - return None - - def get_netdev_by_mac(mac): - for device in os.listdir(root_prefix() + "/sys/class/net"): - dev_mac = get_netdev_mac(device) - if (dev_mac and mac.lower() == dev_mac.lower() and - get_netdev_tx_queue_len(device)): - return device - return None - - def rename_netdev(old_name, new_name): - raise Error("Trying to rename %s to %s - This functionality has been removed" % (old_name, new_name)) - # log("Changing the name of %s to %s" % (old_name, new_name)) - # run_command(['/sbin/ip', 'link', 'set', old_name, 'down']) - # if not run_command(['/sbin/ip', 'link', 'set', old_name, 'name', new_name]): - # raise Error("Could not rename %s to %s" % (old_name, new_name)) - - pifrec = db().get_pif_record(pif) - device = pifrec['device'] - mac = pifrec['MAC'] - - # Is there a network device named 'device' at all? - device_exists = netdev_exists(device) - if device_exists: - # Yes. Does it have MAC 'mac'? - found_mac = get_netdev_mac(device) - if found_mac and mac.lower() == found_mac.lower(): - # Yes, everything checks out the way we want. Nothing to do. - return - else: - log("No network device %s" % device) - - # What device has MAC 'mac'? - cur_device = get_netdev_by_mac(mac) - if not cur_device: - log("No network device has MAC %s" % mac) - return - - # First rename 'device', if it exists, to get it out of the way - # for 'cur_device' to replace it. - if device_exists: - rename_netdev(device, "dev%d" % random.getrandbits(24)) - - # Rename 'cur_device' to 'device'. - rename_netdev(cur_device, device) - -# -# IP Network Devices -- network devices with IP configuration -# - -def ifdown(netdev): - """Bring down a network interface""" - if not netdev_exists(netdev): - log("ifdown: device %s does not exist, ignoring" % netdev) - return - if not os.path.exists("%s/etc/sysconfig/network-scripts/ifcfg-%s" % (root_prefix(), netdev)): - log("ifdown: device %s exists but ifcfg-%s does not" % (netdev,netdev)) - run_command(["/sbin/ip", "link", "set", netdev, 'down']) - return - run_command(["/sbin/ifdown", netdev]) - -def ifup(netdev): - """Bring up a network interface""" - if not os.path.exists(root_prefix() + "/etc/sysconfig/network-scripts/ifcfg-%s" % netdev): - raise Error("ifup: device %s exists but ifcfg-%s does not" % (netdev,netdev)) - d = os.getenv("DHCLIENTARGS","") - if os.path.exists("/etc/firstboot.d/data/firstboot_in_progress"): - os.putenv("DHCLIENTARGS", d + " -T 240 " ) - run_command(["/sbin/ifup", netdev]) - os.putenv("DHCLIENTARGS", d ) - -# -# -# - -def pif_rename_physical_devices(pif): - if pif_is_tunnel(pif): - return - - if pif_is_vlan(pif): - pif = pif_get_vlan_slave(pif) - - if pif_is_bond(pif): - pifs = pif_get_bond_slaves(pif) - else: - pifs = [pif] - - for pif in pifs: - netdev_remap_name(pif) - -# -# IP device configuration -# - -def ipdev_configure_static_routes(interface, oc, f): - """Open a route-<interface> file for static routes. - - Opens the static routes configuration file for interface and writes one - line for each route specified in the network's other config "static-routes" value. - E.g. if - interface ( RO): xenbr1 - other-config (MRW): static-routes: 172.16.0.0/15/192.168.0.3,172.18.0.0/16/192.168.0.4;... - - Then route-xenbr1 should be - 172.16.0.0/15 via 192.168.0.3 dev xenbr1 - 172.18.0.0/16 via 192.168.0.4 dev xenbr1 - """ - if 'static-routes' in oc: - # The key is present - extract comma separates entries - lines = oc['static-routes'].split(',') - else: - # The key is not present, i.e. there are no static routes - lines = [] - - child = ConfigurationFile("%s/etc/sysconfig/network-scripts/route-%s" % (root_prefix(), interface)) - child.write("# DO NOT EDIT: This file (%s) was autogenerated by %s\n" % \ - (os.path.basename(child.path()), os.path.basename(sys.argv[0]))) - - try: - for l in lines: - network, masklen, gateway = l.split('/') - child.write("%s/%s via %s dev %s\n" % (network, masklen, gateway, interface)) - - f.attach_child(child) - child.close() - - except ValueError as e: - log("Error in other-config['static-routes'] format for network %s: %s" % (interface, e)) - -def ipdev_open_ifcfg(pif): - ipdev = pif_ipdev_name(pif) - - log("Writing network configuration for %s" % ipdev) - - f = ConfigurationFile("%s/etc/sysconfig/network-scripts/ifcfg-%s" % (root_prefix(), ipdev)) - - f.write("# DO NOT EDIT: This file (%s) was autogenerated by %s\n" % \ - (os.path.basename(f.path()), os.path.basename(sys.argv[0]))) - f.write("XEMANAGED=yes\n") - f.write("DEVICE=%s\n" % ipdev) - f.write("ONBOOT=no\n") - f.write("NOZEROCONF=yes\n") - - return f - -def ipdev_configure_network(pif, dp): - """Write the configuration file for a network. - - Writes configuration derived from the network object into the relevant - ifcfg file. The configuration file is passed in, but if the network is - bridgeless it will be ifcfg-<interface>, otherwise it will be ifcfg-<bridge>. - - This routine may also write ifcfg files of the networks corresponding to other PIFs - in order to maintain consistency. - - params: - pif: Opaque_ref of pif - dp: Datapath object - """ - - pifrec = db().get_pif_record(pif) - nw = pifrec['network'] - nwrec = db().get_network_record(nw) - - ipdev = pif_ipdev_name(pif) - - f = ipdev_open_ifcfg(pif) - - mode = pifrec['ip_configuration_mode'] - log("Configuring %s using %s configuration" % (ipdev, mode)) - - oc = None - if 'other_config' in pifrec: - oc = pifrec['other_config'] - - dp.configure_ipdev(f) - - if pifrec['ip_configuration_mode'] == "DHCP": - f.write("BOOTPROTO=dhcp\n") - f.write("PERSISTENT_DHCLIENT=yes\n") - elif pifrec['ip_configuration_mode'] == "Static": - f.write("BOOTPROTO=none\n") - f.write("NETMASK=%(netmask)s\n" % pifrec) - f.write("IPADDR=%(IP)s\n" % pifrec) - f.write("GATEWAY=%(gateway)s\n" % pifrec) - elif pifrec['ip_configuration_mode'] == "None": - f.write("BOOTPROTO=none\n") - else: - raise Error("Unknown ip-configuration-mode %s" % pifrec['ip_configuration_mode']) - - if 'other_config' in nwrec: - settings,offload = ethtool_settings(nwrec['other_config']) - if len(settings): - f.write("ETHTOOL_OPTS=\"%s\"\n" % str.join(" ", settings)) - if len(offload): - f.write("ETHTOOL_OFFLOAD_OPTS=\"%s\"\n" % str.join(" ", offload)) - - ipdev_configure_static_routes(ipdev, nwrec['other_config'], f) - - mtu = mtu_setting(nw, "Network", nwrec['other_config']) - if mtu: - f.write("MTU=%s\n" % mtu) - - - if 'DNS' in pifrec and pifrec['DNS'] != "": - ServerList = pifrec['DNS'].split(",") - for i in range(len(ServerList)): f.write("DNS%d=%s\n" % (i+1, ServerList[i])) - if oc and 'domain' in oc: - f.write("DOMAIN='%s'\n" % oc['domain'].replace(',', ' ')) - - # There can be only one DNSDEV and one GATEWAYDEV in /etc/sysconfig/network. - # - # 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. - - # Work out which pif on this host should be the DNSDEV and which - # should be the GATEWAYDEV - # - # 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. - - pifs_on_host = [p for p in db().get_all_pifs() if not p in pif_get_bond_masters(pif)] - - # now prune out bond slaves as they are not connected to the IP - # stack and so cannot be used as gateway or DNS devices. - pifs_on_host = [ p for p in pifs_on_host if len(pif_get_bond_masters(p)) == 0] - - # loop through all the pifs on this host looking for one with - # other-config:peerdns = true, and one with - # other-config:default-route=true - peerdns_pif = None - defaultroute_pif = None - for __pif in pifs_on_host: - __pifrec = db().get_pif_record(__pif) - __oc = __pifrec['other_config'] - if 'peerdns' in __oc 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 'defaultroute' in __oc 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 - - is_dnsdev = peerdns_pif == pif - is_gatewaydev = defaultroute_pif == pif - - if is_dnsdev or is_gatewaydev: - fnetwork = ConfigurationFile(root_prefix() + "/etc/sysconfig/network") - for line in fnetwork.readlines(): - if is_dnsdev and line.lstrip().startswith('DNSDEV='): - fnetwork.write('DNSDEV=%s\n' % ipdev) - is_dnsdev = False - elif is_gatewaydev and line.lstrip().startswith('GATEWAYDEV='): - fnetwork.write('GATEWAYDEV=%s\n' % ipdev) - is_gatewaydev = False - else: - fnetwork.write(line) - - if is_dnsdev: - fnetwork.write('DNSDEV=%s\n' % ipdev) - if is_gatewaydev: - fnetwork.write('GATEWAYDEV=%s\n' % ipdev) - - fnetwork.close() - f.attach_child(fnetwork) - - return f - -# -# Toplevel actions -# - -def action_up(pif, force): - pifrec = db().get_pif_record(pif) - - ipdev = pif_ipdev_name(pif) - dp = DatapathFactory()(pif) - - log("action_up: %s" % ipdev) - - f = ipdev_configure_network(pif, dp) - - dp.preconfigure(f) - - f.close() - - pif_rename_physical_devices(pif) - - # if we are not forcing the interface up then attempt to tear down - # any existing devices which might interfere with brinign this one - # up. - if not force: - ifdown(ipdev) - - dp.bring_down_existing() - - try: - f.apply() - - dp.configure() - - ifup(ipdev) - - dp.post() - - # Update /etc/issue (which contains the IP address of the management interface) - os.system(root_prefix() + "/sbin/update-issue") - - f.commit() - except Error as e: - log("failed to apply changes: %s" % e.msg) - f.revert() - raise - -def action_down(pif): - ipdev = pif_ipdev_name(pif) - dp = DatapathFactory()(pif) - - log("action_down: %s" % ipdev) - - ifdown(ipdev) - - dp.bring_down() - -def action_rewrite(): - DatapathFactory().rewrite() - -# This is useful for reconfiguring the mgmt interface after having lost connectivity to the pool master -def action_force_rewrite(bridge, config): - def getUUID(): - import subprocess - uuid,_ = subprocess.Popen(['uuidgen'], stdout = subprocess.PIPE).communicate() - return uuid.strip() - - # Notes: - # 1. that this assumes the interface is bridged - # 2. If --gateway is given it will make that the default gateway for the host - - # extract the configuration - try: - mode = config['mode'] - mac = config['mac'] - interface = config['device'] - except: - raise Usage("Please supply --mode, --mac and --device") - - if mode == 'static': - try: - netmask = config['netmask'] - ip = config['ip'] - except: - raise Usage("Please supply --netmask and --ip") - try: - gateway = config['gateway'] - except: - gateway = None - elif mode != 'dhcp': - raise Usage("--mode must be either static or dhcp") - - if 'vlan' in config: - is_vlan = True - vlan_slave, vlan_vid = config['vlan'].split('.') - else: - is_vlan = False - - if is_vlan: - raise Error("Force rewrite of VLAN not implemented") - - log("Configuring %s using %s configuration" % (bridge, mode)) - - f = ConfigurationFile(root_prefix() + dbcache_file) - - pif_uuid = getUUID() - network_uuid = getUUID() - - f.write('<?xml version="1.0" ?>\n') - f.write('<xenserver-network-configuration>\n') - f.write('\t<pif ref="OpaqueRef:%s">\n' % pif_uuid) - f.write('\t\t<network>OpaqueRef:%s</network>\n' % network_uuid) - f.write('\t\t<management>True</management>\n') - f.write('\t\t<uuid>%sPif</uuid>\n' % interface) - f.write('\t\t<bond_slave_of>OpaqueRef:NULL</bond_slave_of>\n') - f.write('\t\t<bond_master_of/>\n') - f.write('\t\t<VLAN_slave_of/>\n') - f.write('\t\t<VLAN_master_of>OpaqueRef:NULL</VLAN_master_of>\n') - f.write('\t\t<VLAN>-1</VLAN>\n') - f.write('\t\t<tunnel_access_PIF_of/>\n') - f.write('\t\t<tunnel_transport_PIF_of/>\n') - f.write('\t\t<device>%s</device>\n' % interface) - f.write('\t\t<MAC>%s</MAC>\n' % mac) - f.write('\t\t<other_config/>\n') - if mode == 'dhcp': - f.write('\t\t<ip_configuration_mode>DHCP</ip_configuration_mode>\n') - f.write('\t\t<IP></IP>\n') - f.write('\t\t<netmask></netmask>\n') - f.write('\t\t<gateway></gateway>\n') - f.write('\t\t<DNS></DNS>\n') - elif mode == 'static': - f.write('\t\t<ip_configuration_mode>Static</ip_configuration_mode>\n') - f.write('\t\t<IP>%s</IP>\n' % ip) - f.write('\t\t<netmask>%s</netmask>\n' % netmask) - if gateway is not None: - f.write('\t\t<gateway>%s</gateway>\n' % gateway) - f.write('\t\t<DNS></DNS>\n') - else: - raise Error("Unknown mode %s" % mode) - f.write('\t</pif>\n') - - f.write('\t<network ref="OpaqueRef:%s">\n' % network_uuid) - f.write('\t\t<uuid>InitialManagementNetwork</uuid>\n') - f.write('\t\t<PIFs>\n') - f.write('\t\t\t<PIF>OpaqueRef:%s</PIF>\n' % pif_uuid) - f.write('\t\t</PIFs>\n') - f.write('\t\t<bridge>%s</bridge>\n' % bridge) - f.write('\t\t<other_config/>\n') - f.write('\t</network>\n') - f.write('</xenserver-network-configuration>\n') - - f.close() - - try: - f.apply() - f.commit() - except Error as e: - log("failed to apply changes: %s" % e.msg) - f.revert() - raise - -def main(argv=None): - global 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 = [ "pif=", "pif-uuid=", - "session=", - "force=", - "force-interface=", - "management", - "mac=", "device=", "mode=", "ip=", "netmask=", "gateway=", - "root-prefix=", - "no-syslog", - "help" ] - arglist, args = getopt.gnu_getopt(argv[1:], shortops, longops) - except getopt.GetoptError as msg: - raise Usage(msg) - - force_rewrite_config = {} - - for o,a in arglist: - if 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 ["--mac", "--device", "--mode", "--ip", "--netmask", "--gateway"]: - force_rewrite_config[o[2:]] = a - elif o == "--root-prefix": - set_root_prefix(a) - elif o == "--no-syslog": - set_log_destination("stderr") - elif o == "-h" or o == "--help": - print(__doc__ % {'command-name': os.path.basename(argv[0])}) - return 0 - - if get_log_destination() == "syslog": - 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] - - if not action in ["up", "down", "rewrite", "rewrite-configuration"]: - raise Usage("Unknown action \"%s\"" % action) - - # backwards compatibility - if action == "rewrite-configuration": action = "rewrite" - - 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") - if (action == "rewrite") and (pif or pif_uuid ): - raise Usage("rewrite action does not take --pif or --pif-uuid") - - global db - if force_interface: - log("Force interface %s %s" % (force_interface, action)) - - if action == "rewrite": - action_force_rewrite(force_interface, force_rewrite_config) - elif action in ["up", "down"]: - db_init_from_cache(dbcache_file) - pif = db().get_pif_by_bridge(force_interface) - management_pif = db().get_management_pif() - - if action == "up": - action_up(pif, True) - elif action == "down": - action_down(pif) - else: - raise Error("Unknown action %s" % action) - else: - db_init_from_xenapi(session) - - if pif_uuid: - pif = db().get_pif_by_uuid(pif_uuid) - - if action == "rewrite": - action_rewrite() - else: - 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) - management_pif = db().get_management_pif() - - log_pif_action(action, pif) - - if not check_allowed(pif): - return 0 - - if action == "up": - action_up(pif, False) - elif action == "down": - action_down(pif) - else: - raise Error("Unknown action %s" % action) - - # Save cache. - db().save(dbcache_file) - - except Usage as err: - sys.stderr.write(err.msg + "\n") - sys.stderr.write("For help use --help.\n") - sys.stderr.flush() - return 2 - except Error as 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) - - syslog.closelog() - - sys.exit(rc) diff --git a/xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py b/xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py deleted file mode 100644 index 8946917d5..000000000 --- a/xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py +++ /dev/null @@ -1,331 +0,0 @@ -# Copyright (c) 2009,2010,2011,2012,2013 Nicira, Inc. -# Copyright (c) 2007-2011 Citrix Systems 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; version 2 only. -# -# 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. - -from XSConsoleLog import * - -import os -import socket -import subprocess - -vsctl="/usr/bin/ovs-vsctl" - -if __name__ == "__main__": - raise Exception("This script is a plugin for xsconsole and cannot run independently") - -from XSConsoleStandard import * - -class VSwitchService: - service = {} - - def __init__(self, name, processname=None): - self.name = name - self.processname = processname - if self.processname == None: - self.processname = name - - def version(self): - try: - output = ShellPipe(["service", self.name, "version"]).Stdout() - except StandardError as e: - XSLogError("vswitch version retrieval error: " + str(e)) - return "<unknown>" - for line in output: - if self.processname in line: - return line.split()[-1] - return "<unknown>" - - def status(self): - try: - output = ShellPipe(["service", self.name, "status"]).Stdout() - except StandardError as e: - XSLogError("vswitch status retrieval error: " + str(e)) - return "<unknown>" - if len(output) == 0: - return "<unknown>" - for line in output: - if self.processname not in line: - continue - elif "running" in line: - return "Running" - elif "stop" in line: - return "Stopped" - else: - return "<unknown>" - return "<unknown>" - - def restart(self): - try: - ShellPipe(["service", self.name, "restart"]).Call() - except StandardError as e: - XSLogError("vswitch restart 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] = VSwitchService(name, processname) - return cls.service[key] - -class VSwitchConfig: - - @staticmethod - def Get(action): - try: - arg = [vsctl, "-vconsole:off"] + action.split() - output = ShellPipe(arg).Stdout() - except StandardError as e: - XSLogError("config retrieval error: " + str(e)) - return "<unknown>" - - if len(output) == 0: - output = "" - else: - output = output[0].strip() - return output - - -class VSwitchControllerDialogue(Dialogue): - def __init__(self): - Dialogue.__init__(self) - data=Data.Inst() - - self.hostsInPool = 0 - self.hostsUpdated = 0 - self.xs_version = data.host.software_version.product_version('') - pool = data.GetPoolForThisHost() - if pool is not None: - self.controller = pool.get("vswitch_controller", "") - else: - 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 ovs-vswitchd"), -# lambda: self.restartService("vswitch")), - ] - self.menu = Menu(self, None, Lang("Configure Open vSwitch"), choiceDefs) - - self.ChangeState("INITIAL") - - def BuildPane(self): - pane = self.NewPane(DialoguePane(self.parent)) - pane.TitleSet(Lang("Configure Open 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 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'] - Layout.Inst().PopDialogue() - - # Make sure the controller is specified as a valid dotted quad - try: - socket.inet_aton(self.controller) - except socket.error: - Layout.Inst().PushDialogue(InfoDialogue(Lang("Please enter in dotted quad format"))) - return True - - Layout.Inst().TransientBanner(Lang("Setting controller...")) - try: - self.SetController(self.controller) - Layout.Inst().PushDialogue(InfoDialogue(Lang("Setting controller successful"))) - except Exception as e: - Layout.Inst().PushDialogue(InfoDialogue(Lang("Setting controller failed"))) - - self.ChangeState("INITIAL") - return True - else: - return pane.CurrentInput().HandleKey(inKey) - - def restartService(self, name): - s = VSwitchService.Inst(name) - s.restart() - Layout.Inst().PopDialogue() - - def getController(self): - self.ChangeState("GETCONTROLLER") - self.Pane().InputIndexSet(0) - - def deleteController(self): - self.controller = "" - Layout.Inst().PopDialogue() - Layout.Inst().TransientBanner(Lang("Deleting controller...")) - try: - self.SetController(None) - Layout.Inst().PushDialogue(InfoDialogue(Lang("Controller deletion successful"))) - except Exception as e: - Layout.Inst().PushDialogue(InfoDialogue(Lang("Controller deletion failed"))) - - def syncController(self): - Layout.Inst().PopDialogue() - Layout.Inst().TransientBanner(Lang("Resyncing controller setting...")) - try: - Task.Sync(lambda s: self._updateThisServer(s)) - Layout.Inst().PushDialogue(InfoDialogue(Lang("Resyncing controller config successful"))) - except Exception as e: - Layout.Inst().PushDialogue(InfoDialogue(Lang("Resyncing controller config failed"))) - - def SetController(self, ip): - self.hostsInPool = 0 - self.hostsUpdated = 0 - Task.Sync(lambda s: self._modifyPoolConfig(s, ip or "")) - # Should be done asynchronously, maybe with an external script? - Task.Sync(lambda s: self._updateActiveServers(s)) - - def _modifyPoolConfig(self, session, value): - """Modify pool configuration. - - If value == "" then delete configuration, otherwise set to value. - """ - pools = session.xenapi.pool.get_all() - # We assume there is only ever one pool... - if len(pools) == 0: - XSLogFatal(Lang("No pool found for host.")) - return - if len(pools) > 1: - XSLogFatal(Lang("More than one pool for host.")) - return - session.xenapi.pool.set_vswitch_controller(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: - Layout.Inst().TransientBanner("Updating host %d out of %d" - % (self.hostsUpdated + 1, self.hostsInPool)) - session.xenapi.host.call_plugin(host, "openvswitch-cfg-update", "update", {}) - self.hostsUpdated = self.hostsUpdated + 1 - - def _updateThisServer(self, session): - data = Data.Inst() - host = data.host.opaqueref() - session.xenapi.host.call_plugin(host, "openvswitch-cfg-update", "update", {}) - - -class XSFeatureVSwitch: - - @classmethod - def StatusUpdateHandler(cls, inPane): - data = Data.Inst() - xs_version = data.host.software_version.product_version('') - - inPane.AddTitleField(Lang("Open vSwitch")) - - inPane.NewLine() - - inPane.AddStatusField(Lang("Version", 20), - VSwitchService.Inst("openvswitch", "ovs-vswitchd").version()) - - inPane.NewLine() - - pool = data.GetPoolForThisHost() - if pool is not None: - dbController = pool.get("vswitch_controller", "") - else: - dbController = "" - - if dbController == "": - dbController = Lang("<None>") - inPane.AddStatusField(Lang("Controller (config)", 20), dbController) - controller = VSwitchConfig.Get("get-manager") - - if controller == "": - controller = Lang("<None>") - elif controller[0:4] == "ssl:": - controller = controller.split(':')[1] - inPane.AddStatusField(Lang("Controller (in-use)", 20), controller) - - inPane.NewLine() - inPane.AddStatusField(Lang("ovs-vswitchd status", 20), - VSwitchService.Inst("openvswitch", "ovs-vswitchd").status()) - inPane.AddStatusField(Lang("ovsdb-server status", 20), - VSwitchService.Inst("openvswitch", "ovsdb-server").status()) - - inPane.AddKeyHelpField( { - Lang("<Enter>") : Lang("Reconfigure"), - Lang("<F5>") : Lang("Refresh") - }) - - @classmethod - def ActivateHandler(cls): - DialogueUtils.AuthenticatedOnly(lambda: Layout.Inst().PushDialogue(VSwitchControllerDialogue())) - - def Register(self): - Importer.RegisterNamedPlugIn( - self, - 'VSwitch', # Key of this plugin for replacement, etc. - { - 'menuname' : 'MENU_NETWORK', - 'menupriority' : 800, - 'menutext' : Lang('Open vSwitch') , - 'statusupdatehandler' : self.StatusUpdateHandler, - 'activatehandler' : self.ActivateHandler - } - ) - -# Register this plugin when module is imported, IFF vswitchd is running -if os.path.exists('/var/run/openvswitch/ovs-vswitchd.pid'): - XSFeatureVSwitch().Register() diff --git a/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync b/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync deleted file mode 100755 index bff85464b..000000000 --- a/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync +++ /dev/null @@ -1,404 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2009, 2010, 2011, 2012, 2013, 2020 Nicira, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -# A daemon to monitor the external_ids columns of the Bridge and -# Interface OVSDB tables for changes that require interrogating XAPI. -# Its responsibilities include: -# -# - Set the "bridge-id" key in the Bridge table. -# - Set the "iface-id" key in the Interface table. -# - Set the fail-mode on internal bridges. - -import argparse -import os -import sys -import time - -import XenAPI - -import ovs.daemon -import ovs.db.idl -import ovs.dirs -import ovs.unixctl -import ovs.unixctl.server - -vlog = ovs.vlog.Vlog("ovs-xapi-sync") -session = None -flush_cache = False -exiting = False -xapi_down = False - - -def unixctl_exit(conn, unused_argv, unused_aux): - global exiting - exiting = True - conn.reply(None) - - -def unixctl_flush_cache(conn, unused_argv, unused_aux): - global flush_cache - flush_cache = True - conn.reply(None) - - -# Set up a session to interact with XAPI. -# -# On system start-up, OVS comes up before XAPI, so we can't log into the -# session until later. Try to do this on-demand, since we won't -# actually do anything interesting until XAPI is up. -def init_session(): - global session - if session is not None: - return True - - try: - session = XenAPI.xapi_local() - session.xenapi.login_with_password("", "") - except XenAPI.Failure as e: - session = None - vlog.warn("Couldn't login to XAPI (%s)" % e) - return False - - return True - - -def get_network_by_bridge(br_name): - if not init_session(): - vlog.warn("Failed to get bridge id %s because" - " XAPI session could not be initialized" % br_name) - return None - - recs = session.xenapi.network.get_all_records_where( - 'field "bridge"="%s"' % br_name) - if len(recs) > 0: - return next(iter(recs.values())) - - return None - - -# There are possibilities when multiple xs-network-uuids are set for a bridge. -# In cases like that, we should choose the bridge-id associated with the bridge -# name. -def get_single_bridge_id(bridge_ids, br_name, default=None): - global xapi_down - - rec = get_network_by_bridge(br_name) - if rec and rec['uuid'] in bridge_ids: - return rec['uuid'] - - vlog.warn("Failed to get a single bridge id from Xapi.") - xapi_down = True - return default - - -# By default, the "bridge-id" external id in the Bridge table is the -# same as "xs-network-uuids". This may be overridden by defining a -# "nicira-bridge-id" key in the "other_config" field of the network -# record of XAPI. If nicira-bridge-id is undefined returns default. -# On error returns None. -def get_bridge_id(br_name, default=None): - rec = get_network_by_bridge(br_name) - if rec: - return rec['other_config'].get('nicira-bridge-id', default) - return None - - -# By default, the "iface-id" external id in the Interface table is the -# same as "xs-vif-uuid". This may be overridden by defining a -# "nicira-iface-id" key in the "other_config" field of the VIF -# record of XAPI. -def get_iface_id(if_name, xs_vif_uuid): - if not if_name.startswith("vif") and not if_name.startswith("tap"): - # Treat whatever was passed into 'xs_vif_uuid' as a default - # value for non-VIFs. - return xs_vif_uuid - - if not init_session(): - vlog.warn("Failed to get interface id %s because" - " XAPI session could not be initialized" % if_name) - return xs_vif_uuid - - try: - vif = session.xenapi.VIF.get_by_uuid(xs_vif_uuid) - rec = session.xenapi.VIF.get_record(vif) - return rec['other_config'].get('nicira-iface-id', xs_vif_uuid) - except XenAPI.Failure: - vlog.warn("Could not find XAPI entry for VIF %s" % if_name) - return xs_vif_uuid - - -# By default, the "vm-id" external id in the Interface table is the -# same as "xs-vm-uuid". This may be overridden by defining a -# "nicira-vm-id" key in the "other_config" field of the VM -# record of XAPI. -def get_vm_id(if_name, xs_vm_uuid): - if not if_name.startswith("vif") and not if_name.startswith("tap"): - # Treat whatever was passed into 'xs_vm_uuid' as a default - # value for non-VIFs. - return xs_vm_uuid - - if not init_session(): - vlog.warn("Failed to get vm id for interface id %s because" - " XAPI session could not be initialized" % if_name) - return xs_vm_uuid - - try: - vm = session.xenapi.VM.get_by_uuid(xs_vm_uuid) - rec = session.xenapi.VM.get_record(vm) - return rec['other_config'].get('nicira-vm-id', xs_vm_uuid) - except XenAPI.Failure: - vlog.warn("Could not find XAPI entry for VIF %s" % if_name) - return xs_vm_uuid - - -def set_or_delete(d, key, value): - if value is None: - if key in d: - del d[key] - return True - else: - if d.get(key) != value: - d[key] = value - return True - return False - - -def set_external_id(row, key, value): - row.verify("external_ids") - external_ids = row.external_ids - if set_or_delete(external_ids, key, value): - row.external_ids = external_ids - - -# XenServer does not call interface-reconfigure on internal networks, -# which is where the fail-mode would normally be set. -def update_fail_mode(row): - rec = get_network_by_bridge(row.name) - if not rec: - return - - fail_mode = rec['other_config'].get('vswitch-controller-fail-mode') - - if not fail_mode: - pools = session.xenapi.pool.get_all() - if len(pools) == 1: - prec = session.xenapi.pool.get_record(pools[0]) - fail_mode = prec['other_config'].get( - 'vswitch-controller-fail-mode') - - if fail_mode not in ['standalone', 'secure']: - fail_mode = 'standalone' - - row.verify("fail_mode") - if row.fail_mode != fail_mode: - row.fail_mode = fail_mode - - -def update_in_band_mgmt(row): - rec = get_network_by_bridge(row.name) - if not rec: - return - - dib = rec['other_config'].get('vswitch-disable-in-band') - - row.verify("other_config") - other_config = row.other_config - if dib and dib not in ['true', 'false']: - vlog.warn('"%s" isn\'t a valid setting for ' - "other_config:disable-in-band on %s" % (dib, row.name)) - elif set_or_delete(other_config, 'disable-in-band', dib): - row.other_config = other_config - - -def main(): - global flush_cache, xapi_down - - parser = argparse.ArgumentParser() - parser.add_argument("database", metavar="DATABASE", - help="A socket on which ovsdb-server is listening.") - parser.add_argument("--root-prefix", metavar="DIR", default='', - help="Use DIR as alternate root directory" - " (for testing).") - - ovs.vlog.add_args(parser) - ovs.daemon.add_args(parser) - args = parser.parse_args() - ovs.vlog.handle_args(args) - ovs.daemon.handle_args(args) - - remote = args.database - schema_helper = ovs.db.idl.SchemaHelper() - schema_helper.register_columns("Bridge", ["name", "external_ids", - "other_config", "fail_mode"]) - schema_helper.register_columns("Interface", ["name", "external_ids"]) - idl = ovs.db.idl.Idl(remote, schema_helper) - - ovs.daemon.daemonize() - - ovs.unixctl.command_register("exit", "", 0, 0, unixctl_exit, None) - ovs.unixctl.command_register("flush-cache", "", 0, 0, unixctl_flush_cache, - None) - error, unixctl_server = ovs.unixctl.server.UnixctlServer.create(None) - if error: - ovs.util.ovs_fatal(error, "could not create unixctl server", vlog) - - # This daemon is usually started before XAPI, but to complete our - # tasks, we need it. Wait here until it's up. - cookie_file = args.root_prefix + "/var/run/xapi_init_complete.cookie" - while not os.path.exists(cookie_file): - time.sleep(1) - - bridges = {} # Map from bridge name to nicira-bridge-id - iface_ids = {} # Map from xs-vif-uuid to iface-id - vm_ids = {} # Map from xs-vm-uuid to vm-id - seqno = idl.change_seqno # Sequence number when we last processed the db - while True: - unixctl_server.run() - if exiting: - break - - idl.run() - if not xapi_down and not flush_cache and seqno == idl.change_seqno: - poller = ovs.poller.Poller() - unixctl_server.wait(poller) - idl.wait(poller) - poller.block() - continue - - if xapi_down: - vlog.warn("Xapi is probably down. Retry again after a second.") - time.sleep(1) - xapi_down = False - - if flush_cache: - vlog.info("Flushing cache as the result of unixctl.") - bridges = {} - iface_ids = {} - vm_ids = {} - flush_cache = False - seqno = idl.change_seqno - - txn = ovs.db.idl.Transaction(idl) - - new_bridges = {} - for row in idl.tables["Bridge"].rows.values(): - bridge_id = bridges.get(row.name) - if bridge_id is None: - # Configure the new bridge. - update_fail_mode(row) - update_in_band_mgmt(row) - - # Get the correct bridge_id, if we can. - bridge_id = get_bridge_id(row.name) - if bridge_id is None: - xs_network_uuids = row.external_ids.get("xs-network-uuids") - if xs_network_uuids: - bridge_ids = xs_network_uuids.split(";") - if len(bridge_ids) == 1: - bridge_id = bridge_ids[0] - else: - bridge_id = get_single_bridge_id(bridge_ids, - row.name) - set_external_id(row, "bridge-id", bridge_id) - - if bridge_id is not None: - new_bridges[row.name] = bridge_id - bridges = new_bridges - - iface_by_name = {} - for row in idl.tables["Interface"].rows.values(): - iface_by_name[row.name] = row - - new_iface_ids = {} - new_vm_ids = {} - for row in idl.tables["Interface"].rows.values(): - # Match up paired vif and tap devices. - if row.name.startswith("vif"): - vif = row - tap = iface_by_name.get("tap%s" % row.name[3:]) - elif row.name.startswith("tap"): - tap = row - vif = iface_by_name.get("vif%s" % row.name[3:]) - else: - tap = vif = None - - # Several tap external-ids need to be copied from the vif. - if row == tap and vif: - keys = ["attached-mac", - "xs-network-uuid", - "xs-vif-uuid", - "xs-vm-uuid"] - for k in keys: - set_external_id(row, k, vif.external_ids.get(k)) - - # Map from xs-vif-uuid to iface-id. - # - # (A tap's xs-vif-uuid comes from its vif. That falls out - # naturally from the copy loop above.) - xvu = row.external_ids.get("xs-vif-uuid") - if xvu: - iface_id = (new_iface_ids.get(xvu) - or iface_ids.get(xvu) - or get_iface_id(row.name, xvu)) - new_iface_ids[xvu] = iface_id - else: - # No xs-vif-uuid therefore no iface-id. - iface_id = None - set_external_id(row, "iface-id", iface_id) - - # Map from xs-vm-uuid to vm-id. - xvmu = row.external_ids.get("xs-vm-uuid") - if xvmu: - vm_id = (new_vm_ids.get(xvmu) - or vm_ids.get(xvmu) - or get_vm_id(row.name, xvmu)) - new_vm_ids[xvmu] = vm_id - else: - vm_id = None - set_external_id(row, "vm-id", vm_id) - - # When there's a vif and a tap, the tap is active (used for - # traffic). When there's just a vif, the vif is active. - # - # A tap on its own shouldn't happen, and we don't know - # anything about other kinds of devices, so we don't use - # an iface-status for those devices at all. - if vif and tap: - set_external_id(tap, "iface-status", "active") - set_external_id(vif, "iface-status", "inactive") - elif vif: - set_external_id(vif, "iface-status", "active") - else: - set_external_id(row, "iface-status", None) - iface_ids = new_iface_ids - vm_ids = new_vm_ids - - txn.add_comment("ovs-xapi-sync: Updating records from XAPI") - txn.commit_block() - - unixctl_server.close() - idl.close() - - -if __name__ == '__main__': - try: - main() - except SystemExit: - # Let system.exit() calls complete normally - raise - except: - vlog.exception("traceback") - sys.exit(ovs.daemon.RESTART_EXIT_CODE) diff --git a/xenserver/usr_share_openvswitch_scripts_sysconfig.template b/xenserver/usr_share_openvswitch_scripts_sysconfig.template deleted file mode 100644 index 2c0845296..000000000 --- a/xenserver/usr_share_openvswitch_scripts_sysconfig.template +++ /dev/null @@ -1,24 +0,0 @@ -### Configuration options for openvswitch - -# Copyright (C) 2009, 2010, 2011 Nicira, Inc. - -# FORCE_COREFILES: If 'yes' then core files will be enabled. -# FORCE_COREFILES=yes - -# OVSDB_SERVER_PRIORITY: "nice" priority at which to run ovsdb-server. -# -# OVSDB_SERVER_PRIORITY=-10 - -# VSWITCHD_PRIORITY: "nice" priority at which to run ovs-vswitchd. -# VSWITCHD_PRIORITY=-10 - -# VSWITCHD_MLOCKALL: Whether to pass ovs-vswitchd the --mlockall option. -# This option should be set to "yes" or "no". The default is "yes". -# Enabling this option can avoid networking interruptions due to -# system memory pressure in extraordinary situations, such as multiple -# concurrent VM import operations. -# VSWITCHD_MLOCKALL=yes - -# OVS_CTL_OPTS: Extra options to pass to ovs-ctl. This is, for example, -# a suitable place to specify --ovs-vswitchd-wrapper=valgrind. -# OVS_CTL_OPTS= |