From 24e40c6b70d9b4f7ebf1e02bace5794009b0c1b6 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Wed, 3 Jul 2019 03:11:27 +0700 Subject: Initial commit. --- README.md | 11 +++++++++++ bin/vyos-smoketest | 19 +++++++++++++++++++ scripts/test_module_load.py | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 README.md create mode 100755 bin/vyos-smoketest create mode 100755 scripts/test_module_load.py diff --git a/README.md b/README.md new file mode 100644 index 000000000..d02557393 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +vyos-smoketest +============== + +This is a set of scripts and test data for sanity checking VyOS builds. + +The main entry point is /usr/bin/vyos-smoketest + +It will try to check for common things that break such as kernel modules not loading, +and print a test report. + +It also comes with a huge reference config that has almost every feature set. diff --git a/bin/vyos-smoketest b/bin/vyos-smoketest new file mode 100755 index 000000000..b8cc36879 --- /dev/null +++ b/bin/vyos-smoketest @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +import os +import sys + +test_dir = '/usr/libexec/vyos/tests/smoke' + +tests = ['test_load_modules.py'] + +success = True + +for t in tests: + try: + os.system(os.path.join(test_dir, t)) + except Exception as e: + success = False + +if not success: + sys.exit(1) diff --git a/scripts/test_module_load.py b/scripts/test_module_load.py new file mode 100755 index 000000000..a4f3a62eb --- /dev/null +++ b/scripts/test_module_load.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +import sys +import os + +MODULES_INTEL = "e1000 e1000e igb ixgb ixgbe ixgbevf i40e i40evf" +MODULES_ACCEL_PPP = "ipoe" +MODULES_MISC = "wireguard" + +modules = { + "intel": ["e1000", "e1000e", "igb", "ixgb", "ixgbe", "ixgbevf", "i40e", "i40evf"], + "accel_ppp": ["ipoe"], + "misc": ["wireguard"] +} + +if __name__ == '__main__': + success = True + + print("[load modules] Test execution started") + for msk in modules: + ms = modules[msk] + for m in ms: + # We want to uncover all modules that fail, + # not fail at the first one + try: + os.system("modprobe {0}".format(m)) + except Exception as e: + print("[load modules] Test [modprobe {0}] failed: {1}".format(module, e)) + success = False + + if not success: + print("Test [load modules] failed") + sys.exit(1) + else: + print("[load modules] Test succeeded") -- cgit v1.2.3 From 630f398bd23fbfe4e927bf042a7afd3a44f47e08 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Wed, 3 Jul 2019 03:14:16 +0700 Subject: Remove unncesessary lines. --- scripts/test_module_load.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/test_module_load.py b/scripts/test_module_load.py index a4f3a62eb..c96229b92 100755 --- a/scripts/test_module_load.py +++ b/scripts/test_module_load.py @@ -3,10 +3,6 @@ import sys import os -MODULES_INTEL = "e1000 e1000e igb ixgb ixgbe ixgbevf i40e i40evf" -MODULES_ACCEL_PPP = "ipoe" -MODULES_MISC = "wireguard" - modules = { "intel": ["e1000", "e1000e", "igb", "ixgb", "ixgbe", "ixgbevf", "i40e", "i40evf"], "accel_ppp": ["ipoe"], -- cgit v1.2.3 From 35a429c4ca1923b3e87531f34ca64133d4a82efc Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Tue, 2 Jul 2019 22:34:59 +0200 Subject: Add Debian packaging and LGPL license. --- LICENSE | 502 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 4 + bin/vyos-smoketest | 2 +- debian/changelog | 5 + debian/compat | 1 + debian/control | 23 +++ debian/copyright | 35 ++++ debian/rules | 28 +++ 8 files changed, 599 insertions(+), 1 deletion(-) create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100755 debian/rules diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..4362b4915 --- /dev/null +++ b/LICENSE @@ -0,0 +1,502 @@ + 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. + + + Copyright (C) + + 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..c99579b45 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +.PHONY: all + +all: + # Install is just xcopy diff --git a/bin/vyos-smoketest b/bin/vyos-smoketest index b8cc36879..1ae00d5b8 100755 --- a/bin/vyos-smoketest +++ b/bin/vyos-smoketest @@ -5,7 +5,7 @@ import sys test_dir = '/usr/libexec/vyos/tests/smoke' -tests = ['test_load_modules.py'] +tests = ['test_module_load.py'] success = True diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 000000000..2b24a8f9e --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +vyos-smoketest (1.0.0) unstable; urgency=medium + + * Initial release + + -- Daniil Baturin Tue, 02 Jul 2019 22:29:53 +0200 diff --git a/debian/compat b/debian/compat new file mode 100644 index 000000000..ec635144f --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..97f8b27ea --- /dev/null +++ b/debian/control @@ -0,0 +1,23 @@ +Source: vyos-smoketest +Section: contrib/net +Priority: extra +Maintainer: VyOS Package Maintainers +Build-Depends: debhelper (>= 9), + quilt, + python3, + python3-setuptools, + quilt, + python3-lxml, + python3-nose, + python3-coverage +Standards-Version: 3.9.6 + +Package: vyos-smoketest +Architecture: all +Depends: python3, + ${python3:Depends}, + ${shlibs:Depends}, + ${misc:Depends}, + vyos-1x +Description: VyOS build sanity checking toolkit + VyOS build sanity checking toolkit diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 000000000..a3260a7a1 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,35 @@ +This package was debianized by Daniil Baturin on +Tue, 02 Jul 2019 22:24:20 +0200 + +It's original content from the GIT repository + +Upstream Author: + + + +Copyright: + + Copyright (C) 2019 VyOS maintainers and contributors + All Rights Reserved. + +License: + +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; either version 2, 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. + +A copy of the GNU General Public License is available as +`/usr/share/common-licenses/GPL' in the Debian GNU/Linux distribution +or on the World Wide Web at `http://www.gnu.org/copyleft/lgpl.html'. +You can also obtain it by writing to the Free Software Foundation, +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301, USA. + +The Debian packaging is (C) 2019, Daniil Baturin and +is licensed under the GPL, see above. diff --git a/debian/rules b/debian/rules new file mode 100755 index 000000000..4ccc23e86 --- /dev/null +++ b/debian/rules @@ -0,0 +1,28 @@ +#!/usr/bin/make -f + +DIR := debian/vyos-smoketest +VYOS_SBIN_DIR := usr/sbin/ +VYOS_BIN_DIR := usr/bin/ +VYOS_LIBEXEC_DIR := usr/libexec/vyos +VYOS_DATA_DIR := /usr/share/vyos +VYOS_CFG_TMPL_DIR := /opt/vyatta/share/vyatta-cfg/templates +VYOS_OP_TMPL_DIR := /opt/vyatta/share/vyatta-op/templates + +MIGRATION_SCRIPTS_DIR := /opt/vyatta/etc/config-migrate/migrate/ + +SBINDIR := $(DIR)/usr/sbin + +%: + dh $@ --with python3, --with quilt + +override_dh_auto_build: + make all + +override_dh_auto_install: + # Install smoke test scripts + mkdir -p $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/smoke/ + cp -r scripts/* $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/smoke + + # Install system programs + mkdir -p $(SBINDIR) + cp -r bin/* $(SBINDIR) -- cgit v1.2.3 From cd34b290f444614f887eb284aaf135027c7cef41 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Thu, 11 Jul 2019 21:04:52 +0200 Subject: Separate system and CLI tests. --- scripts/system/test_module_load.py | 31 +++++++++++++++++++++++++++++++ scripts/test_module_load.py | 31 ------------------------------- 2 files changed, 31 insertions(+), 31 deletions(-) create mode 100755 scripts/system/test_module_load.py delete mode 100755 scripts/test_module_load.py diff --git a/scripts/system/test_module_load.py b/scripts/system/test_module_load.py new file mode 100755 index 000000000..c96229b92 --- /dev/null +++ b/scripts/system/test_module_load.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +import sys +import os + +modules = { + "intel": ["e1000", "e1000e", "igb", "ixgb", "ixgbe", "ixgbevf", "i40e", "i40evf"], + "accel_ppp": ["ipoe"], + "misc": ["wireguard"] +} + +if __name__ == '__main__': + success = True + + print("[load modules] Test execution started") + for msk in modules: + ms = modules[msk] + for m in ms: + # We want to uncover all modules that fail, + # not fail at the first one + try: + os.system("modprobe {0}".format(m)) + except Exception as e: + print("[load modules] Test [modprobe {0}] failed: {1}".format(module, e)) + success = False + + if not success: + print("Test [load modules] failed") + sys.exit(1) + else: + print("[load modules] Test succeeded") diff --git a/scripts/test_module_load.py b/scripts/test_module_load.py deleted file mode 100755 index c96229b92..000000000 --- a/scripts/test_module_load.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os - -modules = { - "intel": ["e1000", "e1000e", "igb", "ixgb", "ixgbe", "ixgbevf", "i40e", "i40evf"], - "accel_ppp": ["ipoe"], - "misc": ["wireguard"] -} - -if __name__ == '__main__': - success = True - - print("[load modules] Test execution started") - for msk in modules: - ms = modules[msk] - for m in ms: - # We want to uncover all modules that fail, - # not fail at the first one - try: - os.system("modprobe {0}".format(m)) - except Exception as e: - print("[load modules] Test [modprobe {0}] failed: {1}".format(module, e)) - success = False - - if not success: - print("Test [load modules] failed") - sys.exit(1) - else: - print("[load modules] Test succeeded") -- cgit v1.2.3 From afc0b35d1fb485bc315cb8d07bff9f4d62a565ed Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Thu, 11 Jul 2019 21:05:32 +0200 Subject: Add a test for 'system name-server'. --- scripts/cli/test_system_nameserver.py | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 scripts/cli/test_system_nameserver.py diff --git a/scripts/cli/test_system_nameserver.py b/scripts/cli/test_system_nameserver.py new file mode 100644 index 000000000..591680c63 --- /dev/null +++ b/scripts/cli/test_system_nameserver.py @@ -0,0 +1,52 @@ +import os +import re +import unittest + +import vyos.config +import vyos.configsession +import vyos.util as util + +RESOLV_CONF = '/etc/resolv.conf' + +test_servers = ['192.0.2.10', '2001:db8:1::100'] + +base_path = ['system', 'name-server'] + + +def get_name_servers(): + resolv_conf = util.read_file(RESOLV_CONF) + return re.findall(r'\n?nameserver\s+(.*)', resolv_conf) + +class TestSystemNameServer(unittest.TestCase): + def setUp(self): + self.session = vyos.configsession.ConfigSession(os.getpid()) + env = self.session.get_session_env() + self.config = vyos.config.Config(session_env=env) + + # Delete existing name servers + self.session.delete(base_path) + self.session.commit() + + def test_add_server(self): + """ Check if server is added to resolv.conf """ + for s in test_servers: + self.session.set(base_path + [s]) + self.session.commit() + + servers = get_name_servers() + for s in servers: + self.assertTrue(s in servers) + + def test_delete_server(self): + """ Test if a deleted server disappears from resolv.conf """ + for s in test_servers: + self.session.delete(base_path + [s]) + self.session.commit() + + servers = get_name_servers() + for s in servers: + self.assertTrue(test_server_1 not in servers) + +if __name__ == '__main__': + unittest.main() + -- cgit v1.2.3 From 6c076df8aca590aa2a7fe9f40361a2afdb139477 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 18 Dec 2019 14:34:34 +0100 Subject: Jenkins: adjust to new Debian Buster build --- Jenkinsfile | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 000000000..3b8daeb12 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,165 @@ +// Copyright (C) 2019 VyOS maintainers and contributors +// +// This program is free software; you can redistribute it and/or modify +// in order to easy exprort images built to "external" world +// it under the terms of the GNU General Public License version 2 or later as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +@NonCPS + +def getGitBranchName() { + def branch = scm.branches[0].name + return branch.split('/')[-1] +} + +def getGitRepoURL() { + return scm.userRemoteConfigs[0].url +} + +def getGitRepoName() { + return getGitRepoURL().split('/').last() +} + +// Returns true if this is a custom build launched on any project fork. +// Returns false if this is build from git@github.com:vyos/. +// can be e.g. vyos-1x.git or vyatta-op.git +def isCustomBuild() { + // GitHub organisation base URL + def gitURI = 'git@github.com:vyos/' + getGitRepoName() + def httpURI = 'https://github.com/vyos/' + getGitRepoName() + + return ! ((getGitRepoURL() == gitURI) || (getGitRepoURL() == httpURI)) +} + +def setDescription() { + def item = Jenkins.instance.getItemByFullName(env.JOB_NAME) + + // build up the main description text + def description = "" + description += "

VyOS individual package build: " + getGitRepoName().replace('.git', '') + "

" + + if (isCustomBuild()) { + description += "

" + description += "Build not started from official Git repository!
" + description += "
" + description += "Repository: " + getGitRepoURL() + "
" + description += "Branch: " + getGitBranchName() + "
" + description += "

