ZTPServer Package

app Module

ztpserver.app.enable_handler_console(level=None)[source]

Enables logging to stdout

ztpserver.app.load_config(conf=None)[source]
ztpserver.app.main()[source]

The main() is the main entry point for the ztpserver if called from the commmand line. When called from the command line, the server is running in standalone mode as opposed to using the application() to run under a python wsgi compliant server

ztpserver.app.python_supported()[source]

Returns True if the current version of the python runtime is valid

ztpserver.app.run_server(conf, debug)[source]

The run_server() is called by the main command line routine to run the server as standalone. This function accepts a single argument that points towards the configuration file describing this server

This function will block on the active thread until stopped.

Parameters:conf – string path pointing to configuration file
ztpserver.app.run_validator(filename=None)[source]
ztpserver.app.start_logging(debug)[source]

reads the runtime config and starts logging if enabled

ztpserver.app.start_wsgiapp(conf=None, debug=False)[source]

Provides the entry point into the application for wsgi compliant servers. Accepts a single keyword argument conf. The conf keyword argument specifies the path the server configuration file. The default value is /etc/ztpserver/ztpserver.conf.

Parameters:conf – string path pointing to configuration file
Returns:a wsgi application object

config Module

class ztpserver.config.Attr(name, **kwargs)[source]

Bases: object

Base Attribute class for deriving all attributes for a Config object

Parameters:
  • name – required argument specifies attribute name
  • type – optional keyword argument specifies attribute type. the default argument type is String
  • group – optional keyword argument specifies attribute group. All attribute names must be unique within the group
  • default – optional keyword argument specifies the default value for the attribute. The default value is None
class ztpserver.config.BoolAttr(name, **kwargs)[source]

Bases: ztpserver.config.Attr

Boolean attribute class derived from Attr

class ztpserver.config.Config[source]

Bases: _abcoll.Mapping

The Config class represents the configuration for collection.

add_attribute(item, group=None)[source]
add_group(group)[source]
clear_value(name, group=None)[source]

clears the attributes value and resets it to default

read(filename)[source]
set_value(name, value, group=None)[source]
class ztpserver.config.Group(name, config)[source]

Bases: _abcoll.Mapping

The Group class provides a logical grouping of attributes in a Config object. Group names must be unique for each Config instance and cannot be assigned values.

Parameters:
  • name – the name of the group
  • config – the config object the group is associated with
add_attribute(item)[source]
class ztpserver.config.IntAttr(name, min_value=None, max_value=None, **kwargs)[source]

Bases: ztpserver.config.Attr

Integer attribute class derived from Attr

Parameters:
  • min_value – specifies the min value. the default is None
  • max_value – specifies the max value. the default is None
class ztpserver.config.ListAttr(name, delimiter=', ', **kwargs)[source]

Bases: ztpserver.config.Attr

List attribute class derived from Attr

Parameters:delimiter – specifies the delimiter character to split the string on
class ztpserver.config.StrAttr(name, choices=None, **kwargs)[source]

Bases: ztpserver.config.Attr

String attribute class derived from Attr

Parameters:choices – optional keyword argument specifies valid choices

controller Module

class ztpserver.controller.ActionsController(**kwargs)[source]

Bases: ztpserver.controller.BaseController

FOLDER = 'actions'
show(request, resource, **kwargs)[source]

Handles GET /actions/{resource}

class ztpserver.controller.BaseController(**kwargs)[source]

Bases: ztpserver.wsgiapp.WSGIController

FOLDER = None
expand(*args, **kwargs)[source]

Returns an expanded file path relative to data_root

http_bad_request(*args, **kwargs)[source]

Returns HTTP 400 Bad Request

http_internal_server_error(*args, **kwargs)[source]

Returns HTTP 500 Internal server error

http_not_found(*args, **kwargs)[source]

Returns HTTP 404 Not Found

class ztpserver.controller.BootstrapController(**kwargs)[source]

Bases: ztpserver.controller.BaseController

DEFAULT_CONFIG = {'xmpp': {}, 'logging': []}
FOLDER = 'bootstrap'
config(request, **kwargs)[source]

Handles GET /bootstrap/config

index(request, **kwargs)[source]

Handles GET /bootstrap

class ztpserver.controller.FilesController(**kwargs)[source]

Bases: ztpserver.controller.BaseController

FOLDER = 'files'
show(request, resource, **kwargs)[source]

Handles GET /files/{resource}

class ztpserver.controller.MetaController(**kwargs)[source]

Bases: ztpserver.controller.BaseController

