summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorevasquez <eric.vasquez@calxeda.com>2012-11-28 16:55:04 -0600
committerevasquez <eric.vasquez@calxeda.com>2012-11-28 16:55:04 -0600
commit9e5e4f44e1cc2698338ae8d4735432e8838bab54 (patch)
treeb24c72ac80b6eba3ec475229da5a5687e80823e9
parent6fd468f9a14cad95ce9fea1cf3d6ccfe4c1e42ff (diff)
downloadcxmanage-9e5e4f44e1cc2698338ae8d4735432e8838bab54.tar.gz
* Added a Fabric code example (still on-going)
* Made some minor tweaks to Sphinx doc configuration. * Made default max_threads=48 for a Fabric. * Took our get_port() and all references, the port member can just be accessed directly. Also removed the corresponding test. Ran all tests, they passed.
-rw-r--r--cxmanage_api/docs/source/conf.py12
-rw-r--r--cxmanage_api/docs/source/fab_basics.rst163
-rw-r--r--cxmanage_api/docs/source/index.rst25
-rw-r--r--cxmanage_api/fabric.py9
-rw-r--r--cxmanage_api/node.py2
-rw-r--r--cxmanage_api/tftp.py24
-rw-r--r--cxmanage_test/tftp_test.py8
7 files changed, 190 insertions, 53 deletions
diff --git a/cxmanage_api/docs/source/conf.py b/cxmanage_api/docs/source/conf.py
index 3b278d9..d3de9f5 100644
--- a/cxmanage_api/docs/source/conf.py
+++ b/cxmanage_api/docs/source/conf.py
@@ -24,12 +24,12 @@ sys.path.insert(0, os.path.abspath('..'))
# todo_include_todos = True
# If your documentation needs a minimal Sphinx version, state it here.
-# needs_sphinx = '1.0'
+# needs_sp hinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-sphinx_extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.todo',
- 'sphinx.ext.autosummary']
+sphinx_extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode',
+ 'sphinx.ext.todo', 'sphinx.ext.autosummary']
cloud_sptheme_extensions = ['cloud_sptheme.ext.index_styling',
'cloud_sptheme.ext.relbar_toc',
'cloud_sptheme.ext.autodoc_sections',
@@ -74,7 +74,7 @@ release = '1.0.0'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = []
+exclude_patterns = ['_build', '_static']
# The reST default role (used for this markup: `text`) to use for all documents.
# default_role = None
@@ -88,10 +88,10 @@ add_module_names = False
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
-# show_authors = False
+show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
-# pygments_style = 'sphinx' # Default
+# pygments_style = 'sphinx' # Default
pygments_style = 'tango'
# A list of ignored prefixes for module index sorting.
diff --git a/cxmanage_api/docs/source/fab_basics.rst b/cxmanage_api/docs/source/fab_basics.rst
new file mode 100644
index 0000000..ca7e085
--- /dev/null
+++ b/cxmanage_api/docs/source/fab_basics.rst
@@ -0,0 +1,163 @@
+Fabric Basics
+-------------
+
+Overview
+========
+
+This tutorial assumes basic Object Oriented Programming knowledge.
+
+Constructing a Fabric object in Python is **VERY** easy. You simply need to
+know the ip address of *ANY* Node in your configuration ...
+Thats it. The API will do the rest!
+
+What purpose do Fabric objects in Python do for me as a user?
+
+**At a glance, they're useful for:**
+ * Performing the same action on one, all, or a subset of nodes.
+ * Gathering real time information from the Fabric (statistics, topology,
+ software versions, etc.)
+
+Example
+=======
+
+**Lets start by stating what the end goals of this example will be:**
+ 1. Construct a Fabric object using the Cxmanage API in Python.
+ 2. Query the Fabric object for **basic** information from each node.
+ 3. Print out the information.
+
+.. seealso:: `Fabric Info Basic <fabric.html#cxmanage_api.fabric.Fabric.info_basic>`_ & `Node Info Basic <node.html#cxmanage_api.node.Node.info_basic>`_ For more details
+
+**Now lets dive right in with code ...**
+
+You can either write a script in your favorite text editor of choice or use
+Python's Interactive Interpreter. The interactive interpreter is used for these
+code examples, however ANY of this code can be copied/pasted into a script.
+
+To start the Interactive Interpreter, at a terminal command-line prompt::
+
+ python
+ Python 2.7.3 (default, Aug 1 2012, 05:14:39)
+ [GCC 4.6.3] on linux2
+ Type "help", "copyright", "credits" or "license" for more information.
+ >>>
+
+.. note::
+ * If you're using a Virtual Environment ... BEFORE you start the interpreter, be sure to:
+ workon <VirtualEnvironment Name>
+
+.. seealso:: `Using the Python Interpreter <http://docs.python.org/2/tutorial/interpreter.html>`_
+
+
+The Code
+########
+
+.. code-block:: python
+ :linenos:
+
+ from cxmanage_api.fabric import Fabric
+ my_fabric = Fabric('10.20.1.9') # 1. Construct a Fabric Object ...
+ basic_info = my_fabric.info_basic() # 2. Get basic information from each node
+
+ for node_number, info in basic_info.items(): # 3. Print out the Information
+ print 'Basic Info for Node %d:\n' % node_number
+ versions = [name for name in dir(info) if not name.startswith('_')]
+ for version in versions:
+ print '%s = %s' % (version, getattr(info, version))
+ print '=' * 80
+
+The Output
+##########
+
+::
+
+ Basic Info for Node 0:
+
+ a9boot_version = v2012.10.16
+ bootlog_version = v0.9.1-39-g7e10987
+ build_number = 7E10987C
+ card = EnergyCard X02
+ cdb_version = v0.9.1-39-g7e10987
+ dtb_version = v3.6-rc1_cx_2012.10.02
+ header = Calxeda SoC (0x0096CD)
+ soc_version = v0.9.1
+ stage2_version = v0.9.1-39-g7e10987
+ timestamp = 1352911670
+ uboot_version = v2012.07_cx_2012.10.29-6-g6605d9
+ ubootenv_version = v2012.07_cx_2012.10.29-6-g6605d9
+ version = ECX-1000-v1.7.1-dirty
+ ================================================================================
+ Basic Info for Node 1:
+
+ a9boot_version = v2012.10.16
+ bootlog_version = v0.9.1-39-g7e10987
+ build_number = 7E10987C
+ card = EnergyCard X02
+ cdb_version = v0.9.1-39-g7e10987
+ dtb_version = v3.6-rc1_cx_2012.10.02
+ header = Calxeda SoC (0x0096CD)
+ soc_version = v0.9.1
+ stage2_version = v0.9.1-39-g7e10987
+ timestamp = 1352911670
+ uboot_version = v2012.07_cx_2012.10.29-6-g6605d9
+ ubootenv_version = v2012.07_cx_2012.10.29-6-g6605d9
+ version = ECX-1000-v1.7.1-dirty
+ ================================================================================
+ Basic Info for Node 2:
+
+ a9boot_version = v2012.10.16
+ bootlog_version = v0.9.1-39-g7e10987
+ build_number = 7E10987C
+ card = EnergyCard X02
+ cdb_version = v0.9.1-39-g7e10987
+ dtb_version = v3.6-rc1_cx_2012.10.02
+ header = Calxeda SoC (0x0096CD)
+ soc_version = v0.9.1
+ stage2_version = v0.9.1-39-g7e10987
+ timestamp = 1352911670
+ uboot_version = v2012.07_cx_2012.10.29-6-g6605d9
+ ubootenv_version = v2012.07_cx_2012.10.29-6-g6605d9
+ version = ECX-1000-v1.7.1-dirty
+ ================================================================================
+ Basic Info for Node 3:
+
+ a9boot_version = v2012.10.16
+ bootlog_version = v0.9.1-39-g7e10987
+ build_number = 7E10987C
+ card = EnergyCard X02
+ cdb_version = v0.9.1-39-g7e10987
+ dtb_version = v3.6-rc1_cx_2012.10.02
+ header = Calxeda SoC (0x0096CD)
+ soc_version = v0.9.1
+ stage2_version = v0.9.1-39-g7e10987
+ timestamp = 1352911670
+ uboot_version = v2012.07_cx_2012.10.29-6-g6605d9
+ ubootenv_version = v2012.07_cx_2012.10.29-6-g6605d9
+ version = ECX-1000-v1.7.1-dirty
+ ================================================================================
+
+Line by Line Explaination
+#########################
+
+As you can see, in just 10 lines of code, we accomplished all of our stated
+goals. This code also scales to work for Fabrics of N nodes.
+
+**Breakdown**
+
+Line 1: Imports the Fabric class from the *installed* cxmanage_api.
+
+.. code-block:: python
+
+ from cxmanage_api.fabric import Fabric
+
+Line 2: Accomplished our first goal by creating the Fabric object with an ip
+address we knew about.
+
+.. code-block:: python
+
+ my_fabric = Fabric('10.20.1.9')
+
+Line 3: Accomplished our second goal by simply asking the Fabric for Node info
+and storing the result in the 'basic_info' variable, which is a dictionary in
+the format: { node_number : info_basic_result_object }
+
+ \ No newline at end of file
diff --git a/cxmanage_api/docs/source/index.rst b/cxmanage_api/docs/source/index.rst
index 316b097..cd51502 100644
--- a/cxmanage_api/docs/source/index.rst
+++ b/cxmanage_api/docs/source/index.rst
@@ -143,10 +143,15 @@ Getting Started
So you have the Cxmanage Python API properly installed, so now what?
The Cxmanage Python API Docs will give you information on how to use Calxeda
-classes and functions. Optionally, you can view the API source for even more
-clarity on the internals.
+classes and functions.
-``API Docs``
+You can view the API source for even more clarity on the internals. Or jump
+right into the Code Examples.
+
+API Docs & Code Examples
+------------------------
+
+``API Documentation``
.. toctree::
@@ -161,14 +166,10 @@ clarity on the internals.
Internal/External TFTP <tftp>
SIMG <simg>
U-Boot Environment <ubootenv>
-
-PyUnit Test Integration
------------------------
-Documentation about:
- * Calxeda Test Case
- * Pyunit Test writing
+``Code Examples``
+
+.. toctree::
-Sample Code
------------
-Helpful scripts, and/or tests.
+ Fabric Basics <fab_basics>
+
diff --git a/cxmanage_api/fabric.py b/cxmanage_api/fabric.py
index 6db89f6..88c7747 100644
--- a/cxmanage_api/fabric.py
+++ b/cxmanage_api/fabric.py
@@ -56,7 +56,7 @@ class Fabric(object):
"""
def __init__(self, ip_address, username="admin", password="admin",
- tftp=None, max_threads=1, command_delay=0, verbose=False,
+ tftp=None, max_threads=48, command_delay=0, verbose=False,
node=None):
"""Default constructor for the Fabric class."""
self._tftp = tftp
@@ -410,11 +410,11 @@ class Fabric(object):
def info_dump(self, async=False):
"""Dumps info from all nodes.
- .. note::
- * Output condensed for brevity.
-
>>> fabric.info_dump()
>>> {0: n0dump, 1: n1dump, 2: n2dump, 3: n3dump}
+ >>> #
+ >>> # Output condensed for brevity ...
+ >>> #
.. seealso::
`Info Dump <node.html#cxmanage_api.node.Node.info_dump>`_
@@ -473,4 +473,5 @@ class Fabric(object):
command.join()
return command.get_results()
+
# End of file: ./fabric.py
diff --git a/cxmanage_api/node.py b/cxmanage_api/node.py
index 6fa1373..2aa6b19 100644
--- a/cxmanage_api/node.py
+++ b/cxmanage_api/node.py
@@ -120,7 +120,7 @@ class Node(object):
"""
return '%s:%s' % (self.tftp.get_address(relative_host=self.ip_address),
- self.tftp.get_port())
+ self.tftp.port)
def get_mac_addresses(self):
"""Gets a list of MAC addresses for this node.
diff --git a/cxmanage_api/tftp.py b/cxmanage_api/tftp.py
index 5ee2982..0a4f13f 100644
--- a/cxmanage_api/tftp.py
+++ b/cxmanage_api/tftp.py
@@ -101,18 +101,6 @@ class InternalTftp(object):
self.port = int(a_fd.readline())
atexit.register(self.kill)
- def get_port(self):
- """Returns the listening port of this server.
-
- >>> i_tftp.get_port()
- 40865
-
- :return: The listening port of this Internal TFTP server.
- :rtype: integer
-
- """
- return self.port
-
def get_address(self, relative_host=None):
"""Returns the ipv4 address of this server.
If a relative_host is specified, then we discover our address to them.
@@ -232,18 +220,6 @@ class ExternalTftp(object):
del relative_host # Needed only for function signature.
return self.ip_address
- def get_port(self):
- """Return the listening port of this server.
-
- >>> e_tftp.get_port()
- 69
-
- :returns: The port of the external TFTP server connection.
- :rtype: integer
-
- """
- return self.port
-
def get_file(self, src, dest):
"""Download a file from the ExternalTftp Server.
diff --git a/cxmanage_test/tftp_test.py b/cxmanage_test/tftp_test.py
index 1ef75c0..121d666 100644
--- a/cxmanage_test/tftp_test.py
+++ b/cxmanage_test/tftp_test.py
@@ -79,10 +79,6 @@ class InternalTftpTest(unittest.TestCase):
self.assertEqual(open(filename).read(), contents)
os.remove(filename)
- def test_get_port(self):
- """Tests the get_port() function."""
- self.assertEqual(self.tftp1.port, self.tftp1.get_port())
-
def test_get_address_no_relative_host(self):
"""Tests the get_address(relative_host) function with NO relative
host defined.
@@ -98,7 +94,7 @@ class InternalTftpTest(unittest.TestCase):
try:
# RFC863 defines port 9 as the UDP discard port, so we use it to
# find out our local ip to pass as a relative_host
- sock.connect((socket.gethostname(),9))
+ sock.connect((socket.gethostname(), 9))
relative_host = sock.getsockname()[0]
except socket.error:
@@ -121,7 +117,7 @@ class ExternalTftpTest(unittest.TestCase):
self.itftp = InternalTftp(ip_address='127.0.0.250')
self.etftp = ExternalTftp(
self.itftp.get_address(relative_host=_get_relative_host()),
- self.itftp.get_port())
+ self.itftp.port)
def test_put_and_get(self):
"""Test the put_file(src, dest) function. Test the get_file(src,dest)