{ "info": { "author": "Angelo Failla", "author_email": "pallotron@fb.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3 :: Only", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: System :: Boot", "Topic :: Utilities" ], "description": "[![Build Status](https://travis-ci.org/facebook/fbtftp.svg?branch=master)](https://travis-ci.org/facebook/fbtftp)\n[![codebeat badge](https://codebeat.co/badges/2d4c7650-4752-4adf-a570-1948ecb4d6a8)](https://codebeat.co/projects/github-com-facebook-fbtftp)\n\n# What is fbtftp?\n\n`fbtftp` is Facebook's implementation of a dynamic TFTP server framework. It\nlets you create custom TFTP servers and wrap your own logic into it in a very\nsimple manner.\nFacebook currently uses it in production, and it's deployed at global scale\nacross all of our data centers.\n\n# Why did you do that?\n\nWe love to use existing open source software and to contribute upstream, but\nsometimes it's just not enough at our scale. We ended up writing our own tftp\nframework and decided to open source it.\n\n`fbtftp` was born from the need of having an easy-to-configure and\neasy-to-expand TFTP server, that would work at large scale. The standard\n`in.tftpd` is a 20+ years old piece of software written in C that is very\ndifficult to extend.\n\n`fbtftp` is written in `python3` and lets you plug your own logic to:\n\n* publish per session and server wide statistics to your infrastructure\n* define how response data is built:\n * can be a file from disk;\n * can be a file created dynamically;\n * you name it!\n\n# How do you use `fbtftp` at Facebook?\n\nWe created our own Facebook-specific server based on the framework to:\n\n* stream static files (initrd and kernels) from our http repositories (no need\n to fill your tftp root directory with files);\n* generate grub2 per-machine configuration dynamically (no need to copy grub2\n configuration files on disk);\n* publish per-server and per-connection statistics to our internal monitoring\n systems;\n* deployment is easy and \"container-ready\", just copy the application somewhere,\n start it and you are done.\n\n# Is it better than the other TFTP servers?\n\nIt depends on your needs! `fbtftp` is written in Python 3 using a\nmultiprocessing model; its primary focus is not speed, but flexibility and\nscalability. Yet it is fast enough at our datacenter scale :)\nIt is well-suited for large installations where scalability and custom features\nare needed.\n\n# What does it support?\n\nThe framework implements the following RFCs:\n\n* [RFC 1350](https://tools.ietf.org/html/rfc1350) (the main TFTP specification)\n* [RFC 2347](https://tools.ietf.org/html/rfc2347) (Option Extension)\n* [RFC 2348](https://tools.ietf.org/html/rfc2348) (Blocksize option)\n* [RFC 2349](https://tools.ietf.org/html/rfc2349) (Timeout Interval and Transfer\n Size Options).\n\nNote that the server framework only support RRQs (read only) operations.\n(Who uses WRQ TFTP requests in 2016? :P)\n\n# How does it work?\n\nAll you need to do is understanding three classes and two callback functions,\nand you are good to go:\n\n* `BaseServer`: This class implements the process which deals with accepting new\n requests on the UDP port provided. Default TFTP parameters like timeout, port\n number and number of retries can be passed. This class doesn't have to be used\n directly, you must inherit from it and override `get_handler()` method to\n return an instance of `BaseHandler`.\n The class accepts a `server_stats_callback`, more about it below. the callback\n is not re-entrant, if you need this you have to implement your own locking\n logic. This callback is executed periodically and you can use it to publish\n server level stats to your monitoring infrastructure. A series of predefined\n counters are provided. Refer to the class documentation to find out more.\n\n* `BaseHandler`: This class deals with talking to a single client. This class\n lives into its separate process, process which is spawned by the `BaserServer`\n class, which will make sure to reap the child properly when the session is\n over. Do not use this class as is, instead inherit from it and override the `get_response_data()` method. Such method must return an instance of a subclass of `ResponseData`.\n\n* `ResponseData`: it's a file-like class that implements `read(num_bytes)`,\n `size()` and `close()`. As the previous two classes you'll have to inherit\n from this and implement those methods. This class basically let you define how\n to return the actual data\n\n* `server_stats_callback`: function that is called periodically (every 60\n seconds by default). The callback is not re-entrant, if you need this you have\n to implement your own locking logic. This callback is executed periodically\n and you can use it to publish server level stats to your monitoring\n infrastructure. A series of predefined counters are provided.\n Refer to the class documentation to find out more.\n\n* `session_stats_callback`: function that is called when a client session is\n over.\n\n# Requirements\n\n* Linux (or any system that supports [`epoll`](http://linux.die.net/man/4/epoll))\n* Python 3.x\n\n# Installation\n\n`fbtftp` is distributed with the standard `distutils` package, so you can build\nit with:\n\n```\npython setup.py build\n```\n\nand install it with:\n\n```\npython setup.py install\n```\n\nBe sure to run as root if you want to install `fbtftp` system wide. You can also\nuse a `virtualenv`, or install it as user by running:\n\n```\npython setup.py install --user\n```\n\n# Example\n\nWriting your own server is simple. Let's take a look at how to write a simple\nserver that serves files from disk:\n\n```python\nfrom fbtftp.base_handler import BaseHandler\nfrom fbtftp.base_handler import ResponseData\nfrom fbtftp.base_server import BaseServer\n\nimport os\n\nclass FileResponseData(ResponseData):\n def __init__(self, path):\n self._size = os.stat(path).st_size\n self._reader = open(path, 'rb')\n\n def read(self, n):\n return self._reader.read(n)\n\n def size(self):\n return self._size\n\n def close(self):\n self._reader.close()\n\ndef print_session_stats(stats):\n print(stats)\n\ndef print_server_stats(stats):\n counters = stats.get_and_reset_all_counters()\n print('Server stats - every {} seconds'.format(stats.interval))\n print(counters)\n\nclass StaticHandler(BaseHandler):\n def __init__(self, server_addr, peer, path, options, root, stats_callback):\n self._root = root\n super().__init__(server_addr, peer, path, options, stats_callback)\n\n def get_response_data(self):\n return FileResponseData(os.path.join(self._root, self._path))\n\nclass StaticServer(BaseServer):\n def __init__(self, address, port, retries, timeout, root,\n handler_stats_callback, server_stats_callback=None):\n self._root = root\n self._handler_stats_callback = handler_stats_callback\n super().__init__(address, port, retries, timeout, server_stats_callback)\n\n def get_handler(self, server_addr, peer, path, options):\n return StaticHandler(\n server_addr, peer, path, options, self._root,\n self._handler_stats_callback)\n\ndef main():\n server = StaticServer(ip='', port='1069', retries=3, timeout=5,\n root='/var/tftproot', print_session_stats,\n print_server_stats)\n try:\n server.run()\n except KeyboardInterrupt:\n server.close()\n\nif __name__ == '__main__':\n main()\n```\n\n# Who wrote it?\n\n`fbtftp` was created by Marcin Wyszynski (@marcinwyszynski) and Angelo Failla at Facebook Ireland.\n\nOther honorable contributors:\n* Andrea Barberio \n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://www.github.com/facebook/fbtftp", "keywords": "tftp daemon infrastructure provisioning netboot", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "fbtftp", "package_url": "https://pypi.org/project/fbtftp/", "platform": "", "project_url": "https://pypi.org/project/fbtftp/", "project_urls": { "Homepage": "https://www.github.com/facebook/fbtftp" }, "release_url": "https://pypi.org/project/fbtftp/0.2/", "requires_dist": null, "requires_python": "", "summary": "A python3 framework to build dynamic TFTP servers", "version": "0.2" }, "last_serial": 3213704, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "567720601f433d5628162c57d5e613df", "sha256": "d51093985327c7aac9f1a7c50d3655f9dd9ff8af316fc03668efce94b12490e9" }, "downloads": -1, "filename": "fbtftp-0.1.tar.gz", "has_sig": false, "md5_digest": "567720601f433d5628162c57d5e613df", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22281, "upload_time": "2016-05-27T12:07:11", "url": "https://files.pythonhosted.org/packages/ca/44/d08df739facf3ec56ad358775050053dc9d73f915c04cf6bdf044ba4e7c2/fbtftp-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "9ef961a3aca22a2ee2066000de291572", "sha256": "8fc84ce3a6ab7d53864333779faca80b762a4c71c3ffe221fd3ebb9a74fef0b3" }, "downloads": -1, "filename": "fbtftp-0.2.tar.gz", "has_sig": false, "md5_digest": "9ef961a3aca22a2ee2066000de291572", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22788, "upload_time": "2017-09-29T20:13:15", "url": "https://files.pythonhosted.org/packages/df/fd/3fabfbcf25c3f16e29fd9ef8e6d0e7ce26de15048ce94f010cc97f3434af/fbtftp-0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "9ef961a3aca22a2ee2066000de291572", "sha256": "8fc84ce3a6ab7d53864333779faca80b762a4c71c3ffe221fd3ebb9a74fef0b3" }, "downloads": -1, "filename": "fbtftp-0.2.tar.gz", "has_sig": false, "md5_digest": "9ef961a3aca22a2ee2066000de291572", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22788, "upload_time": "2017-09-29T20:13:15", "url": "https://files.pythonhosted.org/packages/df/fd/3fabfbcf25c3f16e29fd9ef8e6d0e7ce26de15048ce94f010cc97f3434af/fbtftp-0.2.tar.gz" } ] }