BODY = {'sha1': None, 'size': None}
FOLDER = 'meta'
metadata(request, **kwargs)[source]

Handles GET /meta/[actions|files|nodes]/<PATH_INFO>

class ztpserver.controller.NodesController(**kwargs)[source]

Bases: ztpserver.controller.BaseController

FOLDER = 'nodes'
create(request, **kwargs)[source]

Handle the POST /nodes request

The create method will handle in incoming POST request from the node and determine if the node already exists or not. If the node does not exist, then the node will be created based on the request body.

Parameters:request (webob.Request) – the request object from WSGI
Returns:A dict as the result of the state machine which is used to create a WSGI response object.
do_actions(response, *args, **kwargs)[source]
do_resources(response, *args, **kwargs)[source]
do_substitution(response, *args, **kwargs)[source]
do_validation(response, *args, **kwargs)[source]
dump_node(response, *args, **kwargs)[source]

Writes the contents of the node to the repository

Parameters:
  • response (dict) – the response object being constructed
  • kwargs (dict) – arbitrary keyword arguments
Returns:

a tuple of response object and next state. The next state is ‘set_location’

finalize_response(response, *args, **kwargs)[source]
fsm(state, **kwargs)[source]

Execute the FSM for the request

get_attributes(response, *args, **kwargs)[source]

Reads the resource specific attributes file and stores it in the response dict as ‘attributes’

get_config(request, resource, **kwargs)[source]
get_definition(response, *args, **kwargs)[source]

Reads the node specific definition from disk and stores it in the repsonse dict with key definition

get_startup_config(response, *args, **kwargs)[source]
node_exists(response, *args, **kwargs)[source]

Checks if the node already exists and determines the next state

This method will check for the existence of the node in the repository based on the node_id. The node_id keyword is pulled from the kwargs dict.

Parameters:
  • response (dict) – the response object being constructed
  • kwargs (dict) – arbitrary keyword arguments
Returns:

A tuple that includes the updated response object and the next state to transition to. If the node already exists in the repository with a valid definition or startup-config, then the next state is ‘dump_node’ otherwise the next state is ‘post_config’

post_config(response, *args, **kwargs)[source]

Writes the nodes startup config file if found in the request

Parameters:
  • response (dict) – the response object being constructed
  • kwargs (dict) – arbitrary keyword arguments
Returns:

a tuple of response object and next state. If a config key was found in the request, the next state is ‘set_location’. If not, the next state is ‘post_node’.

post_node(response, *args, **kwargs)[source]

Checks topology validation matches and writes node specific files

This method will attempt to match the current node against the defined topology. If a match is found, then the pattern matched and definition (defined in the pattern) are written to the nodes folder in the repository and the response status is set to HTTP 201 Created.

Parameters:
  • response (dict) – the response object being constructed
  • kwargs (dict) – arbitrary keyword arguments
Returns:

a tuple of response object and next state. The next state is ‘dump_node’

Raises:
  • If a match is not found, then a log message is created and
  • an IndexError is raised. If the node does not already
  • exist in the repository, then a log message is created and a
  • FileObjectNotFound exception is raised
put_config(request, **kwargs)[source]
set_location(response, *args, **kwargs)[source]

Writes the HTTP Content-Location header

Parameters:
  • response (dict) – the response object being constructed
  • kwargs (dict) – arbitrary keyword arguments
Returns:

a tuple of response object and next state. The next state is None.

Raises:

Exception – catches a general exception for logging and then re-raises it

show(request, resource, *args, **kwargs)[source]

Handle the GET /nodes/{resource} request

Parameters:
  • request (webob.Request) – the request object from WSGI
  • resource (str) – the resource being requested
Returns:

A dict as the result of the state machine which is used to create a WSGI response object.

class ztpserver.controller.Router[source]

Bases: ztpserver.wsgiapp.WSGIRouter

Routes incoming requests by mapping the URL to a controller

exception ztpserver.controller.ValidationError[source]

Bases: exceptions.Exception

Base exception class for Pattern

repository Module

MODULE:
ztpserver.respository
AUTHOR:
Arista Networks
DESCRIPTION:
The repository module provides read and write access to files for ztpserver. The repository module can perform basic file system like functionality for performing basid CRUD on files and well as reading and writing specific file contents.
copyright:Copyright (c) 2014, Arista Networks
license:BSD, see LICENSE for more details
class ztpserver.repository.FileObject(name, path=None, **kwargs)[source]

Bases: object

