commit 5044249e1f6cc5cbcf3bde84ce58f25065645cf5
Author: Ansible Core Team <info@ansible.com>
Date:   Mon Mar 9 13:35:35 2020 +0000

    Initial commit

diff --git a/.github/workflows/collection-continuous-integration.yml b/.github/workflows/collection-continuous-integration.yml
new file mode 100644
index 0000000..0190a66
--- /dev/null
+++ b/.github/workflows/collection-continuous-integration.yml
@@ -0,0 +1,308 @@
+name: Collection test suite
+
+on:
+  push:
+  pull_request:
+  schedule:
+  - cron: 3 0 * * *  # Run daily at 0:03 UTC
+
+jobs:
+  build-collection-artifact:
+    name: Build collection
+    runs-on: ${{ matrix.runner-os }}
+    strategy:
+      matrix:
+        runner-os:
+        - ubuntu-latest
+        ansible-version:
+        - git+https://github.com/ansible/ansible.git@devel
+        runner-python-version:
+        - 3.8
+    steps:
+    - name: Check out ${{ github.repository }} on disk
+      uses: actions/checkout@master
+    - name: Set up Python ${{ matrix.runner-python-version }}
+      uses: actions/setup-python@v1
+      with:
+        python-version: ${{ matrix.runner-python-version }}
+    - name: Set up pip cache
+      uses: actions/cache@v1
+      with:
+        path: ~/.cache/pip
+        key: ${{ runner.os }}-pip-${{ hashFiles('tests/sanity/requirements.txt') }}-${{ hashFiles('tests/unit/requirements.txt') }}
+        restore-keys: |
+          ${{ runner.os }}-pip-
+          ${{ runner.os }}-
+    - name: Install Ansible ${{ matrix.ansible-version }}
+      run: >-
+        python -m
+        pip
+        install
+        --user
+        ${{ matrix.ansible-version }}
+    - name: Build a collection tarball
+      run: >-
+        ~/.local/bin/ansible-galaxy
+        collection
+        build
+        --output-path
+        "${GITHUB_WORKSPACE}/.cache/collection-tarballs"
+    - name: Store migrated collection artifacts
+      uses: actions/upload-artifact@v1
+      with:
+        name: >-
+          collection
+        path: .cache/collection-tarballs
+
+  sanity-test-collection-via-vms:
+    name: Sanity in VM ${{ matrix.os.vm || 'ubuntu-latest' }}
+    needs:
+    - build-collection-artifact
+    runs-on: ${{ matrix.os.vm || 'ubuntu-latest' }}
+    strategy:
+      fail-fast: false
+      matrix:
+        ansible-version:
+        - git+https://github.com/ansible/ansible.git@devel
+        os:
+        - vm: ubuntu-latest
+        - vm: ubuntu-16.04
+        - vm: macos-latest
+        python-version:
+        - 3.8
+        - 3.7
+        - 3.6
+        - 3.5
+        - 2.7
+    steps:
+    - name: Set up Python ${{ matrix.python-version }}
+      uses: actions/setup-python@v1
+      with:
+        python-version: ${{ matrix.python-version }}
+    - name: Set up pip cache
+      uses: actions/cache@v1
+      with:
+        path: ~/.cache/pip
+        key: ${{ runner.os }}-pip-${{ github.ref }}-sanity-VMs
+        restore-keys: |
+          ${{ runner.os }}-pip-
+          ${{ runner.os }}-
+    - name: Install Ansible ${{ matrix.ansible-version }}
+      run: >-
+        python -m
+        pip
+        install
+        --user
+        ${{ matrix.ansible-version }}
+    - name: Download migrated collection artifacts
+      uses: actions/download-artifact@v1
+      with:
+        name: >-
+          collection
+        path: .cache/collection-tarballs
+    - name: Install the collection tarball
+      run: >-
+        ~/.local/bin/ansible-galaxy
+        collection
+        install
+        .cache/collection-tarballs/*.tar.gz
+    - name: Run collection sanity tests
+      run: >-
+        ~/.local/bin/ansible-test
+        sanity
+        --color
+        --requirements
+        --venv
+        --python
+        "${{ matrix.python-version }}"
+        -vvv
+      working-directory: >-
+        /${{ runner.os == 'Linux' && 'home' || 'Users' }}/runner/.ansible/collections/ansible_collections/dellemc_networking/os9
+
+  sanity-test-collection-via-containers:
+    name: Sanity in container via Python ${{ matrix.python-version }}
+    needs:
+    - build-collection-artifact
+    runs-on: ${{ matrix.runner-os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        runner-os:
+        - ubuntu-latest
+        runner-python-version:
+        - 3.8
+        ansible-version:
+        - git+https://github.com/ansible/ansible.git@devel
+        python-version:
+        - 3.8
+        - 2.7
+        - 3.7
+        - 3.6
+        - 3.5
+        - 2.6
+    steps:
+    - name: Set up Python ${{ matrix.runner-python-version }}
+      uses: actions/setup-python@v1
+      with:
+        python-version: ${{ matrix.runner-python-version }}
+    - name: Set up pip cache
+      uses: actions/cache@v1
+      with:
+        path: ~/.cache/pip
+        key: ${{ runner.os }}-pip-${{ github.ref }}-sanity-containers
+        restore-keys: |
+          ${{ runner.os }}-pip-
+          ${{ runner.os }}-
+    - name: Install Ansible ${{ matrix.ansible-version }}
+      run: >-
+        python -m
+        pip
+        install
+        --user
+        ${{ matrix.ansible-version }}
+    - name: Download migrated collection artifacts
+      uses: actions/download-artifact@v1
+      with:
+        name: >-
+          collection
+        path: .cache/collection-tarballs
+    - name: Install the collection tarball
+      run: >-
+        ~/.local/bin/ansible-galaxy
+        collection
+        install
+        .cache/collection-tarballs/*.tar.gz
+    - name: Run collection sanity tests
+      run: >-
+        ~/.local/bin/ansible-test
+        sanity
+        --color
+        --requirements
+        --docker
+        --python
+        "${{ matrix.python-version }}"
+        -vvv
+      working-directory: >-
+        /home/runner/.ansible/collections/ansible_collections/dellemc_networking/os9
+
+  unit-test-collection-via-vms:
+    name: Units in VM ${{ matrix.os.vm || 'ubuntu-latest' }}
+    needs:
+    - build-collection-artifact
+    runs-on: ${{ matrix.os.vm || 'ubuntu-latest' }}
+    strategy:
+      fail-fast: false
+      matrix:
+        ansible-version:
+        - git+https://github.com/ansible/ansible.git@devel
+        os:
+        - vm: ubuntu-latest
+        - vm: ubuntu-16.04
+        - vm: macos-latest
+        python-version:
+        - 3.8
+        - 3.7
+        - 3.6
+        - 3.5
+        - 2.7
+    steps:
+    - name: Set up Python ${{ matrix.python-version }}
+      uses: actions/setup-python@v1
+      with:
+        python-version: ${{ matrix.python-version }}
+    - name: Set up pip cache
+      uses: actions/cache@v1
+      with:
+        path: ~/.cache/pip
+        key: ${{ runner.os }}-pip-${{ github.ref }}-units-VMs
+        restore-keys: |
+          ${{ runner.os }}-pip-
+          ${{ runner.os }}-
+    - name: Install Ansible ${{ matrix.ansible-version }}
+      run: >-
+        python -m
+        pip
+        install
+        --user
+        ${{ matrix.ansible-version }}
+    - name: Download migrated collection artifacts
+      uses: actions/download-artifact@v1
+      with:
+        name: >-
+          collection
+        path: .cache/collection-tarballs
+    - name: Install the collection tarball
+      run: >-
+        ~/.local/bin/ansible-galaxy
+        collection
+        install
+        .cache/collection-tarballs/*.tar.gz
+    - name: Run collection unit tests
+      run: |
+        [[ ! -d 'tests/unit' ]] && echo This collection does not have unit tests. Skipping... || \
+        ~/.local/bin/ansible-test units --color --coverage --requirements --venv --python "${{ matrix.python-version }}" -vvv
+      working-directory: >-
+        /${{ runner.os == 'Linux' && 'home' || 'Users' }}/runner/.ansible/collections/ansible_collections/dellemc_networking/os9
+
+  unit-test-collection-via-containers:
+    name: Units in container ${{ matrix.container-image }}
+    needs:
+    - build-collection-artifact
+    runs-on: ${{ matrix.runner-os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        runner-os:
+        - ubuntu-latest
+        runner-python-version:
+        - 3.8
+        ansible-version:
+        - git+https://github.com/ansible/ansible.git@devel
+        container-image:
+        - fedora31
+        - ubuntu1804
+        - centos8
+        - opensuse15
+        - fedora30
+        - centos7
+        - opensuse15py2
+        - ubuntu1604
+        - centos6
+    steps:
+    - name: Set up Python ${{ matrix.runner-python-version }}
+      uses: actions/setup-python@v1
+      with:
+        python-version: ${{ matrix.runner-python-version }}
+    - name: Set up pip cache
+      uses: actions/cache@v1
+      with:
+        path: ~/.cache/pip
+        key: ${{ runner.os }}-pip-${{ github.ref }}-units-containers
+        restore-keys: |
+          ${{ runner.os }}-pip-
+          ${{ runner.os }}-
+    - name: Install Ansible ${{ matrix.ansible-version }}
+      run: >-
+        python -m
+        pip
+        install
+        --user
+        ${{ matrix.ansible-version }}
+    - name: Download migrated collection artifacts
+      uses: actions/download-artifact@v1
+      with:
+        name: >-
+          collection
+        path: .cache/collection-tarballs
+    - name: Install the collection tarball
+      run: >-
+        ~/.local/bin/ansible-galaxy
+        collection
+        install
+        .cache/collection-tarballs/*.tar.gz
+    - name: Run collection unit tests
+      run: |
+        [[ ! -d 'tests/unit' ]] && echo This collection does not have unit tests. Skipping... || \
+        ~/.local/bin/ansible-test units --color --coverage --requirements --docker "${{ matrix.container-image }}" -vvv
+      working-directory: >-
+        /home/runner/.ansible/collections/ansible_collections/dellemc_networking/os9
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c6fc14a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,387 @@
+
+# Created by https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
+# Edit at https://www.gitignore.io/?templates=git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
+
+### dotenv ###
+.env
+
+### Emacs ###
+# -*- mode: gitignore; -*-
+*~
+\#*\#
+/.emacs.desktop
+/.emacs.desktop.lock
+*.elc
+auto-save-list
+tramp
+.\#*
+
+# Org-mode
+.org-id-locations
+*_archive
+
+# flymake-mode
+*_flymake.*
+
+# eshell files
+/eshell/history
+/eshell/lastdir
+
+# elpa packages
+/elpa/
+
+# reftex files
+*.rel
+
+# AUCTeX auto folder
+/auto/
+
+# cask packages
+.cask/
+dist/
+
+# Flycheck
+flycheck_*.el
+
+# server auth directory
+/server/
+
+# projectiles files
+.projectile
+
+# directory configuration
+.dir-locals.el
+
+# network security
+/network-security.data
+
+
+### Git ###
+# Created by git for backups. To disable backups in Git:
+# $ git config --global mergetool.keepBackup false
+*.orig
+
+# Created by git when using merge tools for conflicts
+*.BACKUP.*
+*.BASE.*
+*.LOCAL.*
+*.REMOTE.*
+*_BACKUP_*.txt
+*_BASE_*.txt
+*_LOCAL_*.txt
+*_REMOTE_*.txt
+
+#!! ERROR: jupyternotebook is undefined. Use list command to see defined gitignore types !!#
+
+### Linux ###
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+### PyCharm+all ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn.  Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### PyCharm+all Patch ###
+# Ignores the whole .idea folder and all .iml files
+# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
+
+.idea/
+
+# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
+
+*.iml
+modules.xml
+.idea/misc.xml
+*.ipr
+
+# Sonarlint plugin
+.idea/sonarlint
+
+### pydev ###
+.pydevproject
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# pyenv
+.python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
+#   install all needed dependencies.
+#Pipfile.lock
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# Mr Developer
+.mr.developer.cfg
+.project
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+### Vim ###
+# Swap
+[._]*.s[a-v][a-z]
+[._]*.sw[a-p]
+[._]s[a-rt-v][a-z]
+[._]ss[a-gi-z]
+[._]sw[a-p]
+
+# Session
+Session.vim
+Sessionx.vim
+
+# Temporary
+.netrwhist
+# Auto-generated tag files
+tags
+# Persistent undo
+[._]*.un~
+
+### WebStorm ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+
+# Generated files
+
+# Sensitive or high-churn files
+
+# Gradle
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn.  Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+
+# Mongo Explorer plugin
+
+# File-based project format
+
+# IntelliJ
+
+# mpeltonen/sbt-idea plugin
+
+# JIRA plugin
+
+# Cursive Clojure plugin
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+
+# Editor-based Rest Client
+
+# Android studio 3.1+ serialized cache file
+
+### WebStorm Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+.idea/**/sonarlint/
+
+# SonarQube Plugin
+.idea/**/sonarIssues.xml
+
+# Markdown Navigator plugin
+.idea/**/markdown-navigator.xml
+.idea/**/markdown-navigator/
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# End of https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..10926e8
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,675 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6cab959
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+[![GitHub Actions CI/CD build status — Collection test suite](https://github.com/ansible-collection-migration/dellemc_networking.os9/workflows/Collection%20test%20suite/badge.svg?branch=master)](https://github.com/ansible-collection-migration/dellemc_networking.os9/actions?query=workflow%3A%22Collection%20test%20suite%22)
+
+Ansible Collection: dellemc_networking.os9
+=================================================
\ No newline at end of file
diff --git a/galaxy.yml b/galaxy.yml
new file mode 100644
index 0000000..158937a
--- /dev/null
+++ b/galaxy.yml
@@ -0,0 +1,15 @@
+namespace: dellemc_networking
+name: os9
+version: 0.1.0
+readme: README.md
+authors: null
+description: null
+license: GPL-3.0-or-later
+license_file: COPYING
+tags: null
+dependencies:
+  ansible.netcommon: '>=0.1.0'
+repository: git@github.com:ansible-collection-migration/dellemc_networking.os9.git
+documentation: https://github.com/ansible-collection-migration/dellemc_networking.os9/tree/master/docs
+homepage: https://github.com/ansible-collection-migration/dellemc_networking.os9
+issues: https://github.com/ansible-collection-migration/dellemc_networking.os9/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
diff --git a/plugins/action/__init__.py b/plugins/action/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/plugins/action/dellos9.py b/plugins/action/dellos9.py
new file mode 100644
index 0000000..7e18a5f
--- /dev/null
+++ b/plugins/action/dellos9.py
@@ -0,0 +1,81 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# Copyright (c) 2017 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_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_networking.os9.plugins.module_utils.network.dellos9.dellos9 import dellos9_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
+
+        module_name = self._task.action.split('.')[-1]
+        self._config_module = True if module_name == 'dellos9_config' else False
+        socket_path = None
+        persistent_connection = self._play_context.connection.split('.')[-1]
+
+        if persistent_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(dellos9_provider_spec, self._task.args)
+            pc = copy.deepcopy(self._play_context)
+            pc.connection = 'network_cli'
+            pc.network_os = 'dellos9'
+            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, task_uuid=self._task._uuid)
+            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
+
+        result = super(ActionModule, self).run(task_vars=task_vars)
+        return result
diff --git a/plugins/cliconf/__init__.py b/plugins/cliconf/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/plugins/cliconf/dellos9.py b/plugins/cliconf/dellos9.py
new file mode 100644
index 0000000..b360807
--- /dev/null
+++ b/plugins/cliconf/dellos9.py
@@ -0,0 +1,122 @@
+#
+# (c) 2017 Red Hat Inc.
+#
+# (c) 2017 Dell EMC.
+#
+# 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: dellos9
+short_description: Use dellos9 cliconf to run command on Dell OS9 platform
+description:
+  - This dellos9 plugin provides low level abstraction apis for
+    sending and receiving CLI commands from Dell OS9 network devices.
+'''
+
+import re
+import json
+
+from itertools import chain
+
+from ansible.errors import AnsibleConnectionFailure
+from ansible.module_utils._text import to_bytes, to_text
+from ansible.module_utils.common._collections_compat import Mapping
+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'] = 'dellos9'
+        reply = self.get('show version')
+        data = to_text(reply, errors='surrogate_or_strict').strip()
+
+        match = re.search(r'Software 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-config | 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(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)
+
+    def run_commands(self, commands=None, check_rc=True):
+        if commands is None:
+            raise ValueError("'commands' value is required")
+
+        responses = list()
+        for cmd in to_list(commands):
+            if not isinstance(cmd, Mapping):
+                cmd = {'command': cmd}
+
+            output = cmd.pop('output', None)
+            if output:
+                raise ValueError("'output' value %s is not supported for run_commands" % output)
+
+            try:
+                out = self.send_command(**cmd)
+            except AnsibleConnectionFailure as e:
+                if check_rc:
+                    raise
+                out = getattr(e, 'err', to_text(e))
+
+            responses.append(out)
+
+        return responses
+
+    def set_cli_prompt_context(self):
+        """
+        Make sure we are in the operational cli mode
+        :return: None
+        """
+        if self._connection.connected:
+            self._update_cli_prompt_context(config_context=')#')
diff --git a/plugins/doc_fragments/__init__.py b/plugins/doc_fragments/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/plugins/doc_fragments/dellos9.py b/plugins/doc_fragments/dellos9.py
new file mode 100644
index 0000000..e65e53c
--- /dev/null
+++ b/plugins/doc_fragments/dellos9.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2015, Peter Sprygada <psprygada@ansible.com>
+# Copyright: (c) 2016, Dell Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+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
+        required: true
+      port:
+        description:
+          - Specifies the port to use when building the connection to the remote
+            device.
+        type: int
+        default: 22
+      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
+        default: 10
+notes:
+  - For more information on using Ansible to manage Dell EMC Network devices see U(https://www.ansible.com/ansible-dell-networking).
+'''
diff --git a/plugins/module_utils/__init__.py b/plugins/module_utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/plugins/module_utils/network/dellos9/dellos9.py b/plugins/module_utils/network/dellos9/dellos9.py
new file mode 100644
index 0000000..cdbd1ad
--- /dev/null
+++ b/plugins/module_utils/network/dellos9/dellos9.py
@@ -0,0 +1,166 @@
+#
+# (c) 2015 Peter Sprygada, <psprygada@ansible.com>
+# (c) 2017 Red Hat, Inc
+#
+# Copyright (c) 2016 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.
+#
+import json
+
+from ansible.module_utils._text import to_text
+from ansible.module_utils.basic import env_fallback
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list, ComplexList
+from ansible.module_utils.connection import Connection, ConnectionError, exec_command
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import NetworkConfig, ConfigLine
+
+_DEVICE_CONFIGS = {}
+
+WARNING_PROMPTS_RE = [
+    r"[\r\n]?\[confirm yes/no\]:\s?$",
+    r"[\r\n]?\[y/n\]:\s?$",
+    r"[\r\n]?\[yes/no\]:\s?$"
+]
+
+dellos9_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'),
+}
+dellos9_argument_spec = {
+    'provider': dict(type='dict', options=dellos9_provider_spec),
+}
+dellos9_top_spec = {
+    'host': dict(removed_in_version=2.9),
+    'port': dict(removed_in_version=2.9, type='int'),
+    'username': dict(removed_in_version=2.9),
+    'password': dict(removed_in_version=2.9, no_log=True),
+    'ssh_keyfile': dict(removed_in_version=2.9, type='path'),
+    'authorize': dict(removed_in_version=2.9, type='bool'),
+    'auth_pass': dict(removed_in_version=2.9, no_log=True),
+    'timeout': dict(removed_in_version=2.9, type='int'),
+}
+dellos9_argument_spec.update(dellos9_top_spec)
+
+
+def get_provider_argspec():
+    return dellos9_provider_spec
+
+
+def get_connection(module):
+    if hasattr(module, '_dellos9_connection'):
+        return module._dellos9_connection
+
+    capabilities = get_capabilities(module)
+    network_api = capabilities.get('network_api')
+    if network_api == 'cliconf':
+        module._dellos9_connection = Connection(module._socket_path)
+    else:
+        module.fail_json(msg='Invalid connection type %s' % network_api)
+
+    return module._dellos9_connection
+
+
+def get_capabilities(module):
+    if hasattr(module, '_dellos9_capabilities'):
+        return module._dellos9_capabilities
+    try:
+        capabilities = Connection(module._socket_path).get_capabilities()
+    except ConnectionError as exc:
+        module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
+    module._dellos9_capabilities = json.loads(capabilities)
+    return module._dellos9_capabilities
+
+
+def check_args(module, warnings):
+    pass
+
+
+def get_config(module, flags=None):
+    flags = [] if flags is None else flags
+
+    cmd = 'show running-config '
+    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 run_commands(module, commands, check_rc=True):
+    connection = get_connection(module)
+    try:
+        return connection.run_commands(commands=commands, check_rc=check_rc)
+    except ConnectionError as exc:
+        module.fail_json(msg=to_text(exc))
+
+
+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'))
+
+    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
diff --git a/plugins/modules/__init__.py b/plugins/modules/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/plugins/modules/dellos9_command.py b/plugins/modules/dellos9_command.py
new file mode 100644
index 0000000..9b4d77f
--- /dev/null
+++ b/plugins/modules/dellos9_command.py
@@ -0,0 +1,239 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2015, Peter Sprygada <psprygada@ansible.com>
+# Copyright: (c) 2016, 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: dellos9_command
+author: "Dhivya P (@dhivyap)"
+short_description: Run commands on remote devices running Dell OS9
+description:
+  - Sends arbitrary commands to a Dell OS9 node 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(dellos9_config) to configure Dell OS9 devices.
+extends_documentation_fragment:
+- dellemc_networking.os9.dellos9
+
+options:
+  commands:
+    description:
+      - List of commands to send to the remote dellos9 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. If a command sent to the
+        device requires answering a prompt, it is possible to pass
+        a dict containing I(command), I(answer) and I(prompt).
+        Common answers are 'yes' or "\r" (carriage return, must be
+        double quotes). See examples.
+    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 retries, the task fails.
+        See examples.
+    type: list
+  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
+
+notes:
+  - This module requires Dell OS9 version 9.10.0.1P13 or above.
+
+  - This module requires to increase the ssh connection rate limit.
+    Use the following command I(ip ssh connection-rate-limit 60)
+    to configure the same. This can be done via M(dellos9_config) module
+    as well.
+
+'''
+
+EXAMPLES = """
+tasks:
+  - name: run show version on remote devices
+    dellos9_command:
+      commands: show version
+
+  - name: run show version and check to see if output contains OS9
+    dellos9_command:
+      commands: show version
+      wait_for: result[0] contains OS9
+
+  - name: run multiple commands on remote nodes
+    dellos9_command:
+      commands:
+        - show version
+        - show interfaces
+
+  - name: run multiple commands and evaluate the output
+    dellos9_command:
+      commands:
+        - show version
+        - show interfaces
+      wait_for:
+        - result[0] contains OS9
+        - result[1] contains Loopback
+
+  - name: run commands that require answering a prompt
+    dellos9_command:
+      commands:
+        - command: 'copy running-config startup-config'
+          prompt: '[confirm yes/no]: ?$'
+          answer: 'yes'
+"""
+
+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._text import to_text
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import Conditional
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import transform_commands, to_lines
+from ansible_collections.dellemc_networking.os9.plugins.module_utils.network.dellos9.dellos9 import run_commands
+from ansible_collections.dellemc_networking.os9.plugins.module_utils.network.dellos9.dellos9 import dellos9_argument_spec, check_args
+
+
+def parse_commands(module, warnings):
+    commands = transform_commands(module)
+
+    if module.check_mode:
+        for item in list(commands):
+            if not item['command'].startswith('show'):
+                warnings.append(
+                    'Only show commands are supported when using check mode, not '
+                    'executing %s' % item['command']
+                )
+                commands.remove(item)
+
+    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'),
+        match=dict(default='all', choices=['all', 'any']),
+
+        retries=dict(default=10, type='int'),
+        interval=dict(default=1, type='int')
+    )
+
+    argument_spec.update(dellos9_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()
+
+    try:
+        conditionals = [Conditional(c) for c in wait_for]
+    except AttributeError as exc:
+        module.fail_json(msg=to_text(exc))
+    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({
+        'stdout': responses,
+        'stdout_lines': list(to_lines(responses))
+    })
+
+    module.exit_json(**result)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/plugins/modules/dellos9_config.py b/plugins/modules/dellos9_config.py
new file mode 100644
index 0000000..16d92ef
--- /dev/null
+++ b/plugins/modules/dellos9_config.py
@@ -0,0 +1,346 @@
+#!/usr/bin/python
+#
+# (c) 2015 Peter Sprygada, <psprygada@ansible.com>
+# Copyright (c) 2016 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: dellos9_config
+author: "Dhivya P (@dhivyap)"
+short_description: Manage Dell EMC Networking OS9 configuration sections
+description:
+  - OS9 configurations use a simple block indent file syntax
+    for segmenting configuration into sections.  This module provides
+    an implementation for working with OS9 configuration sections in
+    a deterministic way.
+extends_documentation_fragment:
+- dellemc_networking.os9.dellos9
+
+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).
+    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.
+  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).
+  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.
+  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.
+  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.
+    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.
+    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.
+    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.
+  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 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>
+      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
+notes:
+  - This module requires Dell OS9 version 9.10.0.1P13 or above.
+
+  - This module requires to increase the ssh connection rate limit.
+    Use the following command I(ip ssh connection-rate-limit 60)
+    to configure the same. This can also be done with the
+    M(dellos9_config) module.
+'''
+
+EXAMPLES = """
+- dellos9_config:
+    lines: ['hostname {{ inventory_hostname }}']
+    provider: "{{ cli }}"
+
+- dellos9_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 extended test']
+    before: ['no ip access-list extended test']
+    match: exact
+
+- dellos9_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 extended test']
+    before: ['no ip access-list extended test']
+    replace: block
+
+- dellos9_config:
+    lines: ['hostname {{ inventory_hostname }}']
+    provider: "{{ cli }}"
+    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', 'bgp 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', 'bgp 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/dellos9_config.2016-07-16@22:28:34
+"""
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.dellemc_networking.os9.plugins.module_utils.network.dellos9.dellos9 import get_config, get_sublevel_config
+from ansible_collections.dellemc_networking.os9.plugins.module_utils.network.dellos9.dellos9 import dellos9_argument_spec, check_args
+from ansible_collections.dellemc_networking.os9.plugins.module_utils.network.dellos9.dellos9 import load_config, run_commands
+from ansible_collections.dellemc_networking.os9.plugins.module_utils.network.dellos9.dellos9 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(dellos9_argument_spec)
+
+    mutually_exclusive = [('lines', 'src'),
+                          ('parents', '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)
+
+    candidate = get_candidate(module)
+
+    if module.params['backup']:
+        if not module.check_mode:
+            result['__backup__'] = get_config(module)
+    commands = list()
+
+    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 = {'command': 'copy running-config startup-config',
+                   '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()
diff --git a/plugins/modules/dellos9_facts.py b/plugins/modules/dellos9_facts.py
new file mode 100644
index 0000000..98dea4c
--- /dev/null
+++ b/plugins/modules/dellos9_facts.py
@@ -0,0 +1,575 @@
+#!/usr/bin/python
+#
+# (c) 2015 Peter Sprygada, <psprygada@ansible.com>
+# Copyright (c) 2016 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: dellos9_facts
+author: "Dhivya P (@dhivyap)"
+short_description: Collect facts from remote devices running Dell EMC Networking OS9
+description:
+  - Collects a base set of device facts from a remote device that
+    is running OS9.  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_networking.os9.dellos9
+
+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.
+    default: [ '!config' ]
+notes:
+  - This module requires OS9 version 9.10.0.1P13 or above.
+
+  - This module requires an increase of the SSH connection rate limit.
+    Use the following command I(ip ssh connection-rate-limit 60)
+    to configure the same. This can be also be done with the M(dellos9_config) module.
+'''
+
+EXAMPLES = """
+# Collect all facts from the device
+- dellos9_facts:
+    gather_subset: all
+
+# Collect only the config and default facts
+- dellos9_facts:
+    gather_subset:
+      - config
+
+# Do not collect hardware facts
+- dellos9_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_model:
+  description: The model name returned from the device
+  returned: always
+  type: str
+ansible_net_serialnum:
+  description: The serial number of the remote device
+  returned: always
+  type: str
+ansible_net_version:
+  description: The operating system version running on the remote device
+  returned: always
+  type: str
+ansible_net_hostname:
+  description: The configured hostname of the device
+  returned: always
+  type: str
+ansible_net_image:
+  description: The image file the device is running
+  returned: always
+  type: str
+
+# hardware
+ansible_net_filesystems:
+  description: All file system names available on the device
+  returned: when hardware is configured
+  type: list
+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 itertools import izip
+except ImportError:
+    izip = zip
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.dellemc_networking.os9.plugins.module_utils.network.dellos9.dellos9 import run_commands
+from ansible_collections.dellemc_networking.os9.plugins.module_utils.network.dellos9.dellos9 import dellos9_argument_spec, check_args
+from ansible.module_utils.six import iteritems
+
+
+class FactsBase(object):
+
+    COMMANDS = list()
+
+    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',
+        'show inventory',
+        'show running-config | grep hostname'
+    ]
+
+    def populate(self):
+        super(Default, self).populate()
+        data = self.responses[0]
+        self.facts['version'] = self.parse_version(data)
+        self.facts['model'] = self.parse_model(data)
+        self.facts['image'] = self.parse_image(data)
+
+        data = self.responses[1]
+        self.facts['serialnum'] = self.parse_serialnum(data)
+
+        data = self.responses[2]
+        self.facts['hostname'] = self.parse_hostname(data)
+
+    def parse_version(self, data):
+        match = re.search(r'Software Version:\s*(.+)', data)
+        if match:
+            return match.group(1)
+
+    def parse_hostname(self, data):
+        match = re.search(r'^hostname (.+)', data, re.M)
+        if match:
+            return match.group(1)
+
+    def parse_model(self, data):
+        match = re.search(r'^System Type:\s*(.+)', data, re.M)
+        if match:
+            return match.group(1)
+
+    def parse_image(self, data):
+        match = re.search(r'image file is "(.+)"', data)
+        if match:
+            return match.group(1)
+
+    def parse_serialnum(self, data):
+        for line in data.split('\n'):
+            if line.startswith('*'):
+                match = re.search(
+                    r'\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)', line, re.M)
+                if match:
+                    return match.group(3)
+
+
+class Hardware(FactsBase):
+
+    COMMANDS = [
+        'show file-systems',
+        'show memory | except Processor'
+    ]
+
+    def populate(self):
+        super(Hardware, self).populate()
+        data = self.responses[0]
+        self.facts['filesystems'] = self.parse_filesystems(data)
+
+        data = self.responses[1]
+        match = re.findall(r'\s(\d+)\s', data)
+        if match:
+            self.facts['memtotal_mb'] = int(match[0]) // 1024
+            self.facts['memfree_mb'] = int(match[2]) // 1024
+
+    def parse_filesystems(self, data):
+        return re.findall(r'\s(\S+):$', 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 interfaces',
+        'show ipv6 interface',
+        'show lldp neighbors detail',
+        'show inventory'
+    ]
+
+    def populate(self):
+        super(Interfaces, self).populate()
+        self.facts['all_ipv4_addresses'] = list()
+        self.facts['all_ipv6_addresses'] = list()
+
+        data = self.responses[0]
+        interfaces = self.parse_interfaces(data)
+
+        for key in list(interfaces.keys()):
+            if "ManagementEthernet" in key:
+                temp_parsed = interfaces[key]
+                del interfaces[key]
+                interfaces.update(self.parse_mgmt_interfaces(temp_parsed))
+
+        for key in list(interfaces.keys()):
+            if "Vlan" in key:
+                temp_parsed = interfaces[key]
+                del interfaces[key]
+                interfaces.update(self.parse_vlan_interfaces(temp_parsed))
+
+        self.facts['interfaces'] = self.populate_interfaces(interfaces)
+
+        data = self.responses[1]
+        if len(data) > 0:
+            data = self.parse_ipv6_interfaces(data)
+            self.populate_ipv6_interfaces(data)
+
+        data = self.responses[3]
+        if 'LLDP' in self.get_protocol_list(data):
+            neighbors = self.responses[2]
+            self.facts['neighbors'] = self.parse_neighbors(neighbors)
+
+    def get_protocol_list(self, data):
+        start = False
+        protocol_list = list()
+        for line in data.split('\n'):
+            match = re.search(r'Software Protocol Configured\s*', line)
+            if match:
+                start = True
+                continue
+            if start:
+                line = line.strip()
+                if line.isalnum():
+                    protocol_list.append(line)
+        return protocol_list
+
+    def populate_interfaces(self, interfaces):
+        facts = dict()
+        for key, value in interfaces.items():
+            intf = dict()
+            intf['description'] = self.parse_description(value)
+            intf['macaddress'] = self.parse_macaddress(value)
+            ipv4 = self.parse_ipv4(value)
+            intf['ipv4'] = self.parse_ipv4(value)
+            if ipv4:
+                self.add_ip_address(ipv4['address'], 'ipv4')
+
+            intf['mtu'] = self.parse_mtu(value)
+            intf['bandwidth'] = self.parse_bandwidth(value)
+            intf['mediatype'] = self.parse_mediatype(value)
+            intf['duplex'] = self.parse_duplex(value)
+            intf['lineprotocol'] = self.parse_lineprotocol(value)
+            intf['operstatus'] = self.parse_operstatus(value)
+            intf['type'] = self.parse_type(value)
+
+            facts[key] = intf
+        return facts
+
+    def populate_ipv6_interfaces(self, data):
+        for key, value in data.items():
+            if key in self.facts['interfaces']:
+                self.facts['interfaces'][key]['ipv6'] = list()
+                addresses = re.findall(r'\s+(.+), subnet', value, re.M)
+                subnets = re.findall(r', subnet is (\S+)', value, re.M)
+                for addr, subnet in izip(addresses, subnets):
+                    ipv6 = dict(address=addr.strip(), subnet=subnet.strip())
+                    self.add_ip_address(addr.strip(), 'ipv6')
+                    self.facts['interfaces'][key]['ipv6'].append(ipv6)
+
+    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_neighbors(self, neighbors):
+        facts = dict()
+
+        for entry in neighbors.split(
+                '========================================================================'):
+            if entry == '':
+                continue
+
+            intf = self.parse_lldp_intf(entry)
+            if intf not in facts:
+                facts[intf] = list()
+            fact = dict()
+            fact['host'] = self.parse_lldp_host(entry)
+            fact['port'] = self.parse_lldp_port(entry)
+            facts[intf].append(fact)
+        return facts
+
+    def parse_interfaces(self, data):
+        parsed = dict()
+        newline_count = 0
+        interface_start = True
+
+        for line in data.split('\n'):
+            if interface_start:
+                newline_count = 0
+            if len(line) == 0:
+                newline_count += 1
+                if newline_count == 2:
+                    interface_start = True
+                continue
+            else:
+                match = re.match(r'^(\S+) (\S+)', line)
+                if match and interface_start:
+                    interface_start = False
+                    key = match.group(0)
+                    parsed[key] = line
+                else:
+                    parsed[key] += '\n%s' % line
+        return parsed
+
+    def parse_mgmt_interfaces(self, data):
+        parsed = dict()
+        interface_start = True
+        for line in data.split('\n'):
+            match = re.match(r'^(\S+) (\S+)', line)
+            if "Time since" in line:
+                interface_start = True
+                parsed[key] += '\n%s' % line
+                continue
+            elif match and interface_start:
+                interface_start = False
+                key = match.group(0)
+                parsed[key] = line
+            else:
+                parsed[key] += '\n%s' % line
+        return parsed
+
+    def parse_vlan_interfaces(self, data):
+        parsed = dict()
+        interface_start = True
+        line_before_end = False
+        for line in data.split('\n'):
+            match = re.match(r'^(\S+) (\S+)', line)
+            match_endline = re.match(r'^\s*\d+ packets, \d+ bytes$', line)
+
+            if "Output Statistics" in line:
+                line_before_end = True
+                parsed[key] += '\n%s' % line
+            elif match_endline and line_before_end:
+                line_before_end = False
+                interface_start = True
+                parsed[key] += '\n%s' % line
+            elif match and interface_start:
+                interface_start = False
+                key = match.group(0)
+                parsed[key] = line
+            else:
+                parsed[key] += '\n%s' % line
+        return parsed
+
+    def parse_ipv6_interfaces(self, data):
+        parsed = dict()
+        for line in data.split('\n'):
+            if len(line) == 0:
+                continue
+            elif line[0] == ' ':
+                parsed[key] += '\n%s' % line
+            else:
+                match = re.match(r'^(\S+) (\S+)', line)
+                if match:
+                    key = match.group(0)
+                    parsed[key] = line
+        return parsed
+
+    def parse_description(self, data):
+        match = re.search(r'Description: (.+)$', data, re.M)
+        if match:
+            return match.group(1)
+
+    def parse_macaddress(self, data):
+        match = re.search(r'address is (\S+)', data)
+        if match:
+            if match.group(1) != "not":
+                return match.group(1)
+
+    def parse_ipv4(self, data):
+        match = re.search(r'Internet address is (\S+)', data)
+        if match:
+            if match.group(1) != "not":
+                addr, masklen = match.group(1).split('/')
+                return dict(address=addr, masklen=int(masklen))
+
+    def parse_mtu(self, data):
+        match = re.search(r'MTU (\d+)', data)
+        if match:
+            return int(match.group(1))
+
+    def parse_bandwidth(self, data):
+        match = re.search(r'LineSpeed (\d+)', data)
+        if match:
+            return int(match.group(1))
+
+    def parse_duplex(self, data):
+        match = re.search(r'(\w+) duplex', data, re.M)
+        if match:
+            return match.group(1)
+
+    def parse_mediatype(self, data):
+        media = re.search(r'(.+) media present, (.+)', data, re.M)
+        if media:
+            match = re.search(r'type is (.+)$', media.group(0), re.M)
+            return match.group(1)
+
+    def parse_type(self, data):
+        match = re.search(r'Hardware is (.+),', data, re.M)
+        if match:
+            return match.group(1)
+
+    def parse_lineprotocol(self, data):
+        match = re.search(r'line protocol is (\w+[ ]?\w*)\(?.*\)?$', data, re.M)
+        if match:
+            return match.group(1)
+
+    def parse_operstatus(self, data):
+        match = re.search(r'^(?:.+) is (.+),', data, re.M)
+        if match:
+            return match.group(1)
+
+    def parse_lldp_intf(self, data):
+        match = re.search(r'^\sLocal Interface (\S+\s\S+)', data, re.M)
+        if match:
+            return match.group(1)
+
+    def parse_lldp_host(self, data):
+        match = re.search(r'Remote System Name: (.+)$', data, re.M)
+        if match:
+            return match.group(1)
+
+    def parse_lldp_port(self, data):
+        match = re.search(r'Remote Port ID: (.+)$', data, re.M)
+        if match:
+            return match.group(1)
+
+
+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(dellos9_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()
diff --git a/plugins/terminal/__init__.py b/plugins/terminal/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/plugins/terminal/dellos9.py b/plugins/terminal/dellos9.py
new file mode 100644
index 0000000..ceb20f8
--- /dev/null
+++ b/plugins/terminal/dellos9.py
@@ -0,0 +1,83 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# Copyright (c) 2017 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 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: (?:(?!\bdoes not exist\b)(?!\balready exists\b)(?!\bHost not found\b)(?!\bnot active\b).)*\n"),
+        re.compile(br"% ?Bad secret"),
+        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"'[^']' +returned error code: ?\d+"),
+    ]
+
+    terminal_initial_prompt = br"\[y/n\]:"
+
+    terminal_initial_answer = b"y"
+
+    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')
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644
index 0000000..ea1472e
--- /dev/null
+++ b/tests/.gitignore
@@ -0,0 +1 @@
+output/
diff --git a/tests/integration/targets/__init__.py b/tests/integration/targets/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/integration/targets/dellos9_command/defaults/main.yaml b/tests/integration/targets/dellos9_command/defaults/main.yaml
new file mode 100644
index 0000000..5f709c5
--- /dev/null
+++ b/tests/integration/targets/dellos9_command/defaults/main.yaml
@@ -0,0 +1,2 @@
+---
+testcase: "*"
diff --git a/tests/integration/targets/dellos9_command/tasks/cli.yaml b/tests/integration/targets/dellos9_command/tasks/cli.yaml
new file mode 100644
index 0000000..8c11e10
--- /dev/null
+++ b/tests/integration/targets/dellos9_command/tasks/cli.yaml
@@ -0,0 +1,16 @@
+---
+- name: collect all cli test cases
+  find:
+    paths: "{{ role_path }}/tests/cli"
+    patterns: "{{ testcase }}.yaml"
+  register: test_cases
+
+- name: set test_items
+  set_fact: 
+    test_items: "{{ test_cases.files | map(attribute='path') | list }}"
+
+- name: run test case
+  include: "{{ test_case_to_run }}"
+  with_items: "{{ test_items }}"
+  loop_control:
+    loop_var: test_case_to_run
diff --git a/tests/integration/targets/dellos9_command/tasks/main.yaml b/tests/integration/targets/dellos9_command/tasks/main.yaml
new file mode 100644
index 0000000..415c99d
--- /dev/null
+++ b/tests/integration/targets/dellos9_command/tasks/main.yaml
@@ -0,0 +1,2 @@
+---
+- { include: cli.yaml, tags: ['cli'] }
diff --git a/tests/integration/targets/dellos9_command/tests/cli/bad_operator.yaml b/tests/integration/targets/dellos9_command/tests/cli/bad_operator.yaml
new file mode 100644
index 0000000..0ec627f
--- /dev/null
+++ b/tests/integration/targets/dellos9_command/tests/cli/bad_operator.yaml
@@ -0,0 +1,20 @@
+---
+- debug: msg="START cli/bad_operator.yaml"
+
+- name: test bad operator
+  dellos9_command:
+    commands:
+      - show version
+      - show interfaces TenGigabitEthernet 0/0
+    wait_for:
+      - "result[0] contains 'Description : blah'"
+    provider: "{{ cli }}"
+  register: result
+  ignore_errors: yes
+
+- assert:
+    that:
+      - "result.failed == true"
+      - "result.msg is defined"
+
+- debug: msg="END cli/bad_operator.yaml"
diff --git a/tests/integration/targets/dellos9_command/tests/cli/contains.yaml b/tests/integration/targets/dellos9_command/tests/cli/contains.yaml
new file mode 100644
index 0000000..4082cdd
--- /dev/null
+++ b/tests/integration/targets/dellos9_command/tests/cli/contains.yaml
@@ -0,0 +1,20 @@
+---
+- debug: msg="START cli/contains.yaml"
+
+- name: test contains operator
+  dellos9_command:
+    commands:
+      - show version
+      - show interface TenGigabitEthernet 0/0
+    wait_for:
+      - "result[0] contains 2.0"
+      - "result[1] contains TenGigabitEthernet "
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+      - "result.stdout is defined"
+
+- debug: msg="END cli/contains.yaml"
diff --git a/tests/integration/targets/dellos9_command/tests/cli/invalid.yaml b/tests/integration/targets/dellos9_command/tests/cli/invalid.yaml
new file mode 100644
index 0000000..6e9e8e3
--- /dev/null
+++ b/tests/integration/targets/dellos9_command/tests/cli/invalid.yaml
@@ -0,0 +1,28 @@
+---
+- debug: msg="START cli/invalid.yaml"
+
+- name: run invalid command
+  dellos9_command:
+    commands: ['show foo']
+    provider: "{{ cli }}"
+  register: result
+  ignore_errors: yes
+
+- assert:
+    that:
+      - "result.failed"
+
+- name: run commands that include invalid command
+  dellos9_command:
+    commands:
+      - show version
+      - show foo
+    provider: "{{ cli }}"
+  register: result
+  ignore_errors: yes
+
+- assert:
+    that:
+      - "result.failed"
+
+- debug: msg="END cli/invalid.yaml"
diff --git a/tests/integration/targets/dellos9_command/tests/cli/output.yaml b/tests/integration/targets/dellos9_command/tests/cli/output.yaml
new file mode 100644
index 0000000..151c1b8
--- /dev/null
+++ b/tests/integration/targets/dellos9_command/tests/cli/output.yaml
@@ -0,0 +1,29 @@
+---
+- debug: msg="START cli/output.yaml"
+
+- name: get output for single command
+  dellos9_command:
+    commands: ['show version']
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+      - "result.stdout is defined"
+
+- name: get output for multiple commands
+  dellos9_command:
+    commands:
+      - show version
+      - show interfaces
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+      - "result.stdout is defined"
+      - "result.stdout | length == 2"
+
+- debug: msg="END cli/output.yaml"
diff --git a/tests/integration/targets/dellos9_command/tests/cli/timeout.yaml b/tests/integration/targets/dellos9_command/tests/cli/timeout.yaml
new file mode 100644
index 0000000..530ca67
--- /dev/null
+++ b/tests/integration/targets/dellos9_command/tests/cli/timeout.yaml
@@ -0,0 +1,19 @@
+---
+- debug: msg="START cli/timeout.yaml"
+
+- name: test bad condition
+  dellos9_command:
+    commands:
+      - show version
+    wait_for:
+      - "result[0] contains bad_value_string"
+    provider: "{{ cli }}"
+  register: result
+  ignore_errors: yes
+
+- assert:
+    that:
+      - "result.failed == true"
+      - "result.msg is defined"
+
+- debug: msg="END cli/timeout.yaml"
diff --git a/tests/integration/targets/dellos9_config/defaults/main.yaml b/tests/integration/targets/dellos9_config/defaults/main.yaml
new file mode 100644
index 0000000..5f709c5
--- /dev/null
+++ b/tests/integration/targets/dellos9_config/defaults/main.yaml
@@ -0,0 +1,2 @@
+---
+testcase: "*"
diff --git a/tests/integration/targets/dellos9_config/tasks/cli.yaml b/tests/integration/targets/dellos9_config/tasks/cli.yaml
new file mode 100644
index 0000000..d675462
--- /dev/null
+++ b/tests/integration/targets/dellos9_config/tasks/cli.yaml
@@ -0,0 +1,15 @@
+---
+- name: collect all cli test cases
+  find:
+    paths: "{{ role_path }}/tests/cli"
+    patterns: "{{ testcase }}.yaml"
+  register: test_cases
+
+- name: set test_items
+  set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
+
+- name: run test case
+  include: "{{ test_case_to_run }}"
+  with_items: "{{ test_items }}"
+  loop_control:
+    loop_var: test_case_to_run
diff --git a/tests/integration/targets/dellos9_config/tasks/main.yaml b/tests/integration/targets/dellos9_config/tasks/main.yaml
new file mode 100644
index 0000000..415c99d
--- /dev/null
+++ b/tests/integration/targets/dellos9_config/tasks/main.yaml
@@ -0,0 +1,2 @@
+---
+- { include: cli.yaml, tags: ['cli'] }
diff --git a/tests/integration/targets/dellos9_config/tests/cli/sublevel.yaml b/tests/integration/targets/dellos9_config/tests/cli/sublevel.yaml
new file mode 100644
index 0000000..b8e95d3
--- /dev/null
+++ b/tests/integration/targets/dellos9_config/tests/cli/sublevel.yaml
@@ -0,0 +1,43 @@
+---
+- debug: msg="START cli/sublevel.yaml"
+
+- name: setup test
+  dellos9_config:
+    lines:
+      - 'no ip access-list extended test'
+      - 'no ip access-list standard test'
+    provider: "{{ cli }}"
+    match: none
+
+- name: configure sub level command
+  dellos9_config:
+    lines: ['seq 5 permit ip any any log threshold-in-msgs 10 interval 5']
+    parents: ['ip access-list extended test']
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == true"
+      - "'ip access-list extended test' in result.updates"
+      - "'seq 5 permit ip any any log threshold-in-msgs 10 interval 5' in result.updates"
+
+- name: configure sub level command idempotent check
+  dellos9_config:
+    lines: ['seq 5 permit ip any any log threshold-in-msgs 10 interval 5']
+    parents: ['ip access-list extended test']
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+
+- name: teardown
+  dellos9_config:
+    lines:
+      - 'no ip access-list extended test'
+    provider: "{{ cli }}"
+    match: none
+
+- debug: msg="END cli/sublevel.yaml"
diff --git a/tests/integration/targets/dellos9_config/tests/cli/sublevel_block.yaml b/tests/integration/targets/dellos9_config/tests/cli/sublevel_block.yaml
new file mode 100644
index 0000000..f7b2983
--- /dev/null
+++ b/tests/integration/targets/dellos9_config/tests/cli/sublevel_block.yaml
@@ -0,0 +1,62 @@
+---
+- debug: msg="START cli/sublevel_block.yaml"
+
+- name: setup
+  dellos9_config:
+    lines:
+      - seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5
+      - seq 10 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5
+      - seq 15 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5
+    parents: ['ip access-list extended test']
+    before: ['no ip access-list extended test']
+    after: ['exit']
+    provider: "{{ cli }}"
+    match: none
+
+- name: configure sub level command using block replace
+  dellos9_config:
+    lines:
+      - seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5
+      - seq 10 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5
+      - seq 15 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5
+      - seq 20 permit ip host 192.0.2.4 any log threshold-in-msgs 10 interval 5
+    parents: ['ip access-list extended test']
+    replace: block
+    after: ['exit']
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == true"
+      - "'ip access-list extended test' in result.updates"
+      - "'seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5' in result.updates"
+      - "'seq 10 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5' in result.updates"
+      - "'seq 15 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5' in result.updates"
+      - "'seq 20 permit ip host 192.0.2.4 any log threshold-in-msgs 10 interval 5' in result.updates"
+
+- name: check sub level command using block replace
+  dellos9_config:
+    lines:
+      - seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5
+      - seq 10 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5
+      - seq 15 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5
+      - seq 20 permit ip host 192.0.2.4 any log threshold-in-msgs 10 interval 5
+    parents: ['ip access-list extended test']
+    replace: block
+    after: ['exit']
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+
+- name: teardown
+  dellos9_config:
+    lines:
+      - no ip access-list extended test
+    match: none
+    provider: "{{ cli }}"
+
+- debug: msg="END cli/sublevel_block.yaml"
diff --git a/tests/integration/targets/dellos9_config/tests/cli/sublevel_exact.yaml b/tests/integration/targets/dellos9_config/tests/cli/sublevel_exact.yaml
new file mode 100644
index 0000000..9c80d3f
--- /dev/null
+++ b/tests/integration/targets/dellos9_config/tests/cli/sublevel_exact.yaml
@@ -0,0 +1,66 @@
+---
+- debug: msg="START cli/sublevel_exact.yaml"
+
+- name: setup
+  dellos9_config:
+    lines:
+      - seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5
+      - seq 10 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5
+      - seq 15 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5
+      - seq 20 permit ip host 192.0.2.4 any log threshold-in-msgs 10 interval 5
+      - seq 25 permit ip host 192.0.2.5 any log threshold-in-msgs 10 interval 5
+    parents: ['ip access-list extended test']
+    before: ['no ip access-list extended test']
+    after: ['exit']
+    provider: "{{ cli }}"
+    match: none
+
+- name: configure sub level command using exact match
+  dellos9_config:
+    lines:
+      - seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5
+      - seq 10 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5
+      - seq 15 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5
+      - seq 20 permit ip host 192.0.2.4 any log threshold-in-msgs 10 interval 5
+    parents: ['ip access-list extended test']
+    after: ['exit']
+    match: exact
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == true"
+      - "'ip access-list extended test' in result.updates"
+      - "'seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5' in result.updates"
+      - "'seq 10 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5' in result.updates"
+      - "'seq 15 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5' in result.updates"
+      - "'seq 20 permit ip host 192.0.2.4 any log threshold-in-msgs 10 interval 5' in result.updates"
+      - "'seq 25 permit ip host 192.0.2.5 any log threshold-in-msgs 10 interval 5' not in result.updates"
+
+- name: check sub level command using exact match
+  dellos9_config:
+    lines:
+      - seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5
+      - seq 10 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5
+      - seq 15 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5
+      - seq 20 permit ip host 192.0.2.4 any log threshold-in-msgs 10 interval 5
+      - seq 25 permit ip host 192.0.2.5 any log threshold-in-msgs 10 interval 5
+    parents: ['ip access-list extended test']
+    after: ['exit']
+    match: exact
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+
+- name: teardown
+  dellos9_config:
+    lines:
+      - no ip access-list extended test
+    provider: "{{ cli }}"
+    match: none
+
+- debug: msg="END cli/sublevel_exact.yaml"
diff --git a/tests/integration/targets/dellos9_config/tests/cli/sublevel_strict.yaml b/tests/integration/targets/dellos9_config/tests/cli/sublevel_strict.yaml
new file mode 100644
index 0000000..3cca5ef
--- /dev/null
+++ b/tests/integration/targets/dellos9_config/tests/cli/sublevel_strict.yaml
@@ -0,0 +1,63 @@
+---
+- debug: msg="START cli/sublevel_strict.yaml"
+
+- name: setup
+  dellos9_config:
+    lines:
+      - seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5
+      - seq 10 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5
+      - seq 15 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5
+      - seq 20 permit ip host 192.0.2.4 any log threshold-in-msgs 10 interval 5
+      - seq 25 permit ip host 192.0.2.5 any log threshold-in-msgs 10 interval 5
+    parents: ['ip access-list extended test']
+    before: ['no ip access-list extended test']
+    after: ['exit']
+    provider: "{{ cli }}"
+    match: none
+
+- name: configure sub level command using strict match
+  dellos9_config:
+    lines:
+      - seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5
+      - seq 10 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5
+      - seq 15 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5
+      - seq 20 permit ip host 192.0.2.4 any log threshold-in-msgs 10 interval 5
+    parents: ['ip access-list extended test']
+    match: strict
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+
+- name: check sub level command using strict match
+  dellos9_config:
+    lines:
+      - seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5
+      - seq 10 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5
+      - seq 15 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5
+    parents: ['ip access-list extended test']
+    after: ['exit']
+    match: strict
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == true"
+      - "'ip access-list extended test' in result.updates"
+      - "'seq 5 permit ip host 192.0.2.1 any log threshold-in-msgs 10 interval 5' not in result.updates"
+      - "'seq 15 permit ip host 192.0.2.2 any log threshold-in-msgs 10 interval 5' in result.updates"
+      - "'seq 10 permit ip host 192.0.2.3 any log threshold-in-msgs 10 interval 5' in result.updates"
+      - "'seq 20 permit ip host 192.0.2.4 any log threshold-in-msgs 10 interval 5' not in result.updates"
+      - "'seq 25 permit ip host 192.0.2.5 any log threshold-in-msgs 10 interval 5' not in result.updates"
+
+- name: teardown
+  dellos9_config:
+    lines:
+      - no ip access-list extended test
+    provider: "{{ cli }}"
+    match: none
+
+- debug: msg="END cli/sublevel_strict.yaml"
diff --git a/tests/integration/targets/dellos9_config/tests/cli/toplevel.yaml b/tests/integration/targets/dellos9_config/tests/cli/toplevel.yaml
new file mode 100644
index 0000000..22669a4
--- /dev/null
+++ b/tests/integration/targets/dellos9_config/tests/cli/toplevel.yaml
@@ -0,0 +1,37 @@
+---
+- debug: msg="START cli/toplevel.yaml"
+
+- name: setup
+  dellos9_config:
+    lines: ['hostname {{ inventory_hostname_short }}']
+    provider: "{{ cli }}"
+    match: none
+
+- name: configure top level command
+  dellos9_config:
+    lines: ['hostname foo']
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == true"
+      - "'hostname foo' in result.updates"
+
+- name: configure top level command idempotent check
+  dellos9_config:
+    lines: ['hostname foo']
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+
+- name: teardown
+  dellos9_config:
+    lines: ['hostname {{ inventory_hostname_short }}']
+    provider: "{{ cli }}"
+    match: none
+
+- debug: msg="END cli/toplevel.yaml"
diff --git a/tests/integration/targets/dellos9_config/tests/cli/toplevel_after.yaml b/tests/integration/targets/dellos9_config/tests/cli/toplevel_after.yaml
new file mode 100644
index 0000000..6b5ee8e
--- /dev/null
+++ b/tests/integration/targets/dellos9_config/tests/cli/toplevel_after.yaml
@@ -0,0 +1,44 @@
+---
+- debug: msg="START cli/toplevel_after.yaml"
+
+- name: setup
+  dellos9_config:
+    lines:
+      - "snmp-server contact ansible"
+      - "hostname {{ inventory_hostname_short }}"
+    provider: "{{ cli }}"
+    match: none
+
+- name: configure top level command with after
+  dellos9_config:
+    lines: ['hostname foo']
+    after: ['snmp-server contact bar']
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == true"
+      - "'hostname foo' in result.updates"
+      - "'snmp-server contact bar' in result.updates"
+
+- name: configure top level command with after idempotent check
+  dellos9_config:
+    lines: ['hostname foo']
+    after: ['snmp-server contact bar']
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+
+- name: teardown
+  dellos9_config:
+    lines:
+      - "no snmp-server contact"
+      - "hostname {{ inventory_hostname_short }}"
+    provider: "{{ cli }}"
+    match: none
+
+- debug: msg="END cli/toplevel_after.yaml"
diff --git a/tests/integration/targets/dellos9_config/tests/cli/toplevel_before.yaml b/tests/integration/targets/dellos9_config/tests/cli/toplevel_before.yaml
new file mode 100644
index 0000000..79b01e4
--- /dev/null
+++ b/tests/integration/targets/dellos9_config/tests/cli/toplevel_before.yaml
@@ -0,0 +1,44 @@
+---
+- debug: msg="START cli/toplevel_before.yaml"
+
+- name: setup
+  dellos9_config:
+    lines:
+      - "snmp-server contact ansible"
+      - "hostname {{ inventory_hostname_short }}"
+    provider: "{{ cli }}"
+    match: none
+
+- name: configure top level command with before
+  dellos9_config:
+    lines: ['hostname foo']
+    before: ['snmp-server contact bar']
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == true"
+      - "'hostname foo' in result.updates"
+      - "'snmp-server contact bar' in result.updates"
+
+- name: configure top level command with before idempotent check
+  dellos9_config:
+    lines: ['hostname foo']
+    before: ['snmp-server contact bar']
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+
+- name: teardown
+  dellos9_config:
+    lines:
+      - "no snmp-server contact"
+      - "hostname {{ inventory_hostname_short }}"
+    provider: "{{ cli }}"
+    match: none
+
+- debug: msg="END cli/toplevel_before.yaml"
diff --git a/tests/integration/targets/dellos9_config/tests/cli/toplevel_nonidempotent.yaml b/tests/integration/targets/dellos9_config/tests/cli/toplevel_nonidempotent.yaml
new file mode 100644
index 0000000..142d5d7
--- /dev/null
+++ b/tests/integration/targets/dellos9_config/tests/cli/toplevel_nonidempotent.yaml
@@ -0,0 +1,39 @@
+---
+- debug: msg="START cli/toplevel_nonidempotent.yaml"
+
+- name: setup
+  dellos9_config:
+    lines: ['hostname {{ inventory_hostname_short }}']
+    provider: "{{ cli }}"
+    match: none
+
+- name: configure top level command
+  dellos9_config:
+    lines: ['hostname foo']
+    provider: "{{ cli }}"
+    match: strict
+  register: result
+
+- assert:
+    that:
+      - "result.changed == true"
+      - "'hostname foo' in result.updates"
+
+- name: configure top level command idempotent check
+  dellos9_config:
+    lines: ['hostname foo']
+    provider: "{{ cli }}"
+    match: strict
+  register: result
+
+- assert:
+    that:
+      - "result.changed == true"
+
+- name: teardown
+  dellos9_config:
+    lines: ['hostname {{ inventory_hostname_short }}']
+    provider: "{{ cli }}"
+    match: none
+
+- debug: msg="END cli/toplevel_nonidempotent.yaml"
diff --git a/tests/integration/targets/dellos9_facts/defaults/main.yaml b/tests/integration/targets/dellos9_facts/defaults/main.yaml
new file mode 100644
index 0000000..5f709c5
--- /dev/null
+++ b/tests/integration/targets/dellos9_facts/defaults/main.yaml
@@ -0,0 +1,2 @@
+---
+testcase: "*"
diff --git a/tests/integration/targets/dellos9_facts/tasks/cli.yaml b/tests/integration/targets/dellos9_facts/tasks/cli.yaml
new file mode 100644
index 0000000..8c11e10
--- /dev/null
+++ b/tests/integration/targets/dellos9_facts/tasks/cli.yaml
@@ -0,0 +1,16 @@
+---
+- name: collect all cli test cases
+  find:
+    paths: "{{ role_path }}/tests/cli"
+    patterns: "{{ testcase }}.yaml"
+  register: test_cases
+
+- name: set test_items
+  set_fact: 
+    test_items: "{{ test_cases.files | map(attribute='path') | list }}"
+
+- name: run test case
+  include: "{{ test_case_to_run }}"
+  with_items: "{{ test_items }}"
+  loop_control:
+    loop_var: test_case_to_run
diff --git a/tests/integration/targets/dellos9_facts/tasks/main.yaml b/tests/integration/targets/dellos9_facts/tasks/main.yaml
new file mode 100644
index 0000000..415c99d
--- /dev/null
+++ b/tests/integration/targets/dellos9_facts/tasks/main.yaml
@@ -0,0 +1,2 @@
+---
+- { include: cli.yaml, tags: ['cli'] }
diff --git a/tests/integration/targets/dellos9_facts/tests/cli/facts.yaml b/tests/integration/targets/dellos9_facts/tests/cli/facts.yaml
new file mode 100644
index 0000000..acea51c
--- /dev/null
+++ b/tests/integration/targets/dellos9_facts/tests/cli/facts.yaml
@@ -0,0 +1,42 @@
+---
+- debug: msg="START cli/facts.yaml"
+
+- name: test all facts
+  dellos9_facts:
+    gather_subset:
+      - all
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+      - "result.ansible_facts is defined"
+
+- name: test all facts except hardware
+  dellos9_facts:
+    gather_subset:
+      - "!hardware"
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+      - "result.ansible_facts.ansible_net_filesystems is not defined"
+
+- name: test interface facts
+  dellos9_facts:
+    gather_subset:
+      - interfaces
+    provider: "{{ cli }}"
+  register: result
+
+- assert:
+    that:
+      - "result.changed == false"
+      - "result.ansible_facts.ansible_net_interfaces is defined"
+      - "result.ansible_facts.ansible_net_filesystems is not defined"
+
+
+- debug: msg="END cli/facts.yaml"
diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt
new file mode 100644
index 0000000..03b3631
--- /dev/null
+++ b/tests/sanity/ignore-2.10.txt
@@ -0,0 +1,31 @@
+plugins/module_utils/network/dellos9/dellos9.py future-import-boilerplate
+plugins/module_utils/network/dellos9/dellos9.py metaclass-boilerplate
+plugins/modules/dellos9_command.py validate-modules:doc-default-does-not-match-spec
+plugins/modules/dellos9_command.py validate-modules:doc-missing-type
+plugins/modules/dellos9_command.py validate-modules:doc-required-mismatch
+plugins/modules/dellos9_command.py validate-modules:parameter-list-no-elements
+plugins/modules/dellos9_command.py validate-modules:parameter-type-not-in-doc
+plugins/modules/dellos9_command.py validate-modules:undocumented-parameter
+plugins/modules/dellos9_config.py validate-modules:doc-default-does-not-match-spec
+plugins/modules/dellos9_config.py validate-modules:doc-missing-type
+plugins/modules/dellos9_config.py validate-modules:doc-required-mismatch
+plugins/modules/dellos9_config.py validate-modules:parameter-list-no-elements
+plugins/modules/dellos9_config.py validate-modules:parameter-type-not-in-doc
+plugins/modules/dellos9_config.py validate-modules:undocumented-parameter
+plugins/modules/dellos9_facts.py validate-modules:doc-default-does-not-match-spec
+plugins/modules/dellos9_facts.py validate-modules:doc-missing-type
+plugins/modules/dellos9_facts.py validate-modules:doc-required-mismatch
+plugins/modules/dellos9_facts.py validate-modules:parameter-list-no-elements
+plugins/modules/dellos9_facts.py validate-modules:parameter-type-not-in-doc
+plugins/modules/dellos9_facts.py validate-modules:undocumented-parameter
+plugins/action/dellos9.py action-plugin-docs # base class for deprecated network platform modules using `connection: local`
+plugins/doc_fragments/dellos9.py future-import-boilerplate
+plugins/doc_fragments/dellos9.py metaclass-boilerplate
+tests/unit/mock/path.py future-import-boilerplate
+tests/unit/mock/path.py metaclass-boilerplate
+tests/unit/mock/yaml_helper.py future-import-boilerplate
+tests/unit/mock/yaml_helper.py metaclass-boilerplate
+tests/unit/modules/conftest.py future-import-boilerplate
+tests/unit/modules/conftest.py metaclass-boilerplate
+tests/unit/modules/utils.py future-import-boilerplate
+tests/unit/modules/utils.py metaclass-boilerplate
\ No newline at end of file
diff --git a/tests/sanity/ignore-2.9.txt b/tests/sanity/ignore-2.9.txt
new file mode 100644
index 0000000..03b3631
--- /dev/null
+++ b/tests/sanity/ignore-2.9.txt
@@ -0,0 +1,31 @@
+plugins/module_utils/network/dellos9/dellos9.py future-import-boilerplate
+plugins/module_utils/network/dellos9/dellos9.py metaclass-boilerplate
+plugins/modules/dellos9_command.py validate-modules:doc-default-does-not-match-spec
+plugins/modules/dellos9_command.py validate-modules:doc-missing-type
+plugins/modules/dellos9_command.py validate-modules:doc-required-mismatch
+plugins/modules/dellos9_command.py validate-modules:parameter-list-no-elements
+plugins/modules/dellos9_command.py validate-modules:parameter-type-not-in-doc
+plugins/modules/dellos9_command.py validate-modules:undocumented-parameter
+plugins/modules/dellos9_config.py validate-modules:doc-default-does-not-match-spec
+plugins/modules/dellos9_config.py validate-modules:doc-missing-type
+plugins/modules/dellos9_config.py validate-modules:doc-required-mismatch
+plugins/modules/dellos9_config.py validate-modules:parameter-list-no-elements
+plugins/modules/dellos9_config.py validate-modules:parameter-type-not-in-doc
+plugins/modules/dellos9_config.py validate-modules:undocumented-parameter
+plugins/modules/dellos9_facts.py validate-modules:doc-default-does-not-match-spec
+plugins/modules/dellos9_facts.py validate-modules:doc-missing-type
+plugins/modules/dellos9_facts.py validate-modules:doc-required-mismatch
+plugins/modules/dellos9_facts.py validate-modules:parameter-list-no-elements
+plugins/modules/dellos9_facts.py validate-modules:parameter-type-not-in-doc
+plugins/modules/dellos9_facts.py validate-modules:undocumented-parameter
+plugins/action/dellos9.py action-plugin-docs # base class for deprecated network platform modules using `connection: local`
+plugins/doc_fragments/dellos9.py future-import-boilerplate
+plugins/doc_fragments/dellos9.py metaclass-boilerplate
+tests/unit/mock/path.py future-import-boilerplate
+tests/unit/mock/path.py metaclass-boilerplate
+tests/unit/mock/yaml_helper.py future-import-boilerplate
+tests/unit/mock/yaml_helper.py metaclass-boilerplate
+tests/unit/modules/conftest.py future-import-boilerplate
+tests/unit/modules/conftest.py metaclass-boilerplate
+tests/unit/modules/utils.py future-import-boilerplate
+tests/unit/modules/utils.py metaclass-boilerplate
\ No newline at end of file
diff --git a/tests/sanity/requirements.txt b/tests/sanity/requirements.txt
new file mode 100644
index 0000000..3e3a966
--- /dev/null
+++ b/tests/sanity/requirements.txt
@@ -0,0 +1,4 @@
+packaging  # needed for update-bundled and changelog
+sphinx ; python_version >= '3.5' # docs build requires python 3+
+sphinx-notfound-page ; python_version >= '3.5' # docs build requires python 3+
+straight.plugin ; python_version >= '3.5' # needed for hacking/build-ansible.py which will host changelog generation and requires python 3+
diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/unit/compat/__init__.py b/tests/unit/compat/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/unit/compat/builtins.py b/tests/unit/compat/builtins.py
new file mode 100644
index 0000000..f60ee67
--- /dev/null
+++ b/tests/unit/compat/builtins.py
@@ -0,0 +1,33 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# 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/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+#
+# Compat for python2.7
+#
+
+# One unittest needs to import builtins via __import__() so we need to have
+# the string that represents it
+try:
+    import __builtin__
+except ImportError:
+    BUILTINS = 'builtins'
+else:
+    BUILTINS = '__builtin__'
diff --git a/tests/unit/compat/mock.py b/tests/unit/compat/mock.py
new file mode 100644
index 0000000..0972cd2
--- /dev/null
+++ b/tests/unit/compat/mock.py
@@ -0,0 +1,122 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# 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/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+'''
+Compat module for Python3.x's unittest.mock module
+'''
+import sys
+
+# Python 2.7
+
+# Note: Could use the pypi mock library on python3.x as well as python2.x.  It
+# is the same as the python3 stdlib mock library
+
+try:
+    # Allow wildcard import because we really do want to import all of mock's
+    # symbols into this compat shim
+    # pylint: disable=wildcard-import,unused-wildcard-import
+    from unittest.mock import *
+except ImportError:
+    # Python 2
+    # pylint: disable=wildcard-import,unused-wildcard-import
+    try:
+        from mock import *
+    except ImportError:
+        print('You need the mock library installed on python2.x to run tests')
+
+
+# Prior to 3.4.4, mock_open cannot handle binary read_data
+if sys.version_info >= (3,) and sys.version_info < (3, 4, 4):
+    file_spec = None
+
+    def _iterate_read_data(read_data):
+        # Helper for mock_open:
+        # Retrieve lines from read_data via a generator so that separate calls to
+        # readline, read, and readlines are properly interleaved
+        sep = b'\n' if isinstance(read_data, bytes) else '\n'
+        data_as_list = [l + sep for l in read_data.split(sep)]
+
+        if data_as_list[-1] == sep:
+            # If the last line ended in a newline, the list comprehension will have an
+            # extra entry that's just a newline.  Remove this.
+            data_as_list = data_as_list[:-1]
+        else:
+            # If there wasn't an extra newline by itself, then the file being
+            # emulated doesn't have a newline to end the last line  remove the
+            # newline that our naive format() added
+            data_as_list[-1] = data_as_list[-1][:-1]
+
+        for line in data_as_list:
+            yield line
+
+    def mock_open(mock=None, read_data=''):
+        """
+        A helper function to create a mock to replace the use of `open`. It works
+        for `open` called directly or used as a context manager.
+
+        The `mock` argument is the mock object to configure. If `None` (the
+        default) then a `MagicMock` will be created for you, with the API limited
+        to methods or attributes available on standard file handles.
+
+        `read_data` is a string for the `read` methoddline`, and `readlines` of the
+        file handle to return.  This is an empty string by default.
+        """
+        def _readlines_side_effect(*args, **kwargs):
+            if handle.readlines.return_value is not None:
+                return handle.readlines.return_value
+            return list(_data)
+
+        def _read_side_effect(*args, **kwargs):
+            if handle.read.return_value is not None:
+                return handle.read.return_value
+            return type(read_data)().join(_data)
+
+        def _readline_side_effect():
+            if handle.readline.return_value is not None:
+                while True:
+                    yield handle.readline.return_value
+            for line in _data:
+                yield line
+
+        global file_spec
+        if file_spec is None:
+            import _io
+            file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))))
+
+        if mock is None:
+            mock = MagicMock(name='open', spec=open)
+
+        handle = MagicMock(spec=file_spec)
+        handle.__enter__.return_value = handle
+
+        _data = _iterate_read_data(read_data)
+
+        handle.write.return_value = None
+        handle.read.return_value = None
+        handle.readline.return_value = None
+        handle.readlines.return_value = None
+
+        handle.read.side_effect = _read_side_effect
+        handle.readline.side_effect = _readline_side_effect()
+        handle.readlines.side_effect = _readlines_side_effect
+
+        mock.return_value = handle
+        return mock
diff --git a/tests/unit/compat/unittest.py b/tests/unit/compat/unittest.py
new file mode 100644
index 0000000..98f08ad
--- /dev/null
+++ b/tests/unit/compat/unittest.py
@@ -0,0 +1,38 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# 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/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+'''
+Compat module for Python2.7's unittest module
+'''
+
+import sys
+
+# Allow wildcard import because we really do want to import all of
+# unittests's symbols into this compat shim
+# pylint: disable=wildcard-import,unused-wildcard-import
+if sys.version_info < (2, 7):
+    try:
+        # Need unittest2 on python2.6
+        from unittest2 import *
+    except ImportError:
+        print('You need unittest2 installed on python2.6.x to run tests')
+else:
+    from unittest import *
diff --git a/tests/unit/mock/__init__.py b/tests/unit/mock/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/unit/mock/loader.py b/tests/unit/mock/loader.py
new file mode 100644
index 0000000..0ee47fb
--- /dev/null
+++ b/tests/unit/mock/loader.py
@@ -0,0 +1,116 @@
+# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
+#
+# 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/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+
+from ansible.errors import AnsibleParserError
+from ansible.parsing.dataloader import DataLoader
+from ansible.module_utils._text import to_bytes, to_text
+
+
+class DictDataLoader(DataLoader):
+
+    def __init__(self, file_mapping=None):
+        file_mapping = {} if file_mapping is None else file_mapping
+        assert type(file_mapping) == dict
+
+        super(DictDataLoader, self).__init__()
+
+        self._file_mapping = file_mapping
+        self._build_known_directories()
+        self._vault_secrets = None
+
+    def load_from_file(self, path, cache=True, unsafe=False):
+        path = to_text(path)
+        if path in self._file_mapping:
+            return self.load(self._file_mapping[path], path)
+        return None
+
+    # TODO: the real _get_file_contents returns a bytestring, so we actually convert the
+    #       unicode/text it's created with to utf-8
+    def _get_file_contents(self, path):
+        path = to_text(path)
+        if path in self._file_mapping:
+            return (to_bytes(self._file_mapping[path]), False)
+        else:
+            raise AnsibleParserError("file not found: %s" % path)
+
+    def path_exists(self, path):
+        path = to_text(path)
+        return path in self._file_mapping or path in self._known_directories
+
+    def is_file(self, path):
+        path = to_text(path)
+        return path in self._file_mapping
+
+    def is_directory(self, path):
+        path = to_text(path)
+        return path in self._known_directories
+
+    def list_directory(self, path):
+        ret = []
+        path = to_text(path)
+        for x in (list(self._file_mapping.keys()) + self._known_directories):
+            if x.startswith(path):
+                if os.path.dirname(x) == path:
+                    ret.append(os.path.basename(x))
+        return ret
+
+    def is_executable(self, path):
+        # FIXME: figure out a way to make paths return true for this
+        return False
+
+    def _add_known_directory(self, directory):
+        if directory not in self._known_directories:
+            self._known_directories.append(directory)
+
+    def _build_known_directories(self):
+        self._known_directories = []
+        for path in self._file_mapping:
+            dirname = os.path.dirname(path)
+            while dirname not in ('/', ''):
+                self._add_known_directory(dirname)
+                dirname = os.path.dirname(dirname)
+
+    def push(self, path, content):
+        rebuild_dirs = False
+        if path not in self._file_mapping:
+            rebuild_dirs = True
+
+        self._file_mapping[path] = content
+
+        if rebuild_dirs:
+            self._build_known_directories()
+
+    def pop(self, path):
+        if path in self._file_mapping:
+            del self._file_mapping[path]
+            self._build_known_directories()
+
+    def clear(self):
+        self._file_mapping = dict()
+        self._known_directories = []
+
+    def get_basedir(self):
+        return os.getcwd()
+
+    def set_vault_secrets(self, vault_secrets):
+        self._vault_secrets = vault_secrets
diff --git a/tests/unit/mock/path.py b/tests/unit/mock/path.py
new file mode 100644
index 0000000..ebe2760
--- /dev/null
+++ b/tests/unit/mock/path.py
@@ -0,0 +1,5 @@
+from ansible_collections.dellemc_networking.os9.tests.unit.compat.mock import MagicMock
+from ansible.utils.path import unfrackpath
+
+
+mock_unfrackpath_noop = MagicMock(spec_set=unfrackpath, side_effect=lambda x, *args, **kwargs: x)
diff --git a/tests/unit/mock/procenv.py b/tests/unit/mock/procenv.py
new file mode 100644
index 0000000..d5ff79f
--- /dev/null
+++ b/tests/unit/mock/procenv.py
@@ -0,0 +1,90 @@
+# (c) 2016, Matt Davis <mdavis@ansible.com>
+# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# 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/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import sys
+import json
+
+from contextlib import contextmanager
+from io import BytesIO, StringIO
+from ansible_collections.dellemc_networking.os9.tests.unit.compat import unittest
+from ansible.module_utils.six import PY3
+from ansible.module_utils._text import to_bytes
+
+
+@contextmanager
+def swap_stdin_and_argv(stdin_data='', argv_data=tuple()):
+    """
+    context manager that temporarily masks the test runner's values for stdin and argv
+    """
+    real_stdin = sys.stdin
+    real_argv = sys.argv
+
+    if PY3:
+        fake_stream = StringIO(stdin_data)
+        fake_stream.buffer = BytesIO(to_bytes(stdin_data))
+    else:
+        fake_stream = BytesIO(to_bytes(stdin_data))
+
+    try:
+        sys.stdin = fake_stream
+        sys.argv = argv_data
+
+        yield
+    finally:
+        sys.stdin = real_stdin
+        sys.argv = real_argv
+
+
+@contextmanager
+def swap_stdout():
+    """
+    context manager that temporarily replaces stdout for tests that need to verify output
+    """
+    old_stdout = sys.stdout
+
+    if PY3:
+        fake_stream = StringIO()
+    else:
+        fake_stream = BytesIO()
+
+    try:
+        sys.stdout = fake_stream
+
+        yield fake_stream
+    finally:
+        sys.stdout = old_stdout
+
+
+class ModuleTestCase(unittest.TestCase):
+    def setUp(self, module_args=None):
+        if module_args is None:
+            module_args = {'_ansible_remote_tmp': '/tmp', '_ansible_keep_remote_files': False}
+
+        args = json.dumps(dict(ANSIBLE_MODULE_ARGS=module_args))
+
+        # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
+        self.stdin_swap = swap_stdin_and_argv(stdin_data=args)
+        self.stdin_swap.__enter__()
+
+    def tearDown(self):
+        # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
+        self.stdin_swap.__exit__(None, None, None)
diff --git a/tests/unit/mock/vault_helper.py b/tests/unit/mock/vault_helper.py
new file mode 100644
index 0000000..dcce9c7
--- /dev/null
+++ b/tests/unit/mock/vault_helper.py
@@ -0,0 +1,39 @@
+# 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/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible.module_utils._text import to_bytes
+
+from ansible.parsing.vault import VaultSecret
+
+
+class TextVaultSecret(VaultSecret):
+    '''A secret piece of text. ie, a password. Tracks text encoding.
+
+    The text encoding of the text may not be the default text encoding so
+    we keep track of the encoding so we encode it to the same bytes.'''
+
+    def __init__(self, text, encoding=None, errors=None, _bytes=None):
+        super(TextVaultSecret, self).__init__()
+        self.text = text
+        self.encoding = encoding or 'utf-8'
+        self._bytes = _bytes
+        self.errors = errors or 'strict'
+
+    @property
+    def bytes(self):
+        '''The text encoded with encoding, unless we specifically set _bytes.'''
+        return self._bytes or to_bytes(self.text, encoding=self.encoding, errors=self.errors)
diff --git a/tests/unit/mock/yaml_helper.py b/tests/unit/mock/yaml_helper.py
new file mode 100644
index 0000000..cc095fe
--- /dev/null
+++ b/tests/unit/mock/yaml_helper.py
@@ -0,0 +1,121 @@
+import io
+import yaml
+
+from ansible.module_utils.six import PY3
+from ansible.parsing.yaml.loader import AnsibleLoader
+from ansible.parsing.yaml.dumper import AnsibleDumper
+
+
+class YamlTestUtils(object):
+    """Mixin class to combine with a unittest.TestCase subclass."""
+    def _loader(self, stream):
+        """Vault related tests will want to override this.
+
+        Vault cases should setup a AnsibleLoader that has the vault password."""
+        return AnsibleLoader(stream)
+
+    def _dump_stream(self, obj, stream, dumper=None):
+        """Dump to a py2-unicode or py3-string stream."""
+        if PY3:
+            return yaml.dump(obj, stream, Dumper=dumper)
+        else:
+            return yaml.dump(obj, stream, Dumper=dumper, encoding=None)
+
+    def _dump_string(self, obj, dumper=None):
+        """Dump to a py2-unicode or py3-string"""
+        if PY3:
+            return yaml.dump(obj, Dumper=dumper)
+        else:
+            return yaml.dump(obj, Dumper=dumper, encoding=None)
+
+    def _dump_load_cycle(self, obj):
+        # Each pass though a dump or load revs the 'generation'
+        # obj to yaml string
+        string_from_object_dump = self._dump_string(obj, dumper=AnsibleDumper)
+
+        # wrap a stream/file like StringIO around that yaml
+        stream_from_object_dump = io.StringIO(string_from_object_dump)
+        loader = self._loader(stream_from_object_dump)
+        # load the yaml stream to create a new instance of the object (gen 2)
+        obj_2 = loader.get_data()
+
+        # dump the gen 2 objects directory to strings
+        string_from_object_dump_2 = self._dump_string(obj_2,
+                                                      dumper=AnsibleDumper)
+
+        # The gen 1 and gen 2 yaml strings
+        self.assertEqual(string_from_object_dump, string_from_object_dump_2)
+        # the gen 1 (orig) and gen 2 py object
+        self.assertEqual(obj, obj_2)
+
+        # again! gen 3... load strings into py objects
+        stream_3 = io.StringIO(string_from_object_dump_2)
+        loader_3 = self._loader(stream_3)
+        obj_3 = loader_3.get_data()
+
+        string_from_object_dump_3 = self._dump_string(obj_3, dumper=AnsibleDumper)
+
+        self.assertEqual(obj, obj_3)
+        # should be transitive, but...
+        self.assertEqual(obj_2, obj_3)
+        self.assertEqual(string_from_object_dump, string_from_object_dump_3)
+
+    def _old_dump_load_cycle(self, obj):
+        '''Dump the passed in object to yaml, load it back up, dump again, compare.'''
+        stream = io.StringIO()
+
+        yaml_string = self._dump_string(obj, dumper=AnsibleDumper)
+        self._dump_stream(obj, stream, dumper=AnsibleDumper)
+
+        yaml_string_from_stream = stream.getvalue()
+
+        # reset stream
+        stream.seek(0)
+
+        loader = self._loader(stream)
+        # loader = AnsibleLoader(stream, vault_password=self.vault_password)
+        obj_from_stream = loader.get_data()
+
+        stream_from_string = io.StringIO(yaml_string)
+        loader2 = self._loader(stream_from_string)
+        # loader2 = AnsibleLoader(stream_from_string, vault_password=self.vault_password)
+        obj_from_string = loader2.get_data()
+
+        stream_obj_from_stream = io.StringIO()
+        stream_obj_from_string = io.StringIO()
+
+        if PY3:
+            yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper)
+            yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper)
+        else:
+            yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper, encoding=None)
+            yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper, encoding=None)
+
+        yaml_string_stream_obj_from_stream = stream_obj_from_stream.getvalue()
+        yaml_string_stream_obj_from_string = stream_obj_from_string.getvalue()
+
+        stream_obj_from_stream.seek(0)
+        stream_obj_from_string.seek(0)
+
+        if PY3:
+            yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper)
+            yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper)
+        else:
+            yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper, encoding=None)
+            yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper, encoding=None)
+
+        assert yaml_string == yaml_string_obj_from_stream
+        assert yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
+        assert (yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string == yaml_string_stream_obj_from_stream ==
+                yaml_string_stream_obj_from_string)
+        assert obj == obj_from_stream
+        assert obj == obj_from_string
+        assert obj == yaml_string_obj_from_stream
+        assert obj == yaml_string_obj_from_string
+        assert obj == obj_from_stream == obj_from_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
+        return {'obj': obj,
+                'yaml_string': yaml_string,
+                'yaml_string_from_stream': yaml_string_from_stream,
+                'obj_from_stream': obj_from_stream,
+                'obj_from_string': obj_from_string,
+                'yaml_string_obj_from_string': yaml_string_obj_from_string}
diff --git a/tests/unit/modules/__init__.py b/tests/unit/modules/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/unit/modules/conftest.py b/tests/unit/modules/conftest.py
new file mode 100644
index 0000000..3bbfe0b
--- /dev/null
+++ b/tests/unit/modules/conftest.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2017 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+import json
+
+import pytest
+
+from ansible.module_utils.six import string_types
+from ansible.module_utils._text import to_bytes
+from ansible.module_utils.common._collections_compat import MutableMapping
+
+
+@pytest.fixture
+def patch_ansible_module(request, mocker):
+    if isinstance(request.param, string_types):
+        args = request.param
+    elif isinstance(request.param, MutableMapping):
+        if 'ANSIBLE_MODULE_ARGS' not in request.param:
+            request.param = {'ANSIBLE_MODULE_ARGS': request.param}
+        if '_ansible_remote_tmp' not in request.param['ANSIBLE_MODULE_ARGS']:
+            request.param['ANSIBLE_MODULE_ARGS']['_ansible_remote_tmp'] = '/tmp'
+        if '_ansible_keep_remote_files' not in request.param['ANSIBLE_MODULE_ARGS']:
+            request.param['ANSIBLE_MODULE_ARGS']['_ansible_keep_remote_files'] = False
+        args = json.dumps(request.param)
+    else:
+        raise Exception('Malformed data to the patch_ansible_module pytest fixture')
+
+    mocker.patch('ansible.module_utils.basic._ANSIBLE_ARGS', to_bytes(args))
diff --git a/tests/unit/modules/network/__init__.py b/tests/unit/modules/network/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/unit/modules/network/dellos9/__init__.py b/tests/unit/modules/network/dellos9/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/unit/modules/network/dellos9/dellos9_module.py b/tests/unit/modules/network/dellos9/dellos9_module.py
new file mode 100644
index 0000000..0b85946
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/dellos9_module.py
@@ -0,0 +1,90 @@
+# (c) 2016 Red Hat Inc.
+#
+# (c) 2017 Dell EMC.
+#
+# 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/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+
+from ansible_collections.dellemc_networking.os9.tests.unit.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase
+
+
+fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures')
+fixture_data = {}
+
+
+def load_fixture(name):
+    path = os.path.join(fixture_path, name)
+
+    if path in fixture_data:
+        return fixture_data[path]
+
+    with open(path) as f:
+        data = f.read()
+
+    try:
+        data = json.loads(data)
+    except Exception:
+        pass
+
+    fixture_data[path] = data
+    return data
+
+
+class TestDellos9Module(ModuleTestCase):
+
+    def execute_module(self, failed=False, changed=False, commands=None, sort=True, defaults=False):
+
+        self.load_fixtures(commands)
+
+        if failed:
+            result = self.failed()
+            self.assertTrue(result['failed'], result)
+        else:
+            result = self.changed(changed)
+            self.assertEqual(result['changed'], changed, result)
+
+        if commands is not None:
+            if sort:
+                self.assertEqual(sorted(commands), sorted(result['updates']), result['updates'])
+            else:
+                self.assertEqual(commands, result['updates'], result['updates'])
+
+        return result
+
+    def failed(self):
+        with self.assertRaises(AnsibleFailJson) as exc:
+            self.module.main()
+
+        result = exc.exception.args[0]
+        self.assertTrue(result['failed'], result)
+        return result
+
+    def changed(self, changed=False):
+        with self.assertRaises(AnsibleExitJson) as exc:
+            self.module.main()
+
+        result = exc.exception.args[0]
+        self.assertEqual(result['changed'], changed, result)
+        return result
+
+    def load_fixtures(self, commands=None):
+        pass
diff --git a/tests/unit/modules/network/dellos9/fixtures/dellos9_config_config.cfg b/tests/unit/modules/network/dellos9/fixtures/dellos9_config_config.cfg
new file mode 100644
index 0000000..b8f62da
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/fixtures/dellos9_config_config.cfg
@@ -0,0 +1,13 @@
+!
+hostname router
+!
+interface fortyGigE 1/6
+ ip address 1.2.3.4/24
+ description test string
+!
+interface fortyGigE 1/7
+ ip address 6.7.8.9/24
+ description test string
+ shutdown
+!
+
diff --git a/tests/unit/modules/network/dellos9/fixtures/dellos9_config_src.cfg b/tests/unit/modules/network/dellos9/fixtures/dellos9_config_src.cfg
new file mode 100644
index 0000000..7ab3338
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/fixtures/dellos9_config_src.cfg
@@ -0,0 +1,12 @@
+!
+hostname foo
+!
+interface fortyGigE 1/6
+ no ip address
+!
+interface fortyGigE 1/7
+ ip address 6.7.8.9/24
+ description test string
+ shutdown
+!
+
diff --git a/tests/unit/modules/network/dellos9/fixtures/show_file-systems b/tests/unit/modules/network/dellos9/fixtures/show_file-systems
new file mode 100644
index 0000000..1c02bb6
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/fixtures/show_file-systems
@@ -0,0 +1,10 @@
+      Size(b)     Free(b)      Feature      Type   Flags  Prefixes
+   6429872128  5582319616        FAT32 USERFLASH      rw  flash:
+            -           -  unformatted USERFLASH      rw  fcmfs:
+    241172480    91893760      Unknown  NFSMOUNT      rw  nfsmount:
+            -           -            -   network      rw  ftp:
+            -           -            -   network      rw  tftp:
+            -           -            -   network      rw  scp:
+            -           -            -   network      rw  http:
+            -           -            -   network      rw  https:
+
diff --git a/tests/unit/modules/network/dellos9/fixtures/show_interfaces b/tests/unit/modules/network/dellos9/fixtures/show_interfaces
new file mode 100644
index 0000000..5f19f38
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/fixtures/show_interfaces
@@ -0,0 +1,1259 @@
+TenGigabitEthernet 0/0 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1048580
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 10000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:13:21
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:16:47
+
+
+TenGigabitEthernet 0/1 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1048708
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 10000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:17:48
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:16:49
+
+
+TenGigabitEthernet 0/2 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1048836
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 10000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:18:30
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:17:31
+
+
+TenGigabitEthernet 0/3 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1048964
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 10000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:18:33
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:17:35
+
+
+fortyGigE 0/4 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1049093
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:38:08
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:37:09
+
+
+fortyGigE 0/8 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1049605
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:38:08
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:40:18
+
+
+fortyGigE 0/12 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1050117
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:41:18
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:40:20
+
+
+fortyGigE 0/16 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1050629
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:42:41
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:41:43
+
+
+fortyGigE 0/20 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1051141
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:43:10
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:42:12
+
+
+fortyGigE 0/24 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1051653
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:43:45
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:42:47
+
+
+fortyGigE 0/28 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1052165
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:44:35
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:43:37
+
+
+fortyGigE 0/32 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1052677
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:44:53
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:43:54
+
+
+fortyGigE 0/36 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1053189
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:46:20
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:45:21
+
+
+fortyGigE 0/40 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1053701
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:46:32
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:45:33
+
+
+fortyGigE 0/44 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1054213
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:46:56
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:45:58
+
+
+fortyGigE 0/48 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1054725
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:47:10
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:46:11
+
+
+fortyGigE 0/52 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1055237
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:47:22
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:46:24
+
+
+fortyGigE 0/56 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1055749
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:47:47
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:46:48
+
+
+fortyGigE 0/60 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1056261
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:47:58
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:47:00
+
+
+fortyGigE 0/64 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1056773
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:48:26
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:47:28
+
+
+fortyGigE 0/68 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1057285
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:48:38
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:47:40
+
+
+fortyGigE 0/72 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1057797
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:49:05
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:48:07
+
+
+fortyGigE 0/76 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1058309
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:49:17
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:48:18
+
+
+fortyGigE 0/80 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1058821
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:49:36
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:48:37
+
+
+fortyGigE 0/84 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1059333
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:49:58
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:49:00
+
+
+fortyGigE 0/88 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1059845
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:50:12
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:49:14
+
+
+fortyGigE 0/92 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1060357
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:50:36
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:49:37
+
+
+fortyGigE 0/96 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1060869
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:50:50
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:49:52
+
+
+fortyGigE 0/100 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1061381
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:51:16
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:50:17
+
+
+fortyGigE 0/104 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1061893
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:51:26
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:50:28
+
+
+fortyGigE 0/108 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1062405
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:51:50
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:50:52
+
+
+fortyGigE 0/112 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1062917
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:52:02
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:51:04
+
+
+fortyGigE 0/116 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1063429
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:52:14
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:51:15
+
+
+fortyGigE 0/120 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1063941
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:52:44
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:51:45
+
+
+fortyGigE 0/124 is down, line protocol is down
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 1064453
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 40000 Mbit
+Flowcontrol rx off tx off
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:52:55
+Queueing strategy: fifo
+Input Statistics:
+     0 packets, 0 bytes
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 runts, 0 giants, 0 throttles
+     0 CRC, 0 overrun, 0 discarded
+Output Statistics:
+     0 packets, 0 bytes, 0 underruns
+     0 64-byte pkts, 0 over 64-byte pkts, 0 over 127-byte pkts
+     0 over 255-byte pkts, 0 over 511-byte pkts, 0 over 1023-byte pkts
+     0 Multicasts, 0 Broadcasts, 0 Unicasts
+     0 throttles, 0 discarded, 0 collisions, 0 wreddrops
+Rate info (interval 299 seconds):
+     Input 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+     Output 00.00 Mbits/sec,          0 packets/sec, 0.00% of line-rate
+Time since last interface status change: 13:51:56
+
+
+ManagementEthernet 0/0 is up, line protocol is up
+Hardware is DellEth, address is 90:b1:1c:f4:a2:8f
+    Current address is 90:b1:1c:f4:a2:8f
+Pluggable media not present
+Interface index is 7340033
+Internet address is 10.16.148.71/16
+Mode of IPv4 Address Assignment : MANUAL
+DHCP Client-ID(61): 90b11cf4a28f
+Virtual-IP is not set
+Virtual-IP IPv6 address is not set
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed 1000 Mbit, Mode full duplex
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:52:17
+Queueing strategy: fifo
+    Input 111338 packets, 7239813 bytes, 96163 multicast
+    Received 0 errors, 0 discarded
+    Output 8316 packets, 1491845 bytes, 0 multicast
+    Output 0 errors, 0 invalid protocol
+Time since last interface status change: 13:52:13
+
+
+ManagementEthernet 1/0 is up, line protocol is not present
+Hardware is DellEth, address is not set
+Interface index is 8388609
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed auto, Mode full duplex
+ARP type: ARPA, ARP Timeout 04:00:00
+Queueing strategy: fifo
+Time since last interface status change: 13:52:33
+
+
+ManagementEthernet 2/0 is up, line protocol is not present
+Hardware is DellEth, address is not set
+Interface index is 9437185
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed auto, Mode full duplex
+ARP type: ARPA, ARP Timeout 04:00:00
+Queueing strategy: fifo
+Time since last interface status change: 13:52:33
+
+
+ManagementEthernet 3/0 is up, line protocol is not present
+Hardware is DellEth, address is not set
+Interface index is 10485761
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed auto, Mode full duplex
+ARP type: ARPA, ARP Timeout 04:00:00
+Queueing strategy: fifo
+Time since last interface status change: 13:52:43
+
+
+ManagementEthernet 4/0 is up, line protocol is not present
+Hardware is DellEth, address is not set
+Interface index is 11534337
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed auto, Mode full duplex
+ARP type: ARPA, ARP Timeout 04:00:00
+Queueing strategy: fifo
+Time since last interface status change: 13:52:43
+
+
+ManagementEthernet 5/0 is up, line protocol is not present
+Hardware is DellEth, address is not set
+Interface index is 12582913
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed auto, Mode full duplex
+ARP type: ARPA, ARP Timeout 04:00:00
+Queueing strategy: fifo
+Time since last interface status change: 13:52:53
+
+
+Vlan 1 is down, line protocol is down
+Address is 90:b1:1c:f4:a2:8f, Current address is 90:b1:1c:f4:a2:8f
+Interface index is 1275068928
+Internet address is not set
+Mode of IPv4 Address Assignment : NONE
+DHCP Client-ID :90b11cf4a28f
+MTU 1554 bytes, IP MTU 1500 bytes
+LineSpeed auto
+ARP type: ARPA, ARP Timeout 04:00:00
+Last clearing of "show interface" counters 13:53:06
+Queueing strategy: fifo
+Time since last interface status change: 13:53:06
+Input Statistics:
+    0 packets, 0 bytes
+Output Statistics:
+    0 packets, 0 bytes
+
diff --git a/tests/unit/modules/network/dellos9/fixtures/show_inventory b/tests/unit/modules/network/dellos9/fixtures/show_inventory
new file mode 100644
index 0000000..90c0295
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/fixtures/show_inventory
@@ -0,0 +1,19 @@
+System Type            : S6000
+System Mode            : 1.0
+Software Version       : 9.12(0.0)
+
+Unit Type               Serial Number  Part Number  Rev  Piece Part ID            Rev  Svc Tag  Exprs Svc Code
+--------------------------------------------------------------------------------------------------------------
+* 0  S6000-01-FE-32T    NA             08YWFG       A00  CN-08YWFG-28298-3AG-0031 A00  6BJ8VS1  137 581 490 89
+  0  S6000-PWR-AC       NA             0T9FNW       A00  CN-0T9FNW-28298-3AG-0119 A00  NA       NA
+  0  S6000-FAN          NA             0MGDH8       A00  CN-0MGDH8-28298-3AG-0094 A00  NA       NA
+  0  S6000-FAN          NA             0MGDH8       A00  CN-0MGDH8-28298-3AG-0096 A00  NA       NA
+  0  S6000-FAN          NA             0MGDH8       A00  CN-0MGDH8-28298-3AG-0095 A00  NA       NA
+
+ * - Management Unit
+
+
+Software Protocol Configured
+--------------------------------------------------------------
+  LLDP
+
diff --git a/tests/unit/modules/network/dellos9/fixtures/show_ipv6_interface b/tests/unit/modules/network/dellos9/fixtures/show_ipv6_interface
new file mode 100644
index 0000000..0cc43da
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/fixtures/show_ipv6_interface
@@ -0,0 +1,26 @@
+fortyGigE 0/16 is down, line protocol is down
+  IPV6 is enabled
+  Link Local address: fe80::92b1:1cff:fef4:a28f
+  Global Unicast address(es):
+    2001:4898:5808:ffa2::5, subnet is 2001:4898:5808:ffa2::4/126 (MANUAL)
+     Remaining lifetime: infinite
+  Global Anycast address(es):
+  Joined Group address(es):
+    ff02::1
+    ff02::2
+    ff02::1:ff00:5
+    ff02::1:fff4:a28f
+  IP MTU is 1500 bytes
+  ND MTU is 0
+  ICMP redirects are not sent
+  DAD is enabled, number of DAD attempts: 3
+  ND reachable time is 35780 milliseconds
+  ND base reachable time is 30000 milliseconds
+  ND advertised reachable time is 0 milliseconds
+  ND advertised retransmit interval is 0 milliseconds
+  ND router advertisements are sent every 198 to 600 seconds
+  ND router advertisements live for 1800 seconds
+  ND advertised hop limit is 64
+  IPv6 hop limit for originated packets is 64
+  IPv6 unicast RPF check is not supported
+
diff --git a/tests/unit/modules/network/dellos9/fixtures/show_lldp_neighbors_detail b/tests/unit/modules/network/dellos9/fixtures/show_lldp_neighbors_detail
new file mode 100644
index 0000000..a868571
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/fixtures/show_lldp_neighbors_detail
@@ -0,0 +1,35 @@
+========================================================================
+ Local Interface Ma 0/0 has 1 neighbor
+  Total Frames Out: 1747
+  Total Frames In: 10333
+  Total Neighbor information Age outs: 0
+  Total Multiple Neighbors Detected: 0
+  Total Frames Discarded: 0
+  Total In Error Frames: 0
+  Total Unrecognized TLVs: 0
+  Total TLVs Discarded: 0
+  Next packet will be sent after 17 seconds
+  The neighbors are given below:
+  -----------------------------------------------------------------------
+
+    Remote Chassis ID Subtype: Mac address (4)
+    Remote Chassis ID:  90:b1:1c:f4:2f:6d
+    Remote Port Subtype:  Interface name (5)
+    Remote Port ID:  TenGigabitEthernet 0/33
+    Remote Port Description:  TenGigabitEthernet 0/33
+    Local Port ID: ManagementEthernet 0/0
+    Locally assigned remote Neighbor Index: 1
+    Remote TTL:  20
+    Information valid for next 17 seconds
+    Time since last information change of this neighbor:  14:54:48
+    Remote System Name:  swlab1-maa-tor-A2
+    Remote System Desc:  Dell Real Time Operating System Software. Dell
+     Operating System Version: 2.0. Dell Application Software Version:
+     9.11(2.0) Copyright (c) 1999-2017Dell Inc. All Rights Reserved.Build
+     Time: Tue Apr 25 21:22:59 2017
+    Existing System Capabilities:  Repeater Bridge Router
+    Enabled System Capabilities:  Repeater Bridge Router
+    Remote Port Vlan ID:  148
+    Port and Protocol Vlan ID: 148, Capability: Supported, Status: Enabled
+   ---------------------------------------------------------------------------
+
diff --git a/tests/unit/modules/network/dellos9/fixtures/show_memory__except_Processor b/tests/unit/modules/network/dellos9/fixtures/show_memory__except_Processor
new file mode 100644
index 0000000..c2f6541
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/fixtures/show_memory__except_Processor
@@ -0,0 +1,4 @@
+     ===========================
+   Total(b)      Used(b)       Free(b)      Lowest(b)      Largest(b)
+  3203911680       3172120    3200739560   3200673304   3200739560
+
diff --git a/tests/unit/modules/network/dellos9/fixtures/show_running-config b/tests/unit/modules/network/dellos9/fixtures/show_running-config
new file mode 100644
index 0000000..4804ebb
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/fixtures/show_running-config
@@ -0,0 +1,238 @@
+Current Configuration ...
+! Version 9.12(0.0)
+! Last configuration change at Thu Jan 11 06:53:29 2018 by admin
+!
+!
+logging coredump stack-unit  0
+logging coredump stack-unit  1
+logging coredump stack-unit  2
+logging coredump stack-unit  3
+logging coredump stack-unit  4
+logging coredump stack-unit  5
+!
+hostname Dell
+!
+protocol lldp
+!
+redundancy auto-synchronize full
+!
+enable password 7 b125455cf679b208e79b910e85789edf
+!
+username admin password 7 1d28e9f33f99cf5c
+!
+stack-unit 0 quad-port-profile 0,8,16,24,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,100,108,116,124
+!
+stack-unit 0 provision S6000
+!
+stack-unit 0 port 0 portmode quad
+!
+interface TenGigabitEthernet 0/0
+ no ip address
+ shutdown
+!
+interface TenGigabitEthernet 0/1
+ no ip address
+ shutdown
+!
+interface TenGigabitEthernet 0/2
+ no ip address
+ shutdown
+!
+interface TenGigabitEthernet 0/3
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/4
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/8
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/12
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/16
+ no ip address
+ ipv6 address 2001:4898:5808:ffa2::5/126
+ shutdown
+!
+interface fortyGigE 0/20
+ no ip address
+ switchport
+ ip access-group ipv6-ssh-only in
+ shutdown
+!
+interface fortyGigE 0/24
+ no ip address
+ switchport
+ mac access-group ssh-only-mac in
+ mac access-group ssh-only-mac out
+ shutdown
+!
+interface fortyGigE 0/28
+ no ip address
+ switchport
+ mac access-group ssh-only-mac in
+ mac access-group ssh-only-mac out
+ shutdown
+!
+interface fortyGigE 0/32
+ no ip address
+ switchport
+ ip access-group ipv6-ssh-only out
+ shutdown
+!
+interface fortyGigE 0/36
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/40
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/44
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/48
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/52
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/56
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/60
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/64
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/68
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/72
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/76
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/80
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/84
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/88
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/92
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/96
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/100
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/104
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/108
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/112
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/116
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/120
+ no ip address
+ shutdown
+!
+interface fortyGigE 0/124
+ no ip address
+ shutdown
+!
+interface ManagementEthernet 0/0
+ ip address 10.16.148.71/16
+ no shutdown
+!
+interface ManagementEthernet 1/0
+ no shutdown
+!
+interface ManagementEthernet 2/0
+ no shutdown
+!
+interface ManagementEthernet 3/0
+ no shutdown
+!
+interface ManagementEthernet 4/0
+ no shutdown
+!
+interface ManagementEthernet 5/0
+ no shutdown
+!
+interface Vlan 1
+!untagged fortyGigE 0/20-32
+!
+ipv6 access-list ipv6-ssh-only
+ description ipv6acl
+ remark 1 ipv6
+ seq 10 permit ipv6 2001:4898::/32 any
+ seq 20 permit tcp any eq 2 2404:f801::/32
+ seq 30 permit tcp any 2a01:110::/31 ack
+ seq 40 permit tcp any any
+!
+mac access-list extended ssh-only-mac
+ description macacl
+ remark 1 mac
+ seq 5 permit any any count
+ seq 6 deny any any
+!
+ip ssh server enable
+!
+line console 0
+line vty 0
+line vty 1
+ access-class ipv6-ssh-only ipv6
+line vty 2
+ access-class ipv6-ssh-only ipv6
+line vty 3
+ access-class ipv6-ssh-only ipv6
+line vty 4
+line vty 5
+line vty 6
+line vty 7
+line vty 8
+line vty 9
+!
+reload-type
+ boot-type normal-reload
+ config-scr-download enable
+!
+end
+
diff --git a/tests/unit/modules/network/dellos9/fixtures/show_running-config__grep_hostname b/tests/unit/modules/network/dellos9/fixtures/show_running-config__grep_hostname
new file mode 100644
index 0000000..7c4137c
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/fixtures/show_running-config__grep_hostname
@@ -0,0 +1 @@
+hostname dellos9_sw1
diff --git a/tests/unit/modules/network/dellos9/fixtures/show_version b/tests/unit/modules/network/dellos9/fixtures/show_version
new file mode 100644
index 0000000..e385cf3
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/fixtures/show_version
@@ -0,0 +1,18 @@
+Dell Real Time Operating System Software
+Dell Operating System Version:  2.0
+Dell Application Software Version:  9.10(0.1P13)
+Copyright (c) 1999-2016 by Dell Inc. All Rights Reserved.
+Build Time: Wed Sep  7 23:48:35 2016
+Build Path: /sites/eqx/work/swbuild01_1/build01/E9-10-0/SW/SRC
+Dell Networking OS uptime is 12 week(s), 6 day(s), 9 hour(s), 20 minute(s)
+
+System image file is "system://A"
+
+System Type: S6000-ON
+Control Processor: Intel Centerton with 3 Gbytes (3203911680 bytes) of memory, core(s) 2.
+
+16G bytes of boot flash memory.
+
+  1 32-port TE/FG (SI-ON)
+ 32 Forty GigabitEthernet/IEEE 802.3 interface(s)
+
diff --git a/tests/unit/modules/network/dellos9/test_dellos9_command.py b/tests/unit/modules/network/dellos9/test_dellos9_command.py
new file mode 100644
index 0000000..f9959ba
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/test_dellos9_command.py
@@ -0,0 +1,110 @@
+# (c) 2016 Red Hat Inc.
+#
+# (c) 2017 Dell EMC.
+#
+# 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/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+
+from ansible_collections.dellemc_networking.os9.tests.unit.compat.mock import patch
+from ansible_collections.dellemc_networking.os9.plugins.modules import dellos9_command
+from ansible_collections.dellemc_networking.os9.tests.unit.modules.utils import set_module_args
+from ..dellos9_module import TestDellos9Module, load_fixture
+
+
+class TestDellos9CommandModule(TestDellos9Module):
+
+    module = dellos9_command
+
+    def setUp(self):
+        super(TestDellos9CommandModule, self).setUp()
+
+        self.mock_run_commands = patch('ansible_collections.dellemc_networking.os9.plugins.modules.dellos9_command.run_commands')
+        self.run_commands = self.mock_run_commands.start()
+
+    def tearDown(self):
+        super(TestDellos9CommandModule, self).tearDown()
+        self.mock_run_commands.stop()
+
+    def load_fixtures(self, commands=None):
+
+        def load_from_file(*args, **kwargs):
+            module, commands = args
+            output = list()
+
+            for item in commands:
+                try:
+                    obj = json.loads(item['command'])
+                    command = obj['command']
+                except ValueError:
+                    command = item['command']
+                filename = str(command).replace(' ', '_')
+                output.append(load_fixture(filename))
+            return output
+
+        self.run_commands.side_effect = load_from_file
+
+    def test_dellos9_command_simple(self):
+        set_module_args(dict(commands=['show version']))
+        result = self.execute_module()
+        self.assertEqual(len(result['stdout']), 1)
+        self.assertTrue(result['stdout'][0].startswith('Dell Real Time'))
+
+    def test_dellos9_command_multiple(self):
+        set_module_args(dict(commands=['show version', 'show version']))
+        result = self.execute_module()
+        self.assertEqual(len(result['stdout']), 2)
+        self.assertTrue(result['stdout'][0].startswith('Dell Real Time'))
+
+    def test_dellos9_command_wait_for(self):
+        wait_for = 'result[0] contains "Dell Real"'
+        set_module_args(dict(commands=['show version'], wait_for=wait_for))
+        self.execute_module()
+
+    def test_dellos9_command_wait_for_fails(self):
+        wait_for = 'result[0] contains "test string"'
+        set_module_args(dict(commands=['show version'], wait_for=wait_for))
+        self.execute_module(failed=True)
+        self.assertEqual(self.run_commands.call_count, 10)
+
+    def test_dellos9_command_retries(self):
+        wait_for = 'result[0] contains "test string"'
+        set_module_args(dict(commands=['show version'], wait_for=wait_for, retries=2))
+        self.execute_module(failed=True)
+        self.assertEqual(self.run_commands.call_count, 2)
+
+    def test_dellos9_command_match_any(self):
+        wait_for = ['result[0] contains "Dell Real"',
+                    'result[0] contains "test string"']
+        set_module_args(dict(commands=['show version'], wait_for=wait_for, match='any'))
+        self.execute_module()
+
+    def test_dellos9_command_match_all(self):
+        wait_for = ['result[0] contains "Dell Real"',
+                    'result[0] contains "Operating System"']
+        set_module_args(dict(commands=['show version'], wait_for=wait_for, match='all'))
+        self.execute_module()
+
+    def test_dellos9_command_match_all_failure(self):
+        wait_for = ['result[0] contains "Dell Real"',
+                    'result[0] contains "test string"']
+        commands = ['show version', 'show version']
+        set_module_args(dict(commands=commands, wait_for=wait_for, match='all'))
+        self.execute_module(failed=True)
diff --git a/tests/unit/modules/network/dellos9/test_dellos9_config.py b/tests/unit/modules/network/dellos9/test_dellos9_config.py
new file mode 100644
index 0000000..3319686
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/test_dellos9_config.py
@@ -0,0 +1,150 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# (c) 2017 Dell EMC.
+#
+# 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/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible_collections.dellemc_networking.os9.tests.unit.compat.mock import patch
+from ansible_collections.dellemc_networking.os9.plugins.modules import dellos9_config
+from ansible_collections.dellemc_networking.os9.tests.unit.modules.utils import set_module_args
+from ..dellos9_module import TestDellos9Module, load_fixture
+
+
+class TestDellos9ConfigModule(TestDellos9Module):
+
+    module = dellos9_config
+
+    def setUp(self):
+        super(TestDellos9ConfigModule, self).setUp()
+
+        self.mock_get_config = patch('ansible_collections.dellemc_networking.os9.plugins.modules.dellos9_config.get_config')
+        self.get_config = self.mock_get_config.start()
+
+        self.mock_load_config = patch('ansible_collections.dellemc_networking.os9.plugins.modules.dellos9_config.load_config')
+        self.load_config = self.mock_load_config.start()
+
+        self.mock_run_commands = patch('ansible_collections.dellemc_networking.os9.plugins.modules.dellos9_config.run_commands')
+        self.run_commands = self.mock_run_commands.start()
+
+    def tearDown(self):
+        super(TestDellos9ConfigModule, self).tearDown()
+        self.mock_get_config.stop()
+        self.mock_load_config.stop()
+        self.mock_run_commands.stop()
+
+    def load_fixtures(self, commands=None):
+        config_file = 'dellos9_config_config.cfg'
+        self.get_config.return_value = load_fixture(config_file)
+        self.load_config.return_value = None
+
+    def test_dellos9_config_unchanged(self):
+        src = load_fixture('dellos9_config_config.cfg')
+        set_module_args(dict(src=src))
+        self.execute_module()
+
+    def test_dellos9_config_src(self):
+        src = load_fixture('dellos9_config_src.cfg')
+        set_module_args(dict(src=src))
+        commands = ['hostname foo', 'interface fortyGigE 1/6',
+                    'no ip address']
+        self.execute_module(changed=True, commands=commands)
+
+    def test_dellos9_config_backup(self):
+        set_module_args(dict(backup=True))
+        result = self.execute_module()
+        self.assertIn('__backup__', result)
+
+    def test_dellos9_config_save(self):
+        set_module_args(dict(save=True))
+        self.execute_module(changed=True)
+        self.assertEqual(self.run_commands.call_count, 1)
+        self.assertEqual(self.get_config.call_count, 0)
+        self.assertEqual(self.load_config.call_count, 0)
+        args = self.run_commands.call_args[0][1]
+        self.assertDictContainsSubset({'command': 'copy running-config startup-config'}, args[0])
+#        self.assertIn('copy running-config startup-config\r', args)
+
+    def test_dellos9_config_lines_wo_parents(self):
+        set_module_args(dict(lines=['hostname foo']))
+        commands = ['hostname foo']
+        self.execute_module(changed=True, commands=commands)
+
+    def test_dellos9_config_lines_w_parents(self):
+        set_module_args(dict(lines=['shutdown'], parents=['interface fortyGigE 1/6']))
+        commands = ['interface fortyGigE 1/6', 'shutdown']
+        self.execute_module(changed=True, commands=commands)
+
+    def test_dellos9_config_before(self):
+        set_module_args(dict(lines=['hostname foo'], before=['snmp-server contact bar']))
+        commands = ['snmp-server contact bar', 'hostname foo']
+        self.execute_module(changed=True, commands=commands, sort=False)
+
+    def test_dellos9_config_after(self):
+        set_module_args(dict(lines=['hostname foo'], after=['snmp-server contact bar']))
+        commands = ['hostname foo', 'snmp-server contact bar']
+        self.execute_module(changed=True, commands=commands, sort=False)
+
+    def test_dellos9_config_before_after_no_change(self):
+        set_module_args(dict(lines=['hostname router'],
+                             before=['snmp-server contact bar'],
+                             after=['snmp-server location chennai']))
+        self.execute_module()
+
+    def test_dellos9_config_config(self):
+        config = 'hostname localhost'
+        set_module_args(dict(lines=['hostname router'], config=config))
+        commands = ['hostname router']
+        self.execute_module(changed=True, commands=commands)
+
+    def test_dellos9_config_replace_block(self):
+        lines = ['description test string', 'test string']
+        parents = ['interface fortyGigE 1/6']
+        set_module_args(dict(lines=lines, replace='block', parents=parents))
+        commands = parents + lines
+        self.execute_module(changed=True, commands=commands)
+
+    def test_dellos9_config_match_none(self):
+        lines = ['hostname router']
+        set_module_args(dict(lines=lines, match='none'))
+        self.execute_module(changed=True, commands=lines)
+
+    def test_dellos9_config_match_none(self):
+        lines = ['ip address 1.2.3.4/24', 'description test string']
+        parents = ['interface fortyGigE 1/6']
+        set_module_args(dict(lines=lines, parents=parents, match='none'))
+        commands = parents + lines
+        self.execute_module(changed=True, commands=commands, sort=False)
+
+    def test_dellos9_config_match_strict(self):
+        lines = ['ip address 1.2.3.4/24', 'description test string',
+                 'shutdown']
+        parents = ['interface fortyGigE 1/6']
+        set_module_args(dict(lines=lines, parents=parents, match='strict'))
+        commands = parents + ['shutdown']
+        self.execute_module(changed=True, commands=commands, sort=False)
+
+    def test_dellos9_config_match_exact(self):
+        lines = ['ip address 1.2.3.4/24', 'description test string',
+                 'shutdown']
+        parents = ['interface fortyGigE 1/6']
+        set_module_args(dict(lines=lines, parents=parents, match='exact'))
+        commands = parents + lines
+        self.execute_module(changed=True, commands=commands, sort=False)
diff --git a/tests/unit/modules/network/dellos9/test_dellos9_facts.py b/tests/unit/modules/network/dellos9/test_dellos9_facts.py
new file mode 100644
index 0000000..2a375d1
--- /dev/null
+++ b/tests/unit/modules/network/dellos9/test_dellos9_facts.py
@@ -0,0 +1,106 @@
+# (c) 2016 Red Hat 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/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+
+from ansible_collections.dellemc_networking.os9.tests.unit.compat.mock import patch
+from ansible_collections.dellemc_networking.os9.tests.unit.modules.utils import set_module_args
+from ..dellos9_module import TestDellos9Module, load_fixture
+from ansible_collections.dellemc_networking.os9.plugins.modules import dellos9_facts
+
+
+class TestDellos9Facts(TestDellos9Module):
+
+    module = dellos9_facts
+
+    def setUp(self):
+        super(TestDellos9Facts, self).setUp()
+
+        self.mock_run_command = patch(
+            'ansible_collections.dellemc_networking.os9.plugins.modules.dellos9_facts.run_commands')
+        self.run_command = self.mock_run_command.start()
+
+    def tearDown(self):
+        super(TestDellos9Facts, self).tearDown()
+
+        self.mock_run_command.stop()
+
+    def load_fixtures(self, commands=None):
+
+        def load_from_file(*args, **kwargs):
+            module, commands = args
+            output = list()
+
+            for item in commands:
+                try:
+                    obj = json.loads(item)
+                    command = obj['command']
+                except ValueError:
+                    command = item
+                if '|' in command:
+                    command = str(command).replace('|', '')
+                filename = str(command).replace(' ', '_')
+                filename = filename.replace('/', '7')
+                output.append(load_fixture(filename))
+            return output
+
+        self.run_command.side_effect = load_from_file
+
+    def test_dellos9_facts_gather_subset_default(self):
+        set_module_args(dict())
+        result = self.execute_module()
+        ansible_facts = result['ansible_facts']
+        self.assertIn('hardware', ansible_facts['ansible_net_gather_subset'])
+        self.assertIn('default', ansible_facts['ansible_net_gather_subset'])
+        self.assertIn('interfaces', ansible_facts['ansible_net_gather_subset'])
+        self.assertEqual('dellos9_sw1', ansible_facts['ansible_net_hostname'])
+        self.assertIn('fortyGigE 0/24', ansible_facts['ansible_net_interfaces'].keys())
+        self.assertEqual(3128820, ansible_facts['ansible_net_memtotal_mb'])
+        self.assertEqual(3125722, ansible_facts['ansible_net_memfree_mb'])
+
+    def test_dellos9_facts_gather_subset_config(self):
+        set_module_args({'gather_subset': 'config'})
+        result = self.execute_module()
+        ansible_facts = result['ansible_facts']
+        self.assertIn('default', ansible_facts['ansible_net_gather_subset'])
+        self.assertIn('config', ansible_facts['ansible_net_gather_subset'])
+        self.assertEqual('dellos9_sw1', ansible_facts['ansible_net_hostname'])
+        self.assertIn('ansible_net_config', ansible_facts)
+
+    def test_dellos9_facts_gather_subset_hardware(self):
+        set_module_args({'gather_subset': 'hardware'})
+        result = self.execute_module()
+        ansible_facts = result['ansible_facts']
+        self.assertIn('default', ansible_facts['ansible_net_gather_subset'])
+        self.assertIn('hardware', ansible_facts['ansible_net_gather_subset'])
+        self.assertEqual(['flash', 'fcmfs', 'nfsmount', 'ftp', 'tftp', 'scp', 'http', 'https'], ansible_facts['ansible_net_filesystems'])
+        self.assertEqual(3128820, ansible_facts['ansible_net_memtotal_mb'])
+        self.assertEqual(3125722, ansible_facts['ansible_net_memfree_mb'])
+
+    def test_dellos9_facts_gather_subset_interfaces(self):
+        set_module_args({'gather_subset': 'interfaces'})
+        result = self.execute_module()
+        ansible_facts = result['ansible_facts']
+        self.assertIn('default', ansible_facts['ansible_net_gather_subset'])
+        self.assertIn('interfaces', ansible_facts['ansible_net_gather_subset'])
+        self.assertIn('fortyGigE 0/24', ansible_facts['ansible_net_interfaces'].keys())
+        self.assertEqual(['Ma 0/0'], list(ansible_facts['ansible_net_neighbors'].keys()))
+        self.assertIn('ansible_net_interfaces', ansible_facts)
diff --git a/tests/unit/modules/utils.py b/tests/unit/modules/utils.py
new file mode 100644
index 0000000..86ea270
--- /dev/null
+++ b/tests/unit/modules/utils.py
@@ -0,0 +1,47 @@
+import json
+
+from ansible_collections.dellemc_networking.os9.tests.unit.compat import unittest
+from ansible_collections.dellemc_networking.os9.tests.unit.compat.mock import patch
+from ansible.module_utils import basic
+from ansible.module_utils._text import to_bytes
+
+
+def set_module_args(args):
+    if '_ansible_remote_tmp' not in args:
+        args['_ansible_remote_tmp'] = '/tmp'
+    if '_ansible_keep_remote_files' not in args:
+        args['_ansible_keep_remote_files'] = False
+
+    args = json.dumps({'ANSIBLE_MODULE_ARGS': args})
+    basic._ANSIBLE_ARGS = to_bytes(args)
+
+
+class AnsibleExitJson(Exception):
+    pass
+
+
+class AnsibleFailJson(Exception):
+    pass
+
+
+def exit_json(*args, **kwargs):
+    if 'changed' not in kwargs:
+        kwargs['changed'] = False
+    raise AnsibleExitJson(kwargs)
+
+
+def fail_json(*args, **kwargs):
+    kwargs['failed'] = True
+    raise AnsibleFailJson(kwargs)
+
+
+class ModuleTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.mock_module = patch.multiple(basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json)
+        self.mock_module.start()
+        self.mock_sleep = patch('time.sleep')
+        self.mock_sleep.start()
+        set_module_args({})
+        self.addCleanup(self.mock_module.stop)
+        self.addCleanup(self.mock_sleep.stop)
diff --git a/tests/unit/requirements.txt b/tests/unit/requirements.txt
new file mode 100644
index 0000000..a9772be
--- /dev/null
+++ b/tests/unit/requirements.txt
@@ -0,0 +1,42 @@
+boto3
+placebo
+pycrypto
+passlib
+pypsrp
+python-memcached
+pytz
+pyvmomi
+redis
+requests
+setuptools > 0.6 # pytest-xdist installed via requirements does not work with very old setuptools (sanity_ok)
+unittest2 ; python_version < '2.7'
+importlib ; python_version < '2.7'
+netaddr
+ipaddress
+netapp-lib
+solidfire-sdk-python
+
+# requirements for F5 specific modules
+f5-sdk ; python_version >= '2.7'
+f5-icontrol-rest ; python_version >= '2.7'
+deepdiff
+
+# requirement for Fortinet specific modules
+pyFMG
+
+# requirement for aci_rest module
+xmljson
+
+# requirement for winrm connection plugin tests
+pexpect
+
+# requirement for the linode module
+linode-python # APIv3
+linode_api4 ; python_version > '2.6' # APIv4
+
+# requirement for the gitlab module
+python-gitlab
+httmock
+
+# requirment for kubevirt modules
+openshift ; python_version >= '2.7'