Init: mediaserver

This commit is contained in:
2023-02-08 12:13:28 +01:00
parent 848bc9739c
commit f7c23d4ba9
31914 changed files with 6175775 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (c) 2020, Dell Inc. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (c) 2020, Dell Inc. All rights reserved.
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -0,0 +1,38 @@
{
"collection_info": {
"namespace": "dellemc",
"name": "os10",
"version": "1.1.1",
"authors": [
"Parameswaran Krishnamurthy <Parameswaran_Krishna@Dell.com>",
"Senthil Ganesan Ganesan <Senthil_Kumar_Ganesa@Dell.com>",
"Shreeja R <Shreeja_R@Dell.com>"
],
"readme": "README.md",
"tags": [
"dell",
"dellemc",
"os10",
"emc",
"networking"
],
"description": "Ansible Network Collection for Dell EMC SmartFabric OS10",
"license": [],
"license_file": "LICENSE",
"dependencies": {
"ansible.netcommon": ">=1.0.0"
},
"repository": "https://github.com/ansible-collections/dellemc.os10",
"documentation": "https://github.com/ansible-collections/dellemc.os10/tree/master/docs",
"homepage": "https://github.com/ansible-collections/dellemc.os10",
"issues": "https://github.com/ansible-collections/dellemc.os10/issues"
},
"file_manifest_file": {
"name": "FILES.json",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "afa56fa2200f773fcafd6a3cd52df1affca39c600c356d3bccb09fcc1b92bdfd",
"format": 1
},
"format": 1
}

View File