The FileObject represents a single file entity in the repository. The instance provides convienent methods to read and write contents to the file using a specified serialization

hash()[source]

Returns the SHA1 hash of the object.

Raises:IOError
read(content_type=None, node_id=None)[source]

Reads the contents from the file system

Parameters:content_type (str) – defines the content_type of the file used to deserialize the object
Returns:object
Raises:FileObjectError

The read method will read the file from the file system, deserializing the contents as specified by the content_type argument. If the content_type argument is not specified, the read method will read the file as text. If any errors occur, a FileObjectError is raised.

size()[source]

Returns the size of the object in bytes.

Raises:IOError
write(contents, content_type=None)[source]

Writes the contents to the file

Parameters:
  • contents (str) – specifies the contents to be written to the file
  • content_type (str) – defines the serialization format to use when saving the file
Returns:

None

Raises:

FileObjectError

The write method takes the contents argument and writes it to the file using the serialization specified in the content_type argument. If the content_type argument is not specified, the contents are written as string text. This method will overwrite any contents that previously existed for the FileObj instance. If any errors are encountered during the write operation, a FileObjectError is raised

exception ztpserver.repository.FileObjectError[source]

Bases: exceptions.Exception

Base exception class for FileObject

exception ztpserver.repository.FileObjectNotFound[source]

Bases: ztpserver.repository.RepositoryError

Raised when a requested file is not found in the repository. This exception is a subclass of RespositoryError

class ztpserver.repository.Repository(path)[source]

Bases: object

The Respository class represents a repository of FileObject instances. It is an abstract wrapper providing the ability to interact with persistently stored files.

add_file(file_path, contents=None, content_type=None)[source]

Adds a new FileObject to the repository

Parameters:
  • file_path (str) – the full path of the file to add
  • contents (str) – the contents to write to the file
  • content_type (str) – specifies the serialization to use for the file
Returns:

FileObject

Raises:

RespositoryError

The add_file method allows for a new file to be added to the respository. If the file already exists, it is returned as an instance of FileObject. If the file doesn’t already exist and the contents argument is not None, then the file is created and the contents written to the file. The content_type argument provides the serialization to be used when saving the file.

add_folder(folder_path)[source]

Add a new folder to the repository

Parameters:folder_path (str) – the full path of the folder to add
Returns:str – the full path to the new folder
Raises:RespositoryError
delete_file(file_path)[source]

Deletes an existing file in the respository

Parameters:file_path (str) – the file path of the instance to delete
Returns:None
Raises:RepositoryError
exists(file_path)[source]

Returns boolean if the file_path exists in the repository

Parameters:file_path (str) – the file_path to check for existence
Returns:boolean – True if it exists otherwise False
expand(file_path)[source]

Expands a file_path to the full path to a file object

Parameters:file_path (str) – the file path to expand
Returns:str – the full path to the file

This method is used to transform a relative file path into an absolute file path for identifying a file object resource

get_file(file_path)[source]

Returns an intance of FileObject if it exists

Parameters:file_path (str) – the file path of the instance to return
Returns:instance of FileObject
Raises:FileObjectNotFound

This method will retrieve a file object instance if it exists in the repository. If the file does not exist then an error is raised

exception ztpserver.repository.RepositoryError[source]

Bases: exceptions.Exception

Base exception class for Repository

ztpserver.repository.create_repository(path)[source]

resources Module

class ztpserver.resources.ResourcePool(node_id)[source]

Bases: object

allocate(pool, node)[source]
dump(pool)[source]
load(pool)[source]
lookup(pool, node)[source]

Return an existing allocated resource if one exists

serialize()[source]
exception ztpserver.resources.ResourcePoolError[source]

Bases: exceptions.Exception

base error raised by Resource

serializers Module

class ztpserver.serializers.BaseSerializer(node_id)[source]

Bases: object

Base serializer object

deserialize(data)[source]

Deserialize an object to dict

serialize(data)[source]

Serialize a dict to object

class ztpserver.serializers.JSONSerializer(node_id)[source]

Bases: ztpserver.serializers.BaseSerializer

deserialize(data)[source]

Deserialize a JSON object and return a dict

serialize(data)[source]

Serialize a dict object and return JSON

class ztpserver.serializers.Serializer(node_id)[source]

Bases: object

add_handler(content_type, instance)[source]
deserialize(data, content_type=None)[source]

Deserialize the data based on the content_type

handlers[source]
serialize(data, content_type)[source]

Serialize the data based on the content_type

exception ztpserver.serializers.SerializerError[source]

Bases: exceptions.Exception

