From 2d6dff014e5ee531da341584f98d1ea8121c55a2 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Mon, 27 Jul 2015 15:23:38 +0200 Subject: [PATCH 01/16] Added lxcpp's license [Feature] lxcpp is on LGPL 2.1 license [Cause] N/A [Solution] N/A [Verification] N/A Change-Id: Ia1916f4ba8ea815467ea958020db401f46cfa5cb --- libs/lxcpp/CMakeLists.txt | 22 +- libs/lxcpp/LICENSE | 458 ++++++++++++++++++++++++++++++++++++++++++ libs/lxcpp/container-impl.cpp | 23 +-- libs/lxcpp/container-impl.hpp | 23 +-- libs/lxcpp/container.hpp | 23 +-- libs/lxcpp/exception.hpp | 23 +-- libs/lxcpp/lxcpp.cpp | 23 +-- libs/lxcpp/lxcpp.hpp | 23 +-- 8 files changed, 535 insertions(+), 83 deletions(-) create mode 100644 libs/lxcpp/LICENSE diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt index fa63074..74522a3 100644 --- a/libs/lxcpp/CMakeLists.txt +++ b/libs/lxcpp/CMakeLists.txt @@ -1,17 +1,17 @@ -# Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +# Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1 as published by the Free Software Foundation. # -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 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 # # @file CMakeLists.txt # @author Mateusz Malicki (m.malicki2@samsung.com) diff --git a/libs/lxcpp/LICENSE b/libs/lxcpp/LICENSE new file mode 100644 index 0000000..fe17b67 --- /dev/null +++ b/libs/lxcpp/LICENSE @@ -0,0 +1,458 @@ + 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 \ No newline at end of file diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp index c0fd907..a7f404e 100644 --- a/libs/lxcpp/container-impl.cpp +++ b/libs/lxcpp/container-impl.cpp @@ -1,19 +1,18 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved * - * Contact: Mateusz Malicki + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License + * 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 */ /** diff --git a/libs/lxcpp/container-impl.hpp b/libs/lxcpp/container-impl.hpp index e53684e..9b9b1ea 100644 --- a/libs/lxcpp/container-impl.hpp +++ b/libs/lxcpp/container-impl.hpp @@ -1,19 +1,18 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved * - * Contact: Mateusz Malicki + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License + * 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 */ /** diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp index b3ce50a..36e877e 100644 --- a/libs/lxcpp/container.hpp +++ b/libs/lxcpp/container.hpp @@ -1,19 +1,18 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved * - * Contact: Mateusz Malicki + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License + * 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 */ /** diff --git a/libs/lxcpp/exception.hpp b/libs/lxcpp/exception.hpp index e841c0b..1e3ce4c 100644 --- a/libs/lxcpp/exception.hpp +++ b/libs/lxcpp/exception.hpp @@ -1,19 +1,18 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved * - * Contact: Mateusz Malicki + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License + * 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 */ /** diff --git a/libs/lxcpp/lxcpp.cpp b/libs/lxcpp/lxcpp.cpp index a81f8f9..3cb906c 100644 --- a/libs/lxcpp/lxcpp.cpp +++ b/libs/lxcpp/lxcpp.cpp @@ -1,19 +1,18 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved * - * Contact: Mateusz Malicki + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License + * 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 */ /** diff --git a/libs/lxcpp/lxcpp.hpp b/libs/lxcpp/lxcpp.hpp index a6b8437..8037d3c 100644 --- a/libs/lxcpp/lxcpp.hpp +++ b/libs/lxcpp/lxcpp.hpp @@ -1,19 +1,18 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved * - * Contact: Mateusz Malicki + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License + * 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 */ /** -- 2.7.4 From d58f1b9ef9e764daae6079beb920f3570081c06e Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 27 Jul 2015 11:20:37 +0200 Subject: [PATCH 02/16] Hide VsmZone and VsmNetdevType structs from API [Feature] N/A [Cause] Make it easier to change them in the future without breaking the ABI. Also remove duplicate related API function from the code. [Solution] N/A [Verification] N/A Change-Id: Ib0ec7374ee0f94cd88e2998e9d10f18ae094ee98 --- cli/command-line-interface.cpp | 68 +++++++++++++---------------- client/vasum-client-impl.cpp | 23 +++------- client/vasum-client-impl.hpp | 27 +++++++++--- client/vasum-client.cpp | 59 +++++++++++++++++++------ client/vasum-client.h | 81 +++++++++++++++++++++-------------- tests/unit_tests/client/ut-client.cpp | 25 ++--------- wrapper/wrapper.cpp | 20 +++++---- 7 files changed, 167 insertions(+), 136 deletions(-) diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp index 29dd4a3..1338afe 100644 --- a/cli/command-line-interface.cpp +++ b/cli/command-line-interface.cpp @@ -51,17 +51,9 @@ VsmClient CommandLineInterface::client = NULL; namespace { -template -string stringAsInStream(const T& value) +std::string zoneStateToString(const VsmZoneState& state) { - std::ostringstream stream; - stream << value; - return stream.str(); -} - -ostream& operator<<(ostream& out, const VsmZoneState& state) -{ - const char* name; + std::string name; switch (state) { case STOPPED: name = "STOPPED"; break; case STARTING: name = "STARTING"; break; @@ -77,33 +69,33 @@ ostream& operator<<(ostream& out, const VsmZoneState& state) default: name = "MAX_STATE (ERROR)"; } - out << name; - return out; + return name; } -ostream& operator<<(ostream& out, const VsmZone& zone) +std::string zoneToString(const VsmZone& zone) { - out << "Name: " << zone->id - << "\nTerminal: " << zone->terminal - << "\nState: " << zone->state - << "\nRoot: " << zone->rootfs_path; + std::string out = std::string("Name: ") + vsm_zone_get_id(zone) + + std::string("\nTerminal: ") + std::to_string(vsm_zone_get_terminal(zone)) + + std::string("\nState: ") + zoneStateToString(vsm_zone_get_state(zone)) + + std::string("\nRoot: ") + vsm_zone_get_rootfs(zone); return out; } -ostream& operator<<(ostream& out, const VsmNetdevType& netdevType) +std::string netdevTypeToString(const VsmNetdevType& netdevType) { + std::string type; switch (netdevType) { - case VSMNETDEV_VETH: out << "VETH"; break; - case VSMNETDEV_PHYS: out << "PHYS"; break; - case VSMNETDEV_MACVLAN: out << "MACVLAN"; break; + case VSMNETDEV_VETH: type = "VETH"; break; + case VSMNETDEV_PHYS: type = "PHYS"; break; + case VSMNETDEV_MACVLAN: type = "MACVLAN"; break; } - return out; + return type; } -ostream& operator<<(ostream& out, const VsmNetdev& netdev) +std::string netdevToString(const VsmNetdev& netdev) { - out << "Name: " << netdev->name - << "\nType: " << netdev->type; + std::string out = std::string("Name: ") + vsm_netdev_get_name(netdev) + + std::string("\nType: ") + netdevTypeToString(vsm_netdev_get_type(netdev)); return out; } @@ -316,12 +308,12 @@ void console_zone(const Args& argv) VsmZone zone; CommandLineInterface::executeCallback(bind(vsm_lookup_zone_by_id, _1, argv[1].c_str(), &zone)); - if (stringAsInStream(zone->state) != "RUNNING") { + if (zoneStateToString(vsm_zone_get_state(zone)) != "RUNNING") { vsm_zone_free(zone); throw runtime_error("Zone is not running"); } - std::string zonesPath = zone->rootfs_path; + std::string zonesPath = vsm_zone_get_rootfs(zone); std::string zoneRootFs = argv[1] + "/rootfs"; zonesPath.erase(zonesPath.length()- zoneRootFs.length(), zoneRootFs.length()); @@ -374,12 +366,12 @@ void get_zones_status(const Args& /* argv */) for (VsmString* id = ids; *id; ++id) { VsmZone zone; CommandLineInterface::executeCallback(bind(vsm_lookup_zone_by_id, _1, *id, &zone)); - assert(string(zone->id) == string(*id)); - table.push_back({string(zone->id) == string(activeId) ? "*" : "", - zone->id, - stringAsInStream(zone->state), - to_string(zone->terminal), - zone->rootfs_path}); + assert(string(vsm_zone_get_id(zone)) == string(*id)); + table.push_back({string(vsm_zone_get_id(zone)) == string(activeId) ? "*" : "", + vsm_zone_get_id(zone), + zoneStateToString(vsm_zone_get_state(zone)), + to_string(vsm_zone_get_terminal(zone)), + vsm_zone_get_rootfs(zone)}); vsm_zone_free(zone); } vsm_string_free(activeId); @@ -421,7 +413,7 @@ void lookup_zone_by_id(const Args& argv) VsmZone zone; CommandLineInterface::executeCallback(bind(vsm_lookup_zone_by_id, _1, argv[1].c_str(), &zone)); - cout << zone << endl; + cout << zoneToString(zone) << endl; vsm_zone_free(zone); } @@ -497,14 +489,14 @@ void lookup_netdev_by_name(const Args& argv) if (argv.size() <= 2) { throw runtime_error("Not enough parameters"); } - VsmNetdev vsmNetdev = NULL; + VsmNetdev netdev = NULL; CommandLineInterface::executeCallback(bind(vsm_lookup_netdev_by_name, _1, argv[1].c_str(), argv[2].c_str(), - &vsmNetdev)); - cout << vsmNetdev << endl; - vsm_netdev_free(vsmNetdev); + &netdev)); + cout << netdevToString(netdev) << endl; + vsm_netdev_free(netdev); } diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index 78c2d8f..15cccf6 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -93,9 +93,9 @@ void convert(const api::VectorOfStrings& in, VsmArrayString& out) } } -void convert(const api::ZoneInfoOut& info, VsmZone& zone) +void convert(const api::ZoneInfoOut& info, Zone& zone) { - VsmZone vsmZone = reinterpret_cast(malloc(sizeof(*vsmZone))); + Zone vsmZone = static_cast(malloc(sizeof(*vsmZone))); vsmZone->id = ::strdup(info.id.c_str()); vsmZone->terminal = info.vt; vsmZone->state = getZoneState(info.state.c_str()); @@ -349,19 +349,6 @@ VsmStatus Client::vsm_get_active_zone_id(VsmString* id) noexcept }); } -VsmStatus Client::vsm_get_zone_rootpath(const char* id, VsmString* rootpath) noexcept -{ - return coverException([&] { - IS_SET(id); - IS_SET(rootpath); - - api::ZoneInfoOut info = *mClient->callSync( - api::ipc::METHOD_GET_ZONE_INFO, - std::make_shared(api::ZoneId{ id })); - *rootpath = ::strdup(info.rootPath.c_str()); - }); -} - VsmStatus Client::vsm_lookup_zone_by_pid(int pid, VsmString* id) noexcept { return coverException([&] { @@ -383,7 +370,7 @@ VsmStatus Client::vsm_lookup_zone_by_pid(int pid, VsmString* id) noexcept }); } -VsmStatus Client::vsm_lookup_zone_by_id(const char* id, VsmZone* zone) noexcept +VsmStatus Client::vsm_lookup_zone_by_id(const char* id, Zone* zone) noexcept { return coverException([&] { IS_SET(id); @@ -742,7 +729,7 @@ VsmStatus Client::vsm_create_netdev_phys(const char* id, const char* devId) noex VsmStatus Client::vsm_lookup_netdev_by_name(const char* id, const char* netdevId, - VsmNetdev* netdev) noexcept + Netdev* netdev) noexcept { using namespace boost::algorithm; @@ -772,7 +759,7 @@ VsmStatus Client::vsm_lookup_netdev_by_name(const char* id, throw InvalidResponseException("Unknown netdev type: " + it->second); } - *netdev = reinterpret_cast(malloc(sizeof(**netdev))); + *netdev = static_cast(malloc(sizeof(**netdev))); (*netdev)->name = ::strdup(id); (*netdev)->type = type; }); diff --git a/client/vasum-client-impl.hpp b/client/vasum-client-impl.hpp index 1195b66..4297c95 100644 --- a/client/vasum-client-impl.hpp +++ b/client/vasum-client-impl.hpp @@ -46,6 +46,24 @@ typedef std::function VsmZoneDbusStateFunction; /** + * Zone information structure + */ +typedef struct ZoneStructure { + char *id; + int terminal; + VsmZoneState state; + char *rootfs_path; +} *Zone; + +/** + * Network device information structure + */ +typedef struct NetdevStructure { + char *name; + VsmNetdevType type; +} *Netdev; + +/** * vasum's client definition. * * Client uses dbus API. @@ -131,11 +149,6 @@ public: VsmStatus vsm_get_active_zone_id(VsmString* id) noexcept; /** - * @see ::vsm_get_zone_rootpath - */ - VsmStatus vsm_get_zone_rootpath(const char* id, VsmString* rootpath) noexcept; - - /** * @see ::vsm_lookup_zone_by_pid */ VsmStatus vsm_lookup_zone_by_pid(int pid, VsmString* id) noexcept; @@ -143,7 +156,7 @@ public: /** * @see ::vsm_lookup_zone_by_id */ - VsmStatus vsm_lookup_zone_by_id(const char* id, VsmZone* zone) noexcept; + VsmStatus vsm_lookup_zone_by_id(const char* id, Zone* zone) noexcept; /** * @see ::vsm_lookup_zone_by_terminal_id @@ -295,7 +308,7 @@ public: */ VsmStatus vsm_lookup_netdev_by_name(const char* zone, const char* netdevId, - VsmNetdev* netdev) noexcept; + Netdev* netdev) noexcept; /** * @see ::vsm_destroy_netdev diff --git a/client/vasum-client.cpp b/client/vasum-client.cpp index 68496d5..ee3e6d4 100644 --- a/client/vasum-client.cpp +++ b/client/vasum-client.cpp @@ -112,17 +112,55 @@ API void vsm_string_free(VsmString string) free(string); } +API VsmString vsm_zone_get_id(VsmZone zone) +{ + Zone z = static_cast(zone); + return z->id; +} + +API int vsm_zone_get_terminal(VsmZone zone) +{ + Zone z = static_cast(zone); + return z->terminal; +} + +API VsmZoneState vsm_zone_get_state(VsmZone zone) +{ + Zone z = static_cast(zone); + return z->state; +} + +API VsmString vsm_zone_get_rootfs(VsmZone zone) +{ + Zone z = static_cast(zone); + return z->rootfs_path; +} + API void vsm_zone_free(VsmZone zone) { - free(zone->rootfs_path); - free(zone->id); - free(zone); + Zone z = static_cast(zone); + free(z->rootfs_path); + free(z->id); + free(z); +} + +API VsmString vsm_netdev_get_name(VsmNetdev netdev) +{ + Netdev n = static_cast(netdev); + return n->name; +} + +API VsmNetdevType vsm_netdev_get_type(VsmNetdev netdev) +{ + Netdev n = static_cast(netdev); + return n->type; } API void vsm_netdev_free(VsmNetdev netdev) { - free(netdev->name); - free(netdev); + Netdev n = static_cast(netdev); + free(n->name); + free(n); } API void vsm_client_free(VsmClient client) @@ -157,11 +195,6 @@ API VsmStatus vsm_get_active_zone_id(VsmClient client, VsmString* id) return getClient(client).vsm_get_active_zone_id(id); } -API VsmStatus vsm_get_zone_rootpath(VsmClient client, const char* id, VsmString* rootpath) -{ - return getClient(client).vsm_get_zone_rootpath(id, rootpath); -} - API VsmStatus vsm_lookup_zone_by_pid(VsmClient client, int pid, VsmString* id) { return getClient(client).vsm_lookup_zone_by_pid(pid, id); @@ -169,7 +202,8 @@ API VsmStatus vsm_lookup_zone_by_pid(VsmClient client, int pid, VsmString* id) API VsmStatus vsm_lookup_zone_by_id(VsmClient client, const char* id, VsmZone* zone) { - return getClient(client).vsm_lookup_zone_by_id(id, zone); + Zone* z = reinterpret_cast(zone); + return getClient(client).vsm_lookup_zone_by_id(id, z); } API VsmStatus vsm_lookup_zone_by_terminal_id(VsmClient client, int terminal, VsmString* id) @@ -338,7 +372,8 @@ API VsmStatus vsm_lookup_netdev_by_name(VsmClient client, const char* netdevId, VsmNetdev* netdev) { - return getClient(client).vsm_lookup_netdev_by_name(zone, netdevId, netdev); + Netdev* n = reinterpret_cast(netdev); + return getClient(client).vsm_lookup_netdev_by_name(zone, netdevId, n); } API VsmStatus vsm_destroy_netdev(VsmClient client, const char* zone, const char* devId) diff --git a/client/vasum-client.h b/client/vasum-client.h index fbdd3b1..b696dcf 100644 --- a/client/vasum-client.h +++ b/client/vasum-client.h @@ -221,19 +221,9 @@ typedef enum { } VsmZoneState; /** - * Zone information structure - */ -typedef struct { - char* id; - int terminal; - VsmZoneState state; - char *rootfs_path; -} VsmZoneStructure; - -/** * Zone information */ -typedef VsmZoneStructure* VsmZone; +typedef void* VsmZone; /** * Netowrk device type @@ -245,17 +235,9 @@ typedef enum { } VsmNetdevType; /** - * Network device information structure - */ -typedef struct { - char* name; - VsmNetdevType type; -} VsmNetdevStructure; - -/** * Network device information */ -typedef VsmNetdevStructure* VsmNetdev; +typedef void* VsmNetdev; /** * File type @@ -391,6 +373,38 @@ void vsm_array_string_free(VsmArrayString astring); void vsm_string_free(VsmString string); /** + * Get zone id (offline) + * + * @param zone VsmZone + * @return zone id + */ +VsmString vsm_zone_get_id(VsmZone zone); + +/** + * Get zone terminal (offline) + * + * @param zone VsmZone + * @return zone terminal + */ +int vsm_zone_get_terminal(VsmZone zone); + +/** + * Get zone state (offline) + * + * @param zone VsmZone + * @return zone state + */ +VsmZoneState vsm_zone_get_state(VsmZone zone); + +/** + * Get zone rootfs path (offline) + * + * @param zone VsmZone + * @return zone rootfs path + */ +VsmString vsm_zone_get_rootfs(VsmZone zone); + +/** * Release VsmZone * * @param zone VsmZone @@ -398,6 +412,22 @@ void vsm_string_free(VsmString string); void vsm_zone_free(VsmZone zone); /** + * Get netdev name (offline) + * + * @param netdev VsmNetdev + * @return netdev name + */ +VsmString vsm_netdev_get_name(VsmNetdev netdev); + +/** + * Get netdev type (offline) + * + * @param netdev VsmNetdev + * @return netdev type + */ +VsmNetdevType vsm_netdev_get_type(VsmNetdev netdev); + +/** * Release VsmNetdev * * @param netdev VsmNetdev @@ -464,17 +494,6 @@ VsmStatus vsm_get_zone_ids(VsmClient client, VsmArrayString* array); VsmStatus vsm_get_active_zone_id(VsmClient client, VsmString* id); /** - * Get zone rootfs path. - * - * @param[in] client vasum-server's client - * @param[in] id zone name - * @param[out] rootpath zone rootfs path - * @return status of this function call - * @remark Use @p vsm_string_free() to free memory occupied by @p rootpath. - */ -VsmStatus vsm_get_zone_rootpath(VsmClient client, const char* id, VsmString* rootpath); - -/** * Get zone name of process with given pid. * * @param[in] client vasum-server's client diff --git a/tests/unit_tests/client/ut-client.cpp b/tests/unit_tests/client/ut-client.cpp index 1681c36..8b1530f 100644 --- a/tests/unit_tests/client/ut-client.cpp +++ b/tests/unit_tests/client/ut-client.cpp @@ -252,23 +252,6 @@ BOOST_AUTO_TEST_CASE(GetActiveZoneId) vsm_client_free(client); } -BOOST_AUTO_TEST_CASE(GetZoneRootPath) -{ - const std::string zoneId = "zone1"; - - VsmClient client = vsm_client_create(); - VsmStatus status = vsm_connect(client); - BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status); - VsmString rootpath; - status = vsm_get_zone_rootpath(client, zoneId.c_str(), &rootpath); - BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status); - - BOOST_CHECK_EQUAL(rootpath, "/tmp/ut-zones/" + zoneId + "/rootfs"); - - vsm_string_free(rootpath); - vsm_client_free(client); -} - BOOST_AUTO_TEST_CASE(LookupZoneById) { const std::string activeZoneId = "zone1"; @@ -280,10 +263,10 @@ BOOST_AUTO_TEST_CASE(LookupZoneById) status = vsm_lookup_zone_by_id(client, activeZoneId.c_str(), &info); BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status); - BOOST_CHECK_EQUAL(info->id, activeZoneId); - BOOST_CHECK_EQUAL(info->state, RUNNING); - BOOST_CHECK_EQUAL(info->terminal, -1); - BOOST_CHECK_EQUAL(info->rootfs_path, "/tmp/ut-zones/" + activeZoneId + "/rootfs"); + BOOST_CHECK_EQUAL(vsm_zone_get_id(info), activeZoneId); + BOOST_CHECK_EQUAL(vsm_zone_get_state(info), RUNNING); + BOOST_CHECK_EQUAL(vsm_zone_get_terminal(info), -1); + BOOST_CHECK_EQUAL(vsm_zone_get_rootfs(info), "/tmp/ut-zones/" + activeZoneId + "/rootfs"); vsm_zone_free(info); vsm_client_free(client); diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index a975087..c3a071f 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -105,7 +105,7 @@ void init_wrapper() LOGS(""); } -static struct vsm_zone* wrap_vsm_zone(WrappedContext *w, VsmZone zone, bool create = false) +static struct vsm_zone* wrap_vsm_zone(WrappedContext *w, Zone zone, bool create = false) { if (zone == NULL) { return NULL; @@ -303,7 +303,9 @@ API int vsm_destroy_zone(struct vsm_context *ctx, const char *zone_name, int for if (!w->client) return VSM_ERROR_GENERIC; VsmStatus st = w->client->vsm_destroy_zone(zone_name); if (st == VSMCLIENT_SUCCESS) { - auto zonebyname = [zone_name](const WrappedZone& v) {return v.zone->id == zone_name;}; + auto zonebyname = [zone_name](const WrappedZone& v) { + return static_cast(v.zone)->id == zone_name; + }; auto zonelist = std::remove_if(w->zones.begin(), w->zones.end(), zonebyname); w->zones.erase(zonelist); } @@ -390,7 +392,7 @@ API int vsm_iterate_zone(struct vsm_context *ctx, void (*callback)(struct vsm_zo if (!w->client) return -VSM_ERROR_GENERIC; callback(ctx->root_zone, user_data); for (auto& z : w->zones) { - LOGI("iterate callback zone: " << z.zone->id); + LOGI("iterate callback zone: " << static_cast(z.zone)->id); callback(&z.vz, user_data); } return 0; @@ -401,7 +403,7 @@ API struct vsm_zone *vsm_lookup_zone_by_name(struct vsm_context *ctx, const char LOGS("name=" << path); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); - VsmZone zone; + Zone zone; if (!w->client) return NULL; //CHECK if path is same as zone_name if (w->client->vsm_lookup_zone_by_id(path, &zone) != VSMCLIENT_SUCCESS) @@ -415,7 +417,7 @@ API struct vsm_zone *vsm_lookup_zone_by_pid(struct vsm_context *ctx, pid_t pid) LOGS("pid=" << pid); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); - VsmZone zone; + Zone zone; VsmString id; VsmStatus st; if (!w->client) return NULL; @@ -440,7 +442,7 @@ API int vsm_add_state_changed_callback(struct vsm_context *ctx, vsm_zone_state_c auto dbus_cb = [=](const char* id, const char* dbusAddress, void* data) -> void { - VsmZone zone; + Zone zone; //TODO what are valid state, event vsm_zone_state_t t = VSM_ZONE_STATE_RUNNING; UNUSED(dbusAddress); @@ -467,7 +469,7 @@ API int vsm_grant_device(struct vsm_zone *dom, const char *name, uint32_t flags) callcheck(); WrappedZone *w = container_of(dom, WrappedZone, vz); const char *id = dom->name; - VsmZone zone; + Zone zone; w->client->vsm_lookup_zone_by_id(id, &zone); VsmStatus st = w->client->vsm_grant_device(id, name, flags); return wrap_error(st, w->client); @@ -542,7 +544,7 @@ API struct vsm_netdev *vsm_lookup_netdev_by_name(struct vsm_zone *zone, const ch LOGS(""); callcheck(); WrappedZone *w = container_of(zone, WrappedZone, vz); - VsmNetdev nd; + Netdev nd; VsmStatus st = w->client->vsm_lookup_netdev_by_name(zone->name, name, &nd); if (st == VSMCLIENT_SUCCESS) { auto devbyname = [name](const vsm_netdev& v) {return ::strcmp(v.name, name) == 0;}; @@ -695,7 +697,7 @@ API struct vsm_zone *vsm_lookup_zone_by_terminal_id(struct vsm_context *ctx, int LOGS("terminal=" << terminal); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); - VsmZone zone; + Zone zone; VsmString id; if (!w->client) return NULL; if (w->client->vsm_lookup_zone_by_terminal_id(terminal, &id) != VSMCLIENT_SUCCESS) -- 2.7.4 From 24894159f283d2d23012251da4851ed813229cb3 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 27 Jul 2015 16:45:35 +0200 Subject: [PATCH 03/16] Remove debug logs in release build. [Bug] Remove debug logs in release build. [Cause] N/A [Solution] N/A [Verification] Build release/debug, run server. Change-Id: Id34991a45e0fbee8edddfea10b64f69809141af3 --- common/utils/execute.cpp | 2 +- common/utils/fs.cpp | 7 +++++-- libs/dbus/connection.cpp | 4 ++-- libs/ipc/epoll/event-poll.cpp | 2 +- libs/ipc/internals/processor.cpp | 4 ++-- libs/logger/logger-scope.hpp | 4 ++++ libs/logger/logger.hpp | 9 ++++++++- server/main.cpp | 7 +------ tests/unit_tests/log/ut-logger.cpp | 2 ++ wrapper/wrapper-compatibility.cpp | 4 +++- zone-daemon/main.cpp | 7 +------ 11 files changed, 30 insertions(+), 22 deletions(-) diff --git a/common/utils/execute.cpp b/common/utils/execute.cpp index d030177..4b6d59d 100644 --- a/common/utils/execute.cpp +++ b/common/utils/execute.cpp @@ -35,7 +35,7 @@ namespace utils { namespace { -std::ostream& operator<< (std::ostream& out, const char* const* argv) +__attribute__((unused)) std::ostream& operator<< (std::ostream& out, const char* const* argv) { if (*argv) { argv++; //skip diff --git a/common/utils/fs.cpp b/common/utils/fs.cpp index a093c9e..a7a979a 100644 --- a/common/utils/fs.cpp +++ b/common/utils/fs.cpp @@ -201,10 +201,13 @@ bool isMountPoint(const std::string& path, bool& result) { std::string parentPath = dirName(path); bool newResult; - bool ret = hasSameMountPoint(path, parentPath, newResult); + if (!hasSameMountPoint(path, parentPath, newResult)) { + LOGE("Failed to check the files' mount points"); + return false; + } result = !newResult; - return ret; + return true; } bool hasSameMountPoint(const std::string& path1, const std::string& path2, bool& result) diff --git a/libs/dbus/connection.cpp b/libs/dbus/connection.cpp index ee4cea9..5851631 100644 --- a/libs/dbus/connection.cpp +++ b/libs/dbus/connection.cpp @@ -181,7 +181,7 @@ void DbusConnection::setName(const std::string& name, &deleteCallbackWrapper); } -void DbusConnection::onNameAcquired(GDBusConnection*, const gchar* name, gpointer userData) +void DbusConnection::onNameAcquired(GDBusConnection*, __attribute__((unused)) const gchar* name, gpointer userData) { LOGD("Name acquired " << name); const NameCallbacks& callbacks = getCallbackFromPointer(userData); @@ -190,7 +190,7 @@ void DbusConnection::onNameAcquired(GDBusConnection*, const gchar* name, gpointe } } -void DbusConnection::onNameLost(GDBusConnection*, const gchar* name, gpointer userData) +void DbusConnection::onNameLost(GDBusConnection*, __attribute__((unused)) const gchar* name, gpointer userData) { LOGD("Name lost " << name); const NameCallbacks& callbacks = getCallbackFromPointer(userData); diff --git a/libs/ipc/epoll/event-poll.cpp b/libs/ipc/epoll/event-poll.cpp index b6c4902..650e121 100644 --- a/libs/ipc/epoll/event-poll.cpp +++ b/libs/ipc/epoll/event-poll.cpp @@ -51,7 +51,7 @@ EventPoll::~EventPoll() { if (!mCallbacks.empty()) { LOGW("Not removed callbacks: " << mCallbacks.size()); - for (const auto& item : mCallbacks) { + for (__attribute__((unused)) const auto& item : mCallbacks) { LOGT("Not removed fd: " << item.first); } assert(0 && "Not removed callbacks left"); diff --git a/libs/ipc/internals/processor.cpp b/libs/ipc/internals/processor.cpp index 8f81b24..a8c671e 100644 --- a/libs/ipc/internals/processor.cpp +++ b/libs/ipc/internals/processor.cpp @@ -389,8 +389,8 @@ bool Processor::onReturnValue(Peers::iterator& peerIt, } bool Processor::onRemoteSignal(Peers::iterator& peerIt, - const MethodID methodID, - const MessageID messageID, + __attribute__((unused)) const MethodID methodID, + __attribute__((unused)) const MessageID messageID, std::shared_ptr signalCallbacks) { LOGS(mLogPrefix + "Processor onRemoteSignal; methodID: " << methodID << " messageID: " << messageID); diff --git a/libs/logger/logger-scope.hpp b/libs/logger/logger-scope.hpp index 41a99bf..1462272 100644 --- a/libs/logger/logger-scope.hpp +++ b/libs/logger/logger-scope.hpp @@ -74,8 +74,12 @@ private: * @brief Automatically create LoggerScope object which logs at the construction and destruction * @ingroup libLogger */ +#if !defined(NDEBUG) #define LOGS(MSG) logger::LoggerScope logScopeObj(__FILE__, __LINE__, __func__, \ logger::SStreamWrapper() << MSG, \ PROJECT_SOURCE_DIR) +#else +#define LOGS(MSG) do {} while (0) +#endif #endif // COMMON_LOGGER_LOGGER_SCOPE_HPP diff --git a/libs/logger/logger.hpp b/libs/logger/logger.hpp index e27d3dd..bedddb0 100644 --- a/libs/logger/logger.hpp +++ b/libs/logger/logger.hpp @@ -117,6 +117,7 @@ public: /// Logging information #define LOGI(MESSAGE) LOG(INFO, MESSAGE) +#if !defined(NDEBUG) /// Logging debug information #define LOGD(MESSAGE) LOG(DEBUG, MESSAGE) @@ -125,6 +126,12 @@ public: /// Logging tracing information #define LOGT(MESSAGE) LOG(TRACE, MESSAGE) +#else +#define LOGD(MESSAGE) do {} while (0) +#define LOGH(MESSAGE) do {} while (0) +#define LOGT(MESSAGE) do {} while (0) +#endif #endif // COMMON_LOGGER_LOGGER_HPP -/*@}*/ \ No newline at end of file + +/*@}*/ diff --git a/server/main.cpp b/server/main.cpp index 707eb50..e9440cb 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -23,11 +23,6 @@ * @brief Main file for the Vasum Daemon */ -// Always log to console in DEBUG mode -#if !defined(LOG_TO_CONSOLE) && !defined(NDEBUG) -#define LOG_TO_CONSOLE -#endif - #include "config.hpp" #include "exception.hpp" @@ -109,7 +104,7 @@ int main(int argc, char* argv[]) } Logger::setLogLevel(vm["log-level"].as()); -#ifdef LOG_TO_CONSOLE +#if !defined(NDEBUG) Logger::setLogBackend(new StderrBackend()); #elif HAVE_SYSTEMD Logger::setLogBackend(new SystemdJournalBackend()); diff --git a/tests/unit_tests/log/ut-logger.cpp b/tests/unit_tests/log/ut-logger.cpp index 36f52e3..9201f8f 100644 --- a/tests/unit_tests/log/ut-logger.cpp +++ b/tests/unit_tests/log/ut-logger.cpp @@ -176,6 +176,7 @@ BOOST_AUTO_TEST_CASE(LogsLevelInfo) BOOST_CHECK(tf.logContains("[TRACE]") == false); } +#if !defined(NDEBUG) BOOST_AUTO_TEST_CASE(LogsLevelDebug) { TestLog tf(LogLevel::DEBUG); @@ -199,6 +200,7 @@ BOOST_AUTO_TEST_CASE(LogsLevelTrace) BOOST_CHECK(tf.logContains("[DEBUG]") == true); BOOST_CHECK(tf.logContains("[TRACE]") == true); } +#endif BOOST_AUTO_TEST_CASE(LoggerScope) { diff --git a/wrapper/wrapper-compatibility.cpp b/wrapper/wrapper-compatibility.cpp index 6c3dfa9..634c187 100644 --- a/wrapper/wrapper-compatibility.cpp +++ b/wrapper/wrapper-compatibility.cpp @@ -278,7 +278,9 @@ API int sock_send_fd(int fd, int sendfd, void *data, size_t size) { return sendmsg(fd, &msg, MSG_NOSIGNAL); } // vasum_log -API void vasum_log(int type, const char *tag, const char *fmt, ...) { +API void vasum_log(__attribute__((unused)) int type, + __attribute__((unused)) const char *tag, + const char *fmt, ...) { va_list arg_ptr; char buf[255]; LOGS("type=" << type << " tag=" << tag); diff --git a/zone-daemon/main.cpp b/zone-daemon/main.cpp index 0cfe21f..58fad9b 100644 --- a/zone-daemon/main.cpp +++ b/zone-daemon/main.cpp @@ -23,11 +23,6 @@ * @brief Main file for the Vasum Daemon */ -// Always log to console in DEBUG mode -#if !defined(LOG_TO_CONSOLE) && !defined(NDEBUG) -#define LOG_TO_CONSOLE -#endif - #include "config.hpp" #include "exception.hpp" @@ -99,7 +94,7 @@ int main(int argc, char* argv[]) } Logger::setLogLevel(vm["log-level"].as()); -#ifdef LOG_TO_CONSOLE +#if !defined(NDEBUG) Logger::setLogBackend(new StderrBackend()); #elif HAVE_SYSTEMD Logger::setLogBackend(new SystemdJournalBackend()); -- 2.7.4 From 5649bd03bdb39c513ec38545dffe5b00a6448160 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Tue, 28 Jul 2015 13:12:10 +0200 Subject: [PATCH 04/16] lxcpp: Added logger, tests and changed exceptions [Feature] Using libLogger in lxcpp in an example clone function. Set up unit-tests Changed exception names [Cause] N/A [Solution] N/A [Verification] N/A Change-Id: I039bf3e17d791ccf1a18f17a9b2a180ee2081722 --- libs/lxcpp/CMakeLists.txt | 1 + libs/lxcpp/container-impl.cpp | 30 +++++++++---------- libs/lxcpp/container-impl.hpp | 2 +- libs/lxcpp/container.hpp | 2 +- libs/lxcpp/exception.hpp | 21 ++++++++----- libs/lxcpp/lxcpp.cpp | 2 +- libs/lxcpp/lxcpp.hpp | 4 +-- libs/lxcpp/process.cpp | 52 ++++++++++++++++++++++++++++++++ libs/lxcpp/process.hpp | 35 ++++++++++++++++++++++ tests/unit_tests/CMakeLists.txt | 2 +- tests/unit_tests/lxcpp/ut-container.cpp | 53 +++++++++++++++++++++++++++++++++ 11 files changed, 175 insertions(+), 29 deletions(-) create mode 100644 libs/lxcpp/process.cpp create mode 100644 libs/lxcpp/process.hpp create mode 100644 tests/unit_tests/lxcpp/ut-container.cpp diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt index 74522a3..0d49df9 100644 --- a/libs/lxcpp/CMakeLists.txt +++ b/libs/lxcpp/CMakeLists.txt @@ -37,6 +37,7 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES ## Link libraries ############################################################## INCLUDE_DIRECTORIES(${LIBS_FOLDER}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} Logger) ## Generate the pc file ######################################################## CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY) diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp index a7f404e..e4f290d 100644 --- a/libs/lxcpp/container-impl.cpp +++ b/libs/lxcpp/container-impl.cpp @@ -21,8 +21,8 @@ * @brief ContainerImpl definition */ -#include -#include +#include "lxcpp/container-impl.hpp" +#include "lxcpp/exception.hpp" namespace lxcpp { @@ -36,62 +36,62 @@ ContainerImpl::~ContainerImpl() std::string ContainerImpl::getName() { - throw NotImplemented(); + throw NotImplementedException(); } void ContainerImpl::setName(const std::string& /* name */) { - throw NotImplemented(); + throw NotImplementedException(); } void ContainerImpl::start() { - throw NotImplemented(); + throw NotImplementedException(); } void ContainerImpl::stop() { - throw NotImplemented(); + throw NotImplementedException(); } void ContainerImpl::freeze() { - throw NotImplemented(); + throw NotImplementedException(); } void ContainerImpl::unfreeze() { - throw NotImplemented(); + throw NotImplementedException(); } void ContainerImpl::reboot() { - throw NotImplemented(); + throw NotImplementedException(); } int ContainerImpl::getInitPid() { - throw NotImplemented(); + throw NotImplementedException(); } void ContainerImpl::create() { - throw NotImplemented(); + throw NotImplementedException(); } void ContainerImpl::destroy() { - throw NotImplemented(); + throw NotImplementedException(); } void ContainerImpl::setRootPath(const std::string& /* path */) { - throw NotImplemented(); + throw NotImplementedException(); } -std::string getRootPath() +std::string ContainerImpl::getRootPath() { - throw NotImplemented(); + throw NotImplementedException(); } } // namespace lxcpp diff --git a/libs/lxcpp/container-impl.hpp b/libs/lxcpp/container-impl.hpp index 9b9b1ea..f5d9547 100644 --- a/libs/lxcpp/container-impl.hpp +++ b/libs/lxcpp/container-impl.hpp @@ -24,7 +24,7 @@ #ifndef LXCPP_CONTAINER_IMPL_HPP #define LXCPP_CONTAINER_IMPL_HPP -#include +#include "lxcpp/container.hpp" namespace lxcpp { diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp index 36e877e..74caa51 100644 --- a/libs/lxcpp/container.hpp +++ b/libs/lxcpp/container.hpp @@ -30,7 +30,7 @@ namespace lxcpp { class Container { public: - virtual ~Container(); + virtual ~Container() {}; virtual std::string getName() = 0; virtual void setName(const std::string& name) = 0; diff --git a/libs/lxcpp/exception.hpp b/libs/lxcpp/exception.hpp index 1e3ce4c..9d59101 100644 --- a/libs/lxcpp/exception.hpp +++ b/libs/lxcpp/exception.hpp @@ -28,18 +28,23 @@ namespace lxcpp { -class ContainerException : std::runtime_error -{ -public: - ContainerException(const std::string& what) : std::runtime_error(what) {} +/** + * Base class for exceptions in lxcpp + */ +struct Exception: public std::runtime_error { + Exception(const std::string& message) + : std::runtime_error(message) {} }; -class NotImplemented : ContainerException -{ -public: - NotImplemented() : ContainerException(std::string()) {} +struct NotImplementedException: public Exception { + NotImplementedException(const std::string& message = "Functionality not yet implemented") + : Exception(message) {} }; +struct ProcessSetupException: public Exception { + ProcessSetupException(const std::string& message = "Error during setting up a process") + : Exception(message) {} +}; } // namespace lxcpp #endif // LXCPP_EXCEPTION_HPP diff --git a/libs/lxcpp/lxcpp.cpp b/libs/lxcpp/lxcpp.cpp index 3cb906c..97c3866 100644 --- a/libs/lxcpp/lxcpp.cpp +++ b/libs/lxcpp/lxcpp.cpp @@ -21,7 +21,7 @@ * @brief lxcpp container factory definition */ -#include +#include "lxcpp/container-impl.hpp" namespace lxcpp { diff --git a/libs/lxcpp/lxcpp.hpp b/libs/lxcpp/lxcpp.hpp index 8037d3c..5eb3f57 100644 --- a/libs/lxcpp/lxcpp.hpp +++ b/libs/lxcpp/lxcpp.hpp @@ -18,13 +18,13 @@ /** * @file * @author Mateusz Malicki (m.malicki2@samsung.com) - * @brief LXCpp factory declaration + * @brief lxcpp container factory */ #ifndef LXCPP_LXCPP_HPP #define LXCPP_LXCPP_HPP -#include +#include "lxcpp/container.hpp" namespace lxcpp { diff --git a/libs/lxcpp/process.cpp b/libs/lxcpp/process.cpp new file mode 100644 index 0000000..200d12e --- /dev/null +++ b/libs/lxcpp/process.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief process handling routines + */ + +#include "lxcpp/process.hpp" +#include "lxcpp/exception.hpp" +#include "logger/logger.hpp" + +#include +#include +#include +#include + +namespace lxcpp { + +pid_t clone(int (*function)(void *), int flags, void *args) { + // Won't fail, well known resource name + size_t stackSize = ::sysconf(_SC_PAGESIZE); + + // PAGESIZE is enough, it'll exec after this + char *stack = static_cast(::alloca(stackSize)); + + pid_t ret; + ret = ::clone(function, stack + stackSize, flags | SIGCHLD, args); + if (ret < 0) { + LOGE("clone() failed"); + throw ProcessSetupException("clone() failed"); + } + + return ret; +} + +} // namespace lxcpp \ No newline at end of file diff --git a/libs/lxcpp/process.hpp b/libs/lxcpp/process.hpp new file mode 100644 index 0000000..8ca8aaf --- /dev/null +++ b/libs/lxcpp/process.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief process handling routines + */ + +#ifndef LXCPP_PROCESS_HPP +#define LXCPP_PROCESS_HPP + +#include + +namespace lxcpp { + +pid_t clone(int (*function)(void *), int flags, void *args); + +} // namespace lxcpp + +#endif // LXCPP_PROCESS_HPP \ No newline at end of file diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index aa652c7..956082d 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -61,7 +61,7 @@ SET_TARGET_PROPERTIES(${UT_SERVER_CODENAME} PROPERTIES ) TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} ${UT_SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES} - Logger Config Ipc) + Logger Config Ipc lxcpp) IF(NOT WITHOUT_DBUS) TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} SimpleDbus) ENDIF(NOT WITHOUT_DBUS) diff --git a/tests/unit_tests/lxcpp/ut-container.cpp b/tests/unit_tests/lxcpp/ut-container.cpp new file mode 100644 index 0000000..74ebbfe --- /dev/null +++ b/tests/unit_tests/lxcpp/ut-container.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Piotr Bartosiewicz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + + +/** + * @file + * @author Jan Olszak(j.olszak@samsung.com) + * @brief Unit tests of lxcpp Container class + */ + +#include "config.hpp" +#include "ut.hpp" + +#include "lxcpp/lxcpp.hpp" +#include "lxcpp/exception.hpp" + +#include + +namespace { + +struct Fixture { + Fixture() {} + ~Fixture() {} +}; + +} // namespace + +BOOST_FIXTURE_TEST_SUITE(LxcppContainerSuite, Fixture) + +using namespace lxcpp; + +BOOST_AUTO_TEST_CASE(ConstructorDestructor) +{ + auto c = createContainer(); + delete c; +} + +BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 44461ead945d681a7941e0d2a2dc10b7103330f7 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Wed, 29 Jul 2015 12:03:08 +0200 Subject: [PATCH 05/16] Fix pkg-config files from returning wrong relative paths. [Bug] The pkg-config files were using wrong relative paths [Cause] CMAKE_INSTALL_* variables are relative, cmake could handle them internally for INSTALL and similar, but for pkgconfig understands them literally. [Solution] Use absolute paths everywhere. [Verification] Check the content of *.pc files after make install. Change-Id: I2a14d0f9ddc45238be7e8d487d186df1877730bd --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5203a6a..735b349 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,15 +161,15 @@ IF(NOT DEFINED SYSCONF_INSTALL_DIR) ENDIF(NOT DEFINED SYSCONF_INSTALL_DIR) IF(NOT DEFINED LIB_INSTALL_DIR) - SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") + SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") ENDIF(NOT DEFINED LIB_INSTALL_DIR) IF(NOT DEFINED INCLUDE_INSTALL_DIR) - SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") + SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") ENDIF(NOT DEFINED INCLUDE_INSTALL_DIR) IF(NOT DEFINED SCRIPT_INSTALL_DIR) - SET(SCRIPT_INSTALL_DIR "${CMAKE_INSTALL_SBINDIR}") + SET(SCRIPT_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SBINDIR}") ENDIF(NOT DEFINED SCRIPT_INSTALL_DIR) IF(NOT DEFINED SYSTEMD_UNIT_DIR) -- 2.7.4 From cb894f96478a1a9817ea45c04e9e95bf7b5e2b33 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Thu, 23 Jul 2015 16:27:57 +0200 Subject: [PATCH 06/16] Make vasum-cli arguments shorter/nicer with autocomplete, rename tool vasum-cli to vsm [Feature] Shorter and nicer arguments for command line tool [Cause] Messy underscore, too many commands [Solution] More generic commands, shorter, easier to enter names [Verification] Build, install, use vsm with various arguments Try autocompletion for arguments Change-Id: I2e8d1bff3a5dcf96df1250b29b8df55c8f23171d --- cli/CMakeLists.txt | 8 +- cli/command-line-interface.cpp | 344 +++++++++++--------- cli/command-line-interface.hpp | 81 ++--- cli/main.cpp | 576 ++++++++++++++------------------- cli/support/vasum-cli-completion.sh.in | 15 - cli/support/vsm-completion.sh.in | 10 + common/netlink/netlink.cpp | 8 +- packaging/vasum.spec | 4 +- server/netdev.cpp | 49 +-- 9 files changed, 500 insertions(+), 595 deletions(-) delete mode 100755 cli/support/vasum-cli-completion.sh.in create mode 100755 cli/support/vsm-completion.sh.in diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index fe4b067..0f4fbfe 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -24,7 +24,7 @@ FILE(GLOB cli_SRCS *.cpp *.hpp ${COMMON_FOLDER}/utils/c-array.hpp) ## Setup target ################################################################ -SET(CLI_CODENAME "${PROJECT_NAME}-cli") +SET(CLI_CODENAME "vsm") ADD_EXECUTABLE(${CLI_CODENAME} ${cli_SRCS}) ## Readline detection ########################################################## @@ -52,11 +52,11 @@ INCLUDE_DIRECTORIES(${CLIENT_FOLDER}) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) TARGET_LINK_LIBRARIES(${CLI_CODENAME} ${PROJECT_NAME}-client ${LIB_DEPS_LIBRARIES} Ipc) -CONFIGURE_FILE(support/vasum-cli-completion.sh.in - ${CMAKE_BINARY_DIR}/vasum-cli-completion.sh +CONFIGURE_FILE(support/vsm-completion.sh.in + ${CMAKE_BINARY_DIR}/vsm-completion.sh @ONLY) ## Install ##################################################################### INSTALL(TARGETS ${CLI_CODENAME} DESTINATION bin) -INSTALL(FILES ${CMAKE_BINARY_DIR}/vasum-cli-completion.sh +INSTALL(FILES ${CMAKE_BINARY_DIR}/vsm-completion.sh DESTINATION ${SYSCONF_INSTALL_DIR}/bash_completion.d) diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp index 1338afe..e8922ee 100644 --- a/cli/command-line-interface.cpp +++ b/cli/command-line-interface.cpp @@ -36,11 +36,12 @@ #include #include #include -#include #include +#include #include #include #include +#include using namespace std; @@ -72,15 +73,6 @@ std::string zoneStateToString(const VsmZoneState& state) return name; } -std::string zoneToString(const VsmZone& zone) -{ - std::string out = std::string("Name: ") + vsm_zone_get_id(zone) - + std::string("\nTerminal: ") + std::to_string(vsm_zone_get_terminal(zone)) - + std::string("\nState: ") + zoneStateToString(vsm_zone_get_state(zone)) - + std::string("\nRoot: ") + vsm_zone_get_rootfs(zone); - return out; -} - std::string netdevTypeToString(const VsmNetdevType& netdevType) { std::string type; @@ -139,14 +131,61 @@ enum macvlan_mode macvlanFromString(const std::string& mode) { throw runtime_error("Unsupported macvlan mode"); } +void buildZoneList(std::vector& list) +{ + using namespace std::placeholders; + VsmArrayString ids; + + CommandLineInterface::executeCallback(bind(vsm_get_zone_ids, _1, &ids)); + for (VsmString* id = ids; *id; ++id) { + list.push_back(*id); + } + vsm_array_string_free(ids); +} + } // namespace +const std::vector CommandLineInterface::buildCompletionList(const Args& a) const +{ + std::vector v; + + if (a.size() > mArgsSpec.size() + 1) { + return v; + } + + ArgSpec as = mArgsSpec[a.size() - 2]; + string::size_type s = 0U; + string::size_type e = s; + while (e != string::npos) { + e = as.format.find('|', s); + std::string ss = as.format.substr(s, e - s); + s = e + 1; + + if (ss == "{ZONE}") { + buildZoneList(v); + } + else if (ss == "{NETDEV}") { + //TODO: get list of available interfaces + v.push_back("lo"); + v.push_back("eth0"); + } + else if (ss.length() > 0) { + v.push_back(ss); + } + } + + return v; +} + void CommandLineInterface::connect() { VsmStatus status; + if (CommandLineInterface::client != nullptr) { + return; + } CommandLineInterface::client = vsm_client_create(); - if (NULL == CommandLineInterface::client) { + if (CommandLineInterface::client == nullptr) { throw runtime_error("Can't create client"); } @@ -154,7 +193,7 @@ void CommandLineInterface::connect() if (VSMCLIENT_SUCCESS != status) { string msg = vsm_get_status_message(CommandLineInterface::client); vsm_client_free(CommandLineInterface::client); - CommandLineInterface::client = NULL; + CommandLineInterface::client = nullptr; throw runtime_error(msg); } } @@ -164,13 +203,17 @@ void CommandLineInterface::disconnect() string msg; VsmStatus status; + if (CommandLineInterface::client == nullptr) { + return ; + } + status = vsm_disconnect(CommandLineInterface::client); if (VSMCLIENT_SUCCESS != status) { msg = vsm_get_status_message(CommandLineInterface::client); } vsm_client_free(CommandLineInterface::client); - CommandLineInterface::client = NULL; + CommandLineInterface::client = nullptr; if (VSMCLIENT_SUCCESS != status) { throw runtime_error(msg); @@ -179,9 +222,9 @@ void CommandLineInterface::disconnect() void CommandLineInterface::executeCallback(const function& fun) { - VsmStatus status; + CommandLineInterface::connect(); - status = fun(CommandLineInterface::client); + VsmStatus status = fun(CommandLineInterface::client); if (VSMCLIENT_SUCCESS != status) { throw runtime_error(vsm_get_status_message(CommandLineInterface::client)); } @@ -201,7 +244,7 @@ void CommandLineInterface::printUsage(std::ostream& out) const { out << mName; for (const auto& args : mArgsSpec) { - out << " " << args.first; + out << " " << args.name; } out << "\n\n" @@ -211,7 +254,7 @@ void CommandLineInterface::printUsage(std::ostream& out) const if (!mArgsSpec.empty()) { out << "\n\tOptions\n"; for (const auto& args : mArgsSpec) { - out << "\t\t" << args.first << " -- " << args.second << "\n"; + out << "\t\t" << args.name << " -- " << args.description << "\n"; } } out << "\n"; @@ -222,7 +265,7 @@ bool CommandLineInterface::isAvailable(unsigned int mode) const return (mAvailability & mode) == mode; } -void CommandLineInterface::execute(const Args& argv) +void CommandLineInterface::execute(const Args& argv) const { mExecutorCallback(argv); } @@ -242,7 +285,7 @@ void set_active_zone(const Args& argv) { using namespace std::placeholders; - if (argv.size() <= 1) { + if (argv.size() < 2) { throw runtime_error("Not enough parameters"); } @@ -253,7 +296,7 @@ void create_zone(const Args& argv) { using namespace std::placeholders; - if (argv.size() <= 1) { + if (argv.size() < 2) { throw runtime_error("Not enough parameters"); } @@ -268,7 +311,7 @@ void destroy_zone(const Args& argv) { using namespace std::placeholders; - if (argv.size() <= 1) { + if (argv.size() < 2) { throw runtime_error("Not enough parameters"); } @@ -279,7 +322,7 @@ void shutdown_zone(const Args& argv) { using namespace std::placeholders; - if (argv.size() <= 1) { + if (argv.size() < 2) { throw runtime_error("Not enough parameters"); } @@ -290,7 +333,7 @@ void start_zone(const Args& argv) { using namespace std::placeholders; - if (argv.size() <= 1) { + if (argv.size() < 2) { throw runtime_error("Not enough parameters"); } @@ -301,7 +344,7 @@ void console_zone(const Args& argv) { using namespace std::placeholders; - if (argv.size() <= 1) { + if (argv.size() < 2) { throw runtime_error("Not enough parameters"); } @@ -310,7 +353,7 @@ void console_zone(const Args& argv) if (zoneStateToString(vsm_zone_get_state(zone)) != "RUNNING") { vsm_zone_free(zone); - throw runtime_error("Zone is not running"); + throw runtime_error("Zone '" + argv[1] + "' is not running"); } std::string zonesPath = vsm_zone_get_rootfs(zone); @@ -334,7 +377,7 @@ void lock_zone(const Args& argv) { using namespace std::placeholders; - if (argv.size() <= 1) { + if (argv.size() < 2) { throw runtime_error("Not enough parameters"); } @@ -345,14 +388,14 @@ void unlock_zone(const Args& argv) { using namespace std::placeholders; - if (argv.size() <= 1) { + if (argv.size() < 2) { throw runtime_error("Not enough parameters"); } CommandLineInterface::executeCallback(bind(vsm_unlock_zone, _1, argv[1].c_str())); } -void get_zones_status(const Args& /* argv */) +void get_zones_status(const Args& argv) { using namespace std::placeholders; @@ -360,14 +403,24 @@ void get_zones_status(const Args& /* argv */) VsmString activeId; Table table; - CommandLineInterface::executeCallback(bind(vsm_get_zone_ids, _1, &ids)); + if (argv.size() < 2) { + CommandLineInterface::executeCallback(bind(vsm_get_zone_ids, _1, &ids)); + } + else { + ids = reinterpret_cast(calloc(argv.size(), sizeof(char*))); + for (unsigned i = 1; i Args; +struct ArgSpec { + std::string name; + std::string description; + std::string format; +}; + /** * Class that implements command pattern. */ @@ -54,7 +60,7 @@ public: /** * @see CommandLineInterface::CommandLineInterface */ - typedef std::vector> ArgsSpec; + typedef std::vector ArgsSpec; /** * Dummy constructor (for stl usage) @@ -133,8 +139,9 @@ public: * * @param argv Command line arguments */ - void execute(const Args& argv); + void execute(const Args& argv) const; + const std::vector buildCompletionList(const Args& argv) const; private: static VsmClient client; @@ -233,14 +240,7 @@ void get_zone_ids(const Args& argv); * * @see vsm_get_active_zone_id */ -void get_active_zone_id(const Args& argv); - -/** - * Parses command line arguments and call vsm_lookup_zone_by_id - * - * @see vsm_lookup_zone_by_id - */ -void lookup_zone_by_id(const Args& argv); +void get_active_zone(const Args& argv); /** * Parses command line arguments and call vsm_grant_device @@ -257,32 +257,11 @@ void grant_device(const Args& argv); void revoke_device(const Args& argv); /** - * Parses command line arguments and call vsm_create_netdev_veth - * - * @see vsm_create_netdev_veth - */ -void create_netdev_veth(const Args& argv); - -/** - * Parses command line arguments and call vsm_create_netdev_macvlan - * - * @see vsm_create_netdev_macvlan - */ -void create_netdev_macvlan(const Args& argv); - -/** - * Parses command line arguments and call vsm_create_netdev_phys + * Parses command line arguments and call vsm_create_netdev_* * - * @see vsm_create_netdev_phys + * @see vsm_create_netdev_veth,vsm_create_netdev_macvlan,vsm_create_netdev_phys */ -void create_netdev_phys(const Args& argv); - -/** - * Parses command line arguments and call vsm_lookup_netdev_by_name - * - * @see vsm_lookup_netdev_by_name - */ -void lookup_netdev_by_name(const Args& argv); +void create_netdev(const Args& argv); /** * Parses command line arguments and call vsm_destroy_netdev @@ -292,39 +271,27 @@ void lookup_netdev_by_name(const Args& argv); void destroy_netdev(const Args& argv); /** - * Parses command line arguments and prints result of vsm_zone_get_netdevs - * - * @see vsm_zone_get_netdevs - */ -void zone_get_netdevs(const Args& argv); - -/** - * Parses command line arguments and prints result of vsm_netdev_get_ipv4_addr - * - * @see vsm_netdev_get_ipv4_addr - */ -void netdev_get_ipv4_addr(const Args& argv); - -/** - * Parses command line arguments and and prints result of vsm_netdev_get_ipv6_addr + * Parses command line arguments and prints result of vsm_zone_get_netdevs, + * vsm_lookup_netdev_by_name, vsm_netdev_get_ipv4_addr, vsm_netdev_get_ipv6_addr * - * @see vsm_netdev_get_ipv6_addr + * @see vsm_zone_get_netdevs, vsm_lookup_netdev_by_name, + * @see vsm_netdev_get_ipv4_addr, vsm_netdev_get_ipv6_addr */ -void netdev_get_ipv6_addr(const Args& argv); +void netdev_list(const Args& argv); /** - * Parses command line arguments and call vsm_netdev_set_ipv4_addr + * Parses command line arguments and call vsm_netdev_set_ipv4_addr, vsm_netdev_set_ipv6_addr * - * @see vsm_netdev_set_ipv4_addr + * @see vsm_netdev_set_ipv4_addr, vsm_netdev_set_ipv6_addr */ -void netdev_set_ipv4_addr(const Args& argv); +void netdev_add_ip_addr(const Args& argv); /** - * Parses command line arguments and call vsm_netdev_set_ipv6_addr + * Parses command line arguments and call vsm_netdev_del_ipv4_addr, vsm_netdev_del_ipv6_addr * - * @see vsm_netdev_set_ipv6_addr + * @see vsm_netdev_del_ipv4_addr, vsm_netdev_del_ipv6_addr */ -void netdev_set_ipv6_addr(const Args& argv); +void netdev_del_ip_addr(const Args& argv); /** * Parses command line arguments and call vsm_netdev_up diff --git a/cli/main.cpp b/cli/main.cpp index efff7c6..9bec3e7 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -45,305 +45,195 @@ using namespace vasum::cli; namespace { static int interactiveMode = 0; -std::map commands = { +std::vector commands = { { - "lock_queue", { - lock_queue, - "lock_queue", - "Exclusively lock the command queue", - MODE_INTERACTIVE, - {} - } - }, - { - "unlock_queue", { - unlock_queue, - "unlock_queue", - "Unlock the queue", - MODE_INTERACTIVE, - {} - } - }, - { - "set_active_zone", { - set_active_zone, - "set_active_zone", - "Set active (foreground) zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}} - } - }, - { - "create_zone", { - create_zone, - "create_zone", - "Create and add zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"[zone_tname]", "optional zone template name"}} - } - }, - { - "destroy_zone", { - destroy_zone, - "destroy_zone", - "Destroy zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}} - } - }, - { - "shutdown_zone", { - shutdown_zone, - "shutdown_zone", - "Shutdown zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}} - } + create_zone, + "create", + "Create and add zone", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", ""}, + {"[zone_tname]", "optional zone template name", ""}} }, { - "start_zone", { - start_zone, - "start_zone", - "Start zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}} - } + destroy_zone, + "destroy", + "Destroy zone", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}} }, { - "console_zone", { - console_zone, - "console_zone", - "Log into zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}} - } - }, - { - "lock_zone", { - lock_zone, - "lock_zone", - "Lock zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}} - } + start_zone, + "start", + "Start zone", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}} }, { - "unlock_zone", { - unlock_zone, - "unlock_zone", - "Unlock zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}} - } + console_zone, + "console", + "Attach to zone text console", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}} }, { - "get_zones_status", { - get_zones_status, - "get_zones_status", - "Get list of zone with some useful informations (id, state, terminal, root path)", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {} - } + shutdown_zone, + "shutdown", + "Shutdown zone", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}} }, { - "get_zone_ids", { - get_zone_ids, - "get_zone_ids", - "Get all zone ids", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {} - } + lock_zone, + "suspend", + "Suspend (lock) zone", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}} }, { - "get_active_zone_id", { - get_active_zone_id, - "get_active_zone_id", - "Get active (foreground) zone ids", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {} - } + unlock_zone, + "resume", + "Resume (unlock) zone", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}} }, { - "lookup_zone_by_id", { - lookup_zone_by_id, - "lookup_zone_by_id", - "Prints informations about zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}} - } + set_active_zone, + "set-active", + "Set active (foreground) zone", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}} }, { - "grant_device", { - grant_device, - "grant_device", - "Grants access to the given device", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"device_name", " device name"}} - } + get_active_zone, + "get-active", + "Get active (foreground) zone", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {} }, { - "revoke_device", { - revoke_device, - "revoke_device", - "Revokes access to the given device", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"device_name", " device name"}} - } + get_zone_ids, + "list", + "Get available zone ids", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {} }, { - "create_netdev_veth", { - create_netdev_veth, - "create_netdev_veth", - "Create netdev in zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"zone_netdev_id", "network device id"}, - {"host_netdev_id", "host bridge id"}} - } + get_zones_status, + "status", + "List status for one or all zones (id, state, terminal, root path)", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"[zone_id]", "zone name", "{ZONE}"}} }, { - "create_netdev_macvlan", { - create_netdev_macvlan, - "create_netdev_macvlan", - "Create netdev in zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"zone_netdev_id", "network device id"}, - {"host_netdev_id", "host bridge id"}, - {"mode", "macvlan mode (private, vepa, bridge, passthru)"}} - } + clean_up_zones_root, + "clean", + "Clean up zones root directory", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {} }, { - "create_netdev_phys", { - create_netdev_phys, - "create_netdev_phys", - "Create/move netdev to zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"netdev_id", "network device name"}} - } + grant_device, + "device-grant", + "Grants access to the given device", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}, + {"device", "device name", ""}} }, { - "lookup_netdev_by_name", { - lookup_netdev_by_name, - "lookup_netdev_by_name", - "Get netdev flags", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"netdev_id", "network device name"}} - } + revoke_device, + "device-revoke", + "Revokes access to the given device", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}, + {"device", "device name", ""}} }, { - "destroy_netdev", { - destroy_netdev, - "destroy_netdev", - "Destroy netdev in zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"netdev_id", "network device name"}} - } + create_netdev, + "net-create", + "Create network interface in zone", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + { + {"zone_id", "zone name", "{ZONE}"}, + {"netdevtype", "interface type", "macvlan|phys|veth"}, + {"zone_netdev", "interface name (eth0)", "eth0|eth1"}, + {"host_netdev", "bridge name (virbr0)", "virbr0|virbr1"}, + {"mode", "macvlan mode (private, vepa, bridge, passthru)", "private|vepa|bridge|passthru"}} }, { - "zone_get_netdevs", { - zone_get_netdevs, - "zone_get_netdevs", - "List network devices in the zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}} - } + destroy_netdev, + "net-destroy", + "Destroy netdev in zone", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}, + {"netdev", "interface name (eth0)", "{NETDEV}"}} }, { - "netdev_get_ipv4_addr", { - netdev_get_ipv4_addr, - "netdev_get_ipv4_addr", - "Get ipv4 address", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"netdev_id", "network device name"}} - } + netdev_list, + "net-list", + "List network devices in the zone", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}, + {"[netdev]", "interface name (eth0)", "{NETDEV}"}} }, { - "netdev_get_ipv6_addr", { - netdev_get_ipv6_addr, - "netdev_get_ipv6_addr", - "Get ipv6 address", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"netdev_id", "network device name"}} - } + netdev_up, + "net-up", + "Setup a network device in the zone up", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}, + {"netdev", "interface name (eth0)", "{NETDEV}"}} }, { - "netdev_set_ipv4_addr", { - netdev_set_ipv4_addr, - "netdev_set_ipv4_addr", - "Set ipv4 address", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"netdev_id", "network device name"}, - {"address", "ipv4 address"}, - {"prefix_len", "bit length of prefix"}} - } + netdev_down, + "net-down", + "Setup a network device in the zone down", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}, + {"netdev", "interface name (eth0)", "{NETDEV}"}} }, { - "netdev_set_ipv6_addr", { - netdev_set_ipv6_addr, - "netdev_set_ipv6_addr", - "Set ipv6 address", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"netdev_id", "network device name"}, - {"address", "ipv6 address"}, - {"prefix_len", "bit length of prefix"}} - } + netdev_add_ip_addr, + "net-ip-add", + "Add ip/mask address to network interface", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}, + {"netdev", "interface name (eth0)", "{NETDEV}"}, + {"ip", "address IPv4 or IPv6", ""}, + {"prefix", "mask length in bits", "24"}} }, { - "netdev_up", { - netdev_up, - "netdev_up", - "Turn up a network device in the zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"netdev_id", "network device id"}} - } + netdev_del_ip_addr, + "net-ip-del", + "Del ip/mask address from network interface", + MODE_COMMAND_LINE | MODE_INTERACTIVE, + {{"zone_id", "zone name", "{ZONE}"}, + {"netdev", "interface name (eth0)", "{NETDEV}"}, + {"ip", "address IPv4 or IPv6", ""}, + {"prefix", "mask length in bits", "24"}} }, { - "netdev_down", { - netdev_down, - "netdev_down", - "Turn down a network device in the zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"netdev_id", "network device id"}} - } + lock_queue, + "qlock", + "Exclusively lock the command queue", + MODE_INTERACTIVE, + {} }, { - "zone_get_netdevs", { - zone_get_netdevs, - "zone_get_netdevs", - "Turn down a network device in the zone", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {{"zone_id", "id zone name"}, - {"netdev_id", "network device id"}} - } + unlock_queue, + "qunlock", + "Unlock the queue", + MODE_INTERACTIVE, + {} }, - { - "clean_up_zones_root", { - clean_up_zones_root, - "clean_up_zones_root", - "Clean up zones root directory", - MODE_COMMAND_LINE | MODE_INTERACTIVE, - {} - } - } }; +std::map commandMap; + // wrappers for CommandLineInterface void printUsage(std::ostream& out, const std::string& name, unsigned int mode) { + const std::vector addLineBefore = {"device-grant", "net-create", "qlock"}; std::string n; if (!name.empty()) { n = name + " "; @@ -361,9 +251,12 @@ void printUsage(std::ostream& out, const std::string& name, unsigned int mode) out << "command can be one of the following:\n"; for (const auto& command : commands) { - if (command.second.isAvailable(mode)) { - out << " " << std::setw(30) << std::left << command.second.getName() - << command.second.getDescription() << "\n"; + if (command.isAvailable(mode)) { + if (std::find(addLineBefore.begin(), addLineBefore.end(), command.getName()) != addLineBefore.end()) { + out << std::endl; + } + out << " " << std::setw(25) << std::left << command.getName() + << command.getDescription() << std::endl; } } @@ -396,13 +289,14 @@ int disconnect() int executeCommand(const Args& argv, int mode) { - auto pair = commands.find(argv[0]); - if (pair == commands.end()) { + auto pair = commandMap.find(argv[0]); + if (pair == commandMap.end()) { return EXIT_FAILURE; } - CommandLineInterface& command = pair->second; + const CommandLineInterface& command = pair->second; if (!command.isAvailable(mode)) { + std::cerr << "Command not available in this mode" << std::endl; return EXIT_FAILURE; } @@ -423,81 +317,43 @@ int executeCommand(const Args& argv, int mode) } // readline completion support - -char* object_generator(const char* text, int state) +const std::vector buildComplList(const Args& argv); +char *completion_generator(const char* text, int state) { - static std::vector objs; - static size_t len = 0, index = 0; - + static std::vector list; + static unsigned index = 0; if (state == 0) { - objs.clear(); - len = ::strlen(text); + list.clear(); index = 0; - using namespace std::placeholders; - VsmArrayString ids = NULL; - try { - CommandLineInterface::executeCallback(bind(vsm_get_zone_ids, _1, &ids)); - } catch (const std::runtime_error& ex) { - // Quietly ignore, nothing we can do anyway - } - - if (ids != NULL) { - for (VsmString* id = ids; *id; ++id) { - if (::strncmp(text, *id, len) == 0) { - objs.push_back(*id); - } - } + char *ln = rl_line_buffer; + std::istringstream iss(ln); + Args argv{std::istream_iterator{iss}, + std::istream_iterator{}}; - vsm_array_string_free(ids); + size_t len = strlen(text); + if (len == 0 && argv.size() > 0) { + argv.push_back(""); } - } - if (index < objs.size()) { - return ::strdup(objs[index++].c_str()); - } - - return NULL; -} - -char* cmd_generator(const char* text, int state) -{ - static std::vector cmds; - static size_t len = 0, index = 0; - - if (state == 0) { - cmds.clear(); - len = ::strlen(text); - index = 0; - - for (const auto& command : commands) { - if (command.second.isAvailable(MODE_INTERACTIVE)) { - const std::string& cmd = command.second.getName(); - if (::strncmp(text, cmd.c_str(), len) == 0) { - cmds.push_back(cmd); - } + const std::vector& l = buildComplList(argv); + for (const auto &i : l) { + if (strncmp(text, i.c_str(), len) == 0) { + list.push_back(i); } } } - - if (index < cmds.size()) { - return ::strdup(cmds[index++].c_str()); + if (index < list.size()) { + return ::strdup(list[index++].c_str()); } return NULL; } -char** completion(const char* text, int start, int /*end*/) +char** completion(const char* text, int /*start*/, int /*end*/) { - char **matches = NULL; - - if (start == 0) { - matches = ::rl_completion_matches(text, &cmd_generator); - } else { - matches = ::rl_completion_matches(text, &object_generator); - } - - return matches; + ::rl_attempted_completion_over = 1; //disable default completion + return ::rl_completion_matches(text, &completion_generator); } static bool readline_from(const std::string& prompt, std::istream& stream, std::string& ln) @@ -529,6 +385,7 @@ static int processStream(std::istream& stream) return EXIT_FAILURE; } + int rc = EXIT_FAILURE; std::string ln; while (readline_from(">>> ", stream, ln)) { if (ln.empty() || ln[0] == '#') { //skip empty line or comment @@ -539,16 +396,18 @@ static int processStream(std::istream& stream) Args argv{std::istream_iterator{iss}, std::istream_iterator{}}; - if (commands.count(argv[0]) == 0) { + if (commandMap.count(argv[0]) == 0) { printUsage(std::cout, "", MODE_INTERACTIVE); continue; } - executeCommand(argv, MODE_INTERACTIVE); + rc = executeCommand(argv, MODE_INTERACTIVE); + if (rc == EXIT_FAILURE && !interactiveMode) { + break; + } } - disconnect(); - return EXIT_SUCCESS; + return rc; } static int processFile(const std::string& fn) @@ -563,15 +422,43 @@ static int processFile(const std::string& fn) return processStream(stream); } -int bashComplMode() +void printList(const std::vector& list) { - for (const auto& command : commands) { - if (command.second.isAvailable(MODE_COMMAND_LINE)) { - std::cout << command.second.getName() << "\n"; + for (const auto& i : list) { + std::cout << i << std::endl; + } +} + +const std::vector buildComplList(const Args& argv) +{ + if (argv.size() < 2) { + std::vector list; + for (const auto& command : commands) { + if (command.isAvailable(MODE_COMMAND_LINE)) { + list.push_back(command.getName()); + } + } + return list; + } else { + std::string cmd = argv[0]; + if (commandMap.find(cmd) != commandMap.end()) { + return commandMap[cmd].buildCompletionList(argv); } + return std::vector(); } +} - return EXIT_SUCCESS; +int bashComplMode(int argc, const char *argv[]) +{ + int rc = EXIT_FAILURE; + try { + Args args(argv, argv + argc); + printList(buildComplList(args)); + rc = EXIT_SUCCESS; + } catch (const std::runtime_error& ex) { + } + + return rc; } int cliMode(const int argc, const char** argv) @@ -581,22 +468,15 @@ int cliMode(const int argc, const char** argv) return EXIT_SUCCESS; } - if (commands.find(argv[1]) == commands.end()) { + if (commandMap.find(argv[1]) == commandMap.end()) { printUsage(std::cout, argv[0], MODE_COMMAND_LINE); return EXIT_FAILURE; } - //TODO: Connect when it is necessary - //f.e. vasum-cli -h doesn't need connection - if (connect() != EXIT_SUCCESS) { - return EXIT_FAILURE; - } - // pass all the arguments excluding argv[0] - the executable name - Args commandArgs(argv+1, argv+argc); + Args commandArgs(argv + 1, argv + argc); int rc = executeCommand(commandArgs, MODE_COMMAND_LINE); - disconnect(); return rc; } @@ -605,26 +485,38 @@ int cliMode(const int argc, const char** argv) int main(const int argc, const char *argv[]) { + for (const auto& command : commands) { + commandMap.insert(std::pair(command.getName(),command)); + } + + int rc = EXIT_FAILURE; if (argc > 1) { + //process arguments if (std::string(argv[1]) == "--bash-completion") { - return bashComplMode(); - } - - if (std::string(argv[1]) == "-f") { + rc = bashComplMode(argc - 2, argv + 2); + } else if (std::string(argv[1]) == "-f") { if (argc < 3) { std::cerr << "Filename expected" << std::endl; - return EXIT_FAILURE; + rc = EXIT_FAILURE; + } + else { + rc = processFile(std::string(argv[2])); } - return processFile(std::string(argv[2])); + } else { + rc = cliMode(argc, argv); } - return cliMode(argc, argv); - } + } else { + + if (isatty(0) == 1) { + interactiveMode = 1; + ::rl_attempted_completion_function = completion; + } - if (isatty(0) == 1) { - interactiveMode = 1; - ::rl_attempted_completion_function = completion; + rc = processStream(std::cin); } - return processStream(std::cin); + + disconnect(); + return rc; } diff --git a/cli/support/vasum-cli-completion.sh.in b/cli/support/vasum-cli-completion.sh.in deleted file mode 100755 index e04b56f..0000000 --- a/cli/support/vasum-cli-completion.sh.in +++ /dev/null @@ -1,15 +0,0 @@ -# Check for bash -[ -z "$BASH_VERSION" ] && return - -__@PROJECT_NAME@_cli() { - local cur="${COMP_WORDS[COMP_CWORD]}" - - COMPREPLY=() - if [ "$COMP_CWORD" == "1" ]; then - COMPREPLY=($(compgen -W "$(@CLI_CODENAME@ --bash-completion)" -- $cur)) - elif [ "$COMP_CWORD" == "2" ]; then - COMPREPLY=($(compgen -W "-h" -- $cur)) - fi -} - -complete -F __@PROJECT_NAME@_cli @CLI_CODENAME@ diff --git a/cli/support/vsm-completion.sh.in b/cli/support/vsm-completion.sh.in new file mode 100755 index 0000000..1177348 --- /dev/null +++ b/cli/support/vsm-completion.sh.in @@ -0,0 +1,10 @@ +# Check for bash +[ -z "$BASH_VERSION" ] && return + +__@PROJECT_NAME@_cli() { + local exe=$1 cur=$2 prev=$3 + words=`@CLI_CODENAME@ --bash-completion "${COMP_WORDS[@]:1}"` + COMPREPLY=($(compgen -W "$words" -- $cur)) +} + +complete -F __@PROJECT_NAME@_cli vsm diff --git a/common/netlink/netlink.cpp b/common/netlink/netlink.cpp index b048031..dd11ef3 100644 --- a/common/netlink/netlink.cpp +++ b/common/netlink/netlink.cpp @@ -109,7 +109,7 @@ void Netlink::open(int netNsPid) mFd = utils::passNamespacedFd(netNsPid, CLONE_NEWNET, fdFactory); } if (mFd == -1) { - throw VasumException("Can't open netlink connection"); + throw VasumException("Can't open netlink connection (zone not running)"); } sockaddr_nl local = utils::make_clean(); @@ -178,13 +178,13 @@ std::unique_ptr> Netlink::rcv(unsigned int nlmsgSeq) // It is NACK/ACK message nlmsgerr *err = reinterpret_cast(NLMSG_DATA(answer)); if (answer->nlmsg_seq != nlmsgSeq) { - throw VasumException("Sending failed: answer message was mismatched"); + throw VasumException("Receive failed: answer message was mismatched"); } if (err->error) { - throw VasumException("Sending failed: " + getSystemErrorMessage(-err->error)); + throw VasumException("Receive failed: " + getSystemErrorMessage(-err->error)); } } else if (answer->nlmsg_type == NLMSG_OVERRUN) { - throw VasumException("Sending failed: data lost"); + throw VasumException("Receive failed: data lost"); } } if (lastOk == NULL) { diff --git a/packaging/vasum.spec b/packaging/vasum.spec index 0ec93da..22de326 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -243,7 +243,7 @@ Command Line Interface for vasum. %files cli %defattr(644,root,root,755) -%attr(755,root,root) %{_bindir}/vasum-cli +%attr(755,root,root) %{_bindir}/vsm %package cli-completion Summary: Vasum Command Line Interface bash completion @@ -255,7 +255,7 @@ Requires: vasum-cli = %{epoch}:%{version}-%{release} Command Line Interface bash completion for vasum. %files cli-completion -%attr(755,root,root) %{_sysconfdir}/bash_completion.d/vasum-cli-completion.sh +%attr(755,root,root) %{_sysconfdir}/bash_completion.d/vsm-completion.sh ## Test Package ################################################################ %package tests diff --git a/server/netdev.cpp b/server/netdev.cpp index 8c53d38..bf2576c 100644 --- a/server/netdev.cpp +++ b/server/netdev.cpp @@ -488,35 +488,42 @@ Attrs getAttrs(const pid_t nsPid, const std::string& netdev) infoPeer.ifi_change = 0xFFFFFFFF; nlm.put(infoPeer) .put(IFLA_IFNAME, netdev); - NetlinkResponse response = send(nlm, nsPid); - if (!response.hasMessage()) { - throw VasumException("Can't get interface information"); - } - response.fetch(infoPeer); - Attrs attrs; - while (response.hasAttribute()) { - uint32_t mtu, link; - int attrType = response.getAttributeType(); - switch (attrType) { - case IFLA_MTU: - response.fetch(IFLA_MTU, mtu); - attrs.push_back(make_tuple("mtu", std::to_string(mtu))); - break; - case IFLA_LINK: - response.fetch(IFLA_LINK, link); - attrs.push_back(make_tuple("link", std::to_string(link))); - break; - default: - response.skipAttribute(); - break; + try { + NetlinkResponse response = send(nlm, nsPid); + if (!response.hasMessage()) { + throw VasumException("Can't get interface information"); } + response.fetch(infoPeer); + + while (response.hasAttribute()) { + uint32_t mtu, link; + int attrType = response.getAttributeType(); + switch (attrType) { + case IFLA_MTU: + response.fetch(IFLA_MTU, mtu); + attrs.push_back(make_tuple("mtu", std::to_string(mtu))); + break; + case IFLA_LINK: + response.fetch(IFLA_LINK, link); + attrs.push_back(make_tuple("link", std::to_string(link))); + break; + default: + response.skipAttribute(); + break; + } + } + } catch (const std::exception& ex) { + LOGE(ex.what()); + throw VasumException(netdev + ": " + ex.what()); } + attrs.push_back(make_tuple("flags", std::to_string(infoPeer.ifi_flags))); attrs.push_back(make_tuple("type", std::to_string(infoPeer.ifi_type))); for (const auto& address : getIpAddresses(nsPid, AF_INET, infoPeer.ifi_index)) { attrs.push_back(make_tuple("ipv4", joinAddresses(address))); } + for (const auto& address : getIpAddresses(nsPid, AF_INET6, infoPeer.ifi_index)) { attrs.push_back(make_tuple("ipv6", joinAddresses(address))); } -- 2.7.4 From d7572ebdc785cd0cc4b3c79dac92c9b44c61f400 Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Tue, 28 Jul 2015 09:42:48 +0200 Subject: [PATCH 07/16] Add test for Lock/UnlockQueue API [Feature] Test for Lock/UnlockQueue API [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: Id8a88af8459a63e61db06668d4b4a57b2578b4e2 --- tests/unit_tests/server/ut-zones-manager.cpp | 240 +++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) diff --git a/tests/unit_tests/server/ut-zones-manager.cpp b/tests/unit_tests/server/ut-zones-manager.cpp index 214ed1a..819da53 100644 --- a/tests/unit_tests/server/ut-zones-manager.cpp +++ b/tests/unit_tests/server/ut-zones-manager.cpp @@ -415,6 +415,28 @@ public: return fileFd; } + void callMethodLockQueue() + { + assert(isHost()); + GVariantPtr result = mClient->callMethod(api::dbus::BUS_NAME, + api::dbus::OBJECT_PATH, + api::dbus::INTERFACE, + api::dbus::METHOD_LOCK_QUEUE, + nullptr, + "()"); + } + + void callMethodUnlockQueue() + { + assert(isHost()); + GVariantPtr result = mClient->callMethod(api::dbus::BUS_NAME, + api::dbus::OBJECT_PATH, + api::dbus::INTERFACE, + api::dbus::METHOD_UNLOCK_QUEUE, + nullptr, + "()"); + } + private: const int mId; DbusConnection::Pointer mClient; @@ -556,6 +578,22 @@ public: return result->fd.value; } + void callMethodLockQueue() + { + auto result = mClient.callSync( + api::ipc::METHOD_LOCK_QUEUE, + nullptr, + EVENT_TIMEOUT*10); + } + + void callMethodUnlockQueue() + { + auto result = mClient.callSync( + api::ipc::METHOD_UNLOCK_QUEUE, + nullptr, + EVENT_TIMEOUT*10); + } + private: ipc::epoll::ThreadDispatcher mDispatcher; ipc::Client mClient; @@ -1177,4 +1215,206 @@ MULTI_FIXTURE_TEST_CASE(CreateWriteReadFile, F, ACCESSORS) BOOST_REQUIRE(::close(returnedFd) != -1); } +MULTI_FIXTURE_TEST_CASE(BasicLockUnlockQueue, F, ACCESSORS) +{ + ZonesManager cm(F::dispatcher.getPoll(), TEST_CONFIG_PATH); + cm.start(); + cm.createZone("test1", SIMPLE_TEMPLATE); + cm.createZone("test2", SIMPLE_TEMPLATE); + cm.restoreAll(); + + // two clients + typename F::HostAccessory host; + typename F::HostAccessory hostLocker; + + // set up active zone as test1 to have something to compare to + host.callMethodSetActiveZone("test1"); + + // lock queue to host 1 + hostLocker.callMethodLockQueue(); + + // try setting different active zone, should result in error + BOOST_REQUIRE_THROW(host.callMethodSetActiveZone("test2"), std::runtime_error); + BOOST_CHECK_EQUAL(host.callMethodGetActiveZoneId(), "test1"); + + // unlock + hostLocker.callMethodUnlockQueue(); + + // now switch should work + host.callMethodSetActiveZone("test2"); + BOOST_CHECK_EQUAL(host.callMethodGetActiveZoneId(), "test2"); +} + +MULTI_FIXTURE_TEST_CASE(LockAndDisconnectQueue, F, ACCESSORS) +{ + ZonesManager cm(F::dispatcher.getPoll(), TEST_CONFIG_PATH); + cm.start(); + cm.createZone("test1", SIMPLE_TEMPLATE); + cm.createZone("test2", SIMPLE_TEMPLATE); + cm.restoreAll(); + + // two clients + typename F::HostAccessory host; + + { + typename F::HostAccessory hostLocker; + + // set up active zone as test1 to have something to compare to + host.callMethodSetActiveZone("test1"); + + // lock queue to host 1 + hostLocker.callMethodLockQueue(); + + // try setting different active zone, should result in error + BOOST_REQUIRE_THROW(host.callMethodSetActiveZone("test2"), std::runtime_error); + BOOST_CHECK_EQUAL(host.callMethodGetActiveZoneId(), "test1"); + + // leaving scope simulates disconnect + } + + // now switch should work + host.callMethodSetActiveZone("test2"); + BOOST_CHECK_EQUAL(host.callMethodGetActiveZoneId(), "test2"); +} + +MULTI_FIXTURE_TEST_CASE(DoubleLockQueue, F, ACCESSORS) +{ + ZonesManager cm(F::dispatcher.getPoll(), TEST_CONFIG_PATH); + cm.start(); + + typename F::HostAccessory host; + + // first lock - should succeed + host.callMethodLockQueue(); + + // second lock - should fail + BOOST_REQUIRE_THROW(host.callMethodLockQueue(), std::runtime_error); +} + +MULTI_FIXTURE_TEST_CASE(DoubleUnlockQueue, F, ACCESSORS) +{ + ZonesManager cm(F::dispatcher.getPoll(), TEST_CONFIG_PATH); + cm.start(); + + typename F::HostAccessory host; + + // we are already unlocked - should return an error + BOOST_REQUIRE_THROW(host.callMethodUnlockQueue(), std::runtime_error); +} + +#ifdef DBUS_CONNECTION +// test cases similar to BasicLockUnlockQueue, however with cross-fixture calls +BOOST_AUTO_TEST_CASE(IPCLockFromDbusQueue) +{ + ZonesManager cm(dispatcher.getPoll(), TEST_CONFIG_PATH); + cm.start(); + cm.createZone("test1", SIMPLE_TEMPLATE); + cm.createZone("test2", SIMPLE_TEMPLATE); + cm.restoreAll(); + + IPCFixture::HostAccessory hostIPC; + DbusFixture::HostAccessory hostDbus; + + // we should be unlocked, Dbus should be able to call something + hostDbus.callMethodSetActiveZone("test1"); + + // lock the queue with IPC host + hostIPC.callMethodLockQueue(); + + // now Dbus should be unable to do calls + BOOST_REQUIRE_THROW(hostDbus.callMethodSetActiveZone("test2"), std::runtime_error); + BOOST_CHECK_EQUAL(hostDbus.callMethodGetActiveZoneId(), "test1"); + + // unlock + hostIPC.callMethodUnlockQueue(); + + // should be able to call now + hostDbus.callMethodSetActiveZone("test2"); + BOOST_CHECK_EQUAL(hostDbus.callMethodGetActiveZoneId(), "test2"); +} + +BOOST_AUTO_TEST_CASE(DbusLockFromIPCQueue) +{ + ZonesManager cm(dispatcher.getPoll(), TEST_CONFIG_PATH); + cm.start(); + cm.createZone("test1", SIMPLE_TEMPLATE); + cm.createZone("test2", SIMPLE_TEMPLATE); + cm.restoreAll(); + + IPCFixture::HostAccessory hostIPC; + DbusFixture::HostAccessory hostDbus; + + // Same approach as in IPCLockFromDbusQueue, however with flipped host types + hostIPC.callMethodSetActiveZone("test1"); + + hostDbus.callMethodLockQueue(); + + BOOST_REQUIRE_THROW(hostIPC.callMethodSetActiveZone("test2"), std::runtime_error); + BOOST_CHECK_EQUAL(hostIPC.callMethodGetActiveZoneId(), "test1"); + + hostDbus.callMethodUnlockQueue(); + + hostIPC.callMethodSetActiveZone("test2"); + BOOST_CHECK_EQUAL(hostIPC.callMethodGetActiveZoneId(), "test2"); +} + +// simulate disconnect cross-fixture +BOOST_AUTO_TEST_CASE(IPCLockFromDbusAndDisconnectQueue) +{ + ZonesManager cm(dispatcher.getPoll(), TEST_CONFIG_PATH); + cm.start(); + cm.createZone("test1", SIMPLE_TEMPLATE); + cm.createZone("test2", SIMPLE_TEMPLATE); + cm.restoreAll(); + + DbusFixture::HostAccessory hostDbus; + + { + IPCFixture::HostAccessory hostIPC; + + // we should be unlocked, Dbus should be able to call something + hostDbus.callMethodSetActiveZone("test1"); + + // lock the queue with IPC host + hostIPC.callMethodLockQueue(); + + // now Dbus should be unable to do calls + BOOST_REQUIRE_THROW(hostDbus.callMethodSetActiveZone("test2"), std::runtime_error); + BOOST_CHECK_EQUAL(hostDbus.callMethodGetActiveZoneId(), "test1"); + + // leaving scope should simulate disconnect + } + + // should be able to call now + hostDbus.callMethodSetActiveZone("test2"); + BOOST_CHECK_EQUAL(hostDbus.callMethodGetActiveZoneId(), "test2"); +} + +BOOST_AUTO_TEST_CASE(DbusLockFromIPCAndDisconnectQueue) +{ + ZonesManager cm(dispatcher.getPoll(), TEST_CONFIG_PATH); + cm.start(); + cm.createZone("test1", SIMPLE_TEMPLATE); + cm.createZone("test2", SIMPLE_TEMPLATE); + cm.restoreAll(); + + IPCFixture::HostAccessory hostIPC; + + { + DbusFixture::HostAccessory hostDbus; + + // Same approach as in IPCLockFromDbusAndDisconnectQueue, however with flipped host types + hostIPC.callMethodSetActiveZone("test1"); + + hostDbus.callMethodLockQueue(); + + BOOST_REQUIRE_THROW(hostIPC.callMethodSetActiveZone("test2"), std::runtime_error); + BOOST_CHECK_EQUAL(hostIPC.callMethodGetActiveZoneId(), "test1"); + } + + hostIPC.callMethodSetActiveZone("test2"); + BOOST_CHECK_EQUAL(hostIPC.callMethodGetActiveZoneId(), "test2"); +} +#endif + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From b41fd1bbaf120f85b745d923070b1d020fdcc5d2 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Wed, 29 Jul 2015 15:06:02 +0200 Subject: [PATCH 08/16] lxcpp: setns wrapper [Feature] Added setns wrapper Added Namespace type [Cause] N/A [Solution] N/A [Verification] N/A Change-Id: Ib07374bb07183dba604053139d624bdf2a850268 --- common/utils/execute.cpp | 1 + libs/lxcpp/CMakeLists.txt | 1 + libs/lxcpp/exception.hpp | 6 ++ libs/lxcpp/namespace.cpp | 84 ++++++++++++++++++++++ libs/lxcpp/namespace.hpp | 56 +++++++++++++++ libs/lxcpp/process.cpp | 69 ++++++++++++++++-- libs/lxcpp/process.hpp | 10 ++- tests/unit_tests/lxcpp/ut-container.cpp | 6 +- tests/unit_tests/lxcpp/ut-namespace.cpp | 76 ++++++++++++++++++++ tests/unit_tests/lxcpp/ut-process.cpp | 121 ++++++++++++++++++++++++++++++++ 10 files changed, 418 insertions(+), 12 deletions(-) create mode 100644 libs/lxcpp/namespace.cpp create mode 100644 libs/lxcpp/namespace.hpp create mode 100644 tests/unit_tests/lxcpp/ut-namespace.cpp create mode 100644 tests/unit_tests/lxcpp/ut-process.cpp diff --git a/common/utils/execute.cpp b/common/utils/execute.cpp index 4b6d59d..55fc912 100644 --- a/common/utils/execute.cpp +++ b/common/utils/execute.cpp @@ -120,6 +120,7 @@ bool waitPid(pid_t pid, int& status) { while (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) { + LOGE("waitpid() failed: " << getSystemErrorMessage()); return false; } } diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt index 0d49df9..65bd2fc 100644 --- a/libs/lxcpp/CMakeLists.txt +++ b/libs/lxcpp/CMakeLists.txt @@ -37,6 +37,7 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES ## Link libraries ############################################################## INCLUDE_DIRECTORIES(${LIBS_FOLDER}) +INCLUDE_DIRECTORIES(${COMMON_FOLDER}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} Logger) ## Generate the pc file ######################################################## diff --git a/libs/lxcpp/exception.hpp b/libs/lxcpp/exception.hpp index 9d59101..12ae299 100644 --- a/libs/lxcpp/exception.hpp +++ b/libs/lxcpp/exception.hpp @@ -45,6 +45,12 @@ struct ProcessSetupException: public Exception { ProcessSetupException(const std::string& message = "Error during setting up a process") : Exception(message) {} }; + +struct BadArgument: public Exception { + BadArgument(const std::string& message = "Bad argument passed") + : Exception(message) {} +}; + } // namespace lxcpp #endif // LXCPP_EXCEPTION_HPP diff --git a/libs/lxcpp/namespace.cpp b/libs/lxcpp/namespace.cpp new file mode 100644 index 0000000..35bc140 --- /dev/null +++ b/libs/lxcpp/namespace.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief lxcpp container factory definition + */ + +#include "lxcpp/namespace.hpp" +#include "lxcpp/exception.hpp" +#include "logger/logger.hpp" + +#include +#include + +namespace lxcpp { + +Namespace operator|(const Namespace a, const Namespace b) +{ + return static_cast(static_cast::type>(a) | + static_cast::type>(b)); +} + +std::string toString(const Namespace ns) +{ + switch(ns) { + case Namespace::USER: + return "user"; + case Namespace::MNT: + return "mnt"; + case Namespace::PID: + return "pid"; + case Namespace::UTS: + return "uts"; + case Namespace::IPC: + return "ipc"; + case Namespace::NET: + return "net"; + default: + LOGE("Bad namespace passed to the function"); + throw BadArgument("Bad namespace passed to the function"); + } +} + +int toFlag(const std::vector& namespaces) +{ + Namespace flag = std::accumulate(namespaces.begin(), + namespaces.end(), + static_cast(0), + std::bit_or()); + return static_cast(flag); +} + +int toFlag(const Namespace ns) +{ + return static_cast(ns); +} + +std::string getNsPath(const pid_t pid) +{ + return "/proc/" + std::to_string(pid) + "/ns"; +} + +std::string getPath(const pid_t pid, const Namespace ns) +{ + return getNsPath(pid) + "/" + toString(ns); +} + +} // namespace lxcpp diff --git a/libs/lxcpp/namespace.hpp b/libs/lxcpp/namespace.hpp new file mode 100644 index 0000000..be6d033 --- /dev/null +++ b/libs/lxcpp/namespace.hpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief process handling routines + */ + +#ifndef LXCPP_NAMESPACE_HPP +#define LXCPP_NAMESPACE_HPP + +#include +#include +#include + +namespace lxcpp { + +enum class Namespace : int { + USER = CLONE_NEWUSER, + MNT = CLONE_NEWNS, + PID = CLONE_NEWPID, + UTS = CLONE_NEWUTS, + IPC = CLONE_NEWIPC, + NET = CLONE_NEWNET +}; + +Namespace operator |(const Namespace a, const Namespace b); + +std::string toString(const Namespace ns); + +std::string getNsPath(const pid_t pid); + +std::string getPath(const pid_t pid, const Namespace ns); + +int toFlag(const Namespace ns); + +int toFlag(const std::vector& namespaces); + +} // namespace lxcpp + +#endif // LXCPP_NAMESPACE_HPP \ No newline at end of file diff --git a/libs/lxcpp/process.cpp b/libs/lxcpp/process.cpp index 200d12e..68fd62c 100644 --- a/libs/lxcpp/process.cpp +++ b/libs/lxcpp/process.cpp @@ -23,30 +23,85 @@ #include "lxcpp/process.hpp" #include "lxcpp/exception.hpp" + #include "logger/logger.hpp" +#include "utils/fd-utils.hpp" +#include "utils/exception.hpp" #include #include #include #include +#include namespace lxcpp { -pid_t clone(int (*function)(void *), int flags, void *args) { +pid_t clone(int (*function)(void *), + void *args, + const std::vector& namespaces, + const int additionalFlags) +{ // Won't fail, well known resource name size_t stackSize = ::sysconf(_SC_PAGESIZE); // PAGESIZE is enough, it'll exec after this char *stack = static_cast(::alloca(stackSize)); - pid_t ret; - ret = ::clone(function, stack + stackSize, flags | SIGCHLD, args); - if (ret < 0) { - LOGE("clone() failed"); - throw ProcessSetupException("clone() failed"); + pid_t pid = ::clone(function, stack + stackSize, toFlag(namespaces) | additionalFlags | SIGCHLD, args); + if (pid < 0) { + const std::string msg = utils::getSystemErrorMessage(); + LOGE("clone() failed: " << msg); + throw ProcessSetupException("clone() failed " + msg); + } + + return pid; +} + +void setns(const std::vector& namespaces) +{ + pid_t pid = ::getpid(); + + int dirFD = ::open(getNsPath(pid).c_str(), O_DIRECTORY | O_CLOEXEC); + if(dirFD < 0) { + const std::string msg = utils::getSystemErrorMessage(); + LOGE("open() failed: " << msg); + throw ProcessSetupException("open() failed: " + msg); + } + + // Open FDs connected with the requested namespaces + std::vector fds(namespaces.size(), -1); + for(size_t i = 0; i < namespaces.size(); ++i) { + fds[i] = ::openat(dirFD, toString(namespaces[i]).c_str(), O_RDONLY | O_CLOEXEC); + if(fds[i] < 0) { + const std::string msg = utils::getSystemErrorMessage(); + + for (size_t j = 0; j < i; ++j) { + utils::close(fds[j]); + } + utils::close(dirFD); + + LOGE("openat() failed: " << msg); + throw ProcessSetupException("openat() failed: " + msg); + } + } + + // Setns for every namespace + for(size_t i = 0; i < fds.size(); ++i) { + if(-1 == ::setns(fds[i], toFlag(namespaces[i]))) { + const std::string msg = utils::getSystemErrorMessage(); + + for (size_t j = i; j < fds.size(); ++j) { + utils::close(fds[j]); + } + utils::close(dirFD); + + LOGE("setns() failed: " << msg); + throw ProcessSetupException("setns() failed: " + msg); + } + utils::close(fds[i]); } - return ret; + utils::close(dirFD); } } // namespace lxcpp \ No newline at end of file diff --git a/libs/lxcpp/process.hpp b/libs/lxcpp/process.hpp index 8ca8aaf..1255589 100644 --- a/libs/lxcpp/process.hpp +++ b/libs/lxcpp/process.hpp @@ -24,11 +24,19 @@ #ifndef LXCPP_PROCESS_HPP #define LXCPP_PROCESS_HPP +#include "lxcpp/namespace.hpp" + #include +#include namespace lxcpp { -pid_t clone(int (*function)(void *), int flags, void *args); +pid_t clone(int (*function)(void *), + void *args, + const std::vector& namespaces, + const int additionalFlags = 0); + +void setns(const std::vector& namespaces); } // namespace lxcpp diff --git a/tests/unit_tests/lxcpp/ut-container.cpp b/tests/unit_tests/lxcpp/ut-container.cpp index 74ebbfe..6177502 100644 --- a/tests/unit_tests/lxcpp/ut-container.cpp +++ b/tests/unit_tests/lxcpp/ut-container.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved * - * Contact: Piotr Bartosiewicz + * Contact: Jan Olszak(j.olszak@samsung.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,8 +29,6 @@ #include "lxcpp/lxcpp.hpp" #include "lxcpp/exception.hpp" -#include - namespace { struct Fixture { diff --git a/tests/unit_tests/lxcpp/ut-namespace.cpp b/tests/unit_tests/lxcpp/ut-namespace.cpp new file mode 100644 index 0000000..9e10e81 --- /dev/null +++ b/tests/unit_tests/lxcpp/ut-namespace.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jan Olszak(j.olszak@samsung.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + + +/** + * @file + * @author Jan Olszak(j.olszak@samsung.com) + * @brief Unit tests of lxcpp namespace helpers + */ + +#include "config.hpp" +#include "ut.hpp" + +#include "lxcpp/namespace.hpp" +#include +#include + +namespace { + +struct Fixture { + Fixture() {} + ~Fixture() {} +}; + +} // namespace + +BOOST_FIXTURE_TEST_SUITE(LxcppNamespaceSuite, Fixture) + +using namespace lxcpp; + +const std::array NAMESPACES {{ + Namespace::USER, + Namespace::MNT, + Namespace::PID, + Namespace::UTS, + Namespace::IPC, + Namespace::NET + }}; + +BOOST_AUTO_TEST_CASE(OR) +{ + Namespace a = Namespace::USER; + Namespace b = Namespace::MNT; + BOOST_CHECK_EQUAL(CLONE_NEWUSER | CLONE_NEWNS, static_cast(a | b)); +} + +BOOST_AUTO_TEST_CASE(GetPath) +{ + for(const auto ns: NAMESPACES) { + getPath(0, ns); + } +} + +BOOST_AUTO_TEST_CASE(ToString) +{ + for(const auto ns: NAMESPACES) { + toString(ns); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/unit_tests/lxcpp/ut-process.cpp b/tests/unit_tests/lxcpp/ut-process.cpp new file mode 100644 index 0000000..df9f33d --- /dev/null +++ b/tests/unit_tests/lxcpp/ut-process.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jan Olszak(j.olszak@samsung.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + + +/** + * @file + * @author Jan Olszak(j.olszak@samsung.com) + * @brief Unit tests of lxcpp process helpers + */ + +#include "config.hpp" +#include "ut.hpp" + +#include "lxcpp/process.hpp" +#include "lxcpp/exception.hpp" +#include "utils/exception.hpp" +#include "utils/execute.hpp" + +#include +#include +#include + +namespace { + +struct Fixture { + Fixture() {} + ~Fixture() {} +}; + +int clonefn(void* /*args*/) { + return 0; +} + +} // namespace + +BOOST_FIXTURE_TEST_SUITE(LxcppProcessSuite, Fixture) + +using namespace lxcpp; + +const std::vector NAMESPACES {{ + Namespace::USER, + Namespace::MNT, + Namespace::PID, + Namespace::UTS, + Namespace::IPC, + Namespace::NET + }}; + +BOOST_AUTO_TEST_CASE(Clone) +{ + BOOST_CHECK_NO_THROW(clone(clonefn, nullptr, NAMESPACES)); + BOOST_CHECK_NO_THROW(clone(clonefn, nullptr, {Namespace::MNT})); +} + +BOOST_AUTO_TEST_CASE(Setns) +{ + const int TEST_PASSED = 0; + const int ERROR = 1; + + pid_t pid = fork(); + if (pid==-1) { + BOOST_REQUIRE(false); + } else if(pid ==0) { + try { + setns({Namespace::MNT, + Namespace::PID, + Namespace::UTS, + Namespace::IPC, + Namespace::NET + }); + exit(TEST_PASSED); + } catch(...) { + exit(ERROR); + } + } else if(pid>0) { + int status = -1; + BOOST_REQUIRE(utils::waitPid(pid, status)); + BOOST_REQUIRE(status == TEST_PASSED); + } +} + +BOOST_AUTO_TEST_CASE(SetnsUserNamespace) +{ + const int TEST_PASSED = 0; + const int ERROR = -1; + + pid_t pid = fork(); + if (pid==-1) { + BOOST_REQUIRE(false); + } else if(pid ==0) { + try { + setns({Namespace::USER}); + exit(ERROR); + } catch(ProcessSetupException) { + exit(TEST_PASSED); + } catch(...) { + exit(ERROR); + } + } else if(pid>0) { + int status; + BOOST_REQUIRE(utils::waitPid(pid, status)); + BOOST_REQUIRE(status == TEST_PASSED); + } +} + +BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 6c71adb3430b415b16392a0d00772225d394e395 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 3 Aug 2015 15:52:58 +0200 Subject: [PATCH 09/16] Fix lxcpp tests [Bug] N/A [Cause] N/A [Solution] N/A [Verification] N/A Change-Id: Idf5939f96ffb6af7380cfc5fe216361b53402801 --- tests/unit_tests/lxcpp/ut-process.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/unit_tests/lxcpp/ut-process.cpp b/tests/unit_tests/lxcpp/ut-process.cpp index df9f33d..cae893a 100644 --- a/tests/unit_tests/lxcpp/ut-process.cpp +++ b/tests/unit_tests/lxcpp/ut-process.cpp @@ -83,9 +83,9 @@ BOOST_AUTO_TEST_CASE(Setns) Namespace::IPC, Namespace::NET }); - exit(TEST_PASSED); + _exit(TEST_PASSED); } catch(...) { - exit(ERROR); + _exit(ERROR); } } else if(pid>0) { int status = -1; @@ -105,11 +105,11 @@ BOOST_AUTO_TEST_CASE(SetnsUserNamespace) } else if(pid ==0) { try { setns({Namespace::USER}); - exit(ERROR); + _exit(ERROR); } catch(ProcessSetupException) { - exit(TEST_PASSED); + _exit(TEST_PASSED); } catch(...) { - exit(ERROR); + _exit(ERROR); } } else if(pid>0) { int status; -- 2.7.4 From 3ba639b76de913af1a80d35c94cc2106dd6b1376 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Fri, 31 Jul 2015 17:11:16 +0200 Subject: [PATCH 10/16] lxcpp: Added utils sources [Feature] N/A [Cause] N/A [Solution] N/A [Verification] Link only against liblxcpp Change-Id: I7e9d32fc502a068dd9c50e5e45ab3ed07756f815 --- libs/lxcpp/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt index 65bd2fc..4ea53ef 100644 --- a/libs/lxcpp/CMakeLists.txt +++ b/libs/lxcpp/CMakeLists.txt @@ -22,14 +22,18 @@ PROJECT(lxcpp) MESSAGE(STATUS "") MESSAGE(STATUS "Generating makefile for the liblxcpp...") FILE(GLOB HEADERS *.hpp) +FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/fd-utils.hpp + ${COMMON_FOLDER}/utils/exception.hpp) FILE(GLOB SRCS *.cpp *.hpp) +FILE(GLOB SRCS_UTILS ${COMMON_FOLDER}/utils/fd-utils.cpp + ${COMMON_FOLDER}/utils/exception.cpp) SET(_LIB_VERSION_ "${VERSION}") SET(_LIB_SOVERSION_ "0") SET(PC_FILE "lib${PROJECT_NAME}.pc") ## Setup target ################################################################ -ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_UTILS}) SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${_LIB_SOVERSION_} VERSION ${_LIB_VERSION_} @@ -53,3 +57,5 @@ INSTALL(TARGETS ${PROJECT_NAME} INSTALL(FILES ${HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp) +INSTALL(FILES ${HEADERS_UTILS} + DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp/utils) -- 2.7.4 From aa482a5e599af2f33ce893dbef2c73a2e6804e3b Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Tue, 28 Jul 2015 15:55:25 +0200 Subject: [PATCH 11/16] Add daemonize function to work in the background. [Feature] Add daemonize function to work in the background. [Cause] N/A [Solution] N/A [Verification] Build, run tests, run server as daemon. Change-Id: Ie8987ac4d23ac350ab6036c476ade47436afbe69 --- common/utils/daemon.cpp | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ common/utils/daemon.hpp | 34 ++++++++++++++++++ server/main.cpp | 11 +++++- zone-daemon/main.cpp | 11 +++++- 4 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 common/utils/daemon.cpp create mode 100644 common/utils/daemon.hpp diff --git a/common/utils/daemon.cpp b/common/utils/daemon.cpp new file mode 100644 index 0000000..8ee84c5 --- /dev/null +++ b/common/utils/daemon.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Dariusz Michaluk + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Dariusz Michaluk + * @brief Run a process as a daemon + */ + +#include "fd-utils.hpp" + +#include +#include +#include +#include +#include + +namespace utils { + +bool daemonize() +{ + pid_t pid = ::fork(); + + if (pid == -1) { + std::cerr << "Fork failed" << std::endl; + return false; + } else if (pid != 0) { + exit (0); + } + + if (::setsid() == -1) { + return false; + } + + pid = ::fork(); + + /* + * Fork a second child and exit immediately to prevent zombies. + * This causes the second child process to be orphaned, making the init + * process responsible for its cleanup. And, since the first child is + * a session leader without a controlling terminal, it's possible for + * it to acquire one by opening a terminal in the future (System V + * based systems). This second fork guarantees that the child is no + * longer a session leader, preventing the daemon from ever acquiring + * a controlling terminal. + */ + + if (pid == -1) { + std::cerr << "Fork failed" << std::endl; + return false; + } else if (pid != 0) { + exit(0); + } + + if (::chdir("/") == -1) { + return false; + } + + ::umask(0); + + /** Close all open standard file descriptors */ + int fd = ::open("/dev/null", O_RDWR); + if (fd == -1) { + return false; + } + + for (int i = 0; i <= 2; i++) { + if (::dup2(fd, i) == -1) { + utils::close(fd); + return false; + } + } + utils::close(fd); + + return true; +} + +} // namespace utils diff --git a/common/utils/daemon.hpp b/common/utils/daemon.hpp new file mode 100644 index 0000000..4b5924a --- /dev/null +++ b/common/utils/daemon.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Dariusz Michaluk + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Dariusz Michaluk + * @brief Run a process as a daemon + */ + +#ifndef COMMON_UTILS_DAEMON_HPP +#define COMMON_UTILS_DAEMON_HPP + +namespace utils { + +bool daemonize(); + +} // namespace utils + +#endif // COMMON_UTILS_DAEMON_HPP diff --git a/server/main.cpp b/server/main.cpp index e9440cb..7ed4ef1 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -34,6 +34,7 @@ #include "logger/backend-syslog.hpp" #include "utils/typeinfo.hpp" #include "utils/signal.hpp" +#include "utils/daemon.hpp" #include #include @@ -64,9 +65,10 @@ int main(int argc, char* argv[]) desc.add_options() ("help,h", "print this help") ("root,r", "Don't drop root privileges at startup") - ("version,v", "show application version") + ("daemon,d", "Run server as daemon") ("log-level,l", po::value()->default_value("DEBUG"), "set log level") ("check,c", "check runtime environment and exit") + ("version,v", "show application version") ; po::variables_map vm; @@ -103,6 +105,13 @@ int main(int argc, char* argv[]) return Server::checkEnvironment() ? 0 : 1; } + bool runAsDaemon = vm.count("daemon") > 0; + + if (runAsDaemon && !utils::daemonize()) { + std::cerr << "Failed to daemonize" << std::endl; + return 1; + } + Logger::setLogLevel(vm["log-level"].as()); #if !defined(NDEBUG) Logger::setLogBackend(new StderrBackend()); diff --git a/zone-daemon/main.cpp b/zone-daemon/main.cpp index 58fad9b..1bb3091 100644 --- a/zone-daemon/main.cpp +++ b/zone-daemon/main.cpp @@ -33,6 +33,7 @@ #include "logger/backend-journal.hpp" #include "logger/backend-syslog.hpp" #include "utils/typeinfo.hpp" +#include "utils/daemon.hpp" #include #include @@ -58,8 +59,9 @@ int main(int argc, char* argv[]) desc.add_options() ("help,h", "print this help") - ("version,v", "show application version") + ("daemon,d", "Run server as daemon") ("log-level,l", po::value()->default_value("DEBUG"), "set log level") + ("version,v", "show application version") ; po::variables_map vm; @@ -93,6 +95,13 @@ int main(int argc, char* argv[]) return 0; } + bool runAsDaemon = vm.count("daemon") > 0; + + if (runAsDaemon && !utils::daemonize()) { + std::cerr << "Failed to daemonize" << std::endl; + return 1; + } + Logger::setLogLevel(vm["log-level"].as()); #if !defined(NDEBUG) Logger::setLogBackend(new StderrBackend()); -- 2.7.4 From a18c42df8f27093a407ce428d98698c14b28fe73 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Mon, 27 Jul 2015 17:28:22 +0200 Subject: [PATCH 12/16] InputMonitor connected to epoll dispatcher [Feature] InputMonitor connected to epoll dispatcher [Cause] N/A [Solution] N/A [Verification] Build, run tests Change-Id: If2bdcd8c8493bc22357aa93b43b5c6e530c954d4 --- server/input-monitor.cpp | 139 +++++++++++---------------- server/input-monitor.hpp | 36 +++---- server/zones-manager.cpp | 16 ++- server/zones-manager.hpp | 3 +- tests/unit_tests/server/ut-input-monitor.cpp | 125 ++++++++++++++++++------ 5 files changed, 179 insertions(+), 140 deletions(-) diff --git a/server/input-monitor.cpp b/server/input-monitor.cpp index e99906f..bb65b90 100644 --- a/server/input-monitor.cpp +++ b/server/input-monitor.cpp @@ -26,19 +26,17 @@ #include "input-monitor-config.hpp" #include "input-monitor.hpp" +#include "zones-manager.hpp" #include "exception.hpp" #include "logger/logger.hpp" #include "utils/exception.hpp" #include "utils/fs.hpp" -#include "utils/callback-wrapper.hpp" -#include "utils/scoped-gerror.hpp" +#include "utils/fd-utils.hpp" #include #include #include -#include -#include #include #include #include @@ -64,10 +62,13 @@ const std::string DEVICE_DIR = "/dev/input/"; } // namespace -InputMonitor::InputMonitor(const InputConfig& inputConfig, - const NotifyCallback& notifyCallback) - : mConfig(inputConfig), - mNotifyCallback(notifyCallback) +InputMonitor::InputMonitor(ipc::epoll::EventPoll& eventPoll, + const InputConfig& inputConfig, + ZonesManager* zonesManager) + : mConfig(inputConfig) + , mZonesManager(zonesManager) + , mFd(-1) + , mEventPoll(eventPoll) { if (mConfig.timeWindowMs > MAX_TIME_WINDOW_SEC * 1000L) { LOGE("Time window exceeds maximum: " << MAX_TIME_WINDOW_SEC); @@ -79,37 +80,39 @@ InputMonitor::InputMonitor(const InputConfig& inputConfig, throw InputMonitorException("Number of events exceeds maximum"); } - std::string devicePath = getDevicePath(); + mDevicePath = getDevicePath(); LOGT("Input monitor configuration: \n" << "\tenabled: " << mConfig.enabled << "\n" << "\tdevice: " << mConfig.device << "\n" - << "\tpath: " << devicePath << "\n" + << "\tpath: " << mDevicePath << "\n" << "\ttype: " << EV_KEY << "\n" << "\tcode: " << mConfig.code << "\n" << "\tvalue: " << KEY_PRESSED << "\n" << "\tnumberOfEvents: " << mConfig.numberOfEvents << "\n" << "\ttimeWindowMs: " << mConfig.timeWindowMs); - - createGIOChannel(devicePath); } InputMonitor::~InputMonitor() { + std::unique_lock mMutex; LOGD("Destroying InputMonitor"); - ScopedGError error; - g_io_channel_unref(mChannelPtr); - if (g_io_channel_shutdown(mChannelPtr, FALSE, &error) - != G_IO_STATUS_NORMAL) { - LOGE("Error during shutting down GIOChannel: " << error->message); - } + stop(); +} - if (!g_source_remove(mSourceId)) { - LOGE("Error during removing the source"); - } +void InputMonitor::start() +{ + std::unique_lock mMutex; + setHandler(mDevicePath); +} + +void InputMonitor::stop() +{ + leaveDevice(); } namespace { + bool isDeviceWithName(const boost::regex& deviceNameRegex, const fs::directory_entry& directoryEntry) { @@ -119,7 +122,7 @@ bool isDeviceWithName(const boost::regex& deviceNameRegex, return false; } - int fd = open(path.c_str(), O_RDONLY); + int fd = ::open(path.c_str(), O_RDONLY); if (fd < 0) { LOGD("Failed to open " << path); return false; @@ -128,13 +131,13 @@ bool isDeviceWithName(const boost::regex& deviceNameRegex, char name[DEVICE_NAME_LENGTH]; if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) { LOGD("Failed to get the device name of: " << path); - if (close(fd) < 0) { + if (::close(fd) < 0) { LOGE("Error during closing file " << path); } return false; } - if (close(fd) < 0) { + if (::close(fd) < 0) { LOGE("Error during closing file " << path); } @@ -146,6 +149,7 @@ bool isDeviceWithName(const boost::regex& deviceNameRegex, return false; } + } // namespace std::string InputMonitor::getDevicePath() const @@ -174,80 +178,47 @@ std::string InputMonitor::getDevicePath() const return it->path().string(); } - - -void InputMonitor::createGIOChannel(const std::string& devicePath) +void InputMonitor::setHandler(const std::string& devicePath) { + using namespace std::placeholders; + // We need NONBLOCK for FIFOs in the tests - int fd = open(devicePath.c_str(), O_RDONLY | O_NONBLOCK); - if (fd < 0) { + mFd = ::open(devicePath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (mFd < 0) { LOGE("Cannot create input monitor channel. Device file: " << devicePath << " doesn't exist"); throw InputMonitorException("Device does not exist"); } - - mChannelPtr = g_io_channel_unix_new(fd); - - // Read binary data - if (g_io_channel_set_encoding(mChannelPtr, - NULL, - NULL) != G_IO_STATUS_NORMAL) { - LOGE("Cannot set encoding for input monitor channel "); - throw InputMonitorException("Cannot set encoding"); - } - - using namespace std::placeholders; - ReadDeviceCallback callback = std::bind(&InputMonitor::readDevice, this, _1); - // Add the callback - mSourceId = g_io_add_watch_full(mChannelPtr, - G_PRIORITY_DEFAULT, - G_IO_IN, - readDeviceCallback, - utils::createCallbackWrapper(callback, mGuard.spawn()), - &utils::deleteCallbackWrapper); - if (!mSourceId) { - LOGE("Cannot add watch on device input file"); - throw InputMonitorException("Cannot add watch"); - } + mEventPoll.addFD(mFd, EPOLLIN, std::bind(&InputMonitor::handleInternal, this, _1, _2)); } -gboolean InputMonitor::readDeviceCallback(GIOChannel* gio, - GIOCondition /*condition*/, - gpointer data) -{ - const ReadDeviceCallback& callback = utils::getCallbackFromPointer(data); - callback(gio); - return TRUE; -} - -void InputMonitor::readDevice(GIOChannel* gio) +void InputMonitor::handleInternal(int /* fd */, ipc::epoll::Events events) { struct input_event ie; - gsize nBytesReadTotal = 0; - gsize nBytesRequested = sizeof(struct input_event); - ScopedGError error; - - do { - gsize nBytesRead = 0; - GIOStatus readStatus = g_io_channel_read_chars(gio, - &reinterpret_cast(&ie)[nBytesReadTotal], - nBytesRequested, - &nBytesRead, - &error); - - if (readStatus == G_IO_STATUS_ERROR) { - LOGE("Read from input monitor channel failed: " << error->message); + try { + if (events == EPOLLHUP) { + stop(); return; } - - nBytesRequested -= nBytesRead; - nBytesReadTotal += nBytesRead; - } while (nBytesRequested > 0); - - + utils::read(mFd, &ie, sizeof(struct input_event)); + } catch (const std::exception& ex) { + LOGE("Read from input monitor channel failed: " << ex.what()); + return; + } if (isExpectedEventSequence(ie)) { LOGI("Input monitor detected pattern."); - mNotifyCallback(); + if (mZonesManager->isRunning()) { + mZonesManager->switchingSequenceMonitorNotify(); + } + } +} + +void InputMonitor::leaveDevice() +{ + if (mFd != -1) { + mEventPoll.removeFD(mFd); + utils::close(mFd); + mFd = -1; } } diff --git a/server/input-monitor.hpp b/server/input-monitor.hpp index 2b0ed45..7ab5344 100644 --- a/server/input-monitor.hpp +++ b/server/input-monitor.hpp @@ -26,45 +26,45 @@ #define SERVER_INPUT_MONITOR_HPP #include "input-monitor-config.hpp" -#include "utils/callback-guard.hpp" +#include "ipc/epoll/event-poll.hpp" #include #include -#include -#include #include #include +#include namespace vasum { +class ZonesManager; + class InputMonitor { public: - typedef std::function NotifyCallback; - - InputMonitor(const InputConfig& inputConfig, - const NotifyCallback& notifyCallback); + InputMonitor(ipc::epoll::EventPoll& eventPoll, + const InputConfig& inputConfig, + ZonesManager* zonesManager); ~InputMonitor(); + void start(); + void stop(); private: - typedef std::function ReadDeviceCallback; + typedef std::mutex Mutex; InputConfig mConfig; - NotifyCallback mNotifyCallback; - + ZonesManager* mZonesManager; + int mFd; + ipc::epoll::EventPoll& mEventPoll; std::list mEventTimes; - GIOChannel* mChannelPtr; + std::string mDevicePath; + Mutex mMutex; std::string getDevicePath() const; - void createGIOChannel(const std::string& devicePath); - - // Internal callback to be registered at glib g_io_add_watch() - static gboolean readDeviceCallback(GIOChannel*, GIOCondition, gpointer); + void setHandler(const std::string& devicePath); + void handleInternal(int fd, ipc::epoll::Events events); + void leaveDevice(); bool isExpectedEventSequence(const struct input_event&); - void readDevice(GIOChannel*); - utils::CallbackGuard mGuard; - guint mSourceId; }; } // namespace vasum diff --git a/server/zones-manager.cpp b/server/zones-manager.cpp index 484b3e9..0d88d24 100644 --- a/server/zones-manager.cpp +++ b/server/zones-manager.cpp @@ -173,6 +173,11 @@ ZonesManager::ZonesManager(ipc::epoll::EventPoll& eventPoll, const std::string& configPath, mDynamicConfig, getVasumDbPrefix()); + + if (mConfig.inputConfig.enabled) { + LOGI("Registering input monitor [" << mConfig.inputConfig.device.c_str() << "]"); + mSwitchingSequenceMonitor.reset(new InputMonitor(eventPoll, mConfig.inputConfig, this)); + } } ZonesManager::~ZonesManager() @@ -207,11 +212,8 @@ void ZonesManager::start() LOGD("ZonesManager object instantiated"); if (mConfig.inputConfig.enabled) { - LOGI("Registering input monitor [" << mConfig.inputConfig.device.c_str() << "]"); - mSwitchingSequenceMonitor.reset( - new InputMonitor(mConfig.inputConfig, - std::bind(&ZonesManager::switchingSequenceMonitorNotify, - this))); + LOGI("Starting input monitor "); + mSwitchingSequenceMonitor->start(); } // After everything's initialized start to respond to clients' requests @@ -238,6 +240,10 @@ void ZonesManager::stop(bool wait) // wait for all tasks to complete mWorker.reset(); mHostIPCConnection.stop(wait); + if (mConfig.inputConfig.enabled) { + LOGI("Stopping input monitor "); + mSwitchingSequenceMonitor->stop(); + } mIsRunning = false; } diff --git a/server/zones-manager.hpp b/server/zones-manager.hpp index de6663d..c6f6918 100644 --- a/server/zones-manager.hpp +++ b/server/zones-manager.hpp @@ -198,6 +198,8 @@ public: api::MethodResultBuilder::Pointer result); void handleCleanUpZonesRootCall(api::MethodResultBuilder::Pointer result); + void switchingSequenceMonitorNotify(); + private: typedef std::recursive_mutex Mutex; typedef std::unique_lock Lock; @@ -227,7 +229,6 @@ private: void saveDynamicConfig(); void updateDefaultId(); void refocus(); - void switchingSequenceMonitorNotify(); void generateNewConfig(const std::string& id, const std::string& templatePath); std::string getTemplatePathForExistingZone(const std::string& id); diff --git a/tests/unit_tests/server/ut-input-monitor.cpp b/tests/unit_tests/server/ut-input-monitor.cpp index 22fba47..75079a2 100644 --- a/tests/unit_tests/server/ut-input-monitor.cpp +++ b/tests/unit_tests/server/ut-input-monitor.cpp @@ -29,10 +29,12 @@ #include "input-monitor.hpp" #include "input-monitor-config.hpp" #include "exception.hpp" +#include "zones-manager.hpp" #include "utils/glib-loop.hpp" #include "utils/latch.hpp" #include "utils/scoped-dir.hpp" +#include "ipc/epoll/thread-dispatcher.hpp" #include #include @@ -44,7 +46,6 @@ #include #include - using namespace vasum; using namespace utils; @@ -58,16 +59,24 @@ const int EVENT_CODE = 139; const int EVENT_BUTTON_RELEASED = 0; const int EVENT_BUTTON_PRESSED = 1; -const int SINGLE_EVENT_TIMEOUT = 1000; +const int EVENT_TIMEOUT = 1000; + +const std::string CONFIG_DIR = VSM_TEST_CONFIG_INSTALL_DIR; +const std::string TEST_CONFIG_PATH = CONFIG_DIR + "/test-daemon.conf"; +const std::string SIMPLE_TEMPLATE = "console-ipc"; +const std::string ZONES_PATH = "/tmp/ut-zones"; // the same as in daemon.conf struct Fixture { utils::ScopedGlibLoop mLoop; ScopedDir mTestPathGuard; + ScopedDir mZonesPathGuard; InputConfig inputConfig; struct input_event ie; + ipc::epoll::ThreadDispatcher dispatcher; Fixture() : mTestPathGuard(TEST_DIR) + , mZonesPathGuard(ZONES_PATH) { inputConfig.numberOfEvents = 2; inputConfig.device = TEST_INPUT_DEVICE; @@ -84,46 +93,65 @@ struct Fixture { BOOST_CHECK(::mkfifo(TEST_INPUT_DEVICE.c_str(), S_IWUSR | S_IRUSR) >= 0); } + + ipc::epoll::EventPoll& getPoll() { + return dispatcher.getPoll(); + } }; + +template +bool spinWaitFor(int timeoutMs, Predicate pred) +{ + auto until = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeoutMs); + while (!pred()) { + if (std::chrono::steady_clock::now() >= until) { + return false; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + return true; +} + } // namespace BOOST_FIXTURE_TEST_SUITE(InputMonitorSuite, Fixture) BOOST_AUTO_TEST_CASE(ConfigOK) { - InputMonitor inputMonitor(inputConfig, InputMonitor::NotifyCallback()); + ZonesManager cm(getPoll(), TEST_CONFIG_PATH); + InputMonitor inputMonitor(getPoll(), inputConfig, &cm); } BOOST_AUTO_TEST_CASE(ConfigTimeWindowMsTooHigh) { + ZonesManager cm(getPoll(), TEST_CONFIG_PATH); inputConfig.timeWindowMs = 50000; - BOOST_REQUIRE_EXCEPTION(InputMonitor inputMonitor(inputConfig, InputMonitor::NotifyCallback()), + BOOST_REQUIRE_EXCEPTION(InputMonitor inputMonitor(getPoll(), inputConfig, &cm), InputMonitorException, WhatEquals("Time window exceeds maximum")); } BOOST_AUTO_TEST_CASE(ConfigDeviceFilePathNotExisting) { + ZonesManager cm(getPoll(), TEST_CONFIG_PATH); inputConfig.device = TEST_INPUT_DEVICE + "notExisting"; - BOOST_REQUIRE_EXCEPTION(InputMonitor inputMonitor(inputConfig, InputMonitor::NotifyCallback()), + BOOST_REQUIRE_EXCEPTION(InputMonitor inputMonitor(getPoll(), inputConfig, &cm), InputMonitorException, WhatEquals("Cannot find a device")); } namespace { -void sendNEvents(Fixture& f, unsigned int noOfEventsToSend) +void sendEvent(Fixture& f, ZonesManager& cm) { - Latch eventLatch; - - InputMonitor inputMonitor(f.inputConfig, [&] {eventLatch.set();}); - + InputMonitor inputMonitor(f.getPoll(), f.inputConfig, &cm); + inputMonitor.start(); int fd = ::open(TEST_INPUT_DEVICE.c_str(), O_WRONLY); BOOST_REQUIRE(fd >= 0); - for (unsigned int i = 0; i < noOfEventsToSend * f.inputConfig.numberOfEvents; ++i) { + for (int i = 0; i < f.inputConfig.numberOfEvents; ++i) { // button pressed event f.ie.value = EVENT_BUTTON_PRESSED; f.ie.time.tv_usec += 5; @@ -140,36 +168,52 @@ void sendNEvents(Fixture& f, unsigned int noOfEventsToSend) } BOOST_CHECK(::close(fd) >= 0); - BOOST_CHECK(eventLatch.waitForN(noOfEventsToSend, SINGLE_EVENT_TIMEOUT * noOfEventsToSend)); - - // Check if no more events are waiting - BOOST_CHECK(!eventLatch.wait(10)); } } // namespace -BOOST_AUTO_TEST_CASE(EventOneAtATime) +BOOST_AUTO_TEST_CASE(SingleEvent) { - sendNEvents(*this, 1); + ZonesManager cm(getPoll(), TEST_CONFIG_PATH); + cm.start(); + cm.createZone("zone1", SIMPLE_TEMPLATE); + cm.createZone("zone2", SIMPLE_TEMPLATE); + cm.createZone("zone3", SIMPLE_TEMPLATE); + cm.restoreAll(); + sendEvent(*this, cm); + BOOST_CHECK(spinWaitFor(EVENT_TIMEOUT, [&] { + return cm.getRunningForegroundZoneId() == "zone2"; + })); } -BOOST_AUTO_TEST_CASE(EventTenAtATime) +BOOST_AUTO_TEST_CASE(MultipleEvent) { - sendNEvents(*this, 10); + ZonesManager cm(getPoll(), TEST_CONFIG_PATH); + cm.start(); + cm.createZone("zone1", SIMPLE_TEMPLATE); + cm.createZone("zone2", SIMPLE_TEMPLATE); + cm.createZone("zone3", SIMPLE_TEMPLATE); + cm.restoreAll(); + for (int i = 1; i < 10; ++i) { + sendEvent(*this, cm); + std::string zoneId = "zone" + std::to_string(i % 3 + 1); + BOOST_CHECK(spinWaitFor(EVENT_TIMEOUT, [&] { + return cm.getRunningForegroundZoneId() == zoneId; + })); + } } namespace { -void sendNEventsWithPauses(Fixture& f, unsigned int noOfEventsToSend) +void sendEventWithPauses(Fixture& f, ZonesManager& cm) { - Latch eventLatch; - - InputMonitor inputMonitor(f.inputConfig, [&] {eventLatch.set();}); + InputMonitor inputMonitor(f.getPoll(), f.inputConfig, &cm); + inputMonitor.start(); int fd = ::open(TEST_INPUT_DEVICE.c_str(), O_WRONLY); BOOST_REQUIRE(fd >= 0); - for (unsigned int i = 0; i < noOfEventsToSend * f.inputConfig.numberOfEvents; ++i) { + for (int i = 0; i < f.inputConfig.numberOfEvents; ++i) { // Send first two bytes of the button pressed event f.ie.value = EVENT_BUTTON_PRESSED; f.ie.time.tv_usec += 5; @@ -191,22 +235,39 @@ void sendNEventsWithPauses(Fixture& f, unsigned int noOfEventsToSend) BOOST_CHECK(ret > 0); } BOOST_CHECK(::close(fd) >= 0); - BOOST_CHECK(eventLatch.waitForN(noOfEventsToSend, SINGLE_EVENT_TIMEOUT * noOfEventsToSend)); - - // Check if no more events are waiting - BOOST_CHECK(!eventLatch.wait(10)); } } // namespace -BOOST_AUTO_TEST_CASE(EventOneAtATimeWithPauses) +BOOST_AUTO_TEST_CASE(SingleEventWithPauses) { - sendNEventsWithPauses(*this, 1); + ZonesManager cm(getPoll(), TEST_CONFIG_PATH); + cm.start(); + cm.createZone("zone1", SIMPLE_TEMPLATE); + cm.createZone("zone2", SIMPLE_TEMPLATE); + cm.createZone("zone3", SIMPLE_TEMPLATE); + cm.restoreAll(); + sendEventWithPauses(*this, cm); + BOOST_CHECK(spinWaitFor(EVENT_TIMEOUT, [&] { + return cm.getRunningForegroundZoneId() == "zone2"; + })); } -BOOST_AUTO_TEST_CASE(EventTenAtATimeWithPauses) +BOOST_AUTO_TEST_CASE(MultipleEventWithPauses) { - sendNEventsWithPauses(*this, 10); + ZonesManager cm(getPoll(), TEST_CONFIG_PATH); + cm.start(); + cm.createZone("zone1", SIMPLE_TEMPLATE); + cm.createZone("zone2", SIMPLE_TEMPLATE); + cm.createZone("zone3", SIMPLE_TEMPLATE); + cm.restoreAll(); + for (int i = 1; i < 10; ++i) { + sendEventWithPauses(*this, cm); + std::string zoneId = "zone" + std::to_string(i % 3 + 1); + BOOST_CHECK(spinWaitFor(EVENT_TIMEOUT, [&] { + return cm.getRunningForegroundZoneId() == zoneId; + })); + } } -- 2.7.4 From 7d2ce1f9cfb60d4de3336fc3e8d7296f183daace Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 4 Aug 2015 12:17:23 +0200 Subject: [PATCH 13/16] lxcpp: fix linking of 3rd party binaries with lxcpp [Feature] N/A [Cause] To be finally able to link with lxcpp of 3rd party code [Solution] N/A [Verification] Link non-vasum program against liblxcpp Change-Id: I218756ace9d9217db87d3e19b820d35653a22153 --- libs/lxcpp/CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt index 4ea53ef..c7bd926 100644 --- a/libs/lxcpp/CMakeLists.txt +++ b/libs/lxcpp/CMakeLists.txt @@ -40,9 +40,10 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES ) ## Link libraries ############################################################## -INCLUDE_DIRECTORIES(${LIBS_FOLDER}) -INCLUDE_DIRECTORIES(${COMMON_FOLDER}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} Logger) +FIND_PACKAGE(Boost COMPONENTS system filesystem) +INCLUDE_DIRECTORIES(${LIBS_FOLDER} ${COMMON_FOLDER}) +INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${Boost_LIBRARIES} Logger) ## Generate the pc file ######################################################## CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY) -- 2.7.4 From 991d45a32263a07df6d1e1af42fba048f2b06bf6 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Fri, 31 Jul 2015 15:01:38 +0200 Subject: [PATCH 14/16] Cleanup cppcheck statistics [Feature] N/A [Cause] Cppcheck results reported on jenkins contains error/warning messages [Solution] Make code correction to satisfy cppcheck, add cppcheck configuration to suppress some messages (e.g. API funcs) [Verification] Have installed cppcheck >= v1.66 Perform ./tests/cppcheck/cppcheck.sh script before commiting to review Change-Id: Ice10bbc118ab921feb9cb7261d4a2bdc22282353 --- common/netlink/netlink-message.cpp | 7 ++++--- common/utils/same-thread-guard.hpp | 4 ++-- common/utils/worker.cpp | 2 +- libs/config/fields.hpp | 5 +---- libs/config/sqlite3/connection.cpp | 4 +--- libs/config/types.hpp | 2 +- libs/ipc/client.cpp | 1 + libs/ipc/internals/processor.hpp | 4 +--- libs/ipc/internals/socket.cpp | 8 ++++++-- server/host-dbus-connection.cpp | 3 ++- server/host-dbus-connection.hpp | 2 +- server/netdev.cpp | 2 +- server/zone-provision.cpp | 8 ++++---- server/zone-provision.hpp | 8 ++++---- server/zones-manager.cpp | 2 +- tests/cppcheck/cppcheck.sh | 15 +++++++++++++++ tests/cppcheck/cppcheck.suppress | 7 +++++++ tests/unit_tests/config/testconfig-example.hpp | 13 +++++++------ tests/unit_tests/ipc/ut-ipc.cpp | 7 +------ tests/unit_tests/lxc/ut-zone.cpp | 4 ++-- tests/unit_tests/server/ut-server.cpp | 2 +- tests/unit_tests/server/ut-zone-provision.cpp | 6 +++--- tests/unit_tests/server/ut-zone.cpp | 4 ++-- wrapper/wrapper-compatibility.cpp | 21 ++++++++++----------- zone-daemon/daemon.cpp | 10 ++++++---- zone-daemon/daemon.hpp | 6 +++--- zone-daemon/runner.hpp | 4 ++-- 27 files changed, 90 insertions(+), 71 deletions(-) create mode 100755 tests/cppcheck/cppcheck.sh create mode 100644 tests/cppcheck/cppcheck.suppress diff --git a/common/netlink/netlink-message.cpp b/common/netlink/netlink-message.cpp index 29b079a..58aa1a2 100644 --- a/common/netlink/netlink-message.cpp +++ b/common/netlink/netlink-message.cpp @@ -289,14 +289,15 @@ inline int NetlinkResponse::getHdrPosition() const NetlinkResponse send(const NetlinkMessage& msg, int pid) { - assert(msg.hdr().nlmsg_flags & NLM_F_ACK); + const auto &hdr = msg.hdr(); + assert(hdr.nlmsg_flags & NLM_F_ACK); std::unique_ptr> data; Netlink nl; nl.open(pid); try { - nl.send(&msg.hdr()); - data = nl.rcv(msg.hdr().nlmsg_seq); + nl.send(&hdr); + data = nl.rcv(hdr.nlmsg_seq); } catch (const std::exception& ex) { LOGE("Sending failed (" << ex.what() << ")"); nl.close(); diff --git a/common/utils/same-thread-guard.hpp b/common/utils/same-thread-guard.hpp index 3a173b5..ec62b70 100644 --- a/common/utils/same-thread-guard.hpp +++ b/common/utils/same-thread-guard.hpp @@ -67,8 +67,8 @@ private: #else // ENABLE_SAME_THREAD_GUARD # define ASSERT_SAME_THREAD(g) - bool check() {return true;} - void reset() {} + static bool check() {return true;} + static void reset() {} #endif // ENABLE_SAME_THREAD_GUARD }; diff --git a/common/utils/worker.cpp b/common/utils/worker.cpp index 09069e8..eeac593 100644 --- a/common/utils/worker.cpp +++ b/common/utils/worker.cpp @@ -145,7 +145,7 @@ private: LOGT("Worker thread exited"); } - void execute(const TaskInfo& taskInfo) + static void execute(const TaskInfo& taskInfo) { try { LOGT("Executing task from subgroup " << taskInfo.groupID); diff --git a/libs/config/fields.hpp b/libs/config/fields.hpp index 8169cb4..d1fc4be 100644 --- a/libs/config/fields.hpp +++ b/libs/config/fields.hpp @@ -60,10 +60,7 @@ #define CONFIG_REGISTER_EMPTY \ template \ - void accept(Visitor ) { \ - } \ - template \ - void accept(Visitor ) const { \ + static void accept(Visitor ) { \ } \ #define CONFIG_REGISTER(...) \ diff --git a/libs/config/sqlite3/connection.cpp b/libs/config/sqlite3/connection.cpp index cb25694..3887352 100644 --- a/libs/config/sqlite3/connection.cpp +++ b/libs/config/sqlite3/connection.cpp @@ -50,9 +50,7 @@ Connection::Connection(const std::string& path) Connection::~Connection() { - if (::sqlite3_close(mDbPtr) != SQLITE_OK) { - throw ConfigException("Error during closing the database. Error: " + getErrorMessage()); - } + ::sqlite3_close(mDbPtr); } void Connection::exec(const std::string& query) diff --git a/libs/config/types.hpp b/libs/config/types.hpp index 3355f8f..f8b788d 100644 --- a/libs/config/types.hpp +++ b/libs/config/types.hpp @@ -41,4 +41,4 @@ struct FileDescriptor { }// config -#endif //COMMON_CONFIG_TYPES_HPP \ No newline at end of file +#endif //COMMON_CONFIG_TYPES_HPP diff --git a/libs/ipc/client.cpp b/libs/ipc/client.cpp index ad2eb47..245faee 100644 --- a/libs/ipc/client.cpp +++ b/libs/ipc/client.cpp @@ -32,6 +32,7 @@ namespace ipc { Client::Client(epoll::EventPoll& eventPoll, const std::string& socketPath) : mEventPoll(eventPoll), + mServiceID(-1), mProcessor(eventPoll, "[CLIENT] "), mSocketPath(socketPath) { diff --git a/libs/ipc/internals/processor.hpp b/libs/ipc/internals/processor.hpp index 4d0089f..7f7cd63 100644 --- a/libs/ipc/internals/processor.hpp +++ b/libs/ipc/internals/processor.hpp @@ -329,8 +329,6 @@ public: FileDescriptor getEventFD(); private: - typedef std::function& data)> SerializeCallback; - typedef std::function(int fd)> ParseCallback; typedef std::unique_lock Lock; typedef RequestQueue::Request Request; @@ -340,7 +338,7 @@ private: struct RegisterSignalsProtocolMessage { RegisterSignalsProtocolMessage() = default; - RegisterSignalsProtocolMessage(const std::vector ids) + RegisterSignalsProtocolMessage(const std::vector& ids) : ids(ids) {} std::vector ids; diff --git a/libs/ipc/internals/socket.cpp b/libs/ipc/internals/socket.cpp index 1961a52..c58809d 100644 --- a/libs/ipc/internals/socket.cpp +++ b/libs/ipc/internals/socket.cpp @@ -182,11 +182,15 @@ int Socket::createSocketInternal(const std::string& path) Socket Socket::createSocket(const std::string& path) { // Initialize a socket - int fd = -1; + int fd; #ifdef HAVE_SYSTEMD fd = getSystemdSocketInternal(path); + if (fd == -1) { + fd = createSocketInternal(path); + } +#else + fd = createSocketInternal(path); #endif // HAVE_SYSTEMD - fd = fd != -1 ? fd : createSocketInternal(path); return Socket(fd); } diff --git a/server/host-dbus-connection.cpp b/server/host-dbus-connection.cpp index 1229acb..ce415c8 100644 --- a/server/host-dbus-connection.cpp +++ b/server/host-dbus-connection.cpp @@ -424,8 +424,9 @@ void HostDbusConnection::onSignalCall(const std::string& /* senderBusName */, const std::string& objectPath, const std::string& interface, const std::string& /* signalName */, - GVariant* /* parameters */) + GVariant* /* parameters */) const { + (void)this; // satisfy cpp-check if (objectPath != api::dbus::OBJECT_PATH || interface != api::dbus::INTERFACE) { return; } diff --git a/server/host-dbus-connection.hpp b/server/host-dbus-connection.hpp index bb59afc..1a703e7 100644 --- a/server/host-dbus-connection.hpp +++ b/server/host-dbus-connection.hpp @@ -97,7 +97,7 @@ private: const std::string& objectPath, const std::string& interface, const std::string& signalName, - GVariant* parameters); + GVariant* parameters) const; }; diff --git a/server/netdev.cpp b/server/netdev.cpp index bf2576c..3086e7f 100644 --- a/server/netdev.cpp +++ b/server/netdev.cpp @@ -595,7 +595,7 @@ void setAttrs(const pid_t nsPid, const std::string& netdev, const Attrs& attrs) size_t pos = addrAttr.find(":"); if (pos == string::npos || pos == addrAttr.length()) { LOGE("Wrong input data format: ill formed address attribute: " << addrAttr); - VasumException("Wrong input data format: ill formed address attribute"); + throw VasumException("Wrong input data format: ill formed address attribute"); } attrs.push_back(make_tuple(addrAttr.substr(0, pos), addrAttr.substr(pos + 1))); } diff --git a/server/zone-provision.cpp b/server/zone-provision.cpp index 70c3711..4e99f83 100644 --- a/server/zone-provision.cpp +++ b/server/zone-provision.cpp @@ -255,7 +255,7 @@ void ZoneProvision::link(const ZoneProvisioningConfig::Link& config) throw UtilsException("Failed to hard link: path prefix is not valid"); } -std::string ZoneProvision::getId(const ZoneProvisioningConfig::File& file) const +std::string ZoneProvision::getId(const ZoneProvisioningConfig::File& file) { //TODO output of type,flags and mode should be more user friendly return "file " + @@ -265,7 +265,7 @@ std::string ZoneProvision::getId(const ZoneProvisioningConfig::File& file) const std::to_string(file.mode); } -std::string ZoneProvision::getId(const ZoneProvisioningConfig::Mount& mount) const +std::string ZoneProvision::getId(const ZoneProvisioningConfig::Mount& mount) { //TODO output of flags should be more user friendly return "mount " + @@ -276,12 +276,12 @@ std::string ZoneProvision::getId(const ZoneProvisioningConfig::Mount& mount) con mount.data; } -std::string ZoneProvision::getId(const ZoneProvisioningConfig::Link& link) const +std::string ZoneProvision::getId(const ZoneProvisioningConfig::Link& link) { return "link " + link.source + " " + link.target; } -std::string ZoneProvision::getId(const ZoneProvisioningConfig::Provision& provision) const +std::string ZoneProvision::getId(const ZoneProvisioningConfig::Provision& provision) { using namespace vasum; if (provision.is()) { diff --git a/server/zone-provision.hpp b/server/zone-provision.hpp index 2f123ae..cf3d5c6 100644 --- a/server/zone-provision.hpp +++ b/server/zone-provision.hpp @@ -113,10 +113,10 @@ private: void file(const ZoneProvisioningConfig::File& config); void link(const ZoneProvisioningConfig::Link& config); - std::string getId(const ZoneProvisioningConfig::File& file) const; - std::string getId(const ZoneProvisioningConfig::Mount& mount) const; - std::string getId(const ZoneProvisioningConfig::Link& link) const; - std::string getId(const ZoneProvisioningConfig::Provision& provision) const; + static std::string getId(const ZoneProvisioningConfig::File& file); + static std::string getId(const ZoneProvisioningConfig::Mount& mount); + static std::string getId(const ZoneProvisioningConfig::Link& link); + static std::string getId(const ZoneProvisioningConfig::Provision& provision); }; } // namespace vasum diff --git a/server/zones-manager.cpp b/server/zones-manager.cpp index 0d88d24..5280d21 100644 --- a/server/zones-manager.cpp +++ b/server/zones-manager.cpp @@ -399,7 +399,7 @@ void ZonesManager::focusInternal(Zones::iterator iter) } Zone& zoneToFocus = get(iter); - const std::string idToFocus = zoneToFocus.getId(); + const std::string& idToFocus = zoneToFocus.getId(); if (idToFocus == mActiveZoneId) { return; diff --git a/tests/cppcheck/cppcheck.sh b/tests/cppcheck/cppcheck.sh new file mode 100755 index 0000000..b8bb637 --- /dev/null +++ b/tests/cppcheck/cppcheck.sh @@ -0,0 +1,15 @@ +#!/bin/bash +OPT="" +OPT+=" --enable=all" +OPT+=" --std=c++11" +OPT+=" --inconclusive" +OPT+=" --suppressions tests/cppcheck/cppcheck.suppress" +OPT+=" --suppress=missingIncludeSystem" +OPT+=" --inline-suppr" +OPT+=" -iCMakeFiles" +OPT+=" -I common" +OPT+=" -I libs" +OPT+=" -I client" +OPT+=" -I server" +OPT+=" -U__NR_capset" +cppcheck ${OPT} --template=gcc ./ 1>/dev/null diff --git a/tests/cppcheck/cppcheck.suppress b/tests/cppcheck/cppcheck.suppress new file mode 100644 index 0000000..d3b098f --- /dev/null +++ b/tests/cppcheck/cppcheck.suppress @@ -0,0 +1,7 @@ +// public API functions (or write tests to use them all) +unusedFunction:wrapper/wrapper-compatibility.cpp +unusedFunction:wrapper/wrapper.cpp + +// lambda not recognized to catch exception (v1.68) +exceptThrowInNoexecptFunction:client/vasum-client-impl.cpp + diff --git a/tests/unit_tests/config/testconfig-example.hpp b/tests/unit_tests/config/testconfig-example.hpp index ff5c2ef..549985b 100644 --- a/tests/unit_tests/config/testconfig-example.hpp +++ b/tests/unit_tests/config/testconfig-example.hpp @@ -34,13 +34,7 @@ struct TestConfig { struct SubConfig { struct SubSubConfig { - int intVal; - bool moved; - CONFIG_REGISTER - ( - intVal - ) SubSubConfig() : intVal(), moved(false) {} SubSubConfig(const SubSubConfig& config) : intVal(config.intVal), moved(false) {} SubSubConfig(SubSubConfig&& config) : intVal(std::move(config.intVal)), moved(false) { @@ -60,6 +54,13 @@ struct TestConfig { bool isMoved() const { return moved; } + + int intVal; + bool moved; + CONFIG_REGISTER + ( + intVal + ) }; int intVal; diff --git a/tests/unit_tests/ipc/ut-ipc.cpp b/tests/unit_tests/ipc/ut-ipc.cpp index ab920fe..8bb829e 100644 --- a/tests/unit_tests/ipc/ut-ipc.cpp +++ b/tests/unit_tests/ipc/ut-ipc.cpp @@ -159,15 +159,10 @@ struct EmptyData { struct ThrowOnAcceptData { template - void accept(Visitor) + static void accept(Visitor) { throw std::runtime_error("intentional failure in accept"); } - template - void accept(Visitor) const - { - throw std::runtime_error("intentional failure in accept const"); - } }; void returnEmptyCallback(const PeerID, diff --git a/tests/unit_tests/lxc/ut-zone.cpp b/tests/unit_tests/lxc/ut-zone.cpp index 6702773..80c003f 100644 --- a/tests/unit_tests/lxc/ut-zone.cpp +++ b/tests/unit_tests/lxc/ut-zone.cpp @@ -60,7 +60,7 @@ struct Fixture { cleanup(); } - void cleanup() + static void cleanup() { LxcZone lxc(ZONE_PATH, ZONE_NAME); if (lxc.isDefined()) { @@ -71,7 +71,7 @@ struct Fixture { } } - void waitForInit() + static void waitForInit() { // wait for init fully started (wait for bash to be able to trap SIGTERM) std::this_thread::sleep_for(std::chrono::milliseconds(200)); diff --git a/tests/unit_tests/server/ut-server.cpp b/tests/unit_tests/server/ut-server.cpp index e4d1ce4..79a7d72 100644 --- a/tests/unit_tests/server/ut-server.cpp +++ b/tests/unit_tests/server/ut-server.cpp @@ -63,7 +63,7 @@ struct Fixture { LOGI("------------ setup complete -----------"); } - void prepare() + static void prepare() { ScopedGlibLoop loop; ipc::epoll::ThreadDispatcher mDispatcher; diff --git a/tests/unit_tests/server/ut-zone-provision.cpp b/tests/unit_tests/server/ut-zone-provision.cpp index 45a74d7..034552e 100644 --- a/tests/unit_tests/server/ut-zone-provision.cpp +++ b/tests/unit_tests/server/ut-zone-provision.cpp @@ -69,7 +69,7 @@ struct Fixture { BOOST_REQUIRE(utils::saveFileContent(SOME_FILE_PATH.string(), "text")); } - ZoneProvision create(const std::vector& validLinkPrefixes) + static ZoneProvision create(const std::vector& validLinkPrefixes) { return ZoneProvision(ROOTFS_PATH.string(), TEST_CONFIG_PATH, @@ -78,12 +78,12 @@ struct Fixture { validLinkPrefixes); } - void load(ZoneProvisioningConfig& config) + static void load(ZoneProvisioningConfig& config) { config::loadFromKVStoreWithJsonFile(DB_PATH.string(), TEST_CONFIG_PATH, config, DB_PREFIX); } - void save(const ZoneProvisioningConfig& config) + static void save(const ZoneProvisioningConfig& config) { config::saveToKVStore(DB_PATH.string(), config, DB_PREFIX); } diff --git a/tests/unit_tests/server/ut-zone.cpp b/tests/unit_tests/server/ut-zone.cpp index e492c37..0072d74 100644 --- a/tests/unit_tests/server/ut-zone.cpp +++ b/tests/unit_tests/server/ut-zone.cpp @@ -102,12 +102,12 @@ struct Fixture { } - void ensureStarted() + static void ensureStarted() { // wait for zones init to fully start std::this_thread::sleep_for(std::chrono::milliseconds(200)); } - void ensureStop() + static void ensureStop() { // wait for fully stop std::this_thread::sleep_for(std::chrono::milliseconds(200)); diff --git a/wrapper/wrapper-compatibility.cpp b/wrapper/wrapper-compatibility.cpp index 634c187..04c043d 100644 --- a/wrapper/wrapper-compatibility.cpp +++ b/wrapper/wrapper-compatibility.cpp @@ -342,10 +342,9 @@ API int wait_for_pid_status(pid_t pid) API vsm_fso_type_t fso_string_to_type(char *str) { LOGS(""); - int len; int i; for (i = 0; i <= VSM_FSO_MAX_TYPE; i++) { - len = strlen(fso_type_strtab[i]); + int len = strlen(fso_type_strtab[i]); if (strncmp(str, fso_type_strtab[i], len) == 0) return static_cast(i); } @@ -358,12 +357,11 @@ API int mkdir_p(const char *dir, mode_t mode) LOGS(""); const char *tmp = dir; const char *orig = dir; - char *makeme; do { dir = tmp + strspn(tmp, "/"); tmp = dir + strcspn(dir, "/"); - makeme = strndup(orig, dir - orig); + char *makeme = strndup(orig, dir - orig); if (*makeme) { if (mkdir(makeme, mode) && errno != EEXIST) { free(makeme); @@ -421,8 +419,6 @@ API int remove_file(char *path) { LOGS(""); struct stat path_stat; - DIR *dp; - struct dirent *d; int status = 0; if (lstat(path, &path_stat) < 0) { @@ -433,6 +429,8 @@ API int remove_file(char *path) } if (S_ISDIR(path_stat.st_mode)) { + struct dirent *d; + DIR *dp; if ((dp = opendir(path)) == NULL) { ERROR("Unable to opendir %s", path); return -1; @@ -475,7 +473,6 @@ API int copy_file(const char *source, const char *dest, int /*flags*/) LOGS(""); int ret; FILE *sfp, *dfp; - size_t nread, nwritten, size = BUF_SIZE; char buffer[BUF_SIZE]; if ((sfp = fopen(source, "r")) == NULL) { @@ -490,6 +487,7 @@ API int copy_file(const char *source, const char *dest, int /*flags*/) } while (1) { + size_t nread, nwritten, size = BUF_SIZE; nread = fread(buffer, 1, size, sfp); if (nread != size && ferror(sfp)) { @@ -840,7 +838,7 @@ API pid_t get_init_pid(const char *name) fp = fopen(filename, "r"); if (fp != NULL) { - if (fscanf(fp, "%d", &ret) < 0) { + if (fscanf(fp, "%7d", &ret) < 0) { ERROR("Failed to read %s\n", filename); ret = -2; } @@ -894,7 +892,7 @@ API pid_t get_zone_pid(const char *name, const char *target) FILE *cmdfp; char cmdpath[PATH_MAX]; - res = sscanf(line, "%d", &pid); + res = sscanf(line, "%7d", &pid); if (res != 1) { ERROR("Failed to read %s\n", path); res = -1; @@ -915,7 +913,7 @@ API pid_t get_zone_pid(const char *name, const char *target) continue; } - if (fscanf(cmdfp, "%s", cmd) < 0) { + if (fscanf(cmdfp, "%1023s", cmd) < 0) { ERROR("Failed to read cmdline - pid : %d\n", pid); continue; } @@ -1271,11 +1269,12 @@ static int parse_statement(struct parser_context *ctx, int argc, char **argv, { struct parser_state state; char *args[PARSER_MAXARGS]; - int i, nargs, done, rc; + int i; int ret = 0; UNUSED(ctx); for (i = 0; i < argc; i++) { + int nargs, done, rc; done = nargs = 0; parser_init_state(&state, argv[i]); diff --git a/zone-daemon/daemon.cpp b/zone-daemon/daemon.cpp index 0ded40a..c4979e0 100644 --- a/zone-daemon/daemon.cpp +++ b/zone-daemon/daemon.cpp @@ -45,21 +45,23 @@ Daemon::~Daemon() { } -void Daemon::onNameLostCallback() +void Daemon::onNameLostCallback() const { + (void)this; // satisfy cpp-check //TODO: Try to reconnect or close the daemon. LOGE("Dbus name lost"); } -void Daemon::onGainFocusCallback() +void Daemon::onGainFocusCallback() const { + (void)this; // satisfy cpp-check LOGD("Gained Focus"); } -void Daemon::onLoseFocusCallback() +void Daemon::onLoseFocusCallback() const { + (void)this; // satisfy cpp-check LOGD("Lost Focus"); - } } // namespace zone_daemon diff --git a/zone-daemon/daemon.hpp b/zone-daemon/daemon.hpp index 92dcccf..ab52e69 100644 --- a/zone-daemon/daemon.hpp +++ b/zone-daemon/daemon.hpp @@ -40,9 +40,9 @@ public: virtual ~Daemon(); private: - void onNameLostCallback(); - void onGainFocusCallback(); - void onLoseFocusCallback(); + void onNameLostCallback() const; + void onGainFocusCallback() const; + void onLoseFocusCallback() const; std::unique_ptr mConnectionPtr; }; diff --git a/zone-daemon/runner.hpp b/zone-daemon/runner.hpp index 1a88530..1827553 100644 --- a/zone-daemon/runner.hpp +++ b/zone-daemon/runner.hpp @@ -39,13 +39,13 @@ public: /** * Starts all the daemon and blocks until SIGINT or SIGTERM */ - void run(); + static void run(); /** * Terminates the daemon. * Equivalent of sending SIGINT or SIGTERM signal */ - void terminate(); + static void terminate(); }; -- 2.7.4 From 36dfc7551f4fca721d364638b1a6191908ce34dd Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Thu, 30 Jul 2015 14:04:25 +0200 Subject: [PATCH 15/16] Support getting list of ip/mask for one interface, change netdev_set_ip* to netdev_add_ip* [Feature] Get list of configured ip/mask for zone interface [Cause] Many ip/mask entries can be assigned to one interface [Solution] Implement generic method getting list of network addresses [Verification] Build, install, use vsm net-add-ip to add ips vsm net-list to get configured ips Change-Id: I8d4c1b59e03800aa513811992cc13e71df8d599e --- cli/command-line-interface.cpp | 32 ++++++++------------ client/vasum-client-impl.cpp | 68 ++++++++++++++++++++++++++++-------------- client/vasum-client-impl.hpp | 29 +++++++++++++----- client/vasum-client.cpp | 49 +++++++++++++++++++++++++++--- client/vasum-client.h | 61 ++++++++++++++++++++++++++++++++++--- 5 files changed, 181 insertions(+), 58 deletions(-) diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp index e8922ee..86bc808 100644 --- a/cli/command-line-interface.cpp +++ b/cli/command-line-interface.cpp @@ -562,8 +562,6 @@ void netdev_list(const Args& argv) } else { VsmNetdev netdev = NULL; - in_addr ipv4; - in6_addr ipv6; char buf[INET_ADDRSTRLEN|INET6_ADDRSTRLEN]; CommandLineInterface::executeCallback(bind(vsm_lookup_netdev_by_name, _1, @@ -573,25 +571,21 @@ void netdev_list(const Args& argv) cout << netdevToString(netdev) << endl; vsm_netdev_free(netdev); - CommandLineInterface::executeCallback(bind(vsm_netdev_get_ipv4_addr, + VsmAddrList addrs = NULL; + CommandLineInterface::executeCallback(bind(vsm_netdev_get_ip_addr, _1, argv[1].c_str(), argv[2].c_str(), - &ipv4)); - if (inet_ntop(AF_INET, &ipv4, buf, INET_ADDRSTRLEN) == NULL) { - throw runtime_error("Wrong address received"); + &addrs)); + unsigned listsize = vsm_addrlist_size(addrs); + for (unsigned i=0; i < listsize; ++i) { + int type=vsm_addrlist_get_type(addrs, i); + if (inet_ntop(type, vsm_addrlist_get_addr(addrs, i), buf, INET6_ADDRSTRLEN) == NULL) { + throw runtime_error("Wrong address received ["+std::to_string(i)+"] type="+std::to_string(type)); + } + cout << buf << "/" << vsm_addrlist_get_prefix(addrs, i) << endl; } - cout << buf << endl; - - CommandLineInterface::executeCallback(bind(vsm_netdev_get_ipv6_addr, - _1, - argv[1].c_str(), - argv[2].c_str(), - &ipv6)); - if (inet_ntop(AF_INET6, &ipv6, buf, INET6_ADDRSTRLEN) == NULL) { - throw runtime_error("Wrong address received"); - } - cout << buf << endl; + vsm_addrlist_free(addrs); } } @@ -606,7 +600,7 @@ void netdev_add_ip_addr(const Args& argv) if (inet_pton(AF_INET, argv[3].c_str(), &addr) != 1) { throw runtime_error("Wrong address format"); }; - CommandLineInterface::executeCallback(bind(vsm_netdev_set_ipv4_addr, + CommandLineInterface::executeCallback(bind(vsm_netdev_add_ipv4_addr, _1, argv[1].c_str(), argv[2].c_str(), @@ -618,7 +612,7 @@ void netdev_add_ip_addr(const Args& argv) if (inet_pton(AF_INET6, argv[3].c_str(), &addr) != 1) { throw runtime_error("Wrong address format"); }; - CommandLineInterface::executeCallback(bind(vsm_netdev_set_ipv6_addr, + CommandLineInterface::executeCallback(bind(vsm_netdev_add_ipv6_addr, _1, argv[1].c_str(), argv[2].c_str(), diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index 15cccf6..e3aca1d 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -525,42 +525,48 @@ VsmStatus Client::vsm_zone_get_netdevs(const char* id, VsmArrayString* netdevIds VsmStatus Client::vsm_netdev_get_ip_addr(const char* id, const char* netdevId, - int type, - void* addr) noexcept + std::vector& addrs) noexcept { using namespace boost::algorithm; return coverException([&] { IS_SET(id); IS_SET(netdevId); - IS_SET(addr); + + addrs.clear(); api::GetNetDevAttrs attrs = *mClient->callSync( api::ipc::METHOD_GET_NETDEV_ATTRS, std::make_shared(api::GetNetDevAttrsIn{ id, netdevId })); - auto it = find_if(attrs.values.begin(), - attrs.values.end(), - [type](const api::StringPair& entry) { - return entry.first == (type == AF_INET ? "ipv4" : "ipv6"); - }); + for (const auto &attr : attrs.values) { + InetAddr addr; + if (attr.first == "ipv4") { + addr.type = AF_INET; + } + else if (attr.first == "ipv6") { + addr.type = AF_INET6; + } + else continue; - if (it != attrs.values.end()) { - vector addrAttrs; - for(auto addrAttr : split(addrAttrs, it->second, is_any_of(","))) { + std::vector addrAttrs; + for(const auto& addrAttr : split(addrAttrs, attr.second, is_any_of(","))) { size_t pos = addrAttr.find(":"); - if (addrAttr.substr(0, pos) == "ip") { - if (pos != string::npos && pos < addrAttr.length() && - inet_pton(type, addrAttr.substr(pos + 1).c_str(), addr) == 1) { - //XXX: return only one address - return; - } else { - throw InvalidResponseException("Wrong address format returned"); + if (pos == string::npos) continue; + + if (addrAttr.substr(0, pos) == "prefixlen") { + addr.prefix = atoi(addrAttr.substr(pos + 1).c_str()); + } + else if (addrAttr.substr(0, pos) == "ip") { + if (inet_pton(addr.type, addrAttr.substr(pos + 1).c_str(), &addr.addr) != 1) { + addr.type = -1; + break; } } } + if (addr.type >= 0) + addrs.push_back(addr); } - throw OperationFailedException("Address not found"); }); } @@ -568,17 +574,33 @@ VsmStatus Client::vsm_netdev_get_ipv4_addr(const char* id, const char* netdevId, struct in_addr* addr) noexcept { - return vsm_netdev_get_ip_addr(id, netdevId, AF_INET, addr); + std::vector addrs; + VsmStatus st=vsm_netdev_get_ip_addr(id, netdevId, addrs); + for (const auto& a : addrs) { + if (a.type == AF_INET) { + memcpy(addr, &a.addr, sizeof(*addr)); + break; + } + } + return st; } VsmStatus Client::vsm_netdev_get_ipv6_addr(const char* id, const char* netdevId, struct in6_addr* addr) noexcept { - return vsm_netdev_get_ip_addr(id, netdevId, AF_INET6, addr); + std::vector addrs; + VsmStatus st=vsm_netdev_get_ip_addr(id, netdevId, addrs); + for (const auto& a : addrs) { + if (a.type == AF_INET6) { + memcpy(addr, &a.addr, sizeof(*addr)); + break; + } + } + return st; } -VsmStatus Client::vsm_netdev_set_ipv4_addr(const char* id, +VsmStatus Client::vsm_netdev_add_ipv4_addr(const char* id, const char* netdevId, struct in_addr* addr, int prefix) noexcept @@ -596,7 +618,7 @@ VsmStatus Client::vsm_netdev_set_ipv4_addr(const char* id, }); } -VsmStatus Client::vsm_netdev_set_ipv6_addr(const char* id, +VsmStatus Client::vsm_netdev_add_ipv6_addr(const char* id, const char* netdevId, struct in6_addr* addr, int prefix) noexcept diff --git a/client/vasum-client-impl.hpp b/client/vasum-client-impl.hpp index 4297c95..dbc9001 100644 --- a/client/vasum-client-impl.hpp +++ b/client/vasum-client-impl.hpp @@ -64,6 +64,19 @@ typedef struct NetdevStructure { } *Netdev; /** + * Network interface information structure + */ +typedef struct { + int type; + int prefix; + union { + struct in_addr ipv4; + struct in6_addr ipv6; + } addr; +} InetAddr; + + +/** * vasum's client definition. * * Client uses dbus API. @@ -227,6 +240,10 @@ public: */ VsmStatus vsm_zone_get_netdevs(const char* zone, VsmArrayString* netdevIds) noexcept; + VsmStatus vsm_netdev_get_ip_addr(const char* zone, + const char* netdevId, + std::vector& addrs) noexcept; + /** * @see ::vsm_netdev_get_ipv4_addr */ @@ -242,17 +259,17 @@ public: struct in6_addr *addr) noexcept; /** - * @see ::vsm_netdev_set_ipv4_addr + * @see ::vsm_netdev_add_ipv4_addr */ - VsmStatus vsm_netdev_set_ipv4_addr(const char* zone, + VsmStatus vsm_netdev_add_ipv4_addr(const char* zone, const char* netdevId, struct in_addr *addr, int prefix) noexcept; /** - * @see ::vsm_netdev_set_ipv6_addr + * @see ::vsm_netdev_add_ipv6_addr */ - VsmStatus vsm_netdev_set_ipv6_addr(const char* zone, + VsmStatus vsm_netdev_add_ipv6_addr(const char* zone, const char* netdevId, struct in6_addr *addr, int prefix) noexcept; @@ -376,10 +393,6 @@ private: bool isInternalDispatcherEnabled() const; ipc::epoll::EventPoll& getEventPoll() const; VsmStatus coverException(const std::function& worker) noexcept; - VsmStatus vsm_netdev_get_ip_addr(const char* zone, - const char* netdevId, - int type, - void* addr) noexcept; }; #endif /* VASUM_CLIENT_IMPL_HPP */ diff --git a/client/vasum-client.cpp b/client/vasum-client.cpp index ee3e6d4..9cf15b3 100644 --- a/client/vasum-client.cpp +++ b/client/vasum-client.cpp @@ -279,6 +279,21 @@ API VsmStatus vsm_zone_get_netdevs(VsmClient client, return getClient(client).vsm_zone_get_netdevs(zone, netdevIds); } +API VsmStatus vsm_netdev_get_ip_addr(VsmClient client, + const char* zone, + const char* netdevId, + VsmAddrList *addrs) +{ + std::vector addrlist; + VsmStatus status = getClient(client).vsm_netdev_get_ip_addr(zone, netdevId, addrlist); + int n = addrlist.size(); + InetAddr *a = (InetAddr *)malloc((n+1)*sizeof(InetAddr)); + std::copy(addrlist.begin(), addrlist.end(), a); + a[n].type=-1; + *addrs = a; + return status; +} + API VsmStatus vsm_netdev_get_ipv4_addr(VsmClient client, const char* zone, const char* netdevId, @@ -295,22 +310,22 @@ API VsmStatus vsm_netdev_get_ipv6_addr(VsmClient client, return getClient(client).vsm_netdev_get_ipv6_addr(zone, netdevId, addr); } -API VsmStatus vsm_netdev_set_ipv4_addr(VsmClient client, +API VsmStatus vsm_netdev_add_ipv4_addr(VsmClient client, const char* zone, const char* netdevId, struct in_addr *addr, int prefix) { - return getClient(client).vsm_netdev_set_ipv4_addr(zone, netdevId, addr, prefix); + return getClient(client).vsm_netdev_add_ipv4_addr(zone, netdevId, addr, prefix); } -API VsmStatus vsm_netdev_set_ipv6_addr(VsmClient client, +API VsmStatus vsm_netdev_add_ipv6_addr(VsmClient client, const char* zone, const char* netdevId, struct in6_addr *addr, int prefix) { - return getClient(client).vsm_netdev_set_ipv6_addr(zone, netdevId, addr, prefix); + return getClient(client).vsm_netdev_add_ipv6_addr(zone, netdevId, addr, prefix); } API VsmStatus vsm_netdev_del_ipv4_addr(VsmClient client, @@ -430,3 +445,29 @@ API VsmStatus vsm_clean_up_zones_root(VsmClient client) return getClient(client).vsm_clean_up_zones_root(); } +API unsigned int vsm_addrlist_size(VsmAddrList addrs) +{ + InetAddr *a = static_cast(addrs); + unsigned int i; + for (i = 0; a[i].type >= 0; ++i) ; + return i; +} + +API int vsm_addrlist_get_type(VsmAddrList addrs, unsigned int i) +{ + return static_cast(addrs)[i].type; +} + +API const void *vsm_addrlist_get_addr(VsmAddrList addrs, unsigned int i) +{ + return &static_cast(addrs)[i].addr; +} + +API unsigned int vsm_addrlist_get_prefix(VsmAddrList addrs, unsigned int i) +{ + return static_cast(addrs)[i].prefix; +} + +API void vsm_addrlist_free(VsmAddrList addrs) { + free(addrs); +} diff --git a/client/vasum-client.h b/client/vasum-client.h index b696dcf..253306d 100644 --- a/client/vasum-client.h +++ b/client/vasum-client.h @@ -186,6 +186,7 @@ typedef char* VsmString; */ typedef VsmString* VsmArrayString; +typedef void *VsmAddrList; /** * Completion status of libvasum-client's functions */ @@ -652,6 +653,29 @@ VsmStatus vsm_revoke_device(VsmClient client, const char* zone, const char* devi */ VsmStatus vsm_zone_get_netdevs(VsmClient client, const char* zone, VsmArrayString* netdevIds); + +/** + * Get ipv4 address for given netdevId + * + * @param[in] client vasum-server's client + * @param[in] zone zone name + * @param[in] netdevId netdev id + * @param[out] addrs ip address array + * @return status of this function call + * @remark Use vsm_netdev_addr_free() to free memory occupied by address array. + */ +VsmStatus vsm_netdev_get_ip_addr(VsmClient client, + const char* zone, + const char* netdevId, + VsmAddrList *addrs); + +/** + * Release VsmAddrList + * + * @param addrs VsmAddrList + */ +void vsm_addrlist_free(VsmAddrList addrs); + /** * Get ipv4 address for given netdevId * @@ -681,7 +705,7 @@ VsmStatus vsm_netdev_get_ipv6_addr(VsmClient client, struct in6_addr *addr); /** - * Set ipv4 address for given netdevId + * Add ipv4 address for given netdevId * * @param[in] client vasum-server's client * @param[in] zone zone name @@ -690,14 +714,14 @@ VsmStatus vsm_netdev_get_ipv6_addr(VsmClient client, * @param[in] prefix bit-length of the network prefix * @return status of this function call */ -VsmStatus vsm_netdev_set_ipv4_addr(VsmClient client, +VsmStatus vsm_netdev_add_ipv4_addr(VsmClient client, const char* zone, const char* netdevId, struct in_addr *addr, int prefix); /** - * Set ipv6 address for given netdevId + * Add ipv6 address for given netdevId * * @param[in] client vasum-server's client * @param[in] zone zone name @@ -706,7 +730,7 @@ VsmStatus vsm_netdev_set_ipv4_addr(VsmClient client, * @param[in] prefix bit-length of the network prefix * @return status of this function call */ -VsmStatus vsm_netdev_set_ipv6_addr(VsmClient client, +VsmStatus vsm_netdev_add_ipv6_addr(VsmClient client, const char* zone, const char* netdevId, struct in6_addr *addr, @@ -933,6 +957,35 @@ VsmStatus vsm_remove_declaration(VsmClient client, */ VsmStatus vsm_clean_up_zones_root(VsmClient client); +/** + * Retrieve array size + * + * @return array size + */ +unsigned int vsm_addrlist_size(VsmAddrList addrs); + +/** + * Get address type for i'th entry + * + * @return network type (AF_INET or AF_INET6) + */ +int vsm_addrlist_get_type(VsmAddrList addrs, unsigned int i); + +/** + * Get pointer to in_addr property for i'th entry + * see inet_ntop man pages + * + * @return poiner of in_addr + */ +const void *vsm_addrlist_get_addr(VsmAddrList addrs, unsigned int i); + +/** + * Get address prefix for i'th entry + * + * @return adress prefix (mask bits count) + */ +unsigned int vsm_addrlist_get_prefix(VsmAddrList addrs, unsigned int i); + #endif /* __VASUM_WRAPPER_SOURCE__ */ #ifdef __cplusplus -- 2.7.4 From 2e5e4e040a25202b5fdc868b24f0c2e0ba183662 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Fri, 7 Aug 2015 11:05:14 +0200 Subject: [PATCH 16/16] vsm: persistant history of entered commands in interactive mode [Feature] Keep history of entered commands (in ~/.vsm_history file) [Cause] No history after starting vsm [Solution] use read_history/write_history from readline library [Verification] Build, install, use vsm command Change-Id: I107ba49ac01d52825312416a11fbb094735401af --- cli/main.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cli/main.cpp b/cli/main.cpp index 9bec3e7..48a71f2 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -36,12 +36,15 @@ #include #include #include +#include #include #include using namespace vasum::cli; +namespace fs = boost::filesystem; + namespace { static int interactiveMode = 0; @@ -480,6 +483,12 @@ int cliMode(const int argc, const char** argv) return rc; } +fs::path getHomePath() { + const char *h = ::getenv("HOME"); + return fs::path(h ? h : ""); +} + + } // namespace @@ -508,13 +517,24 @@ int main(const int argc, const char *argv[]) } } else { + fs::path historyfile(".vsm_history"); if (isatty(0) == 1) { + fs::path home = getHomePath(); + if (!home.empty()) { + historyfile = home / historyfile; + } + ::read_history(historyfile.c_str()); + interactiveMode = 1; ::rl_attempted_completion_function = completion; } rc = processStream(std::cin); + + if (interactiveMode) { + ::write_history(historyfile.c_str()); + } } disconnect(); -- 2.7.4