" + } else { + description += "Sources taken from Git branch: " + getGitBranchName() + "
" + } + + item.setDescription(description) + item.save() +} + +/* Only keep the 10 most recent builds. */ +def projectProperties = [ + [$class: 'BuildDiscarderProperty',strategy: [$class: 'LogRotator', numToKeepStr: '10']], +] + +properties(projectProperties) +setDescription() + +pipeline { + agent { + docker { + args '--sysctl net.ipv6.conf.lo.disable_ipv6=0 -e GOSU_UID=1006 -e GOSU_GID=1006' + image 'vyos/vyos-build:current' + alwaysPull true + } + } + options { + disableConcurrentBuilds() + skipDefaultCheckout() + timeout(time: 30, unit: 'MINUTES') + timestamps() + } + stages { + stage('Fetch') { + steps { + script { + dir('build') { + git branch: getGitBranchName(), + url: getGitRepoURL() + } + } + } + } + stage('Build') { + steps { + script { + dir('build') { + def commitId = sh(returnStdout: true, script: 'git rev-parse --short=11 HEAD').trim() + currentBuild.description = sprintf('Git SHA1: %s', commitId[-11..-1]) + + sh 'dpkg-buildpackage -b -us -uc -tc' + } + } + } + } + } + post { + cleanup { + deleteDir() + } + success { + script { + // archive *.deb artifact on custom builds, deploy to repo otherwise + if ( isCustomBuild()) { + archiveArtifacts artifacts: '*.deb', fingerprint: true + } else { + // publish build result, using SSH-dev.packages.vyos.net Jenkins Credentials + sshagent(['SSH-dev.packages.vyos.net']) { + // build up some fancy groovy variables so we do not need to write/copy + // every option over and over again! + + def VYOS_REPO_PATH = '/home/sentrium/web/dev.packages.vyos.net/public_html/repositories/' + getGitBranchName() + '/' + def SSH_OPTS = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR' + def SSH_REMOTE = 'khagen@10.217.48.113' + + echo "Uploading package(s) and updating package(s) in the repository ..." + + files = findFiles(glob: '*.deb') + files.each { PACKAGE -> + def RELEASE = getGitBranchName() + def ARCH = sh(returnStdout: true, script: "dpkg-deb -f ${PACKAGE} Architecture").trim() + def SUBSTRING = sh(returnStdout: true, script: "dpkg-deb -f ${PACKAGE} Package").trim() + def SSH_DIR = '~/VyOS/' + RELEASE + '/' + ARCH + def ARCH_OPT = '' + if (ARCH != 'all') + ARCH_OPT = '-A ' + ARCH + + // No need to explicitly check the return code. The pipeline + // will fail if sh returns a non 0 exit code + sh """ + ssh ${SSH_OPTS} ${SSH_REMOTE} -t "bash --login -c 'mkdir -p ${SSH_DIR}'" + """ + sh """ + scp ${SSH_OPTS} ${PACKAGE} ${SSH_REMOTE}:${SSH_DIR}/ + """ + sh """ + ssh ${SSH_OPTS} ${SSH_REMOTE} -t "uncron-add 'reprepro -v -b ${VYOS_REPO_PATH} ${ARCH_OPT} remove ${RELEASE} ${SUBSTRING}'" + """ + sh """ + ssh ${SSH_OPTS} ${SSH_REMOTE} -t "uncron-add 'reprepro -v -b ${VYOS_REPO_PATH} deleteunreferenced'" + """ + sh """ + ssh ${SSH_OPTS} ${SSH_REMOTE} -t "uncron-add 'reprepro -v -b ${VYOS_REPO_PATH} ${ARCH_OPT} includedeb ${RELEASE} ${SSH_DIR}/${PACKAGE}'" + """ + } + } + } + } + } + } +} + -- cgit v1.2.3 From a17d72be46fe80f036058f044085e15b76740de2 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 18 Dec 2019 14:42:01 +0100 Subject: Jenkins: add exception for master branch to deploy path --- Jenkinsfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 3b8daeb12..63a271bc1 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -121,8 +121,12 @@ pipeline { sshagent(['SSH-dev.packages.vyos.net']) { // build up some fancy groovy variables so we do not need to write/copy // every option over and over again! + def RELEASE = getGitBranchName() + if (getGitBranchName() == "master") { + RELEASE = 'current' + } - def VYOS_REPO_PATH = '/home/sentrium/web/dev.packages.vyos.net/public_html/repositories/' + getGitBranchName() + '/' + def VYOS_REPO_PATH = '/home/sentrium/web/dev.packages.vyos.net/public_html/repositories/' + RELEASE + '/' def SSH_OPTS = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR' def SSH_REMOTE = 'khagen@10.217.48.113' @@ -130,7 +134,6 @@ pipeline { files = findFiles(glob: '*.deb') files.each { PACKAGE -> - def RELEASE = getGitBranchName() def ARCH = sh(returnStdout: true, script: "dpkg-deb -f ${PACKAGE} Architecture").trim() def SUBSTRING = sh(returnStdout: true, script: "dpkg-deb -f ${PACKAGE} Package").trim() def SSH_DIR = '~/VyOS/' + RELEASE + '/' + ARCH -- cgit v1.2.3 From 4f42b4f7411dd4ca4e670a47be1dfe7f81d02e05 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 28 Dec 2019 00:22:13 +0100 Subject: Search testcases and execute automatically --- bin/vyos-smoketest | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/bin/vyos-smoketest b/bin/vyos-smoketest index 1ae00d5b8..3c54b8780 100755 --- a/bin/vyos-smoketest +++ b/bin/vyos-smoketest @@ -1,19 +1,38 @@ #!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . import os import sys -test_dir = '/usr/libexec/vyos/tests/smoke' - -tests = ['test_module_load.py'] +from stat import * success = True +for root, dirs, files in os.walk('/usr/libexec/vyos/tests/smoke'): + for name in files: + test_file = os.path.join(root, name) + mode = os.stat(test_file).st_mode + + if mode & S_IXOTH: + try: + os.system(test_file) + except Exception as e: + print('Testcase "{}" raised an exception'.format(test_file)) + success = False -for t in tests: - try: - os.system(os.path.join(test_dir, t)) - except Exception as e: - success = False +if success: + sys.exit(0) -if not success: - sys.exit(1) +sys.exit(1) -- cgit v1.2.3 From ae2c359c2938466001359823d4b2a97bd360a889 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 28 Dec 2019 09:43:50 +0100 Subject: Debian: install binary to /usr/bin --- debian/rules | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/debian/rules b/debian/rules index 4ccc23e86..526fb8537 100755 --- a/debian/rules +++ b/debian/rules @@ -1,7 +1,6 @@ #!/usr/bin/make -f DIR := debian/vyos-smoketest -VYOS_SBIN_DIR := usr/sbin/ VYOS_BIN_DIR := usr/bin/ VYOS_LIBEXEC_DIR := usr/libexec/vyos VYOS_DATA_DIR := /usr/share/vyos @@ -10,8 +9,6 @@ VYOS_OP_TMPL_DIR := /opt/vyatta/share/vyatta-op/templates MIGRATION_SCRIPTS_DIR := /opt/vyatta/etc/config-migrate/migrate/ -SBINDIR := $(DIR)/usr/sbin - %: dh $@ --with python3, --with quilt @@ -24,5 +21,5 @@ override_dh_auto_install: cp -r scripts/* $(DIR)/$(VYOS_LIBEXEC_DIR)/tests/smoke # Install system programs - mkdir -p $(SBINDIR) - cp -r bin/* $(SBINDIR) + mkdir -p $(DIR)/$(VYOS_BIN_DIR) + cp -r bin/* $(DIR)/$(VYOS_BIN_DIR) -- cgit v1.2.3 From 1553a4f693729b1ecbd38b3256fc05ac456092b2 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 28 Dec 2019 09:43:58 +0100 Subject: Jenkins: make pipeline branch independent --- Jenkinsfile | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 63a271bc1..ed98477f2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -69,11 +69,24 @@ def projectProperties = [ properties(projectProperties) setDescription() +node('Docker') { + stage('Define Agent') { + script { + // create container name on demand + def branchName = getGitBranchName() + if (branchName == "master") { + branchName = "current" + } + env.DOCKER_IMAGE = "vyos/vyos-build:" + branchName + } + } +} + pipeline { agent { docker { - args '--sysctl net.ipv6.conf.lo.disable_ipv6=0 -e GOSU_UID=1006 -e GOSU_GID=1006' - image 'vyos/vyos-build:current' + args "--sysctl net.ipv6.conf.lo.disable_ipv6=0 -e GOSU_UID=1006 -e GOSU_GID=1006" + image "${env.DOCKER_IMAGE}" alwaysPull true } } @@ -127,6 +140,9 @@ pipeline { } def VYOS_REPO_PATH = '/home/sentrium/web/dev.packages.vyos.net/public_html/repositories/' + RELEASE + '/' + if (getGitBranchName() == "crux") + VYOS_REPO_PATH += 'vyos/' + def SSH_OPTS = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR' def SSH_REMOTE = 'khagen@10.217.48.113' -- cgit v1.2.3 From e8e0e502cee05dc1335ae7d1cc693270e8a5292a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 21 Jan 2020 14:19:10 +0100 Subject: nameserver: add missing shebang (#!) --- scripts/cli/test_system_nameserver.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/cli/test_system_nameserver.py b/scripts/cli/test_system_nameserver.py index 591680c63..80c6cb454 100644 --- a/scripts/cli/test_system_nameserver.py +++ b/scripts/cli/test_system_nameserver.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import os import re import unittest -- cgit v1.2.3 From a985907d54ecada217e85ca23e002790bf6591e3 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 21 Jan 2020 14:19:34 +0100 Subject: nameserver: add GPL2 license --- scripts/cli/test_system_nameserver.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/scripts/cli/test_system_nameserver.py b/scripts/cli/test_system_nameserver.py index 80c6cb454..cab867983 100644 --- a/scripts/cli/test_system_nameserver.py +++ b/scripts/cli/test_system_nameserver.py @@ -1,4 +1,18 @@ #!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . import os import re -- cgit v1.2.3 From 47c8f35dd476d2730aad3990e63240af1c7027cf Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 21 Jan 2020 14:20:22 +0100 Subject: nameserver: enable test --- scripts/cli/test_system_nameserver.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/cli/test_system_nameserver.py diff --git a/scripts/cli/test_system_nameserver.py b/scripts/cli/test_system_nameserver.py old mode 100644 new mode 100755 -- cgit v1.2.3 From a7cd2bc683ca03ab2787879d3db06e8d5d3fd5ca Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 24 Jan 2020 14:03:45 +0100 Subject: nameserver: fix indent --- scripts/cli/test_system_nameserver.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/cli/test_system_nameserver.py b/scripts/cli/test_system_nameserver.py index cab867983..a07ad31ad 100755 --- a/scripts/cli/test_system_nameserver.py +++ b/scripts/cli/test_system_nameserver.py @@ -25,13 +25,11 @@ import vyos.util as util RESOLV_CONF = '/etc/resolv.conf' test_servers = ['192.0.2.10', '2001:db8:1::100'] - base_path = ['system', 'name-server'] - def get_name_servers(): - resolv_conf = util.read_file(RESOLV_CONF) - return re.findall(r'\n?nameserver\s+(.*)', resolv_conf) + resolv_conf = util.read_file(RESOLV_CONF) + return re.findall(r'\n?nameserver\s+(.*)', resolv_conf) class TestSystemNameServer(unittest.TestCase): def setUp(self): -- cgit v1.2.3 From b55fc6241dc9e83aed74277b1d85e1e5f436b12a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 24 Jan 2020 14:04:12 +0100 Subject: smoketest: inform user about current testcase --- bin/vyos-smoketest | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/vyos-smoketest b/bin/vyos-smoketest index 3c54b8780..6d3442622 100755 --- a/bin/vyos-smoketest +++ b/bin/vyos-smoketest @@ -27,6 +27,7 @@ for root, dirs, files in os.walk('/usr/libexec/vyos/tests/smoke'): if mode & S_IXOTH: try: + print('Running Testcase: ' + test_file) os.system(test_file) except Exception as e: print('Testcase "{}" raised an exception'.format(test_file)) -- cgit v1.2.3 From ef2cd3db3faafb209189f14dd3762587e31affe9 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 24 Jan 2020 14:04:48 +0100 Subject: bond: very basic test for a bonding interface --- scripts/cli/test_bond.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100755 scripts/cli/test_bond.py diff --git a/scripts/cli/test_bond.py b/scripts/cli/test_bond.py new file mode 100755 index 000000000..fb948ffdf --- /dev/null +++ b/scripts/cli/test_bond.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import unittest +import vyos.config +import vyos.configsession + +from netifaces import ifaddresses, AF_INET, AF_INET6 +from vyos.validate import is_intf_addr_assigned + +base_path = ['interfaces', 'bonding'] +test_addr = ['192.0.2.1/25', '2001:db8:1::ffff/64'] +interfaces = ['bond0'] + +class TestInterfacesBond(unittest.TestCase): + def setUp(self): + self.session = vyos.configsession.ConfigSession(os.getpid()) + env = self.session.get_session_env() + self.config = vyos.config.Config(session_env=env) + + def tearDown(self): + # Delete existing interfaces + self.session.delete(base_path) + self.session.commit() + + def test_add_address(self): + """ Check if address is added to interface """ + for intf in interfaces: + for addr in test_addr: + self.session.set(base_path + [intf, 'address', addr]) + self.session.commit() + + for intf in interfaces: + for af in AF_INET, AF_INET6: + for addr in ifaddresses(intf)[af]: + self.assertTrue(is_intf_addr_assigned(intf, addr['addr'])) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From ebb6bfc751bc65b8a99d7f176c753c938846e257 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 24 Jan 2020 17:22:12 +0100 Subject: kernel: migrate module load test to unittest framework --- scripts/system/test_module_load.py | 55 +++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/scripts/system/test_module_load.py b/scripts/system/test_module_load.py index c96229b92..598ea9882 100755 --- a/scripts/system/test_module_load.py +++ b/scripts/system/test_module_load.py @@ -1,31 +1,42 @@ #!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . -import sys import os +import unittest modules = { - "intel": ["e1000", "e1000e", "igb", "ixgb", "ixgbe", "ixgbevf", "i40e", "i40evf"], - "accel_ppp": ["ipoe"], - "misc": ["wireguard"] + "intel": ["e1000", "e1000e", "igb", "ixgb", "ixgbe", "ixgbevf", "i40e", "i40evf"], + "accel_ppp": ["ipoe", "vlan_mon"], + "misc": ["wireguard"] } -if __name__ == '__main__': - success = True +class TestKernelModules(unittest.TestCase): + def test_load_modules(self): + success = True + for msk in modules: + ms = modules[msk] + for m in ms: + # We want to uncover all modules that fail, + # not fail at the first one + try: + os.system("modprobe {0}".format(m)) + except: + success = False - print("[load modules] Test execution started") - for msk in modules: - ms = modules[msk] - for m in ms: - # We want to uncover all modules that fail, - # not fail at the first one - try: - os.system("modprobe {0}".format(m)) - except Exception as e: - print("[load modules] Test [modprobe {0}] failed: {1}".format(module, e)) - success = False + self.assertTrue(success) - if not success: - print("Test [load modules] failed") - sys.exit(1) - else: - print("[load modules] Test succeeded") +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From b6ad4c9908b03cc9cbb5d1173476984b08b68222 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 25 Jan 2020 11:45:10 +0100 Subject: interface: provide common test class for networking Currently only bonding and bridge interfaces are supported --- scripts/cli/test_bond.py | 53 ----------------------- scripts/cli/test_interfaces.py | 95 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 53 deletions(-) delete mode 100755 scripts/cli/test_bond.py create mode 100755 scripts/cli/test_interfaces.py diff --git a/scripts/cli/test_bond.py b/scripts/cli/test_bond.py deleted file mode 100755 index fb948ffdf..000000000 --- a/scripts/cli/test_bond.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2019-2020 VyOS maintainers and contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 or later as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import os -import unittest -import vyos.config -import vyos.configsession - -from netifaces import ifaddresses, AF_INET, AF_INET6 -from vyos.validate import is_intf_addr_assigned - -base_path = ['interfaces', 'bonding'] -test_addr = ['192.0.2.1/25', '2001:db8:1::ffff/64'] -interfaces = ['bond0'] - -class TestInterfacesBond(unittest.TestCase): - def setUp(self): - self.session = vyos.configsession.ConfigSession(os.getpid()) - env = self.session.get_session_env() - self.config = vyos.config.Config(session_env=env) - - def tearDown(self): - # Delete existing interfaces - self.session.delete(base_path) - self.session.commit() - - def test_add_address(self): - """ Check if address is added to interface """ - for intf in interfaces: - for addr in test_addr: - self.session.set(base_path + [intf, 'address', addr]) - self.session.commit() - - for intf in interfaces: - for af in AF_INET, AF_INET6: - for addr in ifaddresses(intf)[af]: - self.assertTrue(is_intf_addr_assigned(intf, addr['addr'])) - -if __name__ == '__main__': - unittest.main() diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py new file mode 100755 index 000000000..1f96bdfc6 --- /dev/null +++ b/scripts/cli/test_interfaces.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import unittest +import vyos.config +import vyos.configsession + +from netifaces import ifaddresses, AF_INET, AF_INET6 +from vyos.validate import is_intf_addr_assigned, is_ipv6_link_local +from vyos.interfaces import list_interfaces_of_type + +class BasicInterfaceTest: + class BaseTest(unittest.TestCase): + def setUp(self): + self.session = vyos.configsession.ConfigSession(os.getpid()) + env = self.session.get_session_env() + self.config = vyos.config.Config(session_env=env) + self._test_addr = ['192.0.2.1/25', '2001:db8:1::ffff/64'] + + def tearDown(self): + self.session.delete(self._base_path) + self.session.commit() + + def test_add_address(self): + """ Check if address can be added to interface """ + + # Add address + for intf in self._interfaces: + for addr in self._test_addr: + self.session.set(self._base_path + [intf, 'address', addr]) + self.session.commit() + + # Validate address + for intf in self._interfaces: + for af in AF_INET, AF_INET6: + for addr in ifaddresses(intf)[af]: + # checking link local addresses makes no sense + if is_ipv6_link_local(addr['addr']): + continue + + self.assertTrue(is_intf_addr_assigned(intf, addr['addr'])) + + +class BondInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + self._base_path = ['interfaces', 'bonding'] + self._interfaces = ['bond0'] + + def test_add_remove_member(self): + members = [] + # we need to filter out VLAN interfaces identified by a dot (.) + # in their name - just in case! + for tmp in list_interfaces_of_type("ethernet"): + if not '.' in tmp: + members.append(tmp) + + for intf in self._interfaces: + for member in members: + # We can not enslave an interface when there is an address + # assigned - thus we do not allow it in case someone + # runs vyos-smoketest on his production device + self.session.set(self._base_path + [intf, 'member', 'interface', member]) + + self.session.commit() + + for intf in self._interfaces: + self.session.delete(self._base_path + [intf, 'member']) + + self.session.commit() + + +class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + self._base_path = ['interfaces', 'bridge'] + self._interfaces = ['br0'] + + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From ecd4207f5620795356768f4235d0af8c6ab90248 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 25 Jan 2020 11:50:52 +0100 Subject: interface: adjust comments in BondInterfaceTest --- scripts/cli/test_interfaces.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py index 1f96bdfc6..8b1318791 100755 --- a/scripts/cli/test_interfaces.py +++ b/scripts/cli/test_interfaces.py @@ -72,8 +72,8 @@ class BondInterfaceTest(BasicInterfaceTest.BaseTest): for intf in self._interfaces: for member in members: # We can not enslave an interface when there is an address - # assigned - thus we do not allow it in case someone - # runs vyos-smoketest on his production device + # assigned - take care here - or find them dynamically if a user + # runs vyos-smoketest on his production device? self.session.set(self._base_path + [intf, 'member', 'interface', member]) self.session.commit() -- cgit v1.2.3 From c8814cf9692577c6bf963d2cfc4118f9ee1cd32a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 25 Jan 2020 12:01:15 +0100 Subject: interface: add test for bridge member interfaces --- scripts/cli/test_interfaces.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py index 8b1318791..0e7c4dc07 100755 --- a/scripts/cli/test_interfaces.py +++ b/scripts/cli/test_interfaces.py @@ -90,6 +90,23 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): self._base_path = ['interfaces', 'bridge'] self._interfaces = ['br0'] + def test_add_remove_member(self): + members = list_interfaces_of_type("ethernet") + + for intf in self._interfaces: + cost = 1000 + priority = 10 + + self.session.set(self._base_path + [intf, 'stp']) + for member in members: + self.session.set(self._base_path + [intf, 'member', 'interface', member]) + self.session.set(self._base_path + [intf, 'member', 'interface', member, 'cost', str(cost)]) + self.session.set(self._base_path + [intf, 'member', 'interface', member, 'priority', str(priority)]) + cost += 1 + priority += 1 + + self.session.commit() + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 558c6349dc8b851fdf57411196b20765531005eb Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 26 Jan 2020 20:04:35 +0100 Subject: interface: bridge: delete member interfaces int test_add_remove_member() --- scripts/cli/test_interfaces.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py index 0e7c4dc07..fb5c53adc 100755 --- a/scripts/cli/test_interfaces.py +++ b/scripts/cli/test_interfaces.py @@ -104,7 +104,10 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): self.session.set(self._base_path + [intf, 'member', 'interface', member, 'priority', str(priority)]) cost += 1 priority += 1 + self.session.commit() + for intf in self._interfaces: + self.session.delete(self._base_path + [intf, 'member']) self.session.commit() -- cgit v1.2.3 From 4b8ee464d0899ae63ecc398b857eb144c013e4cb Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 1 Feb 2020 19:21:55 +0100 Subject: interface: add test case for interface description --- scripts/cli/test_interfaces.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py index fb5c53adc..5ba01a35c 100755 --- a/scripts/cli/test_interfaces.py +++ b/scripts/cli/test_interfaces.py @@ -35,6 +35,20 @@ class BasicInterfaceTest: self.session.delete(self._base_path) self.session.commit() + def test_add_description(self): + """ Check if description can be added to interface """ + for intf in self._interfaces: + test_string='Description-Test-{}'.format(intf) + self.session.set(self._base_path + [intf, 'description', test_string]) + self.session.commit() + + # Validate interface description + for intf in self._interfaces: + test_string='Description-Test-{}'.format(intf) + with open('/sys/class/net/{}/ifalias'.format(intf), 'r') as f: + tmp = f.read().rstrip() + self.assertTrue(tmp, test_string) + def test_add_address(self): """ Check if address can be added to interface """ -- cgit v1.2.3 From bd85f1adc86b5645808cfc75fd1fef354146cba1 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 1 Feb 2020 19:22:22 +0100 Subject: interface: add test for dummy interface --- scripts/cli/test_interfaces.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py index 5ba01a35c..4f52f83d7 100755 --- a/scripts/cli/test_interfaces.py +++ b/scripts/cli/test_interfaces.py @@ -69,6 +69,13 @@ class BasicInterfaceTest: self.assertTrue(is_intf_addr_assigned(intf, addr['addr'])) +class DummyInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + self._base_path = ['interfaces', 'dummy'] + self._interfaces = ['dum0', 'dum1', 'dum2'] + + class BondInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): super().setUp() -- cgit v1.2.3 From 4bb7dedba86d9bc8fd0613bbabe159a072c16c3e Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 1 Feb 2020 19:22:32 +0100 Subject: interface: add test for loopback interface --- scripts/cli/test_interfaces.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py index 4f52f83d7..6bbacc585 100755 --- a/scripts/cli/test_interfaces.py +++ b/scripts/cli/test_interfaces.py @@ -76,6 +76,13 @@ class DummyInterfaceTest(BasicInterfaceTest.BaseTest): self._interfaces = ['dum0', 'dum1', 'dum2'] +class LoopbackInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + self._base_path = ['interfaces', 'loopback'] + self._interfaces = ['lo'] + + class BondInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): super().setUp() -- cgit v1.2.3 From a8d94f0a16f3473c10ef0922ee2d6d6e9659c87a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 3 Feb 2020 07:40:36 +0100 Subject: snmp: add test for SNMPv2 --- scripts/cli/test_service_snmp.py | 81 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100755 scripts/cli/test_service_snmp.py diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py new file mode 100755 index 000000000..d8521b770 --- /dev/null +++ b/scripts/cli/test_service_snmp.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import re +import unittest + +import vyos.config +import vyos.configsession +import vyos.util as util +from vyos.validate import is_ipv4 + +SNMPD_CONF = '/etc/snmp/snmpd.conf' + +base_path = ['service', 'snmp'] + +def get_config_value(key): + tmp = util.read_file(SNMPD_CONF) + return re.findall(r'\n?{}\s+(.*)'.format(key), tmp) + +class TestSystemNameServer(unittest.TestCase): + def setUp(self): + self.session = vyos.configsession.ConfigSession(os.getpid()) + env = self.session.get_session_env() + self.config = vyos.config.Config(session_env=env) + + def tearDown(self): + # Delete SNNP configuration + self.session.delete(base_path) + self.session.commit() + + def test_snmpv2(self): + """ Check if SNMPv2 can be configured and service runs """ + clients = ['192.0.2.1', '2001:db8::1'] + networks = ['192.0.2.128/25', '2001:db8:babe::/48'] + listen = ['127.0.0.1', '::1'] + + for auth in ['ro', 'rw']: + community = 'VyOS' + auth + self.session.set(base_path + ['community', community, 'authorization', auth]) + for client in clients: + self.session.set(base_path + ['community', community, 'client', client]) + for network in networks: + self.session.set(base_path + ['community', community, 'network', network]) + for addr in listen: + self.session.set(base_path + ['listen-address', addr]) + + self.session.set(base_path + ['contact', 'maintainers@vyos.io']) + self.session.set(base_path + ['location', 'qemu']) + + self.session.commit() + + # verify listen address, it will be returned as + # ['unix:/run/snmpd.socket,udp:127.0.0.1:161,udp6:[::1]:161'] + # thus we need to transfor this into a proper list + config = get_config_value('agentaddress')[0] + expected = 'unix:/run/snmpd.socket' + for addr in listen: + if is_ipv4(addr): + expected += ',udp:{}:161'.format(addr) + else: + expected += ',udp6:[{}]:161'.format(addr) + + self.assertTrue(expected in config) + +if __name__ == '__main__': + unittest.main() + -- cgit v1.2.3 From 594ca265b327ffcacfef57f30bd24939be97bc90 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 4 Feb 2020 18:10:48 +0100 Subject: snmp: ensure snmpd process is running --- scripts/cli/test_service_snmp.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index d8521b770..cca39f7c6 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -18,10 +18,12 @@ import os import re import unittest +from vyos.validate import is_ipv4 +from psutil import process_iter + import vyos.config import vyos.configsession import vyos.util as util -from vyos.validate import is_ipv4 SNMPD_CONF = '/etc/snmp/snmpd.conf' @@ -42,8 +44,8 @@ class TestSystemNameServer(unittest.TestCase): self.session.delete(base_path) self.session.commit() - def test_snmpv2(self): - """ Check if SNMPv2 can be configured and service runs """ + def test_snmp(self): + """ Check if SNMP can be configured and service runs """ clients = ['192.0.2.1', '2001:db8::1'] networks = ['192.0.2.128/25', '2001:db8:babe::/48'] listen = ['127.0.0.1', '::1'] @@ -55,11 +57,12 @@ class TestSystemNameServer(unittest.TestCase): self.session.set(base_path + ['community', community, 'client', client]) for network in networks: self.session.set(base_path + ['community', community, 'network', network]) - for addr in listen: - self.session.set(base_path + ['listen-address', addr]) - self.session.set(base_path + ['contact', 'maintainers@vyos.io']) - self.session.set(base_path + ['location', 'qemu']) + for addr in listen: + self.session.set(base_path + ['listen-address', addr]) + + self.session.set(base_path + ['contact', 'maintainers@vyos.io']) + self.session.set(base_path + ['location', 'qemu']) self.session.commit() @@ -76,6 +79,9 @@ class TestSystemNameServer(unittest.TestCase): self.assertTrue(expected in config) + # Check for running process + self.assertTrue("snmpd" in (p.name() for p in process_iter())) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 70f0d321325f3a7d9966c11c39dfb2ef6ecea97e Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 4 Feb 2020 18:11:16 +0100 Subject: snmp: add testcase for SNMPv3 --- scripts/cli/test_service_snmp.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index cca39f7c6..04db860f6 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -82,6 +82,29 @@ class TestSystemNameServer(unittest.TestCase): # Check for running process self.assertTrue("snmpd" in (p.name() for p in process_iter())) + def test_snmpv3(self): + """ Check if SNMPv3 can be configured and service runs""" + + self.session.set(base_path + ['v3', 'engineid', '0xaffedeadbeef']) + self.session.set(base_path + ['v3', 'group', 'default', 'mode', 'ro']) + # check validate() - a view must be created before this can be comitted + with self.assertRaises(vyos.configsession.ConfigSessionError): + self.session.commit() + + self.session.set(base_path + ['v3', 'view', 'default', 'oid', '1']) + self.session.set(base_path + ['v3', 'group', 'default', 'view', 'default']) + self.session.commit() + + # create user + for authpriv in ['auth', 'privacy']: + self.session.set(base_path + ['v3', 'user', 'vyos', authpriv, 'plaintext-key', 'vyos1234']) + self.session.set(base_path + ['v3', 'user', 'vyos', 'group', 'default']) + + # TODO: read in config file and check values + + # Check for running process + self.assertTrue("snmpd" in (p.name() for p in process_iter())) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From a9eb356dd479330d23e598ac76521cc67356b963 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 5 Feb 2020 22:33:05 +0100 Subject: user: add test for adding/deleting system users --- debian/control | 1 + scripts/cli/test_system_login.py | 80 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100755 scripts/cli/test_system_login.py diff --git a/debian/control b/debian/control index 97f8b27ea..7dde84d3e 100644 --- a/debian/control +++ b/debian/control @@ -9,6 +9,7 @@ Build-Depends: debhelper (>= 9), quilt, python3-lxml, python3-nose, + python3-paramiko, python3-coverage Standards-Version: 3.9.6 diff --git a/scripts/cli/test_system_login.py b/scripts/cli/test_system_login.py new file mode 100755 index 000000000..c804a6117 --- /dev/null +++ b/scripts/cli/test_system_login.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import re +import unittest + +from paramiko import SSHClient, WarningPolicy + +import vyos.config +import vyos.configsession +import vyos.util as util + +base_path = ['system', 'login'] +users = ['vyos1', 'vyos2'] + +class TestSystemLoginServer(unittest.TestCase): + def setUp(self): + self.session = vyos.configsession.ConfigSession(os.getpid()) + env = self.session.get_session_env() + self.config = vyos.config.Config(session_env=env) + + def tearDown(self): + # Delete SNNP configuration + for user in users: + self.session.delete(base_path + ['user', user]) + + self.session.commit() + + def test_user(self): + """ Check if user can be created and we can SSH to localhost """ + + for user in users: + name = "VyOS Roxx " + user + home_dir = "/tmp/" + user + + self.session.set(base_path + ['user', user, 'authentication', 'plaintext-password', user]) + self.session.set(base_path + ['user', user, 'full-name', 'VyOS Roxx']) + self.session.set(base_path + ['user', user, 'home-directory', home_dir]) + + self.session.commit() + + # check if we can login via SSH + for user in users: + # check if homedir has been created + self.assertTrue(os.path.isdir("/tmp/" + user)) + + ssh = SSHClient() + ssh.set_missing_host_key_policy(WarningPolicy) + + try: + ssh.connect('localhost', username=user, password=user) + stdin, stdout, stderr = ssh.exec_command('who') + print(stdout.read().decode()) + except Exception as e: + print(e) + self.assertTrue(False) + + ssh.close() + + # check if homedir has been created + # this can only be done after we have connected via ssh and + # pam_mkhomedir was executes + self.assertTrue(os.path.isdir("/tmp/" + user)) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 6aea18a15f96c733505fc7587ac35e263c165549 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 7 Feb 2020 19:07:35 +0100 Subject: Debian: move python3-paramiko from Build-Depends to Depends Commit a9eb356 ("user: add test for adding/deleting system users") added python3-paramiko to the list of build dependencies, but its a runtime dependency. --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 7dde84d3e..41a0338db 100644 --- a/debian/control +++ b/debian/control @@ -9,13 +9,13 @@ Build-Depends: debhelper (>= 9), quilt, python3-lxml, python3-nose, - python3-paramiko, python3-coverage Standards-Version: 3.9.6 Package: vyos-smoketest Architecture: all Depends: python3, + python3-paramiko, ${python3:Depends}, ${shlibs:Depends}, ${misc:Depends}, -- cgit v1.2.3 From 3d4af18fb0cb257d1466fac417c9f13f080ecd04 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 8 Feb 2020 17:11:40 +0100 Subject: Evaluate exit code when running tests --- bin/vyos-smoketest | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/bin/vyos-smoketest b/bin/vyos-smoketest index 6d3442622..cb039db42 100755 --- a/bin/vyos-smoketest +++ b/bin/vyos-smoketest @@ -15,9 +15,10 @@ # along with this program. If not, see . import os -import sys -from stat import * +from sys import exit +from stat import S_IXOTH +from subprocess import Popen, PIPE success = True for root, dirs, files in os.walk('/usr/libexec/vyos/tests/smoke'): @@ -26,14 +27,16 @@ for root, dirs, files in os.walk('/usr/libexec/vyos/tests/smoke'): mode = os.stat(test_file).st_mode if mode & S_IXOTH: - try: - print('Running Testcase: ' + test_file) - os.system(test_file) - except Exception as e: - print('Testcase "{}" raised an exception'.format(test_file)) + print('Running Testcase: ' + test_file) + process = Popen([test_file], stdout=PIPE) + (output, err) = process.communicate() + exit_code = process.wait() + # We do not want an instant fail - other tests should be run, too + if exit_code != 0: success = False if success: - sys.exit(0) + exit(0) -sys.exit(1) +print("ERROR: One or more tests failed!") +exit(1) -- cgit v1.2.3 From 189b724dd7e5f4a5be4137809376127298bf9d25 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 13:00:07 +0100 Subject: login: remove ssh test --- debian/control | 1 - scripts/cli/test_system_login.py | 25 ------------------------- 2 files changed, 26 deletions(-) diff --git a/debian/control b/debian/control index 41a0338db..97f8b27ea 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,6 @@ Standards-Version: 3.9.6 Package: vyos-smoketest Architecture: all Depends: python3, - python3-paramiko, ${python3:Depends}, ${shlibs:Depends}, ${misc:Depends}, diff --git a/scripts/cli/test_system_login.py b/scripts/cli/test_system_login.py index c804a6117..b14b52603 100755 --- a/scripts/cli/test_system_login.py +++ b/scripts/cli/test_system_login.py @@ -18,8 +18,6 @@ import os import re import unittest -from paramiko import SSHClient, WarningPolicy - import vyos.config import vyos.configsession import vyos.util as util @@ -53,28 +51,5 @@ class TestSystemLoginServer(unittest.TestCase): self.session.commit() - # check if we can login via SSH - for user in users: - # check if homedir has been created - self.assertTrue(os.path.isdir("/tmp/" + user)) - - ssh = SSHClient() - ssh.set_missing_host_key_policy(WarningPolicy) - - try: - ssh.connect('localhost', username=user, password=user) - stdin, stdout, stderr = ssh.exec_command('who') - print(stdout.read().decode()) - except Exception as e: - print(e) - self.assertTrue(False) - - ssh.close() - - # check if homedir has been created - # this can only be done after we have connected via ssh and - # pam_mkhomedir was executes - self.assertTrue(os.path.isdir("/tmp/" + user)) - if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 6c2a6e0153ea36e5690661f0dec634322352f21a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 13:02:18 +0100 Subject: all: do not import entire module, use "from foo import" instead --- scripts/cli/test_interfaces.py | 9 +++++---- scripts/cli/test_service_snmp.py | 16 +++++++++------- scripts/cli/test_system_login.py | 11 ++++++----- scripts/cli/test_system_nameserver.py | 8 ++++---- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py index 6bbacc585..ad8e653ce 100755 --- a/scripts/cli/test_interfaces.py +++ b/scripts/cli/test_interfaces.py @@ -16,9 +16,9 @@ import os import unittest -import vyos.config -import vyos.configsession +from vyos.config import Config +from vyos.configsession import ConfigSession, ConfigSessionError from netifaces import ifaddresses, AF_INET, AF_INET6 from vyos.validate import is_intf_addr_assigned, is_ipv6_link_local from vyos.interfaces import list_interfaces_of_type @@ -26,9 +26,9 @@ from vyos.interfaces import list_interfaces_of_type class BasicInterfaceTest: class BaseTest(unittest.TestCase): def setUp(self): - self.session = vyos.configsession.ConfigSession(os.getpid()) + self.session = ConfigSession(os.getpid()) env = self.session.get_session_env() - self.config = vyos.config.Config(session_env=env) + self.config = Config(session_env=env) self._test_addr = ['192.0.2.1/25', '2001:db8:1::ffff/64'] def tearDown(self): @@ -136,6 +136,7 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): for intf in self._interfaces: self.session.delete(self._base_path + [intf, 'member']) + self.session.commit() diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index 04db860f6..5fd5eafcc 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -21,29 +21,30 @@ import unittest from vyos.validate import is_ipv4 from psutil import process_iter -import vyos.config -import vyos.configsession +from vyos.config import Config +from vyos.configsession import ConfigSession, ConfigSessionError import vyos.util as util SNMPD_CONF = '/etc/snmp/snmpd.conf' - base_path = ['service', 'snmp'] def get_config_value(key): tmp = util.read_file(SNMPD_CONF) return re.findall(r'\n?{}\s+(.*)'.format(key), tmp) -class TestSystemNameServer(unittest.TestCase): +class TestSNMPService(unittest.TestCase): def setUp(self): - self.session = vyos.configsession.ConfigSession(os.getpid()) + self.session = ConfigSession(os.getpid()) env = self.session.get_session_env() - self.config = vyos.config.Config(session_env=env) + self.config = Config(session_env=env) def tearDown(self): # Delete SNNP configuration self.session.delete(base_path) self.session.commit() + del self.session + def test_snmp(self): """ Check if SNMP can be configured and service runs """ clients = ['192.0.2.1', '2001:db8::1'] @@ -82,13 +83,14 @@ class TestSystemNameServer(unittest.TestCase): # Check for running process self.assertTrue("snmpd" in (p.name() for p in process_iter())) + def test_snmpv3(self): """ Check if SNMPv3 can be configured and service runs""" self.session.set(base_path + ['v3', 'engineid', '0xaffedeadbeef']) self.session.set(base_path + ['v3', 'group', 'default', 'mode', 'ro']) # check validate() - a view must be created before this can be comitted - with self.assertRaises(vyos.configsession.ConfigSessionError): + with self.assertRaises(ConfigSessionError): self.session.commit() self.session.set(base_path + ['v3', 'view', 'default', 'oid', '1']) diff --git a/scripts/cli/test_system_login.py b/scripts/cli/test_system_login.py index b14b52603..aa26b3bec 100755 --- a/scripts/cli/test_system_login.py +++ b/scripts/cli/test_system_login.py @@ -18,18 +18,18 @@ import os import re import unittest -import vyos.config -import vyos.configsession +from vyos.config import Config +from vyos.configsession import ConfigSession, ConfigSessionError import vyos.util as util base_path = ['system', 'login'] users = ['vyos1', 'vyos2'] -class TestSystemLoginServer(unittest.TestCase): +class TestSystemLogin(unittest.TestCase): def setUp(self): - self.session = vyos.configsession.ConfigSession(os.getpid()) + self.session = ConfigSession(os.getpid()) env = self.session.get_session_env() - self.config = vyos.config.Config(session_env=env) + self.config = Config(session_env=env) def tearDown(self): # Delete SNNP configuration @@ -40,6 +40,7 @@ class TestSystemLoginServer(unittest.TestCase): def test_user(self): """ Check if user can be created and we can SSH to localhost """ + self.session.set(['service', 'ssh', 'port', '22']) for user in users: name = "VyOS Roxx " + user diff --git a/scripts/cli/test_system_nameserver.py b/scripts/cli/test_system_nameserver.py index a07ad31ad..eba8acd80 100755 --- a/scripts/cli/test_system_nameserver.py +++ b/scripts/cli/test_system_nameserver.py @@ -18,8 +18,8 @@ import os import re import unittest -import vyos.config -import vyos.configsession +from vyos.config import Config +from vyos.configsession import ConfigSession, ConfigSessionError import vyos.util as util RESOLV_CONF = '/etc/resolv.conf' @@ -33,9 +33,9 @@ def get_name_servers(): class TestSystemNameServer(unittest.TestCase): def setUp(self): - self.session = vyos.configsession.ConfigSession(os.getpid()) + self.session = ConfigSession(os.getpid()) env = self.session.get_session_env() - self.config = vyos.config.Config(session_env=env) + self.config = Config(session_env=env) # Delete existing name servers self.session.delete(base_path) -- cgit v1.2.3 From c033c77b487caeb9505217232add571f362f7afe Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 13:02:40 +0100 Subject: all: delete session in tearDown() --- scripts/cli/test_interfaces.py | 2 ++ scripts/cli/test_system_login.py | 1 + scripts/cli/test_system_nameserver.py | 3 +++ 3 files changed, 6 insertions(+) diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py index ad8e653ce..1b775e1fe 100755 --- a/scripts/cli/test_interfaces.py +++ b/scripts/cli/test_interfaces.py @@ -35,6 +35,8 @@ class BasicInterfaceTest: self.session.delete(self._base_path) self.session.commit() + del self.session + def test_add_description(self): """ Check if description can be added to interface """ for intf in self._interfaces: diff --git a/scripts/cli/test_system_login.py b/scripts/cli/test_system_login.py index aa26b3bec..88e5695e7 100755 --- a/scripts/cli/test_system_login.py +++ b/scripts/cli/test_system_login.py @@ -37,6 +37,7 @@ class TestSystemLogin(unittest.TestCase): self.session.delete(base_path + ['user', user]) self.session.commit() + del self.session def test_user(self): """ Check if user can be created and we can SSH to localhost """ diff --git a/scripts/cli/test_system_nameserver.py b/scripts/cli/test_system_nameserver.py index eba8acd80..07fc9494b 100755 --- a/scripts/cli/test_system_nameserver.py +++ b/scripts/cli/test_system_nameserver.py @@ -37,10 +37,13 @@ class TestSystemNameServer(unittest.TestCase): env = self.session.get_session_env() self.config = Config(session_env=env) + def tearDown(self): # Delete existing name servers self.session.delete(base_path) self.session.commit() + del self.session + def test_add_server(self): """ Check if server is added to resolv.conf """ for s in test_servers: -- cgit v1.2.3 From bcc0b5bd6e11a9fbc2fcb3c450fdb48bb85499e8 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 14:54:42 +0100 Subject: snmp: output expected value on error --- scripts/cli/test_service_snmp.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index 5fd5eafcc..e9d04a1ae 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -78,7 +78,11 @@ class TestSNMPService(unittest.TestCase): else: expected += ',udp6:[{}]:161'.format(addr) - self.assertTrue(expected in config) + try: + self.assertTrue(expected in config) + except: + print("expected: {}".format(expected)) + print("config: {}".format(config)) # Check for running process self.assertTrue("snmpd" in (p.name() for p in process_iter())) -- cgit v1.2.3 From 1b96bcb56ffbf3b6161eb95383ac6726be0281c1 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 15:39:26 +0100 Subject: login: check if our newly created users can login to the system --- scripts/cli/test_system_login.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/cli/test_system_login.py b/scripts/cli/test_system_login.py index 88e5695e7..9e95a445d 100755 --- a/scripts/cli/test_system_login.py +++ b/scripts/cli/test_system_login.py @@ -18,6 +18,7 @@ import os import re import unittest +from subprocess import Popen, PIPE from vyos.config import Config from vyos.configsession import ConfigSession, ConfigSessionError import vyos.util as util @@ -53,5 +54,17 @@ class TestSystemLogin(unittest.TestCase): self.session.commit() + for user in users: + cmd = ['su','-', user] + proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) + tmp = "{}\nuname -a".format(user) + proc.stdin.write(tmp.encode()) + proc.stdin.flush() + (stdout, stderr) = proc.communicate() + + # stdout is something like this: + # b'Linux vyos 4.19.101-amd64-vyos #1 SMP Sun Feb 2 10:18:07 UTC 2020 x86_64 GNU/Linux\n' + self.assertTrue(len(stdout) > 40) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 0ffc1fa39944a202dc8cfd1a77a2493e59c84755 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 15:45:59 +0100 Subject: ssh: basic test to see if SSH server launches --- scripts/cli/test_service_ssh.py | 47 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100755 scripts/cli/test_service_ssh.py diff --git a/scripts/cli/test_service_ssh.py b/scripts/cli/test_service_ssh.py new file mode 100755 index 000000000..b5247d77a --- /dev/null +++ b/scripts/cli/test_service_ssh.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import unittest + +from psutil import process_iter +from vyos.config import Config +from vyos.configsession import ConfigSession, ConfigSessionError + +base_path = ['service', 'ssh'] + +class TestServiceSSH(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + env = self.session.get_session_env() + self.config = Config(session_env=env) + + def tearDown(self): + # Delete SSH configuration + self.session.delete(base_path) + self.session.commit() + + del self.session + + def test_ssh(self): + """ Check if SSH service can be configured and runs """ + self.session.set(base_path) + + # Check for running process + self.assertTrue("sshd" in (p.name() for p in process_iter())) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 3f739f8e55f80948aebebf1f89f0ef49b0c14447 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 15:46:22 +0100 Subject: snmp: only import read_file from vyos.util --- scripts/cli/test_service_snmp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index e9d04a1ae..72f338e31 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -23,13 +23,13 @@ from psutil import process_iter from vyos.config import Config from vyos.configsession import ConfigSession, ConfigSessionError -import vyos.util as util +from vyos.util import read_file SNMPD_CONF = '/etc/snmp/snmpd.conf' base_path = ['service', 'snmp'] def get_config_value(key): - tmp = util.read_file(SNMPD_CONF) + tmp = read_file(SNMPD_CONF) return re.findall(r'\n?{}\s+(.*)'.format(key), tmp) class TestSNMPService(unittest.TestCase): -- cgit v1.2.3 From c63bf6ea07009a60fe2d00c5ca2c2264710200a7 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 15:46:46 +0100 Subject: login: fix typo in tearDown() --- scripts/cli/test_system_login.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cli/test_system_login.py b/scripts/cli/test_system_login.py index 9e95a445d..4abbcaf20 100755 --- a/scripts/cli/test_system_login.py +++ b/scripts/cli/test_system_login.py @@ -33,7 +33,7 @@ class TestSystemLogin(unittest.TestCase): self.config = Config(session_env=env) def tearDown(self): - # Delete SNNP configuration + # Delete individual users from configuration for user in users: self.session.delete(base_path + ['user', user]) -- cgit v1.2.3 From 86c87d5110d9ad602a91f887da3fa50d024fd7aa Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 18:42:39 +0100 Subject: ssh: add missing commit() --- scripts/cli/test_service_ssh.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/cli/test_service_ssh.py b/scripts/cli/test_service_ssh.py index b5247d77a..e272872ea 100755 --- a/scripts/cli/test_service_ssh.py +++ b/scripts/cli/test_service_ssh.py @@ -40,6 +40,9 @@ class TestServiceSSH(unittest.TestCase): """ Check if SSH service can be configured and runs """ self.session.set(base_path) + # commit changes + self.session.commit() + # Check for running process self.assertTrue("sshd" in (p.name() for p in process_iter())) -- cgit v1.2.3 From 50315abd38be71554a2daf18f8c3c23bf8690bcf Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 9 Feb 2020 18:43:08 +0100 Subject: ssh: add test for proper port and host validation --- scripts/cli/test_service_ssh.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/scripts/cli/test_service_ssh.py b/scripts/cli/test_service_ssh.py index e272872ea..f0ad2e565 100755 --- a/scripts/cli/test_service_ssh.py +++ b/scripts/cli/test_service_ssh.py @@ -14,15 +14,23 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import re import os import unittest from psutil import process_iter from vyos.config import Config from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.util import read_file +SSHD_CONF = '/etc/ssh/sshd_config' base_path = ['service', 'ssh'] +def get_config_value(key): + tmp = read_file(SSHD_CONF) + return re.findall(r'\n?{}\s+(.*)'.format(key), tmp) + + class TestServiceSSH(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) @@ -38,11 +46,20 @@ class TestServiceSSH(unittest.TestCase): def test_ssh(self): """ Check if SSH service can be configured and runs """ - self.session.set(base_path) + self.session.set(base_path + ['port', '2222']) + self.session.set(base_path + ['disable-host-validation']) # commit changes self.session.commit() + # Check configured port + port = get_config_value('Port')[0] + self.assertTrue("2222" in port) + + # Check DNS usage + dns = get_config_value('UseDNS')[0] + self.assertTrue("no" in dns) + # Check for running process self.assertTrue("sshd" in (p.name() for p in process_iter())) -- cgit v1.2.3 From d9af64aa0af6ba1e42fc0afd5cad10b1853e8a43 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 10 Feb 2020 19:14:05 +0100 Subject: Revert "snmp: output expected value on error" This reverts commit bcc0b5bd6e11a9fbc2fcb3c450fdb48bb85499e8. --- scripts/cli/test_service_snmp.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index 72f338e31..2f918c929 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -78,11 +78,7 @@ class TestSNMPService(unittest.TestCase): else: expected += ',udp6:[{}]:161'.format(addr) - try: - self.assertTrue(expected in config) - except: - print("expected: {}".format(expected)) - print("config: {}".format(config)) + self.assertTrue(expected in config) # Check for running process self.assertTrue("snmpd" in (p.name() for p in process_iter())) -- cgit v1.2.3 From 8a871793c54dc45bd85fdb1b98f51bbfad3a25a2 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 15 Feb 2020 20:03:46 +0100 Subject: interface: bond: remove useless for loop on member removal --- scripts/cli/test_interfaces.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py index 1b775e1fe..712a150c6 100755 --- a/scripts/cli/test_interfaces.py +++ b/scripts/cli/test_interfaces.py @@ -108,9 +108,9 @@ class BondInterfaceTest(BasicInterfaceTest.BaseTest): self.session.commit() - for intf in self._interfaces: - self.session.delete(self._base_path + [intf, 'member']) + # check if member deletion works as expected + self.session.delete(self._base_path + [intf, 'member']) self.session.commit() -- cgit v1.2.3 From 42bc2005d32ac5c0fcd1ce3d2d7327e830d0dfb8 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 15 Feb 2020 20:04:15 +0100 Subject: interface: bond: check that only real interfaces can be enslaved --- scripts/cli/test_interfaces.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py index 712a150c6..4e6617319 100755 --- a/scripts/cli/test_interfaces.py +++ b/scripts/cli/test_interfaces.py @@ -108,6 +108,10 @@ class BondInterfaceTest(BasicInterfaceTest.BaseTest): self.session.commit() + # check validate() - we can only add existing interfaces + self.session.set(self._base_path + [intf, 'member', 'interface', 'eth99']) + with self.assertRaises(ConfigSessionError): + self.session.commit() # check if member deletion works as expected self.session.delete(self._base_path + [intf, 'member']) -- cgit v1.2.3 From 5014e35efc13d762ef12e7934ba59374751c487c Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 16 Feb 2020 13:16:56 +0100 Subject: ddns: add initial unittest --- scripts/cli/test_service_dns_dynamic.py | 109 ++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100755 scripts/cli/test_service_dns_dynamic.py diff --git a/scripts/cli/test_service_dns_dynamic.py b/scripts/cli/test_service_dns_dynamic.py new file mode 100755 index 000000000..2b65b38c7 --- /dev/null +++ b/scripts/cli/test_service_dns_dynamic.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import re +import os +import unittest + +from psutil import process_iter +from vyos.config import Config +from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.util import read_file + +DDCLIENT_CONF = '/etc/ddclient/ddclient.conf' +base_path = ['service', 'dns', 'dynamic'] + +def get_config_value(key): + tmp = read_file(DDCLIENT_CONF) + return re.findall(r'\n?{}\s+(.*)'.format(key), tmp) + + +class TestServiceDDNS(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + env = self.session.get_session_env() + self.config = Config(session_env=env) + + def tearDown(self): + # Delete DDNS configuration + self.session.delete(base_path) + self.session.commit() + + del self.session + + def test_service(self): + """ Check individual DDNS service providers """ + ddns = ['interface', 'eth0', 'service'] + services = ['cloudflare'] + + for service in services: + self.session.set(base_path + ddns + [service, 'host-name', 'test.ddns.vyos.io']) + self.session.set(base_path + ddns + [service, 'login', 'vyos_user']) + self.session.set(base_path + ddns + [service, 'password', 'vyos_pass']) + + # commit changes + self.session.commit() + + # TODO: inspect generated configuration file + + # Check for running process + # process name changes dynamically "ddclient - sleeping for 270 seconds" + # thus we need a different approach + running = False + for p in process_iter(): + if "ddclient" in p.name(): + running = True + self.assertTrue(running) + + + def test_rfc2136(self): + """ Check if DDNS service can be configured and runs """ + ddns = ['interface', 'eth0', 'rfc2136', 'vyos'] + ddns_key_file = '/config/auth/my.key' + + self.session.set(base_path + ddns + ['key', ddns_key_file]) + self.session.set(base_path + ddns + ['record', 'test.ddns.vyos.io']) + self.session.set(base_path + ddns + ['server', 'ns1.vyos.io']) + self.session.set(base_path + ddns + ['ttl', '300']) + self.session.set(base_path + ddns + ['zone', 'vyos.io']) + + # ensure an exception will be raised as no key is present + if os.path.exists(ddns_key_file): + os.unlink(ddns_key_file) + + # check validate() - the key file does not exist yet + with self.assertRaises(ConfigSessionError): + self.session.commit() + + with open(ddns_key_file, 'w') as f: + f.write('S3cretKey') + + # commit changes + self.session.commit() + + # TODO: inspect generated configuration file + + # Check for running process + # process name changes dynamically "ddclient - sleeping for 270 seconds" + # thus we need a different approach + running = False + for p in process_iter(): + if "ddclient" in p.name(): + running = True + self.assertTrue(running) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From b612fb0a8e6afa94b2fb239335c8f41724689172 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 16 Feb 2020 20:36:12 +0100 Subject: ddns: read back configuration file and check plausibility --- scripts/cli/test_service_dns_dynamic.py | 87 +++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/scripts/cli/test_service_dns_dynamic.py b/scripts/cli/test_service_dns_dynamic.py index 2b65b38c7..21d52be18 100755 --- a/scripts/cli/test_service_dns_dynamic.py +++ b/scripts/cli/test_service_dns_dynamic.py @@ -18,6 +18,7 @@ import re import os import unittest +from getpass import getuser from psutil import process_iter from vyos.config import Config from vyos.configsession import ConfigSession, ConfigSessionError @@ -28,8 +29,20 @@ base_path = ['service', 'dns', 'dynamic'] def get_config_value(key): tmp = read_file(DDCLIENT_CONF) - return re.findall(r'\n?{}\s+(.*)'.format(key), tmp) - + tmp = re.findall(r'\n?{}=+(.*)'.format(key), tmp) + tmp = tmp[0].rstrip(',') + return tmp + +def check_process(): + """ + Check for running process, process name changes dynamically e.g. + "ddclient - sleeping for 270 seconds", thus we need a different approach + """ + running = False + for p in process_iter(): + if "ddclient" in p.name(): + running = True + return running class TestServiceDDNS(unittest.TestCase): def setUp(self): @@ -47,26 +60,54 @@ class TestServiceDDNS(unittest.TestCase): def test_service(self): """ Check individual DDNS service providers """ ddns = ['interface', 'eth0', 'service'] - services = ['cloudflare'] + services = ['cloudflare', 'afraid', 'dyndns', 'zoneedit'] for service in services: + user = 'vyos_user' + password = 'vyos_pass' + zone = 'vyos.io' + self.session.delete(base_path) self.session.set(base_path + ddns + [service, 'host-name', 'test.ddns.vyos.io']) - self.session.set(base_path + ddns + [service, 'login', 'vyos_user']) - self.session.set(base_path + ddns + [service, 'password', 'vyos_pass']) - - # commit changes - self.session.commit() - - # TODO: inspect generated configuration file - - # Check for running process - # process name changes dynamically "ddclient - sleeping for 270 seconds" - # thus we need a different approach - running = False - for p in process_iter(): - if "ddclient" in p.name(): - running = True - self.assertTrue(running) + self.session.set(base_path + ddns + [service, 'login', user]) + self.session.set(base_path + ddns + [service, 'password', password]) + self.session.set(base_path + ddns + [service, 'zone', zone]) + + # commit changes + if service == 'cloudflare': + self.session.commit() + else: + # zone option only works on cloudflare, an exception is raised + # for all others + with self.assertRaises(ConfigSessionError): + self.session.commit() + self.session.delete(base_path + ddns + [service, 'zone', 'vyos.io']) + # commit changes again - now it should work + self.session.commit() + + # we can only read the configuration file when we operate as 'root' + if getuser() == 'root': + protocol = get_config_value('protocol') + login = get_config_value('login') + pwd = get_config_value('password') + + # some services need special treatment + protoname = service + if service == 'cloudflare': + tmp = get_config_value('zone') + self.assertTrue(tmp == zone) + elif service == 'afraid': + protoname = 'freedns' + elif service == 'dyndns': + protoname = 'dyndns2' + elif service == 'zoneedit': + protoname = 'zoneedit1' + + self.assertTrue(protocol == protoname) + self.assertTrue(login == user) + self.assertTrue(pwd == "'" + password + "'") + + # Check for running process + self.assertTrue(check_process()) def test_rfc2136(self): @@ -97,13 +138,7 @@ class TestServiceDDNS(unittest.TestCase): # TODO: inspect generated configuration file # Check for running process - # process name changes dynamically "ddclient - sleeping for 270 seconds" - # thus we need a different approach - running = False - for p in process_iter(): - if "ddclient" in p.name(): - running = True - self.assertTrue(running) + self.assertTrue(check_process()) if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 8627392150bb9bc9e0f9f494ff2b0eb88f224e30 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 20:27:36 +0100 Subject: interfaces: split interface tests into individual files --- scripts/cli/base_interfaces_test.py | 76 ++++++++++++++++ scripts/cli/test_interfaces.py | 150 -------------------------------- scripts/cli/test_interfaces_bonding.py | 52 +++++++++++ scripts/cli/test_interfaces_bridge.py | 47 ++++++++++ scripts/cli/test_interfaces_dummy.py | 26 ++++++ scripts/cli/test_interfaces_loopback.py | 26 ++++++ 6 files changed, 227 insertions(+), 150 deletions(-) create mode 100644 scripts/cli/base_interfaces_test.py delete mode 100755 scripts/cli/test_interfaces.py create mode 100755 scripts/cli/test_interfaces_bonding.py create mode 100755 scripts/cli/test_interfaces_bridge.py create mode 100755 scripts/cli/test_interfaces_dummy.py create mode 100755 scripts/cli/test_interfaces_loopback.py diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py new file mode 100644 index 000000000..e6667f993 --- /dev/null +++ b/scripts/cli/base_interfaces_test.py @@ -0,0 +1,76 @@ +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import unittest + +from vyos.config import Config +from vyos.configsession import ConfigSession, ConfigSessionError +from netifaces import ifaddresses, AF_INET, AF_INET6 +from vyos.validate import is_intf_addr_assigned, is_ipv6_link_local +from vyos.interfaces import list_interfaces_of_type + +class BasicInterfaceTest: + class BaseTest(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + env = self.session.get_session_env() + self.config = Config(session_env=env) + + self._test_addr = ['192.0.2.1/25', '2001:db8:1::ffff/64'] + self._test_mtu = False + + def tearDown(self): + self.session.delete(self._base_path) + self.session.commit() + + del self.session + + def test_add_description(self): + """ + Check if description can be added to interface + """ + for intf in self._interfaces: + test_string='Description-Test-{}'.format(intf) + self.session.set(self._base_path + [intf, 'description', test_string]) + self.session.commit() + + # Validate interface description + for intf in self._interfaces: + test_string='Description-Test-{}'.format(intf) + with open('/sys/class/net/{}/ifalias'.format(intf), 'r') as f: + tmp = f.read().rstrip() + self.assertTrue(tmp, test_string) + + def test_add_address(self): + """ + Check if address can be added to interface + """ + + # Add address + for intf in self._interfaces: + for addr in self._test_addr: + self.session.set(self._base_path + [intf, 'address', addr]) + self.session.commit() + + # Validate address + for intf in self._interfaces: + for af in AF_INET, AF_INET6: + for addr in ifaddresses(intf)[af]: + # checking link local addresses makes no sense + if is_ipv6_link_local(addr['addr']): + continue + + self.assertTrue(is_intf_addr_assigned(intf, addr['addr'])) + diff --git a/scripts/cli/test_interfaces.py b/scripts/cli/test_interfaces.py deleted file mode 100755 index 4e6617319..000000000 --- a/scripts/cli/test_interfaces.py +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2019-2020 VyOS maintainers and contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 or later as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import os -import unittest - -from vyos.config import Config -from vyos.configsession import ConfigSession, ConfigSessionError -from netifaces import ifaddresses, AF_INET, AF_INET6 -from vyos.validate import is_intf_addr_assigned, is_ipv6_link_local -from vyos.interfaces import list_interfaces_of_type - -class BasicInterfaceTest: - class BaseTest(unittest.TestCase): - def setUp(self): - self.session = ConfigSession(os.getpid()) - env = self.session.get_session_env() - self.config = Config(session_env=env) - self._test_addr = ['192.0.2.1/25', '2001:db8:1::ffff/64'] - - def tearDown(self): - self.session.delete(self._base_path) - self.session.commit() - - del self.session - - def test_add_description(self): - """ Check if description can be added to interface """ - for intf in self._interfaces: - test_string='Description-Test-{}'.format(intf) - self.session.set(self._base_path + [intf, 'description', test_string]) - self.session.commit() - - # Validate interface description - for intf in self._interfaces: - test_string='Description-Test-{}'.format(intf) - with open('/sys/class/net/{}/ifalias'.format(intf), 'r') as f: - tmp = f.read().rstrip() - self.assertTrue(tmp, test_string) - - def test_add_address(self): - """ Check if address can be added to interface """ - - # Add address - for intf in self._interfaces: - for addr in self._test_addr: - self.session.set(self._base_path + [intf, 'address', addr]) - self.session.commit() - - # Validate address - for intf in self._interfaces: - for af in AF_INET, AF_INET6: - for addr in ifaddresses(intf)[af]: - # checking link local addresses makes no sense - if is_ipv6_link_local(addr['addr']): - continue - - self.assertTrue(is_intf_addr_assigned(intf, addr['addr'])) - - -class DummyInterfaceTest(BasicInterfaceTest.BaseTest): - def setUp(self): - super().setUp() - self._base_path = ['interfaces', 'dummy'] - self._interfaces = ['dum0', 'dum1', 'dum2'] - - -class LoopbackInterfaceTest(BasicInterfaceTest.BaseTest): - def setUp(self): - super().setUp() - self._base_path = ['interfaces', 'loopback'] - self._interfaces = ['lo'] - - -class BondInterfaceTest(BasicInterfaceTest.BaseTest): - def setUp(self): - super().setUp() - self._base_path = ['interfaces', 'bonding'] - self._interfaces = ['bond0'] - - def test_add_remove_member(self): - members = [] - # we need to filter out VLAN interfaces identified by a dot (.) - # in their name - just in case! - for tmp in list_interfaces_of_type("ethernet"): - if not '.' in tmp: - members.append(tmp) - - for intf in self._interfaces: - for member in members: - # We can not enslave an interface when there is an address - # assigned - take care here - or find them dynamically if a user - # runs vyos-smoketest on his production device? - self.session.set(self._base_path + [intf, 'member', 'interface', member]) - - self.session.commit() - - # check validate() - we can only add existing interfaces - self.session.set(self._base_path + [intf, 'member', 'interface', 'eth99']) - with self.assertRaises(ConfigSessionError): - self.session.commit() - - # check if member deletion works as expected - self.session.delete(self._base_path + [intf, 'member']) - self.session.commit() - - -class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): - def setUp(self): - super().setUp() - self._base_path = ['interfaces', 'bridge'] - self._interfaces = ['br0'] - - def test_add_remove_member(self): - members = list_interfaces_of_type("ethernet") - - for intf in self._interfaces: - cost = 1000 - priority = 10 - - self.session.set(self._base_path + [intf, 'stp']) - for member in members: - self.session.set(self._base_path + [intf, 'member', 'interface', member]) - self.session.set(self._base_path + [intf, 'member', 'interface', member, 'cost', str(cost)]) - self.session.set(self._base_path + [intf, 'member', 'interface', member, 'priority', str(priority)]) - cost += 1 - priority += 1 - self.session.commit() - - for intf in self._interfaces: - self.session.delete(self._base_path + [intf, 'member']) - - self.session.commit() - - -if __name__ == '__main__': - unittest.main() diff --git a/scripts/cli/test_interfaces_bonding.py b/scripts/cli/test_interfaces_bonding.py new file mode 100755 index 000000000..7e6523778 --- /dev/null +++ b/scripts/cli/test_interfaces_bonding.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from base_interfaces_test import * + +class BondInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + self._base_path = ['interfaces', 'bonding'] + self._interfaces = ['bond0'] + + def test_add_remove_member(self): + members = [] + # we need to filter out VLAN interfaces identified by a dot (.) + # in their name - just in case! + for tmp in list_interfaces_of_type("ethernet"): + if not '.' in tmp: + members.append(tmp) + + for intf in self._interfaces: + for member in members: + # We can not enslave an interface when there is an address + # assigned - take care here - or find them dynamically if a user + # runs vyos-smoketest on his production device? + self.session.set(self._base_path + [intf, 'member', 'interface', member]) + + self.session.commit() + + # check validate() - we can only add existing interfaces + self.session.set(self._base_path + [intf, 'member', 'interface', 'eth99']) + with self.assertRaises(ConfigSessionError): + self.session.commit() + + # check if member deletion works as expected + self.session.delete(self._base_path + [intf, 'member']) + self.session.commit() + +if __name__ == '__main__': + unittest.main() diff --git a/scripts/cli/test_interfaces_bridge.py b/scripts/cli/test_interfaces_bridge.py new file mode 100755 index 000000000..72e5da65f --- /dev/null +++ b/scripts/cli/test_interfaces_bridge.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from base_interfaces_test import * + +class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + self._base_path = ['interfaces', 'bridge'] + self._interfaces = ['br0'] + + def test_add_remove_member(self): + members = list_interfaces_of_type("ethernet") + + for intf in self._interfaces: + cost = 1000 + priority = 10 + + self.session.set(self._base_path + [intf, 'stp']) + for member in members: + self.session.set(self._base_path + [intf, 'member', 'interface', member]) + self.session.set(self._base_path + [intf, 'member', 'interface', member, 'cost', str(cost)]) + self.session.set(self._base_path + [intf, 'member', 'interface', member, 'priority', str(priority)]) + cost += 1 + priority += 1 + self.session.commit() + + for intf in self._interfaces: + self.session.delete(self._base_path + [intf, 'member']) + + self.session.commit() + +if __name__ == '__main__': + unittest.main() diff --git a/scripts/cli/test_interfaces_dummy.py b/scripts/cli/test_interfaces_dummy.py new file mode 100755 index 000000000..3f0cb8bcc --- /dev/null +++ b/scripts/cli/test_interfaces_dummy.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from base_interfaces_test import * + +class DummyInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + self._base_path = ['interfaces', 'dummy'] + self._interfaces = ['dum0', 'dum1', 'dum2'] + +if __name__ == '__main__': + unittest.main() diff --git a/scripts/cli/test_interfaces_loopback.py b/scripts/cli/test_interfaces_loopback.py new file mode 100755 index 000000000..ceb06aced --- /dev/null +++ b/scripts/cli/test_interfaces_loopback.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from base_interfaces_test import * + +class LoopbackInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + self._base_path = ['interfaces', 'loopback'] + self._interfaces = ['lo'] + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 8077cb1106beb2d2e8eceaa258880198216a2c47 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 20:28:01 +0100 Subject: ethernet: add initial interface test --- scripts/cli/test_interfaces_ethernet.py | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100755 scripts/cli/test_interfaces_ethernet.py diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py new file mode 100755 index 000000000..e070ab98a --- /dev/null +++ b/scripts/cli/test_interfaces_ethernet.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from base_interfaces_test import * +from vyos.interfaces import list_interfaces_of_type + +class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + self._base_path = ['interfaces', 'ethernet'] + self._interfaces = [] + + # auto detect all ethernet interfaces + for interface in list_interfaces_of_type("ethernet"): + if '.' not in interface: + self._interfaces.append(interface) + + + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From f0b4e4ff74cf735488bba985748c448c7202a366 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 20:31:19 +0100 Subject: gitignore: initial version --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..e57e2953a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +debian/.debhelper/ +debian/files +debian/vyos-smoketest.debhelper.log +debian/vyos-smoketest.substvars +debian/vyos-smoketest/ -- cgit v1.2.3 From 175447bfec4cb60068fcea9899b09fcbdd2103ba Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Mon, 17 Feb 2020 19:35:59 +0000 Subject: Makefile: add "make deb" target adding an option to the Makefile to build the debian package --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index c99579b45..e3d0d706c 100644 --- a/Makefile +++ b/Makefile @@ -2,3 +2,6 @@ all: # Install is just xcopy + +deb: + dpkg-buildpackage -uc -us -tc -b -- cgit v1.2.3 From f95c1471f241f2c0a4d0dca5832a1636755ee391 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 20:47:54 +0100 Subject: interfaces: add generic MTU test which can be enabled per interface --- scripts/cli/base_interfaces_test.py | 23 ++++++++++++++++++++++- scripts/cli/test_interfaces_bonding.py | 5 ++++- scripts/cli/test_interfaces_bridge.py | 3 +++ scripts/cli/test_interfaces_ethernet.py | 2 ++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index e6667f993..885995fb8 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -55,7 +55,7 @@ class BasicInterfaceTest: def test_add_address(self): """ - Check if address can be added to interface + Check if IPv4/IPv6 addresses can be added to interface. """ # Add address @@ -74,3 +74,24 @@ class BasicInterfaceTest: self.assertTrue(is_intf_addr_assigned(intf, addr['addr'])) + + def test_change_mtu(self): + """ + Check if MTU can be changed on interface. + Test MTU size will be 1400 bytes. + """ + if self._test_mtu is False: + return None + + # choose a MTU which works on every interface + mtu = '1400' + for intf in self._interfaces: + self.session.set(self._base_path + [intf, 'mtu', mtu]) + + self.session.commit() + + # Validate interface description + for intf in self._interfaces: + with open('/sys/class/net/{}/mtu'.format(intf), 'r') as f: + tmp = f.read().rstrip() + self.assertTrue(tmp == mtu) diff --git a/scripts/cli/test_interfaces_bonding.py b/scripts/cli/test_interfaces_bonding.py index 7e6523778..e1abd7ff1 100755 --- a/scripts/cli/test_interfaces_bonding.py +++ b/scripts/cli/test_interfaces_bonding.py @@ -15,11 +15,14 @@ # along with this program. If not, see . from base_interfaces_test import * +from vyos.interfaces import list_interfaces_of_type -class BondInterfaceTest(BasicInterfaceTest.BaseTest): +class BondingInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): super().setUp() + self._base_path = ['interfaces', 'bonding'] + self._test_mtu = True self._interfaces = ['bond0'] def test_add_remove_member(self): diff --git a/scripts/cli/test_interfaces_bridge.py b/scripts/cli/test_interfaces_bridge.py index 72e5da65f..1d462645e 100755 --- a/scripts/cli/test_interfaces_bridge.py +++ b/scripts/cli/test_interfaces_bridge.py @@ -15,11 +15,14 @@ # along with this program. If not, see . from base_interfaces_test import * +from vyos.interfaces import list_interfaces_of_type class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): super().setUp() + self._base_path = ['interfaces', 'bridge'] + self._test_mtu = True self._interfaces = ['br0'] def test_add_remove_member(self): diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index e070ab98a..330db08e0 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -20,7 +20,9 @@ from vyos.interfaces import list_interfaces_of_type class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): super().setUp() + self._base_path = ['interfaces', 'ethernet'] + self._test_mtu = True self._interfaces = [] # auto detect all ethernet interfaces -- cgit v1.2.3 From 7311b15f601a7aedae96f545f752b208153bb73f Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 20:48:13 +0100 Subject: ethernet: automatically detect available interfaces --- scripts/cli/test_interfaces_ethernet.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index 330db08e0..f8eac6ec3 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -25,11 +25,11 @@ class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): self._test_mtu = True self._interfaces = [] - # auto detect all ethernet interfaces - for interface in list_interfaces_of_type("ethernet"): - if '.' not in interface: - self._interfaces.append(interface) - + # we need to filter out VLAN interfaces identified by a dot (.) + # in their name - just in case! + for tmp in list_interfaces_of_type("ethernet"): + if not '.' in tmp: + self._interfaces.append(tmp) if __name__ == '__main__': -- cgit v1.2.3 From bcd124eb8db82c0a857d5351a1b6fccf615d05dc Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 20:48:27 +0100 Subject: bridge: automatically detect available interfaces --- scripts/cli/test_interfaces_bridge.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/cli/test_interfaces_bridge.py b/scripts/cli/test_interfaces_bridge.py index 1d462645e..28ba218a6 100755 --- a/scripts/cli/test_interfaces_bridge.py +++ b/scripts/cli/test_interfaces_bridge.py @@ -26,19 +26,27 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): self._interfaces = ['br0'] def test_add_remove_member(self): - members = list_interfaces_of_type("ethernet") + members = [] + # we need to filter out VLAN interfaces identified by a dot (.) + # in their name - just in case! + for tmp in list_interfaces_of_type("ethernet"): + if not '.' in tmp: + members.append(tmp) for intf in self._interfaces: cost = 1000 priority = 10 self.session.set(self._base_path + [intf, 'stp']) + + # assign members to bridge interface for member in members: self.session.set(self._base_path + [intf, 'member', 'interface', member]) self.session.set(self._base_path + [intf, 'member', 'interface', member, 'cost', str(cost)]) self.session.set(self._base_path + [intf, 'member', 'interface', member, 'priority', str(priority)]) cost += 1 priority += 1 + self.session.commit() for intf in self._interfaces: -- cgit v1.2.3 From 83597a5f435703595d42cef4839acad6a341c6ec Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 20:53:52 +0100 Subject: bridge: disable MTU test as it can not be configured --- scripts/cli/test_interfaces_bridge.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/cli/test_interfaces_bridge.py b/scripts/cli/test_interfaces_bridge.py index 28ba218a6..d35ac6eb6 100755 --- a/scripts/cli/test_interfaces_bridge.py +++ b/scripts/cli/test_interfaces_bridge.py @@ -22,7 +22,6 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): super().setUp() self._base_path = ['interfaces', 'bridge'] - self._test_mtu = True self._interfaces = ['br0'] def test_add_remove_member(self): -- cgit v1.2.3 From 36629c88ccdf856a79627a710ff34a6f5a47cee4 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 21:08:25 +0100 Subject: ethernet: generic tearDown() should not destroy ethernet CLI nodes --- scripts/cli/base_interfaces_test.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 885995fb8..6c558795a 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -32,9 +32,15 @@ class BasicInterfaceTest: self._test_mtu = False def tearDown(self): - self.session.delete(self._base_path) - self.session.commit() + # we should not remove ethernet from the overall CLI + if 'ethernet' in self._base_path: + self.session.delete(self._base_path) + for intf in self._interfaces: + self.session.set(self._base_path + [intf]) + else: + self.session.delete(self._base_path) + self.session.commit() del self.session def test_add_description(self): -- cgit v1.2.3 From 0078259e5eecee5439e0ef013b64235e4db91c76 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 21:20:22 +0100 Subject: ssh: get_config_value() should return str not list --- scripts/cli/test_service_ssh.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/cli/test_service_ssh.py b/scripts/cli/test_service_ssh.py index f0ad2e565..40e1433b2 100755 --- a/scripts/cli/test_service_ssh.py +++ b/scripts/cli/test_service_ssh.py @@ -28,7 +28,8 @@ base_path = ['service', 'ssh'] def get_config_value(key): tmp = read_file(SSHD_CONF) - return re.findall(r'\n?{}\s+(.*)'.format(key), tmp) + tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) + return tmp[0] class TestServiceSSH(unittest.TestCase): @@ -53,11 +54,11 @@ class TestServiceSSH(unittest.TestCase): self.session.commit() # Check configured port - port = get_config_value('Port')[0] + port = get_config_value('Port') self.assertTrue("2222" in port) # Check DNS usage - dns = get_config_value('UseDNS')[0] + dns = get_config_value('UseDNS') self.assertTrue("no" in dns) # Check for running process -- cgit v1.2.3 From 13686def7e7370ff910abce20b744f5ded932718 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 21:21:12 +0100 Subject: ssh: add test for disable-password-authentication --- scripts/cli/test_service_ssh.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/cli/test_service_ssh.py b/scripts/cli/test_service_ssh.py index 40e1433b2..e882b8f0a 100755 --- a/scripts/cli/test_service_ssh.py +++ b/scripts/cli/test_service_ssh.py @@ -49,6 +49,7 @@ class TestServiceSSH(unittest.TestCase): """ Check if SSH service can be configured and runs """ self.session.set(base_path + ['port', '2222']) self.session.set(base_path + ['disable-host-validation']) + self.session.set(base_path + ['disable-password-authentication']) # commit changes self.session.commit() @@ -61,6 +62,10 @@ class TestServiceSSH(unittest.TestCase): dns = get_config_value('UseDNS') self.assertTrue("no" in dns) + # Check PasswordAuthentication + pwd = get_config_value('PasswordAuthentication') + self.assertTrue("no" in pwd) + # Check for running process self.assertTrue("sshd" in (p.name() for p in process_iter())) -- cgit v1.2.3 From b6000fb7e48d049ce78afbdbeaa24d91c85f0191 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 21:21:54 +0100 Subject: ssh: clean out current configuration in setUp() --- scripts/cli/test_service_ssh.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/cli/test_service_ssh.py b/scripts/cli/test_service_ssh.py index e882b8f0a..43656be9b 100755 --- a/scripts/cli/test_service_ssh.py +++ b/scripts/cli/test_service_ssh.py @@ -38,11 +38,11 @@ class TestServiceSSH(unittest.TestCase): env = self.session.get_session_env() self.config = Config(session_env=env) - def tearDown(self): - # Delete SSH configuration + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) self.session.delete(base_path) - self.session.commit() + def tearDown(self): del self.session def test_ssh(self): -- cgit v1.2.3 From e38c7397d4a7f427bef1dfebf3e7d329d895ec1e Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 21:22:20 +0100 Subject: snmp: get_config_value() should return str not list --- scripts/cli/test_service_snmp.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index 2f918c929..e46b4b588 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -30,7 +30,8 @@ base_path = ['service', 'snmp'] def get_config_value(key): tmp = read_file(SNMPD_CONF) - return re.findall(r'\n?{}\s+(.*)'.format(key), tmp) + tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) + return tmp[0] class TestSNMPService(unittest.TestCase): def setUp(self): @@ -70,7 +71,7 @@ class TestSNMPService(unittest.TestCase): # verify listen address, it will be returned as # ['unix:/run/snmpd.socket,udp:127.0.0.1:161,udp6:[::1]:161'] # thus we need to transfor this into a proper list - config = get_config_value('agentaddress')[0] + config = get_config_value('agentaddress') expected = 'unix:/run/snmpd.socket' for addr in listen: if is_ipv4(addr): @@ -100,6 +101,7 @@ class TestSNMPService(unittest.TestCase): # create user for authpriv in ['auth', 'privacy']: self.session.set(base_path + ['v3', 'user', 'vyos', authpriv, 'plaintext-key', 'vyos1234']) + self.session.set(base_path + ['v3', 'user', 'vyos', 'group', 'default']) # TODO: read in config file and check values -- cgit v1.2.3 From 963825a3a32e3bff4f298b2accf2b7e3ed13b91b Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 21:22:37 +0100 Subject: snmp: clean out current configuration in setUp() --- scripts/cli/test_service_snmp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index e46b4b588..d2e5fff27 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -39,11 +39,11 @@ class TestSNMPService(unittest.TestCase): env = self.session.get_session_env() self.config = Config(session_env=env) - def tearDown(self): - # Delete SNNP configuration + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) self.session.delete(base_path) - self.session.commit() + def tearDown(self): del self.session def test_snmp(self): -- cgit v1.2.3 From c521c670dd2b6a3dfe66a9a2c32382fb3e6524a8 Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Mon, 17 Feb 2020 20:54:20 +0000 Subject: tunnel: T2028: check for tunnel creation check that we are able to create tunnel for all encapsulation supported in interfaces tunnel. --- scripts/cli/test_interfaces_tunnel.py | 82 +++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 scripts/cli/test_interfaces_tunnel.py diff --git a/scripts/cli/test_interfaces_tunnel.py b/scripts/cli/test_interfaces_tunnel.py new file mode 100644 index 000000000..01d6ff93b --- /dev/null +++ b/scripts/cli/test_interfaces_tunnel.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from base_interfaces_test import * + +from vyos.ifconfig import Interface + + +class TunnelInterfaceTest(BasicInterfaceTest.BaseTest): + _base_path = ['interfaces', 'tunnel'] + _interfaces = [] + + # encoding, tunnel endpoint (v4/v6), address (v4/v6) + _valid = [ + ('gre', 4, 4), + ('gre', 4, 6), + ('ip6gre', 6, 4), + ('ip6gre', 6, 6), + ('gre-bridge', 4, 4), + ('ipip', 4, 4), + ('ipip', 4, 6), + ('ipip6', 6, 4), + ('ipip6', 6, 6), + ('ip6ip6', 6, 6), + ('sit', 4, 6), + ] + + remote = { + 4: '192.0.{}.1', + 6: '2002::{}:1', + } + + addrs = { + 4: '10.100.{}.1/24', + 6: '2001:db8:{}::1/64', + } + + def setUp(self): + for number in range(len(self._valid)): + self._interfaces.append('tun%d' % (number+1)) + self._test_mtu = True + super().setUp() + + self.session.set(['interfaces', 'dummy', 'dum444', + 'address', '169.254.0.1/24']) + self.session.set( + ['interfaces', 'dummy', 'dum666', 'address', '2002::1/16']) + self.session.commit() + + local = { + 4: Interface('dum444').get_addr()[0].split('/')[0], + 6: Interface('dum666').get_addr()[0].split('/')[0], + } + + number = 1 + for encap, p2p, addr in self._valid: + intf = 'tun%d' % number + tunnel = {} + tunnel['encapsulation'] = encap + tunnel['local-ip'] = local[p2p].format(number) + tunnel['remote-ip'] = self.remote[p2p].format(number) + tunnel['address'] = self.addrs[addr].format(number) + for name in tunnel: + self.session.set(self._base_path + [intf, name, tunnel[name]]) + number += 1 + + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From b6fd5d5799590c5069e1b34c0e0381c684bd94ce Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 17 Feb 2020 22:15:12 +0100 Subject: tunnel: enable unittest (chmod +x) --- scripts/cli/test_interfaces_tunnel.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/cli/test_interfaces_tunnel.py diff --git a/scripts/cli/test_interfaces_tunnel.py b/scripts/cli/test_interfaces_tunnel.py old mode 100644 new mode 100755 -- cgit v1.2.3 From 74888b22f92abf7f10c8b0baddf815fb5d462897 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 19 Feb 2020 08:47:31 +0100 Subject: tunnel: remove duplicated code --- scripts/cli/test_interfaces_tunnel.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/scripts/cli/test_interfaces_tunnel.py b/scripts/cli/test_interfaces_tunnel.py index 01d6ff93b..f67bda702 100755 --- a/scripts/cli/test_interfaces_tunnel.py +++ b/scripts/cli/test_interfaces_tunnel.py @@ -15,10 +15,8 @@ # along with this program. If not, see . from base_interfaces_test import * - from vyos.ifconfig import Interface - class TunnelInterfaceTest(BasicInterfaceTest.BaseTest): _base_path = ['interfaces', 'tunnel'] _interfaces = [] @@ -54,10 +52,9 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest): self._test_mtu = True super().setUp() - self.session.set(['interfaces', 'dummy', 'dum444', - 'address', '169.254.0.1/24']) - self.session.set( - ['interfaces', 'dummy', 'dum666', 'address', '2002::1/16']) + base_path = ['interfaces', 'dummy'] + self.session.set(base_path + ['dum444', 'address', '169.254.0.1/24']) + self.session.set(base_path + ['dum666', 'address', '2002::1/16']) self.session.commit() local = { @@ -77,6 +74,5 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest): self.session.set(self._base_path + [intf, name, tunnel[name]]) number += 1 - if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 30965ed538d6b90e338c25c4c5bfe45cebdc1ce4 Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Wed, 19 Feb 2020 09:53:33 +0000 Subject: tunnel: tidying up move all variable creation within setUp() create the interfaces using a list comprehension --- scripts/cli/test_interfaces_tunnel.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/cli/test_interfaces_tunnel.py b/scripts/cli/test_interfaces_tunnel.py index f67bda702..136a33c35 100755 --- a/scripts/cli/test_interfaces_tunnel.py +++ b/scripts/cli/test_interfaces_tunnel.py @@ -17,10 +17,8 @@ from base_interfaces_test import * from vyos.ifconfig import Interface -class TunnelInterfaceTest(BasicInterfaceTest.BaseTest): - _base_path = ['interfaces', 'tunnel'] - _interfaces = [] +class TunnelInterfaceTest(BasicInterfaceTest.BaseTest): # encoding, tunnel endpoint (v4/v6), address (v4/v6) _valid = [ ('gre', 4, 4), @@ -47,11 +45,13 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest): } def setUp(self): - for number in range(len(self._valid)): - self._interfaces.append('tun%d' % (number+1)) - self._test_mtu = True super().setUp() + self._base_path = ['interfaces', 'tunnel'] + self._interfaces = ['tun%d' % (n+1) for n in range(len(self._valid))] + self._test_mtu = True + + # creating two dummy interface as to use as local-ip for the tunnels base_path = ['interfaces', 'dummy'] self.session.set(base_path + ['dum444', 'address', '169.254.0.1/24']) self.session.set(base_path + ['dum666', 'address', '2002::1/16']) -- cgit v1.2.3 From f1beefe681240113c6ec856b01e55dc646f52294 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 26 Feb 2020 07:27:52 +0100 Subject: cli: remove superfluous imports (we never use Config()) Every test hat a Config() instance but it was never referenced. It has been introduced by simple means of copy/pasting the first nameserver test. --- scripts/cli/base_interfaces_test.py | 3 --- scripts/cli/test_service_dns_dynamic.py | 3 --- scripts/cli/test_service_snmp.py | 4 ---- scripts/cli/test_service_ssh.py | 4 ---- scripts/cli/test_system_login.py | 3 --- scripts/cli/test_system_nameserver.py | 3 --- 6 files changed, 20 deletions(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 6c558795a..180a11bfb 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -15,7 +15,6 @@ import os import unittest -from vyos.config import Config from vyos.configsession import ConfigSession, ConfigSessionError from netifaces import ifaddresses, AF_INET, AF_INET6 from vyos.validate import is_intf_addr_assigned, is_ipv6_link_local @@ -25,8 +24,6 @@ class BasicInterfaceTest: class BaseTest(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) - env = self.session.get_session_env() - self.config = Config(session_env=env) self._test_addr = ['192.0.2.1/25', '2001:db8:1::ffff/64'] self._test_mtu = False diff --git a/scripts/cli/test_service_dns_dynamic.py b/scripts/cli/test_service_dns_dynamic.py index 21d52be18..e6205cf8b 100755 --- a/scripts/cli/test_service_dns_dynamic.py +++ b/scripts/cli/test_service_dns_dynamic.py @@ -20,7 +20,6 @@ import unittest from getpass import getuser from psutil import process_iter -from vyos.config import Config from vyos.configsession import ConfigSession, ConfigSessionError from vyos.util import read_file @@ -47,8 +46,6 @@ def check_process(): class TestServiceDDNS(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) - env = self.session.get_session_env() - self.config = Config(session_env=env) def tearDown(self): # Delete DDNS configuration diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index d2e5fff27..d4bbdc0b1 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -21,7 +21,6 @@ import unittest from vyos.validate import is_ipv4 from psutil import process_iter -from vyos.config import Config from vyos.configsession import ConfigSession, ConfigSessionError from vyos.util import read_file @@ -36,9 +35,6 @@ def get_config_value(key): class TestSNMPService(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) - env = self.session.get_session_env() - self.config = Config(session_env=env) - # ensure we can also run this test on a live system - so lets clean # out the current configuration :) self.session.delete(base_path) diff --git a/scripts/cli/test_service_ssh.py b/scripts/cli/test_service_ssh.py index 43656be9b..f9f0de3db 100755 --- a/scripts/cli/test_service_ssh.py +++ b/scripts/cli/test_service_ssh.py @@ -19,7 +19,6 @@ import os import unittest from psutil import process_iter -from vyos.config import Config from vyos.configsession import ConfigSession, ConfigSessionError from vyos.util import read_file @@ -35,9 +34,6 @@ def get_config_value(key): class TestServiceSSH(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) - env = self.session.get_session_env() - self.config = Config(session_env=env) - # ensure we can also run this test on a live system - so lets clean # out the current configuration :) self.session.delete(base_path) diff --git a/scripts/cli/test_system_login.py b/scripts/cli/test_system_login.py index 4abbcaf20..3c4b1fa28 100755 --- a/scripts/cli/test_system_login.py +++ b/scripts/cli/test_system_login.py @@ -19,7 +19,6 @@ import re import unittest from subprocess import Popen, PIPE -from vyos.config import Config from vyos.configsession import ConfigSession, ConfigSessionError import vyos.util as util @@ -29,8 +28,6 @@ users = ['vyos1', 'vyos2'] class TestSystemLogin(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) - env = self.session.get_session_env() - self.config = Config(session_env=env) def tearDown(self): # Delete individual users from configuration diff --git a/scripts/cli/test_system_nameserver.py b/scripts/cli/test_system_nameserver.py index 07fc9494b..9040be072 100755 --- a/scripts/cli/test_system_nameserver.py +++ b/scripts/cli/test_system_nameserver.py @@ -18,7 +18,6 @@ import os import re import unittest -from vyos.config import Config from vyos.configsession import ConfigSession, ConfigSessionError import vyos.util as util @@ -34,8 +33,6 @@ def get_name_servers(): class TestSystemNameServer(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) - env = self.session.get_session_env() - self.config = Config(session_env=env) def tearDown(self): # Delete existing name servers -- cgit v1.2.3 From e5acf008785066e2266a913703abb7b9f5e99286 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 26 Feb 2020 07:38:13 +0100 Subject: interfaces: replace wildcard import with dedicated import --- scripts/cli/test_interfaces_bonding.py | 2 +- scripts/cli/test_interfaces_bridge.py | 2 +- scripts/cli/test_interfaces_dummy.py | 2 +- scripts/cli/test_interfaces_ethernet.py | 2 +- scripts/cli/test_interfaces_loopback.py | 2 +- scripts/cli/test_interfaces_tunnel.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/cli/test_interfaces_bonding.py b/scripts/cli/test_interfaces_bonding.py index e1abd7ff1..ccb4428b4 100755 --- a/scripts/cli/test_interfaces_bonding.py +++ b/scripts/cli/test_interfaces_bonding.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from base_interfaces_test import * +from base_interfaces_test import BasicInterfaceTest from vyos.interfaces import list_interfaces_of_type class BondingInterfaceTest(BasicInterfaceTest.BaseTest): diff --git a/scripts/cli/test_interfaces_bridge.py b/scripts/cli/test_interfaces_bridge.py index d35ac6eb6..545239038 100755 --- a/scripts/cli/test_interfaces_bridge.py +++ b/scripts/cli/test_interfaces_bridge.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from base_interfaces_test import * +from base_interfaces_test import BasicInterfaceTest from vyos.interfaces import list_interfaces_of_type class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): diff --git a/scripts/cli/test_interfaces_dummy.py b/scripts/cli/test_interfaces_dummy.py index 3f0cb8bcc..21d0a5cf8 100755 --- a/scripts/cli/test_interfaces_dummy.py +++ b/scripts/cli/test_interfaces_dummy.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from base_interfaces_test import * +from base_interfaces_test import BasicInterfaceTest class DummyInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index f8eac6ec3..a2cede02e 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from base_interfaces_test import * +from base_interfaces_test import BasicInterfaceTest from vyos.interfaces import list_interfaces_of_type class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): diff --git a/scripts/cli/test_interfaces_loopback.py b/scripts/cli/test_interfaces_loopback.py index ceb06aced..697c7cd99 100755 --- a/scripts/cli/test_interfaces_loopback.py +++ b/scripts/cli/test_interfaces_loopback.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from base_interfaces_test import * +from base_interfaces_test import BasicInterfaceTest class LoopbackInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): diff --git a/scripts/cli/test_interfaces_tunnel.py b/scripts/cli/test_interfaces_tunnel.py index f67bda702..980bfa726 100755 --- a/scripts/cli/test_interfaces_tunnel.py +++ b/scripts/cli/test_interfaces_tunnel.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from base_interfaces_test import * +from base_interfaces_test import BasicInterfaceTest from vyos.ifconfig import Interface class TunnelInterfaceTest(BasicInterfaceTest.BaseTest): -- cgit v1.2.3 From 3d94f59766dbfa3230bcebc9233efe8dbf807b2e Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 26 Feb 2020 18:28:49 +0100 Subject: interfaces: add missing unittest import --- scripts/cli/test_interfaces_bonding.py | 2 ++ scripts/cli/test_interfaces_bridge.py | 2 ++ scripts/cli/test_interfaces_dummy.py | 2 ++ scripts/cli/test_interfaces_ethernet.py | 2 ++ scripts/cli/test_interfaces_loopback.py | 2 ++ scripts/cli/test_interfaces_tunnel.py | 2 ++ 6 files changed, 12 insertions(+) diff --git a/scripts/cli/test_interfaces_bonding.py b/scripts/cli/test_interfaces_bonding.py index ccb4428b4..d42e34ee4 100755 --- a/scripts/cli/test_interfaces_bonding.py +++ b/scripts/cli/test_interfaces_bonding.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import unittest + from base_interfaces_test import BasicInterfaceTest from vyos.interfaces import list_interfaces_of_type diff --git a/scripts/cli/test_interfaces_bridge.py b/scripts/cli/test_interfaces_bridge.py index 545239038..100f6fdf2 100755 --- a/scripts/cli/test_interfaces_bridge.py +++ b/scripts/cli/test_interfaces_bridge.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import unittest + from base_interfaces_test import BasicInterfaceTest from vyos.interfaces import list_interfaces_of_type diff --git a/scripts/cli/test_interfaces_dummy.py b/scripts/cli/test_interfaces_dummy.py index 21d0a5cf8..01942fc89 100755 --- a/scripts/cli/test_interfaces_dummy.py +++ b/scripts/cli/test_interfaces_dummy.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import unittest + from base_interfaces_test import BasicInterfaceTest class DummyInterfaceTest(BasicInterfaceTest.BaseTest): diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index a2cede02e..a6c5e902c 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import unittest + from base_interfaces_test import BasicInterfaceTest from vyos.interfaces import list_interfaces_of_type diff --git a/scripts/cli/test_interfaces_loopback.py b/scripts/cli/test_interfaces_loopback.py index 697c7cd99..4462f64fe 100755 --- a/scripts/cli/test_interfaces_loopback.py +++ b/scripts/cli/test_interfaces_loopback.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import unittest + from base_interfaces_test import BasicInterfaceTest class LoopbackInterfaceTest(BasicInterfaceTest.BaseTest): diff --git a/scripts/cli/test_interfaces_tunnel.py b/scripts/cli/test_interfaces_tunnel.py index 8f8311511..d0ccede54 100755 --- a/scripts/cli/test_interfaces_tunnel.py +++ b/scripts/cli/test_interfaces_tunnel.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import unittest + from base_interfaces_test import BasicInterfaceTest from vyos.ifconfig import Interface -- cgit v1.2.3 From dec387b1450ec9fcac9bca6c3df2991558444851 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 26 Feb 2020 19:02:54 +0100 Subject: interfaces: bond: add missing import on ConfigSessionError --- scripts/cli/test_interfaces_bonding.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/cli/test_interfaces_bonding.py b/scripts/cli/test_interfaces_bonding.py index d42e34ee4..ecd12b957 100755 --- a/scripts/cli/test_interfaces_bonding.py +++ b/scripts/cli/test_interfaces_bonding.py @@ -17,7 +17,9 @@ import unittest from base_interfaces_test import BasicInterfaceTest + from vyos.interfaces import list_interfaces_of_type +from vyos.configsession import ConfigSessionError class BondingInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): -- cgit v1.2.3 From a44bf235060e2b12c60b0f3dff7f4ef07615ab78 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 26 Feb 2020 19:03:25 +0100 Subject: interfaces: base: remove superfluous import of ConfigSessionError --- scripts/cli/base_interfaces_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 180a11bfb..12932605e 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -15,7 +15,7 @@ import os import unittest -from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.configsession import ConfigSession from netifaces import ifaddresses, AF_INET, AF_INET6 from vyos.validate import is_intf_addr_assigned, is_ipv6_link_local from vyos.interfaces import list_interfaces_of_type -- cgit v1.2.3 From fdad8650e851ecc67d982139fbfce744708eb32d Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 27 Feb 2020 21:17:53 +0100 Subject: pppoe: add initial test --- scripts/cli/test_interfaces_pppoe.py | 96 ++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100755 scripts/cli/test_interfaces_pppoe.py diff --git a/scripts/cli/test_interfaces_pppoe.py b/scripts/cli/test_interfaces_pppoe.py new file mode 100755 index 000000000..714e3e739 --- /dev/null +++ b/scripts/cli/test_interfaces_pppoe.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import re +import os +import unittest + +from psutil import process_iter +from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.util import read_file + +config_file = '/etc/ppp/peers/{}' +base_path = ['interfaces', 'pppoe'] + +def get_config_value(interface, key): + with open(config_file.format(interface), 'r') as f: + for line in f: + if line.startswith(key): + return list(line.split()) + return [] + +class PPPoEInterfaceTest(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + self._interfaces = ['pppoe0', 'pppoe1', 'pppoe2'] + + def tearDown(self): + self.session.delete(base_path) + self.session.commit() + del self.session + + def test_pppoe_1(self): + """ Check if PPPoE dialer can be configured and runs """ + # ensure source-interface is available + source_interface = 'eth0' + self.session.set(['interfaces', 'ethernet', source_interface]) + + for interface in self._interfaces: + user = 'VyOS-user-' + interface + passwd = 'VyOS-passwd-' + interface + + self.session.set(base_path + [interface, 'authentication', 'user', user]) + self.session.set(base_path + [interface, 'authentication', 'password', passwd]) + self.session.set(base_path + [interface, 'default-route', 'auto']) + self.session.set(base_path + [interface, 'mtu', '1400']) + self.session.set(base_path + [interface, 'no-peer-dns']) + + # check validate() - a source-interface is required + with self.assertRaises(ConfigSessionError): + self.session.commit() + self.session.set(base_path + [interface, 'source-interface', 'eth0']) + + # commit changes + self.session.commit() + + # verify configuration file(s) + for interface in self._interfaces: + user = 'VyOS-user-' + interface + password = 'VyOS-passwd-' + interface + + cur_mtu = get_config_value(interface, 'mtu')[1] + cur_user = get_config_value(interface, 'user')[1].replace('"', '') + cur_password = get_config_value(interface, 'password')[1].replace('"', '') + cur_default_route = get_config_value(interface, 'defaultroute')[0] + cur_ifname = get_config_value(interface, 'ifname')[1] + + self.assertTrue(cur_mtu == '1400') + self.assertTrue(cur_user == user) + self.assertTrue(cur_password == password) + self.assertTrue(cur_default_route == 'defaultroute') + self.assertTrue(cur_ifname == interface) + + # Check if ppp process is running in the interface in question + running = False + for p in process_iter(): + if "pppd" in p.name(): + if interface in p.cmdline(): + running = True + + self.assertTrue(running) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 5baaa066ff35b673e2b8453ea4a88688ad70ca20 Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Thu, 27 Feb 2020 20:19:42 +0000 Subject: tunnel: fix several issues in testcase The addresses for the tunnels were not correctly assigned, leading to some tunnels sharing the same local-ip/remote-ip pairs. The tearnDown code was not removing the dummy interface created and required for testing. Still two tunnels are not deleted as the current code is not using 'ip tunnel delete' for ip6gre (most likely 'ip link delete' instead) This will be resolved when the tunnel interface code is moved to python/vyos-1x --- scripts/cli/test_interfaces_tunnel.py | 69 +++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/scripts/cli/test_interfaces_tunnel.py b/scripts/cli/test_interfaces_tunnel.py index d0ccede54..7611ffe26 100755 --- a/scripts/cli/test_interfaces_tunnel.py +++ b/scripts/cli/test_interfaces_tunnel.py @@ -14,11 +14,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import os import unittest -from base_interfaces_test import BasicInterfaceTest -from vyos.ifconfig import Interface +from vyos.configsession import ConfigSession +from base_interfaces_test import BasicInterfaceTest class TunnelInterfaceTest(BasicInterfaceTest.BaseTest): # encoding, tunnel endpoint (v4/v6), address (v4/v6) @@ -36,45 +37,73 @@ class TunnelInterfaceTest(BasicInterfaceTest.BaseTest): ('sit', 4, 6), ] + local = { + 4: '10.100.{}.1/24', + 6: '2001:db8:{}::1/64', + } + remote = { 4: '192.0.{}.1', 6: '2002::{}:1', } - addrs = { + address = { 4: '10.100.{}.1/24', 6: '2001:db8:{}::1/64', } def setUp(self): - super().setUp() + local = {} + remote = {} + address = {} + self._intf_dummy = ['interfaces', 'dummy'] self._base_path = ['interfaces', 'tunnel'] - self._interfaces = ['tun%d' % (n+1) for n in range(len(self._valid))] + self._interfaces = ['tun{}'.format(n) for n in range(len(self._valid))] + self._test_mtu = True + super().setUp() - # creating two dummy interface as to use as local-ip for the tunnels - base_path = ['interfaces', 'dummy'] - self.session.set(base_path + ['dum444', 'address', '169.254.0.1/24']) - self.session.set(base_path + ['dum666', 'address', '2002::1/16']) - self.session.commit() + for number in range(len(self._valid)): + dum4 = 'dum4{}'.format(number) + dum6 = 'dum6{}'.format(number) - local = { - 4: Interface('dum444').get_addr()[0].split('/')[0], - 6: Interface('dum666').get_addr()[0].split('/')[0], - } + ipv4 = self.local[4].format(number) + ipv6 = self.local[6].format(number) - number = 1 - for encap, p2p, addr in self._valid: + local.setdefault(4, {})[number] = ipv4 + local.setdefault(6, {})[number] = ipv6 + + ipv4 = self.remote[4].format(number) + ipv6 = self.remote[6].format(number) + + remote.setdefault(4, {})[number] = ipv4 + remote.setdefault(6, {})[number] = ipv6 + + ipv4 = self.address[4].format(number) + ipv6 = self.address[6].format(number) + + address.setdefault(4, {})[number] = ipv4 + address.setdefault(6, {})[number] = ipv6 + + self.session.set(self._intf_dummy + [dum4, 'address', ipv4]) + self.session.set(self._intf_dummy + [dum6, 'address', ipv6]) + self.session.commit() + + for number, (encap, p2p, addr) in enumerate(self._valid): intf = 'tun%d' % number tunnel = {} tunnel['encapsulation'] = encap - tunnel['local-ip'] = local[p2p].format(number) - tunnel['remote-ip'] = self.remote[p2p].format(number) - tunnel['address'] = self.addrs[addr].format(number) + tunnel['local-ip'] = local[p2p][number].split('/')[0] + tunnel['remote-ip'] = remote[p2p][number].split('/')[0] + tunnel['address'] = address[addr][number] for name in tunnel: self.session.set(self._base_path + [intf, name, tunnel[name]]) - number += 1 + + def tearDown(self): + self.session.delete(self._intf_dummy) + super().tearDown() + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From dae341a019335e22ea31b3e12934be08d9c00b8a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 29 Feb 2020 08:50:37 +0100 Subject: interfaces: base: add rfc3021 test using /31 prefixes --- scripts/cli/base_interfaces_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 12932605e..11a7031ef 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -25,7 +25,8 @@ class BasicInterfaceTest: def setUp(self): self.session = ConfigSession(os.getpid()) - self._test_addr = ['192.0.2.1/25', '2001:db8:1::ffff/64'] + self._test_addr = ['192.0.2.1/26', '192.0.2.255/31', '192.0.2.64/32', + '2001:db8:1::ffff/64', '2001:db8:101::1/112'] self._test_mtu = False def tearDown(self): -- cgit v1.2.3 From 300452f724c7dcd1aec1a5afc132319347c14939 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 29 Feb 2020 09:38:19 +0100 Subject: interfaces: wireguard: add initial test WireGuard interface can not be easily inherit the BasicInterfaceTest class as every operation on WireGuard interfaces require IP addresses assigned to the interface - I do not now if this is really a requirement or just a to restrict validate() on the WireGuard interface. Nevertheless this helps to see if changes on e.g. ifconfig.py breaks this interface. --- scripts/cli/test_interfaces_wireguard.py | 65 ++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 scripts/cli/test_interfaces_wireguard.py diff --git a/scripts/cli/test_interfaces_wireguard.py b/scripts/cli/test_interfaces_wireguard.py new file mode 100644 index 000000000..ff1ff5d7e --- /dev/null +++ b/scripts/cli/test_interfaces_wireguard.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import unittest + +from vyos.configsession import ConfigSession, ConfigSessionError +from base_interfaces_test import BasicInterfaceTest + +# Generate WireGuard default keypair +if not os.path.isdir('/config/auth/wireguard/default'): + os.system('/usr/libexec/vyos/op_mode/wireguard.py --genkey') + +base_path = ['interfaces', 'wireguard'] + +class WireGuardInterfaceTest(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + self._test_addr = ['192.0.2.1/26', '192.0.2.255/31', '192.0.2.64/32', + '2001:db8:1::ffff/64', '2001:db8:101::1/112'] + self._interfaces = ['wg0', 'wg1'] + + def tearDown(self): + self.session.delete(base_path) + self.session.commit() + del self.session + + def test_peer_setup(self): + """ + Create WireGuard interfaces with associated peers + """ + for intf in self._interfaces: + peer = 'foo-' + intf + psk = 'u2xdA70hkz0S1CG0dZlOh0aq2orwFXRIVrKo4DCvHgM=' + pubkey = 'n6ZZL7ph/QJUJSUUTyu19c77my1dRCDHkMzFQUO9Z3A=' + + for addr in self._test_addr: + self.session.set(base_path + [intf, 'address', addr]) + + self.session.set(base_path + [intf, 'peer', peer, 'endpoint', '127.0.0.1:1337']) + + # Allow different prefixes to traverse the tunnel + allowed_ips = ['0.0.0.0/0'] + for ip in allowed_ips: + self.session.set(base_path + [intf, 'peer', peer, 'allowed-ips', ip]) + + self.session.set(base_path + [intf, 'peer', peer, 'preshared-key', psk]) + self.session.set(base_path + [intf, 'peer', peer, 'pubkey', pubkey]) + self.session.commit() + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From b242ca610ddc5f30470ba5d2e43af625574806e5 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 29 Feb 2020 10:09:01 +0100 Subject: interfaces: wireguard: make test script executable --- scripts/cli/test_interfaces_wireguard.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/cli/test_interfaces_wireguard.py diff --git a/scripts/cli/test_interfaces_wireguard.py b/scripts/cli/test_interfaces_wireguard.py old mode 100644 new mode 100755 -- cgit v1.2.3 From e978f00f4749866a38c349528360a063b47d78ff Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 5 Mar 2020 22:08:49 +0100 Subject: vrf: initial unittest --- scripts/cli/test_vrf.py | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100755 scripts/cli/test_vrf.py diff --git a/scripts/cli/test_vrf.py b/scripts/cli/test_vrf.py new file mode 100755 index 000000000..efa095b30 --- /dev/null +++ b/scripts/cli/test_vrf.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import unittest + +from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.util import read_file + +class VRFTest(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + self._vrfs = ['red', 'green', 'blue'] + + def tearDown(self): + # delete all VRFs + self.session.delete(['vrf']) + self.session.commit() + del self.session + + def test_table_id(self): + table = 1000 + for vrf in self._vrfs: + base = ['vrf', 'name', vrf] + description = "VyOS-VRF-" + vrf + self.session.set(base + ['description', description]) + + # check validate() - a table ID is mandatory + with self.assertRaises(ConfigSessionError): + self.session.commit() + + self.session.set(base + ['table', str(table)]) + table += 1 + + # commit changes + self.session.commit() + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From e5231d59c636dd62d916a533fa86d865a1a1e54d Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 8 Mar 2020 18:33:29 +0100 Subject: wireless: add basic unittest --- scripts/cli/test_interfaces_wireless.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 scripts/cli/test_interfaces_wireless.py diff --git a/scripts/cli/test_interfaces_wireless.py b/scripts/cli/test_interfaces_wireless.py new file mode 100755 index 000000000..9fdc2d20a --- /dev/null +++ b/scripts/cli/test_interfaces_wireless.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import unittest + +from base_interfaces_test import BasicInterfaceTest + +class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + + self._base_path = ['interfaces', 'wireless'] + self._interfaces = ['wlan0', 'wlan1'] + +if __name__ == '__main__': + os.system("modprobe mac80211_hwsim") + unittest.main() -- cgit v1.2.3 From 9957f76f3aa7726b8b2b86c3e76a763da0b8d34f Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 21 Mar 2020 18:25:29 +0100 Subject: Jenkins: T1870: support GitHub PullRequest builds --- Jenkinsfile | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ed98477f2..7a79b0f43 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -36,7 +36,7 @@ def isCustomBuild() { def gitURI = 'git@github.com:vyos/' + getGitRepoName() def httpURI = 'https://github.com/vyos/' + getGitRepoName() - return ! ((getGitRepoURL() == gitURI) || (getGitRepoURL() == httpURI)) + return !((getGitRepoURL() == gitURI) || (getGitRepoURL() == httpURI)) || env.CHANGE_ID } def setDescription() { @@ -74,7 +74,13 @@ node('Docker') { script { // create container name on demand def branchName = getGitBranchName() - if (branchName == "master") { + // Adjust PR target branch name so we can re-map it to the proper + // Docker image. CHANGE_ID is set only for pull requests, so it is + // safe to access the pullRequest global variable + if (env.CHANGE_ID) { + branchName = "${env.CHANGE_TARGET}".toLowerCase() + } + if (branchName.equals("master")) { branchName = "current" } env.DOCKER_IMAGE = "vyos/vyos-build:" + branchName @@ -92,7 +98,6 @@ pipeline { } options { disableConcurrentBuilds() - skipDefaultCheckout() timeout(time: 30, unit: 'MINUTES') timestamps() } @@ -101,8 +106,7 @@ pipeline { steps { script { dir('build') { - git branch: getGitBranchName(), - url: getGitRepoURL() + checkout scm } } } -- cgit v1.2.3 From 5fe2877e539d62294d29e485d1a613b70685c39f Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 22 Mar 2020 12:11:49 +0100 Subject: module: add Intel iavf driver to load list --- scripts/system/test_module_load.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/test_module_load.py b/scripts/system/test_module_load.py index 598ea9882..59c3e0b6a 100755 --- a/scripts/system/test_module_load.py +++ b/scripts/system/test_module_load.py @@ -18,7 +18,7 @@ import os import unittest modules = { - "intel": ["e1000", "e1000e", "igb", "ixgb", "ixgbe", "ixgbevf", "i40e", "i40evf"], + "intel": ["e1000", "e1000e", "igb", "ixgb", "ixgbe", "ixgbevf", "i40e", "i40evf", "iavf"], "accel_ppp": ["ipoe", "vlan_mon"], "misc": ["wireguard"] } -- cgit v1.2.3 From 40540d9c27d781bbb5730d7d83a93edd2380acd3 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 22 Mar 2020 18:31:34 +0100 Subject: wireless: add mandatory physical-interface --- scripts/cli/test_interfaces_wireless.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/scripts/cli/test_interfaces_wireless.py b/scripts/cli/test_interfaces_wireless.py index 9fdc2d20a..f88533b94 100755 --- a/scripts/cli/test_interfaces_wireless.py +++ b/scripts/cli/test_interfaces_wireless.py @@ -24,7 +24,26 @@ class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): super().setUp() self._base_path = ['interfaces', 'wireless'] - self._interfaces = ['wlan0', 'wlan1'] + self._interfaces = ['wlan0'] + + + def test_add_description(self): + """ + A physical interface is mandatory thus we overwrite this function. + """ + for intf in self._interfaces: + self.session.set(self._base_path + [intf, 'physical-device', 'phy0']) + + super.test_add_description() + + def test_add_address(self): + """ + A physical interface is mandatory thus we overwrite this function. + """ + for intf in self._interfaces: + self.session.set(self._base_path + [intf, 'physical-device', 'phy0']) + + super.test_add_description() if __name__ == '__main__': os.system("modprobe mac80211_hwsim") -- cgit v1.2.3 From ff626be2b3378cdad5f1e22bde2f5ba552a18e5a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 22 Mar 2020 19:01:54 +0100 Subject: wireless: fix call to wrong base class method --- scripts/cli/test_interfaces_wireless.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/cli/test_interfaces_wireless.py b/scripts/cli/test_interfaces_wireless.py index f88533b94..2d26ed039 100755 --- a/scripts/cli/test_interfaces_wireless.py +++ b/scripts/cli/test_interfaces_wireless.py @@ -26,7 +26,6 @@ class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): self._base_path = ['interfaces', 'wireless'] self._interfaces = ['wlan0'] - def test_add_description(self): """ A physical interface is mandatory thus we overwrite this function. @@ -43,7 +42,7 @@ class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): for intf in self._interfaces: self.session.set(self._base_path + [intf, 'physical-device', 'phy0']) - super.test_add_description() + super.test_add_address() if __name__ == '__main__': os.system("modprobe mac80211_hwsim") -- cgit v1.2.3 From fc44f25ea39deff5953933e821fb9d47cd6c603a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 22 Mar 2020 20:03:21 +0100 Subject: wireless: temporary disable wireless test --- scripts/cli/test_interfaces_wireless.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 scripts/cli/test_interfaces_wireless.py diff --git a/scripts/cli/test_interfaces_wireless.py b/scripts/cli/test_interfaces_wireless.py old mode 100755 new mode 100644 -- cgit v1.2.3 From 442dd75b3635428824f1e0921846b0a2a7012b14 Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Sun, 22 Mar 2020 20:55:19 +0000 Subject: vxlan: add basic testing --- scripts/cli/base_interfaces_test.py | 14 ++++++++++++++ scripts/cli/test_interfaces_vxlan.py | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 scripts/cli/test_interfaces_vxlan.py diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 11a7031ef..9fa0fb49e 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -22,12 +22,18 @@ from vyos.interfaces import list_interfaces_of_type class BasicInterfaceTest: class BaseTest(unittest.TestCase): + _test_mtu = False + _base_path = [] + _options = {} + _interfaces = [] + def setUp(self): self.session = ConfigSession(os.getpid()) self._test_addr = ['192.0.2.1/26', '192.0.2.255/31', '192.0.2.64/32', '2001:db8:1::ffff/64', '2001:db8:101::1/112'] self._test_mtu = False + self._options = {} def tearDown(self): # we should not remove ethernet from the overall CLI @@ -48,6 +54,9 @@ class BasicInterfaceTest: for intf in self._interfaces: test_string='Description-Test-{}'.format(intf) self.session.set(self._base_path + [intf, 'description', test_string]) + for option in self._options.get(intf, []): + self.session.set(self._base_path + [intf] + option.split()) + self.session.commit() # Validate interface description @@ -66,6 +75,9 @@ class BasicInterfaceTest: for intf in self._interfaces: for addr in self._test_addr: self.session.set(self._base_path + [intf, 'address', addr]) + for option in self._options.get(intf, []): + self.session.set(self._base_path + [intf] + option.split()) + self.session.commit() # Validate address @@ -91,6 +103,8 @@ class BasicInterfaceTest: mtu = '1400' for intf in self._interfaces: self.session.set(self._base_path + [intf, 'mtu', mtu]) + for option in self._options.get(intf, []): + self.session.set(self._base_path + [intf] + option.split()) self.session.commit() diff --git a/scripts/cli/test_interfaces_vxlan.py b/scripts/cli/test_interfaces_vxlan.py new file mode 100644 index 000000000..dc5502838 --- /dev/null +++ b/scripts/cli/test_interfaces_vxlan.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import unittest + +from vyos.configsession import ConfigSession, ConfigSessionError +from base_interfaces_test import BasicInterfaceTest + + +class VXLANInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + + self._test_mtu = True + self._base_path = ['interfaces', 'vxlan'] + self._options = { + 'vxlan0': ['vni 10', 'remote 127.0.0.2'], + 'vxlan1': ['vni 20', 'group 239.1.1.1', 'link eth0'], + } + self._interfaces = list(self._options) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From a3704e5408b1caafd004ed7040d5fe82b3fb2acc Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Mon, 23 Mar 2020 12:03:29 +0000 Subject: geneve: add basic interface testing --- scripts/cli/test_interfaces_geneve.py | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 scripts/cli/test_interfaces_geneve.py diff --git a/scripts/cli/test_interfaces_geneve.py b/scripts/cli/test_interfaces_geneve.py new file mode 100644 index 000000000..0479240d7 --- /dev/null +++ b/scripts/cli/test_interfaces_geneve.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import unittest + +from vyos.configsession import ConfigSession, ConfigSessionError +from base_interfaces_test import BasicInterfaceTest + + +class GeneveInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + + self._test_mtu = True + self._base_path = ['interfaces', 'geneve'] + self._options = { + 'gnv0': ['vni 10', 'remote 127.0.1.1'], + 'gnv1': ['vni 20', 'remote 127.0.1.2'], + } + self._interfaces = list(self._options) + + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From c0b55338a9503a7db49690fca0ec028bb8683875 Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Wed, 25 Mar 2020 09:34:58 +0000 Subject: update to use Interface.listing --- scripts/cli/base_interfaces_test.py | 2 +- scripts/cli/test_interfaces_bonding.py | 4 ++-- scripts/cli/test_interfaces_bridge.py | 4 ++-- scripts/cli/test_interfaces_ethernet.py | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 9fa0fb49e..1fa5472d5 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -18,7 +18,7 @@ import unittest from vyos.configsession import ConfigSession from netifaces import ifaddresses, AF_INET, AF_INET6 from vyos.validate import is_intf_addr_assigned, is_ipv6_link_local -from vyos.interfaces import list_interfaces_of_type +from vyos.ifconfig import Interface class BasicInterfaceTest: class BaseTest(unittest.TestCase): diff --git a/scripts/cli/test_interfaces_bonding.py b/scripts/cli/test_interfaces_bonding.py index ecd12b957..36433ed62 100755 --- a/scripts/cli/test_interfaces_bonding.py +++ b/scripts/cli/test_interfaces_bonding.py @@ -18,7 +18,7 @@ import unittest from base_interfaces_test import BasicInterfaceTest -from vyos.interfaces import list_interfaces_of_type +from vyos.ifconfig import Interface from vyos.configsession import ConfigSessionError class BondingInterfaceTest(BasicInterfaceTest.BaseTest): @@ -33,7 +33,7 @@ class BondingInterfaceTest(BasicInterfaceTest.BaseTest): members = [] # we need to filter out VLAN interfaces identified by a dot (.) # in their name - just in case! - for tmp in list_interfaces_of_type("ethernet"): + for tmp in Interface.listing("ethernet"): if not '.' in tmp: members.append(tmp) diff --git a/scripts/cli/test_interfaces_bridge.py b/scripts/cli/test_interfaces_bridge.py index 100f6fdf2..af6b62724 100755 --- a/scripts/cli/test_interfaces_bridge.py +++ b/scripts/cli/test_interfaces_bridge.py @@ -17,7 +17,7 @@ import unittest from base_interfaces_test import BasicInterfaceTest -from vyos.interfaces import list_interfaces_of_type +from vyos.ifconfig import Interface class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): @@ -30,7 +30,7 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): members = [] # we need to filter out VLAN interfaces identified by a dot (.) # in their name - just in case! - for tmp in list_interfaces_of_type("ethernet"): + for tmp in Interface.listing("ethernet"): if not '.' in tmp: members.append(tmp) diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index a6c5e902c..ddc6ffb27 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -17,7 +17,7 @@ import unittest from base_interfaces_test import BasicInterfaceTest -from vyos.interfaces import list_interfaces_of_type +from vyos.ifconfig import Interface class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): @@ -29,7 +29,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): # we need to filter out VLAN interfaces identified by a dot (.) # in their name - just in case! - for tmp in list_interfaces_of_type("ethernet"): + for tmp in Interface.listing("ethernet"): if not '.' in tmp: self._interfaces.append(tmp) -- cgit v1.2.3 From c26648b99c9a5e7019294dbd2e0a6a3c23f9f85a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 4 Apr 2020 20:36:39 +0200 Subject: pppoe: T2219: default route now implemented via ip-up script --- scripts/cli/test_interfaces_pppoe.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/cli/test_interfaces_pppoe.py b/scripts/cli/test_interfaces_pppoe.py index 714e3e739..9a9a1512c 100755 --- a/scripts/cli/test_interfaces_pppoe.py +++ b/scripts/cli/test_interfaces_pppoe.py @@ -74,13 +74,11 @@ class PPPoEInterfaceTest(unittest.TestCase): cur_mtu = get_config_value(interface, 'mtu')[1] cur_user = get_config_value(interface, 'user')[1].replace('"', '') cur_password = get_config_value(interface, 'password')[1].replace('"', '') - cur_default_route = get_config_value(interface, 'defaultroute')[0] cur_ifname = get_config_value(interface, 'ifname')[1] self.assertTrue(cur_mtu == '1400') self.assertTrue(cur_user == user) self.assertTrue(cur_password == password) - self.assertTrue(cur_default_route == 'defaultroute') self.assertTrue(cur_ifname == interface) # Check if ppp process is running in the interface in question -- cgit v1.2.3 From dc36efc4d70e861d9adcfdcb2865706ac7f32e0f Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 5 Apr 2020 15:02:05 +0200 Subject: wifi: add precondition of physical-interface for all tests --- scripts/cli/test_interfaces_wireless.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) mode change 100644 => 100755 scripts/cli/test_interfaces_wireless.py diff --git a/scripts/cli/test_interfaces_wireless.py b/scripts/cli/test_interfaces_wireless.py old mode 100644 new mode 100755 index 2d26ed039..cefe0e323 --- a/scripts/cli/test_interfaces_wireless.py +++ b/scripts/cli/test_interfaces_wireless.py @@ -24,7 +24,13 @@ class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): super().setUp() self._base_path = ['interfaces', 'wireless'] - self._interfaces = ['wlan0'] + self._interfaces = ['wlan0', 'wlan1', 'wlan10', 'wlan11'] + self._options = { + 'wlan0': ['physical-device phy0'], + 'wlan1': ['physical-device phy0'], + 'wlan10': ['physical-device phy1'], + 'wlan11': ['physical-device phy1'], + } def test_add_description(self): """ -- cgit v1.2.3 From b2da290cdce8d5a9cd1fd964f4583b1a2c34c9f2 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 5 Apr 2020 15:03:52 +0200 Subject: wifi: remove superfluous inherited tests --- scripts/cli/test_interfaces_wireless.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/scripts/cli/test_interfaces_wireless.py b/scripts/cli/test_interfaces_wireless.py index cefe0e323..8693f77e2 100755 --- a/scripts/cli/test_interfaces_wireless.py +++ b/scripts/cli/test_interfaces_wireless.py @@ -32,23 +32,6 @@ class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): 'wlan11': ['physical-device phy1'], } - def test_add_description(self): - """ - A physical interface is mandatory thus we overwrite this function. - """ - for intf in self._interfaces: - self.session.set(self._base_path + [intf, 'physical-device', 'phy0']) - - super.test_add_description() - - def test_add_address(self): - """ - A physical interface is mandatory thus we overwrite this function. - """ - for intf in self._interfaces: - self.session.set(self._base_path + [intf, 'physical-device', 'phy0']) - - super.test_add_address() if __name__ == '__main__': os.system("modprobe mac80211_hwsim") -- cgit v1.2.3 From 6ad15ea8bd767d5c6655d3255d0d8532c507c305 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 5 Apr 2020 16:10:50 +0200 Subject: wifi: add basic interface test --- scripts/cli/test_interfaces_wireless.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/scripts/cli/test_interfaces_wireless.py b/scripts/cli/test_interfaces_wireless.py index 8693f77e2..6edff78b3 100755 --- a/scripts/cli/test_interfaces_wireless.py +++ b/scripts/cli/test_interfaces_wireless.py @@ -24,13 +24,29 @@ class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): super().setUp() self._base_path = ['interfaces', 'wireless'] - self._interfaces = ['wlan0', 'wlan1', 'wlan10', 'wlan11'] self._options = { - 'wlan0': ['physical-device phy0'], - 'wlan1': ['physical-device phy0'], - 'wlan10': ['physical-device phy1'], - 'wlan11': ['physical-device phy1'], + 'wlan0': ['physical-device phy0', 'ssid VyOS-WIFI-0', + 'type station', 'address 192.0.2.1/30'], + 'wlan1': ['physical-device phy0', 'ssid VyOS-WIFI-1', + 'type access-point', 'address 192.0.2.5/30', 'channel 0'], + 'wlan10': ['physical-device phy1', 'ssid VyOS-WIFI-2', + 'type station', 'address 192.0.2.9/30'], + 'wlan11': ['physical-device phy1', 'ssid VyOS-WIFI-3', + 'type access-point', 'address 192.0.2.13/30', 'channel 0'], } + self._interfaces = list(self._options) + self.session.set(['system', 'wifi-regulatory-domain', 'SE']) + + def test_wifi_client(self): + """ test creation of a wireless station """ + for intf in self._interfaces: + # prepare interfaces + for option in self._options.get(intf, []): + self.session.set(self._base_path + [intf] + option.split()) + + # commit changes + self.session.commit() + if __name__ == '__main__': -- cgit v1.2.3 From d2b7359a7bd953e03b5dcdd440e3fa7c633fdfa4 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 5 Apr 2020 16:42:09 +0200 Subject: wireguard: T2206: split endpoint into proper address and port nodes --- scripts/cli/test_interfaces_wireguard.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/cli/test_interfaces_wireguard.py b/scripts/cli/test_interfaces_wireguard.py index ff1ff5d7e..159be02f1 100755 --- a/scripts/cli/test_interfaces_wireguard.py +++ b/scripts/cli/test_interfaces_wireguard.py @@ -50,7 +50,8 @@ class WireGuardInterfaceTest(unittest.TestCase): for addr in self._test_addr: self.session.set(base_path + [intf, 'address', addr]) - self.session.set(base_path + [intf, 'peer', peer, 'endpoint', '127.0.0.1:1337']) + self.session.set(base_path + [intf, 'peer', peer, 'address', '127.0.0.1']) + self.session.set(base_path + [intf, 'peer', peer, 'port', '1337']) # Allow different prefixes to traverse the tunnel allowed_ips = ['0.0.0.0/0'] -- cgit v1.2.3 From 73a9ff255de4be4e8a9d9cb258a5f5c9d8311098 Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Sat, 11 Apr 2020 20:15:41 +0100 Subject: interfaces: T2238: update code to match new API --- scripts/cli/test_interfaces_bonding.py | 4 ++-- scripts/cli/test_interfaces_bridge.py | 4 ++-- scripts/cli/test_interfaces_ethernet.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/cli/test_interfaces_bonding.py b/scripts/cli/test_interfaces_bonding.py index 36433ed62..bfadc4a9d 100755 --- a/scripts/cli/test_interfaces_bonding.py +++ b/scripts/cli/test_interfaces_bonding.py @@ -18,7 +18,7 @@ import unittest from base_interfaces_test import BasicInterfaceTest -from vyos.ifconfig import Interface +from vyos.ifconfig import Section from vyos.configsession import ConfigSessionError class BondingInterfaceTest(BasicInterfaceTest.BaseTest): @@ -33,7 +33,7 @@ class BondingInterfaceTest(BasicInterfaceTest.BaseTest): members = [] # we need to filter out VLAN interfaces identified by a dot (.) # in their name - just in case! - for tmp in Interface.listing("ethernet"): + for tmp in Section.interfaces("ethernet"): if not '.' in tmp: members.append(tmp) diff --git a/scripts/cli/test_interfaces_bridge.py b/scripts/cli/test_interfaces_bridge.py index af6b62724..03c78c210 100755 --- a/scripts/cli/test_interfaces_bridge.py +++ b/scripts/cli/test_interfaces_bridge.py @@ -17,7 +17,7 @@ import unittest from base_interfaces_test import BasicInterfaceTest -from vyos.ifconfig import Interface +from vyos.ifconfig import Section class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): @@ -30,7 +30,7 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): members = [] # we need to filter out VLAN interfaces identified by a dot (.) # in their name - just in case! - for tmp in Interface.listing("ethernet"): + for tmp in Section.interfaces("ethernet"): if not '.' in tmp: members.append(tmp) diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index ddc6ffb27..373c81680 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -17,7 +17,7 @@ import unittest from base_interfaces_test import BasicInterfaceTest -from vyos.ifconfig import Interface +from vyos.ifconfig import Section class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): @@ -29,7 +29,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): # we need to filter out VLAN interfaces identified by a dot (.) # in their name - just in case! - for tmp in Interface.listing("ethernet"): + for tmp in Section.interfaces("ethernet"): if not '.' in tmp: self._interfaces.append(tmp) -- cgit v1.2.3 From c40b538e329da9ce49965ae442ff66ee2a6a7c22 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 13 Apr 2020 21:49:36 +0200 Subject: ddns: adjust to new config path in /run --- scripts/cli/test_service_dns_dynamic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cli/test_service_dns_dynamic.py b/scripts/cli/test_service_dns_dynamic.py index e6205cf8b..be52360ed 100755 --- a/scripts/cli/test_service_dns_dynamic.py +++ b/scripts/cli/test_service_dns_dynamic.py @@ -23,7 +23,7 @@ from psutil import process_iter from vyos.configsession import ConfigSession, ConfigSessionError from vyos.util import read_file -DDCLIENT_CONF = '/etc/ddclient/ddclient.conf' +DDCLIENT_CONF = '/run/ddclient/ddclient.conf' base_path = ['service', 'dns', 'dynamic'] def get_config_value(key): -- cgit v1.2.3 From f0b453c6709b2830d04981c09ec4075b978a5427 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 21 May 2020 20:07:48 +0200 Subject: pppoe: do not check manually if pppoe process runs ... this should rather be done by checking "systemctl status ppp@pppoe0" --- scripts/cli/test_interfaces_pppoe.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/scripts/cli/test_interfaces_pppoe.py b/scripts/cli/test_interfaces_pppoe.py index 9a9a1512c..0e19f514a 100755 --- a/scripts/cli/test_interfaces_pppoe.py +++ b/scripts/cli/test_interfaces_pppoe.py @@ -81,14 +81,5 @@ class PPPoEInterfaceTest(unittest.TestCase): self.assertTrue(cur_password == password) self.assertTrue(cur_ifname == interface) - # Check if ppp process is running in the interface in question - running = False - for p in process_iter(): - if "pppd" in p.name(): - if interface in p.cmdline(): - running = True - - self.assertTrue(running) - if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 8417f55135979be657ae0a3d3e010104c73fc400 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 22 May 2020 12:30:47 +0200 Subject: Revert "pppoe: do not check manually if pppoe process runs" This reverts commit f0b453c6709b2830d04981c09ec4075b978a5427. Test was right - pppd did not run (it was a bug T2488) --- scripts/cli/test_interfaces_pppoe.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/cli/test_interfaces_pppoe.py b/scripts/cli/test_interfaces_pppoe.py index 0e19f514a..9a9a1512c 100755 --- a/scripts/cli/test_interfaces_pppoe.py +++ b/scripts/cli/test_interfaces_pppoe.py @@ -81,5 +81,14 @@ class PPPoEInterfaceTest(unittest.TestCase): self.assertTrue(cur_password == password) self.assertTrue(cur_ifname == interface) + # Check if ppp process is running in the interface in question + running = False + for p in process_iter(): + if "pppd" in p.name(): + if interface in p.cmdline(): + running = True + + self.assertTrue(running) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 160cb06775d51da89fb10b083850ddf42c96b11b Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 12 Jun 2020 16:03:56 +0200 Subject: interfaces: base: speedup address test Instead of calling commit() on every interface we add an address, rather configure all addresses first and then commit() in a single shot! --- scripts/cli/base_interfaces_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 1fa5472d5..3f8a74254 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -78,7 +78,7 @@ class BasicInterfaceTest: for option in self._options.get(intf, []): self.session.set(self._base_path + [intf] + option.split()) - self.session.commit() + self.session.commit() # Validate address for intf in self._interfaces: -- cgit v1.2.3 From b38a42d9d4ab302b44d48844fae49bb0a0817d04 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 19 Jun 2020 21:29:04 +0200 Subject: peth/macvlan: T2589: add basic smoketest --- scripts/cli/test_interfaces_pseudo_ethernet.py | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100755 scripts/cli/test_interfaces_pseudo_ethernet.py diff --git a/scripts/cli/test_interfaces_pseudo_ethernet.py b/scripts/cli/test_interfaces_pseudo_ethernet.py new file mode 100755 index 000000000..e75fb0250 --- /dev/null +++ b/scripts/cli/test_interfaces_pseudo_ethernet.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import unittest + +from base_interfaces_test import BasicInterfaceTest + +class PEthInterfaceTest(BasicInterfaceTest.BaseTest): + + def setUp(self): + super().setUp() + self._base_path = ['interfaces', 'pseudo-ethernet'] + self._options = { + 'peth0': ['source-interface eth0', 'ip arp-cache-timeout 10'], + 'peth1': ['source-interface eth0', 'ip arp-cache-timeout 10'], + } + self._interfaces = list(self._options) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 353fd532ca97711f6c7a22a5c394e9ef7d03f910 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 22 Jun 2020 22:18:01 +0200 Subject: Jenkins: T2625: migrate to build library --- Jenkinsfile | 178 +++--------------------------------------------------------- 1 file changed, 7 insertions(+), 171 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 7a79b0f43..7a760b40b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,4 +1,4 @@ -// Copyright (C) 2019 VyOS maintainers and contributors +// Copyright (C) 2020 VyOS maintainers and contributors // // This program is free software; you can redistribute it and/or modify // in order to easy exprort images built to "external" world @@ -15,174 +15,10 @@ @NonCPS -def getGitBranchName() { - def branch = scm.branches[0].name - return branch.split('/')[-1] -} - -def getGitRepoURL() { - return scm.userRemoteConfigs[0].url -} - -def getGitRepoName() { - return getGitRepoURL().split('/').last() -} - -// Returns true if this is a custom build launched on any project fork. -// Returns false if this is build from git@github.com:vyos/. -// can be e.g. vyos-1x.git or vyatta-op.git -def isCustomBuild() { - // GitHub organisation base URL - def gitURI = 'git@github.com:vyos/' + getGitRepoName() - def httpURI = 'https://github.com/vyos/' + getGitRepoName() - - return !((getGitRepoURL() == gitURI) || (getGitRepoURL() == httpURI)) || env.CHANGE_ID -} - -def setDescription() { - def item = Jenkins.instance.getItemByFullName(env.JOB_NAME) - - // build up the main description text - def description = "" - description += "