base error raised by serialization functions

class ztpserver.serializers.TextSerializer(node_id)[source]

Bases: ztpserver.serializers.BaseSerializer

deserialize(data)[source]

Deserialize a text object and return a dict

serialize(data)[source]

Serialize a dict object and return text

class ztpserver.serializers.YAMLSerializer(node_id)[source]

Bases: ztpserver.serializers.BaseSerializer

deserialize(data)[source]

Deserialize a YAML object and return a dict

serialize(data)[source]

Serialize a dict object and return YAML

ztpserver.serializers.dump(data, file_path, content_type, node_id=None)[source]
ztpserver.serializers.dumps(data, content_type, node_id)[source]
ztpserver.serializers.load(file_path, content_type, node_id=None)[source]
ztpserver.serializers.loads(data, content_type, node_id)[source]

topology Module

class ztpserver.topology.ExactFunction(value)[source]

Bases: ztpserver.topology.Function

match(arg)[source]
class ztpserver.topology.ExcludesFunction(value)[source]

Bases: ztpserver.topology.Function

match(arg)[source]
class ztpserver.topology.Function(value)[source]

Bases: object

match(arg)[source]
class ztpserver.topology.IncludesFunction(value)[source]

Bases: ztpserver.topology.Function

match(arg)[source]
class ztpserver.topology.InterfacePattern(interface, remote_device, remote_interface, node_id)[source]

Bases: object

FUNCTIONS = {'regex': <class 'ztpserver.topology.RegexFunction'>, 'excludes': <class 'ztpserver.topology.ExcludesFunction'>, 'exact': <class 'ztpserver.topology.ExactFunction'>, 'includes': <class 'ztpserver.topology.IncludesFunction'>}
KEYWORDS = {'none': <ztpserver.topology.RegexFunction object at 0x7fbac13eddd0>, 'any': <ztpserver.topology.RegexFunction object at 0x7fbac13edd90>}
compile(value)[source]
is_positive_constraint()[source]
match(interface, neighbors)[source]
match_interface(interface)[source]
match_neighbor(interface, neighbor)[source]
match_remote_device(remote_device)[source]
match_remote_interface(remote_interface)[source]
refresh()[source]
exception ztpserver.topology.InterfacePatternError[source]

Bases: exceptions.Exception

Base exception class for InterfacePattern

class ztpserver.topology.Neighbor

Bases: tuple

Neighbor(device, interface)

__getnewargs__()

Return self as a plain tuple. Used by copy and pickle.

__getstate__()

Exclude the OrderedDict from pickling

__repr__()

Return a nicely formatted representation string

device

Alias for field number 0

interface

Alias for field number 1

class ztpserver.topology.Neighbordb(node_id)[source]

Bases: object

RESERVED_VARIABLES = ['any', 'none']
add_pattern(name, **kwargs)[source]
add_patterns(patterns)[source]
add_variable(key, value, overwrite=False)[source]
add_variables(variables)[source]
find_patterns(node)[source]
get_patterns()[source]
static identifier(node)[source]
is_global_pattern(pattern)[source]
is_node_pattern(pattern)[source]
match_node(node)[source]
exception ztpserver.topology.NeighbordbError[source]

Bases: exceptions.Exception

Base exception class for Neighbordb

class ztpserver.topology.Node(**kwargs)[source]

Bases: object

A Node object is maps the metadata from an EOS node. It provides access to the node’s meta data including interfaces and the associated neighbors found on those interfaces.

add_neighbor(interface, peers)[source]
add_neighbors(neighbors)[source]
identifier()[source]
serialize()[source]
exception ztpserver.topology.NodeError[source]

Bases: exceptions.Exception

Base exception class for Node

class ztpserver.topology.OrderedCollection(*args, **kwds)[source]

Bases: collections.OrderedDict

base object for using an ordered dictionary

class ztpserver.topology.Pattern(name=None, definition=None, interfaces=None, node=None, variables=None, node_id=None)[source]

Bases: object

add_interface(interface)[source]
add_interfaces(interfaces)[source]
match_node(node)[source]
parse_interface(neighbor)[source]
serialize()[source]
variable_substitution()[source]
exception ztpserver.topology.PatternError[source]

Bases: exceptions.Exception

Base exception class for Pattern

class ztpserver.topology.RegexFunction(value)[source]

Bases: ztpserver.topology.Function

match(arg)[source]
ztpserver.topology.create_node(nodeattrs)[source]
ztpserver.topology.default_filename()[source]

Returns the path for neighbordb based on the conf file

