From 292e8c9cfd1d401e9b85b5bfab12460a71a7803d Mon Sep 17 00:00:00 2001 From: Serge Kovaleff Date: Wed, 18 Nov 2015 17:27:05 +0200 Subject: [PATCH] Generate Sphinx docs Change-Id: I540b28d6173b30baf6ee2e6e14d8ba5ffb67b660 Closes-Bug: #1514803 --- .gitignore | 2 +- README.rst | 540 +----------------- doc/Makefile | 159 ++++++ doc/source/.gitignore | 2 + doc/source/api/HTTP-API.rst | 274 +++++++++ doc/source/conf.py | 90 +++ doc/source/deploy/install-guide.rst | 241 ++++++++ doc/source/dev/contributing_link.rst | 3 + doc/source/index.rst | 73 +++ .../troubleshooting/troubleshooting.rst | 113 ++++ doc/source/usage/usage.rst | 187 ++++++ .../notes/sphinx-docs-4d0a5886261e57bf.yaml | 12 + setup.cfg | 5 + test-requirements.txt | 1 + tox.ini | 7 + 15 files changed, 1174 insertions(+), 535 deletions(-) create mode 100644 doc/Makefile create mode 100644 doc/source/.gitignore create mode 100644 doc/source/api/HTTP-API.rst create mode 100644 doc/source/conf.py create mode 100644 doc/source/deploy/install-guide.rst create mode 100644 doc/source/dev/contributing_link.rst create mode 100644 doc/source/index.rst create mode 100644 doc/source/troubleshooting/troubleshooting.rst create mode 100644 doc/source/usage/usage.rst create mode 100644 releasenotes/notes/sphinx-docs-4d0a5886261e57bf.yaml diff --git a/.gitignore b/.gitignore index ad83135f6..73b013cac 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ # Sphinx _build -doc/source/api/ +#doc/source/api/ # release notes build releasenotes/build diff --git a/README.rst b/README.rst index 2af736630..73a9c0251 100644 --- a/README.rst +++ b/README.rst @@ -24,6 +24,9 @@ Refer to CONTRIBUTING.rst_ for instructions on how to contribute. .. _Ironic: https://wiki.openstack.org/wiki/Ironic .. _PyPI: https://pypi.python.org/pypi/ironic-inspector .. _CONTRIBUTING.rst: https://github.com/openstack/ironic-inspector/blob/master/CONTRIBUTING.rst +.. _diskimage-builder: https://github.com/openstack/diskimage-builder +.. _ironic-discoverd-ramdisk element: https://github.com/openstack/diskimage-builder/tree/master/elements/ironic-discoverd-ramdisk +.. _Configuration: https://github.com/openstack/ironic-inspector/blob/master/doc/source/install-guide.rst .. note:: **ironic-inspector** was called *ironic-discoverd* before version 2.0.0. @@ -66,7 +69,7 @@ Usual hardware introspection flow is as follows: Power management credentials should be provided to Ironic at this step. * Nodes are put in the correct state for introspection as described in - `Node States`_. + :ref:`node_states`. * Operator sends nodes on introspection using **ironic-inspector** API or CLI (see Usage_). @@ -110,543 +113,12 @@ Usual hardware introspection flow is as follows: for a given node. * Nodes are put in the correct state for deploying as described in - `Node States`_. + :ref:`node_states`. Starting DHCP server and configuring PXE boot environment is not part of this package and should be done separately. .. _instack-undercloud: https://www.rdoproject.org/Deploying_an_RDO_Undercloud_with_Instack .. _Ironic inspection documentation: http://docs.openstack.org/developer/ironic/deploy/install-guide.html#hardware-inspection +.. _Usage: https://github.com/openstack/ironic-inspector/blob/master/doc/source/usage.rst -Installation ------------- - -Install from PyPI_ (you may want to use virtualenv to isolate your -environment):: - - pip install ironic-inspector - -Also there is a `DevStack `_ -plugin for **ironic-inspector** - see CONTRIBUTING.rst_ for the current status. - -Finally, some distributions (e.g. Fedora) provide **ironic-inspector** -packaged, some of them - under its old name *ironic-discoverd*. - -Configuration -~~~~~~~~~~~~~ - -Copy ``example.conf`` to some permanent place -(e.g. ``/etc/ironic-inspector/inspector.conf``). -Fill in at least these configuration values: - -* ``os_username``, ``os_password``, ``os_tenant_name`` - Keystone credentials - to use when accessing other services and check client authentication tokens; - -* ``os_auth_url``, ``identity_uri`` - Keystone endpoints for validating - authentication tokens and checking user roles; - -* ``connection`` in the ``database`` section - SQLAlchemy connection string - for the database; - -* ``dnsmasq_interface`` - interface on which ``dnsmasq`` (or another DHCP - service) listens for PXE boot requests (defaults to ``br-ctlplane`` which is - a sane default for TripleO-based installations but is unlikely to work for - other cases). - -See comments inside `example.conf -`_ -for the other possible configuration options. - -.. note:: - Configuration file contains a password and thus should be owned by ``root`` - and should have access rights like ``0600``. - -**ironic-inspector** requires root rights for managing iptables. It gets them -by running ``ironic-inspector-rootwrap`` utility with ``sudo``. -To allow it, copy file ``rootwrap.conf`` and directory ``rootwrap.d`` to the -configuration directory (e.g. ``/etc/ironic-inspector/``) and create file -``/etc/sudoers.d/ironic-inspector-rootwrap`` with the following content:: - - stack ALL=(root) NOPASSWD: /usr/bin/ironic-inspector-rootwrap /etc/ironic-inspector/rootwrap.conf * - -.. DANGER:: - Be very careful about typos in ``/etc/sudoers.d/ironic-inspector-rootwrap`` - as any typo will break sudo for **ALL** users on the system. Especially, - make sure there is a new line at the end of this file. - -.. note:: - ``rootwrap.conf`` and all files in ``rootwrap.d`` must be writeable - only by root. - -.. note:: - If you store ``rootwrap.d`` in a different location, make sure to update - the *filters_path* option in ``rootwrap.conf`` to reflect the change. - - If your ``rootwrap.conf`` is in a different location, then you need - to update the *rootwrap_config* option in ``ironic-inspector.conf`` - to point to that location. - -Replace ``stack`` with whatever user you'll be using to run -**ironic-inspector**. - -Configuring PXE -^^^^^^^^^^^^^^^ - -As for PXE boot environment, you'll need: - -* TFTP server running and accessible (see below for using *dnsmasq*). - Ensure ``pxelinux.0`` is present in the TFTP root. - - -* You need PXE boot server (e.g. *dnsmasq*) running on **the same** machine as - **ironic-inspector**. Don't do any firewall configuration: - **ironic-inspector** will handle it for you. In **ironic-inspector** - configuration file set ``dnsmasq_interface`` to the interface your - PXE boot server listens on. Here is an example *dnsmasq.conf*:: - - port=0 - interface={INTERFACE} - bind-interfaces - dhcp-range={DHCP IP RANGE, e.g. 192.168.0.50,192.168.0.150} - enable-tftp - tftp-root={TFTP ROOT, e.g. /tftpboot} - dhcp-boot=pxelinux.0 - -* You have to install and configure one of 2 available ramdisks: simple - bash-based (see `Using simple ramdisk`_) or more complex based on - ironic-python-agent_ (See `Using IPA`_). - -Here is *inspector.conf* you may end up with:: - - [DEFAULT] - debug = false - [ironic] - identity_uri = http://127.0.0.1:35357 - os_auth_url = http://127.0.0.1:5000/v2.0 - os_username = admin - os_password = password - os_tenant_name = admin - [firewall] - dnsmasq_interface = br-ctlplane - -.. note:: - Set ``debug = true`` if you want to see complete logs. - -Using simple ramdisk -^^^^^^^^^^^^^^^^^^^^ - -* Build and put into your TFTP the kernel and ramdisk created using the - diskimage-builder_ `ironic-discoverd-ramdisk element`_:: - - ramdisk-image-create -o discovery fedora ironic-discoverd-ramdisk - - You need diskimage-builder_ 0.1.38 or newer to do it (using the latest one - is always advised). - -* Configure your ``$TFTPROOT/pxelinux.cfg/default`` with something like:: - - default introspect - - label introspect - kernel discovery.kernel - append initrd=discovery.initramfs discoverd_callback_url=http://{IP}:5050/v1/continue - - ipappend 3 - - Replace ``{IP}`` with IP of the machine (do not use loopback interface, it - will be accessed by ramdisk on a booting machine). - - .. note:: - There are some prebuilt images which use obsolete ``ironic_callback_url`` - instead of ``discoverd_callback_url``. Modify ``pxelinux.cfg/default`` - accordingly if you have one of these. - -Using IPA -^^^^^^^^^ - -ironic-python-agent_ is a new ramdisk developed for Ironic. During the Liberty -cycle support for **ironic-inspector** was added. This is experimental -for now, but we plan on making IPA the default ramdisk in Mitaka cycle. - -.. note:: - You need at least 1.5 GiB of RAM on the machines to use this ramdisk. - -To build an ironic-python-agent ramdisk, do the following: - -* Get the latest diskimage-builder_:: - - sudo pip install -U "diskimage-builder>=1.1.2" - -* Build the ramdisk:: - - disk-image-create ironic-agent fedora -o ironic-agent - - .. note:: - Replace "fedora" with your distribution of choice. - -* Copy resulting files ``ironic-agent.vmlinuz`` and ``ironic-agent.initramfs`` - to the TFTP root directory. - -Next, set up ``$TFTPROOT/pxelinux.cfg/default`` as follows:: - - default introspect - - label introspect - kernel ironic-agent.vmlinuz - append initrd=ironic-agent.initramfs ipa-inspection-callback-url=http://{IP}:5050/v1/continue systemd.journald.forward_to_console=yes - - ipappend 3 - -Replace ``{IP}`` with IP of the machine (do not use loopback interface, it -will be accessed by ramdisk on a booting machine). - -.. note:: - While ``systemd.journald.forward_to_console=yes`` is not actually - required, it will substantially simplify debugging if something goes wrong. - -.. _diskimage-builder: https://github.com/openstack/diskimage-builder -.. _ironic-discoverd-ramdisk element: https://github.com/openstack/diskimage-builder/tree/master/elements/ironic-discoverd-ramdisk -.. _ironic-python-agent: https://github.com/openstack/ironic-python-agent - -Managing the **ironic-inspector** database -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**ironic-inspector** provides a command line client for managing its database, -this client can be used for upgrading, and downgrading the database using -alembic migrations. - -If this is your first time running **ironic-inspector** to migrate the -database simply run: -:: - - ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade - -If you have previously run a version of **ironic-inspector** earlier than -2.2.0, the safest thing is to delete the existing SQLite database and run -``upgrade`` as shown above. If you, however, want to save the existing -database, to ensure your database will work with the migrations, you'll need to -run an extra step before upgrading the database. You only need to do this the -first time running version 2.2.0 or later. - -If you are upgrading from **ironic-inspector** version 2.1.0 or lower: -:: - - ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf stamp --revision 578f84f38d - ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade - -If you are upgrading from a git master install of **ironic-inspector** from -after `Introspection Rules`_ were introduced: -:: - - ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf stamp --revision d588418040d - ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade - -Other available commands can be discovered by running:: - - ironic-inspector-dbsync --help - -Running -~~~~~~~ - -:: - - ironic-inspector --config-file /etc/ironic-inspector/inspector.conf - -A good starting point for writing your own *systemd* unit should be `one used -in Fedora `_ -(note usage of old name). - -Usage ------ - -Refer to HTTP-API.rst_ for information on the HTTP API. -Refer to the `client page`_ for information on how to use CLI and Python -library. - -.. _HTTP-API.rst: https://github.com/openstack/ironic-inspector/blob/master/HTTP-API.rst -.. _HTTP API: https://github.com/openstack/ironic-inspector/blob/master/HTTP-API.rst -.. _client page: https://pypi.python.org/pypi/python-ironic-inspector-client - -Using from Ironic API -~~~~~~~~~~~~~~~~~~~~~ - -Ironic Kilo introduced support for hardware introspection under name of -"inspection". **ironic-inspector** introspection is supported for some generic -drivers, please refer to `Ironic inspection documentation`_ for details. - -Node States -~~~~~~~~~~~ - -* The nodes should be moved to ``MANAGEABLE`` provision state before - introspection (requires *python-ironicclient* of version 0.5.0 or newer):: - - ironic node-set-provision-state manage - -* After successful introspection and before deploying nodes should be made - available to Nova, by moving them to ``AVAILABLE`` state:: - - ironic node-set-provision-state provide - - .. note:: - Due to how Nova interacts with Ironic driver, you should wait 1 minute - before Nova becomes aware of available nodes after issuing this command. - Use ``nova hypervisor-stats`` command output to check it. - -Introspection Rules -~~~~~~~~~~~~~~~~~~~ - -Inspector supports a simple JSON-based DSL to define rules to run during -introspection. Inspector provides an API to manage such rules, and will run -them automatically after running all processing hooks. - -A rule consists of conditions to check, and actions to run. If conditions -evaluate to true on the introspection data, then actions are run on a node. -All actions have "rollback actions" associated with them, which are run when -conditions evaluate to false. This way we can safely rerun introspection. - -Available conditions and actions are defined by plugins, and can be extended, -see CONTRIBUTING.rst_ for details. See `HTTP API`_ for specific calls to define -introspection rules. - -Conditions -^^^^^^^^^^ - -A condition is represented by an object with fields: - -``op`` the type of comparison operation, default available operators include : -``eq``, ``le``, ``ge``, ``ne``, ``lt``, ``gt`` (basic comparison operators), -``in-net`` (checks that IP address is in a given network). - -``field`` a `JSON path `_ to the field -in the introspection data to use in comparison. - -``multiple`` how to treat situations where the ``field`` query returns multiple -results (e.g. the field contains a list), available options are: - -* ``any`` (the default) require any to match, -* ``all`` require all to match, -* ``first`` requrie the first to match. - -All other fields are passed to the condition plugin, e.g. numeric comparison -operations require a ``value`` field to compare against. - -Actions -^^^^^^^ - -An action is represented by an object with fields: - -``action`` type of action. Possible values are defined by plugins. - -All other fields are passed to the action plugin. - -Default available actions include: - -* ``fail`` fail introspection. Requires a ``message`` parameter for the failure - message. - -* ``set-attribute`` sets an attribute on an Ironic node. Requires a ``path`` - field, which is the path to the attribute as used by ironic (e.g. - ``/properties/something``), and a ``value`` to set. - -* ``set-capability`` sets a capability on an Ironic node. Requires ``name`` - and ``value`` fields, which are the name and the value for a new capability - accordingly. Existing value for this same capability is replaced. - -* ``extend-attribute`` the same as ``set-attribute``, but treats existing - value as a list and appends value to it. If optional ``unique`` parameter is - set to ``True``, nothing will be added if given value is already in a list. - -Setting IPMI Credentials -~~~~~~~~~~~~~~~~~~~~~~~~ - -If you have physical access to your nodes, you can use **ironic-inspector** to -set IPMI credentials for them without knowing the original ones. The workflow -is as follows: - -* Ensure nodes will PXE boot on the right network by default. - -* Set ``enable_setting_ipmi_credentials = true`` in the **ironic-inspector** - configuration file, restart **ironic-inspector**. - -* Enroll nodes in Ironic with setting their ``ipmi_address`` only (or - equivalent driver-specific property, as per ``ipmi_address_fields`` - configuration option). - - With Ironic Liberty use ironic API version ``1.11``, so that new node gets - into ``enroll`` provision state:: - - ironic --ironic-api-version 1.11 node-create -d -i ipmi_address=
- - Providing ``ipmi_address`` allows **ironic-inspector** to distinguish nodes. - -* With Ironic Kilo or older, set maintenance mode on nodes. - That's an important step, otherwise Ironic might interfere with introspection - process. This is replaced by ``enroll`` state in Ironic Liberty. - -* Start introspection with providing additional parameters: - - * ``new_ipmi_password`` IPMI password to set, - * ``new_ipmi_username`` IPMI user name to set, defaults to one in node - driver_info. - -* Manually power on the nodes and wait. - -* After introspection is finished (watch nodes power state or use - **ironic-inspector** status API) you can move node to ``manageable`` and - then ``available`` states - see `Node States`_. With Ironic Kilo you have to - move a node out of maintenance mode. - -Note that due to various limitations on password value in different BMC, -**ironic-inspector** will only accept passwords with length between 1 and 20 -consisting only of letters and numbers. - -Plugins -~~~~~~~ - -**ironic-inspector** heavily relies on plugins for data processing. Even the -standard functionality is largely based on plugins. Set ``processing_hooks`` -option in the configuration file to change the set of plugins to be run on -introspection data. Note that order does matter in this option. - -These are plugins that are enabled by default and should not be disabled, -unless you understand what you're doing: - -``ramdisk_error`` - reports error, if ``error`` field is set by the ramdisk, also optionally - stores logs from ``logs`` field, see `HTTP API`_ for details. -``scheduler`` - validates and updates basic hardware scheduling properties: CPU number and - architecture, memory and disk size. -``validate_interfaces`` - validates network interfaces information. - -Here are some plugins that can be additionally enabled: - -``example`` - example plugin logging it's input and output. -``raid_device`` (deprecated name ``root_device_hint``) - gathers block devices from ramdisk and exposes root device in multiple - runs. -``extra_hardware`` - stores the value of the 'data' key returned by the ramdisk as a JSON - encoded string in a Swift object. The plugin will also attempt to convert - the data into a format usable by introspection rules. If this is successful - then the new format will be stored in the 'extra' key. The 'data' key is - then deleted from the introspection data, as unless converted it's assumed - unusable by introspection rules. - -Refer to CONTRIBUTING.rst_ for information on how to write your own plugin. - -Troubleshooting ---------------- - -Errors when starting introspection -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -* *Invalid provision state "available"* - - In Kilo release with *python-ironicclient* 0.5.0 or newer Ironic - defaults to reporting provision state ``AVAILABLE`` for newly enrolled - nodes. **ironic-inspector** will refuse to conduct introspection in - this state, as such nodes are supposed to be used by Nova for scheduling. - See `Node States`_ for instructions on how to put nodes into - the correct state. - -Introspection times out -~~~~~~~~~~~~~~~~~~~~~~~ - -There may be 3 reasons why introspection can time out after some time -(defaulting to 60 minutes, altered by ``timeout`` configuration option): - -#. Fatal failure in processing chain before node was found in the local cache. - See `Troubleshooting data processing`_ for the hints. - -#. Failure to load the ramdisk on the target node. See `Troubleshooting - PXE boot`_ for the hints. - -#. Failure during ramdisk run. See `Troubleshooting ramdisk run`_ for the - hints. - -Troubleshooting data processing -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In this case **ironic-inspector** logs should give a good idea what went wrong. -E.g. for RDO or Fedora the following command will output the full log:: - - sudo journalctl -u openstack-ironic-inspector - -(use ``openstack-ironic-discoverd`` for version < 2.0.0). - -.. note:: - Service name and specific command might be different for other Linux - distributions (and for old version of **ironic-inspector**). - -If ``ramdisk_error`` plugin is enabled and ``ramdisk_logs_dir`` configuration -option is set, **ironic-inspector** will store logs received from the ramdisk -to the ``ramdisk_logs_dir`` directory. This depends, however, on the ramdisk -implementation. - -Troubleshooting PXE boot -^^^^^^^^^^^^^^^^^^^^^^^^ - -PXE booting most often becomes a problem for bare metal environments with -several physical networks. If the hardware vendor provides a remote console -(e.g. iDRAC for DELL), use it to connect to the machine and see what is going -on. You may need to restart introspection. - -Another source of information is DHCP and TFTP server logs. Their location -depends on how the servers were installed and run. For RDO or Fedora use:: - - $ sudo journalctl -u openstack-ironic-inspector-dnsmasq - -(use ``openstack-ironic-discoverd-dnsmasq`` for version < 2.0.0). - -The last resort is ``tcpdump`` utility. Use something like -:: - - $ sudo tcpdump -i any port 67 or port 68 or port 69 - -to watch both DHCP and TFTP traffic going through your machine. Replace -``any`` with a specific network interface to check that DHCP and TFTP -requests really reach it. - -If you see node not attempting PXE boot or attempting PXE boot on the wrong -network, reboot the machine into BIOS settings and make sure that only one -relevant NIC is allowed to PXE boot. - -If you see node attempting PXE boot using the correct NIC but failing, make -sure that: - -#. network switches configuration does not prevent PXE boot requests from - propagating, - -#. there is no additional firewall rules preventing access to port 67 on the - machine where *ironic-inspector* and its DHCP server are installed. - -If you see node receiving DHCP address and then failing to get kernel and/or -ramdisk or to boot them, make sure that: - -#. TFTP server is running and accessible (use ``tftp`` utility to verify), - -#. no firewall rules prevent access to TFTP port, - -#. DHCP server is correctly set to point to the TFTP server, - -#. ``pxelinux.cfg/default`` within TFTP root contains correct reference to the - kernel and ramdisk. - -Troubleshooting ramdisk run -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Connect to the remote console as described in `Troubleshooting PXE boot`_ to -see what is going on with the ramdisk. The ramdisk drops into emergency shell -on failure, which you can use to look around. There should be file called -``logs`` with the current ramdisk logs. - -Troubleshooting DNS issues on Ubuntu -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Ubuntu uses local DNS caching, so tries localhost for DNS results first -before calling out to an external DNS server. When DNSmasq is installed and -configured for use with ironic-inspector, it can cause problems by interfering -with the local DNS cache. To fix this issue ensure that ``/etc/resolve.conf`` -points to your external DNS servers and not to ``127.0.0.1``. diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 000000000..5cdf0aaab --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,159 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " xml to make Docutils-native XML files" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Heat.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Heat.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Heat" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Heat" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The xml files are in $(BUILDDIR)/xml." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." \ No newline at end of file diff --git a/doc/source/.gitignore b/doc/source/.gitignore new file mode 100644 index 000000000..8647666aa --- /dev/null +++ b/doc/source/.gitignore @@ -0,0 +1,2 @@ +target/ +build/ \ No newline at end of file diff --git a/doc/source/api/HTTP-API.rst b/doc/source/api/HTTP-API.rst new file mode 100644 index 000000000..363e683e7 --- /dev/null +++ b/doc/source/api/HTTP-API.rst @@ -0,0 +1,274 @@ +HTTP API +-------- + +By default **ironic-inspector** listens on ``0.0.0.0:5050``, port +can be changed in configuration. Protocol is JSON over HTTP. + +Start Introspection +~~~~~~~~~~~~~~~~~~~ + +``POST /v1/introspection/`` initiate hardware introspection for node +````. All power management configuration for this node needs to be done +prior to calling the endpoint (except when `Setting IPMI Credentials`_). + +Requires X-Auth-Token header with Keystone token for authentication. + +Optional parameters: + +* ``new_ipmi_password`` if set, **ironic-inspector** will try to set IPMI + password on the machine to this value. Power credentials validation will be + skipped and manual power on will be required. See `Setting IPMI + credentials`_ for details. + +* ``new_ipmi_username`` provides new IPMI user name in addition to password + set by ``new_ipmi_password``. Defaults to current ``ipmi_username`` in + node ``driver_info`` field. + +Response: + +* 202 - accepted introspection request +* 400 - bad request +* 401, 403 - missing or invalid authentication +* 404 - node cannot be found + +Get Introspection Status +~~~~~~~~~~~~~~~~~~~~~~~~ + +``GET /v1/introspection/`` get hardware introspection status. + +Requires X-Auth-Token header with Keystone token for authentication. + +Response: + +* 200 - OK +* 400 - bad request +* 401, 403 - missing or invalid authentication +* 404 - node cannot be found + +Response body: JSON dictionary with keys: + +* ``finished`` (boolean) whether introspection is finished + (``true`` on introspection completion or if it ends because of an error) +* ``error`` error string or ``null`` + +Get Introspection Data +~~~~~~~~~~~~~~~~~~~~~~ + +``GET /v1/introspection//data`` get stored data from successful +introspection. + +Requires X-Auth-Token header with Keystone token for authentication. + +Response: + +* 200 - OK +* 400 - bad request +* 401, 403 - missing or invalid authentication +* 404 - data cannot be found or data storage not configured + +Response body: JSON dictionary with introspection data + +Introspection Rules +~~~~~~~~~~~~~~~~~~~ + +See `Introspection Rules documentation`_ for details. + +All these API endpoints require X-Auth-Token header with Keystone token for +authentication. + +* ``POST /v1/rules`` create a new introspection rule. + + Request body: JSON dictionary with keys: + + * ``conditions`` rule conditions, see `Introspection Rules documentation`_ + * ``actions`` rule actions, see `Introspection Rules documentation`_ + * ``description`` (optional) human-readable description + * ``uuid`` (optional) rule UUID, autogenerated if missing + + Response + + * 200 - OK + * 400 - bad request + + Response body: JSON dictionary with introspection rule representation (the + same as above with UUID filled in). + +* ``GET /v1/rules`` list all introspection rules. + + Response + + * 200 - OK + + Response body: JSON dictionary with key ``rules`` - list of short rule + representations. Short rule representation is a JSON dictionary with keys: + + * ``uuid`` rule UUID + * ``description`` human-readable description + * ``links`` list of HTTP links, use one with ``rel=self`` to get the full + rule details + +* ``DELETE /v1/rules`` delete all introspection rules. + + Response + + * 204 - OK + +* ``GET /v1/rules/`` get one introspection rule by its ````. + + Response + + * 200 - OK + * 404 - not found + + Response body: JSON dictionary with introspection rule representation + (see ``POST /v1/rules`` above). + +* ``DELETE /v1/rules/`` delete one introspection rule by its ````. + + Response + + * 204 - OK + * 404 - not found + +.. _Introspection Rules documentation: https://github.com/openstack/ironic-inspector#introspection-rules + +Ramdisk Callback +~~~~~~~~~~~~~~~~ + +``POST /v1/continue`` internal endpoint for the ramdisk to post back +discovered data. Should not be used for anything other than implementing +the ramdisk. Request body: JSON dictionary with at least these keys: + +* ``cpus`` number of CPU +* ``cpu_arch`` architecture of the CPU +* ``memory_mb`` RAM in MiB +* ``local_gb`` hard drive size in GiB +* ``interfaces`` dictionary filled with data from all NIC's, keys being + interface names, values being dictionaries with keys: + + * ``mac`` MAC address + * ``ip`` IP address + +* ``ipmi_address`` IP address of BMC, may be missing on VM +* ``boot_interface`` optional MAC address of the NIC that the machine + PXE booted from either in standard format ``11:22:33:44:55:66`` or + in *PXELinux* ``BOOTIF`` format ``01-11-22-33-44-55-66``. + +* ``error`` optional error happened during ramdisk run, interpreted by + ``ramdisk_error`` plugin + +* ``logs`` optional base64-encoded logs from the ramdisk + +* ``block_devices`` optional block devices information for + ``root_device_hint`` plugin, dictionary with keys: + + * ``serials`` list of serial numbers of block devices. + +.. note:: + This list highly depends on enabled plugins, provided above are + expected keys for the default set of plugins. See Plugins_ for details. + +.. note:: + This endpoint is not expected to be versioned, though versioning will work + on it. + +Response: + +* 200 - OK +* 400 - bad request +* 403 - node is not on introspection +* 404 - node cannot be found or multiple nodes found + +Response body: JSON dictionary. If `Setting IPMI Credentials`_ is requested, +body will contain the following keys: + +* ``ipmi_setup_credentials`` boolean ``True`` +* ``ipmi_username`` new IPMI user name +* ``ipmi_password`` new IPMI password + +.. _Setting IPMI Credentials: https://github.com/openstack/ironic-inspector#setting-ipmi-credentials +.. _Plugins: https://github.com/openstack/ironic-inspector#plugins + +Error Response +~~~~~~~~~~~~~~ + +If an error happens during request processing, **Ironic Inspector** returns +a response with an appropriate HTTP code set, e.g. 400 for bad request or +404 when something was not found (usually node in cache or node in ironic). +The following JSON body is returned:: + + { + "error": { + "message": "Full error message" + } + } + +This body may be extended in the future to include details that are more error +specific. + +API Versioning +~~~~~~~~~~~~~~ + +The API supports optional API versioning. You can query for minimum and +maximum API version supported by the server. You can also declare required API +version in your requests, so that the server rejects request of unsupported +version. + +.. note:: + Versioning was introduced in **Ironic Inspector 2.1.0**. + +All versions must be supplied as string in form of ``X.Y``, where ``X`` is a +major version and is always ``1`` for now, ``Y`` is a minor version. + +* If ``X-OpenStack-Ironic-Inspector-API-Version`` header is sent with request, + the server will check if it supports this version. HTTP error 406 will be + returned for unsupported API version. + +* All HTTP responses contain + ``X-OpenStack-Ironic-Inspector-API-Minimum-Version`` and + ``X-OpenStack-Ironic-Inspector-API-Maximum-Version`` headers with minimum + and maximum API versions supported by the server. + +API Discovery +~~~~~~~~~~~~~ + +The API supports API discovery. You can query different parts of the API to +discover what other endpoints are avaliable. + +* ``GET /`` List API Versions + + Response: + + * 200 - OK + + Response body: JSON dictionary containing a list of ``versions``, each + version contains: + + * ``status`` Either CURRENT or SUPPORTED + * ``id`` The version identifier + * ``links`` A list of links to this version endpoint containing: + + * ``href`` The URL + * ``rel`` The relationship between the version and the href + +* ``GET /v1`` List API v1 resources + + Response: + + * 200 - OK + + Response body: JSON dictionary containing a list of ``resources``, each + resource contains: + + * ``name`` The name of this resources + * ``links`` A list of link to this resource containing: + + * ``href`` The URL + * ``rel`` The relationship between the resource and the href + +Version History +^^^^^^^^^^^^^^^ + +**1.0** version of API at the moment of introducing versioning. +**1.1** adds endpoint to retrieve stored introspection data. +**1.2** endpoints for manipulating introspection rules. diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 000000000..1b0482b4d --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +# + +# -- General configuration ---------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', + 'sphinx.ext.viewcode', + 'oslosphinx' + ] + +wsme_protocols = ['restjson'] + +# autodoc generation is a bit aggressive and a nuisance when doing heavy +# text edit cycles. +# execute "export SPHINX_DEBUG=1" in your terminal to disable + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Ironic Inspector' +copyright = u'OpenStack Foundation' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +#from ironic import version as ironic_version +# The full version, including alpha/beta/rc tags. +#release = ironic_version.version_info.release_string() +# The short X.Y version. +#version = ironic_version.version_info.version_string() + +# A list of ignored prefixes for module index sorting. +modindex_common_prefix = ['ironic.'] + +# If true, '()' will be appended to :func: etc. cross-reference text. +add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +add_module_names = True + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# NOTE(cinerama): mock out nova modules so docs can build without warnings +#import mock +#import sys +#MOCK_MODULES = ['nova', 'nova.compute', 'nova.context'] +#for module in MOCK_MODULES: +# sys.modules[module] = mock.Mock() + +# -- Options for HTML output -------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +#html_theme_path = ["."] +#html_theme = '_theme' +#html_static_path = ['_static'] + +# Output file base name for HTML help builder. +htmlhelp_basename = '%sdoc' % project + + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass +# [howto/manual]). +latex_documents = [ + ( + 'index', + '%s.tex' % project, + u'%s Documentation' % project, + u'OpenStack Foundation', + 'manual' + ), +] + +# -- Options for seqdiag ------------------------------------------------------ + +seqdiag_html_image_format = "SVG" \ No newline at end of file diff --git a/doc/source/deploy/install-guide.rst b/doc/source/deploy/install-guide.rst new file mode 100644 index 000000000..bd319f46c --- /dev/null +++ b/doc/source/deploy/install-guide.rst @@ -0,0 +1,241 @@ +.. _install_guide: + +Installation +------------ + +Install from PyPI_ (you may want to use virtualenv to isolate your +environment):: + + pip install ironic-inspector + +Also there is a `DevStack `_ +plugin for **ironic-inspector** - see :ref:`contributing_link` for the current status. + +Finally, some distributions (e.g. Fedora) provide **ironic-inspector** +packaged, some of them - under its old name *ironic-discoverd*. + +.. _PyPI: https://pypi.python.org/pypi/ironic-inspector + +Configuration +~~~~~~~~~~~~~ + +Copy ``example.conf`` to some permanent place +(e.g. ``/etc/ironic-inspector/inspector.conf``). +Fill in at least these configuration values: + +* ``os_username``, ``os_password``, ``os_tenant_name`` - Keystone credentials + to use when accessing other services and check client authentication tokens; + +* ``os_auth_url``, ``identity_uri`` - Keystone endpoints for validating + authentication tokens and checking user roles; + +* ``connection`` in the ``database`` section - SQLAlchemy connection string + for the database; + +* ``dnsmasq_interface`` - interface on which ``dnsmasq`` (or another DHCP + service) listens for PXE boot requests (defaults to ``br-ctlplane`` which is + a sane default for TripleO-based installations but is unlikely to work for + other cases). + +See comments inside `example.conf +`_ +for the other possible configuration options. + +.. note:: + Configuration file contains a password and thus should be owned by ``root`` + and should have access rights like ``0600``. + +**ironic-inspector** requires root rights for managing iptables. It gets them +by running ``ironic-inspector-rootwrap`` utility with ``sudo``. +To allow it, copy file ``rootwrap.conf`` and directory ``rootwrap.d`` to the +configuration directory (e.g. ``/etc/ironic-inspector/``) and create file +``/etc/sudoers.d/ironic-inspector-rootwrap`` with the following content:: + + stack ALL=(root) NOPASSWD: /usr/bin/ironic-inspector-rootwrap /etc/ironic-inspector/rootwrap.conf * + +.. DANGER:: + Be very careful about typos in ``/etc/sudoers.d/ironic-inspector-rootwrap`` + as any typo will break sudo for **ALL** users on the system. Especially, + make sure there is a new line at the end of this file. + +.. note:: + ``rootwrap.conf`` and all files in ``rootwrap.d`` must be writeable + only by root. + +.. note:: + If you store ``rootwrap.d`` in a different location, make sure to update + the *filters_path* option in ``rootwrap.conf`` to reflect the change. + + If your ``rootwrap.conf`` is in a different location, then you need + to update the *rootwrap_config* option in ``ironic-inspector.conf`` + to point to that location. + +Replace ``stack`` with whatever user you'll be using to run +**ironic-inspector**. + +Configuring PXE +^^^^^^^^^^^^^^^ + +As for PXE boot environment, you'll need: + +* TFTP server running and accessible (see below for using *dnsmasq*). + Ensure ``pxelinux.0`` is present in the TFTP root. + + +* You need PXE boot server (e.g. *dnsmasq*) running on **the same** machine as + **ironic-inspector**. Don't do any firewall configuration: + **ironic-inspector** will handle it for you. In **ironic-inspector** + configuration file set ``dnsmasq_interface`` to the interface your + PXE boot server listens on. Here is an example *dnsmasq.conf*:: + + port=0 + interface={INTERFACE} + bind-interfaces + dhcp-range={DHCP IP RANGE, e.g. 192.168.0.50,192.168.0.150} + enable-tftp + tftp-root={TFTP ROOT, e.g. /tftpboot} + dhcp-boot=pxelinux.0 + +* You have to install and configure one of 2 available ramdisks: simple + bash-based (see `Using simple ramdisk`_) or more complex based on + ironic-python-agent_ (See `Using IPA`_). + +Here is *inspector.conf* you may end up with:: + + [DEFAULT] + debug = false + [ironic] + identity_uri = http://127.0.0.1:35357 + os_auth_url = http://127.0.0.1:5000/v2.0 + os_username = admin + os_password = password + os_tenant_name = admin + [firewall] + dnsmasq_interface = br-ctlplane + +.. note:: + Set ``debug = true`` if you want to see complete logs. + +Using simple ramdisk +^^^^^^^^^^^^^^^^^^^^ + +* Build and put into your TFTP the kernel and ramdisk created using the + diskimage-builder_ `ironic-discoverd-ramdisk element`_:: + + ramdisk-image-create -o discovery fedora ironic-discoverd-ramdisk + + You need diskimage-builder_ 0.1.38 or newer to do it (using the latest one + is always advised). + +* Configure your ``$TFTPROOT/pxelinux.cfg/default`` with something like:: + + default introspect + + label introspect + kernel discovery.kernel + append initrd=discovery.initramfs discoverd_callback_url=http://{IP}:5050/v1/continue + + ipappend 3 + + Replace ``{IP}`` with IP of the machine (do not use loopback interface, it + will be accessed by ramdisk on a booting machine). + + .. note:: + There are some prebuilt images which use obsolete ``ironic_callback_url`` + instead of ``discoverd_callback_url``. Modify ``pxelinux.cfg/default`` + accordingly if you have one of these. + +Using IPA +^^^^^^^^^ + +ironic-python-agent_ is a new ramdisk developed for Ironic. During the Liberty +cycle support for **ironic-inspector** was added. This is experimental +for now, but we plan on making IPA the default ramdisk in Mitaka cycle. + +.. note:: + You need at least 1.5 GiB of RAM on the machines to use this ramdisk. + +To build an ironic-python-agent ramdisk, do the following: + +* Get the latest diskimage-builder_:: + + sudo pip install -U "diskimage-builder>=1.1.2" + +* Build the ramdisk:: + + disk-image-create ironic-agent fedora -o ironic-agent + + .. note:: + Replace "fedora" with your distribution of choice. + +* Copy resulting files ``ironic-agent.vmlinuz`` and ``ironic-agent.initramfs`` + to the TFTP root directory. + +Next, set up ``$TFTPROOT/pxelinux.cfg/default`` as follows:: + + default introspect + + label introspect + kernel ironic-agent.vmlinuz + append initrd=ironic-agent.initramfs ipa-inspection-callback-url=http://{IP}:5050/v1/continue systemd.journald.forward_to_console=yes + + ipappend 3 + +Replace ``{IP}`` with IP of the machine (do not use loopback interface, it +will be accessed by ramdisk on a booting machine). + +.. note:: + While ``systemd.journald.forward_to_console=yes`` is not actually + required, it will substantially simplify debugging if something goes wrong. + +.. _diskimage-builder: https://github.com/openstack/diskimage-builder +.. _ironic-discoverd-ramdisk element: https://github.com/openstack/diskimage-builder/tree/master/elements/ironic-discoverd-ramdisk +.. _ironic-python-agent: https://github.com/openstack/ironic-python-agent + +Managing the **ironic-inspector** database +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**ironic-inspector** provides a command line client for managing its database, +this client can be used for upgrading, and downgrading the database using +alembic migrations. + +If this is your first time running **ironic-inspector** to migrate the +database simply run: +:: + + ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade + +If you have previously run a version of **ironic-inspector** earlier than +2.2.0, the safest thing is to delete the existing SQLite database and run +``upgrade`` as shown above. If you, however, want to save the existing +database, to ensure your database will work with the migrations, you'll need to +run an extra step before upgrading the database. You only need to do this the +first time running version 2.2.0 or later. + +If you are upgrading from **ironic-inspector** version 2.1.0 or lower: +:: + + ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf stamp --revision 578f84f38d + ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade + +If you are upgrading from a git master install of **ironic-inspector** from +after :ref:`introspection_rules` were introduced: +:: + + ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf stamp --revision d588418040d + ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade + +Other available commands can be discovered by running:: + + ironic-inspector-dbsync --help + +Running +~~~~~~~ + +:: + + ironic-inspector --config-file /etc/ironic-inspector/inspector.conf + +A good starting point for writing your own *systemd* unit should be `one used +in Fedora `_ +(note usage of old name). diff --git a/doc/source/dev/contributing_link.rst b/doc/source/dev/contributing_link.rst new file mode 100644 index 000000000..f4e26a51c --- /dev/null +++ b/doc/source/dev/contributing_link.rst @@ -0,0 +1,3 @@ +.. _contributing_link: + +.. include:: ../../../CONTRIBUTING.rst \ No newline at end of file diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 000000000..1c2315e45 --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,73 @@ +Hardware introspection for OpenStack Bare Metal +=============================================== + +This is an auxiliary service for discovering hardware properties for a +node managed by `Ironic`_. Hardware introspection or hardware +properties discovery is a process of getting hardware parameters required for +scheduling from a bare metal node, given it's power management credentials +(e.g. IPMI address, user name and password). + +A special ramdisk is required to collect the information on a +node. The default one can be built using diskimage-builder_ and +`ironic-discoverd-ramdisk element`_ (see :ref:`install_guide`). + +* Free software: Apache license +* Source: http://git.openstack.org/cgit/openstack/ironic-inspector +* Bugs: http://bugs.launchpad.net/ironic-inspector +* Blueprints: https://blueprints.launchpad.net/ironic-inspector +* Downloads: https://pypi.python.org/pypi/ironic-inspector +* Python client library and CLI tool: `python-ironic-inspector-client + `_. + +.. _Ironic: https://wiki.openstack.org/wiki/Ironic +.. _PyPI: https://pypi.python.org/pypi/ironic-inspector +.. _diskimage-builder: https://github.com/openstack/diskimage-builder +.. _ironic-discoverd-ramdisk element: https://github.com/openstack/diskimage-builder/tree/master/elements/ironic-discoverd-ramdisk + +.. note:: + **ironic-inspector** was called *ironic-discoverd* before version 2.0.0. + +For information on any current or prior version, see `the release +notes`_ and `the wiki pages`_. + +.. _the release notes: releasenotes/index.html +.. _the wiki pages: https://wiki.openstack.org/wiki/Ironic/ReleaseNotes + +Admin Guide +=========== + +Overview +-------- + +.. toctree:: + :maxdepth: 1 + + Installation Guide + Usage + Troubleshooting + +Developer Guide +=============== + +Introduction +------------ + +.. toctree:: + :maxdepth: 1 + + Contribution Guide + +API References +-------------- + +.. toctree:: + :maxdepth: 1 + + HTTP API description + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/source/troubleshooting/troubleshooting.rst b/doc/source/troubleshooting/troubleshooting.rst new file mode 100644 index 000000000..7ff8519e0 --- /dev/null +++ b/doc/source/troubleshooting/troubleshooting.rst @@ -0,0 +1,113 @@ +Troubleshooting +=============== + +Errors when starting introspection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* *Invalid provision state "available"* + + In Kilo release with *python-ironicclient* 0.5.0 or newer Ironic + defaults to reporting provision state ``AVAILABLE`` for newly enrolled + nodes. **ironic-inspector** will refuse to conduct introspection in + this state, as such nodes are supposed to be used by Nova for scheduling. + See :ref:`node_states` for instructions on how to put nodes into + the correct state. + +Introspection times out +~~~~~~~~~~~~~~~~~~~~~~~ + +There may be 3 reasons why introspection can time out after some time +(defaulting to 60 minutes, altered by ``timeout`` configuration option): + +#. Fatal failure in processing chain before node was found in the local cache. + See `Troubleshooting data processing`_ for the hints. + +#. Failure to load the ramdisk on the target node. See `Troubleshooting + PXE boot`_ for the hints. + +#. Failure during ramdisk run. See `Troubleshooting ramdisk run`_ for the + hints. + +Troubleshooting data processing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In this case **ironic-inspector** logs should give a good idea what went wrong. +E.g. for RDO or Fedora the following command will output the full log:: + + sudo journalctl -u openstack-ironic-inspector + +(use ``openstack-ironic-discoverd`` for version < 2.0.0). + +.. note:: + Service name and specific command might be different for other Linux + distributions (and for old version of **ironic-inspector**). + +If ``ramdisk_error`` plugin is enabled and ``ramdisk_logs_dir`` configuration +option is set, **ironic-inspector** will store logs received from the ramdisk +to the ``ramdisk_logs_dir`` directory. This depends, however, on the ramdisk +implementation. + +Troubleshooting PXE boot +^^^^^^^^^^^^^^^^^^^^^^^^ + +PXE booting most often becomes a problem for bare metal environments with +several physical networks. If the hardware vendor provides a remote console +(e.g. iDRAC for DELL), use it to connect to the machine and see what is going +on. You may need to restart introspection. + +Another source of information is DHCP and TFTP server logs. Their location +depends on how the servers were installed and run. For RDO or Fedora use:: + + $ sudo journalctl -u openstack-ironic-inspector-dnsmasq + +(use ``openstack-ironic-discoverd-dnsmasq`` for version < 2.0.0). + +The last resort is ``tcpdump`` utility. Use something like +:: + + $ sudo tcpdump -i any port 67 or port 68 or port 69 + +to watch both DHCP and TFTP traffic going through your machine. Replace +``any`` with a specific network interface to check that DHCP and TFTP +requests really reach it. + +If you see node not attempting PXE boot or attempting PXE boot on the wrong +network, reboot the machine into BIOS settings and make sure that only one +relevant NIC is allowed to PXE boot. + +If you see node attempting PXE boot using the correct NIC but failing, make +sure that: + +#. network switches configuration does not prevent PXE boot requests from + propagating, + +#. there is no additional firewall rules preventing access to port 67 on the + machine where *ironic-inspector* and its DHCP server are installed. + +If you see node receiving DHCP address and then failing to get kernel and/or +ramdisk or to boot them, make sure that: + +#. TFTP server is running and accessible (use ``tftp`` utility to verify), + +#. no firewall rules prevent access to TFTP port, + +#. DHCP server is correctly set to point to the TFTP server, + +#. ``pxelinux.cfg/default`` within TFTP root contains correct reference to the + kernel and ramdisk. + +Troubleshooting ramdisk run +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Connect to the remote console as described in `Troubleshooting PXE boot`_ to +see what is going on with the ramdisk. The ramdisk drops into emergency shell +on failure, which you can use to look around. There should be file called +``logs`` with the current ramdisk logs. + +Troubleshooting DNS issues on Ubuntu +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Ubuntu uses local DNS caching, so tries localhost for DNS results first +before calling out to an external DNS server. When DNSmasq is installed and +configured for use with ironic-inspector, it can cause problems by interfering +with the local DNS cache. To fix this issue ensure that ``/etc/resolve.conf`` +points to your external DNS servers and not to ``127.0.0.1``. diff --git a/doc/source/usage/usage.rst b/doc/source/usage/usage.rst new file mode 100644 index 000000000..9f666c341 --- /dev/null +++ b/doc/source/usage/usage.rst @@ -0,0 +1,187 @@ +Usage +===== + + +Refer to HTTP-API.rst_ for information on the HTTP API. +Refer to the `client page`_ for information on how to use CLI and Python +library. + +.. _HTTP-API.rst: https://github.com/openstack/ironic-inspector/blob/master/HTTP-API.rst +.. _HTTP API: https://github.com/openstack/ironic-inspector/blob/master/HTTP-API.rst +.. _client page: https://pypi.python.org/pypi/python-ironic-inspector-client + +Using from Ironic API +~~~~~~~~~~~~~~~~~~~~~ + +Ironic Kilo introduced support for hardware introspection under name of +"inspection". **ironic-inspector** introspection is supported for some generic +drivers, please refer to `Ironic inspection documentation`_ for details. + +.. _Ironic inspection documentation: http://docs.openstack.org/developer/ironic/deploy/install-guide.html#hardware-inspection + +.. _node_states: + +Node States +~~~~~~~~~~~ + +* The nodes should be moved to ``MANAGEABLE`` provision state before + introspection (requires *python-ironicclient* of version 0.5.0 or newer):: + + ironic node-set-provision-state manage + +* After successful introspection and before deploying nodes should be made + available to Nova, by moving them to ``AVAILABLE`` state:: + + ironic node-set-provision-state provide + + .. note:: + Due to how Nova interacts with Ironic driver, you should wait 1 minute + before Nova becomes aware of available nodes after issuing this command. + Use ``nova hypervisor-stats`` command output to check it. + +.. _introspection_rules: + +Introspection Rules +~~~~~~~~~~~~~~~~~~~ + +Inspector supports a simple JSON-based DSL to define rules to run during +introspection. Inspector provides an API to manage such rules, and will run +them automatically after running all processing hooks. + +A rule consists of conditions to check, and actions to run. If conditions +evaluate to true on the introspection data, then actions are run on a node. +All actions have "rollback actions" associated with them, which are run when +conditions evaluate to false. This way we can safely rerun introspection. + +Available conditions and actions are defined by plugins, and can be extended, +see :ref:`contributing_link` for details. See `HTTP API`_ for specific calls to define +introspection rules. + +Conditions +^^^^^^^^^^ + +A condition is represented by an object with fields: + +``op`` the type of comparison operation, default available operators include : +``eq``, ``le``, ``ge``, ``ne``, ``lt``, ``gt`` (basic comparison operators), +``in-net`` (checks that IP address is in a given network). + +``field`` a `JSON path `_ to the field +in the introspection data to use in comparison. + +``multiple`` how to treat situations where the ``field`` query returns multiple +results (e.g. the field contains a list), available options are: + +* ``any`` (the default) require any to match, +* ``all`` require all to match, +* ``first`` requrie the first to match. + +All other fields are passed to the condition plugin, e.g. numeric comparison +operations require a ``value`` field to compare against. + +Actions +^^^^^^^ + +An action is represented by an object with fields: + +``action`` type of action. Possible values are defined by plugins. + +All other fields are passed to the action plugin. + +Default available actions include: + +* ``fail`` fail introspection. Requires a ``message`` parameter for the failure + message. + +* ``set-attribute`` sets an attribute on an Ironic node. Requires a ``path`` + field, which is the path to the attribute as used by ironic (e.g. + ``/properties/something``), and a ``value`` to set. + +* ``set-capability`` sets a capability on an Ironic node. Requires ``name`` + and ``value`` fields, which are the name and the value for a new capability + accordingly. Existing value for this same capability is replaced. + +* ``extend-attribute`` the same as ``set-attribute``, but treats existing + value as a list and appends value to it. If optional ``unique`` parameter is + set to ``True``, nothing will be added if given value is already in a list. + +Setting IPMI Credentials +~~~~~~~~~~~~~~~~~~~~~~~~ + +If you have physical access to your nodes, you can use **ironic-inspector** to +set IPMI credentials for them without knowing the original ones. The workflow +is as follows: + +* Ensure nodes will PXE boot on the right network by default. + +* Set ``enable_setting_ipmi_credentials = true`` in the **ironic-inspector** + configuration file, restart **ironic-inspector**. + +* Enroll nodes in Ironic with setting their ``ipmi_address`` only (or + equivalent driver-specific property, as per ``ipmi_address_fields`` + configuration option). + + With Ironic Liberty use ironic API version ``1.11``, so that new node gets + into ``enroll`` provision state:: + + ironic --ironic-api-version 1.11 node-create -d -i ipmi_address=
+ + Providing ``ipmi_address`` allows **ironic-inspector** to distinguish nodes. + +* With Ironic Kilo or older, set maintenance mode on nodes. + That's an important step, otherwise Ironic might interfere with introspection + process. This is replaced by ``enroll`` state in Ironic Liberty. + +* Start introspection with providing additional parameters: + + * ``new_ipmi_password`` IPMI password to set, + * ``new_ipmi_username`` IPMI user name to set, defaults to one in node + driver_info. + +* Manually power on the nodes and wait. + +* After introspection is finished (watch nodes power state or use + **ironic-inspector** status API) you can move node to ``manageable`` and + then ``available`` states - see `Node States`_. With Ironic Kilo you have to + move a node out of maintenance mode. + +Note that due to various limitations on password value in different BMC, +**ironic-inspector** will only accept passwords with length between 1 and 20 +consisting only of letters and numbers. + +Plugins +~~~~~~~ + +**ironic-inspector** heavily relies on plugins for data processing. Even the +standard functionality is largely based on plugins. Set ``processing_hooks`` +option in the configuration file to change the set of plugins to be run on +introspection data. Note that order does matter in this option. + +These are plugins that are enabled by default and should not be disabled, +unless you understand what you're doing: + +``ramdisk_error`` + reports error, if ``error`` field is set by the ramdisk, also optionally + stores logs from ``logs`` field, see `HTTP API`_ for details. +``scheduler`` + validates and updates basic hardware scheduling properties: CPU number and + architecture, memory and disk size. +``validate_interfaces`` + validates network interfaces information. + +Here are some plugins that can be additionally enabled: + +``example`` + example plugin logging it's input and output. +``raid_device`` (deprecated name ``root_device_hint``) + gathers block devices from ramdisk and exposes root device in multiple + runs. +``extra_hardware`` + stores the value of the 'data' key returned by the ramdisk as a JSON + encoded string in a Swift object. The plugin will also attempt to convert + the data into a format usable by introspection rules. If this is successful + then the new format will be stored in the 'extra' key. The 'data' key is + then deleted from the introspection data, as unless converted it's assumed + unusable by introspection rules. + +Refer to :ref:`contributing_link` for information on how to write your own plugin. \ No newline at end of file diff --git a/releasenotes/notes/sphinx-docs-4d0a5886261e57bf.yaml b/releasenotes/notes/sphinx-docs-4d0a5886261e57bf.yaml new file mode 100644 index 000000000..6af5d57c0 --- /dev/null +++ b/releasenotes/notes/sphinx-docs-4d0a5886261e57bf.yaml @@ -0,0 +1,12 @@ +--- +prelude: > + This release includes automatic `docs` generation via Sphinx. +other: + - | + Introduced new docs generation via `Sphinx `_ + and `ReST `_. + + * Separate `doc` folder includes `source` and `build` + * Integration with `tox `_ as `docs` target + * `makefile` for manual building + * `Openstack Theme `_ support diff --git a/setup.cfg b/setup.cfg index 0d44a1d1a..e96361674 100644 --- a/setup.cfg +++ b/setup.cfg @@ -66,3 +66,8 @@ input_file = ironic-inspector/locale/ironic-inspector.pot keywords = _ gettext ngettext l_ lazy_gettext mapping_file = babel.cfg output_file = ironic-inspector/locale/ironic-inspector.pot + +[build_sphinx] +all_files = 1 +build-dir = doc/build +source-dir = doc/source diff --git a/test-requirements.txt b/test-requirements.txt index 601a45b56..0d893f882 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -8,3 +8,4 @@ mock>=1.2 sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0 reno>=0.1.1 # Apache2 + diff --git a/tox.ini b/tox.ini index 4c747ceeb..dc2a1fb99 100644 --- a/tox.ini +++ b/tox.ini @@ -57,3 +57,10 @@ max-complexity=15 [hacking] import_exceptions = ironicclient.exceptions,ironic_inspector.common.i18n + +[testenv:docs] +setenv = PYTHONHASHSEED=0 +sitepackages = False +deps = -r{toxinidir}/test-requirements.txt +commands = + python setup.py build_sphinx