VyOS individual package build: " + getGitRepoName().replace('.git', '') + "

" - - if (isCustomBuild()) { - description += "

" - description += "Build not started from official Git repository!
" - description += "
" - description += "Repository: " + getGitRepoURL() + "
" - description += "Branch: " + getGitBranchName() + "
" - description += "

" - } else { - description += "Sources taken from Git branch: " + getGitBranchName() + "
" - } - - item.setDescription(description) - item.save() -} - -/* Only keep the 10 most recent builds. */ -def projectProperties = [ - [$class: 'BuildDiscarderProperty',strategy: [$class: 'LogRotator', numToKeepStr: '10']], -] - -properties(projectProperties) -setDescription() - -node('Docker') { - stage('Define Agent') { - script { - // create container name on demand - def branchName = getGitBranchName() - // Adjust PR target branch name so we can re-map it to the proper - // Docker image. CHANGE_ID is set only for pull requests, so it is - // safe to access the pullRequest global variable - if (env.CHANGE_ID) { - branchName = "${env.CHANGE_TARGET}".toLowerCase() - } - if (branchName.equals("master")) { - branchName = "current" - } - env.DOCKER_IMAGE = "vyos/vyos-build:" + branchName - } - } -} - -pipeline { - agent { - docker { - args "--sysctl net.ipv6.conf.lo.disable_ipv6=0 -e GOSU_UID=1006 -e GOSU_GID=1006" - image "${env.DOCKER_IMAGE}" - alwaysPull true - } - } - options { - disableConcurrentBuilds() - timeout(time: 30, unit: 'MINUTES') - timestamps() - } - stages { - stage('Fetch') { - steps { - script { - dir('build') { - checkout scm - } - } - } - } - stage('Build') { - steps { - script { - dir('build') { - def commitId = sh(returnStdout: true, script: 'git rev-parse --short=11 HEAD').trim() - currentBuild.description = sprintf('Git SHA1: %s', commitId[-11..-1]) - - sh 'dpkg-buildpackage -b -us -uc -tc' - } - } - } - } - } - post { - cleanup { - deleteDir() - } - success { - script { - // archive *.deb artifact on custom builds, deploy to repo otherwise - if ( isCustomBuild()) { - archiveArtifacts artifacts: '*.deb', fingerprint: true - } else { - // publish build result, using SSH-dev.packages.vyos.net Jenkins Credentials - sshagent(['SSH-dev.packages.vyos.net']) { - // build up some fancy groovy variables so we do not need to write/copy - // every option over and over again! - def RELEASE = getGitBranchName() - if (getGitBranchName() == "master") { - RELEASE = 'current' - } - - def VYOS_REPO_PATH = '/home/sentrium/web/dev.packages.vyos.net/public_html/repositories/' + RELEASE + '/' - if (getGitBranchName() == "crux") - VYOS_REPO_PATH += 'vyos/' - - def SSH_OPTS = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR' - def SSH_REMOTE = 'khagen@10.217.48.113' - - echo "Uploading package(s) and updating package(s) in the repository ..." - - files = findFiles(glob: '*.deb') - files.each { PACKAGE -> - def ARCH = sh(returnStdout: true, script: "dpkg-deb -f ${PACKAGE} Architecture").trim() - def SUBSTRING = sh(returnStdout: true, script: "dpkg-deb -f ${PACKAGE} Package").trim() - def SSH_DIR = '~/VyOS/' + RELEASE + '/' + ARCH - def ARCH_OPT = '' - if (ARCH != 'all') - ARCH_OPT = '-A ' + ARCH - - // No need to explicitly check the return code. The pipeline - // will fail if sh returns a non 0 exit code - sh """ - ssh ${SSH_OPTS} ${SSH_REMOTE} -t "bash --login -c 'mkdir -p ${SSH_DIR}'" - """ - sh """ - scp ${SSH_OPTS} ${PACKAGE} ${SSH_REMOTE}:${SSH_DIR}/ - """ - sh """ - ssh ${SSH_OPTS} ${SSH_REMOTE} -t "uncron-add 'reprepro -v -b ${VYOS_REPO_PATH} ${ARCH_OPT} remove ${RELEASE} ${SUBSTRING}'" - """ - sh """ - ssh ${SSH_OPTS} ${SSH_REMOTE} -t "uncron-add 'reprepro -v -b ${VYOS_REPO_PATH} deleteunreferenced'" - """ - sh """ - ssh ${SSH_OPTS} ${SSH_REMOTE} -t "uncron-add 'reprepro -v -b ${VYOS_REPO_PATH} ${ARCH_OPT} includedeb ${RELEASE} ${SSH_DIR}/${PACKAGE}'" - """ - } - } - } - } - } - } -} +// Using a version specifier library, use 'current' branch. The underscore (_) +// is not a typo! You need this underscore if the line immediately after the +// @Library annotation is not an import statement! +@Library('vyos-build@current')_ +// Start package build using library function from https://github.com/c-po/vyos-build +buildPackage() -- cgit v1.2.3 From 95f08f491b96861d2230afdcd6f4428af7dd05d5 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 23 Jun 2020 08:13:18 +0200 Subject: macsec: initial interface test --- scripts/cli/test_interfaces_macsec.py | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100755 scripts/cli/test_interfaces_macsec.py diff --git a/scripts/cli/test_interfaces_macsec.py b/scripts/cli/test_interfaces_macsec.py new file mode 100755 index 000000000..1ba9f5c27 --- /dev/null +++ b/scripts/cli/test_interfaces_macsec.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import unittest + +from vyos.ifconfig import Section +from base_interfaces_test import BasicInterfaceTest + +class MACsecInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + self._base_path = ['interfaces', 'macsec'] + self._options = { + 'macsec0': ['source-interface eth0', + 'security cipher gcm-aes-128', + 'security encrypt', + 'security mka cak 232e44b7fda6f8e2d88a07bf78a7aff4', + 'security mka ckn 40916f4b23e3d548ad27eedd2d10c6f98c2d21684699647d63d41b500dfe8836', + 'security replay-window 128'] + } + + # if we have a physical eth1 interface, add a second macsec instance + if 'eth1' in Section.interfaces("ethernet"): + macsec = { 'macsec1': ['source-interface eth1', 'security cipher gcm-aes-128'] } + self._options.update(macsec) + + self._interfaces = list(self._options) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 23257105b68cb26fe16638928ab490fe3ea99164 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 23 Jun 2020 08:13:24 +0200 Subject: Debian: cleanup runtime dependencies Depends field of package vyos-smoketest: substitution variable ${shlibs:Depends} used, but is not defined --- debian/control | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/control b/debian/control index 97f8b27ea..ada46a4c1 100644 --- a/debian/control +++ b/debian/control @@ -16,7 +16,6 @@ Package: vyos-smoketest Architecture: all Depends: python3, ${python3:Depends}, - ${shlibs:Depends}, ${misc:Depends}, vyos-1x Description: VyOS build sanity checking toolkit -- cgit v1.2.3 From 74c1b3a202a55f4d528f34caf842ad1383b04313 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 23 Jun 2020 08:14:47 +0200 Subject: geneve: enable test --- scripts/cli/test_interfaces_geneve.py | 1 - 1 file changed, 1 deletion(-) mode change 100644 => 100755 scripts/cli/test_interfaces_geneve.py diff --git a/scripts/cli/test_interfaces_geneve.py b/scripts/cli/test_interfaces_geneve.py old mode 100644 new mode 100755 index 0479240d7..f84a55f86 --- a/scripts/cli/test_interfaces_geneve.py +++ b/scripts/cli/test_interfaces_geneve.py @@ -25,7 +25,6 @@ class GeneveInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): super().setUp() - self._test_mtu = True self._base_path = ['interfaces', 'geneve'] self._options = { 'gnv0': ['vni 10', 'remote 127.0.1.1'], -- cgit v1.2.3 From 82024ebc21ff8516620f2fc8ee47e62f83082e3a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 23 Jun 2020 08:14:50 +0200 Subject: vxlan: adjust to new CLI source-interface node --- scripts/cli/test_interfaces_vxlan.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/cli/test_interfaces_vxlan.py b/scripts/cli/test_interfaces_vxlan.py index dc5502838..2628e0285 100644 --- a/scripts/cli/test_interfaces_vxlan.py +++ b/scripts/cli/test_interfaces_vxlan.py @@ -14,13 +14,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import os import unittest from vyos.configsession import ConfigSession, ConfigSessionError from base_interfaces_test import BasicInterfaceTest - class VXLANInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): super().setUp() @@ -29,7 +27,7 @@ class VXLANInterfaceTest(BasicInterfaceTest.BaseTest): self._base_path = ['interfaces', 'vxlan'] self._options = { 'vxlan0': ['vni 10', 'remote 127.0.0.2'], - 'vxlan1': ['vni 20', 'group 239.1.1.1', 'link eth0'], + 'vxlan1': ['vni 20', 'group 239.1.1.1', 'source-interface eth0'], } self._interfaces = list(self._options) -- cgit v1.2.3 From 3d329a77b30b48f51fd104c302c2f2dce0eb4cb2 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 23 Jun 2020 08:15:01 +0200 Subject: vxlan: enable test --- scripts/cli/test_interfaces_vxlan.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/cli/test_interfaces_vxlan.py diff --git a/scripts/cli/test_interfaces_vxlan.py b/scripts/cli/test_interfaces_vxlan.py old mode 100644 new mode 100755 -- cgit v1.2.3 From 1dd18ea39de4184a65527ee0255802f3a6fe3953 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 23 Jun 2020 18:51:56 +0200 Subject: ssh: extend tests --- scripts/cli/test_service_ssh.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/scripts/cli/test_service_ssh.py b/scripts/cli/test_service_ssh.py index f9f0de3db..9127d77ba 100755 --- a/scripts/cli/test_service_ssh.py +++ b/scripts/cli/test_service_ssh.py @@ -46,6 +46,9 @@ class TestServiceSSH(unittest.TestCase): self.session.set(base_path + ['port', '2222']) self.session.set(base_path + ['disable-host-validation']) self.session.set(base_path + ['disable-password-authentication']) + self.session.set(base_path + ['loglevel', 'VERBOSE']) + self.session.set(base_path + ['listen-address', '127.0.0.1']) + self.session.set(base_path + ['client-keepalive-interval', '100']) # commit changes self.session.commit() @@ -62,6 +65,18 @@ class TestServiceSSH(unittest.TestCase): pwd = get_config_value('PasswordAuthentication') self.assertTrue("no" in pwd) + # Check loglevel + loglevel = get_config_value('LogLevel') + self.assertTrue("VERBOSE" in loglevel) + + # Check listen address + address = get_config_value('ListenAddress') + self.assertTrue("127.0.0.1" in address) + + # Check keepalive + keepalive = get_config_value('ClientAliveInterval') + self.assertTrue("100" in keepalive) + # Check for running process self.assertTrue("sshd" in (p.name() for p in process_iter())) -- cgit v1.2.3 From abe6f677ec620c98af7b612569d0d431e05a0bf7 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 24 Jun 2020 18:56:36 +0200 Subject: wireguard: extend tests with multiple allowed-ips --- scripts/cli/test_interfaces_wireguard.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/cli/test_interfaces_wireguard.py b/scripts/cli/test_interfaces_wireguard.py index 159be02f1..0c32a4696 100755 --- a/scripts/cli/test_interfaces_wireguard.py +++ b/scripts/cli/test_interfaces_wireguard.py @@ -22,7 +22,7 @@ from base_interfaces_test import BasicInterfaceTest # Generate WireGuard default keypair if not os.path.isdir('/config/auth/wireguard/default'): - os.system('/usr/libexec/vyos/op_mode/wireguard.py --genkey') + os.system('sudo /usr/libexec/vyos/op_mode/wireguard.py --genkey') base_path = ['interfaces', 'wireguard'] @@ -54,7 +54,7 @@ class WireGuardInterfaceTest(unittest.TestCase): self.session.set(base_path + [intf, 'peer', peer, 'port', '1337']) # Allow different prefixes to traverse the tunnel - allowed_ips = ['0.0.0.0/0'] + allowed_ips = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'] for ip in allowed_ips: self.session.set(base_path + [intf, 'peer', peer, 'allowed-ips', ip]) @@ -62,5 +62,7 @@ class WireGuardInterfaceTest(unittest.TestCase): self.session.set(base_path + [intf, 'peer', peer, 'pubkey', pubkey]) self.session.commit() + self.assertTrue(os.path.isdir(f'/sys/class/net/{intf}')) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From f717f3f3ddb2afca78cf0ff3aab8457242d5f3d0 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 26 Jun 2020 09:43:55 +0200 Subject: ssh: add second test listening on multiple addresses and ports --- scripts/cli/test_service_ssh.py | 56 ++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/scripts/cli/test_service_ssh.py b/scripts/cli/test_service_ssh.py index 9127d77ba..072984ca8 100755 --- a/scripts/cli/test_service_ssh.py +++ b/scripts/cli/test_service_ssh.py @@ -28,8 +28,7 @@ base_path = ['service', 'ssh'] def get_config_value(key): tmp = read_file(SSHD_CONF) tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) - return tmp[0] - + return tmp class TestServiceSSH(unittest.TestCase): def setUp(self): @@ -39,46 +38,79 @@ class TestServiceSSH(unittest.TestCase): self.session.delete(base_path) def tearDown(self): + # delete testing SSH config + self.session.delete(base_path) + # restore "plain" SSH access + self.session.set(base_path) + + self.session.commit() del self.session - def test_ssh(self): + def test_ssh_single(self): """ Check if SSH service can be configured and runs """ - self.session.set(base_path + ['port', '2222']) + self.session.set(base_path + ['port', '1234']) self.session.set(base_path + ['disable-host-validation']) self.session.set(base_path + ['disable-password-authentication']) self.session.set(base_path + ['loglevel', 'VERBOSE']) - self.session.set(base_path + ['listen-address', '127.0.0.1']) self.session.set(base_path + ['client-keepalive-interval', '100']) + self.session.set(base_path + ['listen-address', '127.0.0.1']) # commit changes self.session.commit() # Check configured port - port = get_config_value('Port') - self.assertTrue("2222" in port) + port = get_config_value('Port')[0] + self.assertTrue("1234" in port) # Check DNS usage - dns = get_config_value('UseDNS') + dns = get_config_value('UseDNS')[0] self.assertTrue("no" in dns) # Check PasswordAuthentication - pwd = get_config_value('PasswordAuthentication') + pwd = get_config_value('PasswordAuthentication')[0] self.assertTrue("no" in pwd) # Check loglevel - loglevel = get_config_value('LogLevel') + loglevel = get_config_value('LogLevel')[0] self.assertTrue("VERBOSE" in loglevel) # Check listen address - address = get_config_value('ListenAddress') + address = get_config_value('ListenAddress')[0] self.assertTrue("127.0.0.1" in address) # Check keepalive - keepalive = get_config_value('ClientAliveInterval') + keepalive = get_config_value('ClientAliveInterval')[0] self.assertTrue("100" in keepalive) # Check for running process self.assertTrue("sshd" in (p.name() for p in process_iter())) + def test_ssh_multi(self): + """ Check if SSH service can be configured and runs with multiple + listen ports and listen-addresses """ + ports = ['22', '2222'] + for port in ports: + self.session.set(base_path + ['port', port]) + + addresses = ['127.0.0.1', '::1'] + for address in addresses: + self.session.set(base_path + ['listen-address', address]) + + # commit changes + self.session.commit() + + # Check configured port + tmp = get_config_value('Port') + for port in ports: + self.assertIn(port, tmp) + + # Check listen address + tmp = get_config_value('ListenAddress') + for address in addresses: + self.assertIn(address, tmp) + + # Check for running process + self.assertTrue("sshd" in (p.name() for p in process_iter())) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From d6dc8874daa56e76a8d4ddccfe47224bcd73eb75 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 26 Jun 2020 15:23:38 +0200 Subject: interfaces: add basic test adding only one interface IP address ... this is required for proper testing the "weird" bahavior of T2636 and that the underlaying config parse fabric works as expected while migrating interface code. --- scripts/cli/base_interfaces_test.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 3f8a74254..4fef01236 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -66,7 +66,20 @@ class BasicInterfaceTest: tmp = f.read().rstrip() self.assertTrue(tmp, test_string) - def test_add_address(self): + def test_add_address_single(self): + """ + Check if a single address can be added to interface. + """ + addr = '192.0.2.0/31' + for intf in self._interfaces: + self.session.set(self._base_path + [intf, 'address', addr]) + + self.session.commit() + + for intf in self._interfaces: + self.assertTrue(is_intf_addr_assigned(intf, addr)) + + def test_add_address_multi(self): """ Check if IPv4/IPv6 addresses can be added to interface. """ -- cgit v1.2.3 From 078da2c8c48d29d327740344bfa7c0182fa10986 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 26 Jun 2020 16:58:32 +0200 Subject: loopback: ensure 127.0.0.1, ::1 is always assigned --- scripts/cli/test_interfaces_loopback.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/cli/test_interfaces_loopback.py b/scripts/cli/test_interfaces_loopback.py index 4462f64fe..ba428b5d3 100755 --- a/scripts/cli/test_interfaces_loopback.py +++ b/scripts/cli/test_interfaces_loopback.py @@ -17,12 +17,25 @@ import unittest from base_interfaces_test import BasicInterfaceTest +from vyos.validate import is_intf_addr_assigned class LoopbackInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): super().setUp() + # these addresses are never allowed to be removed from the system + self._loopback_addresses = ['127.0.0.1', '::1'] self._base_path = ['interfaces', 'loopback'] self._interfaces = ['lo'] + def test_add_address_single(self): + super().test_add_address_single() + for addr in self._loopback_addresses: + self.assertTrue(is_intf_addr_assigned('lo', addr)) + + def test_add_address_multi(self): + super().test_add_address_multi() + for addr in self._loopback_addresses: + self.assertTrue(is_intf_addr_assigned('lo', addr)) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From dc5c01765683433a2932bb76ac870651e3ac8904 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 26 Jun 2020 18:07:18 +0200 Subject: interfaces: base: add missing interface options to single IP test --- scripts/cli/base_interfaces_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 4fef01236..53fe553bc 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -73,6 +73,8 @@ class BasicInterfaceTest: addr = '192.0.2.0/31' for intf in self._interfaces: self.session.set(self._base_path + [intf, 'address', addr]) + for option in self._options.get(intf, []): + self.session.set(self._base_path + [intf] + option.split()) self.session.commit() -- cgit v1.2.3 From 90d6d8f3a45d10eb86daee700b10463a3c0fd8d7 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 26 Jun 2020 18:49:48 +0200 Subject: peth: extend basic test with IP options --- scripts/cli/test_interfaces_pseudo_ethernet.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/cli/test_interfaces_pseudo_ethernet.py b/scripts/cli/test_interfaces_pseudo_ethernet.py index e75fb0250..1f5de4f61 100755 --- a/scripts/cli/test_interfaces_pseudo_ethernet.py +++ b/scripts/cli/test_interfaces_pseudo_ethernet.py @@ -23,9 +23,14 @@ class PEthInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): super().setUp() self._base_path = ['interfaces', 'pseudo-ethernet'] + options = ['source-interface eth0', 'ip arp-cache-timeout 10', + 'ip disable-arp-filter', 'ip enable-arp-accept', + 'ip enable-arp-announce', 'ip enable-arp-ignore', + 'ip enable-proxy-arp', 'ip proxy-arp-pvlan'] + self._options = { - 'peth0': ['source-interface eth0', 'ip arp-cache-timeout 10'], - 'peth1': ['source-interface eth0', 'ip arp-cache-timeout 10'], + 'peth0': options, + 'peth1': options, } self._interfaces = list(self._options) -- cgit v1.2.3 From a83375fe1179f694c66314e1640e0a0ea64e3a9e Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 27 Jun 2020 10:31:50 +0200 Subject: macsec: test verify() functions --- scripts/cli/test_interfaces_macsec.py | 70 ++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/scripts/cli/test_interfaces_macsec.py b/scripts/cli/test_interfaces_macsec.py index 1ba9f5c27..60b7037bb 100755 --- a/scripts/cli/test_interfaces_macsec.py +++ b/scripts/cli/test_interfaces_macsec.py @@ -14,10 +14,19 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import re import unittest +from psutil import process_iter from vyos.ifconfig import Section from base_interfaces_test import BasicInterfaceTest +from vyos.configsession import ConfigSessionError +from vyos.util import read_file + +def get_config_value(intf, key): + tmp = read_file(f'/run/wpa_supplicant/{intf}.conf') + tmp = re.findall(r'\n?{}=(.*)'.format(key), tmp) + return tmp[0] class MACsecInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): @@ -25,11 +34,7 @@ class MACsecInterfaceTest(BasicInterfaceTest.BaseTest): self._base_path = ['interfaces', 'macsec'] self._options = { 'macsec0': ['source-interface eth0', - 'security cipher gcm-aes-128', - 'security encrypt', - 'security mka cak 232e44b7fda6f8e2d88a07bf78a7aff4', - 'security mka ckn 40916f4b23e3d548ad27eedd2d10c6f98c2d21684699647d63d41b500dfe8836', - 'security replay-window 128'] + 'security cipher gcm-aes-128'] } # if we have a physical eth1 interface, add a second macsec instance @@ -39,5 +44,60 @@ class MACsecInterfaceTest(BasicInterfaceTest.BaseTest): self._interfaces = list(self._options) + def test_encryption(self): + """ MACsec can be operating in authentication and encryption + mode - both using different mandatory settings, lets test + encryption as the basic authentication test has been performed + using the base class tests """ + intf = 'macsec0' + src_intf = 'eth0' + mak_cak = '232e44b7fda6f8e2d88a07bf78a7aff4' + mak_ckn = '40916f4b23e3d548ad27eedd2d10c6f98c2d21684699647d63d41b500dfe8836' + mak_priority = '100' + replay_window = '64' + self.session.set(self._base_path + [intf, 'security', 'encrypt']) + + # check validate() - Cipher suite must be set for MACsec + with self.assertRaises(ConfigSessionError): + self.session.commit() + self.session.set(self._base_path + [intf, 'security', 'cipher', 'gcm-aes-128']) + + # check validate() - Physical source interface must be set for MACsec + with self.assertRaises(ConfigSessionError): + self.session.commit() + self.session.set(self._base_path + [intf, 'source-interface', src_intf]) + + # check validate() - MACsec security keys mandartory when encryption is enabled + with self.assertRaises(ConfigSessionError): + self.session.commit() + self.session.set(self._base_path + [intf, 'security', 'mka', 'cak', mak_cak]) + + # check validate() - MACsec security keys mandartory when encryption is enabled + with self.assertRaises(ConfigSessionError): + self.session.commit() + self.session.set(self._base_path + [intf, 'security', 'mka', 'ckn', mak_ckn]) + + self.session.set(self._base_path + [intf, 'security', 'mka', 'priority', mak_priority]) + self.session.set(self._base_path + [intf, 'security', 'replay-window', replay_window]) + self.session.commit() + + tmp = get_config_value(src_intf, 'macsec_integ_only') + self.assertTrue("0" in tmp) + + tmp = get_config_value(src_intf, 'mka_cak') + self.assertTrue(mak_cak in tmp) + + tmp = get_config_value(src_intf, 'mka_ckn') + self.assertTrue(mak_ckn in tmp) + + tmp = get_config_value(src_intf, 'mka_priority') + self.assertTrue(mak_priority in tmp) + + tmp = get_config_value(src_intf, 'macsec_replay_window') + self.assertTrue(replay_window in tmp) + + # Check for running process + self.assertTrue("wpa_supplicant" in (p.name() for p in process_iter())) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 28a6cb6b87734a502218d6e7127124dea9353348 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 27 Jun 2020 13:50:00 +0200 Subject: wireless: always use sudo when calling modprobe --- scripts/cli/test_interfaces_wireless.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cli/test_interfaces_wireless.py b/scripts/cli/test_interfaces_wireless.py index 6edff78b3..5d04a1c44 100755 --- a/scripts/cli/test_interfaces_wireless.py +++ b/scripts/cli/test_interfaces_wireless.py @@ -50,5 +50,5 @@ class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): if __name__ == '__main__': - os.system("modprobe mac80211_hwsim") + os.system('sudo modprobe mac80211_hwsim') unittest.main() -- cgit v1.2.3 From 9c3832fc6f6e4f1b326bcd714b6db26fb3188c52 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 27 Jun 2020 14:19:09 +0200 Subject: macsec: test default value for mka priority --- scripts/cli/test_interfaces_macsec.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/cli/test_interfaces_macsec.py b/scripts/cli/test_interfaces_macsec.py index 60b7037bb..0f1b6486d 100755 --- a/scripts/cli/test_interfaces_macsec.py +++ b/scripts/cli/test_interfaces_macsec.py @@ -53,7 +53,6 @@ class MACsecInterfaceTest(BasicInterfaceTest.BaseTest): src_intf = 'eth0' mak_cak = '232e44b7fda6f8e2d88a07bf78a7aff4' mak_ckn = '40916f4b23e3d548ad27eedd2d10c6f98c2d21684699647d63d41b500dfe8836' - mak_priority = '100' replay_window = '64' self.session.set(self._base_path + [intf, 'security', 'encrypt']) @@ -77,7 +76,6 @@ class MACsecInterfaceTest(BasicInterfaceTest.BaseTest): self.session.commit() self.session.set(self._base_path + [intf, 'security', 'mka', 'ckn', mak_ckn]) - self.session.set(self._base_path + [intf, 'security', 'mka', 'priority', mak_priority]) self.session.set(self._base_path + [intf, 'security', 'replay-window', replay_window]) self.session.commit() @@ -90,8 +88,9 @@ class MACsecInterfaceTest(BasicInterfaceTest.BaseTest): tmp = get_config_value(src_intf, 'mka_ckn') self.assertTrue(mak_ckn in tmp) + # check that the default priority of 255 is programmed tmp = get_config_value(src_intf, 'mka_priority') - self.assertTrue(mak_priority in tmp) + self.assertTrue("255" in tmp) tmp = get_config_value(src_intf, 'macsec_replay_window') self.assertTrue(replay_window in tmp) -- cgit v1.2.3 From 4ad5cd436f1082ef5416c03a54730e710cc4441c Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 27 Jun 2020 22:46:00 +0200 Subject: interfaces: wwan: initial testcase --- scripts/cli/test_interfaces_wirelessmodem.py | 84 ++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100755 scripts/cli/test_interfaces_wirelessmodem.py diff --git a/scripts/cli/test_interfaces_wirelessmodem.py b/scripts/cli/test_interfaces_wirelessmodem.py new file mode 100755 index 000000000..baacb8c66 --- /dev/null +++ b/scripts/cli/test_interfaces_wirelessmodem.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import re +import os +import unittest + +from psutil import process_iter +from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.util import read_file + +config_file = '/etc/ppp/peers/{}' +base_path = ['interfaces', 'wirelessmodem'] + +def get_config_value(interface, key): + with open(config_file.format(interface), 'r') as f: + for line in f: + if line.startswith(key): + return list(line.split()) + return [] + +class PPPoEInterfaceTest(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + self._interfaces = ['wlm0', 'wlm1'] + + def tearDown(self): + self.session.delete(base_path) + self.session.commit() + del self.session + + def test_pppoe_1(self): + for interface in self._interfaces: + self.session.set(base_path + [interface, 'no-peer-dns']) + self.session.set(base_path + [interface, 'ondemand']) + + # check validate() - APN must be configure + with self.assertRaises(ConfigSessionError): + self.session.commit() + self.session.set(base_path + [interface, 'apn', 'vyos.net']) + + # check validate() - device must be configure + with self.assertRaises(ConfigSessionError): + self.session.commit() + self.session.set(base_path + [interface, 'device', 'ttyS0']) + + # commit changes + self.session.commit() + + # verify configuration file(s) + for interface in self._interfaces: + tmp = get_config_value(interface, 'ifname')[1] + self.assertTrue(interface in tmp) + + tmp = get_config_value(interface, 'demand')[0] + self.assertTrue('demand' in tmp) + + tmp = os.path.isfile(f'/etc/ppp/peers/chat.{interface}') + self.assertTrue(tmp) + + # Check if ppp process is running in the interface in question + running = False + for p in process_iter(): + if "pppd" in p.name(): + if interface in p.cmdline(): + running = True + + self.assertTrue(running) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 256f5bc1bd1bf80e323d7d7db5ba3c9b7d3463a1 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 28 Jun 2020 20:22:13 +0200 Subject: interfaces: pppoe: add DHCPv6-PD testcase --- scripts/cli/test_interfaces_pppoe.py | 92 +++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 16 deletions(-) diff --git a/scripts/cli/test_interfaces_pppoe.py b/scripts/cli/test_interfaces_pppoe.py index 9a9a1512c..0ad50a2bc 100755 --- a/scripts/cli/test_interfaces_pppoe.py +++ b/scripts/cli/test_interfaces_pppoe.py @@ -23,6 +23,7 @@ from vyos.configsession import ConfigSession, ConfigSessionError from vyos.util import read_file config_file = '/etc/ppp/peers/{}' +dhcp6c_config_file = '/run/dhcp6c/dhcp6c.{}.conf' base_path = ['interfaces', 'pppoe'] def get_config_value(interface, key): @@ -32,10 +33,20 @@ def get_config_value(interface, key): return list(line.split()) return [] +def get_dhcp6c_config_value(interface, key): + tmp = read_file(dhcp6c_config_file.format(interface)) + tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) + + out = [] + for item in tmp: + out.append(item.replace(';','')) + return out + class PPPoEInterfaceTest(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) - self._interfaces = ['pppoe0', 'pppoe1', 'pppoe2'] + self._interfaces = ['pppoe0', 'pppoe50'] + self._source_interface = 'eth0' def tearDown(self): self.session.delete(base_path) @@ -44,24 +55,21 @@ class PPPoEInterfaceTest(unittest.TestCase): def test_pppoe_1(self): """ Check if PPPoE dialer can be configured and runs """ - # ensure source-interface is available - source_interface = 'eth0' - self.session.set(['interfaces', 'ethernet', source_interface]) - for interface in self._interfaces: user = 'VyOS-user-' + interface passwd = 'VyOS-passwd-' + interface + mtu = '1400' self.session.set(base_path + [interface, 'authentication', 'user', user]) self.session.set(base_path + [interface, 'authentication', 'password', passwd]) self.session.set(base_path + [interface, 'default-route', 'auto']) - self.session.set(base_path + [interface, 'mtu', '1400']) + self.session.set(base_path + [interface, 'mtu', mtu]) self.session.set(base_path + [interface, 'no-peer-dns']) # check validate() - a source-interface is required with self.assertRaises(ConfigSessionError): self.session.commit() - self.session.set(base_path + [interface, 'source-interface', 'eth0']) + self.session.set(base_path + [interface, 'source-interface', self._source_interface]) # commit changes self.session.commit() @@ -71,15 +79,14 @@ class PPPoEInterfaceTest(unittest.TestCase): user = 'VyOS-user-' + interface password = 'VyOS-passwd-' + interface - cur_mtu = get_config_value(interface, 'mtu')[1] - cur_user = get_config_value(interface, 'user')[1].replace('"', '') - cur_password = get_config_value(interface, 'password')[1].replace('"', '') - cur_ifname = get_config_value(interface, 'ifname')[1] - - self.assertTrue(cur_mtu == '1400') - self.assertTrue(cur_user == user) - self.assertTrue(cur_password == password) - self.assertTrue(cur_ifname == interface) + tmp = get_config_value(interface, 'mtu')[1] + self.assertTrue(tmp in mtu) + tmp = get_config_value(interface, 'user')[1].replace('"', '') + self.assertTrue(tmp in user) + tmp = get_config_value(interface, 'password')[1].replace('"', '') + self.assertTrue(tmp in password) + tmp = get_config_value(interface, 'ifname')[1] + self.assertTrue(tmp in interface) # Check if ppp process is running in the interface in question running = False @@ -90,5 +97,58 @@ class PPPoEInterfaceTest(unittest.TestCase): self.assertTrue(running) + def test_pppoe_dhcpv6pd(self): + """ Check if PPPoE dialer can be configured and runs """ + address = '1' + sla_id = '0' + sla_len = '8' + for interface in self._interfaces: + self.session.set(base_path + [interface, 'authentication', 'user', 'vyos']) + self.session.set(base_path + [interface, 'authentication', 'password', 'vyos']) + self.session.set(base_path + [interface, 'default-route', 'none']) + self.session.set(base_path + [interface, 'no-peer-dns']) + self.session.set(base_path + [interface, 'source-interface', self._source_interface]) + + # prefix delegation stuff + dhcpv6_pd_base = base_path + [interface, 'dhcpv6-options', 'prefix-delegation'] + self.session.set(dhcpv6_pd_base + ['length', '56']) + self.session.set(dhcpv6_pd_base + ['interface', self._source_interface, 'address', address]) + self.session.set(dhcpv6_pd_base + ['interface', self._source_interface, 'sla-id', sla_id]) + self.session.set(dhcpv6_pd_base + ['interface', self._source_interface, 'sla-len', sla_len]) + + # commit changes + self.session.commit() + + # verify "normal" PPPoE value - 1492 is default MTU + tmp = get_config_value(interface, 'mtu')[1] + self.assertTrue(tmp in '1492') + tmp = get_config_value(interface, 'user')[1].replace('"', '') + self.assertTrue(tmp in 'vyos') + tmp = get_config_value(interface, 'password')[1].replace('"', '') + self.assertTrue(tmp in 'vyos') + + # verify DHCPv6 prefix delegation + # will return: ['delegation', '::/56 infinity;'] + tmp = get_dhcp6c_config_value(interface, 'prefix')[1].split()[0] # mind the whitespace + self.assertTrue(tmp in '::/56') + tmp = get_dhcp6c_config_value(interface, 'prefix-interface')[0].split()[0] + self.assertTrue(tmp in self._source_interface) + tmp = get_dhcp6c_config_value(interface, 'ifid')[0] + self.assertTrue(tmp in address) + tmp = get_dhcp6c_config_value(interface, 'sla-id')[0] + self.assertTrue(tmp in sla_id) + tmp = get_dhcp6c_config_value(interface, 'sla-len')[0] + self.assertTrue(tmp in sla_len) + + # Check if ppp process is running in the interface in question + running = False + for p in process_iter(): + if "pppd" in p.name(): + running = True + self.assertTrue(running) + + # We can not check if wide-dhcpv6 process is running as it is started + # after the PPP interface gets a link to the ISP + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 3db596c271c37a382fb703dbf8a268dc639dcd9c Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 28 Jun 2020 20:22:39 +0200 Subject: interfaces: wwan: remove PPPoE markers --- scripts/cli/test_interfaces_wirelessmodem.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/cli/test_interfaces_wirelessmodem.py b/scripts/cli/test_interfaces_wirelessmodem.py index baacb8c66..40cd03b93 100755 --- a/scripts/cli/test_interfaces_wirelessmodem.py +++ b/scripts/cli/test_interfaces_wirelessmodem.py @@ -14,13 +14,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import re import os import unittest from psutil import process_iter from vyos.configsession import ConfigSession, ConfigSessionError -from vyos.util import read_file config_file = '/etc/ppp/peers/{}' base_path = ['interfaces', 'wirelessmodem'] @@ -32,7 +30,7 @@ def get_config_value(interface, key): return list(line.split()) return [] -class PPPoEInterfaceTest(unittest.TestCase): +class WWANInterfaceTest(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) self._interfaces = ['wlm0', 'wlm1'] @@ -42,7 +40,7 @@ class PPPoEInterfaceTest(unittest.TestCase): self.session.commit() del self.session - def test_pppoe_1(self): + def test_wlm_1(self): for interface in self._interfaces: self.session.set(base_path + [interface, 'no-peer-dns']) self.session.set(base_path + [interface, 'ondemand']) -- cgit v1.2.3 From 22eb02d2a362d30d8f3f6f1df13c59daea0eba25 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 30 Jun 2020 16:38:04 +0200 Subject: interfaces: pppoe: add IPv6 tests --- scripts/cli/test_interfaces_pppoe.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/cli/test_interfaces_pppoe.py b/scripts/cli/test_interfaces_pppoe.py index 0ad50a2bc..3c11da795 100755 --- a/scripts/cli/test_interfaces_pppoe.py +++ b/scripts/cli/test_interfaces_pppoe.py @@ -108,6 +108,7 @@ class PPPoEInterfaceTest(unittest.TestCase): self.session.set(base_path + [interface, 'default-route', 'none']) self.session.set(base_path + [interface, 'no-peer-dns']) self.session.set(base_path + [interface, 'source-interface', self._source_interface]) + self.session.set(base_path + [interface, 'ipv6', 'enable']) # prefix delegation stuff dhcpv6_pd_base = base_path + [interface, 'dhcpv6-options', 'prefix-delegation'] @@ -127,6 +128,10 @@ class PPPoEInterfaceTest(unittest.TestCase): tmp = get_config_value(interface, 'password')[1].replace('"', '') self.assertTrue(tmp in 'vyos') + for param in ['+ipv6', 'ipv6cp-use-ipaddr']: + tmp = get_config_value(interface, param)[0] + self.assertTrue(tmp in param) + # verify DHCPv6 prefix delegation # will return: ['delegation', '::/56 infinity;'] tmp = get_dhcp6c_config_value(interface, 'prefix')[1].split()[0] # mind the whitespace -- cgit v1.2.3 From 8e165496cf32f16acb182022d301360e78465a0b Mon Sep 17 00:00:00 2001 From: fmertz Date: Wed, 1 Jul 2020 17:21:17 +0000 Subject: system display: T2464: initial smoke test + scripts/cli/test_system_display.py system display smoke test --- scripts/cli/test_system_display.py | 135 +++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100755 scripts/cli/test_system_display.py diff --git a/scripts/cli/test_system_display.py b/scripts/cli/test_system_display.py new file mode 100755 index 000000000..001d2d5ab --- /dev/null +++ b/scripts/cli/test_system_display.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 Francois Mertz fireboxled@gmail.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import re +import os +import unittest +import configparser + +from psutil import process_iter +from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.util import read_file + +base_path = ['system', 'display'] + +""" + system display model (sdec|ezio) + system display show host (cpu|cpu-all|cpu-hist|disk|load-hist|memory|proc|uptime) + network interface alias + units (bps|Bps|pps) + clock (big|mini|date-time) + title + + system display time + system display hello + system display bye + system display disabled +""" + +class SystemDisplayTest(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + + def tearDown(self): + self.session.delete(base_path) + self.session.commit() + del self.session + + def test_system_display(self): + # configure some system display + self.session.set(base_path + ['hello', 'Welcome to VyOS']) + self.session.set(base_path + ['bye', 'Bye from VyOS']) + self.session.set(base_path + ['time', '30']) + + # check validate() - a model and a show are required + with self.assertRaises(ConfigSessionError): + self.session.commit() + + self.session.set(base_path + ['model', 'ezio']) + + # check validate() - a show required + with self.assertRaises(ConfigSessionError): + self.session.commit() + + self.session.set(base_path + ['show', 'clock', 'big']) + + self.session.set(base_path + ['show', 'network', 'units', 'pps']) + self.session.set(base_path + ['show', 'network', 'interface', 'eth0', 'alias', 'WAN']) + self.session.set(base_path + ['show', 'network', 'interface', 'eth1', 'alias', 'LAN']) + self.session.set(base_path + ['show', 'network', 'interface', 'eth2', 'alias', 'WIFI']) + # One too many + self.session.set(base_path + ['show', 'network', 'interface', 'eth3']) + + # check validate() - more then 3 interfaces + with self.assertRaises(ConfigSessionError): + self.session.commit() + + self.session.delete(base_path + ['show', 'network', 'interface', 'eth3']) + + # commit changes + self.session.commit() + + # load up ini-styled LCDd.conf + LCDd_conf = configparser.ConfigParser() + LCDd_conf.read('/etc/LCDd.conf') + + # Check settings made it into LCDd.conf + self.assertTrue(LCDd_conf['server']['Driver'] == 'hd44780') + self.assertTrue(LCDd_conf['server']['Hello'] == '"Welcome to VyOS"') + self.assertTrue(LCDd_conf['server']['GoodBye'] == '"Bye from VyOS"') + self.assertTrue(LCDd_conf['server']['WaitTime'] == '30') + + self.assertTrue(LCDd_conf['hd44780']['ConnectionType'] == 'ezio') + self.assertTrue(LCDd_conf['hd44780']['Keypad'] == 'yes') + self.assertTrue(LCDd_conf['hd44780']['Size'] == '16x2') + self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_1'] == 'Enter') + self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_2'] == 'Up') + self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_3'] == 'Down') + self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_4'] == 'Escape') + #self.assertTrue(LCDd_conf['hd44780']['Device'] == '/dev/ttyS1') + + # load up ini-styled lcdproc.conf configuration file + lcdproc_conf = configparser.ConfigParser() + + lcdproc_conf.read('/etc/lcdproc.conf') + # clock + self.assertTrue(lcdproc_conf['TimeDate']['Active'] == 'false') + self.assertTrue(lcdproc_conf['BigClock']['Active'] == 'true') + self.assertTrue(lcdproc_conf['MiniClock']['Active'] == 'false') + # host + self.assertTrue(lcdproc_conf['CPU']['Active'] == 'false') + self.assertTrue(lcdproc_conf['Memory']['Active'] == 'false') + self.assertTrue(lcdproc_conf['Load']['Active'] == 'false') + # network + self.assertTrue(lcdproc_conf['Iface']['Active'] == 'true') + self.assertTrue(lcdproc_conf['Iface']['Interface0'] == 'eth0') + self.assertTrue(lcdproc_conf['Iface']['Alias0'] == 'WAN') + self.assertTrue(lcdproc_conf['Iface']['Interface1'] == 'eth1') + self.assertTrue(lcdproc_conf['Iface']['Alias1'] == 'LAN') + self.assertTrue(lcdproc_conf['Iface']['Interface2'] == 'eth2') + self.assertTrue(lcdproc_conf['Iface']['Alias2'] == 'WIFI') + self.assertTrue(lcdproc_conf['Iface']['unit'] == 'packet') + # Check if LCdd and lcdproc are running + running = 0 + for p in process_iter(): + if p.name() in ['lcdproc', 'LCDd']: + running += 1 + + # both processes running + self.assertTrue(running == 2) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 7bc4167d9520901c001e8d8a08d837e528b3de33 Mon Sep 17 00:00:00 2001 From: fmertz Date: Thu, 2 Jul 2020 05:05:37 +0000 Subject: system display: T2564: conf file in /run * scripts/cli/test_system_display.py conf files in /run --- scripts/cli/test_system_display.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/cli/test_system_display.py b/scripts/cli/test_system_display.py index 001d2d5ab..f9fb00aa5 100755 --- a/scripts/cli/test_system_display.py +++ b/scripts/cli/test_system_display.py @@ -84,7 +84,7 @@ class SystemDisplayTest(unittest.TestCase): # load up ini-styled LCDd.conf LCDd_conf = configparser.ConfigParser() - LCDd_conf.read('/etc/LCDd.conf') + LCDd_conf.read('/run/LCDd/LCDd.lo.conf') # Check settings made it into LCDd.conf self.assertTrue(LCDd_conf['server']['Driver'] == 'hd44780') @@ -104,7 +104,7 @@ class SystemDisplayTest(unittest.TestCase): # load up ini-styled lcdproc.conf configuration file lcdproc_conf = configparser.ConfigParser() - lcdproc_conf.read('/etc/lcdproc.conf') + lcdproc_conf.read('/run/lcdproc/lcdproc.lo.conf') # clock self.assertTrue(lcdproc_conf['TimeDate']['Active'] == 'false') self.assertTrue(lcdproc_conf['BigClock']['Active'] == 'true') -- cgit v1.2.3 From 7981dc1e5b3fc077d3d8732c10bc967fbe9f8596 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 3 Jul 2020 11:09:35 +0200 Subject: ntp: initial simple test --- scripts/cli/test_system_ntp.py | 66 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100755 scripts/cli/test_system_ntp.py diff --git a/scripts/cli/test_system_ntp.py b/scripts/cli/test_system_ntp.py new file mode 100755 index 000000000..c3fff8b06 --- /dev/null +++ b/scripts/cli/test_system_ntp.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import re +import os +import unittest + +from psutil import process_iter +from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.util import read_file + +NTP_CONF = '/etc/ntp.conf' +base_path = ['system', 'ntp'] + +def get_config_value(key): + tmp = read_file(NTP_CONF) + tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) + return tmp + +class TestSystemNTP(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) + self.session.delete(base_path) + + def tearDown(self): + self.session.delete(base_path) + self.session.commit() + del self.session + + def test_ntp_options(self): + servers = ['192.0.2.1', '192.0.2.2'] + options = ['noselect', 'preempt', 'prefer'] + + for server in servers: + for option in options: + self.session.set(base_path + ['server', server, option]) + + # commit changes + self.session.commit() + + # Check configured port + tmp = get_config_value('server') + for server in servers: + test = f'{server} iburst ' + ' '.join(options) + self.assertTrue(test in tmp) + + # Check for running process + self.assertTrue("ntpd" in (p.name() for p in process_iter())) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 2ac2c022d82b572caf40ae04e197ad736233939b Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 3 Jul 2020 11:41:52 +0200 Subject: ntp: extend test with allow-clients, listen-address --- scripts/cli/test_system_ntp.py | 43 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/scripts/cli/test_system_ntp.py b/scripts/cli/test_system_ntp.py index c3fff8b06..ede096376 100755 --- a/scripts/cli/test_system_ntp.py +++ b/scripts/cli/test_system_ntp.py @@ -18,6 +18,7 @@ import re import os import unittest +from ipaddress import ip_network from psutil import process_iter from vyos.configsession import ConfigSession, ConfigSessionError from vyos.util import read_file @@ -43,6 +44,7 @@ class TestSystemNTP(unittest.TestCase): del self.session def test_ntp_options(self): + """ Test basic NTP support with multiple servers and their options """ servers = ['192.0.2.1', '192.0.2.2'] options = ['noselect', 'preempt', 'prefer'] @@ -53,7 +55,7 @@ class TestSystemNTP(unittest.TestCase): # commit changes self.session.commit() - # Check configured port + # Check generated configuration tmp = get_config_value('server') for server in servers: test = f'{server} iburst ' + ' '.join(options) @@ -62,5 +64,44 @@ class TestSystemNTP(unittest.TestCase): # Check for running process self.assertTrue("ntpd" in (p.name() for p in process_iter())) + def test_ntp_clients(self): + """ Test the allowed-networks statement """ + listen_address = ['127.0.0.1', '::1'] + for listen in listen_address: + self.session.set(base_path + ['listen-address', listen]) + + networks = ['192.0.2.0/24', '2001:db8:1000::/64'] + for network in networks: + self.session.set(base_path + ['allow-clients', 'address', network]) + + # Verify "NTP server not configured" verify() statement + with self.assertRaises(ConfigSessionError): + self.session.commit() + + servers = ['192.0.2.1', '192.0.2.2'] + for server in servers: + self.session.set(base_path + ['server', server]) + + self.session.commit() + + # Check generated client address configuration + for network in networks: + network_address = ip_network(network).network_address + network_netmask = ip_network(network).netmask + + tmp = get_config_value(f'restrict {network_address}')[0] + test = f'mask {network_netmask} nomodify notrap nopeer' + self.assertTrue(tmp in test) + + # Check listen address + tmp = get_config_value('interface') + test = ['ignore wildcard'] + for listen in listen_address: + test.append(f'listen {listen}') + self.assertEqual(tmp, test) + + # Check for running process + self.assertTrue("ntpd" in (p.name() for p in process_iter())) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 1b5ff93980fed3e45897a46fe36c5785f0c668fc Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 3 Jul 2020 13:28:18 +0200 Subject: ntp: reuse new library functions for CIDR mangling --- scripts/cli/test_system_ntp.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/cli/test_system_ntp.py b/scripts/cli/test_system_ntp.py index ede096376..856a28916 100755 --- a/scripts/cli/test_system_ntp.py +++ b/scripts/cli/test_system_ntp.py @@ -18,9 +18,9 @@ import re import os import unittest -from ipaddress import ip_network from psutil import process_iter from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.template import vyos_address_from_cidr, vyos_netmask_from_cidr from vyos.util import read_file NTP_CONF = '/etc/ntp.conf' @@ -29,7 +29,8 @@ base_path = ['system', 'ntp'] def get_config_value(key): tmp = read_file(NTP_CONF) tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) - return tmp + # remove possible trailing whitespaces + return [item.strip() for item in tmp] class TestSystemNTP(unittest.TestCase): def setUp(self): @@ -86,8 +87,8 @@ class TestSystemNTP(unittest.TestCase): # Check generated client address configuration for network in networks: - network_address = ip_network(network).network_address - network_netmask = ip_network(network).netmask + network_address = vyos_address_from_cidr(network) + network_netmask = vyos_netmask_from_cidr(network) tmp = get_config_value(f'restrict {network_address}')[0] test = f'mask {network_netmask} nomodify notrap nopeer' -- cgit v1.2.3 From 2cea49cef987e5c6e73744d310857a2e592e409e Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 9 Jul 2020 21:46:35 +0200 Subject: ssh: loglevel is now lowercase --- scripts/cli/test_service_ssh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cli/test_service_ssh.py b/scripts/cli/test_service_ssh.py index 072984ca8..ad56fb53b 100755 --- a/scripts/cli/test_service_ssh.py +++ b/scripts/cli/test_service_ssh.py @@ -51,7 +51,7 @@ class TestServiceSSH(unittest.TestCase): self.session.set(base_path + ['port', '1234']) self.session.set(base_path + ['disable-host-validation']) self.session.set(base_path + ['disable-password-authentication']) - self.session.set(base_path + ['loglevel', 'VERBOSE']) + self.session.set(base_path + ['loglevel', 'verbose']) self.session.set(base_path + ['client-keepalive-interval', '100']) self.session.set(base_path + ['listen-address', '127.0.0.1']) -- cgit v1.2.3 From 10b5196ddfb9a83b17f90f93524ea077275a8557 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 11 Jul 2020 18:03:36 +0200 Subject: snmp: adjust to latest CLI version --- scripts/cli/test_service_snmp.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index d4bbdc0b1..983eadf4c 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -84,7 +84,7 @@ class TestSNMPService(unittest.TestCase): def test_snmpv3(self): """ Check if SNMPv3 can be configured and service runs""" - self.session.set(base_path + ['v3', 'engineid', '0xaffedeadbeef']) + self.session.set(base_path + ['v3', 'engineid', '000000000000000000000002']) self.session.set(base_path + ['v3', 'group', 'default', 'mode', 'ro']) # check validate() - a view must be created before this can be comitted with self.assertRaises(ConfigSessionError): @@ -95,9 +95,10 @@ class TestSNMPService(unittest.TestCase): self.session.commit() # create user - for authpriv in ['auth', 'privacy']: - self.session.set(base_path + ['v3', 'user', 'vyos', authpriv, 'plaintext-key', 'vyos1234']) - + self.session.set(base_path + ['v3', 'user', 'vyos', 'auth', 'plaintext-password', 'vyos12345678']) + self.session.set(base_path + ['v3', 'user', 'vyos', 'auth', 'type', 'sha']) + self.session.set(base_path + ['v3', 'user', 'vyos', 'privacy', 'plaintext-password', 'vyos12345678']) + self.session.set(base_path + ['v3', 'user', 'vyos', 'privacy', 'type', 'aes']) self.session.set(base_path + ['v3', 'user', 'vyos', 'group', 'default']) # TODO: read in config file and check values -- cgit v1.2.3 From 9ac84f533b9dfd80dbf00708ac1f58d260bfdfa7 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 11 Jul 2020 20:22:13 +0200 Subject: snmp: test that encrypted-password is properly inserted into CLI --- scripts/cli/test_service_snmp.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index 983eadf4c..f4f20a3cb 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -92,7 +92,6 @@ class TestSNMPService(unittest.TestCase): self.session.set(base_path + ['v3', 'view', 'default', 'oid', '1']) self.session.set(base_path + ['v3', 'group', 'default', 'view', 'default']) - self.session.commit() # create user self.session.set(base_path + ['v3', 'user', 'vyos', 'auth', 'plaintext-password', 'vyos12345678']) @@ -101,6 +100,16 @@ class TestSNMPService(unittest.TestCase): self.session.set(base_path + ['v3', 'user', 'vyos', 'privacy', 'type', 'aes']) self.session.set(base_path + ['v3', 'user', 'vyos', 'group', 'default']) + self.session.commit() + + # commit will alter the CLI values - check if they have been updated: + hashed_password = '4e52fe55fd011c9c51ae2c65f4b78ca93dcafdfe' + tmp = self.session.show_config(base_path + ['v3', 'user', 'vyos', 'auth', 'encrypted-password']).split()[1] + self.assertEqual(tmp, hashed_password) + + tmp = self.session.show_config(base_path + ['v3', 'user', 'vyos', 'privacy', 'encrypted-password']).split()[1] + self.assertEqual(tmp, hashed_password) + # TODO: read in config file and check values # Check for running process -- cgit v1.2.3 From f2c05556b051126b9bc676f3427114e9889f3b61 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 12 Jul 2020 12:34:33 +0200 Subject: nat: initial simple test --- scripts/cli/test_nat.py | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100755 scripts/cli/test_nat.py diff --git a/scripts/cli/test_nat.py b/scripts/cli/test_nat.py new file mode 100755 index 000000000..fdc1ba7de --- /dev/null +++ b/scripts/cli/test_nat.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import jmespath +import json +import unittest + +from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.util import cmd + +base_path = ['nat'] +snat_pattern = 'nftables[?rule].rule[?chain].{chain: chain, comment: comment, address: { network: expr[].match.right.prefix.addr | [0], prefix: expr[].match.right.prefix.len | [0]}}' + +class TestNAT(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) + self.session.delete(base_path) + + def tearDown(self): + del self.session + + def test_source_nat(self): + """ Check if SNMP can be configured and service runs """ + + path = base_path + ['source'] + network = '192.168.0.0/16' + self.session.set(path + ['rule', '1', 'destination', 'address', network]) + self.session.set(path + ['rule', '1', 'exclude']) + + # check validate() - outbound-interface must be defined + with self.assertRaises(ConfigSessionError): + self.session.commit() + + self.session.set(path + ['rule', '1', 'outbound-interface', 'any']) + self.session.commit() + + tmp = cmd('sudo nft -j list table nat') + nftable_json = json.loads(tmp) + condensed_json = jmespath.search(snat_pattern, nftable_json)[0] + + self.assertEqual(condensed_json['comment'], 'DST-NAT-1') + self.assertEqual(condensed_json['address']['network'], network.split('/')[0]) + self.assertEqual(str(condensed_json['address']['prefix']), network.split('/')[1]) + +if __name__ == '__main__': + unittest.main() + -- cgit v1.2.3 From 497690e812d820c42d56c642358da310eb9459ab Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 12 Jul 2020 13:08:08 +0200 Subject: nat: delete config after test finishes --- scripts/cli/test_nat.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/cli/test_nat.py b/scripts/cli/test_nat.py index fdc1ba7de..416810e40 100755 --- a/scripts/cli/test_nat.py +++ b/scripts/cli/test_nat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright (C) 2020 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -27,16 +27,17 @@ snat_pattern = 'nftables[?rule].rule[?chain].{chain: chain, comment: comment, ad class TestNAT(unittest.TestCase): def setUp(self): - self.session = ConfigSession(os.getpid()) # ensure we can also run this test on a live system - so lets clean # out the current configuration :) + self.session = ConfigSession(os.getpid()) self.session.delete(base_path) def tearDown(self): - del self.session + self.session.delete(base_path) + self.session.commit() def test_source_nat(self): - """ Check if SNMP can be configured and service runs """ + """ Configure and validate source NAT rule(s) """ path = base_path + ['source'] network = '192.168.0.0/16' @@ -60,4 +61,3 @@ class TestNAT(unittest.TestCase): if __name__ == '__main__': unittest.main() - -- cgit v1.2.3 From 01d7ff6ad2919775e6813eeafdcf2f5bb860a1b0 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 12 Jul 2020 14:55:11 +0200 Subject: snmp: add v3 test with MD5 keys --- scripts/cli/test_service_snmp.py | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/scripts/cli/test_service_snmp.py b/scripts/cli/test_service_snmp.py index f4f20a3cb..fb5f5393f 100755 --- a/scripts/cli/test_service_snmp.py +++ b/scripts/cli/test_service_snmp.py @@ -81,8 +81,8 @@ class TestSNMPService(unittest.TestCase): self.assertTrue("snmpd" in (p.name() for p in process_iter())) - def test_snmpv3(self): - """ Check if SNMPv3 can be configured and service runs""" + def test_snmpv3_sha(self): + """ Check if SNMPv3 can be configured with SHA authentication and service runs""" self.session.set(base_path + ['v3', 'engineid', '000000000000000000000002']) self.session.set(base_path + ['v3', 'group', 'default', 'mode', 'ro']) @@ -115,6 +115,41 @@ class TestSNMPService(unittest.TestCase): # Check for running process self.assertTrue("snmpd" in (p.name() for p in process_iter())) + def test_snmpv3_md5(self): + """ Check if SNMPv3 can be configured with MD5 authentication and service runs""" + + self.session.set(base_path + ['v3', 'engineid', '000000000000000000000002']) + self.session.set(base_path + ['v3', 'group', 'default', 'mode', 'ro']) + # check validate() - a view must be created before this can be comitted + with self.assertRaises(ConfigSessionError): + self.session.commit() + + self.session.set(base_path + ['v3', 'view', 'default', 'oid', '1']) + self.session.set(base_path + ['v3', 'group', 'default', 'view', 'default']) + + # create user + self.session.set(base_path + ['v3', 'user', 'vyos', 'auth', 'plaintext-password', 'vyos12345678']) + self.session.set(base_path + ['v3', 'user', 'vyos', 'auth', 'type', 'md5']) + self.session.set(base_path + ['v3', 'user', 'vyos', 'privacy', 'plaintext-password', 'vyos12345678']) + self.session.set(base_path + ['v3', 'user', 'vyos', 'privacy', 'type', 'des']) + self.session.set(base_path + ['v3', 'user', 'vyos', 'group', 'default']) + + self.session.commit() + + # commit will alter the CLI values - check if they have been updated: + hashed_password = '4c67690d45d3dfcd33d0d7e308e370ad' + tmp = self.session.show_config(base_path + ['v3', 'user', 'vyos', 'auth', 'encrypted-password']).split()[1] + self.assertEqual(tmp, hashed_password) + + tmp = self.session.show_config(base_path + ['v3', 'user', 'vyos', 'privacy', 'encrypted-password']).split()[1] + self.assertEqual(tmp, hashed_password) + + # TODO: read in config file and check values + + # Check for running process + self.assertTrue("snmpd" in (p.name() for p in process_iter())) + + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From a06b0051ff3643fdf532db71cceb3a5c9cc40dea Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 17 Jul 2020 19:42:41 +0200 Subject: ethernet: support testing via SSH Instead of running the smoketest on all available interfaces it is now possible to specify a whitespace separated list as environment variable where the test is performed. This is especially usefull when developing/testing via SSH and to limit the test to an interface you are not connected to. Test only with interface eth1: $ TEST_ETH='eth1' /usr/libexec/vyos/tests/smoke/cli/test_interfaces_ethernet.py --- scripts/cli/base_interfaces_test.py | 5 ++++- scripts/cli/test_interfaces_ethernet.py | 12 ++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 53fe553bc..00a6f16e4 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -38,8 +38,11 @@ class BasicInterfaceTest: def tearDown(self): # we should not remove ethernet from the overall CLI if 'ethernet' in self._base_path: - self.session.delete(self._base_path) for intf in self._interfaces: + # when using a dedicated interface to test via TEST_ETH environment + # variable only this one will be cleared in the end - usable to test + # ethernet interfaces via SSH + self.session.delete(self._base_path + [intf]) self.session.set(self._base_path + [intf]) else: self.session.delete(self._base_path) diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index 373c81680..919caab8c 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import os import unittest from base_interfaces_test import BasicInterfaceTest @@ -29,10 +30,13 @@ class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): # we need to filter out VLAN interfaces identified by a dot (.) # in their name - just in case! - for tmp in Section.interfaces("ethernet"): - if not '.' in tmp: - self._interfaces.append(tmp) - + if 'TEST_ETH' in os.environ: + tmp = os.environ['TEST_ETH'].split() + self._interfaces = tmp + else: + for tmp in Section.interfaces("ethernet"): + if not '.' in tmp: + self._interfaces.append(tmp) if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 1316e493983fd14e2282dfc6b107ddf68b16ed8a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 17 Jul 2020 19:55:24 +0200 Subject: interfaces: assume minimum MTU 1280 bytes which always works --- scripts/cli/base_interfaces_test.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 00a6f16e4..489871b8b 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -117,8 +117,9 @@ class BasicInterfaceTest: if self._test_mtu is False: return None - # choose a MTU which works on every interface - mtu = '1400' + # choose MTU which works on every interface - 1280 is minimum for IPv6 so + # it will always work. + mtu = '1280' for intf in self._interfaces: self.session.set(self._base_path + [intf, 'mtu', mtu]) for option in self._options.get(intf, []): @@ -130,4 +131,4 @@ class BasicInterfaceTest: for intf in self._interfaces: with open('/sys/class/net/{}/mtu'.format(intf), 'r') as f: tmp = f.read().rstrip() - self.assertTrue(tmp == mtu) + self.assertEqual(tmp, mtu) -- cgit v1.2.3 From 9579cc1a7d5bf74d6dfa0f55b198dc8a3bdfcfe1 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 17 Jul 2020 20:14:38 +0200 Subject: vlan: add basic test --- scripts/cli/base_interfaces_test.py | 31 ++++++++++++++++++++++++++++++- scripts/cli/test_interfaces_ethernet.py | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 489871b8b..242f9e44c 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -114,7 +114,7 @@ class BasicInterfaceTest: Check if MTU can be changed on interface. Test MTU size will be 1400 bytes. """ - if self._test_mtu is False: + if not self._test_mtu: return None # choose MTU which works on every interface - 1280 is minimum for IPv6 so @@ -132,3 +132,32 @@ class BasicInterfaceTest: with open('/sys/class/net/{}/mtu'.format(intf), 'r') as f: tmp = f.read().rstrip() self.assertEqual(tmp, mtu) + + + def test_8021q_vlan(self): + if not self._test_vlan: + return None + + vlan_range = ['100', '200', '300', '2000'] + for intf in self._interfaces: + for vlan in vlan_range: + address = '192.0.2.1/24' + # choose MTU which works on every interface - 1280 is minimum for IPv6 so + # it will always work. + mtu = '1280' + + base = self._base_path + [intf, 'vif', vlan] + self.session.set(base + ['address', address]) + self.session.set(base + ['mtu', mtu]) + + self.session.commit() + + # Validate interface description + for intf in self._interfaces: + for vlan in vlan_range: + vif = f'{intf}.{vlan}' + with open(f'/sys/class/net/{vif}/mtu', 'r') as f: + tmp = f.read().rstrip() + self.assertEqual(tmp, mtu) + + self.assertTrue(is_intf_addr_assigned(vif, address)) diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index 919caab8c..9ca8a7a02 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -26,6 +26,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): self._base_path = ['interfaces', 'ethernet'] self._test_mtu = True + self._test_vlan = True self._interfaces = [] # we need to filter out VLAN interfaces identified by a dot (.) -- cgit v1.2.3 From 8822783cabeae4b38f881c752a4f2fc3e72d2d70 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 17 Jul 2020 20:32:39 +0200 Subject: interfaces: make single tests reusable, e.g. MTU/VLAN --- scripts/cli/base_interfaces_test.py | 67 ++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 242f9e44c..e73bc6138 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -23,9 +23,15 @@ from vyos.ifconfig import Interface class BasicInterfaceTest: class BaseTest(unittest.TestCase): _test_mtu = False + _test_vlan = False + _test_qinq = False _base_path = [] + _options = {} _interfaces = [] + _vlan_range = ['100', '200', '300', '2000'] + # choose IPv6 minimum MTU value for tests - this must always work + _mtu = '1280' def setUp(self): self.session = ConfigSession(os.getpid()) @@ -108,56 +114,49 @@ class BasicInterfaceTest: self.assertTrue(is_intf_addr_assigned(intf, addr['addr'])) + def _mtu_test(self, intf): + """ helper function to verify MTU size """ + with open('/sys/class/net/{}/mtu'.format(intf), 'r') as f: + tmp = f.read().rstrip() + self.assertEqual(tmp, self._mtu) def test_change_mtu(self): - """ - Check if MTU can be changed on interface. - Test MTU size will be 1400 bytes. - """ + """ Testcase if MTU can be changed on interface """ if not self._test_mtu: return None - - # choose MTU which works on every interface - 1280 is minimum for IPv6 so - # it will always work. - mtu = '1280' for intf in self._interfaces: - self.session.set(self._base_path + [intf, 'mtu', mtu]) + base = self._base_path + [intf] + self.session.set(base + ['mtu', self._mtu]) for option in self._options.get(intf, []): - self.session.set(self._base_path + [intf] + option.split()) + self.session.set(base + option.split()) self.session.commit() - - # Validate interface description for intf in self._interfaces: - with open('/sys/class/net/{}/mtu'.format(intf), 'r') as f: - tmp = f.read().rstrip() - self.assertEqual(tmp, mtu) + self._mtu_test(intf) + + def _vlan_config(self, intf): + for vlan in self._vlan_range: + base = self._base_path + [intf, 'vif', vlan] + self.session.set(base + ['mtu', self._mtu]) + for address in self._test_addr: + self.session.set(base + ['address', address]) + def _vlan_test(self, intf): + for vlan in self._vlan_range: + vif = f'{intf}.{vlan}' + for address in self._test_addr: + self.assertTrue(is_intf_addr_assigned(vif, address)) + with open(f'/sys/class/net/{vif}/mtu', 'r') as f: + tmp = f.read().rstrip() + self.assertEqual(tmp, self._mtu) def test_8021q_vlan(self): if not self._test_vlan: return None - vlan_range = ['100', '200', '300', '2000'] for intf in self._interfaces: - for vlan in vlan_range: - address = '192.0.2.1/24' - # choose MTU which works on every interface - 1280 is minimum for IPv6 so - # it will always work. - mtu = '1280' - - base = self._base_path + [intf, 'vif', vlan] - self.session.set(base + ['address', address]) - self.session.set(base + ['mtu', mtu]) - + self._vlan_config(intf) self.session.commit() - - # Validate interface description for intf in self._interfaces: - for vlan in vlan_range: - vif = f'{intf}.{vlan}' - with open(f'/sys/class/net/{vif}/mtu', 'r') as f: - tmp = f.read().rstrip() - self.assertEqual(tmp, mtu) + self._vlan_test(intf) - self.assertTrue(is_intf_addr_assigned(vif, address)) -- cgit v1.2.3 From a76433c1fde7e7a2c2ee7d5e4078815fb7211184 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 17 Jul 2020 20:38:22 +0200 Subject: interfaces: VLAN tests can not be "functionized" any further --- scripts/cli/base_interfaces_test.py | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index e73bc6138..20899b9b1 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -134,29 +134,24 @@ class BasicInterfaceTest: for intf in self._interfaces: self._mtu_test(intf) - def _vlan_config(self, intf): - for vlan in self._vlan_range: - base = self._base_path + [intf, 'vif', vlan] - self.session.set(base + ['mtu', self._mtu]) - for address in self._test_addr: - self.session.set(base + ['address', address]) - - def _vlan_test(self, intf): - for vlan in self._vlan_range: - vif = f'{intf}.{vlan}' - for address in self._test_addr: - self.assertTrue(is_intf_addr_assigned(vif, address)) - with open(f'/sys/class/net/{vif}/mtu', 'r') as f: - tmp = f.read().rstrip() - self.assertEqual(tmp, self._mtu) - def test_8021q_vlan(self): + """ Testcase for 802.1q VLAN interfaces """ if not self._test_vlan: return None for intf in self._interfaces: - self._vlan_config(intf) + for vlan in self._vlan_range: + base = self._base_path + [intf, 'vif', vlan] + self.session.set(base + ['mtu', self._mtu]) + for address in self._test_addr: + self.session.set(base + ['address', address]) + self.session.commit() for intf in self._interfaces: - self._vlan_test(intf) + for vlan in self._vlan_range: + vif = f'{intf}.{vlan}' + for address in self._test_addr: + self.assertTrue(is_intf_addr_assigned(vif, address)) + self._mtu_test(vif) + -- cgit v1.2.3 From 964ef004065cc0227bfbc36ea655067fe88ad20f Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 17 Jul 2020 20:43:42 +0200 Subject: interfaces: add basic, reusable 802.1ad (Q-in-Q) testcase --- scripts/cli/base_interfaces_test.py | 22 ++++++++++++++++++++++ scripts/cli/test_interfaces_ethernet.py | 1 + 2 files changed, 23 insertions(+) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 20899b9b1..72696f780 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -29,6 +29,7 @@ class BasicInterfaceTest: _options = {} _interfaces = [] + _qinq_range = ['10', '20', '30'] _vlan_range = ['100', '200', '300', '2000'] # choose IPv6 minimum MTU value for tests - this must always work _mtu = '1280' @@ -155,3 +156,24 @@ class BasicInterfaceTest: self._mtu_test(vif) + def test_8021ad_qinq_vlan(self): + """ Testcase for 802.1ad Q-in-Q VLAN interfaces """ + if not self._test_qinq: + return None + + for interface in self._interfaces: + for vif_s in self._qinq_range: + for vif_c in self._vlan_range: + base = self._base_path + [interface, 'vif-s', vif_s, 'vif-c', vif_c] + self.session.set(base + ['mtu', self._mtu]) + for address in self._test_addr: + self.session.set(base + ['address', address]) + + self.session.commit() + for interface in self._interfaces: + for vif_s in self._qinq_range: + for vif_c in self._vlan_range: + vif = f'{interface}.{vif_s}.{vif_c}' + for address in self._test_addr: + self.assertTrue(is_intf_addr_assigned(vif, address)) + self._mtu_test(vif) diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index 9ca8a7a02..7f706aabb 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -27,6 +27,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): self._base_path = ['interfaces', 'ethernet'] self._test_mtu = True self._test_vlan = True + self._test_qinq = True self._interfaces = [] # we need to filter out VLAN interfaces identified by a dot (.) -- cgit v1.2.3 From ded73c194266ee0121b2c4c06dcd78fed0758f81 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 17 Jul 2020 21:53:49 +0200 Subject: bridge: support specifying bridge members via environment variable This eases remote-testing via SSH. --- scripts/cli/test_interfaces_bridge.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/scripts/cli/test_interfaces_bridge.py b/scripts/cli/test_interfaces_bridge.py index 03c78c210..4402cad68 100755 --- a/scripts/cli/test_interfaces_bridge.py +++ b/scripts/cli/test_interfaces_bridge.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import os import unittest from base_interfaces_test import BasicInterfaceTest @@ -30,21 +31,23 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): members = [] # we need to filter out VLAN interfaces identified by a dot (.) # in their name - just in case! - for tmp in Section.interfaces("ethernet"): - if not '.' in tmp: - members.append(tmp) + if 'TEST_ETH' in os.environ: + members = os.environ['TEST_ETH'].split() + else: + for tmp in Section.interfaces("ethernet"): + if not '.' in tmp: members.append(tmp) for intf in self._interfaces: + base = self._base_path + [intf] + self.session.set(base + ['stp']) + cost = 1000 priority = 10 - - self.session.set(self._base_path + [intf, 'stp']) - # assign members to bridge interface for member in members: - self.session.set(self._base_path + [intf, 'member', 'interface', member]) - self.session.set(self._base_path + [intf, 'member', 'interface', member, 'cost', str(cost)]) - self.session.set(self._base_path + [intf, 'member', 'interface', member, 'priority', str(priority)]) + base_member = base + ['member', 'interface', member] + self.session.set(base_member + ['cost', str(cost)]) + self.session.set(base_member + ['priority', str(priority)]) cost += 1 priority += 1 -- cgit v1.2.3 From 511e5aac08e84864dd9c7c1f7992bdbc7d613d47 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 17 Jul 2020 22:06:45 +0200 Subject: bond: verify member interfaces are properly enslaved --- scripts/cli/test_interfaces_bonding.py | 35 ++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/scripts/cli/test_interfaces_bonding.py b/scripts/cli/test_interfaces_bonding.py index bfadc4a9d..b4251fa15 100755 --- a/scripts/cli/test_interfaces_bonding.py +++ b/scripts/cli/test_interfaces_bonding.py @@ -14,46 +14,49 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import os import unittest from base_interfaces_test import BasicInterfaceTest from vyos.ifconfig import Section from vyos.configsession import ConfigSessionError +from vyos.util import read_file class BondingInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): super().setUp() self._base_path = ['interfaces', 'bonding'] - self._test_mtu = True self._interfaces = ['bond0'] + self._test_mtu = True + self._test_vlan = True + self._test_qinq = True - def test_add_remove_member(self): + def test_add_member(self): members = [] # we need to filter out VLAN interfaces identified by a dot (.) # in their name - just in case! - for tmp in Section.interfaces("ethernet"): - if not '.' in tmp: - members.append(tmp) - - for intf in self._interfaces: + if 'TEST_ETH' in os.environ: + members = os.environ['TEST_ETH'].split() + else: + for tmp in Section.interfaces("ethernet"): + if not '.' in tmp: + members.append(tmp) + + for interface in self._interfaces: + base = self._base_path + [interface] for member in members: # We can not enslave an interface when there is an address # assigned - take care here - or find them dynamically if a user # runs vyos-smoketest on his production device? - self.session.set(self._base_path + [intf, 'member', 'interface', member]) + self.session.set(base + ['member', 'interface', member]) self.session.commit() - # check validate() - we can only add existing interfaces - self.session.set(self._base_path + [intf, 'member', 'interface', 'eth99']) - with self.assertRaises(ConfigSessionError): - self.session.commit() - - # check if member deletion works as expected - self.session.delete(self._base_path + [intf, 'member']) - self.session.commit() + for interface in self._interfaces: + slaves = read_file(f'/sys/class/net/{interface}/bonding/slaves').split() + self.assertListEqual(slaves, members) if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 744c656994d87f5ca3b6ab06e072d8ab80a38c39 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 19 Jul 2020 10:50:09 +0200 Subject: service: bcast-relay: add initial tests --- scripts/cli/test_service_bcast-relay.py | 71 +++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100755 scripts/cli/test_service_bcast-relay.py diff --git a/scripts/cli/test_service_bcast-relay.py b/scripts/cli/test_service_bcast-relay.py new file mode 100755 index 000000000..fe4531c3b --- /dev/null +++ b/scripts/cli/test_service_bcast-relay.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import unittest + +from psutil import process_iter +from vyos.configsession import ConfigSession, ConfigSessionError + +base_path = ['service', 'broadcast-relay'] + +class TestServiceBroadcastRelay(unittest.TestCase): + _address1 = '192.0.2.1/24' + _address2 = '192.0.2.1/24' + + def setUp(self): + self.session = ConfigSession(os.getpid()) + self.session.set(['interfaces', 'dummy', 'dum1001', 'address', self._address1]) + self.session.set(['interfaces', 'dummy', 'dum1002', 'address', self._address2]) + self.session.commit() + + def tearDown(self): + self.session.delete(['interfaces', 'dummy', 'dum1001']) + self.session.delete(['interfaces', 'dummy', 'dum1002']) + self.session.delete(base_path) + self.session.commit() + del self.session + + def test_service(self): + """ Check if broadcast relay service can be configured and runs """ + ids = range(1, 5) + for id in ids: + base = base_path + ['id', str(id)] + self.session.set(base + ['description', 'vyos']) + self.session.set(base + ['port', str(10000 + id)]) + + # check validate() - two interfaces must be present + with self.assertRaises(ConfigSessionError): + self.session.commit() + + self.session.set(base + ['interface', 'dum1001']) + self.session.set(base + ['interface', 'dum1002']) + self.session.set(base + ['address', self._address1.split('/')[0]]) + + self.session.commit() + + for id in ids: + # check if process is running + running = False + for p in process_iter(): + if "udp-broadcast-relay" in p.name(): + if p.cmdline()[3] == str(id): + running = True + break + self.assertTrue(running) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From ed4369ca1ed6a5504cbf181722df11c444dd8555 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 24 Jul 2020 17:06:01 +0200 Subject: pppoe: use assertEqual() --- scripts/cli/test_interfaces_pppoe.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/scripts/cli/test_interfaces_pppoe.py b/scripts/cli/test_interfaces_pppoe.py index 3c11da795..d2f6c9b16 100755 --- a/scripts/cli/test_interfaces_pppoe.py +++ b/scripts/cli/test_interfaces_pppoe.py @@ -53,7 +53,7 @@ class PPPoEInterfaceTest(unittest.TestCase): self.session.commit() del self.session - def test_pppoe_1(self): + def test_pppoe(self): """ Check if PPPoE dialer can be configured and runs """ for interface in self._interfaces: user = 'VyOS-user-' + interface @@ -80,13 +80,13 @@ class PPPoEInterfaceTest(unittest.TestCase): password = 'VyOS-passwd-' + interface tmp = get_config_value(interface, 'mtu')[1] - self.assertTrue(tmp in mtu) + self.assertEqual(tmp, mtu) tmp = get_config_value(interface, 'user')[1].replace('"', '') - self.assertTrue(tmp in user) + self.assertEqual(tmp, user) tmp = get_config_value(interface, 'password')[1].replace('"', '') - self.assertTrue(tmp in password) + self.assertEqual(tmp, password) tmp = get_config_value(interface, 'ifname')[1] - self.assertTrue(tmp in interface) + self.assertEqual(tmp, interface) # Check if ppp process is running in the interface in question running = False @@ -98,7 +98,7 @@ class PPPoEInterfaceTest(unittest.TestCase): self.assertTrue(running) def test_pppoe_dhcpv6pd(self): - """ Check if PPPoE dialer can be configured and runs """ + """ Check if PPPoE dialer can be configured with DHCPv6-PD """ address = '1' sla_id = '0' sla_len = '8' @@ -122,28 +122,28 @@ class PPPoEInterfaceTest(unittest.TestCase): # verify "normal" PPPoE value - 1492 is default MTU tmp = get_config_value(interface, 'mtu')[1] - self.assertTrue(tmp in '1492') + self.assertEqual(tmp, '1492') tmp = get_config_value(interface, 'user')[1].replace('"', '') - self.assertTrue(tmp in 'vyos') + self.assertEqual(tmp, 'vyos') tmp = get_config_value(interface, 'password')[1].replace('"', '') - self.assertTrue(tmp in 'vyos') + self.assertEqual(tmp, 'vyos') for param in ['+ipv6', 'ipv6cp-use-ipaddr']: tmp = get_config_value(interface, param)[0] - self.assertTrue(tmp in param) + self.assertEqual(tmp, param) # verify DHCPv6 prefix delegation # will return: ['delegation', '::/56 infinity;'] tmp = get_dhcp6c_config_value(interface, 'prefix')[1].split()[0] # mind the whitespace - self.assertTrue(tmp in '::/56') + self.assertEqual(tmp, '::/56') tmp = get_dhcp6c_config_value(interface, 'prefix-interface')[0].split()[0] - self.assertTrue(tmp in self._source_interface) + self.assertEqual(tmp, self._source_interface) tmp = get_dhcp6c_config_value(interface, 'ifid')[0] - self.assertTrue(tmp in address) + self.assertEqual(tmp, address) tmp = get_dhcp6c_config_value(interface, 'sla-id')[0] - self.assertTrue(tmp in sla_id) + self.assertEqual(tmp, sla_id) tmp = get_dhcp6c_config_value(interface, 'sla-len')[0] - self.assertTrue(tmp in sla_len) + self.assertEqual(tmp, sla_len) # Check if ppp process is running in the interface in question running = False -- cgit v1.2.3 From ded9d1b9372cdee3066fc62fa59c4fd2a0ea3ad5 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 24 Jul 2020 17:06:25 +0200 Subject: ethernet: test "ip" subtree of interface for e.g. ARP settings --- scripts/cli/base_interfaces_test.py | 50 +++++++++++++++++++++++++++++++++ scripts/cli/test_interfaces_ethernet.py | 1 + 2 files changed, 51 insertions(+) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 72696f780..fa3e8a0c1 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -19,9 +19,11 @@ from vyos.configsession import ConfigSession from netifaces import ifaddresses, AF_INET, AF_INET6 from vyos.validate import is_intf_addr_assigned, is_ipv6_link_local from vyos.ifconfig import Interface +from vyos.util import read_file class BasicInterfaceTest: class BaseTest(unittest.TestCase): + _test_ip = False _test_mtu = False _test_vlan = False _test_qinq = False @@ -177,3 +179,51 @@ class BasicInterfaceTest: for address in self._test_addr: self.assertTrue(is_intf_addr_assigned(vif, address)) self._mtu_test(vif) + + def test_ip_options(self): + """ test IP options like arp """ + if not self._test_ip: + return None + + for interface in self._interfaces: + arp_tmo = '300' + path = self._base_path + [interface] + for option in self._options.get(interface, []): + self.session.set(path + option.split()) + + # Options + self.session.set(path + ['ip', 'arp-cache-timeout', arp_tmo]) + self.session.set(path + ['ip', 'disable-arp-filter']) + self.session.set(path + ['ip', 'enable-arp-accept']) + self.session.set(path + ['ip', 'enable-arp-announce']) + self.session.set(path + ['ip', 'enable-arp-ignore']) + self.session.set(path + ['ip', 'enable-proxy-arp']) + self.session.set(path + ['ip', 'proxy-arp-pvlan']) + self.session.set(path + ['ip', 'source-validation', 'loose']) + + self.session.commit() + + for interface in self._interfaces: + tmp = read_file(f'/proc/sys/net/ipv4/neigh/{interface}/base_reachable_time_ms') + self.assertEqual(tmp, str((int(arp_tmo) * 1000))) # tmo value is in milli seconds + + tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_filter') + self.assertEqual('0', tmp) + + tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_accept') + self.assertEqual('1', tmp) + + tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_announce') + self.assertEqual('1', tmp) + + tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_ignore') + self.assertEqual('1', tmp) + + tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/proxy_arp') + self.assertEqual('1', tmp) + + tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/proxy_arp_pvlan') + self.assertEqual('1', tmp) + + tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/rp_filter') + self.assertEqual('2', tmp) diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index 7f706aabb..ccc4238e2 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -25,6 +25,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): super().setUp() self._base_path = ['interfaces', 'ethernet'] + self._test_ip = True self._test_mtu = True self._test_vlan = True self._test_qinq = True -- cgit v1.2.3 From 132b0a424730fca39e1ea3b3ab5c177ec330a057 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 24 Jul 2020 21:29:19 +0200 Subject: wireless: use library function for loading kernel modules --- scripts/cli/test_interfaces_wireless.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/cli/test_interfaces_wireless.py b/scripts/cli/test_interfaces_wireless.py index 5d04a1c44..ff293ac84 100755 --- a/scripts/cli/test_interfaces_wireless.py +++ b/scripts/cli/test_interfaces_wireless.py @@ -18,6 +18,7 @@ import os import unittest from base_interfaces_test import BasicInterfaceTest +from vyos.util import check_kmod class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): @@ -47,8 +48,6 @@ class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): # commit changes self.session.commit() - - if __name__ == '__main__': - os.system('sudo modprobe mac80211_hwsim') + check_kmod('mac80211_hwsim') unittest.main() -- cgit v1.2.3 From fbfab33180dfac893df6447ab3fb5ef9fa8d7e28 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 25 Jul 2020 23:51:30 +0200 Subject: l2tpv3: add initial interface test --- scripts/cli/test_interfaces_l2tpv3.py | 59 +++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100755 scripts/cli/test_interfaces_l2tpv3.py diff --git a/scripts/cli/test_interfaces_l2tpv3.py b/scripts/cli/test_interfaces_l2tpv3.py new file mode 100755 index 000000000..d8655d157 --- /dev/null +++ b/scripts/cli/test_interfaces_l2tpv3.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import json +import jmespath +import unittest + +from base_interfaces_test import BasicInterfaceTest +from vyos.util import cmd + +class GeneveInterfaceTest(BasicInterfaceTest.BaseTest): + def setUp(self): + super().setUp() + + self._base_path = ['interfaces', 'l2tpv3'] + self._options = { + 'l2tpeth10': ['local-ip 127.0.0.1', 'remote-ip 127.10.10.10', + 'tunnel-id 100', 'peer-tunnel-id 10', + 'session-id 100', 'peer-session-id 10', + 'source-port 1010', 'destination-port 10101'], + 'l2tpeth20': ['local-ip 127.0.0.1', 'peer-session-id 20', + 'peer-tunnel-id 200', 'remote-ip 127.20.20.20', + 'session-id 20', 'tunnel-id 200', + 'source-port 2020', 'destination-port 20202'], + } + self._interfaces = list(self._options) + + def test_add_address_single(self): + super().test_add_address_single() + + command = 'sudo ip -j l2tp show session' + json_out = json.loads(cmd(command)) + for interface in self._options: + for config in json_out: + if config['interface'] == interface: + # convert list with configuration items into a dict + dict = {} + for opt in self._options[interface]: + dict.update({opt.split()[0].replace('-','_'): opt.split()[1]}) + + for key in ['peer_session_id', 'peer_tunnel_id', 'session_id', 'tunnel_id']: + self.assertEqual(str(config[key]), dict[key]) + + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From e388ed14fa31f403cd9aadf99965b253fad9f816 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 26 Jul 2020 10:23:56 +0200 Subject: pseudo-ethernet: extend smoketests with VIFs --- scripts/cli/base_interfaces_test.py | 12 ++++++++++-- scripts/cli/test_interfaces_pseudo_ethernet.py | 23 ++++++++++++----------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index fa3e8a0c1..8fae5970e 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -142,9 +142,13 @@ class BasicInterfaceTest: if not self._test_vlan: return None - for intf in self._interfaces: + for interface in self._interfaces: + base = self._base_path + [interface] + for option in self._options.get(interface, []): + self.session.set(base + option.split()) + for vlan in self._vlan_range: - base = self._base_path + [intf, 'vif', vlan] + base = self._base_path + [interface, 'vif', vlan] self.session.set(base + ['mtu', self._mtu]) for address in self._test_addr: self.session.set(base + ['address', address]) @@ -164,6 +168,10 @@ class BasicInterfaceTest: return None for interface in self._interfaces: + base = self._base_path + [interface] + for option in self._options.get(interface, []): + self.session.set(base + option.split()) + for vif_s in self._qinq_range: for vif_c in self._vlan_range: base = self._base_path + [interface, 'vif-s', vif_s, 'vif-c', vif_c] diff --git a/scripts/cli/test_interfaces_pseudo_ethernet.py b/scripts/cli/test_interfaces_pseudo_ethernet.py index 1f5de4f61..bc2e6e7eb 100755 --- a/scripts/cli/test_interfaces_pseudo_ethernet.py +++ b/scripts/cli/test_interfaces_pseudo_ethernet.py @@ -21,18 +21,19 @@ from base_interfaces_test import BasicInterfaceTest class PEthInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): - super().setUp() - self._base_path = ['interfaces', 'pseudo-ethernet'] - options = ['source-interface eth0', 'ip arp-cache-timeout 10', - 'ip disable-arp-filter', 'ip enable-arp-accept', - 'ip enable-arp-announce', 'ip enable-arp-ignore', - 'ip enable-proxy-arp', 'ip proxy-arp-pvlan'] + super().setUp() + self._base_path = ['interfaces', 'pseudo-ethernet'] - self._options = { - 'peth0': options, - 'peth1': options, - } - self._interfaces = list(self._options) + self._test_ip = True + self._test_mtu = True + self._test_vlan = True + self._test_qinq = True + + self._options = { + 'peth0': ['source-interface eth1'], + 'peth1': ['source-interface eth1'], + } + self._interfaces = list(self._options) if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 4e1062ea02ccd99940da18a887e2092b0a9e5650 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 29 Jul 2020 17:41:10 +0200 Subject: mdns-repeater: add basic test --- scripts/cli/test_service_mdns-repeater.py | 51 +++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 scripts/cli/test_service_mdns-repeater.py diff --git a/scripts/cli/test_service_mdns-repeater.py b/scripts/cli/test_service_mdns-repeater.py new file mode 100755 index 000000000..18900b6d2 --- /dev/null +++ b/scripts/cli/test_service_mdns-repeater.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import unittest + +from psutil import process_iter +from vyos.configsession import ConfigSession + +base_path = ['service', 'mdns', 'repeater'] +intf_base = ['interfaces', 'dummy'] + +class TestServiceMDNSrepeater(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + + def tearDown(self): + self.session.delete(base_path) + self.session.delete(intf_base + ['dum10']) + self.session.delete(intf_base + ['dum20']) + self.session.commit() + del self.session + + def test_service(self): + # Service required a configured IP address on the interface + + self.session.set(intf_base + ['dum10', 'address', '192.0.2.1/30']) + self.session.set(intf_base + ['dum20', 'address', '192.0.2.5/30']) + + self.session.set(base_path + ['interface', 'dum10']) + self.session.set(base_path + ['interface', 'dum20']) + self.session.commit() + + # Check for running process + self.assertTrue("mdns-repeater" in (p.name() for p in process_iter())) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From fa3e3915254df7d4bcb3c8964113954669413d12 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 30 Jul 2020 22:56:00 +0200 Subject: router-advert: add initial test --- scripts/cli/test_service_router-advert.py | 98 +++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100755 scripts/cli/test_service_router-advert.py diff --git a/scripts/cli/test_service_router-advert.py b/scripts/cli/test_service_router-advert.py new file mode 100755 index 000000000..cc251e355 --- /dev/null +++ b/scripts/cli/test_service_router-advert.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019-2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import re +import os +import unittest + +from psutil import process_iter +from vyos.configsession import ConfigSession +from vyos.util import read_file + +RADVD_CONF = '/run/radvd/radvd.conf' + +interface = 'eth1' +base_path = ['service', 'router-advert', 'interface', interface] +address_base = ['interfaces', 'ethernet', interface, 'address'] + +def get_config_value(key): + tmp = read_file(RADVD_CONF) + tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp) + return tmp[0].split()[0].replace(';','') + +class TestServiceRADVD(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + self.session.set(address_base + ['2001:db8::1/64']) + + def tearDown(self): + self.session.delete(address_base) + self.session.delete(base_path) + self.session.commit() + del self.session + + def test_single(self): + self.session.set(base_path + ['prefix', '::/64', 'no-on-link-flag']) + self.session.set(base_path + ['prefix', '::/64', 'no-autonomous-flag']) + self.session.set(base_path + ['dnssl', '2001:db8::1234']) + self.session.set(base_path + ['other-config-flag']) + + # commit changes + self.session.commit() + + # verify values + tmp = get_config_value('interface') + self.assertEqual(tmp, interface) + + tmp = get_config_value('prefix') + self.assertEqual(tmp, '::/64') + + tmp = get_config_value('AdvOtherConfigFlag') + self.assertEqual(tmp, 'on') + + # this is a default value + tmp = get_config_value('AdvRetransTimer') + self.assertEqual(tmp, '0') + + # this is a default value + tmp = get_config_value('AdvCurHopLimit') + self.assertEqual(tmp, '64') + + # this is a default value + tmp = get_config_value('AdvDefaultPreference') + self.assertEqual(tmp, 'medium') + + tmp = get_config_value('AdvAutonomous') + self.assertEqual(tmp, 'off') + + # this is a default value + tmp = get_config_value('AdvValidLifetime') + self.assertEqual(tmp, '2592000') + + # this is a default value + tmp = get_config_value('AdvPreferredLifetime') + self.assertEqual(tmp, '14400') + + tmp = get_config_value('AdvOnLink') + self.assertEqual(tmp, 'off') + + + + # Check for running process + self.assertTrue('radvd' in (p.name() for p in process_iter())) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From eb0c2efe324da5ff2287000a28b7270b8782f217 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 31 Jul 2020 15:27:06 +0200 Subject: ipv6: link-local: test address assignment on interfaces --- scripts/cli/base_interfaces_test.py | 42 +++++++++++++++++++++++++++++---- scripts/cli/test_interfaces_bonding.py | 37 ++++++++++++++--------------- scripts/cli/test_interfaces_bridge.py | 26 +++++++++++++------- scripts/cli/test_interfaces_ethernet.py | 1 + 4 files changed, 73 insertions(+), 33 deletions(-) diff --git a/scripts/cli/base_interfaces_test.py b/scripts/cli/base_interfaces_test.py index 8fae5970e..14ec7e137 100644 --- a/scripts/cli/base_interfaces_test.py +++ b/scripts/cli/base_interfaces_test.py @@ -15,11 +15,12 @@ import os import unittest -from vyos.configsession import ConfigSession from netifaces import ifaddresses, AF_INET, AF_INET6 -from vyos.validate import is_intf_addr_assigned, is_ipv6_link_local + +from vyos.configsession import ConfigSession from vyos.ifconfig import Interface from vyos.util import read_file +from vyos.validate import is_intf_addr_assigned, is_ipv6_link_local class BasicInterfaceTest: class BaseTest(unittest.TestCase): @@ -27,6 +28,7 @@ class BasicInterfaceTest: _test_mtu = False _test_vlan = False _test_qinq = False + _test_ipv6 = False _base_path = [] _options = {} @@ -47,12 +49,14 @@ class BasicInterfaceTest: def tearDown(self): # we should not remove ethernet from the overall CLI if 'ethernet' in self._base_path: - for intf in self._interfaces: + for interface in self._interfaces: # when using a dedicated interface to test via TEST_ETH environment # variable only this one will be cleared in the end - usable to test # ethernet interfaces via SSH - self.session.delete(self._base_path + [intf]) - self.session.set(self._base_path + [intf]) + self.session.delete(self._base_path + [interface]) + self.session.set(self._base_path + [interface, 'duplex', 'auto']) + self.session.set(self._base_path + [interface, 'speed', 'auto']) + self.session.set(self._base_path + [interface, 'smp-affinity', 'auto']) else: self.session.delete(self._base_path) @@ -117,6 +121,34 @@ class BasicInterfaceTest: self.assertTrue(is_intf_addr_assigned(intf, addr['addr'])) + def test_ipv6_link_local(self): + """ Common function for IPv6 link-local address assignemnts """ + if not self._test_ipv6: + return None + + for interface in self._interfaces: + base = self._base_path + [interface] + for option in self._options.get(interface, []): + self.session.set(base + option.split()) + + # after commit we must have an IPv6 link-local address + self.session.commit() + + for interface in self._interfaces: + for addr in ifaddresses(interface)[AF_INET6]: + self.assertTrue(is_ipv6_link_local(addr['addr'])) + + # disable IPv6 link-local address assignment + for interface in self._interfaces: + base = self._base_path + [interface] + self.session.set(base + ['ipv6', 'address', 'no-default-link-local']) + + # after commit we must have no IPv6 link-local address + self.session.commit() + + for interface in self._interfaces: + self.assertTrue(AF_INET6 not in ifaddresses(interface)) + def _mtu_test(self, intf): """ helper function to verify MTU size """ with open('/sys/class/net/{}/mtu'.format(intf), 'r') as f: diff --git a/scripts/cli/test_interfaces_bonding.py b/scripts/cli/test_interfaces_bonding.py index b4251fa15..e3d3b25ee 100755 --- a/scripts/cli/test_interfaces_bonding.py +++ b/scripts/cli/test_interfaces_bonding.py @@ -25,38 +25,37 @@ from vyos.util import read_file class BondingInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): - super().setUp() + super().setUp() - self._base_path = ['interfaces', 'bonding'] - self._interfaces = ['bond0'] - self._test_mtu = True - self._test_vlan = True - self._test_qinq = True + self._base_path = ['interfaces', 'bonding'] + self._interfaces = ['bond0'] + self._test_mtu = True + self._test_vlan = True + self._test_qinq = True + self._test_ipv6 = True - def test_add_member(self): - members = [] + self._members = [] # we need to filter out VLAN interfaces identified by a dot (.) # in their name - just in case! if 'TEST_ETH' in os.environ: - members = os.environ['TEST_ETH'].split() + self._members = os.environ['TEST_ETH'].split() else: for tmp in Section.interfaces("ethernet"): if not '.' in tmp: - members.append(tmp) + self._members.append(tmp) + + self._options['bond0'] = [] + for member in self._members: + self._options['bond0'].append(f'member interface {member}') - for interface in self._interfaces: - base = self._base_path + [interface] - for member in members: - # We can not enslave an interface when there is an address - # assigned - take care here - or find them dynamically if a user - # runs vyos-smoketest on his production device? - self.session.set(base + ['member', 'interface', member]) - self.session.commit() + def test_add_address_single(self): + """ derived method to check if member interfaces are enslaved properly """ + super().test_add_address_single() for interface in self._interfaces: slaves = read_file(f'/sys/class/net/{interface}/bonding/slaves').split() - self.assertListEqual(slaves, members) + self.assertListEqual(slaves, self._members) if __name__ == '__main__': unittest.main() diff --git a/scripts/cli/test_interfaces_bridge.py b/scripts/cli/test_interfaces_bridge.py index 4402cad68..bc0bb69c6 100755 --- a/scripts/cli/test_interfaces_bridge.py +++ b/scripts/cli/test_interfaces_bridge.py @@ -24,27 +24,35 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): def setUp(self): super().setUp() + self._test_ipv6 = True + self._base_path = ['interfaces', 'bridge'] self._interfaces = ['br0'] - def test_add_remove_member(self): - members = [] + self._members = [] # we need to filter out VLAN interfaces identified by a dot (.) # in their name - just in case! if 'TEST_ETH' in os.environ: - members = os.environ['TEST_ETH'].split() + self._members = os.environ['TEST_ETH'].split() else: for tmp in Section.interfaces("ethernet"): - if not '.' in tmp: members.append(tmp) + if not '.' in tmp: + self._members.append(tmp) - for intf in self._interfaces: - base = self._base_path + [intf] + self._options['br0'] = [] + for member in self._members: + self._options['br0'].append(f'member interface {member}') + + def test_add_remove_member(self): + for interface in self._interfaces: + base = self._base_path + [interface] self.session.set(base + ['stp']) + self.session.set(base + ['address', '192.0.2.1/24']) cost = 1000 priority = 10 # assign members to bridge interface - for member in members: + for member in self._members: base_member = base + ['member', 'interface', member] self.session.set(base_member + ['cost', str(cost)]) self.session.set(base_member + ['priority', str(priority)]) @@ -53,8 +61,8 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): self.session.commit() - for intf in self._interfaces: - self.session.delete(self._base_path + [intf, 'member']) + for interface in self._interfaces: + self.session.delete(self._base_path + [interface, 'member']) self.session.commit() diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index ccc4238e2..c31a606da 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -29,6 +29,7 @@ class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): self._test_mtu = True self._test_vlan = True self._test_qinq = True + self._test_ipv6 = True self._interfaces = [] # we need to filter out VLAN interfaces identified by a dot (.) -- cgit v1.2.3 From 6cdcbd0aae79a42e32c2f611083f287b80564930 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 3 Aug 2020 20:42:28 +0200 Subject: ssh: config file is now volatile (moved to /run) --- scripts/cli/test_service_ssh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cli/test_service_ssh.py b/scripts/cli/test_service_ssh.py index ad56fb53b..3ee498f3d 100755 --- a/scripts/cli/test_service_ssh.py +++ b/scripts/cli/test_service_ssh.py @@ -22,7 +22,7 @@ from psutil import process_iter from vyos.configsession import ConfigSession, ConfigSessionError from vyos.util import read_file -SSHD_CONF = '/etc/ssh/sshd_config' +SSHD_CONF = '/run/ssh/sshd_config' base_path = ['service', 'ssh'] def get_config_value(key): -- cgit v1.2.3 From 743627b9df6f7e8e34b544270ece4bc64a90b438 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Tue, 4 Aug 2020 22:40:53 +0200 Subject: router-advert: check 'infinity' option in script logic --- scripts/cli/test_service_router-advert.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/cli/test_service_router-advert.py b/scripts/cli/test_service_router-advert.py index cc251e355..ec2110c8a 100755 --- a/scripts/cli/test_service_router-advert.py +++ b/scripts/cli/test_service_router-advert.py @@ -47,6 +47,7 @@ class TestServiceRADVD(unittest.TestCase): def test_single(self): self.session.set(base_path + ['prefix', '::/64', 'no-on-link-flag']) self.session.set(base_path + ['prefix', '::/64', 'no-autonomous-flag']) + self.session.set(base_path + ['prefix', '::/64', 'valid-lifetime', 'infinity']) self.session.set(base_path + ['dnssl', '2001:db8::1234']) self.session.set(base_path + ['other-config-flag']) @@ -80,7 +81,7 @@ class TestServiceRADVD(unittest.TestCase): # this is a default value tmp = get_config_value('AdvValidLifetime') - self.assertEqual(tmp, '2592000') + self.assertEqual(tmp, 'infinity') # this is a default value tmp = get_config_value('AdvPreferredLifetime') -- cgit v1.2.3 From 9455ae27d5ea9517867c2dff3142db31873cbfb4 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 15 Aug 2020 21:40:47 +0200 Subject: ethernet: check interface disable state --- scripts/cli/test_interfaces_ethernet.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/scripts/cli/test_interfaces_ethernet.py b/scripts/cli/test_interfaces_ethernet.py index c31a606da..761ec7506 100755 --- a/scripts/cli/test_interfaces_ethernet.py +++ b/scripts/cli/test_interfaces_ethernet.py @@ -42,5 +42,27 @@ class EthernetInterfaceTest(BasicInterfaceTest.BaseTest): if not '.' in tmp: self._interfaces.append(tmp) + def test_dhcp_disable(self): + """ + When interface is configured as admin down, it must be admin down even + """ + for interface in self._interfaces: + self.session.set(self._base_path + [interface, 'disable']) + for option in self._options.get(interface, []): + self.session.set(self._base_path + [interface] + option.split()) + + # Also enable DHCP (ISC DHCP always places interface in admin up + # state so we check that we do not start DHCP client. + # https://phabricator.vyos.net/T2767 + self.session.set(self._base_path + [interface, 'address', 'dhcp']) + + self.session.commit() + + # Validate interface state + for interface in self._interfaces: + with open(f'/sys/class/net/{interface}/flags', 'r') as f: + flags = f.read() + self.assertEqual(int(flags, 16) & 1, 0) + if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 65e6432298811d4a7586b7e299cd482a97226227 Mon Sep 17 00:00:00 2001 From: DmitriyEshenko Date: Wed, 19 Aug 2020 11:02:13 +0000 Subject: anyconnect: T2812: add basic testing --- scripts/cli/test_vpn_anyconnect.py | 58 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100755 scripts/cli/test_vpn_anyconnect.py diff --git a/scripts/cli/test_vpn_anyconnect.py b/scripts/cli/test_vpn_anyconnect.py new file mode 100755 index 000000000..dd8ab1609 --- /dev/null +++ b/scripts/cli/test_vpn_anyconnect.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import re +import os +import unittest + +from psutil import process_iter +from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.util import read_file + +OCSERV_CONF = '/run/ocserv/ocserv.conf' +base_path = ['vpn', 'anyconnect'] +cert = '/etc/ssl/certs/ssl-cert-snakeoil.pem' +cert_key = '/etc/ssl/private/ssl-cert-snakeoil.key' + +class TestVpnAnyconnect(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + + def tearDown(self): + # Delete vpn anyconnect configuration + self.session.delete(base_path) + self.session.commit() + + del self.session + + def test_vpn(self): + user = 'vyos_user' + password = 'vyos_pass' + self.session.delete(base_path) + self.session.set(base_path + ["authentication", "local-users", "username", user, "password", password]) + self.session.set(base_path + ["authentication", "mode", "local"]) + self.session.set(base_path + ["network-settings", "client-ip-settings", "subnet", "192.0.2.0/24"]) + self.session.set(base_path + ["ssl", "ca-cert-file", cert]) + self.session.set(base_path + ["ssl", "cert-file", cert]) + self.session.set(base_path + ["ssl", "key-file", cert_key]) + + self.session.commit() + + # Check for running process + self.assertTrue("ocserv-main" in (p.name() for p in process_iter())) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 87693ce61819b82b6496cdde3d59835aa81cf6a9 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 23 Aug 2020 01:16:03 +0200 Subject: pppoe: sync to new dhcpv6-pd cli --- scripts/cli/test_interfaces_pppoe.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/cli/test_interfaces_pppoe.py b/scripts/cli/test_interfaces_pppoe.py index d2f6c9b16..7e26b7dac 100755 --- a/scripts/cli/test_interfaces_pppoe.py +++ b/scripts/cli/test_interfaces_pppoe.py @@ -111,11 +111,10 @@ class PPPoEInterfaceTest(unittest.TestCase): self.session.set(base_path + [interface, 'ipv6', 'enable']) # prefix delegation stuff - dhcpv6_pd_base = base_path + [interface, 'dhcpv6-options', 'prefix-delegation'] + dhcpv6_pd_base = base_path + [interface, 'dhcpv6-options', 'pd', '0'] self.session.set(dhcpv6_pd_base + ['length', '56']) self.session.set(dhcpv6_pd_base + ['interface', self._source_interface, 'address', address]) self.session.set(dhcpv6_pd_base + ['interface', self._source_interface, 'sla-id', sla_id]) - self.session.set(dhcpv6_pd_base + ['interface', self._source_interface, 'sla-len', sla_len]) # commit changes self.session.commit() -- cgit v1.2.3 From bd7f30dcd55866de125af012ac63b96dc226a1f1 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 23 Aug 2020 13:26:19 +0200 Subject: wireless: validate hostapd/wpa_supplicant is running --- scripts/cli/test_interfaces_wireless.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/scripts/cli/test_interfaces_wireless.py b/scripts/cli/test_interfaces_wireless.py index ff293ac84..fae233244 100755 --- a/scripts/cli/test_interfaces_wireless.py +++ b/scripts/cli/test_interfaces_wireless.py @@ -18,6 +18,7 @@ import os import unittest from base_interfaces_test import BasicInterfaceTest +from psutil import process_iter from vyos.util import check_kmod class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): @@ -38,15 +39,19 @@ class WirelessInterfaceTest(BasicInterfaceTest.BaseTest): self._interfaces = list(self._options) self.session.set(['system', 'wifi-regulatory-domain', 'SE']) - def test_wifi_client(self): - """ test creation of a wireless station """ - for intf in self._interfaces: - # prepare interfaces - for option in self._options.get(intf, []): - self.session.set(self._base_path + [intf] + option.split()) + def test_add_address_single(self): + """ derived method to check if member interfaces are enslaved properly """ + super().test_add_address_single() - # commit changes - self.session.commit() + for option, option_value in self._options.items(): + if 'type access-point' in option_value: + # Check for running process + self.assertIn('hostapd', (p.name() for p in process_iter())) + elif 'type station' in option_value: + # Check for running process + self.assertIn('wpa_supplicant', (p.name() for p in process_iter())) + else: + self.assertTrue(False) if __name__ == '__main__': check_kmod('mac80211_hwsim') -- cgit v1.2.3 From 11da3f091a98436044e157892cdefd41a2358e42 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 23 Aug 2020 14:45:15 +0200 Subject: pppoe: validate dhcpv6 client will be started --- scripts/cli/test_interfaces_pppoe.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/cli/test_interfaces_pppoe.py b/scripts/cli/test_interfaces_pppoe.py index 7e26b7dac..822f05de6 100755 --- a/scripts/cli/test_interfaces_pppoe.py +++ b/scripts/cli/test_interfaces_pppoe.py @@ -152,7 +152,11 @@ class PPPoEInterfaceTest(unittest.TestCase): self.assertTrue(running) # We can not check if wide-dhcpv6 process is running as it is started - # after the PPP interface gets a link to the ISP + # after the PPP interface gets a link to the ISP - but we can see if + # it would be started by the scripts + tmp = read_file(f'/etc/ppp/ipv6-up.d/1000-vyos-pppoe-{interface}') + tmp = re.findall(f'systemctl start dhcp6c@{interface}.service', tmp) + self.assertTrue(tmp) if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 049a87ed9940d22e8bfd39947ba1a92dee82b04a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 23 Aug 2020 20:26:20 +0200 Subject: pppoe-server: initial smoketest with local and radius auth --- scripts/cli/test_service_pppoe-server.py | 154 +++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100755 scripts/cli/test_service_pppoe-server.py diff --git a/scripts/cli/test_service_pppoe-server.py b/scripts/cli/test_service_pppoe-server.py new file mode 100755 index 000000000..318b6530a --- /dev/null +++ b/scripts/cli/test_service_pppoe-server.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import re +import os +import unittest + +from configparser import ConfigParser +from psutil import process_iter +from vyos.configsession import ConfigSession +from vyos.configsession import ConfigSessionError + +base_path = ['service', 'pppoe-server'] +local_if = ['interfaces', 'dummy', 'dum667'] +pppoe_conf = '/run/accel-pppd/pppoe.conf' + +ac_name = 'ACN' +subnet = '172.18.0.0/24' +gateway = '192.0.2.1' +nameserver = '9.9.9.9' +mtu = '1492' +interface = 'eth0' + +class TestServicePPPoEServer(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + # ensure we can also run this test on a live system - so lets clean + # out the current configuration :) + self.session.delete(base_path) + + def tearDown(self): + self.session.delete(base_path) + self.session.delete(local_if) + self.session.commit() + del self.session + + def verify(self, conf): + # validate some common values in the configuration + for tmp in ['log_syslog', 'pppoe', 'chap-secrets', 'ippool', 'ipv6pool', + 'ipv6_nd', 'ipv6_dhcp', 'auth_mschap_v2', 'auth_mschap_v1', + 'auth_chap_md5', 'auth_pap', 'shaper']: + # Settings without values provide None + self.assertEqual(conf['modules'][tmp], None) + + # check Access Concentrator setting + self.assertTrue(conf['pppoe']['ac-name'] == ac_name) + self.assertTrue(conf['pppoe'].getboolean('verbose')) + self.assertTrue(conf['pppoe']['interface'], interface) + + # check configured subnet + self.assertEqual(conf['ip-pool'][subnet], None) + self.assertEqual(conf['ip-pool']['gw-ip-address'], gateway) + + # check ppp + self.assertTrue(conf['ppp'].getboolean('verbose')) + self.assertTrue(conf['ppp'].getboolean('check-ip')) + self.assertFalse(conf['ppp'].getboolean('ccp')) + self.assertEqual(conf['ppp']['min-mtu'], mtu) + self.assertEqual(conf['ppp']['mtu'], mtu) + self.assertEqual(conf['ppp']['mppe'], 'prefer') + self.assertEqual(conf['ppp']['lcp-echo-interval'], '30') + self.assertEqual(conf['ppp']['lcp-echo-timeout'], '0') + self.assertEqual(conf['ppp']['lcp-echo-failure'], '3') + + def test_local_auth(self): + """ Test configuration of local authentication for PPPoE server """ + self.session.set(local_if + ['address', '192.0.2.1/32']) + self.session.set(base_path + ['access-concentrator', ac_name]) + self.session.set(base_path + ['authentication', 'local-users', 'username', 'vyos', 'password', 'vyos']) + self.session.set(base_path + ['authentication', 'mode', 'local']) + self.session.set(base_path + ['client-ip-pool', 'subnet', subnet]) + self.session.set(base_path + ['name-server', nameserver]) + self.session.set(base_path + ['interface', interface]) + self.session.set(base_path + ['local-ip', gateway]) + + # commit changes + self.session.commit() + + # Validate configuration values + conf = ConfigParser(allow_no_value=True) + conf.read(pppoe_conf) + + # basic verification + self.verify(conf) + + # check auth + self.assertEqual(conf['chap-secrets']['chap-secrets'], '/run/accel-pppd/pppoe.chap-secrets') + self.assertEqual(conf['chap-secrets']['gw-ip-address'], gateway) + + # Check for running process + self.assertTrue('accel-pppd' in (p.name() for p in process_iter())) + + def test_radius_auth(self): + """ Test configuration of RADIUS authentication for PPPoE server """ + radius_server = '192.0.2.22' + radius_key = 'secretVyOS' + radius_port = '2000' + radius_port_acc = '3000' + + self.session.set(local_if + ['address', '192.0.2.1/32']) + self.session.set(base_path + ['access-concentrator', ac_name]) + self.session.set(base_path + ['authentication', 'radius', 'server', radius_server, 'key', radius_key]) + self.session.set(base_path + ['authentication', 'radius', 'server', radius_server, 'port', radius_port]) + self.session.set(base_path + ['authentication', 'radius', 'server', radius_server, 'acct-port', radius_port_acc]) + + self.session.set(base_path + ['authentication', 'mode', 'radius']) + self.session.set(base_path + ['client-ip-pool', 'subnet', subnet]) + self.session.set(base_path + ['name-server', nameserver]) + self.session.set(base_path + ['interface', interface]) + self.session.set(base_path + ['local-ip', gateway]) + + # commit changes + self.session.commit() + + # Validate configuration values + conf = ConfigParser(allow_no_value=True) + conf.read(pppoe_conf) + + # basic verification + self.verify(conf) + + # check auth + self.assertTrue(conf['radius'].getboolean('verbose')) + self.assertTrue(conf['radius']['acct-timeout'], '3') + self.assertTrue(conf['radius']['timeout'], '3') + self.assertTrue(conf['radius']['max-try'], '3') + self.assertTrue(conf['radius']['gw-ip-address'], gateway) + + server = conf['radius']['server'].split(',') + self.assertEqual(radius_server, server[0]) + self.assertEqual(radius_key, server[1]) + self.assertEqual(f'auth-port={radius_port}', server[2]) + self.assertEqual(f'acct-port={radius_port_acc}', server[3]) + self.assertEqual(f'req-limit=0', server[4]) + self.assertEqual(f'fail-time=0', server[5]) + + # Check for running process + self.assertTrue('accel-pppd' in (p.name() for p in process_iter())) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 71a2e3fad3bd773391196f84171c606cad2e3516 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 23 Aug 2020 20:47:20 +0200 Subject: lcd: adapt test to new CLI design --- scripts/cli/test_system_display.py | 135 ------------------------------------- scripts/cli/test_system_lcd.py | 135 +++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 135 deletions(-) delete mode 100755 scripts/cli/test_system_display.py create mode 100755 scripts/cli/test_system_lcd.py diff --git a/scripts/cli/test_system_display.py b/scripts/cli/test_system_display.py deleted file mode 100755 index f9fb00aa5..000000000 --- a/scripts/cli/test_system_display.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2020 Francois Mertz fireboxled@gmail.com -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 or later as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import re -import os -import unittest -import configparser - -from psutil import process_iter -from vyos.configsession import ConfigSession, ConfigSessionError -from vyos.util import read_file - -base_path = ['system', 'display'] - -""" - system display model (sdec|ezio) - system display show host (cpu|cpu-all|cpu-hist|disk|load-hist|memory|proc|uptime) - network interface alias - units (bps|Bps|pps) - clock (big|mini|date-time) - title - - system display time - system display hello - system display bye - system display disabled -""" - -class SystemDisplayTest(unittest.TestCase): - def setUp(self): - self.session = ConfigSession(os.getpid()) - - def tearDown(self): - self.session.delete(base_path) - self.session.commit() - del self.session - - def test_system_display(self): - # configure some system display - self.session.set(base_path + ['hello', 'Welcome to VyOS']) - self.session.set(base_path + ['bye', 'Bye from VyOS']) - self.session.set(base_path + ['time', '30']) - - # check validate() - a model and a show are required - with self.assertRaises(ConfigSessionError): - self.session.commit() - - self.session.set(base_path + ['model', 'ezio']) - - # check validate() - a show required - with self.assertRaises(ConfigSessionError): - self.session.commit() - - self.session.set(base_path + ['show', 'clock', 'big']) - - self.session.set(base_path + ['show', 'network', 'units', 'pps']) - self.session.set(base_path + ['show', 'network', 'interface', 'eth0', 'alias', 'WAN']) - self.session.set(base_path + ['show', 'network', 'interface', 'eth1', 'alias', 'LAN']) - self.session.set(base_path + ['show', 'network', 'interface', 'eth2', 'alias', 'WIFI']) - # One too many - self.session.set(base_path + ['show', 'network', 'interface', 'eth3']) - - # check validate() - more then 3 interfaces - with self.assertRaises(ConfigSessionError): - self.session.commit() - - self.session.delete(base_path + ['show', 'network', 'interface', 'eth3']) - - # commit changes - self.session.commit() - - # load up ini-styled LCDd.conf - LCDd_conf = configparser.ConfigParser() - LCDd_conf.read('/run/LCDd/LCDd.lo.conf') - - # Check settings made it into LCDd.conf - self.assertTrue(LCDd_conf['server']['Driver'] == 'hd44780') - self.assertTrue(LCDd_conf['server']['Hello'] == '"Welcome to VyOS"') - self.assertTrue(LCDd_conf['server']['GoodBye'] == '"Bye from VyOS"') - self.assertTrue(LCDd_conf['server']['WaitTime'] == '30') - - self.assertTrue(LCDd_conf['hd44780']['ConnectionType'] == 'ezio') - self.assertTrue(LCDd_conf['hd44780']['Keypad'] == 'yes') - self.assertTrue(LCDd_conf['hd44780']['Size'] == '16x2') - self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_1'] == 'Enter') - self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_2'] == 'Up') - self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_3'] == 'Down') - self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_4'] == 'Escape') - #self.assertTrue(LCDd_conf['hd44780']['Device'] == '/dev/ttyS1') - - # load up ini-styled lcdproc.conf configuration file - lcdproc_conf = configparser.ConfigParser() - - lcdproc_conf.read('/run/lcdproc/lcdproc.lo.conf') - # clock - self.assertTrue(lcdproc_conf['TimeDate']['Active'] == 'false') - self.assertTrue(lcdproc_conf['BigClock']['Active'] == 'true') - self.assertTrue(lcdproc_conf['MiniClock']['Active'] == 'false') - # host - self.assertTrue(lcdproc_conf['CPU']['Active'] == 'false') - self.assertTrue(lcdproc_conf['Memory']['Active'] == 'false') - self.assertTrue(lcdproc_conf['Load']['Active'] == 'false') - # network - self.assertTrue(lcdproc_conf['Iface']['Active'] == 'true') - self.assertTrue(lcdproc_conf['Iface']['Interface0'] == 'eth0') - self.assertTrue(lcdproc_conf['Iface']['Alias0'] == 'WAN') - self.assertTrue(lcdproc_conf['Iface']['Interface1'] == 'eth1') - self.assertTrue(lcdproc_conf['Iface']['Alias1'] == 'LAN') - self.assertTrue(lcdproc_conf['Iface']['Interface2'] == 'eth2') - self.assertTrue(lcdproc_conf['Iface']['Alias2'] == 'WIFI') - self.assertTrue(lcdproc_conf['Iface']['unit'] == 'packet') - # Check if LCdd and lcdproc are running - running = 0 - for p in process_iter(): - if p.name() in ['lcdproc', 'LCDd']: - running += 1 - - # both processes running - self.assertTrue(running == 2) - -if __name__ == '__main__': - unittest.main() diff --git a/scripts/cli/test_system_lcd.py b/scripts/cli/test_system_lcd.py new file mode 100755 index 000000000..f9fb00aa5 --- /dev/null +++ b/scripts/cli/test_system_lcd.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 Francois Mertz fireboxled@gmail.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import re +import os +import unittest +import configparser + +from psutil import process_iter +from vyos.configsession import ConfigSession, ConfigSessionError +from vyos.util import read_file + +base_path = ['system', 'display'] + +""" + system display model (sdec|ezio) + system display show host (cpu|cpu-all|cpu-hist|disk|load-hist|memory|proc|uptime) + network interface alias + units (bps|Bps|pps) + clock (big|mini|date-time) + title + + system display time + system display hello + system display bye + system display disabled +""" + +class SystemDisplayTest(unittest.TestCase): + def setUp(self): + self.session = ConfigSession(os.getpid()) + + def tearDown(self): + self.session.delete(base_path) + self.session.commit() + del self.session + + def test_system_display(self): + # configure some system display + self.session.set(base_path + ['hello', 'Welcome to VyOS']) + self.session.set(base_path + ['bye', 'Bye from VyOS']) + self.session.set(base_path + ['time', '30']) + + # check validate() - a model and a show are required + with self.assertRaises(ConfigSessionError): + self.session.commit() + + self.session.set(base_path + ['model', 'ezio']) + + # check validate() - a show required + with self.assertRaises(ConfigSessionError): + self.session.commit() + + self.session.set(base_path + ['show', 'clock', 'big']) + + self.session.set(base_path + ['show', 'network', 'units', 'pps']) + self.session.set(base_path + ['show', 'network', 'interface', 'eth0', 'alias', 'WAN']) + self.session.set(base_path + ['show', 'network', 'interface', 'eth1', 'alias', 'LAN']) + self.session.set(base_path + ['show', 'network', 'interface', 'eth2', 'alias', 'WIFI']) + # One too many + self.session.set(base_path + ['show', 'network', 'interface', 'eth3']) + + # check validate() - more then 3 interfaces + with self.assertRaises(ConfigSessionError): + self.session.commit() + + self.session.delete(base_path + ['show', 'network', 'interface', 'eth3']) + + # commit changes + self.session.commit() + + # load up ini-styled LCDd.conf + LCDd_conf = configparser.ConfigParser() + LCDd_conf.read('/run/LCDd/LCDd.lo.conf') + + # Check settings made it into LCDd.conf + self.assertTrue(LCDd_conf['server']['Driver'] == 'hd44780') + self.assertTrue(LCDd_conf['server']['Hello'] == '"Welcome to VyOS"') + self.assertTrue(LCDd_conf['server']['GoodBye'] == '"Bye from VyOS"') + self.assertTrue(LCDd_conf['server']['WaitTime'] == '30') + + self.assertTrue(LCDd_conf['hd44780']['ConnectionType'] == 'ezio') + self.assertTrue(LCDd_conf['hd44780']['Keypad'] == 'yes') + self.assertTrue(LCDd_conf['hd44780']['Size'] == '16x2') + self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_1'] == 'Enter') + self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_2'] == 'Up') + self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_3'] == 'Down') + self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_4'] == 'Escape') + #self.assertTrue(LCDd_conf['hd44780']['Device'] == '/dev/ttyS1') + + # load up ini-styled lcdproc.conf configuration file + lcdproc_conf = configparser.ConfigParser() + + lcdproc_conf.read('/run/lcdproc/lcdproc.lo.conf') + # clock + self.assertTrue(lcdproc_conf['TimeDate']['Active'] == 'false') + self.assertTrue(lcdproc_conf['BigClock']['Active'] == 'true') + self.assertTrue(lcdproc_conf['MiniClock']['Active'] == 'false') + # host + self.assertTrue(lcdproc_conf['CPU']['Active'] == 'false') + self.assertTrue(lcdproc_conf['Memory']['Active'] == 'false') + self.assertTrue(lcdproc_conf['Load']['Active'] == 'false') + # network + self.assertTrue(lcdproc_conf['Iface']['Active'] == 'true') + self.assertTrue(lcdproc_conf['Iface']['Interface0'] == 'eth0') + self.assertTrue(lcdproc_conf['Iface']['Alias0'] == 'WAN') + self.assertTrue(lcdproc_conf['Iface']['Interface1'] == 'eth1') + self.assertTrue(lcdproc_conf['Iface']['Alias1'] == 'LAN') + self.assertTrue(lcdproc_conf['Iface']['Interface2'] == 'eth2') + self.assertTrue(lcdproc_conf['Iface']['Alias2'] == 'WIFI') + self.assertTrue(lcdproc_conf['Iface']['unit'] == 'packet') + # Check if LCdd and lcdproc are running + running = 0 + for p in process_iter(): + if p.name() in ['lcdproc', 'LCDd']: + running += 1 + + # both processes running + self.assertTrue(running == 2) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From a4b064ea73f0d6255f868ad3dec620cad8060f9a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 23 Aug 2020 22:12:00 +0200 Subject: lcd: adjust to cli changes --- scripts/cli/test_system_lcd.py | 103 +++++------------------------------------ 1 file changed, 11 insertions(+), 92 deletions(-) diff --git a/scripts/cli/test_system_lcd.py b/scripts/cli/test_system_lcd.py index f9fb00aa5..931a91c53 100755 --- a/scripts/cli/test_system_lcd.py +++ b/scripts/cli/test_system_lcd.py @@ -14,32 +14,16 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import re import os import unittest -import configparser +from configparser import ConfigParser from psutil import process_iter -from vyos.configsession import ConfigSession, ConfigSessionError -from vyos.util import read_file +from vyos.configsession import ConfigSession -base_path = ['system', 'display'] +base_path = ['system', 'lcd'] -""" - system display model (sdec|ezio) - system display show host (cpu|cpu-all|cpu-hist|disk|load-hist|memory|proc|uptime) - network interface alias - units (bps|Bps|pps) - clock (big|mini|date-time) - title - - system display time - system display hello - system display bye - system display disabled -""" - -class SystemDisplayTest(unittest.TestCase): +class TestSystemLCD(unittest.TestCase): def setUp(self): self.session = ConfigSession(os.getpid()) @@ -50,86 +34,21 @@ class SystemDisplayTest(unittest.TestCase): def test_system_display(self): # configure some system display - self.session.set(base_path + ['hello', 'Welcome to VyOS']) - self.session.set(base_path + ['bye', 'Bye from VyOS']) - self.session.set(base_path + ['time', '30']) - - # check validate() - a model and a show are required - with self.assertRaises(ConfigSessionError): - self.session.commit() - - self.session.set(base_path + ['model', 'ezio']) - - # check validate() - a show required - with self.assertRaises(ConfigSessionError): - self.session.commit() - - self.session.set(base_path + ['show', 'clock', 'big']) - - self.session.set(base_path + ['show', 'network', 'units', 'pps']) - self.session.set(base_path + ['show', 'network', 'interface', 'eth0', 'alias', 'WAN']) - self.session.set(base_path + ['show', 'network', 'interface', 'eth1', 'alias', 'LAN']) - self.session.set(base_path + ['show', 'network', 'interface', 'eth2', 'alias', 'WIFI']) - # One too many - self.session.set(base_path + ['show', 'network', 'interface', 'eth3']) - - # check validate() - more then 3 interfaces - with self.assertRaises(ConfigSessionError): - self.session.commit() - - self.session.delete(base_path + ['show', 'network', 'interface', 'eth3']) + self.session.set(base_path + ['device', 'ttyS1']) + self.session.set(base_path + ['model', 'cfa-533']) # commit changes self.session.commit() # load up ini-styled LCDd.conf - LCDd_conf = configparser.ConfigParser() - LCDd_conf.read('/run/LCDd/LCDd.lo.conf') - - # Check settings made it into LCDd.conf - self.assertTrue(LCDd_conf['server']['Driver'] == 'hd44780') - self.assertTrue(LCDd_conf['server']['Hello'] == '"Welcome to VyOS"') - self.assertTrue(LCDd_conf['server']['GoodBye'] == '"Bye from VyOS"') - self.assertTrue(LCDd_conf['server']['WaitTime'] == '30') - - self.assertTrue(LCDd_conf['hd44780']['ConnectionType'] == 'ezio') - self.assertTrue(LCDd_conf['hd44780']['Keypad'] == 'yes') - self.assertTrue(LCDd_conf['hd44780']['Size'] == '16x2') - self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_1'] == 'Enter') - self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_2'] == 'Up') - self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_3'] == 'Down') - self.assertTrue(LCDd_conf['hd44780']['KeyMatrix_4_4'] == 'Escape') - #self.assertTrue(LCDd_conf['hd44780']['Device'] == '/dev/ttyS1') - - # load up ini-styled lcdproc.conf configuration file - lcdproc_conf = configparser.ConfigParser() + conf = ConfigParser() + conf.read('/run/LCDd/LCDd.conf') - lcdproc_conf.read('/run/lcdproc/lcdproc.lo.conf') - # clock - self.assertTrue(lcdproc_conf['TimeDate']['Active'] == 'false') - self.assertTrue(lcdproc_conf['BigClock']['Active'] == 'true') - self.assertTrue(lcdproc_conf['MiniClock']['Active'] == 'false') - # host - self.assertTrue(lcdproc_conf['CPU']['Active'] == 'false') - self.assertTrue(lcdproc_conf['Memory']['Active'] == 'false') - self.assertTrue(lcdproc_conf['Load']['Active'] == 'false') - # network - self.assertTrue(lcdproc_conf['Iface']['Active'] == 'true') - self.assertTrue(lcdproc_conf['Iface']['Interface0'] == 'eth0') - self.assertTrue(lcdproc_conf['Iface']['Alias0'] == 'WAN') - self.assertTrue(lcdproc_conf['Iface']['Interface1'] == 'eth1') - self.assertTrue(lcdproc_conf['Iface']['Alias1'] == 'LAN') - self.assertTrue(lcdproc_conf['Iface']['Interface2'] == 'eth2') - self.assertTrue(lcdproc_conf['Iface']['Alias2'] == 'WIFI') - self.assertTrue(lcdproc_conf['Iface']['unit'] == 'packet') - # Check if LCdd and lcdproc are running - running = 0 - for p in process_iter(): - if p.name() in ['lcdproc', 'LCDd']: - running += 1 + self.assertEqual(conf['CFontzPacket']['Model'], '533') + self.assertEqual(conf['CFontzPacket']['Device'], '/dev/ttyS1') # both processes running - self.assertTrue(running == 2) + self.assertTrue('LCDd' in (p.name() for p in process_iter())) if __name__ == '__main__': unittest.main() -- cgit v1.2.3 From 756c9153e683be83ab1f2786a72e6ed1e65dd3b5 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 26 Aug 2020 20:03:54 +0200 Subject: pppoe-server: test some more values --- scripts/cli/test_service_pppoe-server.py | 37 +++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/scripts/cli/test_service_pppoe-server.py b/scripts/cli/test_service_pppoe-server.py index 318b6530a..901ca792d 100755 --- a/scripts/cli/test_service_pppoe-server.py +++ b/scripts/cli/test_service_pppoe-server.py @@ -67,25 +67,33 @@ class TestServicePPPoEServer(unittest.TestCase): # check ppp self.assertTrue(conf['ppp'].getboolean('verbose')) self.assertTrue(conf['ppp'].getboolean('check-ip')) - self.assertFalse(conf['ppp'].getboolean('ccp')) self.assertEqual(conf['ppp']['min-mtu'], mtu) self.assertEqual(conf['ppp']['mtu'], mtu) - self.assertEqual(conf['ppp']['mppe'], 'prefer') self.assertEqual(conf['ppp']['lcp-echo-interval'], '30') self.assertEqual(conf['ppp']['lcp-echo-timeout'], '0') self.assertEqual(conf['ppp']['lcp-echo-failure'], '3') - def test_local_auth(self): - """ Test configuration of local authentication for PPPoE server """ + def basic_config(self): self.session.set(local_if + ['address', '192.0.2.1/32']) + self.session.set(base_path + ['access-concentrator', ac_name]) - self.session.set(base_path + ['authentication', 'local-users', 'username', 'vyos', 'password', 'vyos']) self.session.set(base_path + ['authentication', 'mode', 'local']) self.session.set(base_path + ['client-ip-pool', 'subnet', subnet]) self.session.set(base_path + ['name-server', nameserver]) self.session.set(base_path + ['interface', interface]) self.session.set(base_path + ['local-ip', gateway]) + def test_local_auth(self): + """ Test configuration of local authentication for PPPoE server """ + self.basic_config() + # authentication + self.session.set(base_path + ['authentication', 'local-users', 'username', 'vyos', 'password', 'vyos']) + self.session.set(base_path + ['authentication', 'mode', 'local']) + # other settings + self.session.set(base_path + ['ppp-options', 'ccp']) + self.session.set(base_path + ['ppp-options', 'mppe', 'require']) + self.session.set(base_path + ['limits', 'connection-limit', '20/min']) + # commit changes self.session.commit() @@ -100,6 +108,13 @@ class TestServicePPPoEServer(unittest.TestCase): self.assertEqual(conf['chap-secrets']['chap-secrets'], '/run/accel-pppd/pppoe.chap-secrets') self.assertEqual(conf['chap-secrets']['gw-ip-address'], gateway) + # check pado + self.assertEqual(conf['ppp']['mppe'], 'require') + self.assertTrue(conf['ppp'].getboolean('ccp')) + + # check other settings + self.assertEqual(conf['connlimit']['limit'], '20/min') + # Check for running process self.assertTrue('accel-pppd' in (p.name() for p in process_iter())) @@ -110,17 +125,11 @@ class TestServicePPPoEServer(unittest.TestCase): radius_port = '2000' radius_port_acc = '3000' - self.session.set(local_if + ['address', '192.0.2.1/32']) - self.session.set(base_path + ['access-concentrator', ac_name]) + self.basic_config() self.session.set(base_path + ['authentication', 'radius', 'server', radius_server, 'key', radius_key]) self.session.set(base_path + ['authentication', 'radius', 'server', radius_server, 'port', radius_port]) self.session.set(base_path + ['authentication', 'radius', 'server', radius_server, 'acct-port', radius_port_acc]) - self.session.set(base_path + ['authentication', 'mode', 'radius']) - self.session.set(base_path + ['client-ip-pool', 'subnet', subnet]) - self.session.set(base_path + ['name-server', nameserver]) - self.session.set(base_path + ['interface', interface]) - self.session.set(base_path + ['local-ip', gateway]) # commit changes self.session.commit() @@ -147,6 +156,10 @@ class TestServicePPPoEServer(unittest.TestCase): self.assertEqual(f'req-limit=0', server[4]) self.assertEqual(f'fail-time=0', server[5]) + # check defaults + self.assertEqual(conf['ppp']['mppe'], 'prefer') + self.assertFalse(conf['ppp'].getboolean('ccp')) + # Check for running process self.assertTrue('accel-pppd' in (p.name() for p in process_iter())) -- cgit v1.2.3