diff options
author | evasquez <eric.vasquez@calxeda.com> | 2012-11-28 16:55:04 -0600 |
---|---|---|
committer | evasquez <eric.vasquez@calxeda.com> | 2012-11-28 16:55:04 -0600 |
commit | 9e5e4f44e1cc2698338ae8d4735432e8838bab54 (patch) | |
tree | b24c72ac80b6eba3ec475229da5a5687e80823e9 | |
parent | 6fd468f9a14cad95ce9fea1cf3d6ccfe4c1e42ff (diff) | |
download | cxmanage-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.py | 12 | ||||
-rw-r--r-- | cxmanage_api/docs/source/fab_basics.rst | 163 | ||||
-rw-r--r-- | cxmanage_api/docs/source/index.rst | 25 | ||||
-rw-r--r-- | cxmanage_api/fabric.py | 9 | ||||
-rw-r--r-- | cxmanage_api/node.py | 2 | ||||
-rw-r--r-- | cxmanage_api/tftp.py | 24 | ||||
-rw-r--r-- | cxmanage_test/tftp_test.py | 8 |
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) |