ztpserver.topology.load_file(filename, content_type, node_id)[source]

Returns the contents of a file specified by filename.

The requred content_type argument is required and indicates the text serialization format the contents are stored in.

If the serializer load function encounters errors, None is returned

ztpserver.topology.load_neighbordb(node_id, contents=None)[source]
ztpserver.topology.load_pattern(pattern, content_type='application/yaml', node_id=None)[source]

Returns an instance of Pattern

ztpserver.topology.replace_config_action(resource, filename=None)[source]

Builds a definition with a single action replace_config

ztpserver.topology.resources(attributes, node, node_id)[source]

types Module

class ztpserver.types.Boolean[source]

Bases: object

FALSEVALUES = ['no', 'false', '0', 'off']
TRUEVALUES = ['yes', 'true', '1', 'on']
class ztpserver.types.Integer(min_value=None, max_value=None)[source]

Bases: object

class ztpserver.types.List(delimiter=', ')[source]

Bases: object

class ztpserver.types.String(choices=None)[source]

Bases: object

utils Module

ztpserver.utils.atoi(text)[source]
ztpserver.utils.expand_range(interfaces)[source]

Returns a naturally sorted list of items expanded from interfaces.

ztpserver.utils.natural_keys(text)[source]
ztpserver.utils.parse_interface(neighbor, node_id)[source]

validators Module

class ztpserver.validators.InterfacePatternValidator(node_id)[source]

Bases: ztpserver.validators.Validator

validate_interface_pattern()[source]
class ztpserver.validators.NeighbordbValidator(node_id)[source]

Bases: ztpserver.validators.Validator

validate_patterns()[source]
validate_variables()[source]
class ztpserver.validators.PatternValidator(node_id)[source]

Bases: ztpserver.validators.Validator

validate_attributes()[source]
validate_definition()[source]
validate_interfaces()[source]
validate_name()[source]
validate_node()[source]
validate_variables()[source]
exception ztpserver.validators.ValidationError[source]

Bases: exceptions.Exception

Base error class for validation failures

class ztpserver.validators.Validator(node_id)[source]

Bases: object

error(err, *args, **kwargs)[source]
validate(data=None)[source]
ztpserver.validators.validate_neighbordb(contents, node_id)[source]
ztpserver.validators.validate_pattern(contents, node_id)[source]

wsgiapp Module

class ztpserver.wsgiapp.WSGIController[source]

Bases: object

create(request, **kwargs)[source]
delete(request, resource, **kwargs)[source]
edit(request, resource, **kwargs)[source]
index(request, **kwargs)[source]
new(request, **kwargs)[source]
response(**kwargs)[source]
show(request, resource, **kwargs)[source]
update(request, resource, **kwargs)[source]
class ztpserver.wsgiapp.WSGIRouter(mapper)[source]

Bases: object

route[source]

Turns a request-taking, response-returning function into a WSGI app

You can use this like:

@wsgify
def myfunc(req):
    return webob.Response('hey there')

With that myfunc will be a WSGI application, callable like app_iter = myfunc(environ, start_response). You can also call it like normal, e.g., resp = myfunc(req). (You can also wrap methods, like def myfunc(self, req).)

If you raise exceptions from webob.exc they will be turned into WSGI responses.

There are also several parameters you can use to customize the decorator. Most notably, you can use a webob.Request subclass, like:

class MyRequest(webob.Request):
    @property
    def is_local(self):
        return self.remote_addr == '127.0.0.1'
@wsgify(RequestClass=MyRequest)
def myfunc(req):
    if req.is_local:
        return Response('hi!')
    else:
        raise webob.exc.HTTPForbidden

Another customization you can add is to add args (positional arguments) or kwargs (of course, keyword arguments). While generally not that useful, you can use this to create multiple WSGI apps from one function, like:

import simplejson
def serve_json(req, json_obj):
    return Response(json.dumps(json_obj),
                    content_type='application/json')

serve_ob1 = wsgify(serve_json, args=(ob1,))
serve_ob2 = wsgify(serve_json, args=(ob2,))

You can return several things from a function:

  • A webob.Response object (or subclass)
  • Any WSGI application
  • None, and then req.response will be used (a pre-instantiated Response object)
  • A string, which will be written to req.response and then that response will be used.
  • Raise an exception from webob.exc

Also see wsgify.middleware() for a way to make middleware.

You can also subclass this decorator; the most useful things to do in a subclass would be to change RequestClass or override call_func (e.g., to add req.urlvars as keyword arguments to the function).