@@ -0,0 +1,93 @@
# Ansible Network Collection for Dell EMC SmartFabric OS10
### Collection contents
This collection includes Ansible modules, plugins and roles needed to provision and manage Dell EMC PowerSwitch platforms running Dell EMC SmartFabric OS10. Sample playbooks and documentation are also included to show how the collection can be used.
### Collection core modules
Name | Description
--- | ---
[os10_command](https://github.com/ansible-collections/dellemc.os10/blob/master/docs/dellemc.os10.os10_command_module.rst)| Run commands on devices running OS10
[os10_config](https://github.com/ansible-collections/dellemc.os10/blob/master/docs/dellemc.os10.os10_config_module.rst)| Manage configuration on devices running OS10
[os10_facts](https://github.com/ansible-collections/dellemc.os10/blob/master/docs/dellemc.os10.os10_facts_module.rst)| Collect facts from devices running OS10
### Collection roles
These roles facilitate the provisioning and administration of devices running SmartFabric OS10. There are over 30 roles available that provide a comprehensive coverage of most OS10 resources, including *os10_interface*, *os10_acl*, *os10_bgp*, and *os10_vxlan*. The documentation for each role is located at [OS10 roles](https://github.com/ansible-collections/dellemc.os10/blob/master/docs/roles.rst).
### Sample use case playbooks
This collection includes these sample playbooks that illustrate end-to-end use cases.
- [CLOS fabric](https://github.com/ansible-collections/dellemc.os10/blob/master/playbooks/clos_fabric_ebgp/README.md) — Example playbook to build a Layer 3 leaf-spine fabric
- [VXLAN EVPN](https://github.com/ansible-collections/dellemc.os10/blob/master/playbooks/vxlan_evpn/README.md) — Example playbook to build a scale-out leaf-spine topology using VxLAN, BGP EVPN, and symmetric-IRB
## Installation
Use this command to install the latest version of the OS10 collection from Ansible Galaxy.
ansible-galaxy collection install dellemc.os10
To install a specific version, a version range identifier must be specified. For example, to install the most recent version that is greater than or equal to 1.0.0 and less than 2.0.0.
ansible-galaxy collection install 'dellemc.os10:>=1.0.0,<2.0.0'
## Version compatibility
* Ansible version 2.9 or later.
* Python 3.5 or higher, or Python 2.7
### Using in Ansible version 2.9
> **NOTE**: This step is not required for Ansible version 2.10 or later.
To use this collection in Ansible version 2.9 it is required to set the below environment variable while running the playbook.
ANSIBLE_NETWORK_GROUP_MODULES=os10
It can be set permanently in *ansible.cfg* with variable *network_group_modules* under the *defaults* section.
**ansible.cfg**
[defaults]
network_group_modules=os10
> **NOTE**: For Ansible versions lower than 2.9, use the legacy [dellos10 modules](https://ansible-dellos-docs.readthedocs.io/en/latest/modules.html#os10-modules) and [dellos roles](https://ansible-dellos-docs.readthedocs.io/en/latest/roles.html).
## Sample playbook
**playbook.yaml**
- hosts: os10_switches
connection: network_cli
collections:
- dellemc.os10
roles:
- os10_vlan
**host_vars/os10_sw1.yaml**
hostname: os10_sw1
# Parameters for connection type network_cli
ansible_ssh_user: xxxx
ansible_ssh_pass: xxxx
ansible_network_os: dellemc.os10.os10
# Create vlan100 and delete vlan888
os10_vlan:
vlan 100:
description: "Blue"
state: present
vlan 888:
state: absent
**inventory.yaml**
[os10_sw1]
os10_sw1 ansible_host=100.104.28.119
[os10_sw2]
os10_sw2 ansible_host=100.104.28.120
[os10_switches:children]
os10_sw1
os10_sw2
(c) 2017-2020 Dell Inc. or its subsidiaries. All rights reserved.

View File

@@ -0,0 +1,116 @@
======================================================================
Ansible Network Collection for Dell EMC SmartFabric OS10 Release Notes
======================================================================
.. contents:: Topics
v1.1.1
======
Minor Changes
-------------
- Adding support for Ansible version 2.9 (https://github.com/ansible-collections/dellemc.os10/pull/58)
v1.1.0
======
Major Changes
-------------
- os10_bgp - Enhanced router bgp keyword support for non-default vrf which are supported for default vrf and additional keyword to support both default and non-default vrf
- os10_snmp role - Added support for snmp V3 features in community, group, host, engineID
Minor Changes
-------------
- Enhanced os10_bgp role to support internal BGP redistribution under address-family for V4 and V6
- Enhanced os10_bgp role to support maximum-prefix configuration under BGP peer and peer-group.
- os10_ntp role - Added support for vrf and sha1 and sha2-256 authentication-key types
- os10_snmp role - Added support for source-interface and vrf
- os10_template - add template for show spanning tree compatibility mode
- os10_template - add template for show vlt error disabled ports
- os10_uplink role - Added support for downstream disable-links and auto-recover
Breaking Changes / Porting Guide
--------------------------------
- os10_bgp - Changed "subnet" key as list format instead of dictionary format under "listen" key to support multiple neighbor prefix for listen command
- os10_bgp - Changed "vrf" key as list format instead of dictionary format to supprot multiple VRF in router BGP and changed the "vrf" key name to "vrfs"
Bugfixes
--------
- Fixed issue in using interface range in os10_vlan members. (https://github.com/ansible-collections/dellemc.os10/issues/53)
v1.0.2
======
Bugfixes
--------
- Fix issue in using ip_and_mask along with members in os10_vlan role (https://github.com/ansible-collections/dellemc.os10/issues/42)
- Fix issue in using list of strings for `commands` argument for `os10_command` module (https://github.com/ansible-collections/dellemc.os10/issues/43)
- Fixed os10_vlan role idempotency issue with description and members (https://github.com/ansible-collections/dellemc.os10/issues/46)
v1.0.1
======
Release Summary
---------------
Added changelog.
v1.0.0
======
Major Changes
-------------
- New role os10_aaa - Facilitates the configuration of Authentication Authorization and Accounting (AAA), TACACS and RADIUS server.
- New role os10_acl - Facilitates the configuration of Access Control lists.
- New role os10_bfd - Facilitates the configuration of BFD global attributes.
- New role os10_bgp - Facilitates the configuration of border gateway protocol (BGP) attributes.
- New role os10_copy_config - This role pushes the backup running configuration into a OS10 device.
- New role os10_dns - Facilitates the configuration of domain name service (DNS).
- New role os10_ecmp - Facilitates the configuration of equal cost multi-path (ECMP) for IPv4.
- New role os10_fabric_summary Facilitates to get show system information of all the OS10 switches in the fabric.
- New role os10_flow_monitor Facilitates the configuration of ACL flow-based monitoring attributes.
- New role os10_image_upgrade Facilitates installation of OS10 software images.
- New role os10_interface Facilitates the configuration of interface attributes.
- New role os10_lag Facilitates the configuration of link aggregation group (LAG) attributes.
- New role os10_lldp Facilitates the configuration of link layer discovery protocol (LLDP) attributes at global and interface level.
- New role os10_logging Facilitates the configuration of global logging attributes and logging servers.
- New role os10_network_validation Facilitates validation of wiring connection, BGP neighbors, MTU between neighbors and VLT pair.
- New role os10_ntp Facilitates the configuration of network time protocol (NTP) attributes.
- New role os10_prefix_list Facilitates the configuration of IP prefix-list.
- New role os10_qos Facilitates the configuration of quality of service attributes including policy-map and class-map.
- New role os10_raguard Facilitates the configuration of IPv6 RA Guard attributes.
- New role os10_route_map Facilitates the configuration of route-map attributes.
- New role os10_snmp Facilitates the configuration of global SNMP attributes.
- New role os10_system Facilitates the configuration of hostname and hashing algorithm.
- New role os10_template The role takes the raw string input from the CLI of OS10 device, and returns a structured text in the form of a Python dictionary.
- New role os10_uplink Facilitates the configuration of uplink attributes like uplink-state group.
- New role os10_users Facilitates the configuration of global system user attributes.
- New role os10_vlan Facilitates the configuration of virtual LAN (VLAN) attributes.
- New role os10_vlt Facilitates the configuration of virtual link trunking (VLT).
- New role os10_vrf Facilitates the configuration of virtual routing and forwarding (VRF).
- New role os10_vrrp Facilitates the configuration of virtual router redundancy protocol (VRRP) attributes.
- New role os10_vxlan Facilitates the configuration of virtual extensible LAN (VXLAN) attributes.
- New role os10_xstp Facilitates the configuration of xSTP attributes.
New Plugins
-----------
Cliconf
~~~~~~~
- os10 - Use OS10 cliconf to run commands on Dell EMC PowerSwitch devices.
New Modules
-----------
- os10_command - Run commands on devices running Dell EMC SmartFabric OS1O.
- os10_config - Manage configuration on devices running OS10.
- os10_facts - Collect facts from devices running OS10.

View File

@@ -0,0 +1,124 @@
ancestor: null
releases:
1.0.0:
changes:
major_changes:
- New role os10_aaa - Facilitates the configuration of Authentication Authorization
and Accounting (AAA), TACACS and RADIUS server.
- New role os10_acl - Facilitates the configuration of Access Control lists.
- New role os10_bfd - Facilitates the configuration of BFD global attributes.
- New role os10_bgp - Facilitates the configuration of border gateway protocol
(BGP) attributes.
- New role os10_copy_config - This role pushes the backup running configuration
into a OS10 device.
- New role os10_dns - Facilitates the configuration of domain name service (DNS).
- New role os10_ecmp - Facilitates the configuration of equal cost multi-path
(ECMP) for IPv4.
- New role os10_fabric_summary Facilitates to get show system information of
all the OS10 switches in the fabric.
- New role os10_flow_monitor Facilitates the configuration of ACL flow-based
monitoring attributes.
- New role os10_image_upgrade Facilitates installation of OS10 software images.
- New role os10_interface Facilitates the configuration of interface attributes.
- New role os10_lag Facilitates the configuration of link aggregation group
(LAG) attributes.
- New role os10_lldp Facilitates the configuration of link layer discovery protocol
(LLDP) attributes at global and interface level.
- New role os10_logging Facilitates the configuration of global logging attributes
and logging servers.
- New role os10_network_validation Facilitates validation of wiring connection,
BGP neighbors, MTU between neighbors and VLT pair.
- New role os10_ntp Facilitates the configuration of network time protocol (NTP)
attributes.
- New role os10_prefix_list Facilitates the configuration of IP prefix-list.
- New role os10_qos Facilitates the configuration of quality of service attributes
including policy-map and class-map.
- New role os10_raguard Facilitates the configuration of IPv6 RA Guard attributes.
- New role os10_route_map Facilitates the configuration of route-map attributes.
- New role os10_snmp Facilitates the configuration of global SNMP attributes.
- New role os10_system Facilitates the configuration of hostname and hashing
algorithm.
- New role os10_template The role takes the raw string input from the CLI of
OS10 device, and returns a structured text in the form of a Python dictionary.
- New role os10_uplink Facilitates the configuration of uplink attributes like
uplink-state group.
- New role os10_users Facilitates the configuration of global system user attributes.
- New role os10_vlan Facilitates the configuration of virtual LAN (VLAN) attributes.
- New role os10_vlt Facilitates the configuration of virtual link trunking (VLT).
- New role os10_vrf Facilitates the configuration of virtual routing and forwarding
(VRF).
- New role os10_vrrp Facilitates the configuration of virtual router redundancy
protocol (VRRP) attributes.
- New role os10_vxlan Facilitates the configuration of virtual extensible LAN
(VXLAN) attributes.
- New role os10_xstp Facilitates the configuration of xSTP attributes.
modules:
- description: Run commands on devices running Dell EMC SmartFabric OS1O.
name: os10_command
namespace: ''
- description: Manage configuration on devices running OS10.
name: os10_config
namespace: ''
- description: Collect facts from devices running OS10.
name: os10_facts
namespace: ''
plugins:
cliconf:
- description: Use OS10 cliconf to run commands on Dell EMC PowerSwitch devices.
name: os10
namespace: null
release_date: '2020-07-31'
1.0.1:
changes:
release_summary: Added changelog.
fragments:
- 1.0.1.yaml
release_date: '2020-08-14'
1.0.2:
changes:
bugfixes:
- Fix issue in using ip_and_mask along with members in os10_vlan role (https://github.com/ansible-collections/dellemc.os10/issues/42)
- Fix issue in using list of strings for `commands` argument for `os10_command`
module (https://github.com/ansible-collections/dellemc.os10/issues/43)
- Fixed os10_vlan role idempotency issue with description and members (https://github.com/ansible-collections/dellemc.os10/issues/46)
fragments:
- 1.0.2.yaml
- 46-vlan-idempotency-desc-and-members.yaml
release_date: '2020-10-28'
1.1.0:
changes:
breaking_changes:
- os10_bgp - Changed "subnet" key as list format instead of dictionary format
under "listen" key to support multiple neighbor prefix for listen command
- os10_bgp - Changed "vrf" key as list format instead of dictionary format to
supprot multiple VRF in router BGP and changed the "vrf" key name to "vrfs"
bugfixes:
- Fixed issue in using interface range in os10_vlan members. (https://github.com/ansible-collections/dellemc.os10/issues/53)
major_changes:
- os10_bgp - Enhanced router bgp keyword support for non-default vrf which are
supported for default vrf and additional keyword to support both default and
non-default vrf
- os10_snmp role - Added support for snmp V3 features in community, group, host,
engineID
minor_changes:
- Enhanced os10_bgp role to support internal BGP redistribution under address-family
for V4 and V6
- Enhanced os10_bgp role to support maximum-prefix configuration under BGP peer
and peer-group.
- os10_ntp role - Added support for vrf and sha1 and sha2-256 authentication-key
types
- os10_snmp role - Added support for source-interface and vrf
- os10_template - add template for show spanning tree compatibility mode
- os10_template - add template for show vlt error disabled ports
- os10_uplink role - Added support for downstream disable-links and auto-recover
fragments:
- 53-vlan-member-port-range.yaml
- R9.yaml
release_date: '2020-12-02'
1.1.1:
changes:
minor_changes:
- Adding support for Ansible version 2.9 (https://github.com/ansible-collections/dellemc.os10/pull/58)
fragments:
- 58-support-for-ansible-version-2.9.yaml
release_date: '2020-12-11'

View File

@@ -0,0 +1,30 @@
changelog_filename_template: CHANGELOG.rst
changelog_filename_version_depth: 0
changes_file: changelog.yaml
changes_format: combined
keep_fragments: false
mention_ancestor: true
new_plugins_after_name: removed_features
notesdir: fragments
prelude_section_name: release_summary
prelude_section_title: Release Summary
flatmap: true
sections:
- - major_changes
- Major Changes
- - minor_changes
- Minor Changes
- - breaking_changes
- Breaking Changes / Porting Guide
- - deprecated_features
- Deprecated Features
- - removed_features
- Removed Features (previously deprecated)
- - security_fixes
- Security Fixes
- - bugfixes
- Bugfixes
- - known_issues
- Known Issues
title: Ansible Network Collection for Dell EMC SmartFabric OS10
trivial_section_name: trivial

View File

@@ -0,0 +1,8 @@
plugin_routing:
action:
os10_config:
redirect: dellemc.os10.os10
os10_command:
redirect: dellemc.os10.os10
os10_facts:
redirect: dellemc.os10.os10

View File

@@ -0,0 +1,37 @@
# Provision CLOS fabric using the Ansible collection for Dell EMC SmartFabric OS10
This example describes how to use Ansible to build a CLOS fabric using Dell EMC PowerSwitch platforms running Dell EMC SmartFabric OS10. The sample topology is a two-tier CLOS fabric with two spines and four leaves connected as mesh. eBGP is running between the two tiers. All switches in spine have the same AS number, and each leaf switch has a unique AS number. All AS numbers used are private.
For application load-balancing purposes, the same prefix is advertised from multiple leaf switches and uses _BGP multipath relax_ feature.
![CLOS FABRIC Topology](https://ansible-dellos-docs.readthedocs.io/en/latest/_images/topo.png)
## Create simple Ansible playbook
**1**. Create an inventory file called `inventory.yaml`, then specify the device IP address.
**2**. Create a group variable file called `group_vars/all`, then define credentials and SNMP variables.
**3**. Create a group variable file called `group_vars/spine.yaml`, then define credentials, hostname, and BGP neighbors of spine group.
**4**. Create a host variable file called `host_vars/spine1.yaml`, then define the host, credentials, and transport.
**5**. Create a host variable file called `host_vars/spine2.yaml`, then define the host, credentials, and transport.
**6**. Create a host variable file called `host_vars/leaf1.yaml`, then define the host, credentials, and transport.
**7**. Create a host variable file called `host_vars/leaf2.yaml`, then define the host, credentials, and transport.
**8**. Create a host variable file called `host_vars/leaf3.yaml`, then define the host, credentials, and transport.
**9**. Create a host variable file called `host_vars/leaf4.yaml`, then define the host, credentials, and transport.
**10**. Create a playbook called `datacenter.yaml`.
**11**. Run the playbook.
ansible-playbook -i inventory.yaml datacenter.yaml
(c) 2017-2020 Dell Inc. or its subsidiaries. All rights reserved.

View File

@@ -0,0 +1,11 @@
---
- hosts: datacenter
gather_facts: no
connection: network_cli
collections:
- dellemc.os10
roles:
- os10_interface
- os10_bgp
- os10_snmp
- os10_system

View File

@@ -0,0 +1,9 @@
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
os10_snmp:
snmp_community:
- name: public
access_mode: ro
state: present

View File

@@ -0,0 +1,85 @@
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
os10_system:
hostname: "{{ spine_hostname }}"
os10_bgp:
asn: 64901
router_id: "{{ bgp_router_id }}"
best_path:
as_path: multipath-relax
as_path_state: present
med:
- attribute: missing-as-worst
state: present
neighbor:
- type: ipv4
remote_asn: "{{ bgp_neigh1_remote_asn }}"
ip: "{{ bgp_neigh1_ip }}"
admin: up
state: present
- type: ipv4
remote_asn: "{{ bgp_neigh2_remote_asn }}"
ip: "{{ bgp_neigh2_ip }}"
admin: up
state: present
- type: ipv4
remote_asn: "{{ bgp_neigh3_remote_asn }}"
ip: "{{ bgp_neigh3_ip }}"
admin: up
state: present
- type: ipv4
remote_asn: "{{ bgp_neigh4_remote_asn }}"
ip: "{{ bgp_neigh4_ip }}"
admin: up
state: present
- type: ipv6
remote_asn: "{{ bgp_neigh5_remote_asn }}"
ip: "{{ bgp_neigh5_ip }}"
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present
- type: ipv6
remote_asn: "{{ bgp_neigh6_remote_asn }}"
ip: "{{ bgp_neigh6_ip }}"
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present
- type: ipv6
remote_asn: "{{ bgp_neigh7_remote_asn }}"
ip: "{{ bgp_neigh7_ip }}"
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present
- type: ipv6
remote_asn: "{{ bgp_neigh8_remote_asn }}"
ip: "{{ bgp_neigh8_ip }}"
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present

View File

@@ -0,0 +1,77 @@
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
leaf_hostname: "leaf-1"
os10_system:
hostname: "{{ leaf_hostname }}"
hash_algo:
algo:
- name: ecmp
mode: crc
state: present
os10_interface:
ethernet 1/1/1:
desc: "Connected to Spine 1"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.1.1.2/24
ipv6_and_mask: 2001:100:1:1::2/64
state_ipv6: present
ethernet 1/1/9:
desc: "Connected to Spine 2"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.2.1.2/24
ipv6_and_mask: 2001:100:2:1::2/64
state_ipv6: present
os10_bgp:
asn: 64801
router_id: 100.0.2.1
address_family_ipv4: true
address_family_ipv6: true
best_path:
as_path: multipath-relax
as_path_state: present
med:
- attribute: missing-as-worst
state: present
neighbor:
- type: ipv4
remote_asn: 64901
ip: 100.1.1.1
admin: up
state: present
- type: ipv4
remote_asn: 64901
ip: 100.2.1.1
admin: up
state: present
- type: ipv6
remote_asn: 64901
ip: 2001:100:1:1::1
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present
- type: ipv6
remote_asn: 64901
ip: 2001:100:2:1::1
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present
state: present

View File

@@ -0,0 +1,81 @@
hostname: leaf2
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
leaf_hostname: "leaf-2"
os10_system:
hostname: "{{ leaf_hostname }}"
hash_algo:
algo:
- name: ecmp
mode: crc
state: present
os10_interface:
ethernet 1/1/1:
desc: "Connected to Spine 1"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.1.17.2/24
ipv6_and_mask: 2001:100:1:11::2/64
state_ipv6: present
ethernet 1/1/9:
desc: "Connected to Spine 2"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.2.17.2/24
ipv6_and_mask: 2001:100:2:11::2/64
os10_bgp:
asn: 64802
router_id: 100.0.2.2
address_family_ipv4: true
address_family_ipv6: true
best_path:
as_path: multipath-relax
as_path_state: present
med:
- attribute: missing-as-worst
state: present
neighbor:
- type: ipv4
remote_asn: 64901
ip: 100.1.18.1
admin: up
state: present
- type: ipv4
remote_asn: 64901
ip: 100.1.17.1
admin: up
state: present
- type: ipv4
remote_asn: 64901
ip: 100.2.17.1
admin: up
state: present
- type: ipv6
remote_asn: 64901
ip: 2001:100:1:11::1
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present
- type: ipv6
remote_asn: 64901
ip: 2001:100:2:11::1
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present

View File

@@ -0,0 +1,81 @@
hostname: leaf3
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
leaf_hostname: "leaf-3"
os10_system:
hostname: "{{ leaf_hostname }}"
hash_algo:
algo:
- name: ecmp
mode: crc
state: present
os10_interface:
ethernet 1/1/1:
desc: "Connected to Spine 1"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.1.33.2/24
ipv6_and_mask: 2001:100:1:21::2/64
state_ipv6: present
ethernet 1/1/9:
desc: "Connected to Spine 2"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.2.33.2/24
ipv6_and_mask: 2001:100:2:21::2/64
os10_bgp:
asn: 64803
router_id: 100.0.2.3
address_family_ipv4: true
address_family_ipv6: true
best_path:
as_path: multipath-relax
as_path_state: present
med:
- attribute: missing-as-worst
state: present
neighbor:
- type: ipv4
remote_asn: 64901
ip: 100.1.33.1
admin: up
state: present
- type: ipv4
remote_asn: 64901
ip: 100.2.33.1
admin: up
state: present
- type: ipv6
remote_asn: 64901
ip: 2001:100:1:21::1
admin: up
state: present
- type: ipv6
remote_asn: 64901
ip: 2001:100:1:22::1
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present
- type: ipv6
remote_asn: 64901
ip: 2001:100:2:21::1
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present

View File

@@ -0,0 +1,77 @@
hostname: leaf4
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
leaf_hostname: "leaf-4"
os10_system:
hostname: "{{ leaf_hostname }}"
hash_algo:
algo:
- name: ecmp
mode: crc
state: present
os10_interface:
ethernet 1/1/5:
desc: "Connected to Spine 1"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.1.49.2/24
ipv6_and_mask: 2001:100:1:31::2/64
state_ipv6: present
ethernet 1/1/17:
desc: "Connected to Spine 2"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.2.49.2/24
ipv6_and_mask: 2001:100:2:31::2/64
state_ipv6: present
os10_bgp:
asn: 64804
router_id: 100.0.2.4
address_family_ipv4: true
address_family_ipv6: true
best_path:
as_path: multipath-relax
as_path_state: present
med:
- attribute: missing-as-worst
state: present
neighbor:
- type: ipv4
remote_asn: 64901
ip: 100.1.49.1
admin: up
state: present
- type: ipv4
remote_asn: 64901
ip: 100.2.49.1
admin: up
state: present
- type: ipv6
remote_asn: 64901
ip: 2001:100:1:31::1
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present
- type: ipv6
remote_asn: 64901
ip: 2001:100:2:31::1
admin: up
address_family:
- type: ipv4
activate: false
state: present
- type: ipv6
activate: true
state: present
state: present

View File

@@ -0,0 +1,61 @@
hostname: spine1
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
spine_hostname: "spine-1"
os10_interface:
ethernet 1/1/1:
desc: "Connected to leaf 1"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.1.1.1/24
ipv6_and_mask: 2001:100:1:1::1/64
state_ipv6: present
ethernet 1/1/17:
desc: "Connected to leaf 2"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.1.33.1/24
ipv6_and_mask: 2001:100:1:21::1/64
state_ipv6: present
ethernet 1/1/25:
desc: "Connected to leaf 3"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.1.17.1/24
ipv6_and_mask: 2001:100:1:11::1/64
state_ipv6: present
ethernet 1/1/9:
desc: "Connected to leaf 4"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.1.49.1/24
ipv6_and_mask: 2001:100:1:31::1/64
state_ipv6: present
bgp_router_id: "100.0.1.1"
bgp_neigh1_remote_asn: 64801
bgp_neigh1_ip: "100.1.1.2"
bgp_neigh2_remote_asn: 64803
bgp_neigh2_ip: "100.1.33.2"
bgp_neigh3_remote_asn: 64802
bgp_neigh3_ip: "100.1.17.2"
bgp_neigh4_remote_asn: 64804
bgp_neigh4_ip: "100.1.49.2"
bgp_neigh5_remote_asn: 64801
bgp_neigh5_ip: "2001:100:1:1::2"
bgp_neigh6_remote_asn: 64802
bgp_neigh6_ip: "2001:100:1:11::2"
bgp_neigh7_remote_asn: 64803
bgp_neigh7_ip: "2001:100:1:21::2"
bgp_neigh8_remote_asn: 64804
bgp_neigh8_ip: "2001:100:1:31::2"

View File

@@ -0,0 +1,60 @@
hostname: spine2
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
spine_hostname: "spine-2"
os10_interface:
ethernet 1/1/1:
desc: "Connected to leaf 1"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.2.1.1/24
ipv6_and_mask: 2001:100:2:1::1/64
state_ipv6: present
ethernet 1/1/25:
desc: "Connected to leaf 2"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.2.17.1/24
ipv6_and_mask: 2001:100:2:11::1/64
state_ipv6: present
ethernet 1/1/17:
desc: "Connected to leaf 3"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.2.33.1/24
ipv6_and_mask: 2001:100:2:21::1/64
state_ipv6: present
ethernet 1/1/9:
desc: "Connected to leaf 4"
mtu: 9216
portmode:
admin: up
switchport: False
ip_and_mask: 100.2.49.1/24
ipv6_and_mask: 2001:100:2:31::1/64
state_ipv6: present
bgp_router_id: "100.0.1.2"
bgp_neigh1_remote_asn: 64801
bgp_neigh1_ip: "100.2.1.2"
bgp_neigh2_remote_asn: 64802
bgp_neigh2_ip: "100.2.33.2"
bgp_neigh3_remote_asn: 64803
bgp_neigh3_ip: "100.2.17.2"
bgp_neigh4_remote_asn: 64804
bgp_neigh4_ip: "100.2.49.2"
bgp_neigh5_remote_asn: 64801
bgp_neigh5_ip: "2001:100:2:1::2"
bgp_neigh6_remote_asn: 64802
bgp_neigh6_ip: "2001:100:2:11::2"
bgp_neigh7_remote_asn: 64803
bgp_neigh7_ip: "2001:100:2:21::2"
bgp_neigh8_remote_asn: 64804
bgp_neigh8_ip: "2001:100:2:31::2"

View File

@@ -0,0 +1,20 @@
spine1 ansible_host=10.11.182.25
spine2 ansible_host=10.11.182.26
leaf1 ansible_host=10.11.182.27
leaf2 ansible_host=10.11.182.28
leaf3 ansible_host=10.11.182.29
leaf4 ansible_host=10.11.182.30
[spine]
spine1
spine2
[leaf]
leaf1
leaf2
leaf3
leaf4
[datacenter:children]
spine
leaf

View File

@@ -0,0 +1,63 @@
# VxLAN Symmetric-IRB configuration using BGP EVPN using the Ansible collection for Dell EMC SmartFabric OS10
This example describes how to use Ansible to build a Leaf-Spine topology with Dell EMC PowerSwitch platforms running Dell EMC SmartFabric OS10, using a VxLAN Symmetric-IRB configuration model.
VxLAN Symmetric-IRB is configured using BGP EVPN with Leaf-Spine topology. BGP unnumbered is configured between the Leaf and Spine over VLANS for both underlay and overlay. VLT is configured between the pair of Leaf nodes.
In all Leaf nodes, the L3 VRF VNI "test" is configured to route between different VNs spanned across the topology, and the VTEP router MAC is configured to identify the remote VTEPs.
VN 100 and VN 300 is configured in a pair of Leaf nodes, and VN 200 and VN 300 configured in an other pair of Leaf nodes.
## Create simple Ansible playbook
**1**. Create an inventory file called `inventory.yaml`, then specify the device IP address.
**2**. Create a host variable file called `host_vars/spine1.yaml`, then define the host, credentials, and transport.
**3**. Create a host variable file called `host_vars/spine2.yaml`, then define the host, credentials, and transport.
**4**. Use the *os10_interface* and *os10_vlan* roles to configure the required VLANs.
**5**. Use the *os10_bgp* role to configure BGP unnumbered.
**Configurations for VTEP-1**
**1**. Create a host variable file called `host_vars/prim-vtep1.yaml`.
**2**. Create a host variable file called `host_vars/sec-vtep1.yaml`.
**3**. Define the host, credentials, and transport.
**4**. Use the *os10_interface* and *os10_vlan* roles to configure the required VLANs.
**5**. Use the *os10_bgp* role to configure BGP unnumbered.
**6**. Use the *os10_vxlan* role to configure VN networks, EVPN and Symmetric IRB functionality.
**7**. Use *os10_vlt* role to configure VLT between leaves prim-vtep1 and sec-vtep1.
**Configurations for VTEP-2**
**1**. Create a host variable file called `host_vars/prim-vtep2.yaml`.
**2**. Create a host variable file called `host_vars/sec-vtep2.yaml`.
**3**. Define the host, credentials, and transport.
**4**. Use *os10_interface* and *os10_vlan* roles to configure the required VLANs.
**5**. Use the *os10_bgp* role to configure BGP unnumbered.
**6**. Use *os10_vxlan* role to configure VN networks, EVPN and Symmetric IRB functionality.
**7**. Use the *os10_vlt* role to configure VLT between leaves prim-vtep2 and sec-vtep2.
**Create and run the playbook**
**1**. Create a playbook called `datacenter.yaml`.
**2**. Run the playbook.
ansible-playbook -i inventory.yaml datacenter.yaml
(c) 2017-2020 Dell Inc. or its subsidiaries. All rights reserved.

View File

@@ -0,0 +1,16 @@
---
- hosts: datacenter
connection: network_cli
collections:
- dellemc.os10
vars:
build_dir: "/home/administrator/ansible/debug"
roles:
- os10_vrf
- os10_interface
- os10_system
- os10_bgp
- os10_lag
- os10_vlan
- os10_vxlan
- os10_vlt

View File

@@ -0,0 +1,210 @@
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
os10_system:
hostname: "VLT1-Primary"
os10_bgp:
asn: 100
router_id: 1.1.1.10
neighbor:
- type: ipv4
interface: vlan20
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
- type: ipv4
interface: vlan10
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
- type: ipv4
interface: vlan11
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
ipv4_network: 1.1.1.1/32
redistribute:
- route_type: connected
address_type: ipv4
state: present
state: "present"
os10_interface:
loopback 0:
admin: up
ip_and_mask: 1.1.1.1/32
ethernet 1/1/6:
switchport: False
admin: up
ethernet 1/1/4:
admin: up
switchport: False
ethernet 1/1/5:
admin: up
switchport: False
ethernet 1/1/1:
admin: up
switchport: False
portmode: "trunk"
# ethernet 1/1/2:
ethernet 1/1/3:
admin: up
switchport: False
portmode: "trunk"
port-channel 10:
portmode: "trunk"
admin: up
vlan 10:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 11:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 20:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
virtual-network 100:
vrf: "test"
ip_and_mask: "15.1.1.1/24"
ip_virtual_gateway_ip: "15.1.1.254"
admin: up
virtual-network 300:
vrf: "test"
ip_and_mask: "25.1.1.1/24"
ip_virtual_gateway_ip: "25.1.1.254"
admin: up
os10_lag:
port-channel 10:
type: dynamic
channel_members:
# - port: ethernet1/1/5
- port: ethernet1/1/6
mode: active
state: present
os10_vlan:
vlan 10:
tagged_members:
- port: ethernet 1/1/1
state: "present"
access_vlan: "false"
state: "present"
vlan 20:
tagged_members:
# - port: ethernet 1/1/2
- port: ethernet 1/1/3
state: "present"
access_vlan: "false"
state: "present"
os10_vrf:
vrfdetails:
- vrf_name: "test"
state: "present"
os10_vxlan:
anycast_gateway_mac: "00:00:aa:bb:ee:ff"
nve:
source_interface: 0
state: "present"
evpn:
evi:
- id: 100
vni:
id: 100
state: "present"
rd: "auto"
route_target:
- type: "manual"
asn_value: "65530:65532"
route_target_type: "both"
state: "present"
state: "present"
- id: 300
vni:
id: 300
state: "present"
rd: "auto"
route_target:
- type: "auto"
state: "present"
state: "present"
vrf:
- name: "test"
vni: 1000
adv_ipv4:
- type: "connected"
state: "present"
- type: "bgp"
state: "present"
route_target:
- type: "manual"
asn_value: "65530:65534"
route_target_type: "both"
state: "present"
rmac: 00:11:11:11:11:11
dis_rt_asn: "true"
virtual_network:
virtual_net:
- id: 100
vlt_vlan_id: 100
member_interface:
- ifname: "port-channel10"
type: "tagged"
vlanid: 100
state: "present"
vxlan_vni:
id: 100
state: "present"
state: "present"
- id: 300
vlt_vlan_id: 300
member_interface:
- ifname: "port-channel10"
type: "tagged"
vlanid: 300
state: "present"
vxlan_vni:
id: 300
state: "present"
state: "present"
os10_vlt:
domain: 1
destination_type: "ipv4"
peer_routing: True
# discovery_intf: "1/1/3-1/1/4"
discovery_intf: "1/1/4-1/1/5"
vlt_mac: 00:00:00:11:22:33
vlt_peers:
Po 10:
peer_lag: 10
state: "present"

View File

@@ -0,0 +1,194 @@
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
os10_system:
hostname: "VLT2-Primary"
os10_bgp:
asn: 300
router_id: 2.2.2.10
ipv4_network: 2.2.2.2/32
redistribute:
- route_type: connected
address_type: ipv4
state: present
state: "present"
neighbor:
- type: ipv4
interface: vlan50
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
- type: ipv4
interface: vlan60
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
- type: ipv4
interface: vlan11
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
os10_interface:
loopback 0:
admin: up
ip_and_mask: 2.2.2.2/32
loopback 10:
admin: up
vrf: "test"
ip_and_mask: 50.1.1.10/32
loopback 20:
admin: up
vrf: "test"
ip_and_mask: 60.1.1.10/32
ethernet 1/1/1:
admin: up
switchport: False
portmode: "trunk"
ethernet 1/1/2:
admin: up
switchport: False
portmode: "trunk"
ethernet 1/1/3:
switchport: False
admin: up
ethernet 1/1/4:
admin: up
switchport: False
ethernet 1/1/5:
switchport: False
vrf: "test"
ip_and_mask: "21.21.21.20/24"
admin: up
vlan 11:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 50:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 60:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
virtual-network 200:
vrf: "test"
ip_and_mask: "30.1.1.100/24"
ip_virtual_gateway_ip: "30.1.1.254"
admin: up
virtual-network 300:
vrf: "test"
ip_and_mask: "25.1.1.100/24"
ip_virtual_gateway_ip: "25.1.1.254"
admin: up
os10_vlan:
vlan 50:
tagged_members:
- port: ethernet 1/1/1
state: "present"
access_vlan: "false"
state: "present"
vlan 60:
tagged_members:
- port: ethernet 1/1/2
state: "present"
access_vlan: "false"
state: "present"
os10_vrf:
vrfdetails:
- vrf_name: "test"
state: "present"
os10_vxlan:
anycast_gateway_mac: "00:00:aa:bb:ee:ff"
nve:
source_interface: 0
state: "present"
evpn:
evi:
- id: 200
vni:
id: 200
state: "present"
rd: "auto"
route_target:
- type: "manual"
asn_value: "65530:65533"
route_target_type: "both"
state: "present"
state: "present"
- id: 300
vni:
id: 300
state: "present"
rd: "auto"
route_target:
- type: "auto"
state: "present"
state: "present"
vrf:
- name: "test"
vni: 1000
adv_ipv4:
- type: "connected"
state: "present"
- type: "bgp"
state: "present"
route_target:
- type: "manual"
asn_value: "65530:65534"
route_target_type: "both"
state: "present"
rmac: 00:00:22:22:22:22
dis_rt_asn: "true"
virtual_network:
virtual_net:
- id: 200
vlt_vlan_id: 200
vxlan_vni:
id: 200
state: "present"
state: "present"
- id: 300
vlt_vlan_id: 300
vxlan_vni:
id: 300
state: "present"
state: "present"
os10_vlt:
domain: 1
destination_type: "ipv4"
peer_routing: True
discovery_intf: "1/1/3-1/1/4"
vlt_mac: 00:00:00:44:55:66
vlt_peers:
Po 10:
peer_lag: 10
state: "present"

View File

@@ -0,0 +1,206 @@
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
os10_system:
hostname: "VLT1-SEC"
os10_bgp:
asn: 100
router_id: 1.1.1.20
neighbor:
- type: ipv4
interface: vlan40
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
- type: ipv4
interface: vlan30
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
- type: ipv4
interface: vlan11
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
ipv4_network: 1.1.1.1/32
redistribute:
- route_type: connected
address_type: ipv4
state: present
state: "present"
os10_interface:
loopback 0:
admin: up
ip_and_mask: 1.1.1.1/32
ethernet 1/1/3:
switchport: False
admin: up
ethernet 1/1/4:
admin: up
switchport: False
ethernet 1/1/5:
admin: up
switchport: False
ethernet 1/1/1:
admin: up
switchport: False
portmode: "trunk"
ethernet 1/1/2:
admin: up
switchport: False
portmode: "trunk"
port-channel 10:
portmode: "trunk"
admin: up
vlan 30:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 11:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 40:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
virtual-network 100:
vrf: "test"
ip_and_mask: "15.1.1.2/24"
ip_virtual_gateway_ip: "15.1.1.254"
admin: up
virtual-network 300:
vrf: "test"
ip_and_mask: "25.1.1.2/24"
ip_virtual_gateway_ip: "25.1.1.254"
admin: up
os10_lag:
port-channel 10:
type: dynamic
channel_members:
- port: ethernet1/1/5
mode: active
state: present
os10_vlan:
vlan 30:
tagged_members:
- port: ethernet 1/1/1
state: "present"
access_vlan: "false"
state: "present"
vlan 40:
tagged_members:
- port: ethernet 1/1/2
state: "present"
access_vlan: "false"
state: "present"
os10_vrf:
vrfdetails:
- vrf_name: "test"
state: "present"
os10_vxlan:
anycast_gateway_mac: "00:00:aa:bb:ee:ff"
nve:
source_interface: 0
state: "present"
evpn:
evi:
- id: 100
vni:
id: 100
state: "present"
rd: "auto"
route_target:
- type: "manual"
asn_value: "65530:65532"
route_target_type: "both"
state: "present"
state: "present"
- id: 300
vni:
id: 300
state: "present"
rd: "auto"
route_target:
- type: "auto"
state: "present"
state: "present"
vrf:
- name: "test"
vni: 1000
adv_ipv4:
- type: "connected"
state: "present"
- type: "bgp"
state: "present"
route_target:
- type: "manual"
asn_value: "65530:65534"
route_target_type: "both"
state: "present"
rmac: 00:11:11:11:11:11
dis_rt_asn: "true"
virtual_network:
virtual_net:
- id: 100
vlt_vlan_id: 100
member_interface:
- ifname: "port-channel10"
type: "tagged"
vlanid: 100
state: "present"
vxlan_vni:
id: 100
state: "present"
state: "present"
- id: 300
vlt_vlan_id: 300
member_interface:
- ifname: "port-channel10"
type: "tagged"
vlanid: 300
state: "present"
vxlan_vni:
id: 300
state: "present"
state: "present"
os10_vlt:
domain: 1
destination_type: "ipv4"
peer_routing: True
discovery_intf: "1/1/3-1/1/4"
vlt_mac: 00:00:00:11:22:33
vlt_peers:
Po 10:
peer_lag: 10
state: "present"

View File

@@ -0,0 +1,200 @@
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
os10_system:
hostname: "VLT2-SEC"
os10_bgp:
asn: 300
router_id: 2.2.2.20
neighbor:
- type: ipv4
interface: vlan70
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
- type: ipv4
interface: vlan80
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
- type: ipv4
interface: vlan11
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
vrf:
name: "test"
address_type: ipv4
redistribute:
- route_type: l2vpn
ipv4_network: 2.2.2.2/32
redistribute:
- route_type: connected
address_type: ipv4
state: present
state: "present"
os10_interface:
loopback 0:
admin: up
ip_and_mask: 2.2.2.2/32
loopback 10:
admin: up
vrf: "test"
ip_and_mask: 80.1.1.10/32
loopback 20:
admin: up
vrf: "test"
ip_and_mask: 90.1.1.10/32
ethernet 1/1/1:
admin: up
switchport: False
portmode: "trunk"
ethernet 1/1/2:
admin: up
switchport: False
portmode: "trunk"
ethernet 1/1/3:
switchport: False
admin: up
ethernet 1/1/4:
admin: up
switchport: False
ethernet 1/1/5:
switchport: False
vrf: "test"
ip_and_mask: "20.20.20.20/24"
admin: up
vlan 11:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 70:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 80:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
virtual-network 200:
vrf: "test"
ip_and_mask: "30.1.1.101/24"
ip_virtual_gateway_ip: "30.1.1.254"
admin: up
virtual-network 300:
vrf: "test"
ip_and_mask: "25.1.1.101/24"
ip_virtual_gateway_ip: "25.1.1.254"
admin: up
os10_vlan:
vlan 70:
tagged_members:
- port: ethernet 1/1/1
state: "present"
access_vlan: "false"
state: "present"
vlan 80:
tagged_members:
- port: ethernet 1/1/2
state: "present"
access_vlan: "false"
state: "present"
os10_vrf:
vrfdetails:
- vrf_name: "test"
state: "present"
os10_vxlan:
anycast_gateway_mac: "00:00:aa:bb:ee:ff"
nve:
source_interface: 0
state: "present"
evpn:
evi:
- id: 200
vni:
id: 200
state: "present"
rd: "auto"
route_target:
- type: "manual"
asn_value: "65530:65533"
route_target_type: "both"
state: "present"
state: "present"
- id: 300
vni:
id: 300
state: "present"
rd: "auto"
route_target:
- type: "auto"
state: "present"
state: "present"
vrf:
- name: "test"
vni: 1000
adv_ipv4:
- type: "connected"
state: "present"
- type: "bgp"
state: "present"
route_target:
- type: "manual"
asn_value: "65530:65534"
route_target_type: "both"
state: "present"
rmac: 00:00:22:22:22:22
dis_rt_asn: "true"
virtual_network:
virtual_net:
- id: 200
vlt_vlan_id: 200
vxlan_vni:
id: 200
state: "present"
state: "present"
- id: 300
vlt_vlan_id: 300
vxlan_vni:
id: 300
state: "present"
state: "present"
os10_vlt:
domain: 1
destination_type: "ipv4"
peer_routing: True
discovery_intf: "1/1/3-1/1/4"
vlt_mac: 00:00:00:44:55:66
vlt_peers:
Po 10:
peer_lag: 10
state: "present"

View File

@@ -0,0 +1,95 @@
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
os10_system:
hostname: "spine1"
os10_bgp:
asn: 200
router_id: 9.9.9.10
neighbor:
- type: "peergroup"
name: "ebgp_session"
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
state: present
- type: ipv4
interface: vlan10
peergroup: ebgp_session
peergroup_type: ebgp
admin: up
state: present
- type: ipv4
interface: vlan30
peergroup: ebgp_session
peergroup_type: ebgp
admin: up
state: present
- type: ipv4
interface: vlan50
peergroup: ebgp_session
peergroup_type: ebgp
admin: up
state: present
- type: ipv4
interface: vlan70
peergroup: ebgp_session
peergroup_type: ebgp
admin: up
state: present
state: "present"
os10_interface:
vlan 10:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 30:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 50:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 70:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
os10_vlan:
vlan 10:
tagged_members:
- port: ethernet 1/1/1
state: "present"
access_vlan: "false"
state: "present"
vlan 30:
tagged_members:
- port: ethernet 1/1/2
state: "present"
access_vlan: "false"
state: "present"
vlan 50:
tagged_members:
- port: ethernet 1/1/3
state: "present"
access_vlan: "false"
state: "present"
vlan 70:
tagged_members:
- port: ethernet 1/1/4
state: "present"
access_vlan: "false"
state: "present"

View File

@@ -0,0 +1,95 @@
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
os10_system:
hostname: "spine2"
os10_bgp:
asn: 201
router_id: 9.9.9.20
neighbor:
- type: "peergroup"
name: "ebgp_session"
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
state: present
- type: ipv4
interface: vlan20
peergroup: ebgp_session
peergroup_type: ebgp
admin: up
state: present
- type: ipv4
interface: vlan40
peergroup: ebgp_session
peergroup_type: ebgp
admin: up
state: present
- type: ipv4
interface: vlan60
peergroup: ebgp_session
peergroup_type: ebgp
admin: up
state: present
- type: ipv4
interface: vlan80
peergroup: ebgp_session
peergroup_type: ebgp
admin: up
state: present
state: "present"
os10_interface:
vlan 20:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 40:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 60:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
vlan 80:
suppress_ra: absent
min_ra: 3
max_ra: 4
admin: up
os10_vlan:
vlan 20:
tagged_members:
- port: ethernet 1/1/1
state: "present"
access_vlan: "false"
state: "present"
vlan 40:
tagged_members:
- port: ethernet 1/1/2
state: "present"
access_vlan: "false"
state: "present"
vlan 60:
tagged_members:
- port: ethernet 1/1/3
state: "present"
access_vlan: "false"
state: "present"
vlan 80:
tagged_members:
- port: ethernet 1/1/4
state: "present"
access_vlan: "false"
state: "present"

View File

@@ -0,0 +1,20 @@
spine1 ansible_host=101.104.34.141
prim-vtep1 ansible_host=101.104.34.217
sec-vtep1 ansible_host=101.104.34.218
spine2 ansible_host=101.104.34.142
prim-vtep2 ansible_host=101.104.34.219
sec-vtep2 ansible_host=101.104.34.220
[site1]
prim-vtep1
sec-vtep1
spine1
[site2]
prim-vtep2
spine2
sec-vtep2
[datacenter:children]
site1
site2

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View File

@@ -0,0 +1,94 @@
#
# (c) 2020 Red Hat Inc.
#
# (c) 2020 Dell Inc.
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import sys
import copy
from ansible import constants as C
from ansible.module_utils._text import to_text
from ansible.module_utils.connection import Connection
from ansible_collections.ansible.netcommon.plugins.action.network import ActionModule as ActionNetworkModule
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import load_provider
from ansible_collections.dellemc.os10.plugins.module_utils.network.os10 import os10_provider_spec
from ansible.utils.display import Display
display = Display()
class ActionModule(ActionNetworkModule):
def run(self, tmp=None, task_vars=None):
del tmp # tmp no longer has any effect
self._config_module = True if self._task.action == 'os10_config' else False
socket_path = None
if self._play_context.connection == 'network_cli':
provider = self._task.args.get('provider', {})
if any(provider.values()):
display.warning('provider is unnecessary when using network_cli and will be ignored')
del self._task.args['provider']
elif self._play_context.connection == 'local':
provider = load_provider(os10_provider_spec, self._task.args)
pc = copy.deepcopy(self._play_context)
pc.connection = 'network_cli'
pc.network_os = 'dellemc.os10.os10'
pc.remote_addr = provider['host'] or self._play_context.remote_addr
pc.port = int(provider['port'] or self._play_context.port or 22)
pc.remote_user = provider['username'] or self._play_context.connection_user
pc.password = provider['password'] or self._play_context.password
pc.private_key_file = provider['ssh_keyfile'] or self._play_context.private_key_file
command_timeout = int(provider['timeout'] or C.PERSISTENT_COMMAND_TIMEOUT)
pc.become = provider['authorize'] or False
if pc.become:
pc.become_method = 'enable'
pc.become_pass = provider['auth_pass']
display.vvv('using connection plugin %s' % pc.connection, pc.remote_addr)
connection = self._shared_loader_obj.connection_loader.get('persistent', pc, sys.stdin)
connection.set_options(direct={'persistent_command_timeout': command_timeout})
socket_path = connection.run()
display.vvvv('socket_path: %s' % socket_path, pc.remote_addr)
if not socket_path:
return {'failed': True,
'msg': 'unable to open shell. Please see: ' +
'https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell'}
task_vars['ansible_socket'] = socket_path
# make sure we are in the right cli context which should be
# enable mode and not config module
if socket_path is None:
socket_path = self._connection.socket_path
conn = Connection(socket_path)
out = conn.get_prompt()
while to_text(out, errors='surrogate_then_replace').strip().endswith(')#'):
display.vvvv('wrong context, sending exit to device', self._play_context.remote_addr)
conn.send_command('exit')
out = conn.get_prompt()
result = super(ActionModule, self).run(task_vars=task_vars)
return result

View File

@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
# (c) 2020, Ansible by Red Hat, inc
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.module_utils.six import StringIO, string_types
from ansible.plugins.action import ActionBase
from ansible.errors import AnsibleError
try:
import textfsm
HAS_TEXTFSM = True
except ImportError:
HAS_TEXTFSM = False
class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
''' handler for textfsm action '''
if task_vars is None:
task_vars = dict()
result = super(ActionModule, self).run(tmp, task_vars)
del tmp # tmp no longer has any effect
try:
if not HAS_TEXTFSM:
raise AnsibleError('textfsm_parser engine requires the TextFSM library to be installed')
try:
filename = self._task.args.get('file')
src = self._task.args.get('src')
content = self._task.args['content']
name = self._task.args.get('name')
except KeyError as exc:
raise AnsibleError('missing required argument: %s' % exc)
if src and filename:
raise AnsibleError('`src` and `file` are mutually exclusive arguments')
if not isinstance(content, string_types):
return {'failed': True, 'msg': '`content` must be of type str, got %s' % type(content)}
if filename:
tmpl = open(filename)
else:
tmpl = StringIO()
tmpl.write(src.strip())
tmpl.seek(0)
try:
re_table = textfsm.TextFSM(tmpl)
fsm_results = re_table.ParseText(content)
except Exception as exc:
raise AnsibleError(str(exc))
final_facts = []
for item in fsm_results:
facts = {}
facts.update(dict(zip(re_table.header, item)))
final_facts.append(facts)
if name:
result['ansible_facts'] = {name: final_facts}
else:
result['ansible_facts'] = {}
finally:
self._remove_tmp_path(self._connection._shell.tmpdir)
return result

View File

@@ -0,0 +1,88 @@
#
# (c) 2020 Red Hat Inc.
#
# (c) 2020 Dell Inc.
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = """
---
cliconf: os10
short_description: Use os10 cliconf to run command on Dell OS10 platform
description:
- This os10 plugin provides low level abstraction apis for
sending and receiving CLI commands from Dell OS10 network devices.
"""
import re
import json
from itertools import chain
from ansible.module_utils._text import to_bytes, to_text
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
from ansible.plugins.cliconf import CliconfBase, enable_mode
class Cliconf(CliconfBase):
def get_device_info(self):
device_info = {}
device_info['network_os'] = 'dellemc.os10.os10'
reply = self.get('show version')
data = to_text(reply, errors='surrogate_or_strict').strip()
match = re.search(r'OS Version (\S+)', data)
if match:
device_info['network_os_version'] = match.group(1)
match = re.search(r'System Type (\S+)', data, re.M)
if match:
device_info['network_os_model'] = match.group(1)
reply = self.get('show running-configuration | grep hostname')
data = to_text(reply, errors='surrogate_or_strict').strip()
match = re.search(r'^hostname (.+)', data, re.M)
if match:
device_info['network_os_hostname'] = match.group(1)
return device_info
@enable_mode
def get_config(self, source='running', format='text', flags=None):
if source not in ('running', 'startup'):
return self.invalid_params("fetching configuration from %s is not supported" % source)
if source == 'running':
cmd = 'show running-config all'
else:
cmd = 'show startup-config'
return self.send_command(cmd)
@enable_mode
def edit_config(self, command):
for cmd in chain(['configure terminal'], to_list(command), ['end']):
self.send_command(to_bytes(cmd))
def get(self, command, prompt=None, answer=None, sendonly=False, newline=True, check_all=False):
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
def get_capabilities(self):
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)

View File

@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2020, Peter Sprygada <psprygada@ansible.com>
# Copyright: (c) 2020, Dell Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):
# Standard files documentation fragment
DOCUMENTATION = r'''
options:
provider:
description:
- A dict object containing connection details.
type: dict
suboptions:
host:
description:
- Specifies the DNS host name or address for connecting to the remote
device over the specified transport. The value of host is used as
the destination address for the transport.
type: str
port:
description:
- Specifies the port to use when building the connection to the remote
device.
type: int
username:
description:
- User to authenticate the SSH session to the remote device. If the
value is not specified in the task, the value of environment variable
C(ANSIBLE_NET_USERNAME) will be used instead.
type: str
password:
description:
- Password to authenticate the SSH session to the remote device. If the
value is not specified in the task, the value of environment variable
C(ANSIBLE_NET_PASSWORD) will be used instead.
type: str
ssh_keyfile:
description:
- Path to an ssh key used to authenticate the SSH session to the remote
device. If the value is not specified in the task, the value of
environment variable C(ANSIBLE_NET_SSH_KEYFILE) will be used instead.
type: path
timeout:
description:
- Specifies idle timeout (in seconds) for the connection. Useful if the
console freezes before continuing. For example when saving
configurations.
type: int
authorize:
description:
- Instructs the module to enter privileged mode on the remote device before
sending any commands. If not specified, the device will attempt to execute
all commands in non-privileged mode. If the value is not specified in the
task, the value of environment variable C(ANSIBLE_NET_AUTHORIZE) will be
used instead.
type: bool
default: false
auth_pass:
description:
- Specifies the password to use if required to enter privileged mode on the
remote device. If I(authorize) is false, then this argument does nothing.
If the value is not specified in the task, the value of environment variable
C(ANSIBLE_NET_AUTH_PASS) will be used instead.
type: str
notes:
- For more information on using Ansible to manage Dell EMC Network devices see U(https://www.ansible.com/ansible-dell-networking).
'''

View File

@@ -0,0 +1,42 @@
from __future__ import (absolute_import, division, print_function)
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_native
from collections import OrderedDict
import traceback
LIB_IMP_ERR = None
ERR_MSG = None
try:
import xmltodict
import yaml
HAS_LIB = True
except Exception as e:
HAS_LIB = False
ERR_MSG = to_native(e)
LIB_IMP_ERR = traceback.format_exc()
__copyright__ = "(c) Copyright 2020 Dell Inc. or its subsidiaries. All rights reserved."
__metaclass__ = type
class BaseNetworkShow(object):
"""The goal of this class is to extended by other in order to implement show system network view ansible modules"""
def __init__(self):
self.module = AnsibleModule(argument_spec=self.get_fields())
if not HAS_LIB:
self.module.fail_json(
msg=ERR_MSG,
exception=LIB_IMP_ERR)
self.exit_msg = OrderedDict()
def xml_to_dict(self, value):
return xmltodict.parse(value)
def dict_to_yaml(self, value):
return yaml.safe_dump(value, default_flow_style=False)
if __name__ == '__main__':
pass

View File

@@ -0,0 +1,146 @@
#
# (c) 2020 Peter Sprygada, <psprygada@ansible.com>
# (c) 2020 Red Hat, Inc
#
# Copyright (c) 2020 Dell Inc.
#
# This code is part of Ansible, but is an independent component.
# This particular file snippet, and this file snippet only, is BSD licensed.
# Modules you write using this snippet, which is embedded dynamically by Ansible
# still belong to the author of the module, and may assign their own license
# to the complete work.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
from __future__ import (absolute_import, division, print_function)
import re
from ansible.module_utils._text import to_text
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.connection import exec_command
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, ConfigLine
__metaclass__ = type
_DEVICE_CONFIGS = {}
WARNING_PROMPTS_RE = [
r"[\r\n]?\[confirm yes/no\]:\s?$",
r"[\r\n]?\[y/n\]:\s?$",
r"[\r\n]?\[yes/no\]:\s?$"
]
os10_provider_spec = {
'host': dict(),
'port': dict(type='int'),
'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
'authorize': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']), type='bool'),
'auth_pass': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS']), no_log=True),
'timeout': dict(type='int'),
}
os10_argument_spec = {
'provider': dict(type='dict', options=os10_provider_spec),
}
def check_args(module, warnings):
pass
def get_config(module, flags=None):
flags = [] if flags is None else flags
cmd = 'show running-configuration'
cmd += ' '.join(flags)
cmd = cmd.strip()
try:
return _DEVICE_CONFIGS[cmd]
except KeyError:
rc, out, err = exec_command(module, cmd)
if rc != 0:
module.fail_json(msg='unable to retrieve current config', stderr=to_text(err, errors='surrogate_or_strict'))
cfg = to_text(out, errors='surrogate_or_strict').strip()
_DEVICE_CONFIGS[cmd] = cfg
return cfg
def to_commands(module, commands):
spec = {
'command': dict(key=True),
'prompt': dict(),
'answer': dict()
}
transform = ComplexList(spec, module)
return transform(commands)
def run_commands(module, commands, check_rc=True):
responses = list()
commands = to_commands(module, to_list(commands))
for cmd in commands:
cmd = module.jsonify(cmd)
rc, out, err = exec_command(module, cmd)
if check_rc and rc != 0:
module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), rc=rc)
responses.append(to_text(out, errors='surrogate_or_strict'))
return responses
def load_config(module, commands):
rc, out, err = exec_command(module, 'configure terminal')
if rc != 0:
module.fail_json(msg='unable to enter configuration mode', err=to_text(err, errors='surrogate_or_strict'))
commands.append('commit')
for command in to_list(commands):
if command == 'end':
continue
rc, out, err = exec_command(module, command)
if rc != 0:
module.fail_json(msg=to_text(err, errors='surrogate_or_strict'), command=command, rc=rc)
exec_command(module, 'end')
def get_sublevel_config(running_config, module):
contents = list()
current_config_contents = list()
running_config = NetworkConfig(contents=running_config, indent=1)
obj = running_config.get_object(module.params['parents'])
if obj:
contents = obj.children
contents[:0] = module.params['parents']
indent = 0
for c in contents:
if isinstance(c, str):
current_config_contents.append(c.rjust(len(c) + indent, ' '))
if isinstance(c, ConfigLine):
current_config_contents.append(c.raw)
indent = 1
sublevel_config = '\n'.join(current_config_contents)
return sublevel_config

View File

@@ -0,0 +1,124 @@
#!/usr/bin/python
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__copyright__ = "(c) Copyright 2020 Dell Inc. or its subsidiaries. All rights reserved."
__metaclass__ = type
DOCUMENTATION = '''
module: base_xml_to_dict
author: "Senthil Kumar Ganesan (@skg-net)"
short_description: Operations for show command output convertion from xml to json format.
description:
- Get the show system inforamtion of a Leaf-Spine.
options:
cli_responses:
type: str
description:
- show command xml output
required: True
'''
EXAMPLES = '''
Copy below YAML into a playbook (e.g. play.yml) and run as follows:
#$ ansible-playbook -i inv play.yml
name: setup the plabook to get show command output in dict format
hosts: localhost
connection: local
gather_facts: False
vars:
cli:
username: admin
password: admin
tasks:
- name: "Get Dell EMC OS10 Show output in dict format"
os10_command:
commands: "{{ command_list }}"
register: show
- debug: var=show
- name: call to lib to get output in dict
base_xml_to_dict:
cli_responses: "{{ item }}"
loop: "{{ show.stdout }}"
'''
from ansible.module_utils._text import to_native
from ansible.module_utils.basic import AnsibleModule
from collections import OrderedDict
import traceback
LIB_IMP_ERR = None
ERR_MSG = None
try:
import xmltodict
HAS_LIB = True
except Exception as e:
HAS_LIB = False
ERR_MSG = to_native(e)
LIB_IMP_ERR = traceback.format_exc()
class XmlToDictAnsibleModule(object):
"""The goal of this class is to convert xml input to dict"""
def __init__(self):
self.module = AnsibleModule(argument_spec=self.get_fields())
self.cli_responses = self.module.params['cli_responses']
self.exit_msg = OrderedDict()
def get_fields(self):
"""Return valid fields"""
base_fields = {
'cli_responses': {
'type': 'str',
'required': True
}
}
return base_fields
def build_xml_list(self, xml_output):
xml_str_list = []
xml_declaration_tag = '<?xml version="1.0"?>\n'
for data in xml_output.split('<?xml version="1.0"'):
if not data:
continue
xml_data = ''.join(data.splitlines(True)[1:])
xml_str_list.append(xml_declaration_tag + xml_data)
return xml_str_list
def perform_action(self):
try:
out = list()
# the below line should be removed or not valid when the password
# decrypt issue is resolved
self.cli_responses = self.cli_responses.replace(
"*-", '').replace("*", '')
xml_str_list = self.build_xml_list(self.cli_responses)
for xml_list in xml_str_list:
out.append(xmltodict.parse(xml_list))
self.exit_msg.update({"result": out})
self.module.exit_json(changed=False, msg=self.exit_msg)
except Exception as e:
self.module.fail_json(
msg=to_native(e),
exception=traceback.format_exc())
def main():
module_instance = XmlToDictAnsibleModule()
if not HAS_LIB:
module_instance.module.fail_json(msg=ERR_MSG,
exception=LIB_IMP_ERR)
module_instance.perform_action()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,303 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__copyright__ = "(c) 2020 Dell Inc. or its subsidiaries. All rights reserved."
__metaclass__ = type
DOCUMENTATION = '''
module: bgp_validate
author: "Senthil Kumar Ganesan (@skg-net)"
short_description: Validate the bgp neighbor state,raise error if it is not in established state
description:
- Troubleshoot the bgp neighor state info using show ip bgp summary and show ip interface brief.
options:
show_ip_bgp:
description:
- show ip bgp summary output
type: 'list'
required: True
show_ip_intf_brief:
description:
- show ip interface brief output
type: 'list'
required: True
bgp_neighbors:
description:
- planned neighbours input from group_var to compare actual
type: 'list'
required: True
'''
EXAMPLES = '''
Copy below YAML into a playbook (e.g. play.yml) and run as follows:
#$ ansible-playbook -i inv play.yml
name: Validate BGP configuration
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: "Get Dell EMC OS10 Show ip bgp summary"
os10_command:
commands:
- command: "show ip bgp summary | display-xml"
- command: "show ip interface brief | display-xml"
provider: "{{ hostvars[item].cli }}"
with_items: "{{ groups['all'] }}"
register: show_bgp
- set_fact:
output_bgp: "{{ output_bgp|default([])+ [{'host': item.invocation.module_args.provider.host, 'inv_name': item.item,
'stdout_show_bgp': item.stdout.0, 'stdout_show_ip': item.stdout.1}] }}"
loop: "{{ show_bgp.results }}"
- debug: var=output_bgp
- local_action: copy content={{ output_bgp }} dest=show
- name: call lib to convert bgp info from xml to dict format
base_xml_to_dict:
cli_responses: "{{ item.stdout_show_bgp }}"
with_items:
- "{{ output_bgp }}"
register: show_bgp_list
- name: call lib to convert ip interface info from xml to dict format
base_xml_to_dict:
cli_responses: "{{ item.stdout_show_ip }}"
with_items:
- "{{ output_bgp }}"
register: show_ip_intf_list
- name: call lib for bgp validation
bgp_validate:
show_ip_bgp: "{{ show_bgp_list.results }}"
show_ip_intf_brief: "{{ show_ip_intf_list.results }}"
bgp_neighbors: "{{ intended_bgp_neighbors }}"
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_native
from collections import OrderedDict
import traceback
class BgpValidation(object):
def __init__(self):
self.module = AnsibleModule(argument_spec=self.get_fields())
self.show_ip_bgp = self.module.params['show_ip_bgp']
self.show_ip_intf_brief = self.module.params['show_ip_intf_brief']
self.bgp_neighbors = self.module.params['bgp_neighbors']
self.exit_msg = OrderedDict()
def get_fields(self):
spec_fields = {
'show_ip_bgp': {
'type': 'list',
'required': True
},
'show_ip_intf_brief': {
'type': 'list',
'required': True
},
'bgp_neighbors': {
'type': 'list',
'required': True
}
}
return spec_fields
def parse_bgp_output(self):
show_bgp_dict = {}
for show_list in self.show_ip_bgp:
show_bgp_list = list()
item = show_list.get("item")
inv_name = None
if item is not None:
inv_name = item.get("inv_name")
msg = show_list.get("msg")
if msg is not None:
result = msg.get("result")
if result is not None:
for sub_result in result:
bgp_dict = {}
rpc_reply = sub_result.get("rpc-reply")
if rpc_reply is not None:
bulk = rpc_reply.get("bulk")
if bulk is not None:
data = bulk.get("data")
if data is not None and "peer-oper" in data:
peer_oper = data.get("peer-oper")
if peer_oper is not None and "remote-address" in peer_oper:
bgp_dict["remote_address"] = peer_oper.get(
"remote-address")
bgp_dict["bgp-state"] = peer_oper.get(
"bgp-state")
show_bgp_list.append(bgp_dict)
show_bgp_dict[inv_name] = show_bgp_list
return show_bgp_dict
def parse_ip_intf_output(self):
show_ip_dict = {}
for show_list in self.show_ip_intf_brief:
show_ip_list = list()
item = show_list.get("item")
inv_name = None
if item is not None:
inv_name = item.get("inv_name")
msg = show_list.get("msg")
if msg is not None:
result = msg.get("result")
if result is not None:
for sub_result in result:
rpc_reply = sub_result.get("rpc-reply")
if rpc_reply is not None:
bulk = rpc_reply.get("bulk")
if bulk is not None:
data = bulk.get("data")
if data is not None:
sub_val = data.get("interface")
if sub_val is not None:
for val in sub_val:
intf_dict = {}
if "ipv4-info" in val:
ipv4_info = val.get(
"ipv4-info")
if ipv4_info is not None and "addr" in ipv4_info:
intf_dict["address"] = ipv4_info.get(
"addr")
intf_dict["if_name"] = val.get(
"name")
intf_dict["oper_status"] = val.get(
"oper-status")
if bool(intf_dict):
show_ip_list.append(intf_dict)
show_ip_dict[inv_name] = show_ip_list
return show_ip_dict
def get_intf_info_per_ip(self, intf_dict):
final_intf_dict = {}
for key1, value1 in intf_dict.items():
intf_list = value1
intf_dict = {}
for ip in intf_list:
intf_info = {}
ip_address = ip.get("address")
intf_address = ip_address.split('/')
intf_ip = intf_address[0]
intf_info["if_name"] = ip.get("if_name")
intf_info["oper_status"] = ip.get("oper_status")
intf_info["dest_switch"] = key1
intf_dict[intf_ip] = intf_info
if bool(intf_dict):
final_intf_dict[key1] = intf_dict
return final_intf_dict
def get_intf_info_from_neighbor_ip(
self, source_switch, neighbor_ip, intf_dict):
final_intf_info = {}
intf_dict_per_ip = self.get_intf_info_per_ip(intf_dict)
for key, value in intf_dict_per_ip.items():
switch_name = key
if source_switch == switch_name:
continue
intf_info = value.get(neighbor_ip)
if intf_info is None:
continue
final_intf_info = intf_info
break
return final_intf_info
def get_bgp_final_nbr_list(self, bgp_dict, intf_dict):
actual_bgp_dict = {}
final_bgp_dict = {}
for key, value in bgp_dict.items():
actual_bgp_list = list()
bgp_list = value
source_switch = key
for bgp in bgp_list:
final_dict = {}
bgp_state = bgp.get("bgp-state")
remote_address = bgp.get("remote_address")
reason = "neighbor config missing"
error_type = "config_missing"
intf_info = self.get_intf_info_from_neighbor_ip(
source_switch, remote_address, intf_dict)
if bool(intf_info):
dest_switch = intf_info.get("dest_switch")
remote_port = intf_info.get("if_name")
oper_status = intf_info.get("oper_status")
final_dict["source_switch"] = source_switch
final_dict["bgp_neighbor"] = remote_address
final_dict["bgp_state"] = bgp_state
if bgp_state != "established":
if oper_status != "up":
reason = (
"remote port {0} {1} is {2}" .format(
dest_switch, remote_port, oper_status))
error_type = "remote_port_down"
final_dict["error_type"] = error_type
final_dict["possible_reason"] = reason
else:
final_dict["source_switch"] = source_switch
final_dict["bgp_neighbor"] = remote_address
final_dict["bgp_state"] = bgp_state
final_dict["error_type"] = error_type
final_dict["possible_reason"] = reason
actual_bgp_list.append(final_dict)
actual_bgp_dict[source_switch] = actual_bgp_list
# check actual with intended neighbor to display the result
intended_list = list()
for intended_bgp_neighbor in self.bgp_neighbors:
planned_source_switch = intended_bgp_neighbor.get("source_switch")
planned_nbr_list = intended_bgp_neighbor.get("neighbor_ip")
actual_nbr_list = actual_bgp_dict.get(planned_source_switch)
if planned_nbr_list is None or actual_nbr_list is None:
continue
for actual_nbr in actual_nbr_list:
actual_source_switch = actual_nbr.get("source_switch")
actual_bgp_neighbor = actual_nbr.get("bgp_neighbor")
actual_bgp_state = actual_nbr.get("bgp_state")
if actual_bgp_neighbor in planned_nbr_list:
# Don't add established neighbor in result
if actual_bgp_state != "established":
intended_list.append(actual_nbr)
planned_nbr_list.remove(actual_bgp_neighbor)
else:
reason = "neighbor {0} is not an intended, please add this neighbor in the intended_bgp_neighbors".format(
actual_bgp_neighbor)
actual_nbr["bgp_neighbor"] = "-"
actual_nbr["error_type"] = "not_an_intended_neighbor"
actual_nbr["possible_reason"] = reason
intended_list.append(actual_nbr)
# Add the missed planned info which are not present in actual
# results
for planned_nbr in planned_nbr_list:
reason = "neighbor config missing"
temp_dict = {}
temp_dict["source_switch"] = planned_source_switch
temp_dict["bgp_neighbor"] = planned_nbr
temp_dict["error_type"] = "config_missing"
temp_dict["possible_reason"] = reason
intended_list.append(temp_dict)
return intended_list
def perform_action(self):
try:
bgp_dict = self.parse_bgp_output()
intf_dict = self.parse_ip_intf_output()
final_bgp_list = self.get_bgp_final_nbr_list(bgp_dict, intf_dict)
self.exit_msg.update({"results": final_bgp_list})
self.module.exit_json(changed=False, msg=self.exit_msg)
except Exception as e:
self.module.fail_json(
msg=to_native(e),
exception=traceback.format_exc())
def main():
module_instance = BgpValidation()
module_instance.perform_action()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,220 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__copyright__ = "(c) 2020 Dell Inc. or its subsidiaries. All rights reserved."
__metaclass__ = type
DOCUMENTATION = '''
module: mtu_validate
author: "Senthil Kumar Ganesan (@skg-net)"
short_description: Validate the MTU value for lldp neighbors
description:
- Get the wiring info using lldp output and show system network summary.
options:
show_lldp_neighbors_list:
description:
- show lldp neighbor output
type: 'list'
required: True
show_system_network_summary:
description:
- show system network summary output
type: 'list'
required: True
show_ip_intf_brief:
description:
- show ip intf brief
type: 'list'
required: True
'''
EXAMPLES = '''
Copy below YAML into a playbook (e.g. play.yml) and run follows:
#$ ansible-playbook -i inv play.yml
name: show mtu mismatch info
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: "Get Dell EMC OS10 MTU mismatch info"
os10_command:
commands:
- command: "show lldp neighbors"
- command: "show ip interface brief | display-xml"
provider: "{{ hostvars[item].cli }}"
with_items: "{{ groups['all'] }}"
register: show_lldp
- set_fact:
output: "{{ output|default([])+ [{'host': item.invocation.module_args.provider.host, 'inv_name': item.item,
'stdout_show_lldp': item.stdout.0, 'stdout_show_ip': item.stdout.1 }] }}"
loop: "{{ show_lldp.results }}"
- debug: var=output
- local_action: copy content={{ output }} dest=show1
- name: call lib to convert ip interface info from xml to dict format
base_xml_to_dict:
cli_responses: "{{ item.stdout_show_ip }}"
with_items: "{{ output }}"
register: show_ip_intf_list
- local_action: copy content={{ show_ip_intf_list }} dest=show_ip
- name: "Get Dell EMC OS10 Show system"
import_role:
name: os10_fabric_summary
register: show_system_network_summary
- debug: var=show_system_network_summary
- name: call lib to process
mtu_validate:
show_lldp_neighbors_list: "{{ output }}"
show_system_network_summary: "{{ show_system_network_summary.msg.results }}"
show_ip_intf_brief: "{{ show_ip_intf_list.results }}"
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_native
from collections import OrderedDict
import re
import traceback
class MtuValidation(object):
def __init__(self):
self.module = AnsibleModule(argument_spec=self.get_fields())
self.show_lldp_neighbors_list = self.module.params['show_lldp_neighbors_list']
self.show_system_network_summary = self.module.params['show_system_network_summary']
self.show_ip_intf_brief = self.module.params['show_ip_intf_brief']
self.exit_msg = OrderedDict()
def get_fields(self):
spec_fields = {
'show_lldp_neighbors_list': {
'type': 'list',
'required': True
},
'show_system_network_summary': {
'type': 'list',
'required': True
},
'show_ip_intf_brief': {
'type': 'list',
'required': True
}
}
return spec_fields
def get_int_mtu(self, spine, port):
for show_list in self.show_ip_intf_brief:
inv_name = show_list["item"]["inv_name"]
if spine != inv_name:
continue
value = show_list["msg"]["result"]
for data in value:
intf_list = data["rpc-reply"]["bulk"]["data"]["interface"]
for val in intf_list:
intf_name = val["name"]
if intf_name == port:
mtu = val["mtu"]
return mtu
return None
# form actual neighbors per network with help of lldp output and show
# sytem output
def get_actual_neigbor(self, lldp_list):
final_out = list()
for show_system in self.show_system_network_summary:
for lldp in lldp_list:
if show_system["host"] != lldp["host"] and "node-mac" in show_system and "rem_mac" in lldp:
rem_host = show_system["host"]
loc_host = lldp["host"]
# check whether lldp output mac match with system summary
# mac and collect port and host info
dest_switch = show_system["inv_name"]
source_switch = lldp["inv_name"]
lldp_mac = lldp["rem_mac"]
for index, rem_mac in enumerate(lldp_mac):
final_dict = {}
if (str.lower(
show_system["node-mac"])) == (str.lower(rem_mac)):
final_dict["source_switch"] = source_switch
final_dict["dest_switch"] = dest_switch
final_dict["source_port"] = lldp["loc_port"][index]
final_dict["dest_port"] = lldp["rem_port"][index]
source_mtu = self.get_int_mtu(
source_switch, final_dict["source_port"])
dest_mtu = self.get_int_mtu(
dest_switch, final_dict["dest_port"])
if source_mtu is not None:
final_dict["source_mtu"] = source_mtu
if dest_mtu is not None:
final_dict["dest_mtu"] = dest_mtu
final_out.append(final_dict)
return final_out
def parse_lldp_output(self):
nbr_list = list()
for cli in self.show_lldp_neighbors_list:
out_dict = {}
loc_port = list()
rem_port = list()
rem_mac = list()
for key, value in cli.items():
if key == "host":
out_dict[key] = value
if key == "inv_name":
out_dict[key] = value
if key == "stdout_show_lldp":
output = str(value)
lldp_regexp = r"(\S+)\s+(\S+)\s+(\S+)\s+(\S+)"
lines = output.splitlines()
for line in lines:
if "Loc PortID" in line:
continue
match = re.match(lldp_regexp, line)
if match:
val = match.groups()
loc_port.append(val[0])
rem_port.append(val[2])
rem_mac.append(val[3])
out_dict["loc_port"] = loc_port
out_dict["rem_port"] = rem_port
out_dict["rem_mac"] = rem_mac
nbr_list.append(out_dict)
return nbr_list
def get_mtu_mismatch_info(self, nbr_list):
mtu_list = list()
for nbr in nbr_list:
if nbr["source_mtu"] != nbr["dest_mtu"]:
nbr["error"] = "mismatch"
mtu_list.append(nbr)
return mtu_list
def perform_action(self):
try:
lldp_list = self.parse_lldp_output()
actual_nbr = self.get_actual_neigbor(lldp_list)
mtu_mismatch_list = self.get_mtu_mismatch_info(actual_nbr)
if len(mtu_mismatch_list) > 0:
self.exit_msg.update({"results": mtu_mismatch_list})
else:
self.exit_msg.update(
{"results": "There is no MTU mistmatch between neighbors"})
self.module.exit_json(changed=False, msg=self.exit_msg)
except Exception as e:
self.module.fail_json(
msg=to_native(e),
exception=traceback.format_exc())
def main():
module_instance = MtuValidation()
module_instance.perform_action()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,229 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2020, Peter Sprygada <psprygada@ansible.com>
# Copyright: (c) 2020, Dell Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = """
---
module: os10_command
author: "Senthil Kumar Ganesan (@skg-net)"
short_description: Run commands on devices running Dell EMC SmartFabric OS10
description:
- Sends arbitrary commands to a OS10 device and returns the results
read from the device. This module includes an
argument that will cause the module to wait for a specific condition
before returning or timing out if the condition is not met.
- This module does not support running commands in configuration mode.
Please use M(dellemc.os10.os10_config) to configure OS10 devices.
extends_documentation_fragment: dellemc.os10.os10
options:
commands:
description:
- List of commands to send to the remote OS10 device over the
configured provider. The resulting output from the command
is returned. If the I(wait_for) argument is provided, the
module is not returned until the condition is satisfied or
the number of retries has expired.
type: list
required: true
wait_for:
description:
- List of conditions to evaluate against the output of the
command. The task will wait for each condition to be true
before moving forward. If the conditional is not true
within the configured number of I(retries), the task fails.
See examples.
type: list
elements: str
match:
description:
- The I(match) argument is used in conjunction with the
I(wait_for) argument to specify the match policy. Valid
values are C(all) or C(any). If the value is set to C(all)
then all conditionals in the wait_for must be satisfied. If
the value is set to C(any) then only one of the values must be
satisfied.
type: str
default: all
choices: [ all, any ]
retries:
description:
- Specifies the number of retries a command should be tried
before it is considered failed. The command is run on the
target device every retry and evaluated against the
I(wait_for) conditions.
type: int
default: 10
interval:
description:
- Configures the interval in seconds to wait between retries
of the command. If the command does not pass the specified
conditions, the interval indicates how long to wait before
trying the command again.
type: int
default: 1
"""
EXAMPLES = """
tasks:
- name: run show version on remote devices
os10_command:
commands: show version
- name: run show version and check to see if output contains OS10
os10_command:
commands: show version
wait_for: result[0] contains OS10
- name: run multiple commands on remote nodes
os10_command:
commands:
- show version
- show interface
- name: run multiple commands and evaluate the output
os10_command:
commands:
- show version
- show interface
wait_for:
- result[0] contains OS10
- result[1] contains Ethernet
"""
RETURN = """
stdout:
description: The set of responses from the commands
returned: always apart from low level errors (such as action plugin)
type: list
sample: ['...', '...']
stdout_lines:
description: The value of stdout split into a list
returned: always apart from low level errors (such as action plugin)
type: list
sample: [['...', '...'], ['...'], ['...']]
failed_conditions:
description: The list of conditionals that have failed
returned: failed
type: list
sample: ['...', '...']
warnings:
description: The list of warnings (if any) generated by module based on arguments
returned: always
type: list
sample: ['...', '...']
"""
import time
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.dellemc.os10.plugins.module_utils.network.os10 import run_commands
from ansible_collections.dellemc.os10.plugins.module_utils.network.os10 import os10_argument_spec, check_args
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ComplexList
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
from ansible.module_utils.six import string_types
def to_lines(stdout):
for item in stdout:
if isinstance(item, string_types):
item = str(item).split('\n')
yield item
def parse_commands(module, warnings):
command = ComplexList(dict(
command=dict(key=True),
prompt=dict(),
answer=dict()
), module)
commands = command(module.params['commands'])
for index, item in enumerate(commands):
if module.check_mode and not item['command'].startswith('show'):
warnings.append(
'only show commands are supported when using check mode, not '
'executing `%s`' % item['command']
)
elif item['command'].startswith('conf'):
module.fail_json(
msg='os10_command does not support running config mode '
'commands. Please use os10_config instead'
)
return commands
def main():
"""main entry point for module execution
"""
argument_spec = dict(
# { command: <str>, prompt: <str>, response: <str> }
commands=dict(type='list', required=True),
wait_for=dict(type='list', elements='str'),
match=dict(default='all', choices=['all', 'any']),
retries=dict(default=10, type='int'),
interval=dict(default=1, type='int')
)
argument_spec.update(os10_argument_spec)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
result = {'changed': False}
warnings = list()
check_args(module, warnings)
commands = parse_commands(module, warnings)
result['warnings'] = warnings
wait_for = module.params['wait_for'] or list()
conditionals = [Conditional(c) for c in wait_for]
retries = module.params['retries']
interval = module.params['interval']
match = module.params['match']
while retries > 0:
responses = run_commands(module, commands)
for item in list(conditionals):
if item(responses):
if match == 'any':
conditionals = list()
break
conditionals.remove(item)
if not conditionals:
break
time.sleep(interval)
retries -= 1
if conditionals:
failed_conditions = [item.raw for item in conditionals]
msg = 'One or more conditional statements have not been satisfied'
module.fail_json(msg=msg, failed_conditions=failed_conditions)
result.update({
'changed': False,
'stdout': responses,
'stdout_lines': list(to_lines(responses))
})
module.exit_json(**result)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,346 @@
#!/usr/bin/python
#
# (c) 2020 Peter Sprygada, <psprygada@ansible.com>
# Copyright (c) 2020 Dell Inc.
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = """
---
module: os10_config
author: "Senthil Kumar Ganesan (@skg-net)"
short_description: Manage Dell EMC SmartFabric OS10 configuration sections
description:
- OS10 configurations use a simple block indent file syntax
for segmenting configuration into sections. This module provides
an implementation for working with OS10 configuration sections in
a deterministic way.
extends_documentation_fragment: dellemc.os10.os10
options:
lines:
description:
- The ordered set of commands that should be configured in the
section. The commands must be the exact same commands as found
in the device running-config. Be sure to note the configuration
command syntax as some commands are automatically modified by the
device config parser. This argument is mutually exclusive with I(src).
type: list
aliases: ['commands']
parents:
description:
- The ordered set of parents that uniquely identify the section or hierarchy
the commands should be checked against. If the parents argument
is omitted, the commands are checked against the set of top
level or global commands.
type: list
src:
description:
- Specifies the source path to the file that contains the configuration
or configuration template to load. The path to the source file can
either be the full path on the Ansible control host or a relative
path from the playbook or role root directory. This argument is
mutually exclusive with I(lines).
type: path
before:
description:
- The ordered set of commands to push on to the command stack if
a change needs to be made. This allows the playbook designer
the opportunity to perform configuration commands prior to pushing
any changes without affecting how the set of commands are matched
against the system.
type: list
after:
description:
- The ordered set of commands to append to the end of the command
stack if a change needs to be made. Just like with I(before) this
allows the playbook designer to append a set of commands to be
executed after the command set.
type: list
match:
description:
- Instructs the module on the way to perform the matching of
the set of commands against the current device config. If
match is set to I(line), commands are matched line by line. If
match is set to I(strict), command lines are matched with respect
to position. If match is set to I(exact), command lines
must be an equal match. Finally, if match is set to I(none), the
module will not attempt to compare the source configuration with
the running configuration on the remote device.
type: str
default: line
choices: ['line', 'strict', 'exact', 'none']
replace:
description:
- Instructs the module on the way to perform the configuration
on the device. If the replace argument is set to I(line) then
the modified lines are pushed to the device in configuration
mode. If the replace argument is set to I(block) then the entire
command block is pushed to the device in configuration mode if any
line is not correct.
type: str
default: line
choices: ['line', 'block']
update:
description:
- The I(update) argument controls how the configuration statements
are processed on the remote device. Valid choices for the I(update)
argument are I(merge) and I(check). When you set this argument to
I(merge), the configuration changes merge with the current
device running configuration. When you set this argument to I(check)
the configuration updates are determined but not actually configured
on the remote device.
type: str
default: merge
choices: ['merge', 'check']
save:
description:
- The C(save) argument instructs the module to save the running-
config to the startup-config at the conclusion of the module
running. If check mode is specified, this argument is ignored.
type: bool
default: 'no'
config:
description:
- The module, by default, will connect to the remote device and
retrieve the current running-config to use as a base for comparing
against the contents of source. There are times when it is not
desirable to have the task get the current running-config for
every task in a playbook. The I(config) argument allows the
implementer to pass in the configuration to use as the base
config for comparison.
type: str
backup:
description:
- This argument will cause the module to create a full backup of
the current C(running-config) from the remote device before any
changes are made. If the C(backup_options) value is not given,
the backup file is written to the C(backup) folder in the playbook
root directory. If the directory does not exist, it is created.
type: bool
default: 'no'
backup_options:
description:
- This is a dict object containing configurable options related to backup file path.
The value of this option is read only when C(backup) is set to I(yes), if C(backup) is set
to I(no) this option will be silently ignored.
suboptions:
filename:
description:
- The filename to be used to store the backup configuration. If the the filename
is not given it will be generated based on the hostname, current time and date
in format defined by <hostname>_config.<current-date>@<current-time>
type: str
dir_path:
description:
- This option provides the path ending with directory name in which the backup
configuration file will be stored. If the directory does not exist it will be first
created and the filename is either the value of C(filename) or default filename
as described in C(filename) options description. If the path value is not given
in that case a I(backup) directory will be created in the current working directory
and backup configuration will be copied in C(filename) within I(backup) directory.
type: path
type: dict
"""
EXAMPLES = """
- os10_config:
lines: ['hostname {{ inventory_hostname }}']
- os10_config:
lines:
- 10 permit ip host 1.1.1.1 any log
- 20 permit ip host 2.2.2.2 any log
- 30 permit ip host 3.3.3.3 any log
- 40 permit ip host 4.4.4.4 any log
- 50 permit ip host 5.5.5.5 any log
parents: ['ip access-list test']
before: ['no ip access-list test']
match: exact
- os10_config:
lines:
- 10 permit ip host 1.1.1.1 any log
- 20 permit ip host 2.2.2.2 any log
- 30 permit ip host 3.3.3.3 any log
- 40 permit ip host 4.4.4.4 any log
parents: ['ip access-list test']
before: ['no ip access-list test']
replace: block
- os10_config:
lines: ['hostname {{ inventory_hostname }}']
backup: yes
backup_options:
filename: backup.cfg
dir_path: /home/user
"""
RETURN = """
updates:
description: The set of commands that will be pushed to the remote device.
returned: always
type: list
sample: ['hostname foo', 'router bgp 1', 'router-id 1.1.1.1']
commands:
description: The set of commands that will be pushed to the remote device
returned: always
type: list
sample: ['hostname foo', 'router bgp 1', 'router-id 1.1.1.1']
saved:
description: Returns whether the configuration is saved to the startup
configuration or not.
returned: When not check_mode.
type: bool
sample: True
backup_path:
description: The full path to the backup file
returned: when backup is yes
type: str
sample: /playbooks/ansible/backup/os10_config.2016-07-16@22:28:34
"""
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.dellemc.os10.plugins.module_utils.network.os10 import get_config, get_sublevel_config
from ansible_collections.dellemc.os10.plugins.module_utils.network.os10 import os10_argument_spec, check_args
from ansible_collections.dellemc.os10.plugins.module_utils.network.os10 import load_config, run_commands
from ansible_collections.dellemc.os10.plugins.module_utils.network.os10 import WARNING_PROMPTS_RE
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, dumps
def get_candidate(module):
candidate = NetworkConfig(indent=1)
if module.params['src']:
candidate.load(module.params['src'])
elif module.params['lines']:
parents = module.params['parents'] or list()
commands = module.params['lines'][0]
if (isinstance(commands, dict)) and (isinstance((commands['command']), list)):
candidate.add(commands['command'], parents=parents)
elif (isinstance(commands, dict)) and (isinstance((commands['command']), str)):
candidate.add([commands['command']], parents=parents)
else:
candidate.add(module.params['lines'], parents=parents)
return candidate
def get_running_config(module):
contents = module.params['config']
if not contents:
contents = get_config(module)
return contents
def main():
backup_spec = dict(
filename=dict(),
dir_path=dict(type='path')
)
argument_spec = dict(
lines=dict(aliases=['commands'], type='list'),
parents=dict(type='list'),
src=dict(type='path'),
before=dict(type='list'),
after=dict(type='list'),
match=dict(default='line',
choices=['line', 'strict', 'exact', 'none']),
replace=dict(default='line', choices=['line', 'block']),
update=dict(choices=['merge', 'check'], default='merge'),
save=dict(type='bool', default=False),
config=dict(),
backup=dict(type='bool', default=False),
backup_options=dict(type='dict', options=backup_spec)
)
argument_spec.update(os10_argument_spec)
mutually_exclusive = [('lines', 'src')]
module = AnsibleModule(argument_spec=argument_spec,
mutually_exclusive=mutually_exclusive,
supports_check_mode=True)
parents = module.params['parents'] or list()
match = module.params['match']
replace = module.params['replace']
warnings = list()
check_args(module, warnings)
result = dict(changed=False, saved=False, warnings=warnings)
if module.params['backup']:
if not module.check_mode:
result['__backup__'] = get_config(module)
commands = list()
candidate = get_candidate(module)
if any((module.params['lines'], module.params['src'])):
if match != 'none':
config = get_running_config(module)
if parents:
contents = get_sublevel_config(config, module)
config = NetworkConfig(contents=contents, indent=1)
else:
config = NetworkConfig(contents=config, indent=1)
configobjs = candidate.difference(config, match=match, replace=replace)
else:
configobjs = candidate.items
if configobjs:
commands = dumps(configobjs, 'commands')
if ((isinstance((module.params['lines']), list)) and
(isinstance((module.params['lines'][0]), dict)) and
(set(['prompt', 'answer']).issubset(module.params['lines'][0]))):
cmd = {'command': commands,
'prompt': module.params['lines'][0]['prompt'],
'answer': module.params['lines'][0]['answer']}
commands = [module.jsonify(cmd)]
else:
commands = commands.split('\n')
if module.params['before']:
commands[:0] = module.params['before']
if module.params['after']:
commands.extend(module.params['after'])
if not module.check_mode and module.params['update'] == 'merge':
load_config(module, commands)
result['changed'] = True
result['commands'] = commands
result['updates'] = commands
if module.params['save']:
result['changed'] = True
if not module.check_mode:
cmd = {r'command': 'copy running-config startup-config',
r'prompt': r'\[confirm yes/no\]:\s?$', 'answer': 'yes'}
run_commands(module, [cmd])
result['saved'] = True
else:
module.warn('Skipping command `copy running-config startup-config`'
'due to check_mode. Configuration not copied to '
'non-volatile storage')
module.exit_json(**result)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,505 @@
#!/usr/bin/python
#
# (c) 2020 Peter Sprygada, <psprygada@ansible.com>
# Copyright (c) 2020 Dell Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = """
---
module: os10_facts
author: "Senthil Kumar Ganesan (@skg-net)"
short_description: Collect facts from devices running Dell EMC SmartFabric OS10
description:
- Collects a base set of device facts from a remote device that
is running OS10. This module prepends all of the
base network fact keys with C(ansible_net_<fact>). The facts
module will always collect a base set of facts from the device
and can enable or disable collection of additional facts.
extends_documentation_fragment: dellemc.os10.os10
options:
gather_subset:
description:
- When supplied, this argument will restrict the facts collected
to a given subset. Possible values for this argument include
all, hardware, config, and interfaces. Can specify a list of
values to include a larger subset. Values can also be used
with an initial C(M(!)) to specify that a specific subset should
not be collected.
type: list
default: [ '!config' ]
"""
EXAMPLES = """
# Collect all facts from the device
- os10_facts:
gather_subset: all
# Collect only the config and default facts
- os10_facts:
gather_subset:
- config
# Do not collect hardware facts
- os10_facts:
gather_subset:
- "!hardware"
"""
RETURN = """
ansible_net_gather_subset:
description: The list of fact subsets collected from the device
returned: always
type: list
# default
ansible_net_name:
description: The name of the OS that is running.
returned: Always.
type: str
ansible_net_version:
description: The operating system version running on the remote device
returned: always
type: str
ansible_net_servicetag:
description: The service tag number of the remote device.
returned: always
type: str
ansible_net_model:
description: The model name returned from the device.
returned: always
type: str
ansible_net_hostname:
description: The configured hostname of the device
returned: always
type: str
# hardware
ansible_net_cpu_arch:
description: CPU Architecture of the remote device.
returned: when hardware is configured
type: str
ansible_net_memfree_mb:
description: The available free memory on the remote device in Mb
returned: when hardware is configured
type: int
ansible_net_memtotal_mb:
description: The total memory on the remote device in Mb
returned: when hardware is configured
type: int
# config
ansible_net_config:
description: The current active config from the device
returned: when config is configured
type: str
# interfaces
ansible_net_all_ipv4_addresses:
description: All IPv4 addresses configured on the device
returned: when interfaces is configured
type: list
ansible_net_all_ipv6_addresses:
description: All IPv6 addresses configured on the device
returned: when interfaces is configured
type: list
ansible_net_interfaces:
description: A hash of all interfaces running on the system
returned: when interfaces is configured
type: dict
ansible_net_neighbors:
description: The list of LLDP neighbors from the remote device
returned: when interfaces is configured
type: dict
"""
import re
try:
from lxml import etree as ET
except ImportError:
import xml.etree.ElementTree as ET
from ansible_collections.dellemc.os10.plugins.module_utils.network.os10 import run_commands
from ansible_collections.dellemc.os10.plugins.module_utils.network.os10 import os10_argument_spec, check_args
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import iteritems
class FactsBase(object):
COMMANDS = []
def __init__(self, module):
self.module = module
self.facts = dict()
self.responses = None
def populate(self):
self.responses = run_commands(self.module, self.COMMANDS, check_rc=False)
def run(self, cmd):
return run_commands(self.module, cmd, check_rc=False)
class Default(FactsBase):
COMMANDS = [
'show version | display-xml',
'show system | display-xml',
]
def populate(self):
super(Default, self).populate()
data = self.responses[0]
xml_data = ET.fromstring(data.encode('utf8'))
self.facts['name'] = self.parse_name(xml_data)
self.facts['version'] = self.parse_version(xml_data)
self.facts['model'] = self.parse_model(xml_data)
self.facts['hostname'] = self.parse_hostname(xml_data)
data = self.responses[1]
xml_data = ET.fromstring(data.encode('utf8'))
self.facts['servicetag'] = self.parse_servicetag(xml_data)
def parse_name(self, data):
sw_name = data.find('./data/system-sw-state/sw-version/sw-name')
if sw_name is not None:
return sw_name.text
else:
return ""
def parse_version(self, data):
sw_ver = data.find('./data/system-sw-state/sw-version/sw-version')
if sw_ver is not None:
return sw_ver.text
else:
return ""
def parse_hostname(self, data):
hostname = data.find('./data/system-state/system-status/hostname')
if hostname is not None:
return hostname.text
else:
return ""
def parse_model(self, data):
prod_name = data.find('./data/system-sw-state/sw-version/sw-platform')
if prod_name is not None:
return prod_name.text
else:
return ""
def parse_servicetag(self, data):
svc_tag = data.find('./data/system/node/unit/mfg-info/service-tag')
if svc_tag is not None:
return svc_tag.text
else:
return ""
class Hardware(FactsBase):
COMMANDS = [
'show version | display-xml',
'show processes node-id 1 | grep "Mem :"'
]
def populate(self):
super(Hardware, self).populate()
data = self.responses[0]
xml_data = ET.fromstring(data.encode('utf8'))
self.facts['cpu_arch'] = self.parse_cpu_arch(xml_data)
data = self.responses[1]
match = self.parse_memory(data)
if match:
self.facts['memtotal_mb'] = int(match[0]) // 1024
self.facts['memfree_mb'] = int(match[1]) // 1024
def parse_cpu_arch(self, data):
cpu_arch = data.find('./data/system-sw-state/sw-version/cpu-arch')
if cpu_arch is not None:
return cpu_arch.text
else:
return ""
def parse_memory(self, data):
return re.findall(r'(\d+)', data, re.M)
class Config(FactsBase):
COMMANDS = ['show running-config']
def populate(self):
super(Config, self).populate()
self.facts['config'] = self.responses[0]
class Interfaces(FactsBase):
COMMANDS = [
'show interface | display-xml',
'show lldp neighbors | display-xml'
]
def __init__(self, module):
self.intf_facts = dict()
self.lldp_facts = dict()
super(Interfaces, self).__init__(module)
def populate(self):
super(Interfaces, self).populate()
self.facts['all_ipv4_addresses'] = list()
self.facts['all_ipv6_addresses'] = list()
int_show_data = (self.responses[0]).splitlines()
pattern = '?xml version'
data = ''
skip = True
# The output returns multiple xml trees
# parse them before handling.
for line in int_show_data:
if pattern in line:
if skip is False:
xml_data = ET.fromstring(data.encode('utf8'))
self.populate_interfaces(xml_data)
data = ''
else:
skip = False
data += line
if skip is False:
xml_data = ET.fromstring(data.encode('utf8'))
self.populate_interfaces(xml_data)
self.facts['interfaces'] = self.intf_facts
lldp_data = (self.responses[1]).splitlines()
data = ''
skip = True
# The output returns multiple xml trees
# parse them before handling.
for line in lldp_data:
if pattern in line:
if skip is False:
xml_data = ET.fromstring(data.encode('utf8'))
self.populate_neighbors(xml_data)
data = ''
else:
skip = False
data += line
if skip is False:
xml_data = ET.fromstring(data.encode('utf8'))
self.populate_neighbors(xml_data)
self.facts['neighbors'] = self.lldp_facts
def populate_interfaces(self, interfaces):
for interface in interfaces.findall('./data/interfaces/interface'):
intf = dict()
name = self.parse_item(interface, 'name')
intf['description'] = self.parse_item(interface, 'description')
intf['duplex'] = self.parse_item(interface, 'duplex')
intf['primary_ipv4'] = self.parse_primary_ipv4(interface)
intf['secondary_ipv4'] = self.parse_secondary_ipv4(interface)
intf['ipv6'] = self.parse_ipv6_address(interface)
intf['mtu'] = self.parse_item(interface, 'mtu')
intf['type'] = self.parse_item(interface, 'type')
self.intf_facts[name] = intf
for interface in interfaces.findall('./bulk/data/interface'):
name = self.parse_item(interface, 'name')
try:
intf = self.intf_facts[name]
intf['bandwidth'] = self.parse_item(interface, 'speed')
intf['adminstatus'] = self.parse_item(interface, 'admin-status')
intf['operstatus'] = self.parse_item(interface, 'oper-status')
intf['macaddress'] = self.parse_item(interface, 'phys-address')
except KeyError:
# skip the reserved interfaces
pass
for interface in interfaces.findall('./data/ports/ports-state/port'):
name = self.parse_item(interface, 'name')
# media-type name interface name format phy-eth 1/1/1
mediatype = self.parse_item(interface, 'media-type')
typ, sname = name.split('-eth')
name = "ethernet" + sname
try:
intf = self.intf_facts[name]
intf['mediatype'] = mediatype
except Exception:
# fanout
for subport in range(1, 5):
name = "ethernet" + sname + ":" + str(subport)
try:
intf = self.intf_facts[name]
intf['mediatype'] = mediatype
except Exception:
# valid case to handle 2x50G
pass
def add_ip_address(self, address, family):
if family == 'ipv4':
self.facts['all_ipv4_addresses'].append(address)
else:
self.facts['all_ipv6_addresses'].append(address)
def parse_item(self, interface, item):
elem = interface.find(item)
if elem is not None:
return elem.text
else:
return ""
def parse_primary_ipv4(self, interface):
ipv4 = interface.find('ipv4')
ip_address = ""
if ipv4 is not None:
prim_ipaddr = ipv4.find('./address/primary-addr')
if prim_ipaddr is not None:
ip_address = prim_ipaddr.text
self.add_ip_address(ip_address, 'ipv4')
return ip_address
def parse_secondary_ipv4(self, interface):
ipv4 = interface.find('ipv4')
ip_address = ""
if ipv4 is not None:
sec_ipaddr = ipv4.find('./address/secondary-addr')
if sec_ipaddr is not None:
ip_address = sec_ipaddr.text
self.add_ip_address(ip_address, 'ipv4')
return ip_address
def parse_ipv6_address(self, interface):
ip_address = list()
for addr in interface.findall('./ipv6/ipv6-addresses/address'):
ipv6_addr = addr.find('./ipv6-address')
if ipv6_addr is not None:
ip_address.append(ipv6_addr.text)
self.add_ip_address(ipv6_addr.text, 'ipv6')
return ip_address
def populate_neighbors(self, interfaces):
for interface in interfaces.findall('./bulk/data/interface'):
name = interface.find('name').text
rem_sys_name = interface.find('./lldp-rem-neighbor-info/info/rem-system-name')
if rem_sys_name is not None:
self.lldp_facts[name] = list()
fact = dict()
fact['host'] = rem_sys_name.text
rem_sys_port = interface.find('./lldp-rem-neighbor-info/info/rem-lldp-port-id')
fact['port'] = rem_sys_port.text
self.lldp_facts[name].append(fact)
FACT_SUBSETS = dict(
default=Default,
hardware=Hardware,
interfaces=Interfaces,
config=Config,
)
VALID_SUBSETS = frozenset(FACT_SUBSETS.keys())
def main():
"""main entry point for module execution
"""
argument_spec = dict(
gather_subset=dict(default=['!config'], type='list')
)
argument_spec.update(os10_argument_spec)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
gather_subset = module.params['gather_subset']
runable_subsets = set()
exclude_subsets = set()
for subset in gather_subset:
if subset == 'all':
runable_subsets.update(VALID_SUBSETS)
continue
if subset.startswith('!'):
subset = subset[1:]
if subset == 'all':
exclude_subsets.update(VALID_SUBSETS)
continue
exclude = True
else:
exclude = False
if subset not in VALID_SUBSETS:
module.fail_json(msg='Bad subset')
if exclude:
exclude_subsets.add(subset)
else:
runable_subsets.add(subset)
if not runable_subsets:
runable_subsets.update(VALID_SUBSETS)
runable_subsets.difference_update(exclude_subsets)
runable_subsets.add('default')
facts = dict()
facts['gather_subset'] = list(runable_subsets)
instances = list()
for key in runable_subsets:
instances.append(FACT_SUBSETS[key](module))
for inst in instances:
inst.populate()
facts.update(inst.facts)
ansible_facts = dict()
for key, value in iteritems(facts):
key = 'ansible_net_%s' % key
ansible_facts[key] = value
warnings = list()
check_args(module, warnings)
module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,145 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__copyright__ = "(c) 2020 Dell Inc. or its subsidiaries. All rights reserved."
__metaclass__ = type
DOCUMENTATION = '''
module: show_system_network_summary
author: "Senthil Kumar Ganesan (@skg-net)"
short_description: Operations for show_system_network output in json/yaml format.
description:
- Get the show system inforamtion of a Leaf-Spine.
options:
output_type:
type: str
description:
- json or yaml
- Default value is json
default: json
required: False
cli_responses:
type: list
required: True
description:
- show system command xml output
'''
EXAMPLES = '''
Copy below YAML into a playbook (e.g. play.yml) and run as follows:
#$ ansible-playbook -i inv show.yml
name: show system Configuration
hosts: localhost
connection: local
gather_facts: False
vars:
cli:
username: admin
password: admin
tasks:
- name: "Get Dell EMC OS10 Show system summary"
os10_command:
commands: ['show system | display-xml']
provider: "{{ hostvars[item].cli }}"
with_items: "{{ groups['all'] }}"
register: show_system
- set_fact:
output: "{{ output|default([])+ [{'inv_name': item.item, 'host': item.invocation.module_args.provider.host, 'stdout_show_system': item.stdout}] }}"
loop: "{{ show_system.results }}"
- debug: var=output
- name: "show system network call to lib "
show_system_network_summary:
cli_responses: "{{ output}} "
output_type: "{{ output_method if output_method is defined else 'json' }}"
register: show_system_network_summary
- debug: var=show_system_network_summary
'''
import re
from ansible_collections.dellemc.os10.plugins.module_utils.network.base_network_show import BaseNetworkShow
class ShowSystemNetworkSummary(BaseNetworkShow):
def __init__(self):
BaseNetworkShow.__init__(self)
self.cli_responses = self.module.params['cli_responses']
self.output_type = self.module.params['output_type']
self.changed = False
def get_fields(self):
spec_fields = {
'cli_responses': {
'type': 'list',
'required': True
},
'output_type': {
'type': 'str',
'default': "json",
'required': False
}
}
return spec_fields
def perform_action(self):
out = list()
show_system_summary = self.cli_responses
if len(show_system_summary) > 0:
for item in show_system_summary:
out_dict = {}
host = item.get("host")
inv_name = item.get("inv_name")
show_system_response = item.get("stdout_show_system")
if show_system_response is not None:
result = BaseNetworkShow.xml_to_dict(
self, show_system_response[0])
rpc_reply = result.get("rpc-reply")
if rpc_reply is not None:
data = rpc_reply.get("data")
if data is not None:
out_dict["host"] = host
out_dict["inv_name"] = inv_name
system_state = data.get("system-state")
if system_state is not None:
system_status = system_state.get(
"system-status")
if system_status is not None:
out_dict["hostname"] = system_status.get(
"hostname")
system = data.get("system")
if system is not None:
node = system.get("node")
if node is not None:
out_dict["node-mac"] = node.get("node-mac")
unit = node.get("unit")
if unit is not None:
out_dict["software-version"] = unit.get(
"software-version")
mfg_info = node.get("mfg-info")
if mfg_info is not None:
out_dict["service-tag"] = mfg_info.get(
"service-tag")
out_dict["device type"] = mfg_info.get(
"product-name")
if bool(out_dict):
out.append(out_dict)
if self.output_type != "json":
self.exit_msg.update(
{"results": (BaseNetworkShow.dict_to_yaml(self, out))})
else:
self.exit_msg.update({"results": (out)})
self.module.exit_json(changed=False, msg=self.exit_msg)
def main():
module_instance = ShowSystemNetworkSummary()
module_instance.perform_action()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,236 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__copyright__ = "(c) 2020 Dell Inc. or its subsidiaries. All rights reserved."
__metaclass__ = type
DOCUMENTATION = '''
module: vlt_validate
author: "Senthil Kumar Ganesan (@skg-net)"
short_description: Validate the vlt info, raise an error if peer is not in up state
description:
- Troubleshoot the show vlt info and raise an error if peer is not up.
options:
show_vlt:
description:
- show vlt output
type: 'list'
required: True
show_system_network_summary:
description:
- show system summary output
type: 'list'
required: True
intended_vlt_pairs:
description:
- intended vlt pair intput to verify with actual
type: 'list'
required: True
'''
EXAMPLES = '''
Copy below YAML into a playbook (e.g. play.yml) and run as follows:
#$ ansible-playbook -i inv play.yml
name: show system Configuration
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: "Get Dell EMC OS10 Show run vlt"
os10_command:
commands:
- command: "show running-configuration vlt | grep vlt-domain"
provider: "{{ hostvars[item].cli }}"
with_items: "{{ groups['all'] }}"
register: show_run_vlt
- set_fact:
output_vlt: "{{ output_vlt|default([])+ [{'host': item.invocation.module_args.provider.host, 'inv_name': item.item,
'stdout_show_vlt': item.stdout.0}] }}"
loop: "{{ show_run_vlt.results }}"
- debug: var=output_vlt
- name: "Get Dell EMC OS10 Show vlt info"
os10_command:
commands:
- command: "show vlt {{ item.stdout_show_vlt.split()[1] }} | display-xml"
provider: "{{ hostvars[item.inv_name].cli }}"
with_items: "{{ output_vlt }}"
register: show_vlt
- set_fact:
vlt_out: "{{ vlt_out|default([])+ [{'host': item.invocation.module_args.provider.host, 'inv_name': item.item, 'show_vlt_stdout': item.stdout.0}] }}"
loop: "{{ show_vlt.results }}"
register: vlt_output
- name: call lib to convert vlt info from xml to dict format
base_xml_to_dict:
cli_responses: "{{ item.show_vlt_stdout }}"
with_items:
- "{{ vlt_out }}"
register: vlt_dict_output
- name: "Get Dell EMC OS10 Show system"
import_role:
name: os10_fabric_summary
register: show_system_network_summary
- name: call lib to process
vlt_validate:
show_vlt : "{{ vlt_dict_output.results }}"
show_system_network_summary: "{{ show_system_network_summary.msg.results }}"
intended_vlt_pairs: "{{ intended_vlt_pairs }}"
register: show_vlt_info
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_native
from collections import OrderedDict
import traceback
class VltValidation(object):
def __init__(self):
self.module = AnsibleModule(argument_spec=self.get_fields())
self.show_vlt = self.module.params['show_vlt']
self.show_system_network_summary = self.module.params['show_system_network_summary']
self.intended_vlt_pairs = self.module.params['intended_vlt_pairs']
self.exit_msg = OrderedDict()
def get_fields(self):
spec_fields = {
'show_vlt': {
'type': 'list',
'required': True
},
'show_system_network_summary': {
'type': 'list',
'required': True
},
'intended_vlt_pairs': {
'type': 'list',
'required': True
}
}
return spec_fields
# get switch inv name from mac
def get_switch_inv_name_from_mac(self, mac):
inv_name = None
for show_system in self.show_system_network_summary:
if (str.lower(show_system["node-mac"])) == (str.lower(mac)):
inv_name = show_system.get("inv_name")
break
return inv_name
def validate_vlt_pairs(self, actual_vlt_dict):
final_out = list()
intended_vlt_list = self.intended_vlt_pairs
for intended_vlt in intended_vlt_list:
intended_primary = intended_vlt.get("primary")
intended_secondary = intended_vlt.get("secondary")
actual_vlt = actual_vlt_dict.get(intended_primary)
temp_dict = {}
if actual_vlt is not None:
actual_secondary = actual_vlt.get("secondary")
secondary_status = actual_vlt.get("secondary_status")
if actual_secondary is not None and intended_secondary != actual_secondary:
temp_dict["error_type"] = "secondary_mismatch"
temp_dict["intended_primary"] = intended_primary
temp_dict["intended_secondary"] = intended_secondary
temp_dict["secondary"] = actual_secondary
reason = "config mismatch as {0} is expected, but the actual secondary is {1} " .format(
intended_secondary, actual_secondary)
temp_dict["possible_reason"] = reason
final_out.append(temp_dict)
else:
if actual_secondary is None:
temp_dict["intended_primary"] = intended_primary
temp_dict["intended_secondary"] = intended_secondary
temp_dict["error_type"] = "peer_missing"
reason = "peer info is not configured or peer interface is down"
temp_dict["possible_reason"] = reason
final_out.append(temp_dict)
elif intended_secondary == actual_secondary and secondary_status != "up":
temp_dict["intended_primary"] = intended_primary
temp_dict["intended_secondary"] = intended_secondary
temp_dict["secondary"] = actual_secondary
temp_dict["error_type"] = "peer_down"
reason = "peer interface is down"
temp_dict["possible_reason"] = reason
final_out.append(temp_dict)
else:
temp_dict["intended_primary"] = intended_primary
temp_dict["intended_secondary"] = intended_secondary
temp_dict["error_type"] = "vlt_config_missing"
temp_dict["possible_reason"] = "vlt is not configured"
final_out.append(temp_dict)
return final_out
def parse_vlt_output(self):
show_vlt_dict = {}
for show_list in self.show_vlt:
source_switch = None
item = show_list.get("item")
if item is not None:
inv_info = item.get("inv_name")
source_switch = inv_info.get("inv_name")
msg = show_list.get("msg")
if msg is not None:
result = msg.get("result")
for sub_result in result:
vlt_dict = {}
rpc_reply = sub_result.get("rpc-reply")
data = rpc_reply.get("data")
if data is not None:
topo_oper_data = data.get("topology-oper-data")
if topo_oper_data is not None:
vlt_domain = topo_oper_data.get("vlt-domain")
if vlt_domain is not None:
local_info = vlt_domain.get("local-info")
if local_info is not None:
local_role = local_info.get("role")
vlt_dict[local_role] = source_switch
local_mac = local_info.get("system-mac")
vlt_dict[local_role + "_mac"] = local_mac
peer_info = vlt_domain.get("peer-info")
if peer_info is not None:
peer_mac = peer_info.get("system-mac")
peer_switch = self.get_switch_inv_name_from_mac(
peer_mac)
peer_role = peer_info.get("role")
vlt_dict[peer_role] = peer_switch
vlt_dict[peer_role + "_mac"] = peer_mac
peer_status = peer_info.get("peer-status")
vlt_dict[peer_role +
"_status"] = peer_status
if bool(vlt_dict):
primary_switch = vlt_dict.get("primary")
vlt_data = show_vlt_dict.get(primary_switch)
if vlt_data is None:
# update database specific to primary, it helps
# to avoid to skip duplicate data
show_vlt_dict[primary_switch] = vlt_dict
return show_vlt_dict
def perform_action(self):
try:
actual_vlt_dict = self.parse_vlt_output()
final_out = self.validate_vlt_pairs(actual_vlt_dict)
self.exit_msg.update({"results": final_out})
self.module.exit_json(changed=False, msg=self.exit_msg)
except Exception as e:
self.module.fail_json(
msg=to_native(e),
exception=traceback.format_exc())
def main():
module_instance = VltValidation()
module_instance.perform_action()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,246 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__copyright__ = "(c) 2020 Dell Inc. or its subsidiaries. All rights reserved."
__metaclass__ = type
DOCUMENTATION = '''
module: wiring_validate
author: "Senthil Kumar Ganesan (@skg-net)"
short_description: Validate the wiring based on the planned wiring details
description:
- Get the wiring info using lldp output and show system network summary.
options:
show_lldp_neighbors_list:
description:
- show lldp neighbor output
type: 'list'
required: True
show_system_network_summary:
description:
- show system network summary output
type: 'list'
required: True
planned_neighbors:
description:
- planned neighbours input from group_var to compare actual
type: 'list'
required: True
'''
EXAMPLES = '''
Copy below YAML into a playbook (e.g. play.yml) and run as follows:
#$ ansible-playbook -i inv play.yml
name: show system Configuration
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: "Get Dell EMC OS10 Show lldp"
os10_command:
commands:
- command: "show lldp neighbors"
provider: "{{ hostvars[item].cli }}"
with_items: "{{ groups['all'] }}"
register: show_lldp
- local_action: copy content={{ show_lldp }} dest=show
- set_fact:
output_lldp: "{{ output_lldp|default([])+ [{'host': item.invocation.module_args.provider.host, 'inv_name': item.item,
'stdout_show_lldp': item.stdout}] }}"
loop: "{{ show_lldp.results }}"
- debug: var=output_lldp
- name: "Get Dell EMC OS10 Show system"
import_role:
name: os10_fabric_summary
register: show_system_network_summary
- debug: var=show_system_network_summary
- name: call lib to process
wiring_validate:
show_lldp_neighbors_list: "{{ output_lldp }}"
show_system_network_summary: "{{ show_system_network_summary.msg.results }}"
planned_neighbors: "{{ intended_neighbors }}"
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_native
from collections import OrderedDict
import re
import traceback
class WiringValidation(object):
def __init__(self):
self.module = AnsibleModule(argument_spec=self.get_fields())
self.show_lldp_neighbors_list = self.module.params['show_lldp_neighbors_list']
self.show_system_network_summary = self.module.params['show_system_network_summary']
self.planned_neighbors = self.module.params['planned_neighbors']
self.exit_msg = OrderedDict()
def get_fields(self):
spec_fields = {
'show_lldp_neighbors_list': {
'type': 'list',
'required': True
},
'show_system_network_summary': {
'type': 'list',
'required': True
},
'planned_neighbors': {
'type': 'list',
'required': True
}
}
return spec_fields
# get switch inv name from mac
def get_switch_inv_name_from_mac(self, mac):
inv_name = None
for show_system in self.show_system_network_summary:
if (str.lower(show_system["node-mac"])) == (str.lower(mac)):
inv_name = show_system.get("inv_name")
break
return inv_name
# get service tag for switch
def get_service_tag_and_mac(self):
svc_tag_mac = {}
for show_system in self.show_system_network_summary:
temp_dict = {}
temp_dict["svc-tag"] = show_system.get("service-tag")
temp_dict["node-mac"] = show_system.get("node-mac")
if bool(temp_dict):
svc_tag_mac[show_system["inv_name"]] = temp_dict
return svc_tag_mac
# form actual neighbors per network with help of lldp output and show
# sytem output
def get_actual_neigbor(self, lldp_list):
final_out = list()
for lldp in lldp_list:
# check whether lldp output mac match with system summary mac and
# collect port and host info
source_switch = lldp["inv_name"]
lldp_mac = lldp["rem_mac"]
for index, rem_mac in enumerate(lldp_mac):
final_dict = {}
final_dict["source_switch"] = source_switch
final_dict["source_port"] = lldp["loc_port"][index]
final_dict["dest_port"] = lldp["rem_port"][index]
dest_switch = self.get_switch_inv_name_from_mac(rem_mac)
if dest_switch is not None:
final_dict["dest_switch"] = dest_switch
else:
final_dict["dest_switch"] = "unknown"
final_out.append(final_dict)
return final_out
def parse_lldp_output(self):
nbr_list = list()
for item in self.show_lldp_neighbors_list:
out_dict = {}
loc_port = list()
rem_port = list()
rem_mac = list()
out_dict["host"] = item.get("host")
out_dict["inv_name"] = item.get("inv_name")
show_lldp_output = item.get("stdout_show_lldp")
if show_lldp_output is not None:
output = str(show_lldp_output[0])
lldp_regexp = r"(\S+)\s+(\S+)\s+(\S+)\s+(\S+)"
lines = output.splitlines()
for line in lines:
if "Loc PortID" in line:
continue
match = re.match(lldp_regexp, line)
if match:
val = match.groups()
loc_port.append(val[0])
rem_port.append(val[2])
rem_mac.append(val[3])
out_dict["loc_port"] = loc_port
out_dict["rem_port"] = rem_port
out_dict["rem_mac"] = rem_mac
if bool(out_dict):
nbr_list.append(out_dict)
return nbr_list
def perform_action(self):
try:
lldp_list = self.parse_lldp_output()
actual_nbr = self.get_actual_neigbor(lldp_list)
svc_tag_mac = self.get_service_tag_and_mac()
# Validate the planned neighbors with actual neighbors
mismatch_list = list()
for planned_neighbors in self.planned_neighbors:
bflag = False
if planned_neighbors not in actual_nbr:
for actual_neighbors in actual_nbr:
if (actual_neighbors["source_switch"] == planned_neighbors["source_switch"]
and actual_neighbors["source_port"] == planned_neighbors["source_port"]):
if (actual_neighbors["dest_switch"] !=
planned_neighbors["dest_switch"]):
bflag = True
if (actual_neighbors["dest_switch"]
!= "unknown"):
reason = (
"Destination switch is not an expected value, "
"expected switch: {0},port: {1}; actual switch: {2}(svc-tag:{3}, node_mac:{4}), port: {5}" .format(
planned_neighbors["dest_switch"],
planned_neighbors["dest_port"],
actual_neighbors["dest_switch"],
svc_tag_mac.get(
actual_neighbors["dest_switch"]).get("svc-tag"),
svc_tag_mac.get(
actual_neighbors["dest_switch"]).get("node-mac"),
actual_neighbors["dest_port"]))
else:
reason = (
"Destination switch is not an expected value, "
"expected switch: {0},port: {1}; actual switch: {2}, port: {3}" .format(
planned_neighbors["dest_switch"],
planned_neighbors["dest_port"],
actual_neighbors["dest_switch"],
actual_neighbors["dest_port"]))
planned_neighbors["reason"] = reason
planned_neighbors["error_type"] = "link-mismatch"
break
if(actual_neighbors["dest_port"] != planned_neighbors["dest_port"]):
bflag = True
reason = (
"Destination switch port is not an expected value, "
"expected port: {0} actual port: {1}" .format(
planned_neighbors["dest_port"],
actual_neighbors["dest_port"]))
planned_neighbors["reason"] = reason
planned_neighbors["error_type"] = "link-mismatch"
break
if not bflag:
reason = "link is not found for source switch: {0},port: {1}".format(
planned_neighbors["source_switch"], planned_neighbors["source_port"])
planned_neighbors["reason"] = reason
planned_neighbors["error_type"] = "link-missing"
mismatch_list.append(planned_neighbors)
self.exit_msg.update({"results": mismatch_list})
self.module.exit_json(changed=False, msg=self.exit_msg)
except Exception as e:
self.module.fail_json(
msg=to_native(e),
exception=traceback.format_exc())
def main():
module_instance = WiringValidation()
module_instance.perform_action()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,81 @@
#
# (c) 2020 Red Hat Inc.
#
# This file is part of Ansible
#
# Copyright (c) 2020 Dell Inc.
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import re
import json
from ansible.module_utils._text import to_text, to_bytes
from ansible.plugins.terminal import TerminalBase
from ansible.errors import AnsibleConnectionFailure
class TerminalModule(TerminalBase):
terminal_stdout_re = [
re.compile(br"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:#) ?$"),
re.compile(br"\[\w+\@[\w\-\.]+(?: [^\]])\] ?[>#\$] ?$")
]
terminal_stderr_re = [
re.compile(br"% ?Error"),
re.compile(br"% ?Bad secret"),
re.compile(br"Syntax error:"),
re.compile(br"invalid input", re.I),
re.compile(br"(?:incomplete|ambiguous) command", re.I),
re.compile(br"connection timed out", re.I),
re.compile(br"[^\r\n]+ not found", re.I),
re.compile(br"'[^']' +returned error code: ?\d+"),
]
def on_open_shell(self):
try:
self._exec_cli_command(b'terminal length 0')
except AnsibleConnectionFailure:
raise AnsibleConnectionFailure('unable to set terminal parameters')
def on_become(self, passwd=None):
if self._get_prompt().endswith(b'#'):
return
cmd = {u'command': u'enable'}
if passwd:
cmd[u'prompt'] = to_text(r"[\r\n]?password: $", errors='surrogate_or_strict')
cmd[u'answer'] = passwd
try:
self._exec_cli_command(to_bytes(json.dumps(cmd), errors='surrogate_or_strict'))
except AnsibleConnectionFailure:
raise AnsibleConnectionFailure('unable to elevate privilege to enable mode')
def on_unbecome(self):
prompt = self._get_prompt()
if prompt is None:
# if prompt is None most likely the terminal is hung up at a prompt
return
if prompt.strip().endswith(b')#'):
self._exec_cli_command(b'end')
self._exec_cli_command(b'disable')
elif prompt.endswith(b'#'):
self._exec_cli_command(b'disable')

View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (c) 2020, Dell Inc. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (c) 2020, Dell Inc. All rights reserved.
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -0,0 +1,136 @@
AAA role
========
This role facilitates the configuration of authentication, authorization, and acccounting (AAA). It supports the configuration of RADIUS server, TACACS server, and AAA. This role is abstracted for Dell EMC PowerSwitch platforms running Dell EMC SmartFabric OS10.
The AAA role requires an SSH connection for connectivity to a Dell EMC SmartFabric OS10 device. You can use any of the built-in OS connection variables.
Role variables
--------------
- Role is abstracted using the `ansible_network_os` variable that can take `dellemc.os10.os10` as the value
- If `os10_cfg_generate` is set to true, the variable generates the role configuration commands in a file
- Any role variable with a corresponding state variable set to absent negates the configuration of that variable
- Setting an empty value for any variable negates the corresponding configuration
- Variables and values are case-sensitive
**os10_aaa keys**
| Key | Type | Description | Support |
|------------|---------------------------|---------------------------------------------------------|-----------------------|
| ``radius_server`` | dictionary | Configures the RADIUS server (see ``radius_server.*``) | os10 |
| ``radius_server.retransmit`` | integer | Configures the number of retransmissions | os10 |
| ``radius_server.timeout`` | integer | Configures the timeout for retransmissions | os10 |
| ``radius_server.host`` | dictionary | Configures the RADIUS server host (see ``host.*``) | os10 |
| ``host.ip`` | string | Configures the RADIUS server host address | os10 |
| ``host.key`` | string (required); 0,7,LINE | Configures the authentication key | os10 |
| ``host.auth_port`` | integer | Configures the authentication port (0 to 65535) | os10 |
| ``host.state`` | string: present,absent | Removes the RADIUS server host if set to absent | os10 |
| ``auth.key`` | string (required); 0,7,LINE | Configures the authentication key | os10 |
| ``tacacs_server`` | dictionary | Configures the TACACS server (see ``tacacs_server.*``) | os10 |
| ``tacacs_server.timeout`` | integer | Configures the timeout for retransmissions | os10 |
| ``tacacs_server.host`` | dictionary | Configures the TACACS server host (see ``host.*``) | os10 |
| ``host.ip`` | string | Configures the TACACS server host address | os10 |
| ``host.key`` | string (required); 0,7,LINE | Configures the authentication key | os10 |
| ``host.auth_port`` | integer | Configures the authentication port (0 to 65535) | os10 |
| ``host.state`` | string: present,absent | Removes the TACACS server host if set to absent | os10 |
| ``auth.key`` | string (required); 0,7,LINE | Configures the authentication key | os10 |
| ``aaa_accounting`` | dictionary | Configures accounting parameters (see ``aaa_accounting.*``) | os10 |
| ``aaa_accounting.accounting.accounting_type`` | dictionary | Configures accounting type | os10 |
| ``aaa_accounting.accounting.connection_type`` | dictionary | Configures accounting connection type | os10 |
| ``aaa_accounting.accounting.account_mode`` | dictionary | Configures accounting mode | os10 |
| ``aaa_accounting.accounting.server_group`` | dictionary | Configures accounting server group | os10 |
| ``aaa_accounting.accounting.state`` | string: present,absent | Configures/unconfigures accounting parameters | os10 |
| ``aaa_authentication`` | dictionary | Configures authentication parameters (see ``aaa_authentication.*``) | os10 |
| ``aaa_authentication.login`` | dictionary | Configures authentication login (see ``aaa_authentication.login.*``)| os10 |
| ``aaa_authentication.login.console`` | dictionary | Configures authentication method for console login | os10 |
| ``aaa_authentication.login.state`` | string: present,absent | Unconfigures authentication login if set to absent | os10 |
| ``aaa_authentication.login.type`` | dictionary | Configures authentication type | os10 |
| ``aaa_authentication.re_authenticate`` | boolean | Configures re-authenticate by enable if set to true | os10 |
> **NOTE**: Asterisk (*) denotes the default value if none is specified.
Connection variables
--------------------
Ansible Dell EMC network roles require connection information to establish communication with the nodes in your inventory. This information can exist in the Ansible *group_vars* or *host_vars* directories or inventory, or in the playbook itself.
| Key | Required | Choices | Description |
|-------------|----------|------------|-----------------------------------------------------|
| ``ansible_host`` | yes | | Specifies the hostname or address for connecting to the remote device over the specified transport |
| ``ansible_port`` | no | | Specifies the port used to build the connection to the remote device; if value is unspecified, the `ANSIBLE_REMOTE_PORT` option is used; it defaults to 22 |
| ``ansible_ssh_user`` | no | | Specifies the username that authenticates the CLI login for the connection to the remote device; if value is unspecified, the `ANSIBLE_REMOTE_USER` environment variable value is used |
| ``ansible_ssh_pass`` | no | | Specifies the password that authenticates the connection to the remote device |
| ``ansible_become`` | no | yes, no\* | Instructs the module to enter privileged mode on the remote device before sending any commands; if value is unspecified, the `ANSIBLE_BECOME` environment variable value is used, and the device attempts to execute all commands in non-privileged mode |
| ``ansible_become_method`` | no | enable, sudo\* | Instructs the module to allow the become method to be specified for handling privilege escalation; if value is unspecified, the `ANSIBLE_BECOME_METHOD` environment variable value is used |
| ``ansible_become_pass`` | no | | Specifies the password to use if required to enter privileged mode on the remote device; if ``ansible_become`` is set to no this key is not applicable |
| ``ansible_network_os`` | yes | os10, null\* | Loads the correct terminal and cliconf plugins to communicate with the remote device |
> **NOTE**: Asterisk (*) denotes the default value if none is specified.
Example playbook
----------------
This example uses the *os10_aaa* role to configure AAA for radius and TACACS servers. It creates a *hosts* file with the switch details and corresponding variables. The hosts file should define the `ansible_network_os` variable with the corresponding Dell EMC OS10 name.
When `os10_cfg_generate` is set to true, the variable generates the configuration commands as a .part file in the *build_dir* path. By default, it is set to false and it writes a simple playbook that only references the *os10_aaa* role.
**Sample hosts file**
leaf1 ansible_host= <ip_address>
**Sample host_vars/leaf1**
hostname: leaf1
ansible_become: yes
ansible_become_method: xxxxx
ansible_become_pass: xxxxx
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
build_dir: ../temp/temp_os10
os10_aaa:
radius_server:
retransmit: 5
timeout: 10
host:
- ip: 2001:4898:f0:f09b::1001
key: 0
value: "abc"
auth_port: 3
state: present
tacacs_server:
host:
- ip: 2001:4898:f0:f09b::1001
key: 0
value: "abc"
auth_port: 3
state: present
timeout: 6
aaa_authentication:
login:
- console: true
type: group radius group tacacs+ local
state: present
re_authenticate: true
aaa_accounting:
accounting:
- accounting_type: commands
connection_type: console
account_mode: start-stop
server_group: group tacacs+
state: present
**Simple playbook to setup system — leaf.yaml**
- hosts: leaf1
roles:
- dellemc.os10.os10_aaa
**Run**
ansible-playbook -i hosts leaf.yaml
(c) 2017-2020 Dell Inc. or its subsidiaries. All rights reserved.

View File

@@ -0,0 +1,16 @@
---
# defaults file for dellemc.os10.os10_aaa
attribute_type:
mandatory: mandatory
on_for_login_auth: on-for-login-auth
include_in_access_req: include-in-access-req
mac: "mac format"
mac_ietf: "mac format ietf"
mac_ietf_lower_case: "mac format ietf lower-case"
mac_ietf_upper_case: "mac format ietf upper-case"
mac_legacy: "mac format legacy"
mac_legacy_lower_case: "mac format legacy lower-case"
mac_legacy_upper_case: "mac format legacy upper-case"
mac_unformatted: "mac format unformatted"
mac_unformatted_lower_case: "mac format unformatted lower-case"
mac_unformatted_upper_case: "mac format unformatted upper-case"

View File

@@ -0,0 +1,2 @@
---
# handlers file for dellemc.os10.os10_aaa

View File

@@ -0,0 +1,17 @@
# copyright (c) 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
---
galaxy_info:
author: Dell EMC Networking Engineering
description: The os10_aaa role facilitates the configuration of Authentication Authorization Acccounting (AAA) attributes in devices running Dell EMC SmartFabric OS10.
license: GPLv3
min_ansible_version: 2.9.6
platforms:
- name: os10
galaxy_tags:
- networking
- dell
- emc
- dellemc
- os10

View File

@@ -0,0 +1,17 @@
---
# tasks file for os10
- name: "Generating AAA configuration for os10"
template:
src: os10_aaa.j2
dest: "{{ build_dir }}/aaa10_{{ hostname }}.conf.part"
when: (ansible_network_os is defined and ansible_network_os == "dellemc.os10.os10") and ((os10_cfg_generate | default('False')) | bool)
# notify: save config os10
register: generate_output
- name: "Provisioning AAA configuration for os10"
os10_config:
src: os10_aaa.j2
when: (ansible_network_os is defined and ansible_network_os == "dellemc.os10.os10")
# notify: save config os10
register: output

View File

@@ -0,0 +1,148 @@
#jinja2: trim_blocks: True,lstrip_blocks: True
{#############################################
Purpose:
Configure AAA commands for os10 Devices
os10_aaa:
radius_server:
retransmit: 5
timeout: 10
host:
- ip: 2001:4898:f0:f09b::1001
key: 0
value: "abc"
auth_port: 3
state: present
tacacs_server:
host:
- ip: 2001:4898:f0:f09b::1001
key: 0
value: "abc"
auth_port: 3
state: present
timeout: 6
aaa_authentication:
login:
- console: true
type: group radius group tacacs+ local
state: present
re_authenticate: true
aaa_accounting:
accounting:
- accounting_type: commands
connection_type: console
account_mode: start-stop
server_group: group tacacs+
state: present
##################################################}
{% if os10_aaa is defined and os10_aaa %}
{% if os10_aaa.radius_server is defined and os10_aaa.radius_server %}
{% set item = os10_aaa.radius_server %}
{% if item.retransmit is defined and item.retransmit %}
radius-server retransmit {{ item.retransmit }}
{% else %}
no radius-server retransmit
{% endif %}
{% if item.timeout is defined and item.timeout %}
radius-server timeout {{ item.timeout }}
{% else %}
no radius-server timeout
{% endif %}
{% if item.host is defined and item.host %}
{% for it in item.host %}
{% if it.ip is defined and it.ip %}
{% if it.state is defined and it.state == "absent" %}
no radius-server host {{ it.ip }}
{% else %}
{% if it.auth_port is defined and it.auth_port %}
radius-server host {{ it.ip }} auth-port {{ it.auth_port }} key {{ it.key }} {{ it.value }}
{% else %}
radius-server host {{ it.ip }} key {{ it.key }} {{ it.value }}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% if os10_aaa.tacacs_server is defined and os10_aaa.tacacs_server %}
{% set item = os10_aaa.tacacs_server %}
{% if item.timeout is defined and item.timeout %}
tacacs-server timeout {{ item.timeout }}
{% else %}
no tacacs-server timeout
{% endif %}
{% if item.host is defined and item.host %}
{% for it in item.host %}
{% if it.ip is defined and it.ip %}
{% if item.state is defined and item.state == "absent"%}
no tacacs-server host {{it.ip}}
{% else %}
{% if it.auth_port is defined and it.auth_port %}
tacacs-server host {{it.ip}} auth-port {{it.auth_port}} key {{it.key}} {{it.value}}
{% else %}
tacacs-server host {{it.ip}} key {{it.key}} {{it.value}}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% if os10_aaa.aaa_authentication is defined and os10_aaa.aaa_authentication %}
{% set aaa_list = os10_aaa.aaa_authentication %}
{% if aaa_list.login is defined and aaa_list.login %}
{% for aaa_vars in aaa_list.login %}
{% if aaa_vars.console is defined and aaa_vars.console %}
{% if aaa_vars.state is defined and aaa_vars.state == "absent"%}
no aaa authentication login console
{% else %}
{% if aaa_vars.type is defined and aaa_vars.type %}
aaa authentication login console {{aaa_vars.type}}
{% endif %}
{% endif %}
{% else %}
{% if aaa_vars.state is defined and aaa_vars.state == "absent"%}
no aaa authentication login default
{% else %}
{% if aaa_vars.type is defined and aaa_vars.type %}
aaa authentication login default {{aaa_vars.type}}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% set aaa_vars = os10_aaa.aaa_authentication %}
{% if aaa_vars.re_authenticate is defined %}
{% if aaa_vars.re_authenticate %}
aaa re-authenticate enable
{% else %}
no aaa re-authenticate enable
{% endif %}
{% endif %}
{% endif %}
{% if os10_aaa.aaa_accounting is defined and os10_aaa.aaa_accounting %}
{% set acc_list = os10_aaa.aaa_accounting %}
{% if acc_list.accounting is defined and acc_list.accounting %}
{% for aaa_vars in acc_list.accounting %}
{% if aaa_vars.accounting_type is defined and aaa_vars.accounting_type %}
{% if aaa_vars.accounting_type == "commands" %}
{% set accounting_type = aaa_vars.accounting_type + " all" %}
{% endif %}
{% if aaa_vars.connection_type is defined and aaa_vars.connection_type %}
{% if aaa_vars.state is defined and aaa_vars.state == "absent"%}
no aaa accounting {{accounting_type}} {{aaa_vars.connection_type}}
{% else %}
{% if aaa_vars.account_mode is defined and aaa_vars.account_mode == "none" %}
aaa accounting {{accounting_type}} {{aaa_vars.connection_type}} {{aaa_vars.account_mode}}
{% else %}
{% if aaa_vars.server_group is defined and aaa_vars.server_group %}
aaa accounting {{accounting_type}} {{aaa_vars.connection_type}} {{aaa_vars.account_mode}} {{aaa_vars.server_group}}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@@ -0,0 +1,22 @@
---
spine1 ansible_host=10.11.182.25 ansible_network_os="dellemc.os10.os10"
spine2 ansible_host=10.16.151.220 ansible_network_os="dellemc.os10.os10"
leaf1 ansible_host=10.11.182.23 ansible_network_os="dellemc.os10.os10"
leaf2 ansible_host=10.11.182.16 ansible_network_os="dellemc.os10.os10"
leaf3 ansible_host=10.11.182.17 ansible_network_os="dellemc.os10.os10"
leaf4 ansible_host=10.16.148.79 ansible_network_os="dellemc.os10.os10"
[spine]
spine1
spine2
[leaf]
leaf1
leaf2
leaf3
leaf4
[datacenter:children]
spine
leaf

View File

@@ -0,0 +1,35 @@
---
# vars file for dellemc.os10.os10_aaa,
# below gives a sample configuration
# Sample vars for OS10 device
os10_aaa:
radius_server:
retransmit: 5
timeout: 10
host:
- ip: 2001:4898:f0:f09b::1001
key: 0
value: "abc"
auth_port: 3
state: present
tacacs_server:
host:
- ip: 2001:4898:f0:f09b::1001
key: 0
value: "abc"
auth_port: 3
state: present
timeout: 6
aaa_authentication:
login:
- console: true
type: group radius group tacacs+ local
state: present
re_authenticate: true
aaa_accounting:
accounting:
- accounting_type: commands
connection_type: console
account_mode: start-stop
server_group: group tacacs+
state: present

View File

@@ -0,0 +1,5 @@
---
- hosts: datacenter
connection: network_cli
roles:
- dellemc.os10.os10_aaa

View File

@@ -0,0 +1 @@
# vars file for dellemc.os10.os10_aaa

View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (c) 2020, Dell Inc. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (c) 2020, Dell Inc. All rights reserved.
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -0,0 +1,130 @@
ACL role
========
This role facilitates the configuration of an access-control list (ACL). It supports the configuration of different types of ACLs (standard and extended) for both IPv4 and IPv6, and assigns the access-class to the line terminals. This role is abstracted for Dell EMC PowerSwitch platforms running Dell EMC SmartFabric OS10.
The ACL role requires an SSH connection for connectivity to a Dell EMC SmartFabric OS10 device. You can use any of the built-in OS connection variables.
Role variables
--------------
- Role is abstracted using the `ansible_network_os` variable that can take `dellemc.os10.os10` as the value
- If `os10_cfg_generate` is set to true, the variable generates the role configuration commands in a file
- Any role variable with a corresponding state variable set to absent negates the configuration of that variable
- Setting an empty value for any variable negates the corresponding configuration
- Variables and values are case-sensitive
**os10_acl keys**
| Key | Type | Description | Support |
|------------|---------------------------|---------------------------------------------------------|-----------------------|
| ``type`` | string (required): ipv4, ipv6, mac | Configures the L3 (IPv4/IPv6) or L2 (MAC) access-control list | os10 |
| ``name`` | string (required) | Configures the name of the access-control list | os10 |
| ``description`` | string | Configures the description about the access-control list | os10 |
| ``remark`` | list | Configures the ACL remark (see ``remark.*``) | os10|
| ``remark.number`` | integer (required) | Configures the remark sequence number | os10 |
| ``remark.description`` | string | Configures the remark description | os10 |
| ``remark.state`` | string: absent,present\* | Deletes the configured remark for an ACL entry if set to absent | os10 |
| ``entries`` | list | Configures ACL rules (see ``seqlist.*``) | os10 |
| ``entries.number`` | integer (required) | Specifies the sequence number of the ACL rule | os10 |
| ``entries.permit`` | boolean (required): true,false | Specifies the rule to permit packets if set to true; specifies to reject packets if set to false | os10 |
| ``entries.protocol`` | string (required) | Specifies the type of protocol or the protocol number to filter | os10 |
| ``entries.source`` | string (required) | Specifies the source address to match in the packets | os10 |
| ``entries.src_condition`` | string | Specifies the condition to filter packets from the source address; ignored if MAC | os10 |
| ``entries.destination`` | string (required) | Specifies the destination address to match in the packets | os10 |
| ``entries.dest_condition`` | string | Specifies the condition to filter packets to the destination address | os10 |
| ``entries.other_options`` | string | Specifies the other options applied on packets (count, log, order, monitor, and so on) | os10 |
| ``entries.state`` | string: absent,present\* | Deletes the rule from the ACL if set to absent | os10 |
| ``stage_ingress`` | list | Configures ingress ACL to the interface (see ``stage_ingress.*``) | os10 |
| ``stage_ingress.name`` | string (required) | Configures the ingress ACL filter to the interface with this interface name | os10 |
| ``stage_ingress.state`` | string: absent,present\* | Deletes the configured ACL from the interface if set to absent | os10 |
| ``stage_egress`` | list | Configures egress ACL to the interface (see ``stage_egress.*``) | os10 |
| ``stage_egress.name`` | string (required) | Configures the egress ACL filter to the interface with this interface name | os10 |
| ``stage_egress.state`` | string: absent,present\* | Deletes the configured egress ACL from the interface if set to absent | os10 |
| ``lineterminal`` | list | Configures the terminal to apply the ACL (see ``lineterminal.*``) | os10 |
| ``lineterminal.state`` | string: absent,present\* | Deletes the access-class from line terminal if set to absent | os10 |
| ``state`` | string: absent,present\* | Deletes the ACL if set to absent | os10 |
> **NOTE**: Asterisk (\*) denotes the default value if none is specified.
Connection variables
--------------------
Ansible Dell EMC network roles require connection information to establish communication with the nodes in inventory. This information can exist in the Ansible *group_vars* or *host_vars* directories or inventory, or in the playbook itself.
| Key | Required | Choices | Description |
|-------------|----------|------------|-------------------------------------------------------|
| ``ansible_host`` | yes | | Specifies the hostname or address for connecting to the remote device over the specified transport |
| ``ansible_port`` | no | | Specifies the port used to build the connection to the remote device; if value is unspecified, the `ANSIBLE_REMOTE_PORT` option is used; it defaults to 22 |
| ``ansible_ssh_user`` | no | | Specifies the username that authenticates the CLI login for the connection to the remote device; if value is unspecified, the `ANSIBLE_REMOTE_USER` environment variable value is used |
| ``ansible_ssh_pass`` | no | | Specifies the password that authenticates the connection to the remote device |
| ``ansible_become`` | no | yes, no\* | Instructs the module to enter privileged mode on the remote device before sending any commands; if value is unspecified, the `ANSIBLE_BECOM`E environment variable value is used, and the device attempts to execute all commands in non-privileged mode |
| ``ansible_become_method`` | no | enable, sudo\* | Instructs the module to allow the become method to be specified for handling privilege escalation; if value is unspecified, the `ANSIBLE_BECOME_METHOD` environment variable value is used |
| ``ansible_become_pass`` | no | | Specifies the password to use if required to enter privileged mode on the remote device; if ``ansible_become`` is set to no this key is not applicable |
| ``ansible_network_os`` | yes | os10, null\* | Loads the correct terminal and cliconf plugins to communicate with the remote device |
> **NOTE**: Asterisk (_*_) denotes the default value if none is specified.
Example playbook
----------------
This example uses the *os10_acl* role to configure different types of ACLs (standard and extended) for both IPv4 and IPv6 and assigns the access-class to the line terminals. The example creates a *hosts* file with the switch details and corresponding variables. The hosts file should define the `ansible_network_os` variable with the corresponding Dell EMC OS10 name.
When `os10_cfg_generate` is set to true, it generates the configuration commands as a .part file in the *build_dir* path. By default it is set to false. It writes a simple playbook that only references the *os10_acl* role.
**Sample hosts file**
leaf1 ansible_host= <ip_address>
**Sample host_vars/leaf1**
hostname: leaf1
ansible_become: yes
ansible_become_method: xxxxx
ansible_become_pass: xxxxx
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
build_dir: ../temp/temp_os10
os10_acl:
- name: ssh
type: ipv4
description: acl
remark:
- description: 1
number: 3
state: absent
entries:
- number: 14
permit: true
protocol: tcp
source: any
src_condition: neq 6
destination: any
dest_condition: eq 4
other_options: count
state: present
stage_ingress:
- name: ethernet 1/1/1
state: absent
- name: ethernet 1/1/2
state: absent
stage_egress:
- name: ethernet 1/1/3
state: absent
lineterminal:
state: absent
state: present
**Simple playbook to setup system — leaf.yaml**
- hosts: leaf1
roles:
- dellemc.os10.os10_acl
**Run**
ansible-playbook -i hosts leaf.yaml
(c) 2017-2020 Dell Inc. or its subsidiaries. All rights reserved.

View File

@@ -0,0 +1,2 @@
---
# defaults file for dellemc.os10.os10_acl

View File

@@ -0,0 +1,2 @@
---
# handlers file for dellemc.os10.os10_acl

View File

@@ -0,0 +1,17 @@
# Copyright (c) 2017-2020 Dell Inc. or its subsidiaries. All Rights Reserved.
---
galaxy_info:
author: Dell EMC Networking Engineering
description: The os10_acl role facilitates the configuration of access control list (ACL) attributes in devices running Dell EMC SmartFabric OS10.
license: GPLv3
min_ansible_version: 2.9.6
platforms:
- name: os10
galaxy_tags:
- networking
- dell
- emc
- dellemc
- os10

View File

@@ -0,0 +1,16 @@
---
# tasks file for os10
- name: "Generating ACL configuration for os10"
template:
src: os10_acl.j2
dest: "{{ build_dir }}/acl10_{{ hostname }}.conf.part"
when: (ansible_network_os is defined and ansible_network_os == "dellemc.os10.os10") and ((os10_cfg_generate | default('False')) | bool)
# notify: save config os10
register: generate_output
- name: "Provisioning ACL configuration for os10"
os10_config:
src: os10_acl.j2
when: (ansible_network_os is defined and ansible_network_os == "dellemc.os10.os10")
# notify: save config os10
register: output

View File

@@ -0,0 +1,212 @@
#jinja2: trim_blocks: True,lstrip_blocks: True
{####################################
Purpose:
Configure ACL commands for OS10 devices
os10_acl:
- name: ssh-only
type: ipv4
description: acl
remark:
- description: 1
number: 3
state: present
entries:
- number: 10
permit: true
protocol: tcp
source: any
destination: any
src_condition: eq 22
dest_condition: eq 2 ack
other_options: count
state: present
stage_ingress:
- name: ethernet 1/1/1
state: present
- name: ethernet 1/0/1
state: present
stage_egress:
- name: ethernet 1/1/2
state: present
lineterminal:
state: present
state: present
#####################################}
{% if os10_acl is defined and os10_acl %}
{% for val in os10_acl %}
{% if val.name is defined and val.name %}
{% if val.state is defined and val.state == "absent" %}
{% if val.type is defined and val.type == "ipv4" %}
no ip access-list {{ val.name }}
{% elif val.type is defined and val.type == "ipv6" %}
no ipv6 access-list {{ val.name }}
{% elif val.type is defined and val.type == "mac" %}
no mac access-list {{ val.name }}
{% endif %}
{% else %}
{% if val.type is defined and val.type == "ipv4" %}
ip access-list {{ val.name }}
{% elif val.type is defined and val.type == "ipv6" %}
ipv6 access-list {{ val.name }}
{% elif val.type is defined and val.type == "mac" %}
mac access-list {{ val.name }}
{% endif %}
{% if val.description is defined %}
{% if val.description %}
description "{{ val.description }}"
{% endif %}
{% endif %}
{% if val.remark is defined and val.remark %}
{% for remark in val.remark %}
{% if remark.description is defined and remark.description %}
{% if remark.number is defined and remark.number %}
{% if remark.state is defined and remark.state == "absent" %}
no seq {{ remark.number }}
{% else %}
seq {{ remark.number }} remark "{{ remark.description }}"
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if val.entries is defined and val.entries %}
{% for rule in val.entries %}
{% if rule.number is defined and rule.number %}
{% if rule.state is defined and rule.state == "absent" %}
no seq {{ rule.number }}
{% else %}
{% if rule.permit is defined %}
{% if rule.permit %}
{% set is_permit = "permit" %}
{% else %}
{% set is_permit = "deny" %}
{% endif %}
{% endif %}
{% if val.type is defined and val.type %}
{% if rule.protocol is defined and rule.protocol %}
{% if rule.source is defined and rule.source %}
{% if rule.src_condition is defined and rule.src_condition %}
{% if rule.destination is defined and rule.destination %}
{% if rule.dest_condition is defined and rule.dest_condition %}
{% if rule.other_options is defined and rule.other_options %}
{% set other_options = rule.other_options %}
seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.src_condition }} {{ rule.destination }} {{ rule.dest_condition }} {{ other_options }}
{% else %}
seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.src_condition }} {{ rule.destination }} {{ rule.dest_condition }}
{% endif %}
{% else %}
{% if rule.other_options is defined and rule.other_options %}
{% set other_options = rule.other_options %}
seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.src_condition }} {{ rule.destination }} {{ other_options }}
{% else %}
seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.src_condition }} {{ rule.destination }}
{% endif %}
{% endif %}
{% endif %}
{% else %}
{% if rule.destination is defined and rule.destination %}
{% if rule.dest_condition is defined and rule.dest_condition %}
{% if rule.other_options is defined and rule.other_options %}
{% set other_options = rule.other_options %}
seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.destination }} {{ rule.dest_condition }} {{ other_options }}
{% else %}
seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.destination }} {{ rule.dest_condition }}
{% endif %}
{% else %}
{% if rule.other_options is defined and rule.other_options %}
{% set other_options = rule.other_options %}
seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.destination }} {{ other_options }}
{% else %}
seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.destination }}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if val.lineterminal is defined and val.lineterminal %}
{% if val.type is defined and not val.type == "mac" %}
line vty
{% if val.lineterminal.state is defined and val.lineterminal.state == "absent" %}
{% if val.type == "ipv6" %}
no ipv6 access-class {{ val.name }}
{% elif val.type == "ipv4" %}
no ip access-class {{ val.name }}
{% endif %}
{% else %}
{% if val.type == "ipv6" %}
ipv6 access-class {{ val.name }}
{% elif val.type == "ipv4" %}
ip access-class {{ val.name }}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% if val.stage_ingress is defined and val.stage_ingress %}
{% for intf in val.stage_ingress %}
{% if intf.state is defined and intf.state == "absent" %}
{% if intf.name is defined and intf.name %}
interface {{ intf.name }}
{% if val.type is defined and val.type == "mac" %}
no mac access-group {{ val.name }} in
{% elif val.type is defined and val.type == "ipv6" %}
no ipv6 access-group {{ val.name }} in
{% else %}
no ip access-group {{ val.name }} in
{% endif %}
{% endif %}
{% else %}
{% if intf.name is defined and intf.name %}
interface {{ intf.name }}
{% if val.type is defined and val.type == "mac" %}
mac access-group {{ val.name }} in
{% elif val.type is defined and val.type == "ipv6" %}
ipv6 access-group {{ val.name }} in
{% else %}
ip access-group {{ val.name }} in
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if val.stage_egress is defined and val.stage_egress %}
{% for intf in val.stage_egress %}
{% if intf.state is defined and intf.state == "absent" %}
{% if intf.name is defined and intf.name %}
interface {{ intf.name }}
{% if val.type is defined and val.type == "mac" %}
no mac access-group {{ val.name }} out
{% elif val.type is defined and val.type == "ipv6" %}
no ipv6 access-group {{ val.name }} out
{% else %}
no ip access-group {{ val.name }} out
{% endif %}
{% endif %}
{% else %}
{% if intf.name is defined and intf.name %}
interface {{ intf.name }}
{% if val.type is defined and val.type == "mac" %}
mac access-group {{ val.name }} out
{% elif val.type is defined and val.type == "ipv6" %}
ipv6 access-group {{ val.name }} out
{% else %}
ip access-group {{ val.name }} out
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}

View File

@@ -0,0 +1,22 @@
---
spine1 ansible_host=10.11.182.25 ansible_network_os="dellemc.os10.os10"
spine2 ansible_host=10.16.151.220 ansible_network_os="dellemc.os10.os10"
leaf1 ansible_host=10.11.182.23 ansible_network_os="dellemc.os10.os10"
leaf2 ansible_host=10.11.182.16 ansible_network_os="dellemc.os10.os10"
leaf3 ansible_host=10.11.182.17 ansible_network_os="dellemc.os10.os10"
leaf4 ansible_host=10.16.148.79 ansible_network_os="dellemc.os10.os10"
[spine]
spine1
spine2
[leaf]
leaf1
leaf2
leaf3
leaf4
[datacenter:children]
spine
leaf

View File

@@ -0,0 +1,33 @@
---
# vars file for dellemc.os10.os10_acl,
# below gives a sample configuration
# Sample variables for OS10 device
os10_acl:
- name: ssh
type: ipv4
description: acl
remark:
- description: 1
number: 3
state: absent
entries:
- number: 14
permit: true
protocol: tcp
source: any
src_condition: neq 6
destination: any
dest_condition: eq 4
other_options: count
state: present
stage_ingress:
- name: ethernet 1/1/1
state: absent
- name: ethernet 1/1/2
state: absent
stage_egress:
- name: ethernet 1/1/3
state: absent
lineterminal:
state: absent
state: present

View File

@@ -0,0 +1,5 @@
---
- hosts: datacenter
connection: network_cli
roles:
- dellemc.os10.os10_acl

View File

@@ -0,0 +1,2 @@
---
# vars file for dellemc.os10.os10_acl

View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (c) 2020, Dell Inc. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (c) 2020, Dell Inc. All rights reserved.
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -0,0 +1,89 @@
BFD role
===========
This role facilitates the configuration of bidirectional forwarding detection (BFD) global attributes. It specifically enables configuration of BFD interval, min_rx, multiplier, and role. This role is abstracted for Dell EMC PowerSwitch platforms running Dell EMC SmartFabric OS10.
The BFD role requires an SSH connection for connectivity to a Dell EMC SmartFabric OS10 device. You can use any of the built-in OS connection variables.
Role variables
--------------
- Role is abstracted using the `ansible_network_os` variable that can take `dellemc.os10.os10` as the value
- If `os10_cfg_generate` is set to true, the variable generates the role configuration commands in a file
- Any role variable with a corresponding state variable set to absent negates the configuration of that variable
- Setting an empty value for any variable negates the corresponding configuration
- Variables and values are case-sensitive
**os10_bfd keys**
| Key | Type | Description | Support |
|------------|---------------------------|---------------------------------------------------------|-----------------------|
| ``bfd`` | dictionary | Configures global BFD parameters (see ``bfd.*``) | os10 |
| ``bfd.interval`` | integer | Configures the time interval in ms (100 to 1000) | os10 |
| ``bfd.min_rx`` | integer | Configures maximum waiting time for receiving control packets from BFD peers in ms (100 to 1000)| os10 |
| ``bfd.multiplier`` | integer | Configures the maximum number of consecutive packets that are not received from BFD peers before session state changes to Down (3 to 50) | os10 |
| ``bfd.role`` | string: passive,active\* | Configures the BFD role | os10 |
| ``bfd.state`` | string: absent,present\* | Removes the global BFD if set to absent | os10 |
> **NOTE**: Asterisk (\*) denotes the default value if none is specified.
Connection variables
********************
Ansible Dell EMC network roles require connection information to establish communication with the nodes in your inventory. This information can exist in the Ansible *group_vars* or *host_vars* directories, or inventory or in the playbook itself.
| Key | Required | Choices | Description |
|-------------|----------|------------|-----------------------------------------------------|
| ``ansible_host`` | yes | | Specifies the hostname or address for connecting to the remote device over the specified transport |
| ``ansible_port`` | no | | Specifies the port used to build the connection to the remote device; if value is unspecified, the `ANSIBLE_REMOTE_PORT` option is used; it defaults to 22 |
| ``ansible_ssh_user`` | no | | Specifies the username that authenticates the CLI login for the connection to the remote device; if value is unspecified, the `ANSIBLE_REMOTE_USER` environment variable value is used |
| ``ansible_ssh_pass`` | no | | Specifies the password that authenticates the connection to the remote device |
| ``ansible_become`` | no | yes, no\* | Instructs the module to enter privileged mode on the remote device before sending any commands; if value is unspecified, the `ANSIBLE_BECOME` environment variable value is used, and the device attempts to execute all commands in non-privileged mode |
| ``ansible_become_method`` | no | enable, sudo\* | Instructs the module to allow the become method to be specified for handling privilege escalation; if value is unspecified, the `ANSIBLE_BECOME_METHOD` environment variable value is used |
| ``ansible_become_pass`` | no | | Specifies the password to use if required to enter privileged mode on the remote device; if ``ansible_become`` is set to no this key is not applicable |
| ``ansible_network_os`` | yes | os10, null\* | Loads the correct terminal and cliconf plugins to communicate with the remote device |
> **NOTE**: Asterisk (\*) denotes the default value if none is specified.
Example playbook
----------------
This example uses the *os10_bfd role* to completely set the global BFD attributes. It creates a *hosts* file with the switch details and corresponding variables. The hosts file should define the `ansible_network_os` variable with corresponding Dell EMC OS10 name.
When `os10_cfg_generate` is set to true, the variable generates the configuration commands as a .part file in *build_dir* path. By default, the variable is set to false. The bfd role writes a simple playbook that only references the *os10_bfd* role. By including the role, you automatically get access to all of the tasks to configure BFD feature.
**Sample hosts file**
leaf1 ansible_host= <ip_address>
**Sample host_vars/leaf1**
hostname: leaf1
ansible_become: yes
ansible_become_method: xxxxx
ansible_become_pass: xxxxx
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
build_dir: ../temp/os10
os10_bfd:
bfd:
interval: 100
min_rx: 100
multiplier: 3
role: "active"
state: "present"
**Simple playbook to setup bfd — leaf.yaml**
- hosts: leaf1
roles:
- dellemc.os10.os10_bfd
**Run**
ansible-playbook -i hosts leaf.yaml
(c) 2017-2020 Dell Inc. or its subsidiaries. All rights reserved.

View File

@@ -0,0 +1,2 @@
---
# defaults file for dellemc.os10.os10_bfd

View File

@@ -0,0 +1,2 @@
---
# handlers file for dellemc.os10.os10_bfd

View File

@@ -0,0 +1,18 @@
# Copyright (c) 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
---
galaxy_info:
role_name: os10_bfd
author: Dell EMC Networking Engineering
description: The os10_bfd role facilitates the configuration of global bfd attributes in devices running Dell EMC SmartFabric OS10.
license: GPLv3
min_ansible_version: 2.9.6
platforms:
- name: os10
galaxy_tags:
- networking
- dell
- emc
- dellemc
- os10

View File

@@ -0,0 +1,16 @@
---
# tasks file for os10
- name: "Generating bfd global configuration for os10"
template:
src: os10_bfd.j2
dest: "{{ build_dir }}/bfd10_{{ hostname }}.conf.part"
when: (ansible_network_os is defined and ansible_network_os == "dellemc.os10.os10") and ((os10_cfg_generate | default('False')) | bool)
# notify: save config os10
register: generate_output
- name: "Provisioning bfd global configuration for os10"
os10_config:
src: os10_bfd.j2
when: (ansible_network_os is defined and ansible_network_os == "dellemc.os10.os10")
# notify: save config os10
register: output

View File

@@ -0,0 +1,34 @@
#jinja2: trim_blocks: True,lstrip_blocks: True
{#############################################
#Purpose:
Configure bfd global commands for os10 Devices
os10_bfd:
bfd:
interval: 200
min_rx: 200
multiplier: 3
role: "active"
state: "present"
###############################################}
{% if os10_bfd is defined and os10_bfd %}
{% set bfd_vars = os10_bfd %}
{% if bfd_vars.bfd is defined and bfd_vars.bfd %}
{% set bfd = bfd_vars.bfd %}
{% if bfd.state is defined and bfd.state == "absent" %}
no bfd enable
no bfd interval
{% else %}
bfd enable
{% if bfd.interval is defined and bfd.min_rx is defined and bfd.multiplier is defined %}
{% if bfd.interval and bfd.min_rx and bfd.multiplier %}
{% if bfd.role is defined and bfd.role %}
bfd interval {{ bfd.interval }} min_rx {{ bfd.min_rx }} multiplier {{ bfd.multiplier }} role {{ bfd.role }}
{% else %}
bfd interval {{ bfd.interval }} min_rx {{ bfd.min_rx }} multiplier {{ bfd.multiplier }}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}

View File

@@ -0,0 +1,22 @@
---
spine1 ansible_host=10.11.182.25 ansible_network_os="dellemc.os10.os10"
spine2 ansible_host=10.16.151.220 ansible_network_os="dellemc.os10.os10"
leaf1 ansible_host=10.11.182.23 ansible_network_os="dellemc.os10.os10"
leaf2 ansible_host=10.11.182.16 ansible_network_os="dellemc.os10.os10"
leaf3 ansible_host=10.11.182.17 ansible_network_os="dellemc.os10.os10"
leaf4 ansible_host=10.16.148.79 ansible_network_os="dellemc.os10.os10"
[spine]
spine1
spine2
[leaf]
leaf1
leaf2
leaf3
leaf4
[datacenter:children]
spine
leaf

View File

@@ -0,0 +1,11 @@
---
# vars file for dellemc.os10.os10_bfd,
# below gives a sample configuration
# Sample variables for OS10 device
os10_bfd:
bfd:
interval: 100
min_rx: 100
multiplier: 3
role: "active"
state: "present"

View File

@@ -0,0 +1,5 @@
---
- hosts: datacenter
connection: network_cli
roles:
- dellemc.os10.os10_bfd

View File

@@ -0,0 +1,2 @@
---
# vars file for dellemc.os10.os10_bfd

View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (c) 2020, Dell Inc. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (c) 2020, Dell Inc. All rights reserved.
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@@ -0,0 +1,729 @@
BGP role
========
This role facilitates the configuration of border gateway protocol (BGP) attributes. It supports the configuration of router ID, networks, neighbors, and maximum paths. This role is abstracted for Dell EMC PowerSwitch platforms running SmartFabric OS10.
The BGP role requires an SSH connection for connectivity to a Dell EMC SmartFabric OS10 device. You can use any of the built-in OS connection variables.
Role variables
--------------
- Role is abstracted using the `ansible_network_os` variable that can take `dellemc.os10.os10` as the value
- If `os10_cfg_generate` is set to true, it generates the role configuration commands in a file
- Any role variable with a corresponding state variable setting to absent negates the configuration of that variable
- Setting an empty value for any variable negates the corresponding configuration
- Variables and values are case-sensitive
**os10_bgp keys**
| Key | Type | Description | Support |
|------------|---------------------------|---------------------------------------------------------|-----------------------|
| ``asn`` | string (required) | Configures the autonomous system (AS) number of the local BGP instance | os10 |
| ``router_id`` | string | Configures the IP address of the local BGP router instance | os10 |
| ``graceful_restart`` | boolean | Configures graceful restart capability | os10 |
| ``maxpath_ibgp`` | integer | Configures the maximum number of paths to forward packets through iBGP (1 to 64; default 1) | os10 |
| ``maxpath_ebgp`` | integer | Configures the maximum number of paths to forward packets through eBGP (1 to 64; default 1) | os10 |
| ``log_neighbor_changes`` | boolean | Configures log neighbors up/down | os10 |
| ``fast_ext_fallover`` | boolean | Configures a reset session if a link to a directly connected external peer goes down | os10 |
| ``always_compare_med`` | boolean | Configures comparing MED from different neighbors | os10 |
| ``default_loc_pref`` | integer | Configures the default local preference value | os10 |
| ``as_notation`` | string | Configures AS number notation format | os10 |
| ``enforce_first_as`` | boolean | Configures the first AS for eBGP routes | os10 |
| ``non_deterministic_med`` | boolean | Configures nondeterministic path selection algorithm | os10 |
| ``outbound_optimization`` | boolean | Configures outbound optimization for iBGP peer-group members | os10 |
| ``confederation`` | dictionary | Configures AS confederation parameters (see ``confederation.*``) | os10 |
| ``confederation.identifier`` | integer | Configures the routing domain confederation AS | os10 |
| ``confederation.peers`` | string | Configures the peer AS in BGP confederation | os10 |
| ``confederation.peers_state`` | string: absent,present\* | Deletes the peer AS in BGP confederation if set to absent | os10 |
| ``route_reflector`` | dictionary | Configures route reflection parameters (see ``route_reflector.*``) | os10 |
| ``route_reflector.client_to_client`` | boolean | Configures client-to-client route reflection | os10 |
| ``route_reflector.cluster_id`` | string | Configures the route reflector cluster-id | os10 |
| ``address_family_ipv4`` | dictionary | Configures IPv4 address family parameters (see ``address_family_ipv4.*``) | os10 |
| ``address_family_ipv4.aggregate_addr`` | list | Configures IPv4 BGP aggregate entries (see ``aggregate_addr.*``) | os10 |
| ``aggregate_addr.ip_and_mask`` | string | Configures the IPv4 BGP aggregate address | os10 |
| ``aggregate_addr.adv_map`` | string | Configures the advertise map for IPv4 BGP aggregate address | os10 |
| ``aggregate_addr.attr_map`` | string | Configures the attribute map for IPv4 BGP aggregate address | os10 |
| ``aggregate_addr.suppress_map`` | string | Configures the suppress map for IPv4 BGP aggregate address | os10 |
| ``aggregate_addr.summary_only`` | boolean | Sets address to summary only if true | os10 |
| ``aggregate_addr.state`` | string: absent,present\* | Deletes an IPv4 BGP aggregate entry if set to absent | os10 |
| ``address_family_ipv4.dampening`` | dictionary | Configures route-flap dampening (see ``dampening.*``) | os10 |
| ``dampening.value`` | dictionary | Configures dampening values (<half-life time> <start value to reuse> <start value to suppress> <max duration> format; default 15 750 2000 60) | os10 |
| ``dampening.route_map`` | string | Configures the route-map to specify criteria for dampening | os10 |
| ``dampening.state`` | string: absent,present\* | Deletes dampening if set to absent | os10 |
| ``address_family_ipv4.ibgp_redist_internal`` | dictionary | Configures internal BGP reditribution (see ``ibgp_redist_internal.*``) | os10 |
| ``ibgp_redist_internal.state`` | boolean | Configures the internal BGP redistribution for an IPv4 address family | os10 |
| ``address_family_ipv4.default_metric`` | integer | Configures the metric of redistributed routes for IPv4 address family | os10 |
| ``address_family_ipv4.distance_bgp`` | dictionary | Configures BGP distances (see ``distance_bgp.*``) | os10 |
| ``distance_bgp.value`` | dictionary | Configures the BGP administrative distance for IPv4 address family (<routes external to AS> <routes internal to AS> <local routes> format; distance bgp 2 3 4) | os10 |
| ``distance_bgp.state`` | string: absent,present\* | Deletes distance BGP if set to absent | os10 |
| ``address_family_ipv6`` | dictionary | Configures IPv6 address family parameters (see ``address_family_ipv6.*``) | os10 |
| ``address_family_ipv6.aggregate_addr`` | list | Configures IPv6 BGP aggregate entries (see ``aggregate_addr.*``) | os10 |
| ``aggregate_addr.ip_and_mask`` | string | Configures the IPv6 BGP aggregate address | os10 |
| ``aggregate_addr.adv_map`` | string | Configures the advertise map for IPv6 BGP aggregate address | os10 |
| ``aggregate_addr.attr_map`` | string | Configures the attribute map for IPv6 BGP aggregate address | os10 |
| ``aggregate_addr.suppress_map`` | string | Configures the suppress map for IPv6 BGP aggregate address | os10 |
| ``aggregate_addr.summary_only`` | boolean | Sets address to summary-only if true | os10 |
| ``aggregate_addr.state`` | string: absent,present\* | Deletes an IPv6 BGP aggregate entry if set to absent | os10 |
| ``address_family_ipv6.dampening`` | dictionary | Configures route-flap dampening (see ``dampening.*``) | os10 |
| ``dampening.value`` | dictionary | Configures dampening values (<half-life time> <start value to reuse> <start value to suppress> <max duration> format; default 15 750 2000 60) | os10 |
| ``dampening.route_map`` | string | Configures the route-map to specify criteria for dampening | os10 |
| ``dampening.state`` | string: absent,present\* | Deletes dampening if set to absent | os10 |
| ``address_family_ipv6.ibgp_redist_internal`` | dictionary | Configures iBGP reditribution (see ``ibgp_redist_internal.*``) | os10 |
| ``ibgp_redist_internal.state`` | boolean | Configures the iBGP redistribution for an IPv6 address family | os10 |
| ``address_family_ipv6.default_metric`` | integer | Configures the metric of redistributed routes for IPv6 address family | os10 |
| ``address_family_ipv6.distance_bgp`` | dictionary | Configures BGP distances (see ``distance_bgp.*``) | os10 |
| ``distance_bgp.value`` | dictionary | Configures the BGP administrative distance for an IPv6 address family (<routes external to AS> <routes internal to AS> <local routes> format; distance bgp 2 3 4) | os10 |
| ``distance_bgp.state`` | string: absent,present\* | Deletes distance BGP if set to absent | os10 |
| ``best_path`` | list | Configures the default best-path selection (see ``best_path.*``) | os10 |
| ``best_path.as_path`` | string (required): ignore,multipath-relax | Configures the AS path used for the best-path computation | os10 |
| ``best_path.as_path_state`` | string: absent,present\* | Deletes the AS path configuration if set to absent | os10 |
| ``best_path.ignore_router_id`` | boolean: true,false | Ignores the router identifier in best-path computation if set to true | os10 |
| ``best_path.med`` | list | Configures the MED attribute (see ``med.*``) | os10 |
| ``med.attribute`` | string (required): confed,missing-as-best | Configures the MED attribute used for the best-path computation | os10 |
| ``med.state`` | string: absent,present\* | Deletes the MED attribute if set to absent | os10 |
| ``ipv4_network`` | list | Configures an IPv4 BGP networks (see ``ipv4_network.*``) | os10 |
| ``ipv4_network.address`` | string (required) | Configures the IPv4 address of the BGP network (A.B.C.D/E format) | os10 |
| ``ipv4_network.state`` | string: absent,present\* | Deletes an IPv4 BGP network if set to absent | os10 |
| ``ipv6_network`` | list | Configures an IPv6 BGP network (see ``ipv6_network.*``) | os10 |
| ``ipv6_network.address`` | string (required) | Configures the IPv6 address of the BGP network (2001:4898:5808:ffa2::1/126 format) | os10 |
| ``ipv6_network.state`` | string: absent,present\* | Deletes an IPv6 BGP network if set to absent | os10 |
| ``neighbor`` | list | Configures IPv4 BGP neighbors (see ``neighbor.*``) | os10 |
| ``neighbor.ip`` | string (required) | Configures the IPv4 address of the BGP neighbor (10.1.1.1) | os10 |
| ``neighbor.interface`` | string | Configures the BGP neighbor interface details | os10 |
| ``neighbor.name`` | string (required) | Configures the BGP peer-group with this name; supported only when the neighbor is a peer group; mutually exclusive with *neighbor.ip* | os10 |
| ``neighbor.type`` | string (required): ipv4,ipv6,peergroup | Specifies the BGP neighbor type | os10 |
| ``neighbor.auto_peer`` |string: unnumbered-auto | Enables auto discovery of neighbors | os10 |
| ``neighbor.password`` | string | Configures the BGP neighbor password | os10 |
| ``neighbor.peergroup_type`` | string (ibgp, ebgp) | Configures the BGP neighbor peer-group type| os10 |
| ``neighbor.ebgp_peergroup`` | string | Configures the peer-group to all auto-discovered external neighbors | os10 |
| ``neighbor.ebgp_peergroup_state`` | string: present,absent | Removes the peer-group from all auto-discovered external neighbors | os10 |
| ``neighbor.ibgp_peergroup`` | string | Configures the peer-group to all auto-discovered internal neighbors | os10 |
| ``neighbor.ibgp_peergroup_state`` | string: present,absent | Removes the peer-group from all auto-discovered internal neighbors | os10 |
| ``neighbor.route_reflector_client`` | boolean | Configures router reflector client on the BGP neighbor | os10 |
| ``neighbor.local_as`` | integer | Configures the local AS for the BGP peer | os10 |
| ``neighbor.weight`` | integer | Configures the default weight for routes from the neighbor interface | os10 |
| ``neighbor.send_community`` | list | Configures the send community attribute to the BGP neighbor (see ``send_community.*``) | os10 |
| ``send_community.type`` | string (required) | Configures the send community attribute to the BGP neighbor | os10 |
| ``send_community.state`` | string: absent,present\* | Deletes the send community attribute of the BGP neighbor if set to absent | os10 |
| ``neighbor.address_family`` | list | Configures address family commands on the BGP neighbor (see ``address_family.*``)| os10 |
| ``address_family.type`` | string (required): ipv4,ipv6,l2vpn | Configures IPv4/IPv6/EVPN address family command mode on the BGP neighbor | os10 |
| ``address_family.activate`` | boolean | Configures activation/deactivation of IPv4/IPv6 address family command mode on the BGP neighbor | os10 |
| ``address_family.sender_loop_detect`` | boolean | Enables/disables the sender-side loop detection process for a BGP neighbor of IPv4/IPv6/l2vpn address family | os10 |
| ``address_family.allow_as_in`` | integer | Configures the local AS number in the as-path | os10 |
| ``address_family.next_hop_self`` | boolean | Configures disabling the next-hop calculation for the neighbor | os10 |
| ``address_family.soft_reconf`` | boolean | Configures per neighbor soft reconfiguration | os10 |
| ``address_family.add_path`` | string | Configures send or receive multiple paths (value can be 'both <no of paths>', 'send <no of paths>', 'receive')| os10 |
| ``address_family.route_map`` | list | Configures the route-map on the BGP neighbor (see ``route_map.*``) | os10 |
| ``route_map.name`` | string | Configures the name of the route-map for the BGP neighbor | os10 |
| ``route_map.filter`` | string | Configures the filter for routing updates | os10 |
| ``route_map.state`` | string, choices: absent,present\* | Deletes the route-map of the BGP neighbor if set to absent | os10 |
| ``address_family.max_prefix`` | dictionary | Configures maximum-prefix parameters (see ``max_prefix.\*``) | os10 |
| ``max_prefix.count`` | integer | Configures maximum number of prefix accepted from the peer | os10 |
| ``max_prefix.state`` | string: absent,present | Deletes maximum prefix configured for the peer | os10 |
| ``max_prefix.threshold`` | integer | Configures threshold percentage at which warning log is thrown | os10 |
| ``max_prefix.warning``| boolean | Configures a warning without dropping the session when maximum limit exceeds if set to true | os10|
| ``address_family.default_originate`` | dictionary | Configures default-originate parameters (see ``default_originate.\*``) | os10 |
| ``default_originate.route_map`` | string | Configures the name of the route-map to specify criteria to originate default | os10 |
| ``default_originate.state`` | string, choices: absent,present\* | Deletes the default-originate if set to absent | os10 |
| ``address_family.distribute_list`` | list | Configures the distribute list to filter networks from routing updates (see ``distribute_list.*``) | os10 |
| ``distribute_list.in`` | string | Configures the name of the prefix-list to filter incoming packets | os10 |
| ``distribute_list.in_state`` | string: absent,present\* | Deletes the filter at incoming packets if set to absent | os10 |
| ``distribute_list.out`` | string | Configures the name of the prefix-list to filter outgoing packets | os10 |
| ``distribute_list.out_state`` | string: absent,present\* | Deletes the filter at outgoing packets if set to absent | os10 |
| ``address_family.state`` | string: absent,present\* | Deletes the address family command mode of the BGP neighbor if set to absent | os10 |
| ``neighbor.remote_asn`` | string (required) | Configures the remote AS number of the BGP neighbor | os10 |
| ``neighbor.remote_asn_state`` | string: absent,present\* | Deletes the remote AS number from the peer group if set to absent; supported only when *neighbor.type* is "peergroup" | os10 |
| ``neighbor.timer`` | string | Configures neighbor timers; 5 10, where 5 is the keepalive interval and 10 is the holdtime | os10 |
| ``neighbor.peergroup`` | string | Configures neighbor to BGP peer-group (configured peer-group name) | os10 |
| ``neighbor.peergroup_state`` | string: absent,present\* | Deletes the IPv4 BGP neighbor from the peer-group if set to absent | os10 |
| ``neighbor.distribute_list`` | list | Configures the distribute list to filter networks from routing updates (see ``distribute_list.*``) | os10 |
| ``distribute_list.in`` | string | Configures the name of the prefix-list to filter incoming packets | os10 |
| ``distribute_list.in_state`` | string: absent,present\* | Deletes the filter at incoming packets if set to absent | os10 |
| ``distribute_list.out`` | string | Configures the name of the prefix-list to filter outgoing packets | os10 |
| ``distribute_list.out_state`` | string: absent,present\* | Deletes the filter at outgoing packets if set to absent | os10 |
| ``neighbor.admin`` | string: up,down | Configures the administrative state of the neighbor | os10 |
| ``neighbor.adv_interval`` | integer | Configures the advertisement interval of the neighbor | os10 |
| ``neighbor.adv_start`` | integer | Set the advertisement start of the neighbor | os10 |
| ``neighbor.adv_start_state`` | string: absent,present\* | Configures or unconfigures the advertisement start of a neighbor | os10 |
| ``neighbor.conn_retry_timer`` | integer | Configures the peer connection retry timer | os10 |
| ``neighbor.remove_pri_as`` | string: absent,present | Configures the remove private AS number from outbound updates | os10 |
| ``neighbor.fall_over`` | string: absent,present | Configures the session fall on peer-route loss | os10 |
| ``neighbor.sender_loop_detect`` | boolean: true,false | Enables or disables the sender-side loop detect for neighbors | os10 |
| ``neighbor.src_loopback`` | integer | Configures the source loopback interface for routing packets | os10 |
| ``neighbor.ebgp_multihop`` | integer | Configures the maximum-hop count value allowed in eBGP neighbors that are not directly connected (default 255) | os10 |
| ``neighbor.listen`` | list | Configures listen commands on the BGP template (see ``listen.*``)| os10 |
| ``listen.subnet`` | string (required) | Configures the passive BGP neighbor IPv4/IPv6 to this subnet | os10 |
| ``listen.subnet_state`` | string: absent,present\* | Deletes the subnet range set for dynamic IPv4/IPv6 BGP neighbor if set to absent | os10 |
| ``listen.limit`` | integer | Configures maximum dynamic peers count (key is required together with ``neighbor.subnet``) | os10 |
| ``neighbor.bfd`` | boolean | Enables BFD for neighbor | os10 |
| ``neighbor.description`` | string | Configures neighbor description | os10 |
| ``neighbor.state`` | string: absent,present\* | Deletes the IPv4 BGP neighbor if set to absent | os10 |
| ``redistribute`` | list | Configures the redistribute list to get information from other routing protocols (see ``redistribute.*``) | os10 |
| ``redistribute.route_type`` | string (required): static,connected,imported_bgp,l2vpn,ospf | Configures the name of the routing protocol to redistribute | os10 |
| ``redistribute.route_map_name`` | string | Configures the route-map to redistribute | os10 |
| ``redistribute.imported_bgp_vrf_name`` | string | Configures the redistribute imported BGP VRF name | os10 |
| ``redistribute.ospf_id`` | string | Configures the redistribute OSPF | os10 |
| ``redistribute.address_type`` | string (required): ipv4,ipv6 | Configures the address type of IPv4 or IPv6 routes | os10 |
| ``redistribute.state`` | string: absent,present\* | Deletes the redistribution information if set to absent | os10 |
| ``bfd_all_neighbors`` | dictionary | Enables BFD for all BGP neighbors | os10 |
| ``bfd_all_neighbors.interval`` | integer: 100 to 1000 | Configures time interval for sending control packets to BFD peers in ms| os10 |
| ``bfd_all_neighbors.min_rx`` | integer: 100 to 1000 | Configures maximum waiting time for receiving control packets from BFD peers in ms| os10 |
| ``bfd_all_neighbors.multiplier`` | integer: 3 to 50 | Configures maximum number of consecutive packets that are not received from BFD peers before session state changes to Down| os10 |
| ``bfd_all_neighbors.role``| string: active, passive | Configures BFD role | os10 |
| ``bfd_all_neighbors.state`` |string: absent,present\* | Deletes BFD for all neighbors if set to absent | os10 |
| ``vrfs`` | list | Enables VRF under BGP | os10 |
| ``vrf.name`` | string (Required)| Configures VRF name | os10 |
| ``vrf.router_id`` | string | Configures the IP address of the local BGP router instance in VRF | os10 |
| ``vrf.graceful_restart`` | boolean | Configures graceful restart capability in VRF | os10 |
| ``vrf.maxpath_ibgp`` | integer | Configures the maximum number of paths to forward packets through iBGP (1 to 64; default 1) in VRF | os10 |
| ``vrf.maxpath_ebgp`` | integer | Configures the maximum number of paths to forward packets through eBGP (1 to 64; default 1) in VRF | os10 |
| ``vrf.log_neighbor_changes`` | boolean | Configures log neighbors up/down in VRF | os10 |
| ``vrf.fast_ext_fallover`` | boolean | Configures a reset session if a link to a directly connected external peer goes down in VRF | os10 |
| ``vrf.always_compare_med`` | boolean | Configures comparing MED from different neighbors in VRF | os10 |
| ``vrf.default_loc_pref`` | integer | Configures the default local preference value in VRF | os10 |
| ``vrf.as_notation`` | string | Changes the AS number notation format in VRF | os10 |
| ``vrf.enforce_first_as`` | boolean | Configures the first AS for eBGP routes in VRF | os10 |
| ``vrf.non_deterministic_med`` | boolean | Configures nondeterministic path selection algorithm in VRF | os10 |
| ``vrf.outbound_optimization`` | boolean | Configures outbound optimization for iBGP peer-group members in VRF | os10 |
| ``vrf.route_reflector`` | dictionary | Configures route reflection parameters (see ``route_reflector.*``) in VRF | os10 |
| ``vrf.route_reflector.client_to_client`` | boolean | Configures client-to-client route reflection in VRF | os10 |
| ``vrf.route_reflector.cluster_id`` | string | Configures the route-reflector cluster-id in VRF | os10 |
| ``vrf.address_family_ipv4`` | dictionary | Configures IPv4 address family parameters in VRF (see ``address_family_ipv4.*``) in VRF | os10 |
| ``address_family_ipv4.aggregate_addr`` | list | Configures IPv4 BGP aggregate entries (see ``aggregate_addr.*``) in VRF | os10 |
| ``aggregate_addr.ip_and_mask`` | string | Configures the IPv4 BGP aggregate address in VRF | os10 |
| ``aggregate_addr.adv_map`` | string | Configures the advertise map for IPv4 BGP aggregate address | os10 |
| ``aggregate_addr.attr_map`` | string | Configures the attribute map for IPv4 BGP aggregate address | os10 |
| ``aggregate_addr.suppress_map`` | string | Configures the suppress map for IPv4 BGP aggregate address | os10 |
| ``aggregate_addr.summary_only`` | boolean | Sets address to summary-only if true in VRF | os10 |
| ``aggregate_addr.state`` | string: absent,present\* | Deletes an IPv4 BGP aggregate entry if set to absent in VRF | os10 |
| ``address_family_ipv4.dampening`` | dictionary | Configures route-flap dampening (see ``dampening.*``) | os10 |
| ``dampening.value`` | dictionary | Configures dampening values (<half-life time> <start value to reuse> <start value to suppress> <max duration> format; default 15 750 2000 60) | os10 |
| ``dampening.route_map`` | string | Configures the route-map to specify criteria for dampening | os10 |
| ``dampening.state`` | string: absent,present\* | Deletes dampening if set to absent | os10 |
| ``address_family_ipv4.ibgp_redist_internal`` | dictionary | Configures iBGP reditribution (see ``ibgp_redist_internal.*``) | os10 |
| ``ibgp_redist_internal.state`` | boolean | Configures the iBGP redistribution for a IPV4 address family | os10 |
| ``address_family_ipv4.default_metric`` | integer | Configures the metric of redistributed routes for IPV4 address family | os10 |
| ``address_family_ipv4.distance_bgp`` | dictionary | Configures BGP distances (see ``distance_bgp.*``) | os10 |
| ``distance_bgp.value`` | dictionary | Configures the BGP administrative distance for IPV4 address family (<routes external to AS> <routes internal to AS> <local routes> format; distance bgp 2 3 4) | os10 |
| ``distance_bgp.state`` | string: absent,present\* | Deletes distance BGP if set to absent | os10 |
| ``vrf.address_family_ipv6`` | dictionary | Configures IPv6 address family parameters in VRF (see ``address_family_ipv6.*``) | os10 |
| ``address_family_ipv6.aggregate_addr`` | list | Configures IPv6 BGP aggregate entries (see ``aggregate_addr.*``) | os10 |
| ``aggregate_addr.ip_and_mask`` | string | Configures the IPv6 BGP aggregate address | os10 |
| ``aggregate_addr.adv_map`` | string | Configures the advertise map for IPv6 BGP aggregate address | os10 |
| ``aggregate_addr.attr_map`` | string | Configures the attribute map for IPv6 BGP aggregate address | os10 |
| ``aggregate_addr.suppress_map`` | string | Configures the suppress map for IPv6 BGP aggregate address | os10 |
| ``aggregate_addr.summary_only`` | boolean | Sets address to summary-only if true | os10 |
| ``aggregate_addr.state`` | string: absent,present\* | Deletes an IPv6 BGP aggregate entry if set to absent | os10 |
| ``address_family_ipv6.dampening`` | dictionary | Configures route-flap dampening (see ``dampening.*``) | os10 |
| ``dampening.value`` | dictionary | Configures dampening values (<half-life time> <start value to reuse> <start value to suppress> <max duration> format; default 15 750 2000 60) | os10 |
| ``dampening.route_map`` | string | Configures the route-map to specify criteria for dampening | os10 |
| ``dampening.state`` | string: absent,present\* | Deletes dampening if set to absent | os10 |
| ``address_family_ipv6.ibgp_redist_internal`` | dictionary | Configures iBGP reditribution (see ``ibgp_redist_internal.*``) | os10 |
| ``ibgp_redist_internal.state`` | boolean | Configures the iBGP redistribution for a IPv6 address family | os10 |
| ``address_family_ipv6.default_metric`` | integer | Configures the metric of redistributed routes for IPv6 address family | os10 |
| ``address_family_ipv6.distance_bgp`` | dictionary | Configures BGP distances (see ``distance_bgp.*``) | os10 |
| ``distance_bgp.value`` | dictionary | Configures the BGP administrative distance for IPv6 address family (<routes external to AS> <routes internal to AS> <local routes> format; distance bgp 2 3 4) | os10 |
| ``distance_bgp.state`` | string: absent,present\* | Deletes distance BGP if set to absent | os10 |
| ``vrf.best_path`` | list | Configures the default best-path selection in VRF (see ``best_path.*``) | os10 |
| ``best_path.as_path`` | string (required): ignore,multipath-relax | Configures the AS path used for the best-path computation | os10 |
| ``best_path.as_path_state`` | string: absent,present\* | Deletes the AS path configuration if set to absent | os10 |
| ``best_path.ignore_router_id`` | boolean: true,false | Ignores the router identifier in best-path computation if set to true | os10 |
| ``best_path.med`` | list | Configures the MED attribute (see ``med.*``) | os10 |
| ``med.attribute`` | string (required): confed,missing-as-best | Configures the MED attribute used for the best-path computation | os10 |
| ``med.state`` | string: absent,present\* | Deletes the MED attribute if set to absent | os10 |
| ``vrf.ipv4_network`` | list | Configures an IPv4 BGP networks (see ``ipv4_network.*``) | os10 |
| ``ipv4_network.address`` | string (required) | Configures the IPv4 address of the BGP network (A.B.C.D/E format) | os10 |
| ``ipv4_network.state`` | string: absent,present\* | Deletes an IPv4 BGP network if set to absent | os10 |
| ``vrf.ipv6_network`` | list | Configures an IPv6 BGP network (see ``ipv6_network.*``) | os10 |
| ``ipv6_network.address`` | string (required) | Configures the IPv6 address of the BGP network (2001:4898:5808:ffa2::1/126 format) | os10 |
| ``ipv6_network.state`` | string: absent,present\* | Deletes an IPv6 BGP network if set to absent | os10 |
| ``vrf.neighbor`` | list | Configures IPv4 BGP neighbors in VRF (see ``neighbor.*``) | os10 |
| ``neighbor.ip`` | string (required) | Configures the IPv4 address of the BGP neighbor (10.1.1.1) | os10 |
| ``neighbor.interface`` | string | Configures the BGP neighbor interface details | os10 |
| ``neighbor.name`` | string (required) | Configures the BGP peer-group with this name; supported only when the neighbor is a peer group; mutually exclusive with *neighbor.ip* | os10 |
| ``neighbor.type`` | string (required): ipv4,ipv6,peergroup | Specifies the BGP neighbor type | os10 |
| ``neighbor.auto_peer`` |string: unnumbered-auto | Enable auto-discovery of neighbors | os10 |
| ``neighbor.password`` | string | Configures the BGP neighbor password | os10 |
| ``neighbor.peergroup_type`` | string (ibgp, ebgp) | Configures the BGP neighbor peer-group type| os10 |
| ``neighbor.ebgp_peergroup`` | string | Configures the peer-group to all auto-discovered external neighbors | os10 |
| ``neighbor.ebgp_peergroup_state`` | string: present,absent | Removes the peer-group from all auto-discovered external neighbors | os10 |
| ``neighbor.ibgp_peergroup`` | string | Configures the peer-group to all auto-discovered internal neighbors | os10 |
| ``neighbor.ibgp_peergroup_state`` | string: present,absent | Removes the peer-group from all auto-discovered internal neighbors | os10 |
| ``neighbor.route_reflector_client`` | boolean | Configures router reflector client on the BGP neighbor | os10 |
| ``neighbor.local_as`` | integer | Configures the local AS for the BGP peer | os10 |
| ``neighbor.weight`` | integer | Configures the default weight for routes from the neighbor interface | os10 |
| ``neighbor.send_community`` | list | Configures the send community attribute to the BGP neighbor (see ``send_community.*``) | os10 |
| ``send_community.type`` | string (required) | Configures the send community attribute to the BGP neighbor | os10 |
| ``send_community.state`` | string: absent,present\* | Deletes the send community attribute of the BGP neighbor if set to absent | os10 |
| ``neighbor.address_family`` | list | Configures address family commands on the BGP neighbor (see ``address_family.*``)| os10 |
| ``address_family.type`` | string (required): ipv4,ipv6,l2vpn | Configures IPv4/IPv6 EVPN address family command mode on the BGP neighbor | os10 |
| ``address_family.activate`` | boolean | Configures activation or deactivation of IPv4/IPv6 address family command mode on the BGP neighbor | os10 |
| ``address_family.sender_loop_detect`` | boolean | Enables or disables the sender-side loop detection process for a BGP neighbor of IPv4/IPv6 l2vpn address family | os10 |
| ``address_family.allow_as_in`` | integer | Configures the local AS number in the as-path | os10 |
| ``address_family.next_hop_self`` | boolean | Configures disabling the next-hop calculation for the neighbor | os10 |
| ``address_family.soft_reconf`` | boolean | Configures per neighbor soft reconfiguration | os10 |
| ``address_family.add_path`` | string | Configures send or receive multiple paths (value can be 'both <no of paths>', 'send <no of paths>', 'receive')| os10 |
| ``address_family.route_map`` | list | Configures the route-map on the BGP neighbor (see ``route_map.*``) | os10 |
| ``route_map.name`` | string | Configures the name of the route-map for the BGP neighbor | os10 |
| ``route_map.filter`` | string | Configures the filter for routing updates | os10 |
| ``route_map.state`` | string, choices: absent,present* | Deletes the route-map of the BGP neighbor if set to absent | os10 |
| ``address_family.max_prefix`` | dictionary | Configures maximum-prefix parameters (see ``max_prefix.*``) | os10 |
| ``max_prefix.count`` | integer | Configures maximum number of prefix accepted from the peer | os10 |
| ``max_prefix.state`` | string: absent,present | Deletes maximum prefix configured for the peer | os10 |
| ``max_prefix.threshold`` | integer | Configures threshold percentage at which warning log is thrown | os10 |
| ``max_prefix.warning``| boolean | Configures a warning without dropping session when maximum limit exceeds if set to true | os10|
| ``address_family.default_originate`` | dictionary | Configures default-originate parameters (see ``default_originate.\*``) | os10 |
| ``default_originate.route_map`` | string | Configures the name of the route-map to specify criteria to originate default | os10 |
| ``default_originate.state`` | string, choices: absent,present\* | Deletes the default-originate if set to absent | os10 |
| ``address_family.distribute_list`` | list | Configures the distribute list to filter networks from routing updates (see ``distribute_list.*``) | os10 |
| ``distribute_list.in`` | string | Configures the name of the prefix-list to filter incoming packets | os10 |
| ``distribute_list.in_state`` | string: absent,present\* | Deletes the filter at incoming packets if set to absent | os10 |
| ``distribute_list.out`` | string | Configures the name of the prefix-list to filter outgoing packets | os10 |
| ``distribute_list.out_state`` | string: absent,present\* | Deletes the filter at outgoing packets if set to absent | os10 |
| ``address_family.state`` | string: absent,present\* | Deletes the address family command mode of the BGP neighbor if set to absent | os10 |
| ``neighbor.remote_asn`` | string (required) | Configures the remote AS number of the BGP neighbor | os10 |
| ``neighbor.remote_asn_state`` | string: absent,present\* | Deletes the remote AS number from the peer-group if set to absent; supported only when *neighbor.type* is "peergroup" | os10 |
| ``neighbor.timer`` | string | Configures neighbor timers; 5 10, where 5 is the keepalive interval and 10 is the holdtime | os10 |
| ``neighbor.peergroup`` | string | Configures neighbor to BGP peer-group (configured peer-group name) | os10 |
| ``neighbor.peergroup_state`` | string: absent,present\* | Deletes the IPv4 BGP neighbor from the peer-group if set to absent | os10 |
| ``neighbor.distribute_list`` | list | Configures the distribute list to filter networks from routing updates (see ``distribute_list.*``) | os10 |
| ``distribute_list.in`` | string | Configures the name of the prefix-list to filter incoming packets | os10 |
| ``distribute_list.in_state`` | string: absent,present\* | Deletes the filter at incoming packets if set to absent | os10 |
| ``distribute_list.out`` | string | Configures the name of the prefix-list to filter outgoing packets | os10 |
| ``distribute_list.out_state`` | string: absent,present\* | Deletes the filter at outgoing packets if set to absent | os10 |
| ``neighbor.admin`` | string: up,down | Configures the administrative state of the neighbor | os10 |
| ``neighbor.adv_interval`` | integer | Configures the advertisement interval of the neighbor | os10 |
| ``neighbor.adv_start`` | integer | Set the advertisement start of the neighbor | os10 |
| ``neighbor.adv_start_state`` | string: absent,present\* | Configures or unconfigures the advertisement start of the neighbor | os10 |
| ``neighbor.conn_retry_timer`` | integer | Configures the peer connection retry timer | os10 |
| ``neighbor.remove_pri_as`` | string: absent,present | Removes private AS number from outbound updates | os10 |
| ``neighbor.fall_over`` | string: absent,present | Configures the session fall on peer-route loss | os10 |
| ``neighbor.sender_loop_detect`` | boolean: true,false | Enables or disables the sender-side loop detect for neighbors | os10 |
| ``neighbor.src_loopback`` | integer | Configures the source loopback interface for routing packets | os10 |
| ``neighbor.ebgp_multihop`` | integer | Configures the maximum-hop count value allowed in eBGP neighbors that are not directly connected (default 255) | os10 |
| ``neighbor.listen`` | list | Configures listen commands on the BGP template (see ``listen.*``)| os10 |
| ``listen.subnet`` | string (required) | Configures the passive BGP neighbor IPv4/IPv6 to this subnet | os10 |
| ``listen.subnet_state`` | string: absent,present\* | Deletes the subnet range set for dynamic IPv4/IPv6 BGP neighbor if set to absent | os10 |
| ``listen.limit`` | integer | Configures maximum dynamic peers count (key is required together with ``neighbor.subnet``) | os10 |
| ``neighbor.bfd`` | boolean | Enables BFD for neighbor | os10 |
| ``neighbor.description`` | string | Configures neighbor description | os10 |
| ``neighbor.state`` | string: absent,present\* | Deletes the IPv4 BGP neighbor if set to absent | os10 |
| ``vrf.redistribute`` | list | Configures the redistribute list to get information from other routing protocols in VRF (see ``redistribute.*``) | os10 |
| ``redistribute.route_type`` | string (required): static,connected,imported_bgp | Configures the name of the routing protocol to redistribute | os10 |
| ``redistribute.route_map_name`` | string | Configures the route-map to redistribute | os10 |
| ``redistribute.imported_bgp_vrf_name`` | string | Configures the redistribute imported BGP VRF name | os10 |
| ``redistribute.ospf_id`` | string | Configures the redistribute ospf | os10 |
| ``redistribute.address_type`` | string (required): ipv4,ipv6 | Configures the address type of IPv4 or IPv6 routes | os10 |
| ``redistribute.state`` | string: absent,present\* | Deletes the redistribution information if set to absent | os10 |
| ``vrf.bfd_all_neighbors`` | dictionary | Enables BFD for all BGP neighbors in VRF ((see ``bfd_all_neighbors.*``))| os10 |
| ``bfd_all_neighbors.interval`` | integer: 100 to 1000 | Configures time interval for sending control packets to BFD peers in ms| os10 |
| ``bfd_all_neighbors.min_rx`` | integer: 100 to 1000 | Configures maximum waiting time for receiving control packets from BFD peers in ms| os10 |
| ``bfd_all_neighbors.multiplier`` | integer: 3 to 50 | Configures maximum number of consecutive packets that are not received from BFD peers before session state changes to Down| os10 |
| ``bfd_all_neighbors.role``| string: active, passive | Configures BFD role | os10 |
| ``bfd_all_neighbors.state`` |string: absent,present\* | Deletes BFD for all neighbors if set to absent | os10 |
| ``vrf.state`` | string: absent,present\* | Deletes the VRF instance under router BGP if set to absent | os10 |
| ``state`` | string: absent,present\* | Deletes the local router BGP instance if set to absent | os10 |
> **NOTE**: Asterisk (\*) denotes the default value if none is specified.
Connection variables
--------------------
Ansible Dell EMC network roles require connection information to establish communication with the nodes in your inventory. This information can exist in the Ansible *group_vars* or *host_vars* directories or inventory, or in the playbook itself.
| Key | Required | Choices | Description |
|-------------|----------|------------|-----------------------------------------------------|
| ``ansible_host`` | yes | | Specifies the hostname or address for connecting to the remote device over the specified transport |
| ``ansible_port`` | no | | Specifies the port used to build the connection to the remote device; if value is unspecified, the `ANSIBLE_REMOTE_PORT` option is used; it defaults to 22 |
| ``ansible_ssh_user`` | no | | Specifies the username that authenticates the CLI login for the connection to the remote device; if value is unspecified, the `ANSIBLE_REMOTE_USER` environment variable value is used |
| ``ansible_ssh_pass`` | no | | Specifies the password that authenticates the connection to the remote device |
| ``ansible_become`` | no | yes, no\* | Instructs the module to enter privileged mode on the remote device before sending any commands; if value is unspecified, the `ANSIBLE_BECOME` environment variable value is used, and the device attempts to execute all commands in non-privileged mode |
| ``ansible_become_method`` | no | enable, sudo\* | Instructs the module to allow the become method to be specified for handling privilege escalation; if value is unspecified, the `ANSIBLE_BECOME_METHOD` environment variable value is used |
| ``ansible_become_pass`` | no | | Specifies the password to use if required to enter privileged mode on the remote device; if ``ansible_become`` is set to no this key is not applicable |
| ``ansible_network_os`` | yes | os10, null\* | Loads the correct terminal and cliconf plugins to communicate with the remote device |
> **NOTE**: Asterisk (\*) denotes the default value if none is specified.
Example playbook
----------------
This example uses the *os10_bgp* role to configure the BGP network and neighbors. It creates a *hosts* file with the switch details, a *host_vars* file with connection variables and the corresponding role variables. The hosts file should define the `ansible_network_os` variable with the corresponding Dell EMC OS10 name.
When `os10_cfg_generate` is set to true, the variable generates the configuration commands as a .part file in *build_dir* path. By default, the variable is set to false. This example writes a simple playbook that only references the *os10_bgp* role.
**Sample hosts file**
leaf1 ansible_host= <ip_address>
**Sample host_vars/leaf1**
hostname: leaf1
ansible_become: yes
ansible_become_method: xxxxx
ansible_become_pass: xxxxx
ansible_ssh_user: xxxxx
ansible_ssh_pass: xxxxx
ansible_network_os: dellemc.os10.os10
build_dir: ../temp/temp_os10
os10_bgp:
asn: 12
router_id: 90.1.1.4
maxpath_ibgp: 2
maxpath_ebgp: 2
graceful_restart: true
log_neighbor_changes: true
fast_ext_fallover: false
always_compare_med: true
default_loc_pref: 1000
as_notation: asdot
enforce_first_as: false
non_deterministic_med: true
outbound_optimization: true
confederation:
identifier: 25
peers: 23 24
peers_state: present
route_reflector:
client_to_client: false
cluster_id: 4294967295
address_family_ipv4:
aggregate_address:
- ip_and_mask: 1.1.1.1/16
state: present
summary_only: true
dampening:
value: 15 750 2000 60
route_map: qq
state: present
ibgp_redist_internal:
state: present
default_metric: 10
distance_bgp:
value: 3 4 6
state: present
address_family_ipv6:
aggregate_address:
- ip_and_mask: 2001:4898:5808:ffa0::/126
state: present
summary_only: true
ibgp_redist_internal:
state: present
best_path:
as_path: ignore
as_path_state: present
ignore_router_id: true
med:
- attribute: confed
state: present
ipv4_network:
- address: 101.1.1.0/30
state: present
ipv6_network:
- address: "2001:4898:5808:ffa0::/126"
state: present
neighbor:
- name: ebgp_pg
type: peergroup
bfd: yes
state: present
address_family:
- type: ipv4
activate: false
state: present
max_prefix:
count: 20
threshold: 90
warning: true
state: present
listen:
- subnet: 4.4.4.4/32
limit: 4
subnet_state: present
- subnet: 20::/64
limit: 4
subnet_state: present
- name: ibgp_pg
type: peergroup
weight: 10
state: present
- type: ipv4
interface: vlan20
send_community:
- type: extended
state: present
address_family:
- type: l2vpn
activate: true
state: present
admin: up
state: present
- type: ipv4
description: "U_site2-spine1"
remote_asn: 11
ip: 192.168.10.1
peergroup: peer1
peergroup_state: present
peergroup_type: ibgp
adv_interval: 40
fall_over: present
password: bgppassword
route_reflector_client: true
adv_start: 100
adv_start_state: present
conn_retry_timer: 20
remove_pri_as: present
src_loopback: 0
address_family:
- type: ipv4
activate: true
state: present
max_prefix:
count: 10
threshold: 40
warning: true
state: present
default_originate:
route_map: aa
state: present
distribute_list:
in: XX
in_state: present
out: YY
out_state: present
send_community:
- type: standard
state: present
state: present
- type: ipv4
remote_asn: 13
local_as: 10
weight: 10
ip: 192.168.12.3
address_family:
- type: ipv4
activate: true
allow_as_in: 5
next_hop_self: true
soft_reconf: true
add_path: both 3
route_map:
- name: qq
filter: in
state: present
state: present
state: present
- type: ipv6
remote_asn: 14
ip: 2001:4898:5808:ffa2::1
state: present
- type: ipv6
description: "U_site2-spine1-Auto Discovered peers"
auto_peer: unnumbered-auto
ebgp_peergroup: ebgp_pg
ebgp_peergroup_state: absent
ibgp_peergroup: ibgp_pg
ibgp_peergroup_state: present
sender_loop_detect: true
password: bgppassword
address_family:
- type: ipv4
activate: true
sender_loop_detect: true
state: present
allow_as_in: 5
next_hop_self: true
soft_reconf: true
- type: l2vpn
activate: true
sender_loop_detect: false
state: present
send_community:
- type: standard
state: present
admin: up
state: present
redistribute:
- route_type: static
route_map_name: aa
address_type: ipv4
state: present
bfd_all_neighbors:
interval: 200
min_rx: 200
multiplier: 3
role: active
state: present
vrfs:
- name: "GREEN"
router_id: 50.1.1.1
maxpath_ibgp: 2
maxpath_ebgp: 2
graceful_restart: true
log_neighbor_changes: false
fast_ext_fallover: false
always_compare_med: true
default_loc_pref: 1000
route_reflector:
client_to_client: false
cluster_id: 1
address_family_ipv4:
aggregate_address:
- ip_and_mask: 1.1.1.1/16
state: present
dampening:
value: 15 750 2000 60
route_map: qq
state: present
ibgp_redist_internal:
state: present
address_family_ipv6:
aggregate_address:
- ip_and_mask: 2001:4898:5808:ffa0::/126
state: present
summary_only: true
ibgp_redist_internal:
state: present
best_path:
as_path: ignore
as_path_state: present
ignore_router_id: true
med:
- attribute: confed
state: present
- attribute: missing-as-worst
state: present
ipv4_network:
- address: 101.1.1.0/30
state: present
ipv6_network:
- address: "2001:4898:5808:ffa0::/126"
state: present
neighbor:
- name: peer1
type: peergroup
bfd: yes
state: present
- name: ebgp_pg
type: peergroup
bfd: yes
state: present
- name: ibgp_pg
type: peergroup
weight: 10
state: present
- type: ipv4
interface: vlan10
description: U_site2 vlan
send_community:
- type: extended
state: present
admin: up
state: present
- type: ipv4
description: "U_site2 spine1"
remote_asn: 11
ip: 192.168.20.1
name: peer1
peergroup: peer1
peergroup_state: present
peergroup_type: ibgp
adv_interval: 40
fall_over: present
route_reflector_client: true
src_loopback: 0
address_family:
- type: ipv4
activate: false
state: present
send_community:
- type: standard
state: present
state: present
- type: ipv4
description: "U_site2 spine1"
remote_asn: 13
local_as: 10
weight: 10
ip: 192.168.15.3
address_family:
- type: ipv4
activate: false
allow_as_in: 5
next_hop_self: true
soft_reconf: true
add_path: both 3
route_map:
- name: qq
filter: in
state: present
state: present
state: present
- type: ipv6
remote_asn: 14
ip: 2001:4898:5808:ffa2::1
state: present
- type: ipv6
description: "U_site2-spine1-Auto Discovered peers"
auto_peer: unnumbered-auto
ebgp_peergroup: ebgp_pg
ebgp_peergroup_state: present
ibgp_peergroup: ibgp_pg
ibgp_peergroup_state: present
address_family:
- type: ipv4
activate: false
sender_loop_detect: false
state: present
allow_as_in: 5
next_hop_self: true
soft_reconf: true
send_community:
- type: standard
state: present
admin: up
state: present
redistribute:
- route_type: static
route_map_name: aa
address_type: ipv4
state: present
- route_type: connected
route_map_name: bb
address_type: ipv4
state: present
- route_type: l2vpn
route_map_name: cc
address_type: ipv4
state: present
- route_type: imported_bgp
imported_bgp_vrf_name: test6
route_map_name: dd
address_type: ipv4
state: present
- route_type: ospf
ospf_id: 12
address_type: ipv4
state: present
bfd_all_neighbors:
interval: 200
min_rx: 200
multiplier: 3
role: active
state: present
state: present
state: present
**Simple playbook to configure BGP — leaf.yaml**
- hosts: leaf1
roles:
- dellemc.os10.os10_bgp
**Run**
ansible-playbook -i hosts leaf.yaml
(c) 2017-2020 Dell Inc. or its subsidiaries. All rights reserved.

Some files were not shown because too many files have changed in this diff Show More