Metadata-Version: 1.1
Name: nsxramlclient
Version: 1.0.0rc1
Summary: A "pseudo dynamic" client for the VMware NSX for vSphere API that uses a RAML file describing the API as an Input to generate the API calls
Home-page: http://github.com/yfauser/nsxramlclient
Author: yfauser
Author-email: yfauser@yahoo.de
License: MIT
Description: nsxramlclient
        =============
        
        This 'somewhat dynamic client' gets its API structure information (e.g.
        URLs, parameters, schema, etc.) from a RAML file. It is only tested and
        used with the RAML file specific to VMware NSX Manager (NSX for
        vSphere).
        
        The latest version of the NSXv RAML file can be found at
        http://github.com/yfauser/nsxraml
        
        How to install nsxramlclient
        ============================
        
        The following install instructions will focus on Ubuntu 14.04 LTS, but
        installations on other Linux distributions or on MAC should be
        relatively similar.
        
        Check whether pip is installed
        
        .. code:: sh
        
            pip --version
        
        If pip is not installed, install it with apt-get
        
        .. code:: sh
        
            sudo apt-get update
            sudo apt-get -y install python-pip
        
        Now you can install the nsx raml client using pip
        
        .. code:: sh
        
            sudo pip install nsxramlclient
        
        If the installation fails because of missing dependencies of lxml, you
        will see the following message
        
        ::
        
            ERROR: /bin/sh: 1: xslt-config: not found
            ** make sure the development packages of libxml2 and libxslt are installed **
        
        In this case install the following packages through apt-get, and then
        repeat the above pip installation of the nsx raml client:
        
        .. code:: sh
        
            sudo apt-get install libxml2-dev libxslt-dev python-dev zlib1g-dev
        
        How to use nsxramlclient
        ========================
        
        Create a session object
        -----------------------
        
        The first thing you do is to create a session object to work with. This
        session object will then expose the create, read, update and delete
        (CRUD) as well as some helper methods to you.
        
        .. code:: python
        
            from nsxramlclient.client import NsxClient
        
            nsxraml_file = '/raml/nsxvraml/nsxvapiv614.raml'
            nsxmanager = 'nsxmanager.invalid.org'
            nsx_username = 'admin'
            nsx_password = 'vmware'
        
            client_session = NsxClient(nsxraml_file, nsxmanager, nsx_username, 
                                       nsx_password, debug=False)
        
        The NsxClient Class has the following initialization parameters:
        
        .. code:: python
        
            """
            :param raml_file: 
            This mandatory parameter is the RAML File used as the basis of all URL 
            compositions and to extract the body schema and convert them into python dictionaries
        
            :param nsxmanager: 
            This mandatory parameter is either the hostname or IP Address of the NSX Manager
        
            :param nsx_username: 
            This mandatory parameter is the Username on NSX Manager used to do API Calls
        
            :param nsx_password: 
            This mandatory parameter is the Password of the User used to do API Calls
        
            :param debug: Optional: 
            If set to True, the client will print extensive HTTP session information to stdout. 
            Default: False
        
            :param verify: Optional: 
            If set to True, the client will strictly verify the certificate passed by NSX Manager. 
            Default: False
        
            :param suppress_warnings: Optional: 
            If set to True, the client will print out a warning if NSX Manager uses a self signed certificate. 
            Default: True
        
            :return: Returns a NsxClient Session Object
            """
        
        After you initialized a session object you have access to the following
        methods: - create: Sends a HTTP POST to NSX Manager. More details will
        follow later in this readme
        
        -  read: Sends a HTTP GET to NSX Manager
        
        -  update: Sends a HTTP PUT to NSX Manager
        
        -  delete: Sends a HTTP DELETE to NSX Manager
        
        -  view\_response: Each of the above methods returns a Python
           OrderedDictionary with the HTTP Status code, location header, NSX
           Object Id, eTag Header and Body. This methods outputs the OrderedDict
           out in a human readable text to stdout
        
        -  extract\_resource\_body\_schema: This method will retrieve the body
           schema out of the RAML File (if the method has a body schema like
           most create methods), and will return a template python dictionary
           that can be used to construct your call
        
        -  view\_resource\_body\_schema: This method retrieves the body schema
           out of the RAML file and outputs it to stdout as a pretty printed XML
           document
        
        -  view\_body\_dict: This method takes a body dictionary (any python
           dictionary), and outputs it in a more human readable way to stdout
        
        -  view\_resource\_display\_names: This method outputs all displayNames
           and description of all resources in the RAML File with their
           associated URI & Query parameters, additional Headers and what
           methods (CRUD) are supported
        
        Use the create, read, update and delete methods
        -----------------------------------------------
        
        .. code:: python
        
            In [1]: client_session.read('vCenterStatus')
            Out[2]: OrderedDict([('status', 200), ('body', {'vcConfigStatus': {'connected': 'true', 'lastInventorySyncTime': '1440444721014'}}), ('location', None), ('objectId', None), ('Etag', None)])
        
        As you can see the create, read, update and delete methods return an
        Python OrderedDict with the following key/value pairs: - status: The
        HTTP status code returned as an integer - body: The response body
        returned as a dict. If no body was returned this will be ``None`` -
        location: If a location header is returned, this value will be the
        returned location URL as a string, else it will be ``None`` - objectId:
        If a location header is returned, the value of objectId will be the last
        part of the location url as a string, else it will be ``None`` - Etag:
        If a Etag header is returned, the value of Etag will be the content of
        the Etag header returned, else it will be ``None``
        
        To output the response in a more human readable way when working in an
        interactive session, you can use the ``view_response`` method:
        
        .. code:: python
        
            In [3]: response = client_session.read('vCenterStatus')
            In [4]: client_session.view_response(response)
            HTTP status code:
            200
        
            HTTP Body Content:
            {'vcConfigStatus': {'connected': 'true',
                                'lastInventorySyncTime': '1440445281484'}}
        
        If a method needs a URI parameter to work, the NSX RAML Client will
        compose the URL based on the base URL, parent and child method URL and
        the supplied URI parameter. To supply a URI parameter, add a URI
        parameter dict to your call. You can supply multiple URI parameters in
        the call when needed.
        
        .. code:: python
        
            In [5]: response = client_session.read('vdnSegmentPool', 
                                                   uri_parameters={'segmentPoolId': '2'})
            In [6]: client_session.view_response(response)
            HTTP status code:
            200
        
            HTTP Body Content:
            {'segmentRange': {'begin': '5000',
                              'end': '10000',
                              'id': '2',
                              'name': 'legacy'}}
        
        If a method needs one or more query parameters to work, or you want to
        supply optional query parameters, the NSX RAML Client will add the query
        parameter for you. To use this pass a query parameter dict to the call:
        
        .. code:: python
        
            In [7]: response = client_session.read('nwfabricStatus', 
                                                   query_parameters_dict={'resource': 
                                                                          'domain-c1632'})
            In [8]: client_session.view_response(response)
            HTTP status code:
            200
            .... truncated for brevity ....
        
        Of course you can use URI and query parameters concurrently in any call
        you make, and add as many as the resource specifies.
        
        Finally if a resource requires a body to be supplied with data, you can
        compose the body in the following way:
        
        First you can check what the body of a call needs to look like by
        retrieving it out of the RAML file, and displaying it to stdout using
        ``view_resource_body_schema``:
        
        .. code:: python
        
            In [9]: client_session.view_resource_body_schema('logicalSwitches', 'create')
        
            <virtualWireCreateSpec>
                <name>mandatory</name>
                <description/>
                <tenantId>mandatory</tenantId>
                <controlPlaneMode>mandatory</controlPlaneMode>
            </virtualWireCreateSpec>
        
        Also you can create a template python dictionary using
        ``extract_resource_body_schema``, and if you want you can also output
        its structure in a human readable way to stdout:
        
        .. code:: python
        
            In [10]: new_ls = client_session.extract_resource_body_schema('logicalSwitches', 
                                                                          'create')
        
            In [11]: client_session.view_body_dict(new_ls)
            {'virtualWireCreateSpec': {'controlPlaneMode': 'mandatory',
                                       'description': None,
                                       'name': 'mandatory',
                                       'tenantId': 'mandatory'}}
        
        You can now change some values in the dictionary with the data you want
        to send to the API:
        
        .. code:: python
        
            In [12]: new_ls['virtualWireCreateSpec']['controlPlaneMode'] = 'UNICAST_MODE'
            In [13]: new_ls['virtualWireCreateSpec']['name'] = 'TestLogicalSwitch1'
            In [14]: new_ls['virtualWireCreateSpec']['tenantId'] = 'Tenant1'
        
            In [15]: client_session.view_body_dict(new_ls)
            {'virtualWireCreateSpec': {'controlPlaneMode': 'UNICAST_MODE',
                                       'description': None,
                                       'name': 'TestLogicalSwitch1',
                                       'tenantId': 'Tenant1'}}
        
        And finally you send the call to the NSX Manager API by supplying the
        body dictionary in the call:
        
        .. code:: python
        
            In [16]: new_ls_response = client_session.create('logicalSwitches', 
                                                             uri_parameters={'scopeId': 
                                                                             'vdnscope-1'}, 
                                                             request_body_dict=new_ls)
        
            In [17]: client_session.view_response(new_ls_response)
            HTTP status code:
            201
        
            HTTP location header:
            /api/2.0/vdn/virtualwires/virtualwire-1305
        
            NSX Object Id:
            virtualwire-1305
        
            HTTP Body Content:
            'virtualwire-1305'
        
        Note on Etag header and additional headers (e.g. If-match)
        ----------------------------------------------------------
        
        Some resources in NSX Manager will need an additional header supplied,
        namely the ``If-match`` header. To compose the ``If-match`` header, one
        retrieves the content of the Etag and returns it in the ``If-match``
        header. This is e.g used in the distributed firewall configuration to
        deal with conflicts when two users concurrently try to edit the rule
        sets.
        
        Here's an example on how to retrieve a dfw rule, edit it, and update it
        on NSX Manager:
        
        .. code:: python
        
            rule_read_response = client_session.read('dfwL3Rule', 
                                                     uri_parameters={'sectionId': section_id,
                                                                     'ruleId': new_rule_id})
            updated_rule = l3_dfw_rule_read_response['body']
            etag_value = l3_dfw_rule_read_response['Etag']
        
            updated_rule['rule']['name'] = 'UpdatedByRAMLClient'
        
            update_response = client_session.update('dfwL3Rule', 
                                                    uri_parameters={'sectionId': section_id,
                                                                    'ruleId': rule_id},
                                                    additional_headers={'If-match': etag_value},
                                                    request_body_dict=updated_rule)
        
        As you can see the ``If-match`` header is supplied by the
        ``additional_headers`` dictionary.
        
        Note on the use of XML Tags in body schemas
        -------------------------------------------
        
        Some resources in NSX Manager expect values to be set in XML Tags.
        Here's an example of a dfw resource were this is the case:
        
        .. code:: python
        
            In [18]: client_session.view_resource_body_schema('dfwL3Rules', 'create')
            <rule disabled="false" logged="false">
                <name>AddRuleTest</name>
                <action>allow</action>
                <notes/>
            .... truncated for brevity ....
        
        As you can see ``rule``\ has the Tags ``disabled`` and ``logged``. When
        this type of Tag is found, it is converted to a key prefixed by ``@`` in
        the resulting dictionary:
        
        .. code:: python
        
            In [19]: l3rule = client_session.extract_resource_body_schema('dfwL3Rules', 
                                                                          'create')
            In [20]: client_session.view_body_dict(l3rule)
            {'rule': {'@disabled': 'false',
                      '@logged': 'false',
                      'action': 'allow',
            .... truncated for brevity ....
        
        You can set values using the ``@`` prefix, and they will be converted to
        a XML Tag of the top level object.
        
        .. code:: python
        
            l3section_bdict['section']['rule'][0]['@logged'] = 'true'
        
        Note on repeating key/value pairs and resulting python lists containing dicts
        -----------------------------------------------------------------------------
        
        In some cases NSX Manager uses lists of parameters with repeating keys.
        Here's an example:
        
        .. code:: python
        
            In [21]: client_session.view_resource_body_schema('dfwL3Section', 'create')
            <section name="Test">
                <rule disabled="false" logged="true">
                    <name/>
                    <action>ALLOW</action>
                    <appliedToList>
                        <appliedTo>
                            <name/>
                            <value/>
                            <type/>
                            <isValid/>
                        </appliedTo>
                    </appliedToList>
                    <sources excluded="false">
                        <source>
                            <name/>
                            <value/>
                            <type/>
                            <isValid/>
                        </source>
                        <source>
                            <name/>
                            <value/>
                            <type/>
                            <isValid/>
                        </source>
                    </sources>
                    <destinations excluded="false">
                        <destination>
                            <name/>
                            <value/>
                            <type/>
                            <isValid/>
                        </destination>
                        <destination>
                            <name/>
                            <value/>
                            <type/>
                            <isValid/>
                        </destination>
                    </destinations>
                    <services>
                        <service>
                            <destinationPort/>
                            <protocol/>
                            <subProtocol/>
                        </service>
                    </services>
                </rule>
                <rule disabled="false" logged="true">
                   <name/>
                   <action>DENY</action>
                </rule>
            </section>
        
        As you can see, there are multiple ``destination`` keys under
        ``destinations``. To be able to work with python dictionaries,
        nsxramlclient will convert those list of equally named parameter
        'groups' to a python list containing dictionaries. Here's the resulting
        python dictionary for this type of resource body schema:
        
        .. code:: python
        
            In [22]: dfw_l3_sec = client_session.extract_resource_body_schema('dfwL3Section', 
                                                                              'create')
            In [31]: client_session.view_body_dict(dfw_l3_sec)
            {'section': {'@name': 'Test',
                         'rule': [{'@disabled': 'false',
                                   '@logged': 'true',
                                   'action': 'ALLOW',
                                   'appliedToList': {'appliedTo': {'isValid': None,
                                                                   'name': None,
                                                                   'type': None,
                                                                   'value': None}},
                                   'destinations': {'@excluded': 'false',
                                                    'destination': [{'isValid': None,
                                                                     'name': None,
                                                                     'type': None,
                                                                     'value': None},
                                                                    {'isValid': None,
                                                                     'name': None,
                                                                     'type': None,
                                                                     'value': None}]},
                                   'name': None,
                                   'services': {'service': {'destinationPort': None,
                                                            'protocol': None,
                                                            'subProtocol': None}},
                                   'sources': {'@excluded': 'false',
                                               'source': [{'isValid': None,
                                                           'name': None,
                                                           'type': None,
                                                           'value': None},
                                                          {'isValid': None,
                                                           'name': None,
                                                           'type': None,
                                                           'value': None}]}},
                                  {'@disabled': 'false',
                                   '@logged': 'true',
                                   'action': 'DENY',
                                   'name': None}]}}
        
        Note the ``rule`` key, its value is a python List containing multiple
        rule objects that themselves are python dictionaries. Same holds true
        for the ``destinations``\ and ``sources`` keys.
        
        License
        -------
        
        The MIT License (MIT)
        
        Copyright (c) 2015 nsxramlclient
        
        Permission is hereby granted, free of charge, to any person obtaining a
        copy of this software and associated documentation files (the
        "Software"), to deal in the Software without restriction, including
        without limitation the rights to use, copy, modify, merge, publish,
        distribute, sublicense, and/or sell copies of the Software, and to
        permit persons to whom the Software is furnished to do so, subject to
        the following conditions:
        
        The above copyright notice and this permission notice shall be included
        in all copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
        OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
        MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
        IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
        CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
        TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
        SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        
        How to contribute
        -----------------
        
        Any contributions are welcome, bug reports, additional tests,
        enhancements, etc. Also we welcome your feedback if you find that
        anything is missing that would make nsxramlclient better
        
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 2.7
