From: Dietmar Maurer Date: Wed, 22 Feb 2017 05:48:17 +0000 (+0100) Subject: Initial commit X-Git-Url: https://git.proxmox.com/?p=pmg-docs.git;a=commitdiff_plain;h=410dc2c9c45f74f8d077773d8063ae6cc97dc145 Initial commit --- 410dc2c9c45f74f8d077773d8063ae6cc97dc145 diff --git a/GFDL.adoc b/GFDL.adoc new file mode 100644 index 0000000..467b9a7 --- /dev/null +++ b/GFDL.adoc @@ -0,0 +1,424 @@ +GNU Free Documentation License +============================== + +Version 1.3, 3 November 2008 + + +Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, +Inc. + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +.0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +.1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +The "publisher" means any person or entity that distributes copies of +the Document to the public. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +.2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no +other conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +.3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to +give them a chance to provide you with an updated version of the +Document. + + +.4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +.5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +.6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other +documents released under this License, and replace the individual +copies of this License in the various documents with a single copy +that is included in the collection, provided that you follow the rules +of this License for verbatim copying of each of the documents in all +other respects. + +You may extract a single document from such a collection, and +distribute it individually under this License, provided you insert a +copy of this License into the extracted document, and follow this +License in all other respects regarding verbatim copying of that +document. + + +.7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +.8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +.9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, or distribute it is void, and +will automatically terminate your rights under this License. + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, receipt of a copy of some or all of the same material does +not give you any rights to use it. + + +.10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions of the +GNU Free Documentation License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in +detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. If the Document +specifies that a proxy can decide which future versions of this +License can be used, that proxy's public statement of acceptance of a +version permanently authorizes you to choose that version for the +Document. + +.11. RELICENSING + +"Massive Multiauthor Collaboration Site" (or "MMC Site") means any +World Wide Web server that publishes copyrightable works and also +provides prominent facilities for anybody to edit those works. A +public wiki that anybody can edit is an example of such a server. A +"Massive Multiauthor Collaboration" (or "MMC") contained in the site +means any set of copyrightable works thus published on the MMC site. + +"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 +license published by Creative Commons Corporation, a not-for-profit +corporation with a principal place of business in San Francisco, +California, as well as future copyleft versions of that license +published by that same organization. + +"Incorporate" means to publish or republish a Document, in whole or in +part, as part of another Document. + +An MMC is "eligible for relicensing" if it is licensed under this +License, and if all works that were first published under this License +somewhere other than this MMC, and subsequently incorporated in whole or +in part into the MMC, (1) had no cover texts or invariant sections, and +(2) were thus incorporated prior to November 1, 2008. + +The operator of an MMC Site may republish an MMC contained in the site +under CC-BY-SA on the same site at any time before August 1, 2009, +provided the MMC is eligible for relicensing. + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3d94ab1 --- /dev/null +++ b/Makefile @@ -0,0 +1,198 @@ +DGDIR=. +ASCIIDOC_PMG=./asciidoc-pmg + +GEN_PACKAGE=pmg-doc-generator +DOC_PACKAGE=pmg-docs + +# also update debian/changelog +PKGREL=1 + +ARCH:=$(shell dpkg-architecture -qDEB_BUILD_ARCH) + +GEN_DEB=${GEN_PACKAGE}_${DOCRELEASE}-${PKGREL}_${ARCH}.deb +DOC_DEB=${DOC_PACKAGE}_${DOCRELEASE}-${PKGREL}_all.deb +DOC_BUILDDEPS := dblatex, source-highlight, inkscape, imagemagick + + +all: index.html + +.PHONY: verify-images +verify-images: png-verify.pl + for i in ./images/screenshot/*.png; do ./png-verify.pl $$i; done + +ADOC_SOURCES_GUESS=$(filter-out %-synopsis.adoc %-opts.adoc %-table.adoc, $(wildcard *.adoc)) +.pmg-doc-depends link-refs.json: ${ADOC_SOURCES_GUESS} scan-adoc-refs + ./scan-adoc-refs *.adoc --depends .pmg-doc-depends.tmp > link-refs.json.tmp + @cmp --quiet .pmg-doc-depends .pmg-doc-depends.tmp || mv .pmg-doc-depends.tmp .pmg-doc-depends + @cmp --quiet link-refs.json link-refs.json.tmp || mv link-refs.json.tmp link-refs.json + +pmg-doc-generator.mk: .pmg-doc-depends pmg-doc-generator.mk.in + cat pmg-doc-generator.mk.in .pmg-doc-depends > $@.tmp + mv $@.tmp $@ + +include ./pmg-doc-generator.mk + +GEN_DEB_SOURCES= \ + pmg-doc-generator.mk \ + ${MANUAL_SOURCES} \ + docinfo.xml + +GEN_SCRIPTS= + +API_VIEWER_SOURCES= \ + api-viewer/index.html \ + api-viewer/apidoc.js + +asciidoc-pmg: asciidoc-pmg.in link-refs.json + cat asciidoc-pmg.in link-refs.json >asciidoc-pmg.tmp + sed -e s/@RELEASE@/${DOCRELEASE}/ -i asciidoc-pmg.tmp + chmod +x asciidoc-pmg.tmp + mv asciidoc-pmg.tmp asciidoc-pmg + +INDEX_INCLUDES= \ + pmg-admin-guide.pdf \ + pmg-admin-guide.epub \ + chapter-index-table.adoc \ + man1-index-table.adoc \ + man5-index-table.adoc \ + man8-index-table.adoc \ + $(sort $(addsuffix .html, ${MANUAL_PAGES}) ${CHAPTER_LIST}) + +ADOC_STDARG=-b $(shell pwd)/asciidoc/pmg-html -f asciidoc/asciidoc-pmg.conf -a icons -a data-uri -a "date=$(shell date)" -a "revnumber=${DOCRELEASE}" + +BROWSER?=xdg-open + + +README.html: README.adoc + asciidoc -a toc ${ADOC_STDARG} -o $@ $< + +.PHONY: index +index: index.html + $(BROWSER) index.html & + +chapter-index-table.adoc: asciidoc-pmg + ./asciidoc-pmg chapter-table >$@.tmp + mv $@.tmp $@ + +man1-index-table.adoc: asciidoc-pmg + ./asciidoc-pmg man1page-table >$@.tmp + mv $@.tmp $@ + +man5-index-table.adoc: asciidoc-pmg + ./asciidoc-pmg man5page-table >$@.tmp + mv $@.tmp $@ + +man8-index-table.adoc: asciidoc-pmg + ./asciidoc-pmg man8page-table >$@.tmp + mv $@.tmp $@ + +index.html: index.adoc ${API_VIEWER_SOURCES} ${INDEX_INCLUDES} + asciidoc ${ADOC_STDARG} -o $@ index.adoc + +pmg-admin-guide.html: ${PMG_ADMIN_GUIDE_ADOCDEPENDS} + asciidoc -a pmglogo ${ADOC_STDARG} -o $@ pmg-admin-guide.adoc + +pmg-admin-guide.chunked: ${PMG_ADMIN_GUIDE_ADOCDEPENDS} + rm -rf pmg-admin-guide.chunked + a2x -a docinfo -a docinfo1 -a icons -f chunked pmg-admin-guide.adoc + +PMG_DOCBOOK_CONF=-b $(shell pwd)/asciidoc/pmg-docbook -f asciidoc/asciidoc-pmg.conf + +pmg-admin-guide-docinfo.xml: pmg-admin-guide-docinfo.xml.in + sed -e 's/@RELEASE@/${DOCRELEASE}/' <$< >$@ + +pmg-admin-guide.pdf: ${PMG_ADMIN_GUIDE_ADOCDEPENDS} docinfo.xml pmg-admin-guide-docinfo.xml + inkscape -z -D --export-pdf=proxmox-logo.pdf images/proxmox-logo.svg + inkscape -z -D --export-pdf=proxmox-ci-header.pdf images/proxmox-ci-header.svg + grep ">Release ${DOCRELEASE}<" pmg-admin-guide-docinfo.xml || (echo "wrong release in pmg-admin-guide-docinfo.xml" && false); + a2x -a docinfo -a docinfo1 -f pdf -L --asciidoc-opts="${PMG_DOCBOOK_CONF}" --dblatex-opts "-p ./asciidoc/pmg-dblatex.xsl -s asciidoc/dblatex-custom.sty" pmg-admin-guide.adoc + rm proxmox-logo.pdf proxmox-ci-header.pdf + +pmg-admin-guide.epub: ${PMG_ADMIN_GUIDE_ADOCDEPENDS} + a2x -f epub --asciidoc-opts="${PMG_DOCBOOK_CONF}" pmg-admin-guide.adoc + +api-viewer/apidata.js: extractapi.pl + ./extractapi.pl >$@ + +api-viewer/apidoc.js: api-viewer/apidata.js api-viewer/PMGAPI.js + cat api-viewer/apidata.js api-viewer/PMGAPI.js >$@ + +.PHONY: dinstall +dinstall: ${GEN_DEB} ${DOC_DEB} + dpkg -i ${GEN_DEB} ${DOC_DEB} + +.PHONY: deb +deb: + rm -f ${GEN_DEB} ${DOC_DEB} + make all-debs + +.PHONY: all-debs +all-debs: ${GEN_DEB} ${DOC_DEB} + +.PHONY: clean-build +clean-build: + rm -rf build + +define prepare_build + rm -rf build-$1 + mkdir build-$1 + cp -a debian build-$1/debian + mv build-$1/debian/control.in build-$1/debian/control + echo >> build-$1/debian/control + cat debian/$1.control >> build-$1/debian/control + install -dm755 build-$1/usr/share/$1 + install -dm755 build-$1/usr/share/doc/$1 +endef + +.PHONY: gen-deb +gen-deb: $(GEN_DEB) +$(GEN_DEB): $(GEN_DEB_SOURCES) asciidoc-pmg + $(call prepare_build,$(GEN_PACKAGE)) + install -dm755 build-$(GEN_PACKAGE)/usr/bin + # install files + install -m 0644 ${GEN_DEB_SOURCES} build-$(GEN_PACKAGE)/usr/share/${GEN_PACKAGE} + #install -m 0755 ${GEN_SCRIPTS} build-$(GEN_PACKAGE)/usr/share/${GEN_PACKAGE} + # install asciidoc-pmg + install -m 0755 asciidoc-pmg build-$(GEN_PACKAGE)/usr/bin/ + install -dm755 build-$(GEN_PACKAGE)/usr/share/${GEN_PACKAGE}/asciidoc/ + install -m 0644 asciidoc/asciidoc-pmg.conf build-$(GEN_PACKAGE)/usr/share/${GEN_PACKAGE}/asciidoc/ + install -m 0644 asciidoc/pmg-html.conf build-$(GEN_PACKAGE)/usr/share/${GEN_PACKAGE}/asciidoc/ + cd build-$(GEN_PACKAGE) && dpkg-buildpackage -rfakeroot -b -us -uc + lintian ${GEN_DEB} + +.PHONY: doc-deb +doc-deb: $(DOC_DEB) +$(DOC_DEB): index.html $(API_VIEWER_SOURCES) verify-images + $(call prepare_build,$(DOC_PACKAGE)) + sed -i -e '/^Build-Depends/{s/$$/, $(DOC_BUILDDEPS)/}' build-$(DOC_PACKAGE)/debian/control + # install files for pmgdocs package + install -dm755 build-$(DOC_PACKAGE)/usr/share/${DOC_PACKAGE} + install -dm755 build-$(DOC_PACKAGE)/usr/share/doc/${DOC_PACKAGE} + install -m 0644 index.html ${INDEX_INCLUDES} build-$(DOC_PACKAGE)/usr/share/${DOC_PACKAGE} + # install screenshot images + install -dm755 build-$(DOC_PACKAGE)/usr/share/${DOC_PACKAGE}/images/screenshot + install -m 0644 images/screenshot/*.png build-$(DOC_PACKAGE)/usr/share/${DOC_PACKAGE}/images/screenshot + # install api doc viewer + install -dm755 build-$(DOC_PACKAGE)/usr/share/${DOC_PACKAGE}/api-viewer + install -m 0644 ${API_VIEWER_SOURCES} build-$(DOC_PACKAGE)/usr/share/${DOC_PACKAGE}/api-viewer + cd build-$(DOC_PACKAGE) && dpkg-buildpackage -rfakeroot -b -us -uc + lintian ${DOC_DEB} + +.PHONY: upload +upload: ${GEN_DEB} ${DOC_DEB} + tar cf - ${GEN_DEB} ${DOC_DEB} | ssh repoman@repo.proxmox.com upload-pmg + +.PHONY: update +update: clean + find . -regex '.*-\(opts\|synopsis\)\.adoc' -exec rm -f \{\} \; + rm -f api-viewer/apidata.js + make all + +clean: + find . -name '*~' -exec rm {} ';' + rm -rf *.html *.pdf *.epub *.tmp *.1 *.5 *.8 + rm -f *.deb *.changes *.buildinfo + rm -f api-viewer/apidoc.js chapter-*.html *-plain.html chapter-*.html pmg-admin-guide.chunked asciidoc-pmg link-refs.json .asciidoc-pmg-tmp_* + rm -rf .pmg-doc-depends + rm -f pmg-doc-generator.mk chapter-index-table.adoc man1-index-table.adoc man5-index-table.adoc man8-index-table.adoc pmg-admin-guide-docinfo.xml + rm -rf build-* diff --git a/api-viewer/PMGAPI.js b/api-viewer/PMGAPI.js new file mode 100644 index 0000000..d42da60 --- /dev/null +++ b/api-viewer/PMGAPI.js @@ -0,0 +1,284 @@ +// avoid errors when running without development tools +if (!Ext.isDefined(Ext.global.console)) { + var console = { + dir: function() {}, + log: function() {} + }; +} + +Ext.onReady(function() { + + Ext.define('pmg-param-schema', { + extend: 'Ext.data.Model', + fields: [ + 'name', 'type', 'typetext', 'description', 'verbose_description', + 'enum', 'minimum', 'maximum', 'minLength', 'maxLength', + 'pattern', 'title', 'requires', 'format', 'default', + 'disallow', 'extends', 'links', + { + name: 'optional', + type: 'boolean' + } + ] + }); + + var store = Ext.create('Ext.data.TreeStore', { + model: Ext.define('pmg-api-doc', { + extend: 'Ext.data.Model', + fields: [ + 'path', 'info', 'text', + ] + }), + proxy: { + type: 'memory', + data: pmgapi + }, + sorters: [{ + property: 'leaf', + direction: 'ASC' + }, { + property: 'text', + direction: 'ASC' + }] + }); + + var render_description = function(value, metaData, record) { + var pdef = record.data; + + value = pdef.verbose_description || value; + + // TODO: try to render asciidoc correctly + + metaData.style = 'white-space:pre-wrap;' + + return Ext.htmlEncode(value); + }; + + var render_type = function(value, metaData, record) { + var pdef = record.data; + + return pdef['enum'] ? 'enum' : (pdef.type || 'string'); + }; + + var render_format = function(value, metaData, record) { + var pdef = record.data; + + metaData.style = 'white-space:normal;' + + if (pdef.typetext) + return Ext.htmlEncode(pdef.typetext); + + if (pdef['enum']) + return pdef['enum'].join(' | '); + + if (pdef.format) + return pdef.format; + + if (pdef.pattern) + return Ext.htmlEncode(pdef.pattern); + + return ''; + }; + + var render_docu = function(data) { + var md = data.info; + + // console.dir(data); + + var items = []; + + var clicmdhash = { + GET: 'get', + POST: 'create', + PUT: 'set', + DELETE: 'delete' + }; + + Ext.Array.each(['GET', 'POST', 'PUT', 'DELETE'], function(method) { + var info = md[method]; + if (info) { + + var usage = ""; + + usage += ""; + usage += "
HTTP:   " + method + " /api2/json" + data.path + "
 
CLI:pmgsh " + clicmdhash[method] + " " + data.path + "
"; + + var sections = [ + { + title: 'Description', + html: Ext.htmlEncode(info.description), + bodyPadding: 10 + }, + { + title: 'Usage', + html: usage, + bodyPadding: 10 + } + ]; + + if (info.parameters && info.parameters.properties) { + + var pstore = Ext.create('Ext.data.Store', { + model: 'pmg-param-schema', + proxy: { + type: 'memory' + }, + groupField: 'optional', + sorters: [ + { + property: 'name', + direction: 'ASC' + } + ] + }); + + Ext.Object.each(info.parameters.properties, function(name, pdef) { + pdef.name = name; + pstore.add(pdef); + }); + + pstore.sort(); + + var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{ + enableGroupingMenu: false, + groupHeaderTpl: 'OptionalRequired' + }); + + sections.push({ + xtype: 'gridpanel', + title: 'Parameters', + features: [groupingFeature], + store: pstore, + viewConfig: { + trackOver: false, + stripeRows: true + }, + columns: [ + { + header: 'Name', + dataIndex: 'name' + }, + { + header: 'Type', + dataIndex: 'type', + renderer: render_type, + }, + { + header: 'Format', + dataIndex: 'type', + renderer: render_format, + flex: 1 + }, + { + header: 'Description', + dataIndex: 'description', + renderer: render_description, + flex: 2 + } + ] + }); + + } + + if (info.returns) { + + var rtype = info.returns.type; + if (!rtype && info.returns.items) + rtype = 'array'; + if (!rtype) + rtype = 'object'; + + sections.push({ + title: 'Returns: ' + rtype + }); + } + + var permhtml = ''; + if (!info.permissions) { + permhtml = "Root only."; + } else { + if (info.permissions.description) { + permhtml += "
" + + Ext.htmlEncode(info.permissions.description) + "
"; + } + + if (info.permissions.user) { + if (!info.permissions.description) { + if (info.permissions.user === 'world') { + permhtml += "Accessible without any authententification."; + } else if (info.permissions.user === 'all') { + permhtml += "Accessible by all authententicated users."; + } else { + permhtml += 'Onyl accessible by user "' + + info.permissions.user + '"'; + } + } + } else if (info.permissions.check) { + permhtml += "
Check: " + 
+			    Ext.htmlEncode(Ext.JSON.encode(info.permissions.check))  + "
"; + } else { + permhtml += "Unknown systax!"; + } + } + + sections.push({ + title: 'Required permissions', + bodyPadding: 10, + html: permhtml + }); + + + items.push({ + title: method, + autoScroll: true, + defaults: { + border: false + }, + items: sections + }); + } + }); + + var ct = Ext.getCmp('docview'); + ct.setTitle("Path: " + data.path); + ct.removeAll(true); + ct.add(items); + ct.setActiveTab(0); + }; + + var tree = Ext.create('Ext.tree.Panel', { + title: 'Resource Tree', + store: store, + width: 200, + region: 'west', + split: true, + margins: '5 0 5 5', + rootVisible: false, + listeners: { + selectionchange: function(v, selections) { + if (!selections[0]) + return; + var rec = selections[0]; + render_docu(rec.data); + } + } + }); + + Ext.create('Ext.container.Viewport', { + layout: 'border', + renderTo: Ext.getBody(), + items: [ + tree, + { + xtype: 'tabpanel', + title: 'Documentation', + id: 'docview', + region: 'center', + margins: '5 5 5 0', + layout: 'fit', + items: [] + } + ] + }); + +}); diff --git a/api-viewer/apidata.js b/api-viewer/apidata.js new file mode 100644 index 0000000..d92378b --- /dev/null +++ b/api-viewer/apidata.js @@ -0,0 +1,2803 @@ +var pmgapi = [ + { + "children" : [ + { + "children" : [ + { + "info" : { + "GET" : { + "description" : "Get list of rules.", + "method" : "GET", + "name" : "list_rules", + "parameters" : { + "additionalProperties" : 0 + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "items" : { + "properties" : {}, + "type" : "object" + }, + "type" : "array" + } + } + }, + "leaf" : 1, + "path" : "/config/ruledb/rules", + "text" : "rules" + }, + { + "info" : { + "GET" : { + "description" : "Get list of 'action' objects.", + "method" : "GET", + "name" : "list_actions", + "parameters" : { + "additionalProperties" : 0 + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "items" : { + "properties" : {}, + "type" : "object" + }, + "type" : "array" + } + } + }, + "leaf" : 1, + "path" : "/config/ruledb/actions", + "text" : "actions" + }, + { + "info" : { + "GET" : { + "description" : "Get list of 'what' objects.", + "method" : "GET", + "name" : "list_what_object", + "parameters" : { + "additionalProperties" : 0 + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "items" : { + "properties" : {}, + "type" : "object" + }, + "type" : "array" + } + } + }, + "leaf" : 1, + "path" : "/config/ruledb/what", + "text" : "what" + }, + { + "info" : { + "GET" : { + "description" : "Get list of 'when' objects.", + "method" : "GET", + "name" : "list_when_object", + "parameters" : { + "additionalProperties" : 0 + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "items" : { + "properties" : {}, + "type" : "object" + }, + "type" : "array" + } + } + }, + "leaf" : 1, + "path" : "/config/ruledb/when", + "text" : "when" + }, + { + "info" : { + "GET" : { + "description" : "Get list of 'who' objects.", + "method" : "GET", + "name" : "list_who_object", + "parameters" : { + "additionalProperties" : 0 + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "items" : { + "properties" : {}, + "type" : "object" + }, + "type" : "array" + } + } + }, + "leaf" : 1, + "path" : "/config/ruledb/who", + "text" : "who" + } + ], + "info" : { + "GET" : { + "description" : "Directory index.", + "method" : "GET", + "name" : "index", + "parameters" : { + "additionalProperties" : 0 + }, + "returns" : { + "items" : { + "properties" : {}, + "type" : "object" + }, + "links" : [ + { + "href" : "{name}", + "rel" : "child" + } + ], + "type" : "array" + } + } + }, + "leaf" : 0, + "path" : "/config/ruledb", + "text" : "ruledb" + }, + { + "children" : [ + { + "info" : { + "DELETE" : { + "description" : "Delete an LDAP server entry.", + "method" : "DELETE", + "name" : "delete", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "section" : { + "description" : "Secion ID.", + "format" : "pve-configid", + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "type" : "null" + } + }, + "GET" : { + "description" : "Get LDAP server configuration.", + "method" : "GET", + "name" : "read", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "section" : { + "description" : "Secion ID.", + "format" : "pve-configid", + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "master", + "returns" : {} + }, + "PUT" : { + "description" : "Update LDAP server settings.", + "method" : "PUT", + "name" : "update", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "accountattr" : { + "default" : "sAMAccountName", + "description" : "Account attribute name name.", + "optional" : 1, + "pattern" : "[a-zA-Z0-9]+", + "type" : "string" + }, + "basedn" : { + "description" : "Base domain name.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "binddn" : { + "description" : "Bind domain name.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "bindpw" : { + "description" : "Bind password.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "delete" : { + "description" : "A list of settings you want to delete.", + "format" : "pve-configid-list", + "maxLength" : 4096, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "digest" : { + "description" : "Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.", + "maxLength" : 40, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "filter" : { + "description" : "LDAP filter.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "groupbasedn" : { + "description" : "Base domain name for groups.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "mailattr" : { + "default" : "mail, userPrincipalName, proxyAddresses, othermailbox", + "description" : "List of mail attribute names.", + "format" : "string-list", + "optional" : 1, + "pattern" : "[a-zA-Z0-9]+", + "type" : "string" + }, + "mode" : { + "default" : "ldap", + "description" : "LDAP protocol mode ('ldap' or 'ldaps').", + "enum" : [ + "ldap", + "ldaps" + ], + "optional" : 1, + "type" : "string" + }, + "port" : { + "description" : "Specify the port to connect to.", + "maximum" : 65535, + "minimum" : 1, + "optional" : 1, + "type" : "integer", + "typetext" : " (1 - 65535)" + }, + "section" : { + "description" : "Secion ID.", + "format" : "pve-configid", + "type" : "string", + "typetext" : "" + }, + "server1" : { + "description" : "Server address.", + "format" : "address", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "server2" : { + "description" : "Fallback server address. Userd when the first server is not available.", + "format" : "address", + "optional" : 1, + "type" : "string", + "typetext" : "" + } + }, + "type" : "object" + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 1, + "path" : "/config/ldap/{section}", + "text" : "{section}" + } + ], + "info" : { + "GET" : { + "description" : "LDAP server list.", + "method" : "GET", + "name" : "index", + "parameters" : { + "additionalProperties" : 0 + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "items" : { + "properties" : { + "mode" : { + "type" : "string" + }, + "section" : { + "type" : "string" + }, + "server1" : { + "type" : "string" + } + }, + "type" : "object" + }, + "links" : [ + { + "href" : "{section}", + "rel" : "child" + } + ], + "type" : "array" + } + }, + "POST" : { + "description" : "Add LDAP server.", + "method" : "POST", + "name" : "create", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "accountattr" : { + "default" : "sAMAccountName", + "description" : "Account attribute name name.", + "optional" : 1, + "pattern" : "[a-zA-Z0-9]+", + "type" : "string" + }, + "basedn" : { + "description" : "Base domain name.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "binddn" : { + "description" : "Bind domain name.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "bindpw" : { + "description" : "Bind password.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "filter" : { + "description" : "LDAP filter.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "groupbasedn" : { + "description" : "Base domain name for groups.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "mailattr" : { + "default" : "mail, userPrincipalName, proxyAddresses, othermailbox", + "description" : "List of mail attribute names.", + "format" : "string-list", + "optional" : 1, + "pattern" : "[a-zA-Z0-9]+", + "type" : "string" + }, + "mode" : { + "default" : "ldap", + "description" : "LDAP protocol mode ('ldap' or 'ldaps').", + "enum" : [ + "ldap", + "ldaps" + ], + "optional" : 1, + "type" : "string" + }, + "port" : { + "description" : "Specify the port to connect to.", + "maximum" : 65535, + "minimum" : 1, + "optional" : 1, + "type" : "integer", + "typetext" : " (1 - 65535)" + }, + "section" : { + "description" : "Secion ID.", + "format" : "pve-configid", + "type" : "string", + "typetext" : "" + }, + "server1" : { + "description" : "Server address.", + "format" : "address", + "optional" : 0, + "type" : "string", + "typetext" : "" + }, + "server2" : { + "description" : "Fallback server address. Userd when the first server is not available.", + "format" : "address", + "optional" : 1, + "type" : "string", + "typetext" : "" + } + }, + "type" : "object" + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 0, + "path" : "/config/ldap", + "text" : "ldap" + }, + { + "children" : [ + { + "info" : { + "DELETE" : { + "description" : "Delete a relay domain", + "method" : "DELETE", + "name" : "delete", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "domain" : { + "description" : "Domain name.", + "format" : "dns-name", + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 1, + "path" : "/config/domains/{domain}", + "text" : "{domain}" + } + ], + "info" : { + "GET" : { + "description" : "List relay domains.", + "method" : "GET", + "name" : "index", + "parameters" : { + "additionalProperties" : 0 + }, + "proxyto" : "master", + "returns" : { + "items" : { + "properties" : { + "domain" : { + "type" : "string" + } + }, + "type" : "object" + }, + "links" : [ + { + "href" : "{section}", + "rel" : "child" + } + ], + "type" : "array" + } + }, + "POST" : { + "description" : "Add relay domain.", + "method" : "POST", + "name" : "create", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "domain" : { + "description" : "Domain name.", + "format" : "dns-name", + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 0, + "path" : "/config/domains", + "text" : "domains" + }, + { + "info" : { + "GET" : { + "description" : "Cluster node index.", + "method" : "GET", + "name" : "index", + "parameters" : { + "additionalProperties" : 0 + }, + "returns" : { + "items" : { + "properties" : { + "cid" : { + "type" : "integer" + } + }, + "type" : "object" + }, + "links" : [ + { + "href" : "{cid}", + "rel" : "child" + } + ], + "type" : "array" + } + } + }, + "leaf" : 1, + "path" : "/config/cluster", + "text" : "cluster" + }, + { + "info" : { + "GET" : { + "description" : "Read admin configuration properties.", + "method" : "GET", + "name" : "read_admin_section", + "parameters" : { + "additionalProperties" : 0 + }, + "proxyto" : "master", + "returns" : { + "type" : "object" + } + }, + "PUT" : { + "description" : "Update admin configuration properties.", + "method" : "PUT", + "name" : "update_admin_section", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "dailyreport" : { + "default" : 1, + "description" : "Send daily reports.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "delete" : { + "description" : "A list of settings you want to delete.", + "format" : "pve-configid-list", + "maxLength" : 4096, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "demo" : { + "default" : 0, + "description" : "Demo mode - do not start SMTP filter.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "digest" : { + "description" : "Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.", + "maxLength" : 40, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "proxypassword" : { + "description" : "HTTP proxy password.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "proxyport" : { + "default" : 8080, + "description" : "HTTP proxy port.", + "minimum" : 1, + "optional" : 1, + "type" : "integer", + "typetext" : " (1 - N)" + }, + "proxyserver" : { + "description" : "HTTP proxy server address.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "proxyuser" : { + "description" : "HTTP proxy user name.", + "optional" : 1, + "type" : "string", + "typetext" : "" + } + }, + "type" : "object" + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 1, + "path" : "/config/admin", + "text" : "admin" + }, + { + "info" : { + "GET" : { + "description" : "Read clamav configuration properties.", + "method" : "GET", + "name" : "read_clamav_section", + "parameters" : { + "additionalProperties" : 0 + }, + "proxyto" : "master", + "returns" : { + "type" : "object" + } + }, + "PUT" : { + "description" : "Update clamav configuration properties.", + "method" : "PUT", + "name" : "update_clamav_section", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "archiveblockencrypted" : { + "default" : 0, + "description" : "Wether to block encrypted archives. Mark encrypted archives as viruses.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "archivemaxfiles" : { + "default" : 1000, + "description" : "Number of files to be scanned within an archive, a document, or any other kind of container. Warning: disabling this limit or setting it too high may result in severe damage to the system.", + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "archivemaxrec" : { + "default" : 5, + "description" : "Nested archives are scanned recursively, e.g. if a ZIP archive contains a TAR file, all files within it will also be scanned. This options specifies how deeply the process should be continued. Warning: setting this limit too high may result in severe damage to the system.", + "minimum" : 1, + "optional" : 1, + "type" : "integer", + "typetext" : " (1 - N)" + }, + "archivemaxsize" : { + "default" : 25000000, + "description" : "Files larger than this limit won't be scanned.", + "minimum" : 1000000, + "optional" : 1, + "type" : "integer", + "typetext" : " (1000000 - N)" + }, + "dbmirror" : { + "default" : "database.clamav.net", + "description" : "ClamAV database mirror server.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "delete" : { + "description" : "A list of settings you want to delete.", + "format" : "pve-configid-list", + "maxLength" : 4096, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "digest" : { + "description" : "Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.", + "maxLength" : 40, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "maxcccount" : { + "default" : 0, + "description" : "This option sets the lowest number of Credit Card or Social Security numbers found in a file to generate a detect.", + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "maxscansize" : { + "default" : 100000000, + "description" : "Sets the maximum amount of data to be scanned for each input file.", + "minimum" : 1000000, + "optional" : 1, + "type" : "integer", + "typetext" : " (1000000 - N)" + } + }, + "type" : "object" + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 1, + "path" : "/config/clamav", + "text" : "clamav" + }, + { + "info" : { + "GET" : { + "description" : "Read mail configuration properties.", + "method" : "GET", + "name" : "read_mail_section", + "parameters" : { + "additionalProperties" : 0 + }, + "proxyto" : "master", + "returns" : { + "type" : "object" + } + }, + "PUT" : { + "description" : "Update mail configuration properties.", + "method" : "PUT", + "name" : "update_mail_section", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "banner" : { + "default" : "ESMTP Proxmox", + "description" : "ESMTP banner.", + "maxLength" : 1024, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "conn_count_limit" : { + "default" : 50, + "description" : "How many simultaneous connections any client is allowed to make to this service. To disable this feature, specify a limit of 0.", + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "conn_rate_limit" : { + "default" : 0, + "description" : "The maximal number of connection attempts any client is allowed to make to this service per minute. To disable this feature, specify a limit of 0.", + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "delete" : { + "description" : "A list of settings you want to delete.", + "format" : "pve-configid-list", + "maxLength" : 4096, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "digest" : { + "description" : "Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.", + "maxLength" : 40, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "dnsbl_sites" : { + "description" : "Optional list of DNS white/blacklist domains (see postscreen_dnsbl_sites parameter).", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "dwarning" : { + "default" : 4, + "description" : "SMTP delay warning time (in hours).", + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "greylist" : { + "default" : 1, + "description" : "Use Greylisting.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "helotests" : { + "default" : 0, + "description" : "Use SMTP HELO tests.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "hide_received" : { + "default" : 0, + "description" : "Hide received header in outgoing mails.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "max_filters" : { + "default" : 15, + "description" : "Maximum number of pmg-smtp-filter processes.", + "maximum" : 40, + "minimum" : 3, + "optional" : 1, + "type" : "integer", + "typetext" : " (3 - 40)" + }, + "max_policy" : { + "default" : 5, + "description" : "Maximum number of pmgpolicy processes.", + "maximum" : 10, + "minimum" : 2, + "optional" : 1, + "type" : "integer", + "typetext" : " (2 - 10)" + }, + "max_smtpd_in" : { + "default" : 99, + "description" : "Maximum number of SMTP daemon processes (in).", + "maximum" : 100, + "minimum" : 3, + "optional" : 1, + "type" : "integer", + "typetext" : " (3 - 100)" + }, + "max_smtpd_out" : { + "default" : 99, + "description" : "Maximum number of SMTP daemon processes (out).", + "maximum" : 100, + "minimum" : 3, + "optional" : 1, + "type" : "integer", + "typetext" : " (3 - 100)" + }, + "maxsize" : { + "default" : 10485760, + "description" : "Maximum email size. Larger mails are rejected.", + "minimum" : 1024, + "optional" : 1, + "type" : "integer", + "typetext" : " (1024 - N)" + }, + "message_rate_limit" : { + "default" : 0, + "description" : "The maximal number of message delivery requests that any client is allowed to make to this service per minute.To disable this feature, specify a limit of 0.", + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "rejectunknown" : { + "default" : 0, + "description" : "Reject unknown clients.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "rejectunknownsender" : { + "default" : 0, + "description" : "Reject unknown senders.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "relay" : { + "description" : "The default mail delivery transport (incoming mails).", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "relaynomx" : { + "default" : 0, + "description" : "Disable MX lookups for default relay.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "relayport" : { + "default" : 25, + "description" : "SMTP port number for relay host.", + "maximum" : 65535, + "minimum" : 1, + "optional" : 1, + "type" : "integer", + "typetext" : " (1 - 65535)" + }, + "spf" : { + "default" : 1, + "description" : "Use Sender Policy Framework.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "tls" : { + "default" : 0, + "description" : "Use TLS.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "use_rbl" : { + "default" : 1, + "description" : "Use Realtime Blacklists.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "verifyreceivers" : { + "default" : 0, + "description" : "Enable receiver verification. The value (if greater than 0) spefifies the numerical reply code when the Postfix SMTP server rejects a recipient address (450 or 550).", + "maximum" : 599, + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - 599)" + } + }, + "type" : "object" + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 1, + "path" : "/config/mail", + "text" : "mail" + }, + { + "info" : { + "GET" : { + "description" : "Read spam configuration properties.", + "method" : "GET", + "name" : "read_spam_section", + "parameters" : { + "additionalProperties" : 0 + }, + "proxyto" : "master", + "returns" : { + "type" : "object" + } + }, + "PUT" : { + "description" : "Update spam configuration properties.", + "method" : "PUT", + "name" : "update_spam_section", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "bounce_score" : { + "default" : 0, + "description" : "Additional score for bounce mails.", + "maximum" : 1000, + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - 1000)" + }, + "delete" : { + "description" : "A list of settings you want to delete.", + "format" : "pve-configid-list", + "maxLength" : 4096, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "digest" : { + "description" : "Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.", + "maxLength" : 40, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "languages" : { + "default" : "all", + "description" : "This option is used to specify which languages are considered OK for incoming mail.", + "optional" : 1, + "pattern" : "(all|([a-z][a-z])+( ([a-z][a-z])+)*)", + "type" : "string" + }, + "maxspamsize" : { + "default" : 204800, + "description" : "Maximum size of spam messages in bytes.", + "minimum" : 64, + "optional" : 1, + "type" : "integer", + "typetext" : " (64 - N)" + }, + "rbl_checks" : { + "default" : 1, + "description" : "Enable real time blacklists (RBL) checks.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "use_awl" : { + "default" : 1, + "description" : "Use the Auto-Whitelist plugin.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "use_bayes" : { + "default" : 1, + "description" : "Whether to use the naive-Bayesian-style classifier.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "use_ocr" : { + "default" : 0, + "description" : "Enable OCR to scan pictures.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "use_razor" : { + "default" : 1, + "description" : "Whether to use Razor2, if it is available.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "wl_bounce_relays" : { + "description" : "Whitelist legitimate bounce relays.", + "optional" : 1, + "type" : "string", + "typetext" : "" + } + }, + "type" : "object" + }, + "protected" : 1, + "proxyto" : "master", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 1, + "path" : "/config/spam", + "text" : "spam" + } + ], + "info" : { + "GET" : { + "description" : "Directory index.", + "method" : "GET", + "name" : "index", + "parameters" : { + "additionalProperties" : 0 + }, + "returns" : { + "items" : { + "properties" : { + "section" : { + "type" : "string" + } + }, + "type" : "object" + }, + "links" : [ + { + "href" : "{section}", + "rel" : "child" + } + ], + "type" : "array" + } + } + }, + "leaf" : 0, + "path" : "/config", + "text" : "config" + }, + { + "children" : [ + { + "children" : [ + { + "children" : [ + { + "info" : { + "DELETE" : { + "description" : "Delete network device configuration", + "method" : "DELETE", + "name" : "delete_network", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "iface" : { + "description" : "Network interface name.", + "format" : "pve-iface", + "maxLength" : 20, + "minLength" : 2, + "type" : "string", + "typetext" : "" + }, + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "type" : "null" + } + }, + "GET" : { + "description" : "Read network device configuration", + "method" : "GET", + "name" : "network_config", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "iface" : { + "description" : "Network interface name.", + "format" : "pve-iface", + "maxLength" : 20, + "minLength" : 2, + "type" : "string", + "typetext" : "" + }, + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + } + } + }, + "proxyto" : "node", + "returns" : { + "properties" : { + "method" : { + "type" : "string" + }, + "type" : { + "type" : "string" + } + }, + "type" : "object" + } + }, + "PUT" : { + "description" : "Update network device configuration", + "method" : "PUT", + "name" : "update_network", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "address" : { + "description" : "IP address.", + "format" : "ipv4", + "optional" : 1, + "requires" : "netmask", + "type" : "string", + "typetext" : "" + }, + "address6" : { + "description" : "IP address.", + "format" : "ipv6", + "optional" : 1, + "requires" : "netmask6", + "type" : "string", + "typetext" : "" + }, + "autostart" : { + "description" : "Automatically start interface on boot.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "bond_mode" : { + "description" : "Bonding mode.", + "enum" : [ + "balance-rr", + "active-backup", + "balance-xor", + "broadcast", + "802.3ad", + "balance-tlb", + "balance-alb", + "balance-slb", + "lacp-balance-slb", + "lacp-balance-tcp" + ], + "optional" : 1, + "type" : "string" + }, + "bond_xmit_hash_policy" : { + "description" : "Selects the transmit hash policy to use for slave selection in balance-xor and 802.3ad modes.", + "enum" : [ + "layer2", + "layer2+3", + "layer3+4" + ], + "optional" : 1, + "type" : "string" + }, + "bridge_ports" : { + "description" : "Specify the iterfaces you want to add to your bridge.", + "format" : "pve-iface-list", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "bridge_vlan_aware" : { + "description" : "Enable bridge vlan support.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "comments" : { + "description" : "Comments", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "comments6" : { + "description" : "Comments", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "delete" : { + "description" : "A list of settings you want to delete.", + "format" : "pve-configid-list", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "gateway" : { + "description" : "Default gateway address.", + "format" : "ipv4", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "gateway6" : { + "description" : "Default ipv6 gateway address.", + "format" : "ipv6", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "iface" : { + "description" : "Network interface name.", + "format" : "pve-iface", + "maxLength" : 20, + "minLength" : 2, + "type" : "string", + "typetext" : "" + }, + "netmask" : { + "description" : "Network mask.", + "format" : "ipv4mask", + "optional" : 1, + "requires" : "address", + "type" : "string", + "typetext" : "" + }, + "netmask6" : { + "description" : "Network mask.", + "maximum" : 128, + "minimum" : 0, + "optional" : 1, + "requires" : "address6", + "type" : "integer", + "typetext" : " (0 - 128)" + }, + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "ovs_bonds" : { + "description" : "Specify the interfaces used by the bonding device.", + "format" : "pve-iface-list", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "ovs_bridge" : { + "description" : "The OVS bridge associated with a OVS port. This is required when you create an OVS port.", + "format" : "pve-iface", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "ovs_options" : { + "description" : "OVS interface options.", + "maxLength" : 1024, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "ovs_ports" : { + "description" : "Specify the iterfaces you want to add to your bridge.", + "format" : "pve-iface-list", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "ovs_tag" : { + "description" : "Specify a VLan tag (used by OVSPort, OVSIntPort, OVSBond)", + "maximum" : 4094, + "minimum" : 1, + "optional" : 1, + "type" : "integer", + "typetext" : " (1 - 4094)" + }, + "slaves" : { + "description" : "Specify the interfaces used by the bonding device.", + "format" : "pve-iface-list", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "type" : { + "description" : "Network interface type", + "enum" : [ + "bridge", + "bond", + "eth", + "alias", + "vlan", + "OVSBridge", + "OVSBond", + "OVSPort", + "OVSIntPort", + "unknown" + ], + "type" : "string" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/network/{iface}", + "text" : "{iface}" + } + ], + "info" : { + "DELETE" : { + "description" : "Revert network configuration changes.", + "method" : "DELETE", + "name" : "revert_network_changes", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "type" : "null" + } + }, + "GET" : { + "description" : "List available networks", + "method" : "GET", + "name" : "index", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "type" : { + "description" : "Only list specific interface types.", + "enum" : [ + "bridge", + "bond", + "eth", + "alias", + "vlan", + "OVSBridge", + "OVSBond", + "OVSPort", + "OVSIntPort", + "any_bridge" + ], + "optional" : 1, + "type" : "string" + } + } + }, + "proxyto" : "node", + "returns" : { + "items" : { + "properties" : {}, + "type" : "object" + }, + "links" : [ + { + "href" : "{iface}", + "rel" : "child" + } + ], + "type" : "array" + } + }, + "POST" : { + "description" : "Create network device configuration", + "method" : "POST", + "name" : "create_network", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "address" : { + "description" : "IP address.", + "format" : "ipv4", + "optional" : 1, + "requires" : "netmask", + "type" : "string", + "typetext" : "" + }, + "address6" : { + "description" : "IP address.", + "format" : "ipv6", + "optional" : 1, + "requires" : "netmask6", + "type" : "string", + "typetext" : "" + }, + "autostart" : { + "description" : "Automatically start interface on boot.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "bond_mode" : { + "description" : "Bonding mode.", + "enum" : [ + "balance-rr", + "active-backup", + "balance-xor", + "broadcast", + "802.3ad", + "balance-tlb", + "balance-alb", + "balance-slb", + "lacp-balance-slb", + "lacp-balance-tcp" + ], + "optional" : 1, + "type" : "string" + }, + "bond_xmit_hash_policy" : { + "description" : "Selects the transmit hash policy to use for slave selection in balance-xor and 802.3ad modes.", + "enum" : [ + "layer2", + "layer2+3", + "layer3+4" + ], + "optional" : 1, + "type" : "string" + }, + "bridge_ports" : { + "description" : "Specify the iterfaces you want to add to your bridge.", + "format" : "pve-iface-list", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "bridge_vlan_aware" : { + "description" : "Enable bridge vlan support.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "comments" : { + "description" : "Comments", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "comments6" : { + "description" : "Comments", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "gateway" : { + "description" : "Default gateway address.", + "format" : "ipv4", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "gateway6" : { + "description" : "Default ipv6 gateway address.", + "format" : "ipv6", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "iface" : { + "description" : "Network interface name.", + "format" : "pve-iface", + "maxLength" : 20, + "minLength" : 2, + "type" : "string", + "typetext" : "" + }, + "netmask" : { + "description" : "Network mask.", + "format" : "ipv4mask", + "optional" : 1, + "requires" : "address", + "type" : "string", + "typetext" : "" + }, + "netmask6" : { + "description" : "Network mask.", + "maximum" : 128, + "minimum" : 0, + "optional" : 1, + "requires" : "address6", + "type" : "integer", + "typetext" : " (0 - 128)" + }, + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "ovs_bonds" : { + "description" : "Specify the interfaces used by the bonding device.", + "format" : "pve-iface-list", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "ovs_bridge" : { + "description" : "The OVS bridge associated with a OVS port. This is required when you create an OVS port.", + "format" : "pve-iface", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "ovs_options" : { + "description" : "OVS interface options.", + "maxLength" : 1024, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "ovs_ports" : { + "description" : "Specify the iterfaces you want to add to your bridge.", + "format" : "pve-iface-list", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "ovs_tag" : { + "description" : "Specify a VLan tag (used by OVSPort, OVSIntPort, OVSBond)", + "maximum" : 4094, + "minimum" : 1, + "optional" : 1, + "type" : "integer", + "typetext" : " (1 - 4094)" + }, + "slaves" : { + "description" : "Specify the interfaces used by the bonding device.", + "format" : "pve-iface-list", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "type" : { + "description" : "Network interface type", + "enum" : [ + "bridge", + "bond", + "eth", + "alias", + "vlan", + "OVSBridge", + "OVSBond", + "OVSPort", + "OVSIntPort", + "unknown" + ], + "type" : "string" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 0, + "path" : "/nodes/{node}/network", + "text" : "network" + }, + { + "children" : [ + { + "children" : [ + { + "info" : { + "GET" : { + "description" : "Read task log.", + "method" : "GET", + "name" : "read_task_log", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "limit" : { + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "start" : { + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "upid" : { + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "items" : { + "properties" : { + "n" : { + "description" : "Line number", + "type" : "integer" + }, + "t" : { + "description" : "Line text", + "type" : "string" + } + }, + "type" : "object" + }, + "type" : "array" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/tasks/{upid}/log", + "text" : "log" + }, + { + "info" : { + "GET" : { + "description" : "Read task status.", + "method" : "GET", + "name" : "read_task_status", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "upid" : { + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "properties" : { + "pid" : { + "type" : "integer" + }, + "status" : { + "enum" : [ + "running", + "stopped" + ], + "type" : "string" + } + }, + "type" : "object" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/tasks/{upid}/status", + "text" : "status" + } + ], + "info" : { + "DELETE" : { + "description" : "Stop a task.", + "method" : "DELETE", + "name" : "stop_task", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "upid" : { + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "type" : "null" + } + }, + "GET" : { + "description" : "", + "method" : "GET", + "name" : "upid_index", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "upid" : { + "type" : "string", + "typetext" : "" + } + } + }, + "returns" : { + "items" : { + "properties" : {}, + "type" : "object" + }, + "links" : [ + { + "href" : "{name}", + "rel" : "child" + } + ], + "type" : "array" + } + } + }, + "leaf" : 0, + "path" : "/nodes/{node}/tasks/{upid}", + "text" : "{upid}" + } + ], + "info" : { + "GET" : { + "description" : "Read task list for one node (finished tasks).", + "method" : "GET", + "name" : "node_tasks", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "errors" : { + "optional" : 1, + "type" : "boolean", + "typetext" : "" + }, + "limit" : { + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "start" : { + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "userfilter" : { + "optional" : 1, + "type" : "string", + "typetext" : "" + } + } + }, + "proxyto" : "node", + "returns" : { + "items" : { + "properties" : { + "upid" : { + "type" : "string" + } + }, + "type" : "object" + }, + "links" : [ + { + "href" : "{upid}", + "rel" : "child" + } + ], + "type" : "array" + } + } + }, + "leaf" : 0, + "path" : "/nodes/{node}/tasks", + "text" : "tasks" + }, + { + "children" : [ + { + "children" : [ + { + "info" : { + "GET" : { + "description" : "Read service properties", + "method" : "GET", + "name" : "service_state", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "service" : { + "description" : "Service ID", + "enum" : [ + "pmgproxy", + "pmgdaemon", + "pmg-smtp-filter", + "sshd", + "syslog", + "cron", + "postfix", + "systemd-timesyncd" + ], + "type" : "string" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "properties" : {}, + "type" : "object" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/services/{service}/state", + "text" : "state" + }, + { + "info" : { + "POST" : { + "description" : "Start service.", + "method" : "POST", + "name" : "service_start", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "service" : { + "description" : "Service ID", + "enum" : [ + "pmgproxy", + "pmgdaemon", + "pmg-smtp-filter", + "sshd", + "syslog", + "cron", + "postfix", + "systemd-timesyncd" + ], + "type" : "string" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "type" : "string" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/services/{service}/start", + "text" : "start" + }, + { + "info" : { + "POST" : { + "description" : "Stop service.", + "method" : "POST", + "name" : "service_stop", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "service" : { + "description" : "Service ID", + "enum" : [ + "pmgproxy", + "pmgdaemon", + "pmg-smtp-filter", + "sshd", + "syslog", + "cron", + "postfix", + "systemd-timesyncd" + ], + "type" : "string" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "type" : "string" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/services/{service}/stop", + "text" : "stop" + }, + { + "info" : { + "POST" : { + "description" : "Restart service.", + "method" : "POST", + "name" : "service_restart", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "service" : { + "description" : "Service ID", + "enum" : [ + "pmgproxy", + "pmgdaemon", + "pmg-smtp-filter", + "sshd", + "syslog", + "cron", + "postfix", + "systemd-timesyncd" + ], + "type" : "string" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "type" : "string" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/services/{service}/restart", + "text" : "restart" + }, + { + "info" : { + "POST" : { + "description" : "Reload service.", + "method" : "POST", + "name" : "service_reload", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "service" : { + "description" : "Service ID", + "enum" : [ + "pmgproxy", + "pmgdaemon", + "pmg-smtp-filter", + "sshd", + "syslog", + "cron", + "postfix", + "systemd-timesyncd" + ], + "type" : "string" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "type" : "string" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/services/{service}/reload", + "text" : "reload" + } + ], + "info" : { + "GET" : { + "description" : "Directory index", + "method" : "GET", + "name" : "srvcmdidx", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "service" : { + "description" : "Service ID", + "enum" : [ + "pmgproxy", + "pmgdaemon", + "pmg-smtp-filter", + "sshd", + "syslog", + "cron", + "postfix", + "systemd-timesyncd" + ], + "type" : "string" + } + } + }, + "returns" : { + "items" : { + "properties" : { + "subdir" : { + "type" : "string" + } + }, + "type" : "object" + }, + "links" : [ + { + "href" : "{subdir}", + "rel" : "child" + } + ], + "type" : "array" + } + } + }, + "leaf" : 0, + "path" : "/nodes/{node}/services/{service}", + "text" : "{service}" + } + ], + "info" : { + "GET" : { + "description" : "Service list.", + "method" : "GET", + "name" : "index", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "items" : { + "properties" : {}, + "type" : "object" + }, + "links" : [ + { + "href" : "{service}", + "rel" : "child" + } + ], + "type" : "array" + } + } + }, + "leaf" : 0, + "path" : "/nodes/{node}/services", + "text" : "services" + }, + { + "info" : { + "GET" : { + "description" : "Read system log", + "method" : "GET", + "name" : "syslog", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "limit" : { + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "since" : { + "description" : "Display all log since this date-time string.", + "optional" : 1, + "pattern" : "^\\d{4}-\\d{2}-\\d{2}( \\d{2}:\\d{2}(:\\d{2})?)?$", + "type" : "string" + }, + "start" : { + "minimum" : 0, + "optional" : 1, + "type" : "integer", + "typetext" : " (0 - N)" + }, + "until" : { + "description" : "Display all log until this date-time string.", + "optional" : 1, + "pattern" : "^\\d{4}-\\d{2}-\\d{2}( \\d{2}:\\d{2}(:\\d{2})?)?$", + "type" : "string" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "items" : { + "properties" : { + "n" : { + "description" : "Line number", + "type" : "integer" + }, + "t" : { + "description" : "Line text", + "type" : "string" + } + }, + "type" : "object" + }, + "type" : "array" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/syslog", + "text" : "syslog" + }, + { + "info" : { + "POST" : { + "description" : "Creates a VNC Shell proxy.", + "method" : "POST", + "name" : "vncshell", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "websocket" : { + "default" : 1, + "description" : "use websocket instead of standard vnc.", + "optional" : 1, + "type" : "boolean", + "typetext" : "" + } + } + }, + "protected" : 1, + "returns" : { + "additionalProperties" : 0, + "properties" : { + "port" : { + "type" : "integer" + }, + "ticket" : { + "type" : "string" + }, + "upid" : { + "type" : "string" + }, + "user" : { + "type" : "string" + } + } + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/vncshell", + "text" : "vncshell" + }, + { + "info" : { + "GET" : { + "description" : "Opens a weksocket for VNC traffic.", + "method" : "GET", + "name" : "vncwebsocket", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "port" : { + "description" : "Port number returned by previous vncproxy call.", + "maximum" : 5999, + "minimum" : 5900, + "type" : "integer", + "typetext" : " (5900 - 5999)" + }, + "vncticket" : { + "description" : "Ticket from previous call to vncproxy.", + "maxLength" : 512, + "type" : "string", + "typetext" : "" + } + } + }, + "returns" : { + "properties" : { + "port" : { + "type" : "string" + } + }, + "type" : "object" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/vncwebsocket", + "text" : "vncwebsocket" + }, + { + "info" : { + "GET" : { + "description" : "Read DNS settings.", + "method" : "GET", + "name" : "dns", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + } + } + }, + "proxyto" : "node", + "returns" : { + "additionalProperties" : 0, + "properties" : { + "dns1" : { + "description" : "First name server IP address.", + "optional" : 1, + "type" : "string" + }, + "dns2" : { + "description" : "Second name server IP address.", + "optional" : 1, + "type" : "string" + }, + "dns3" : { + "description" : "Third name server IP address.", + "optional" : 1, + "type" : "string" + }, + "search" : { + "description" : "Search domain for host-name lookup.", + "optional" : 1, + "type" : "string" + } + }, + "type" : "object" + } + }, + "PUT" : { + "description" : "Write DNS settings.", + "method" : "PUT", + "name" : "update_dns", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "dns1" : { + "description" : "First name server IP address.", + "format" : "ip", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "dns2" : { + "description" : "Second name server IP address.", + "format" : "ip", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "dns3" : { + "description" : "Third name server IP address.", + "format" : "ip", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "search" : { + "description" : "Search domain for host-name lookup.", + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/dns", + "text" : "dns" + }, + { + "info" : { + "GET" : { + "description" : "Read server time and time zone settings.", + "method" : "GET", + "name" : "time", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + } + } + }, + "proxyto" : "node", + "returns" : { + "additionalProperties" : 0, + "properties" : { + "localtime" : { + "description" : "Seconds since 1970-01-01 00:00:00 (local time)", + "minimum" : 1297163644, + "type" : "integer" + }, + "time" : { + "description" : "Seconds since 1970-01-01 00:00:00 UTC.", + "minimum" : 1297163644, + "type" : "integer" + }, + "timezone" : { + "description" : "Time zone", + "type" : "string" + } + }, + "type" : "object" + } + }, + "PUT" : { + "description" : "Set time zone.", + "method" : "PUT", + "name" : "set_timezone", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + }, + "timezone" : { + "description" : "Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.", + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "proxyto" : "node", + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 1, + "path" : "/nodes/{node}/time", + "text" : "time" + } + ], + "info" : { + "GET" : { + "description" : "Node index.", + "method" : "GET", + "name" : "index", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "node" : { + "description" : "The cluster node name.", + "format" : "pve-node", + "type" : "string", + "typetext" : "" + } + } + }, + "permissions" : { + "user" : "all" + }, + "returns" : { + "items" : { + "properties" : {}, + "type" : "object" + }, + "links" : [ + { + "href" : "{name}", + "rel" : "child" + } + ], + "type" : "array" + } + } + }, + "leaf" : 0, + "path" : "/nodes/{node}", + "text" : "{node}" + } + ], + "info" : { + "GET" : { + "description" : "Cluster node index.", + "method" : "GET", + "name" : "index", + "parameters" : { + "additionalProperties" : 0 + }, + "permissions" : { + "user" : "all" + }, + "returns" : { + "items" : { + "properties" : {}, + "type" : "object" + }, + "links" : [ + { + "href" : "{node}", + "rel" : "child" + } + ], + "type" : "array" + } + } + }, + "leaf" : 0, + "path" : "/nodes", + "text" : "nodes" + }, + { + "children" : [ + { + "info" : { + "GET" : { + "description" : "Dummy. Useful for formaters which want to priovde a login page.", + "method" : "GET", + "name" : "get_ticket", + "parameters" : { + "additionalProperties" : 0 + }, + "permissions" : { + "user" : "world" + }, + "returns" : { + "type" : "null" + } + }, + "POST" : { + "description" : "Create or verify authentication ticket.", + "method" : "POST", + "name" : "create_ticket", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "otp" : { + "description" : "One-time password for Two-factor authentication.", + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "password" : { + "description" : "The secret password. This can also be a valid ticket.", + "type" : "string", + "typetext" : "" + }, + "realm" : { + "description" : "You can optionally pass the realm using this parameter. Normally the realm is simply added to the username @.", + "format" : "pmg-realm", + "maxLength" : 32, + "optional" : 1, + "type" : "string", + "typetext" : "" + }, + "username" : { + "description" : "User name", + "maxLength" : 64, + "type" : "string", + "typetext" : "" + } + } + }, + "permissions" : { + "description" : "You need to pass valid credientials.", + "user" : "world" + }, + "protected" : 1, + "returns" : { + "properties" : { + "CSRFPreventionToken" : { + "optional" : 1, + "type" : "string" + }, + "ticket" : { + "optional" : 1, + "type" : "string" + }, + "username" : { + "type" : "string" + } + }, + "type" : "object" + } + } + }, + "leaf" : 1, + "path" : "/access/ticket", + "text" : "ticket" + }, + { + "info" : { + "PUT" : { + "description" : "Change user password.", + "method" : "PUT", + "name" : "change_passsword", + "parameters" : { + "additionalProperties" : 0, + "properties" : { + "password" : { + "description" : "The new password.", + "maxLength" : 64, + "minLength" : 5, + "type" : "string", + "typetext" : "" + }, + "userid" : { + "description" : "User ID", + "format" : "pmg-userid", + "maxLength" : 64, + "type" : "string", + "typetext" : "" + } + } + }, + "protected" : 1, + "returns" : { + "type" : "null" + } + } + }, + "leaf" : 1, + "path" : "/access/password", + "text" : "password" + } + ], + "info" : { + "GET" : { + "description" : "Directory index.", + "method" : "GET", + "name" : "index", + "parameters" : { + "additionalProperties" : 0 + }, + "permissions" : { + "user" : "all" + }, + "returns" : { + "items" : { + "properties" : { + "subdir" : { + "type" : "string" + } + }, + "type" : "object" + }, + "links" : [ + { + "href" : "{subdir}", + "rel" : "child" + } + ], + "type" : "array" + } + } + }, + "leaf" : 0, + "path" : "/access", + "text" : "access" + }, + { + "info" : { + "GET" : { + "description" : "API version details.", + "method" : "GET", + "name" : "version", + "parameters" : { + "additionalProperties" : 0 + }, + "permissions" : { + "user" : "all" + }, + "returns" : { + "properties" : { + "release" : { + "type" : "string" + }, + "repoid" : { + "type" : "string" + }, + "version" : { + "type" : "string" + } + }, + "type" : "object" + } + } + }, + "leaf" : 1, + "path" : "/version", + "text" : "version" + } +] +; + diff --git a/api-viewer/index.html b/api-viewer/index.html new file mode 100644 index 0000000..97ed69e --- /dev/null +++ b/api-viewer/index.html @@ -0,0 +1,13 @@ + + + + + + Proxmox VE API Documentation + + + + + + + diff --git a/asciidoc-pmg.in b/asciidoc-pmg.in new file mode 100644 index 0000000..e473d8b --- /dev/null +++ b/asciidoc-pmg.in @@ -0,0 +1,625 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Getopt::Long; +use File::Path; +use File::Basename; +use IO::File; +use Cwd; + +use JSON; + +my $verbose; +my $keep_artifacts; + +my $release = '@RELEASE@'; + +my $clicmd = shift or + die "no command specified\n"; + +my $data_str = ""; +while () { $data_str .= $_; } + +my $fileinfo = decode_json($data_str); + +my $tmpprefix = '.asciidoc-pmg-tmp'.$$.'_'; + +my $adoc_source_dir = "/usr/share/pmg-doc-generator"; + +# inside pmg-docs source dir? +if (-f "asciidoc-pmg.in" && -f "pmg-admin-guide.adoc") { + $adoc_source_dir = getcwd(); +} + +my $prepared_files = {}; + +my $man_target = 'man'; +my $env_stack = []; +my $env_skip = 0; + +my $online_help_links = { + 'pmg_service_daemons' => { + link => '/pmg-docs/index.html#_service_daemons', + title => 'Service Daemons', + }, + 'pmg_documentation_index' => { + link => '/pmg-docs/index.html', + title => 'Proxmox VE Documentation Index', + }, + 'pmg_admin_guide' => { + link => '/pmg-docs/pmg-admin-guide.html', + title => 'Proxmox VE Administration Guide', + }, +}; + +sub debug { + my $msg = shift; + + return if !$verbose; + + print STDERR "asciidoc-pmg: $msg\n"; +} + +sub push_environment { + my ($env, $skip) = @_; + + $skip = 1 if $env_skip; + $skip = 0 if !defined($skip); + + push @$env_stack, [$env, $skip]; + + $env_skip = $skip; +} + +sub pop_environment { + my ($env) = @_; + + my $last_stack_entry = pop @$env_stack; + die "unable to pop env '$env'" if !defined($last_stack_entry); + + my ($last_env, $skip) = @$last_stack_entry; + die "environment missmatch (${last_env} != $env)\n" if $last_env ne $env; + + if (!scalar(@$env_stack)) { + $env_skip = 0; + } else { + my (undef, $skip) = @{$env_stack->[-1]}; + $env_skip = $skip; + } +} + +my $files_for_cleanup = []; + +sub cleanup { + + return if $keep_artifacts; + + foreach my $file (@$files_for_cleanup) { + unlink $file; + } +} + +sub replace_wiki_xref { + my ($blockid, $text) = @_; + + my $link = $fileinfo->{blockid_target}->{wiki}->{$blockid}; + my $reftext = $fileinfo->{reftext}->{wiki}->{$blockid}; + + die "unable to resolve wiki link (xref:$blockid)\n" + if !defined($link); + + $text = $reftext if !length($text); + + die "xref: no text for wiki link '$blockid'\n" if !$text; + + return "$link\[$text\]"; +} + +sub replace_default_xref { + my ($blockid, $text) = @_; + + my $link = $fileinfo->{blockid_target}->{default}->{$blockid}; + my $reftext = $fileinfo->{reftext}->{default}->{$blockid}; + + die "unable to resolve chapter link (xref:$blockid)\n" + if !defined($link); + + $text = $reftext if !length($text); + + die "xref: no text for chapter link '$blockid'\n" if !$text; + + return "$link\[$text\]"; +} + +sub replace_man_xref { + my ($blockid, $text) = @_; + + my $link = $fileinfo->{blockid_target}->{manvolnum}->{$blockid}; + my $reftext = $fileinfo->{reftext}->{manvolnum}->{$blockid}; + + die "unable to resolve man page link (xref:$blockid)\n" + if !defined($link); + + $text = $reftext if !length($text); + + die "xref: no text for man page link '$blockid'\n" if !$text; + + my $section = $fileinfo->{mansection}->{manvolnum}->{$link}; + die "link target is not a manual page" if !defined($section); + + + if ($man_target eq 'html') { + my $target = $link; + $target =~ s/\.adoc//; + $target .= ".$section"; + return "link:${target}.html#${blockid}\[$text\]"; + } elsif ($man_target eq 'man') { + my $command = $link; + $command =~ s/\.adoc//; + return "\*${text}\* (man \*${command}\*($section))"; + } else { + die "internal error" + } +} + +sub replace_xref { + my ($env, $blockid, $text) = @_; + + if ($env eq 'wiki') { + return replace_wiki_xref($blockid, $text); + } elsif ($env eq 'manvolnum') { + if (($man_target eq 'man') || ($man_target eq 'html')) { + return replace_man_xref($blockid, $text); + } elsif ($man_target eq 'wiki') { + return replace_wiki_xref($blockid, $text); + } else { + die "internal error" + } + } elsif ($env eq 'default') { + return replace_default_xref($blockid, $text); + } else { + die "internal error"; + } +} + +sub prepare_adoc_file { + my ($target_env, $filename, $attributes) = @_; + + return $prepared_files->{$filename} if defined($prepared_files->{$filename}); + + debug("prepare $filename"); + + my $dirname = dirname($filename); + my $basename = basename($filename); + + my $outfilename = "$dirname/${tmpprefix}$basename"; + + $prepared_files->{$filename} = $outfilename; + + my $fh = IO::File->new("$filename", "r") or + die "unable to open file '$filename' - $!\n"; + + my $outfh = IO::File->new("$outfilename", "w") or + die "unable to open temporary file '$outfilename'\n"; + + push @$files_for_cleanup, $outfilename; + + while (defined (my $line = <$fh>)) { + chomp $line; + if ($line =~ m/^if(n?)def::(\S+)\[(.*)\]\s*$/) { + my ($not, $env, $text) = ($1, $2, $3); + die "unsuported ifdef usage - implement me" if $text; + + my $skip = !exists($attributes->{$env}) ? 1 : 0; + $skip = ($skip ? 0 : 1 ) if $not; + + push_environment($env, $skip); + next; + } elsif ($line =~ m/^endif::(\S+)\[(.*)\]\s*$/) { + my ($env, $text) = ($1, $2); + die "unsuported ifdef usage - implement me" if $text; + pop_environment($env); + next; + } + + next if $env_skip; + + if ($line =~ m/^include::(\S+)(\[.*\]\s*)$/) { + my ($fn, $rest) = ($1, $2); + debug("include $fn"); + my $new_fn = prepare_adoc_file($target_env, $fn, $attributes); + + print $outfh "include::${new_fn}$rest\n"; + next; + } + + if ($line =~ m/xref:\S+?\[[^\]]*$/) { + die "possible xref spanning multiple lines in '$filename':\n(line $.): $line\n"; + } + if ($line =~ m/<<((?!\>\>).)*$/) { + die "possible xref spanning multiple lines in '$filename':\n(line $.): $line\n"; + } + # fix xrefs + $line =~ s/xref:([^\s\[\]]+)\[([^\]]*)\]/replace_xref(${target_env},$1,$2)/ge; + + $line =~ s/<<([^\s,\[\]]+)(?:,(.*?))?>>/replace_xref(${target_env},$1,$2)/ge; + + print $outfh $line . "\n"; + } + + return $outfilename; +} + +sub compile_asciidoc { + my ($env) = @_; + + my $outfile; + + GetOptions ("outfile=s" => \$outfile, + "keep-artifacts" => \$keep_artifacts, + "verbose" => \$verbose) or + die("Error in command line arguments\n"); + + my $infile = shift(@ARGV) or + die "no input file specified\n"; + + scalar(@ARGV) == 0 or + die "too many arguments...\n"; + + my $outfilemap = $fileinfo->{outfile}->{$env}->{$infile} || + die "no output file mapping for '$infile' ($env)"; + + if ($man_target eq 'html') { + $outfilemap .= '.html'; + } elsif ($man_target eq 'wiki') { + $outfilemap .= '-plain.html'; + } + + if (defined($outfile)) { + die "wrong output file name '$outfile != $outfilemap' ($env)" + if $outfile ne $outfilemap; + } else { + $outfile = $outfilemap; + } + + defined($fileinfo->{titles}->{$env}) || + die "unknown environment '$env'"; + + my $title = $fileinfo->{titles}->{$env}->{$infile} or + die "unable to get title for '$infile'$env\n"; + + debug("compile $title"); + + my $leveloffset = 0; + + my $doctype = $fileinfo->{doctype}->{$env}->{$infile}; + + die "unable to get document type for '$infile'\n" + if !defined($doctype); + + $leveloffset = - $doctype; + + my $date = `date`; + chomp $date; + + my $attributes = { + $env => undef, + leveloffset => $leveloffset, + revnumber => $release, + revdate => $date, + }; + + my $mansection = $fileinfo->{mansection}->{$env}->{$infile}; + + if ($env eq 'wiki') { + } elsif ($env eq 'manvolnum') { + die "undefined man section" if !defined($mansection); + $attributes->{manvolnum} = $mansection; + } elsif ($env eq 'default') { + die "$infile: wrong doctype\n" if $doctype != 0; + $attributes->{toc} = undef; + } + + if (!defined($outfile)) { + $outfile = $infile; + $outfile =~ s/\.adoc$//; + if ($env eq 'manvolnum') { + if (($man_target eq 'html') || ($man_target eq 'wiki')) { + $outfile .= ".$mansection.html"; + } else { + $outfile .= ".$mansection"; + } + } else { + $outfile .= ".html"; + } + } + + if (($env eq 'manvolnum') && ($man_target eq 'man')) { + + # asciidoc /etc/asciidoc/docbook-xsl/manpage.xsl skip REFERENCES + # section like footnotes, so we cannot use a2x. + # We use xmlto instead. + + my $cmd = ['asciidoc', '-dmanpage', '-bdocbook', + '-f', "$adoc_source_dir/asciidoc/asciidoc-pmg.conf", + '-a', 'docinfo1']; + + foreach my $key (keys %$attributes) { + my $value = $attributes->{$key}; + if (defined($value)) { + push @$cmd, '-a', "$key=$value"; + } else { + push @$cmd, '-a', $key; + } + } + + push @$cmd, '--verbose' if $verbose; + + my $tmpxmlfile = "${outfile}.xml.tmp"; + + push @$cmd, '--out-file', $tmpxmlfile; + + push @$files_for_cleanup, $tmpxmlfile; + + my $new_infile = prepare_adoc_file($env, $infile, $attributes); + + push @$cmd, $new_infile; + + debug("run " . join(' ', @$cmd)); + + system(@$cmd) == 0 or + die "aciidoc error"; + + $cmd = ['xmlto', 'man', $tmpxmlfile]; + + push @$cmd, '-v' if $verbose; + + debug("run " . join(' ', @$cmd)); + + system(@$cmd) == 0 or + die "xmlto error"; + + } else { + + $attributes->{icons} = undef; + $attributes->{'data-uri'} = undef; + + my $cmd = ['asciidoc', + '-f', "$adoc_source_dir/asciidoc/asciidoc-pmg.conf", + ]; + + if (($env eq 'wiki') || + (($env eq 'manvolnum') && ($man_target eq 'wiki'))) { + + push @$cmd, '-b', "$adoc_source_dir/asciidoc/mediawiki"; + } else { + push @$cmd, '-b', "$adoc_source_dir/asciidoc/pmg-html"; + } + + foreach my $key (keys %$attributes) { + my $value = $attributes->{$key}; + if (defined($value)) { + push @$cmd, '-a', "$key=$value"; + } else { + push @$cmd, '-a', $key; + } + } + + push @$cmd, '--verbose' if $verbose; + + push @$cmd, '--out-file', $outfile; + + my $new_infile = prepare_adoc_file($env, $infile, $attributes); + + push @$cmd, $new_infile; + + debug("run " . join(' ', @$cmd)); + + system(@$cmd) == 0 or + die "aciidoc error"; + } +} + +sub get_links { + + my $data = {}; + + foreach my $blockid (sort keys %{$fileinfo->{blockid_target}->{default}}) { + my $link = $fileinfo->{blockid_target}->{default}->{$blockid}; + my $reftitle = $fileinfo->{reftitle}->{default}->{$blockid}; + my $reftext = $fileinfo->{reftext}->{default}->{$blockid}; + die "internal error" if $link !~ m/^link:/; + $link =~ s/^link://; + + my $file = $fileinfo->{blockid}->{default}->{$blockid}; + die "internal error - no filename" if ! defined($file); + my $title = $fileinfo->{titles}->{default}->{$file} || + die "internal error - no title"; + + $data->{$blockid}->{title} = $title; + $data->{$blockid}->{link} = $link; + my $subtitle = $reftitle || $reftext; + $data->{$blockid}->{subtitle} = $subtitle + if $subtitle && ($title ne $subtitle); + } + + return $data; +} + +sub scan_extjs_file { + my ($filename, $res_data) = @_; + + my $fh = IO::File->new($filename, "r") || + die "unable to open '$filename' - $!\n"; + + debug("scan-extjs $filename"); + + while(defined(my $line = <$fh>)) { + if ($line =~ m/\s+onlineHelp:\s*[\'\"](.*?)[\'\"]/) { + my $blockid = $1; + my $link = $fileinfo->{blockid_target}->{default}->{$blockid}; + die "undefined blockid '$blockid' ($filename, line $.)\n" + if !(defined($link) || defined($online_help_links->{$blockid})); + + $res_data->{$blockid} = 1; + } + } +} + +if ($clicmd eq 'compile-wiki') { + + eval { compile_asciidoc('wiki'); }; + my $err = $@; + + cleanup(); + + die $err if $err; + +} elsif ($clicmd eq 'compile-chapter') { + + eval { compile_asciidoc('default'); }; + my $err = $@; + + cleanup(); + + die $err if $err; + +} elsif ($clicmd eq 'compile-man-html') { + + $man_target = 'html'; + + eval { compile_asciidoc('manvolnum'); }; + my $err = $@; + + cleanup(); + + die $err if $err; + +} elsif ($clicmd eq 'compile-man-wiki') { + + $man_target = 'wiki'; + + eval { compile_asciidoc('manvolnum'); }; + my $err = $@; + + cleanup(); + + die $err if $err; + +} elsif ($clicmd eq 'compile-man') { + + eval { compile_asciidoc('manvolnum'); }; + my $err = $@; + + cleanup(); + + die $err if $err; + +} elsif ($clicmd eq 'print-links') { + + my $outfile; + + GetOptions("outfile=s" => \$outfile, + "verbose" => \$verbose) or + die("Error in command line arguments\n"); + + scalar(@ARGV) == 0 or + die "too many arguments...\n"; + + my $data = get_links(); + + my $res = to_json($data, { pretty => 1, canonical => 1 } ); + + if (defined($outfile)) { + my $outfh = IO::File->new("$outfile", "w") or + die "unable to open temporary file '$outfile'\n"; + + print $outfh $res; + + } else { + + print $res; + } + +} elsif ($clicmd eq 'scan-extjs') { + + GetOptions("verbose" => \$verbose) or + die("Error in command line arguments\n"); + + my $link_hash = {}; + my $scanned_files = {}; + while (my $filename = shift) { + die "got strange file name '$filename'\n" + if $filename !~ m/\.js$/; + next if $scanned_files->{$filename}; + + scan_extjs_file($filename, $link_hash); + $scanned_files->{$filename} = 1; + } + + my $data = get_links(); + + my $res_data = {}; + + foreach my $blockid (keys %$link_hash) { + $res_data->{$blockid} = $data->{$blockid} || $online_help_links->{$blockid} || + die "internal error - no data for '$blockid'"; + } + + my $data_str = to_json($res_data, { pretty => 1, canonical => 1 }); + chomp $data_str; + + print "var pmgOnlineHelpInfo = ${data_str};\n"; + +} elsif ($clicmd eq 'chapter-table') { + + print '[width="100%",options="header"]' . "\n"; + print "|====\n"; + print "|Title|Link\n"; + + my $filelist = $fileinfo->{outfile}->{default}; + foreach my $sourcefile (sort keys %$filelist) { + my $target = $filelist->{$sourcefile}; + next if $target eq 'pmg-admin-guide.html'; + my $title = $fileinfo->{titles}->{default}->{$sourcefile} || + die "not title for '$sourcefile'"; + print "|$title|link:$target\[\]\n"; + } + + print "|====\n"; + +} elsif ($clicmd =~ m/^man([158])page-table$/) { + + my $section = $1; + print '[width="100%",cols="5*d",options="header"]' . "\n"; + print "|====\n"; + print "|Name 3+|Title|Link\n"; + + my $filelist = $fileinfo->{outfile}->{manvolnum}; + foreach my $manpage (sort keys %$filelist) { + next if $section ne $fileinfo->{mansection}->{manvolnum}->{$manpage}; + my $mantitle = $fileinfo->{titles}->{manvolnum}->{$manpage} || + die "not manual title for '$manpage'"; + my $title = $fileinfo->{titles}->{default}->{$manpage} || + die "not title for '$manpage'"; + + # hack - remove command name prefix from titles + $title =~ s/^[a-z]+\s*-\s*//; + + my $target = $filelist->{$manpage}; + print "|$mantitle 3+|$title|link:$target.html\[$target\]\n"; + } + + print "|====\n"; + +} else { + + die "unknown command '$clicmd'\n"; + +} + + +exit 0; + +__END__ diff --git a/asciidoc/asciidoc-pmg.conf b/asciidoc/asciidoc-pmg.conf new file mode 100644 index 0000000..16f7ce1 --- /dev/null +++ b/asciidoc/asciidoc-pmg.conf @@ -0,0 +1,15 @@ + +[attributes] +proxmoxGmbh=Proxmox Server Solutions Gmbh +copyright=Proxmox Server Solutions Gmbh +pmg=Proxmox Mail Gateway +website=http://www.proxmox.com/ +forum-url=https://forum.proxmox.com/ +forum=https://forum.proxmox.com/[Proxmox VE Community Forum] +manmanual=Proxmox Mail Gateway Documentation +max-width=55em +ifndef::docinfo1[] +author=Proxmox Server Solutions Gmbh +email=support@proxmox.com +endif::docinfo1[] + diff --git a/asciidoc/dblatex-custom.sty b/asciidoc/dblatex-custom.sty new file mode 100644 index 0000000..ba4a508 --- /dev/null +++ b/asciidoc/dblatex-custom.sty @@ -0,0 +1,68 @@ +%% +%% This style is derived from the docbook one. +%% +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{asciidoc-proxmox}[2016/10/30 AsciiDoc DocBook Style] + +% this will set letterpaper, because docbook.sty honors page layout +% made by geometry package +%\usepackage[letterpaper,total={7.25in,9.25in}, top=1in]{geometry} +%\usepackage[a4paper]{geometry} + +\usepackage[a4paper, left=2cm, right=1cm, top=2.5cm, bottom=2cm ]{geometry} + +%% Just use the original package and pass the options. +\RequirePackageWithOptions{docbook} + +% Sidebar is a boxed minipage that can contain verbatim. +% Changed shadow box to double box. +\renewenvironment{sidebar}[1][0.95\textwidth]{ + \hspace{0mm}\newline% + \noindent\begin{Sbox}\begin{minipage}{#1}% + \setlength\parskip{\medskipamount}% +}{ + \end{minipage}\end{Sbox}\doublebox{\TheSbox}% +} + +% use parbox for description labels to allow line breaks +\renewcommand\descriptionlabel[1]{ + \parbox[t]{\linewidth}{\raggedright\bfseries #1\smallskip}} + +% For DocBook literallayout elements, see `./dblatex/dblatex-readme.txt`. +\usepackage{alltt} + +\definecolor{proxmoxred}{RGB}{229, 112, 0} +\definecolor{proxmoxgrey1}{RGB}{229, 229, 229} + +\def\drawtitlepage{ + \AddToShipoutPicture*{ + \put(\LenToUnit{0cm},\LenToUnit{2.5cm}){ + {\color{proxmoxgrey1}\rule{\paperwidth}{22cm}}} + \put(\LenToUnit{\dimexpr(\paperwidth-11cm)}, + \LenToUnit{\dimexpr(\paperheight-3.5cm)}){ + \includegraphics[width=10cm]{proxmox-logo}} + } +} + +% custom cover page +\def\DBKcover{ + \thispagestyle{empty} + \vspace*{4cm} + \sffamily + \begin{center} + {\Huge \scshape \color{proxmoxred} \DBKtitle \\[0.5cm]} + {\Large \scshape \DBKsubtitle \\[1cm]} + {\includegraphics[width=132mm]{proxmox-ci-header} \\} + \end{center} + \vfill + \begin{flushright} + {\Large \sffamily + \DBKdate \\ + Proxmox Server Solutions Gmbh \\ + \color{proxmoxred} www.proxmox.com \\ + } + \end{flushright} + \vspace*{1cm} + \drawtitlepage + \pagebreak[4] +} diff --git a/asciidoc/pmg-dblatex.xsl b/asciidoc/pmg-dblatex.xsl new file mode 100644 index 0000000..76edab8 --- /dev/null +++ b/asciidoc/pmg-dblatex.xsl @@ -0,0 +1,92 @@ + + + + + + colorlinks,linkcolor=blue,pdfstartview=FitH + 0 + + 1 + 0 + 0 + 2 + 2 + 0 + 0 + 0 + 12pt + + + + + 1 + + + + \begin{alltt} + \normalfont{} + + \end{alltt} + + + + + \pagebreak[4] + + + + + + \newline + + + + + \begin{center} + \line(1,0){444} + \end{center} + + + + \paragraph*{ + + + + } + + + + + + + + diff --git a/asciidoc/pmg-docbook.conf b/asciidoc/pmg-docbook.conf new file mode 100644 index 0000000..044ea84 --- /dev/null +++ b/asciidoc/pmg-docbook.conf @@ -0,0 +1,810 @@ +# +# docbook45.conf +# +# Asciidoc DocBook 4.5 configuration file. +# +# modified for Proxmox VE docs +# - add thumbnail attribute + +[miscellaneous] +outfilesuffix=.xml +# Printable page width and units. +# Used to calculate DocBook CALS tables absolute column and table widths. +pagewidth=425 +pageunits=* + +[attributes] +basebackend=docbook +basebackend-docbook= +basebackend-docbook45= +# For backward compatibility (docbook backend was renamed to docbook45 at 8.6.2) +backend-docbook= +# toc and numbered are set to maintain original default behavior. +toc= +numbered= + +[replacements2] +# Line break markup. Custom processing instruction in fo.xsl. +(?m)^(.*)\s\+$=\1 + +[replacements] +ifdef::asciidoc7compatible[] +# Superscripts. +\^(.+?)\^=\1 +# Subscripts. +~(.+?)~=\1 +endif::asciidoc7compatible[] + +[ruler-blockmacro] +# Uses custom processing instructions in fo.xsl and asciidoc-dblatex.xsl. + + +[pagebreak-blockmacro] +# Uses custom processing instructions in fo.xsl and asciidoc-dblatex.xsl. + + +[blockdef-pass] +latexmath-style=template="latexmathblock",subs=() + +[macros] +# math macros. +(?su)[\\]?(?Platexmath):(?P\S*?)\[(?P.*?)(?latexmath)::(?P\S*?)(\[(?P.*?)\])$=#[] + +[latexmath-inlinemacro] + + + + + +[latexmath-blockmacro] + + + + + +[latexmathblock] +{title} +{title%} + + +{title#} +{title%} + +[image-inlinemacro] + + + + + {alt={target}} + + +[image-blockmacro] +{title} +{title%}{pgwide-option?} +# DocBook XSL Stylesheets custom processing instructions. + + + + + + + {alt={target}} + +{title#} +{title%} + +[indexterm-inlinemacro] +# Index term. +# Generate separate index entries for primary, secondary and tertiary +# descriptions. +# Primary only. +{2%} +{2%} {1} +{2%} +# Primary and secondary. +{2#}{3%} +{2#}{3%} {1}{2} +{2#}{3%} +{2#}{3%} +{2#}{3%} {2} +{2#}{3%} +# Primary, secondary and tertiary. +{3#} + {1}{2}{3} +{3#} +{3#} + {2}{3} +{3#} +{3#} + {3} +{3#} + +[indexterm2-inlinemacro] +# Index term. +# Single entry index term that is visible in the primary text flow. +{1}{1} + +[footnote-inlinemacro] +# Footnote. +{0} + +[footnoteref-inlinemacro] +# Footnote reference. +{2#}{2} +{2%} + +[callout-inlinemacro] +# Callout. + + +# List tags. +[listtags-bulleted] +list={unbreakable-option? }{title?{title}}| +item=| +text=| + +[listtags-numbered] +list={unbreakable-option? }{title?{title}}{start?}| +item=| +text=| + +[listtags-labeled] +list={title?{title}}| +entry=| +label= +term=| +item=| +text=| + +[listtags-horizontal] +# Horizontal labeled list (implemented with two column table). +# Hardwired column widths to 30%,70% because the current crop of PDF +# generators do not auto calculate column widths. + list=<{title?table}{title!informaltable}{id? id="{id}"}{role? role="{role}"}{reftext? xreflabel="{reftext}"}{style? tabstyle="{style}"}{pgwide-option? pgwide="1"} frame="none" colsep="0" rowsep="0">{title?{title}}|<{title?/table}{title!/informaltable}> +entry=| +label=| +term=| +item=| +text=| + +[listtags-callout] +list={title?{title}}| +item=| +text=| + +[listtags-qanda] +list={title?{title}}| +entry=| +label=| +term=| +item=| +text=| + +[listtags-bibliography] +list={title?{title}}| +item=| +text=| + +[listtags-glossary] +list= +entry=| +label= +term=| +item=| +text=| + +[tags] +# Quoted text +emphasis={1?}|{1?} +strong={1?}|{1?} +monospaced={1?}|{1?} +singlequoted={lsquo}{1?}|{1?}{rsquo} +doublequoted={ldquo}{1?}|{1?}{rdquo} +unquoted={1?}|{1?} +subscript={1?}|{1?} +superscript={1?}|{1?} + +ifdef::deprecated-quotes[] +# Override with deprecated quote attributes. +emphasis={role?}|{role?} +strong={role?}|{role?} +monospaced={role?}|{role?} +singlequoted={role?}{amp}#8216;|{amp}#8217;{role?} +doublequoted={role?}{amp}#8220;|{amp}#8221;{role?} +unquoted={role?}|{role?} +subscript={role?}|{role?} +superscript={role?}|{role?} +endif::deprecated-quotes[] + +# Inline macros +[http-inlinemacro] +{0={name}:{target}} +[https-inlinemacro] +{0={name}:{target}} +[ftp-inlinemacro] +{0={name}:{target}} +[file-inlinemacro] +{0={name}:{target}} +[irc-inlinemacro] +{0={name}:{target}} +[mailto-inlinemacro] +{0={target}} +[callto-inlinemacro] +{0={target}} +[link-inlinemacro] +{0={target}} +# anchor:id[text] +[anchor-inlinemacro] + +# [[id,text]] +[anchor2-inlinemacro] + +# [[[id]]] +[anchor3-inlinemacro] +[{1}] +# xref:id[text] +[xref-inlinemacro] +{0} +{2%} +# <> +[xref2-inlinemacro] +{2} +{2%} +# // comment line +[comment-inlinemacro] +{showcomments#}{passtext} + +[comment-blockmacro] +{showcomments#}{passtext} + +[literal-inlinemacro] +# Inline literal. +{passtext} + +# Special word macros +[emphasizedwords] +{words} +[monospacedwords] +{words} +[strongwords] +{words} + +# Paragraph substitution. +[paragraph] +{title} +{thumbnail#} +{thumbnail#} +{thumbnail#} +{thumbnail#} +{thumbnail#} {alt={thumbnail}} +{thumbnail#} +{title%} +| +{title%} +{title#} +{empty} + +[admonitionparagraph] +<{name}{id? id="{id}"}{role? role="{role}"}{reftext? xreflabel="{reftext}"}>| + +# Delimited blocks. +[literalblock] +{title} +{title#} +{title%} +| + +{title#} + +[listingblock] +{title} +{title#} +{title%} +| + +{title#} + +[sidebarblock-open] + +{title} + +[sidebarblock-close] + + +[sidebarblock] +template::[sidebarblock-open] +| +template::[sidebarblock-close] + +[sidebarparagraph] +template::[sidebarblock-open] +| +template::[sidebarblock-close] + +[abstractblock-open] + +{title} + +[abstractblock-close] + + +[abstractblock] +template::[abstractblock-open] +| +template::[abstractblock-close] + +[abstractparagraph] +template::[abstractblock-open] +| +template::[abstractblock-close] + +[openblock] +| + +[partintroblock-open] + +{title} + +[partintroblock-close] + + +[partintroblock] +template::[partintroblock-open] +| +template::[partintroblock-close] + +[partintroparagraph] +template::[partintroblock-open] +| +template::[partintroblock-close] + +[quote-open] +# Common quote and verse element template. + +{title} +# Include attribution only if either {attribution} or {citetitle} is defined. +{attribution#} +{attribution%}{citetitle#} +{attribution} +{citetitle} +{attribution#} +{attribution%}{citetitle#} + +[quote-close] + + +[quoteblock] +template::[quote-open] +| +template::[quote-close] + +[verseblock] +template::[quote-open] +| +template::[quote-close] + +[quoteparagraph] +template::[quote-open] +| +template::[quote-close] + +[exampleblock-open] +<{title?example}{title!informalexample}{id? id="{id}"}{role? role="{role}"}{reftext? xreflabel="{reftext}"}> +# DocBook XSL Stylesheets custom processing instructions. + + +{title} + +[exampleblock-close] + + +[exampleblock] +template::[exampleblock-open] +| +template::[exampleblock-close] + +[exampleparagraph] +template::[exampleblock-open] +| +template::[exampleblock-close] + +[admonitionblock] +<{name}{id? id="{id}"}{role? role="{role}"}{reftext? xreflabel="{reftext}"}> +{title} +| + + +# Tables. +[tabletags-default] +colspec= +bodyrow=| +headdata=| +bodydata=| +paragraph=| + +[tabletags-emphasis] +paragraph=| + +[tabletags-header] +paragraph=| + +[tabletags-strong] +paragraph=| + +[tabletags-monospaced] +paragraph=| + +[tabletags-verse] +bodydata=| +paragraph= + +[tabletags-literal] +bodydata=| +paragraph= + +[tabletags-asciidoc] +paragraph= + +[table] +<{title?table}{title!informaltable}{id? id="{id}"}{role? role="{role}"}{reftext? xreflabel="{reftext}"}{pgwide-option? pgwide="1"} +frame="{frame=all}" +{grid%rowsep="1" colsep="1"} +rowsep="{grid@none|cols:0:1}" colsep="{grid@none|rows:0:1}" +> +{title} +# DocBook XSL Stylesheets custom processing instructions. + + + + + + +{colspecs} +{headrows#} +{headrows} +{headrows#} +{footrows#} +{footrows} +{footrows#} + +{bodyrows} + + + + +#-------------------------------------------------------------------- +# Deprecated old table definitions. +# + +[old_tabledef-default] +template=old_table +colspec= +bodyrow=| +bodydata=| + +[old_table] +<{title?table}{title!informaltable}{id? id="{id}"}{role? role="{role}"}{reftext? xreflabel="{reftext}"} pgwide="0" +frame="{frame=topbot}" +{grid%rowsep="0" colsep="0"} +rowsep="{grid@none|cols:0:1}" colsep="{grid@none|rows:0:1}" +> +{title} + +{colspecs} +{headrows#} +{headrows} +{headrows#} +{footrows#} +{footrows} +{footrows#} + +{bodyrows} + + + + +# End of deprecated old table definitions. +#-------------------------------------------------------------------- + +# Special sections. +[preface] + +{title=} +| + + +[index] + +{title} +| + + +[bibliography] + +{title} +| + + +[glossary] + +{title} +| + + +[appendix] + +{title} +| + + +[floatingtitle] +{title} + + +[header-declarations] + + +{toc#} +{numbered#} + +[+docinfo] +{notitle%} {doctitle} + {revdate} +# To ensure valid articleinfo/bookinfo when there is no AsciiDoc header. + {doctitle%}{revdate%}{docdate} + {authored#} + {firstname} + {middlename} + {lastname} + {email} + {authored#} + {authorinitials} +{revnumber?{revnumber}}{revdate}{authorinitials?{authorinitials}}{revremark?{revremark}} +{docinfo1,docinfo2#}{include:{docdir}/docinfo.xml} +{docinfo,docinfo2#}{include:{docdir}/{docname}-docinfo.xml} +# DEPRECATED: Use docinfo. +{revisionhistory#}{include:{docdir}/{docname}-revhistory.xml} +# DEPRECATED: Use orgname in preference to companyname. +{companyname} +# DEPRECATED: Use orgname in preference to corpname. +{corpname} +{orgname} + +#------------------------- +# article document type +#------------------------- +ifdef::doctype-article[] + +[header] +template::[header-declarations] + +
+ +template::[docinfo] + + +[footer] +
+ +[preamble] +# Untitled elements between header and first section title. +| + +[abstract] + +| + + +[sect1] + +{title} +| + + +[sect2] + +{title} +| + + +[sect3] + +{title} +| + + +[sect4] + +{title} +| + + +endif::doctype-article[] + +#------------------------- +# manpage document type +#------------------------- +ifdef::doctype-manpage[] + +[replacements] +# The roff format does not substitute special characters so just print them as +# text. +\(C\)=(C) +\(TM\)=(TM) + +[header] +template::[header-declarations] + + +template::[docinfo] + + +{mantitle} +{manvolnum} +# Default source and manual to suppress DocBook XSL warnings. +{mansource= } +{manmanual= } +{manversion={revnumber}} + + + {manname1} + {manname2} + {manname3} + {manname4} + {manname5} + {manname6} + {manname7} + {manname8} + {manname9} + {manpurpose} + + +[footer] + + +# Section macros +[synopsis] + +| + + +[sect1] + +{title} +| + + +[sect2] + +{title} +| + + +[sect3] + +{title} +| + + +endif::doctype-manpage[] + +#------------------------- +# book document type +#------------------------- +ifdef::doctype-book[] + +[header] +template::[header-declarations] + + + +template::[docinfo] + + +[footer] + + +[preamble] +# Preamble is not allowed in DocBook book so wrap it in a preface. + +{title=} +| + + +[dedication] + +{title} +| + + +[colophon] + +{title} +| + + +[sect0] + +{title} +| + + +[sect1] + +{title} +| + + +[sect2] + +{title} +| + + +[sect3] + +{title} +| + + +[sect4] + +{title} +| + + +endif::doctype-book[] + +ifdef::sgml[] +# +# Optional DocBook SGML. +# +# Most of the differences between DocBook XML and DocBook SGML boils +# down to the empty element syntax: SGML does not like the XML empty +# element <.../> syntax, use <...> instead. +# +[miscellaneous] +outfilesuffix=.sgml + +[header-declarations] + + +[tabledef-default] +colspec= + +[image-inlinemacro] + + + + + {alt={target}} + + +[image-blockmacro] +
{title} +{title%} + + + + + {alt={target}} + +{title#}
+{title%} + +# Inline macros +[xref-inlinemacro] +{0} +{2%} +[xref2-inlinemacro] +# <> +{2} +{2%} +[anchor-inlinemacro] + +[anchor2-inlinemacro] +# [[id,text]] + + +endif::sgml[] diff --git a/asciidoc/pmg-html.conf b/asciidoc/pmg-html.conf new file mode 100644 index 0000000..74e0d13 --- /dev/null +++ b/asciidoc/pmg-html.conf @@ -0,0 +1,719 @@ +# +# html5.conf +# +# Asciidoc configuration file. +# html5 backend. +# +# modified for Proxmox VE docs +# - add thumbnail attribute +# - s!./stylesheets!/etc/asciidoc/stylesheets!g +# - s!./javascripts!/etc/asciidoc/javascripts!g + +[miscellaneous] +outfilesuffix=.html + +[attributes] +basebackend=html +basebackend-html= +basebackend-html5= + +[replacements2] +# Line break. +(?m)^(.*)\s\+$=\1
+ +[replacements] +ifdef::asciidoc7compatible[] +# Superscripts. +\^(.+?)\^=\1 +# Subscripts. +~(.+?)~=\1 +endif::asciidoc7compatible[] + +[ruler-blockmacro] +
+ +[pagebreak-blockmacro] +
+ +[blockdef-pass] +asciimath-style=template="asciimathblock",subs=() +latexmath-style=template="latexmathblock",subs=() + +[macros] +(?u)^(?Paudio|video)::(?P\S*?)(\[(?P.*?)\])$=# +# math macros. +# Special characters are escaped in HTML math markup. +(?su)[\\]?(?Pasciimath|latexmath):(?P\S*?)\[(?P.*?)(?asciimath|latexmath)::(?P\S*?)(\[(?P.*?)\])$=#[specialcharacters] + +[asciimath-inlinemacro] +`{passtext}` + +[asciimath-blockmacro] +
+
+
{title}
+`{passtext}` +
+ +[asciimathblock] +
+
+
{title}
+`|` +
+ +[latexmath-inlinemacro] +{passtext} + +[latexmath-blockmacro] +
+
+
{title}
+{passtext} +
+ +[latexmathblock] +
+
+
{title}
+| +
+ +[image-inlinemacro] + + +{data-uri%}{alt={target}} +{data-uri#}{alt={target}} +{link#} + + +[image-blockmacro] +
+ +
{caption={figure-caption} {counter:figure-number}. }{title}
+
+ +[audio-blockmacro] +
+
{caption=}{title}
+
+ +
+ +[video-blockmacro] +
+
{caption=}{title}
+
+ +
+ +[unfloat-blockmacro] +
+ +[toc-blockmacro] +template::[toc] + +[indexterm-inlinemacro] +# Index term. +{empty} + +[indexterm2-inlinemacro] +# Index term. +# Single entry index term that is visible in the primary text flow. +{1} + +[footnote-inlinemacro] +# footnote:[]. +
[{0}]
+ +[footnoteref-inlinemacro] +# footnoteref:[], create reference to footnote. +{2%}
[{1}]
+# footnoteref:[,], create footnote with ID. +{2#}
[{2}]
+ +[callout-inlinemacro] +ifndef::icons[] +<{index}> +endif::icons[] +ifdef::icons[] +ifndef::data-uri[] +{index} +endif::data-uri[] +ifdef::data-uri[] +{index} +endif::data-uri[] +endif::icons[] + +# Comment line macros. +[comment-inlinemacro] +{showcomments#}
{passtext}
+ +[comment-blockmacro] +{showcomments#}

{passtext}

+ +[literal-inlinemacro] +# Inline literal. +{passtext} + +# List tags. +[listtags-bulleted] +list=
{title?
{title}
}
    |
+item=
  • |
  • +text=

    |

    + +[listtags-numbered] +# The start attribute is not valid XHTML 1.1 but all browsers support it. +list=
    {title?
    {title}
    }
      |
    +item=
  • |
  • +text=

    |

    + +[listtags-labeled] +list=
    {title?
    {title}
    }
    |
    +entry= +label= +term=
    |
    +item=
    |
    +text=

    |

    + +[listtags-horizontal] +list=
    {title?
    {title}
    }{labelwidth?}{itemwidth?}|
    +label=| +term=|
    +entry=| +item=| +text=

    |

    + +[listtags-qanda] +list=
    {title?
    {title}
    }
      |
    +entry=
  • |
  • +label= +term=

    |

    +item= +text=

    |

    + +[listtags-callout] +ifndef::icons[] +list=
    {title?
    {title}
    }
      |
    +item=
  • |
  • +text=

    |

    +endif::icons[] +ifdef::icons[] +list=
    {title?
    {title}
    }|
    +ifndef::data-uri[] +item={listindex}| +endif::data-uri[] +ifdef::data-uri[] +item={listindex}| +endif::data-uri[] +text=| +endif::icons[] + +[listtags-glossary] +list=
    {title?
    {title}
    }
    |
    +label= +entry= +term=
    |
    +item=
    |
    +text=

    |

    + +[listtags-bibliography] +list=
    {title?
    {title}
    }
      |
    +item=
  • |
  • +text=

    |

    + +[tags] +# Quoted text. +emphasis={1?}|{1?} +strong={1?}|{1?} +monospaced=| +singlequoted={lsquo}{1?}|{1?}{rsquo} +doublequoted={ldquo}{1?}|{1?}{rdquo} +unquoted={1?}|{1?} +superscript={1?}|{1?} +subscript={1?}|{1?} + +ifdef::deprecated-quotes[] +# Override with deprecated quote attributes. +emphasis={role?}|{role?} +strong={role?}|{role?} +monospaced=| +singlequoted={role?}{1,2,3?}{amp}#8216;|{amp}#8217;{1,2,3?}{role?} +doublequoted={role?}{1,2,3?}{amp}#8220;|{amp}#8221;{1,2,3?}{role?} +unquoted={role?}{1,2,3?}|{1,2,3?}{role?} +superscript={role?}|{role?} +subscript={role?}|{role?} +endif::deprecated-quotes[] + +# Inline macros +[http-inlinemacro] +{0={name}:{target}} +[https-inlinemacro] +{0={name}:{target}} +[ftp-inlinemacro] +{0={name}:{target}} +[file-inlinemacro] +{0={name}:{target}} +[irc-inlinemacro] +{0={name}:{target}} +[mailto-inlinemacro] +{0={target}} +[link-inlinemacro] +{0={target}} +[callto-inlinemacro] +{0={target}} +# anchor:id[text] +[anchor-inlinemacro] + +# [[id,text]] +[anchor2-inlinemacro] + +# [[[id]]] +[anchor3-inlinemacro] +[{1}] +# xref:id[text] +[xref-inlinemacro] +{0=[{target}]} +# <> +[xref2-inlinemacro] +{2=[{1}]} + +# Special word substitution. +[emphasizedwords] +{words} +[monospacedwords] +{words} +[strongwords] +{words} + +# Paragraph substitution. +[paragraph] +
    +{thumbnail#} +{thumbnail#}{alt={thumbnail}} +{title?
    {title}
    }

    +| +

    + +[admonitionparagraph] +template::[admonitionblock] + +# Delimited blocks. +[listingblock] +
    +
    {caption=}{title}
    +
    +
    +|
    +
    +
    + +[literalblock] +
    +
    {title}
    +
    +
    +|
    +
    +
    + +[sidebarblock] +
    +
    +
    {title}
    +| +
    + +[openblock] +
    +
    {title}
    +
    +| +
    + +[partintroblock] +template::[openblock] + +[abstractblock] +template::[quoteblock] + +[quoteblock] +
    +
    {title}
    +
    +| +
    +
    +{citetitle}{attribution?
    } +— {attribution} +
    + +[verseblock] +
    +
    {title}
    +
    +|
    +
    +
    +{citetitle}{attribution?
    } +— {attribution} +
    + +[exampleblock] +
    +
    {caption={example-caption} {counter:example-number}. }{title}
    +
    +| +
    + +[admonitionblock] +
    + + + +
    +{data-uri%}{icons#}{caption} +{data-uri#}{icons#}{caption} +{icons%}
    {caption}
    +
    +
    {title}
    +| +
    +
    + +# Tables. +[tabletags-default] +colspec= +bodyrow=| +headdata=| +bodydata=| +paragraph=

    |

    + +[tabletags-header] +paragraph=

    |

    + +[tabletags-emphasis] +paragraph=

    |

    + +[tabletags-strong] +paragraph=

    |

    + +[tabletags-monospaced] +paragraph=

    |

    + +[tabletags-verse] +bodydata=
    |
    +paragraph= + +[tabletags-literal] +bodydata=
    |
    +paragraph= + +[tabletags-asciidoc] +bodydata=
    |
    +paragraph= + +[table] + + +{colspecs} +{headrows#} +{headrows} +{headrows#} +{footrows#} +{footrows} +{footrows#} + +{bodyrows} + +
    {caption={table-caption} {counter:table-number}. }{title}
    + +#-------------------------------------------------------------------- +# Deprecated old table definitions. +# + +[miscellaneous] +# Screen width in pixels. +pagewidth=800 +pageunits=px + +[old_tabledef-default] +template=old_table +colspec= +bodyrow=| +headdata=| +footdata=| +bodydata=| + +[old_table] + + +{colspecs} +{headrows#} +{headrows} +{headrows#} +{footrows#} +{footrows} +{footrows#} + +{bodyrows} + +
    {caption={table-caption}}{title}
    + +# End of deprecated old table definitions. +#-------------------------------------------------------------------- + +[floatingtitle] +{title} + +[preamble] +# Untitled elements between header and first section title. +
    +
    +| +
    +
    + +# Document sections. +[sect0] +{title} +| + +[sect1] +
    +{numbered?{sectnum} }{title} +
    +| +
    +
    + +[sect2] +
    +{numbered?{sectnum} }{title} +| +
    + +[sect3] +
    +{numbered?{sectnum} }{title} +| +
    + +[sect4] +
    +{title} +| +
    + +[appendix] +
    +{numbered?{sectnum} }{appendix-caption} {counter:appendix-number:A}: {title} +
    +| +
    +
    + +[toc] +
    +
    {toc-title}
    + +
    + +[header] + + + + + + + +{title} +{title%}{doctitle=} +ifdef::linkcss[] + +ifeval::["{source-highlighter}"=="pygments"] + +endif::[] + +# DEPRECATED: 'pygments' attribute. +ifdef::pygments[] + +ifdef::toc2[] + +endif::linkcss[] +ifndef::linkcss[] + +endif::linkcss[] +ifndef::disable-javascript[] +ifdef::linkcss[] + + + +endif::linkcss[] +ifndef::linkcss[] + +endif::linkcss[] +endif::disable-javascript[] +ifdef::asciimath[] +ifdef::linkcss[] + +endif::linkcss[] +ifndef::linkcss[] + +endif::linkcss[] +endif::asciimath[] +ifdef::latexmath[] +ifdef::linkcss[] + +endif::linkcss[] +ifndef::linkcss[] + +endif::linkcss[] +endif::latexmath[] +{docinfo1,docinfo2#}{include:{docdir}/docinfo.html} +{docinfo,docinfo2#}{include:{docdir}/{docname}-docinfo.html} +template::[docinfo] + + +# Article, book header. +ifndef::doctype-manpage[] + +endif::doctype-manpage[] +# Man page header. +ifdef::doctype-manpage[] + +endif::doctype-manpage[] +
    + +[footer] +
    +{disable-javascript%

    } + + + + +[footer-date] +# Default footer date is document modification time +ifeval::["{footer-style=default}"!="revdate"] + {docdate} {doctime} +endif::[] +# If set to "revdate", it'll be set to the revision date +ifeval::["{footer-style=default}"=="revdate"] + {revdate} +endif::[] + +ifdef::doctype-manpage[] +[synopsis] +template::[sect1] +endif::doctype-manpage[] + diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..614896f --- /dev/null +++ b/debian/changelog @@ -0,0 +1,7 @@ +pmg-docs (5.0-1) unstable; urgency=medium + + * first version using asciidoc + + -- Proxmox Support Team Wed, 22 Feb 2017 06:26:49 +0100 + + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 diff --git a/debian/control.in b/debian/control.in new file mode 100644 index 0000000..9b64bda --- /dev/null +++ b/debian/control.in @@ -0,0 +1,6 @@ +Source: pmg-docs +Section: perl +Priority: extra +Maintainer: Proxmox Support Team +Build-Depends: debhelper (>= 7.0.50~), lintian +Standards-Version: 3.8.4 diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..19cd0c8 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,34 @@ +Coryright for files in debian/* and all perl files (*.pl): + + Copyright (C) 2017 Proxmox Server Solutions GmbH + + This software is written by Proxmox Server Solutions GmbH + + + This program is free software: you can redistribute it and/or + modify it under the terms of the GNU Affero General Public License + as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public + License along with this program. If not, see + . + + +All documentation files (*.adoc) are release under: + + Copyright (C) 2017 Proxmox Server Solutions GmbH + + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + + You can find a copy of the license in /usr/share/common-licenses/GFDL. \ No newline at end of file diff --git a/debian/install b/debian/install new file mode 100644 index 0000000..1412e51 --- /dev/null +++ b/debian/install @@ -0,0 +1 @@ +/usr/share/ diff --git a/debian/pmg-doc-generator.control b/debian/pmg-doc-generator.control new file mode 100644 index 0000000..7bd2f20 --- /dev/null +++ b/debian/pmg-doc-generator.control @@ -0,0 +1,8 @@ +Package: pmg-doc-generator +Section: perl +Architecture: any +Depends: ${perl:Depends}, libpve-common-perl, asciidoc, xmlto +Description: Proxmox Mail Gateway Documentation helpers + Tool to auto-generate various Proxmox Mail gateway Documentation files and + manual pages. This package is required to build most other Proxmox Mail + Gateway packages. diff --git a/debian/pmg-doc-generator.install b/debian/pmg-doc-generator.install new file mode 100644 index 0000000..367d8f0 --- /dev/null +++ b/debian/pmg-doc-generator.install @@ -0,0 +1,2 @@ +/usr/bin/asciidoc-pmg +/usr/share/pmg-doc-generator diff --git a/debian/pmg-docs.control b/debian/pmg-docs.control new file mode 100644 index 0000000..3608e49 --- /dev/null +++ b/debian/pmg-docs.control @@ -0,0 +1,5 @@ +Package: pmg-docs +Section: doc +Architecture: all +Description: Proxmox Mail Gateway Documentation + This package contains the Proxmox Mail Gateway documentation files. diff --git a/debian/pmg-docs.install b/debian/pmg-docs.install new file mode 100644 index 0000000..6d40bb4 --- /dev/null +++ b/debian/pmg-docs.install @@ -0,0 +1 @@ +/usr/share/pmg-docs diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..736b14e --- /dev/null +++ b/debian/rules @@ -0,0 +1,7 @@ +#!/usr/bin/make -f + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +%: + dh $@ diff --git a/docinfo.xml b/docinfo.xml new file mode 100644 index 0000000..5a71583 --- /dev/null +++ b/docinfo.xml @@ -0,0 +1,8 @@ + + + + Proxmox Server Solutions Gmbh + www.proxmox.com + + + diff --git a/extractapi.pl b/extractapi.pl new file mode 100755 index 0000000..283d8a0 --- /dev/null +++ b/extractapi.pl @@ -0,0 +1,47 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use JSON; + +use PVE::RESTHandler; + +use PMG::API2; + +sub cleanup_tree { + my ($h) = @_; + + my $class = ref($h); + return $h if !$class; + + if ($class eq 'ARRAY') { + my $res = []; + foreach my $el (@$h) { + push @$res, cleanup_tree($el); + } + return $res; + } elsif ($class eq 'HASH') { + my $res = {}; + foreach my $k (keys %$h) { + if (my $class = ref($h->{$k})) { + if ($class eq 'CODE') { + next if $k eq 'completion'; + } + $res->{$k} = cleanup_tree($h->{$k}); + } else { + $res->{$k} = $h->{$k}; + } + } + return $res; + } elsif ($class eq 'Regexp') { + return "$h"; # return string representation + } else { + die "unknown class '$class'\n"; + } +} + +my $tree = cleanup_tree(PVE::RESTHandler::api_dump('PMG::API2')); + +print "var pmgapi = " . to_json($tree, {pretty => 1, canonical => 1}) . ";\n\n"; + +exit(0); diff --git a/images/proxmox-ci-header.svg b/images/proxmox-ci-header.svg new file mode 100755 index 0000000..4efa8a1 --- /dev/null +++ b/images/proxmox-ci-header.svg @@ -0,0 +1,110 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/images/proxmox-logo.svg b/images/proxmox-logo.svg new file mode 100644 index 0000000..bc5d22a --- /dev/null +++ b/images/proxmox-logo.svg @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/screenshot/gui-login-window.png b/images/screenshot/gui-login-window.png new file mode 100644 index 0000000..57e1d0f Binary files /dev/null and b/images/screenshot/gui-login-window.png differ diff --git a/index.adoc b/index.adoc new file mode 100644 index 0000000..700538f --- /dev/null +++ b/index.adoc @@ -0,0 +1,51 @@ +image:./images/proxmox-logo.svg[] pass:[
    ] {pmg} Documentation Index +======================================================================== +:data-uri: +:icons: +:title: {pmg} Documentation Index + + +{pmg} Administration Guide +-------------------------- + +[width="100%",options="header"] +|=========================================================== +|Format |Link +|Printable version |link:pmg-admin-guide.pdf[] +|Online HTML version |link:pmg-admin-guide.html[] +|E-Book version |link:pmg-admin-guide.epub[] +|=========================================================== + + +Individual Chapters +------------------- + +include::chapter-index-table.adoc[] + + +{pmg} Manual Pages +------------------ + +Command Line Interface +~~~~~~~~~~~~~~~~~~~~~~ + +include::man1-index-table.adoc[] + + +Service Daemons +~~~~~~~~~~~~~~~ + +include::man8-index-table.adoc[] + + +Configuration Options +~~~~~~~~~~~~~~~~~~~~~ + +include::man5-index-table.adoc[] + + +API Viewer +~~~~~~~~~~ + +The link:api-viewer/index.html[API viewer] is a tiny web application +which allows you to inspect all available API calls. diff --git a/pmg-admin-guide-docinfo.xml.in b/pmg-admin-guide-docinfo.xml.in new file mode 100644 index 0000000..31e90c9 --- /dev/null +++ b/pmg-admin-guide-docinfo.xml.in @@ -0,0 +1,19 @@ +Release @RELEASE@ + + + 2017 + Proxmox Server Solutions Gmbh + + + + + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + + + A copy of the license is included in the section entitled "GNU + Free Documentation License". + + diff --git a/pmg-admin-guide.adoc b/pmg-admin-guide.adoc new file mode 100644 index 0000000..44b3d2f --- /dev/null +++ b/pmg-admin-guide.adoc @@ -0,0 +1,98 @@ +ifdef::pmglogo[] +image:./images/proxmox-logo.svg[] pass:[
    ] Proxmox Mail Gateway Administration Guide +======================================================================================= +endif::pmglogo[] +ifndef::pmglogo[] +Proxmox Mail Gateway Administration Guide +========================================= +endif::pmglogo[] +:doctype: book +:title: Proxmox Mail Gateway Administration Guide +:toc: +:numbered: +:data-uri: +:icons: +ifndef::wiki[] +ifndef::manvolnum[] +:pmg-toplevel: + +// Push titles down one level. +:leveloffset: 1 + +include::pmg-intro.adoc[] + + +// Return to normal title levels. +:leveloffset: 0 + +Important Service Daemons +------------------------- + +TODO + +:leveloffset: 2 +//include::pvedaemon.adoc[] + +:leveloffset: 0 + + +Useful Command Line Tools +------------------------- + +TODO + +:leveloffset: 2 +//include::pveceph.adoc[] + +:leveloffset: 0 + +[appendix] +Command Line Interface +---------------------- + +*pmgsh* - {pmg} API Shell +~~~~~~~~~~~~~~~~~~~~~~~~~ + +TODO + +:leveloffset: 1 +//include::pvesm.1-synopsis.adoc[] + +:leveloffset: 0 + + +[appendix] +Service Daemons +--------------- + +*pmgpolicy* - Policy Daemon +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +TODO + +:leveloffset: 1 +//include::pve-firewall.8-synopsis.adoc[] + +:leveloffset: 0 + + +[appendix] +Configuration Files +------------------- + +TODO + +:leveloffset: 2 +//include::datacenter.cfg.adoc[] + +:leveloffset: 0 + +:leveloffset: 1 + +[appendix] +include::GFDL.adoc[] + +:leveloffset: 0 + +endif::manvolnum[] +endif::wiki[] diff --git a/pmg-copyright.adoc b/pmg-copyright.adoc new file mode 100644 index 0000000..6f13599 --- /dev/null +++ b/pmg-copyright.adoc @@ -0,0 +1,18 @@ +Copyright and Disclaimer +------------------------ + +Copyright (C) 2007-2017 Proxmox Server Solutions GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public +License along with this program. If not, see +http://www.gnu.org/licenses/ diff --git a/pmg-doc-generator.mk.in b/pmg-doc-generator.mk.in new file mode 100644 index 0000000..0cd8465 --- /dev/null +++ b/pmg-doc-generator.mk.in @@ -0,0 +1,77 @@ +# also update debian/changelog +DOCRELEASE=5.0 + +DGDIR?=/usr/share/pmg-doc-generator + +ASCIIDOC_PMG?=/usr/bin/asciidoc-pmg + +PERL_DOC_ENV=PMG_GENERATING_DOCS=1 + +PMG_COMMON_DOC_SOURCES= \ + ${ASCIIDOC_PMG} \ + pmg-copyright.adoc \ + docinfo.xml + +all: + +docinfo.xml: + cp ${DGDIR}/$@ $@.tmp + mv $@.tmp $@ + +%-opts.adoc: ${DGDIR}/gen-%-opts.pl + $(PERL_DOC_ENV) perl -I. ${DGDIR}/gen-$*-opts.pl >$@.tmp + mv $@.tmp $@ + +%.adoc: ${DGDIR}/gen-%-adoc.pl + $(PERL_DOC_ENV) perl -I. ${DGDIR}/gen-$*-adoc.pl >$@.tmp + mv $@.tmp $@ + +%.1-synopsis.adoc: + $(PERL_DOC_ENV) perl -I. -e "use PMG::CLI::$(subst -,_,$*);print PMG::CLI::$(subst -,_,$*)->generate_asciidoc_synopsis();" > $@.tmp + mv $@.tmp $@ + +%.8-synopsis.adoc: + $(PERL_DOC_ENV) perl -I. -e "use PMG::Service::$(subst -,_,$*);print PMG::Service::$(subst -,_,$*)->generate_asciidoc_synopsis();" > $@.tmp + mv $@.tmp $@ + +ifneq (${DGDIR},.) +%.adoc: ${DGDIR}/%.adoc + cp $< $@.tmp + mv $@.tmp $@ +endif + + +%-plain.html: %.adoc ${PMG_COMMON_DOC_SOURCES} + ${ASCIIDOC_PMG} compile-wiki -o $@ $*.adoc + +chapter-%.html: %.adoc ${PMG_COMMON_DOC_SOURCES} + ${ASCIIDOC_PMG} compile-chapter -o $@ $*.adoc + +%.1: %.adoc %.1-synopsis.adoc ${PMG_COMMON_DOC_SOURCES} + ${ASCIIDOC_PMG} compile-man -o $@ $*.adoc + test -n "$${NOVIEW}" || man -l $@ + +%.1.html: %.adoc %.1-synopsis.adoc ${PMG_COMMON_DOC_SOURCES} + ${ASCIIDOC_PMG} compile-man-html -o $@ $*.adoc + +%.8: %.adoc %.8-synopsis.adoc ${PMG_COMMON_DOC_SOURCES} + ${ASCIIDOC_PMG} compile-man -o $@ $*.adoc + test -n "$${NOVIEW}" || man -l $@ + +%.8.html: %.adoc %.8-synopsis.adoc ${PMG_COMMON_DOC_SOURCES} + ${ASCIIDOC_PMG} compile-man-html -o $@ $*.adoc + +%.5: %.adoc %.5-opts.adoc ${PMG_COMMON_DOC_SOURCES} + ${ASCIIDOC_PMG} compile-man -o $@ $*.adoc + test -n "$${NOVIEW}" || man -l $@ + +%.5.html: %.adoc %.5-opts.adoc ${PMG_COMMON_DOC_SOURCES} + ${ASCIIDOC_PMG} compile-man-html -o $@ $*.adoc + +%.5-plain.html: %.adoc %.5-opts.adoc ${PMG_COMMON_DOC_SOURCES} + ${ASCIIDOC_PMG} compile-man-wiki -o $@ $*.adoc + + +.PHONY: cleanup-docgen +cleanup-docgen: + rm -f *.xml.tmp *.1 *.5 *.8 *.adoc docinfo.xml diff --git a/pmg-intro.adoc b/pmg-intro.adoc new file mode 100644 index 0000000..a498361 --- /dev/null +++ b/pmg-intro.adoc @@ -0,0 +1,4 @@ +Introduction +============ + +TODO diff --git a/png-verify.pl b/png-verify.pl new file mode 100755 index 0000000..8eb6611 --- /dev/null +++ b/png-verify.pl @@ -0,0 +1,16 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +my $infile = shift || + die "no input file specified\n"; + +my $dpcm = 58; # expected + +my $tmp = `identify -units PixelsPerCentimeter -format '%x x %y' $infile`; + +die "got unexpected density '$tmp' (fix with png-cleanup.pl)\n" + if $tmp ne "$dpcm x $dpcm"; + +exit 0; diff --git a/scan-adoc-refs b/scan-adoc-refs new file mode 100755 index 0000000..e7767dc --- /dev/null +++ b/scan-adoc-refs @@ -0,0 +1,492 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Getopt::Long; +use IO::File; +use JSON; + +use Data::Dumper; + +my $generate_depends; + +GetOptions("depends=s" => \$generate_depends) or + die("Error in command line arguments\n"); + + +my $environments = { + default => 1, + wiki => 1, + manvolnum => 1, + pmglogo => 0, # ignore +}; + +my $fileinfo = {}; + +my $start_env = []; +foreach my $e (keys %$environments) { + push @$start_env, $e if $environments->{$e}; +} + +my $env_stack = [$start_env]; +my $env_name_stack = []; + +sub reset_environment_stack { + $env_stack = [$start_env]; + $env_name_stack = []; +} + +sub push_environment { + my ($env, $not) = @_; + + die "undefined environment '$env'\n" if !defined($environments->{$env}); + + # FIXME: this seems wrong (nested env?)? + return if !$environments->{$env}; # do not track + + if ($not) { + my $new_env = []; + foreach my $e (@{$env_stack->[-1]}) { + if ($e ne $env) { + push @$new_env, $e; + } + } + die "empty environment" if !scalar($new_env); + push @$env_stack, $new_env; + } else { + push @$env_stack, [$env]; + } + + push @$env_name_stack, $env; +} + +sub pop_environment { + my ($env) = @_; + + die "undefined environment '$env'\n" if !defined($environments->{$env}); + + return if !$environments->{$env}; # do not track + + pop @$env_stack; + my $res = pop @$env_name_stack; + + die "environment missmatch ($res != $env)\n" if $res ne $env; +} + +sub register_include { + my ($filename, $include_filename, $env_list) = @_; + + foreach my $e (@$env_list) { + $fileinfo->{include}->{$e}->{$filename}->{$include_filename} = 1; + } +} + +sub register_blockid { + my ($filename, $blockid, $reftext, $env_list) = @_; + + foreach my $e (@$env_list) { + my $fn = $fileinfo->{blockid}->{$e}->{$blockid}; + die "blockid '$blockid' already defined in $fn" + if defined($fn); + $fileinfo->{blockid}->{$e}->{$blockid} = $filename; + $fileinfo->{reftext}->{$e}->{$blockid} = $reftext + if defined($reftext); + } +} + +sub register_title { + my ($filename, $env, $doctype, $title, $blockid) = @_; + + # fixme: what about other macros? + $title =~ s/\{pmg\}/Proxmox Mail Gateway/g; + $title =~ s!http://\S+\[(.*?)\]!$1!g; + + # register document title (onyl once) + if (!defined($fileinfo->{titles}->{$env}->{$filename})) { + + $fileinfo->{titles}->{$env}->{$filename} = $title; + + if (defined($doctype)) { + $fileinfo->{doctype}->{$env}->{$filename} = $doctype; + } else { + die "unable to change title (no doctype)" + if !defined($fileinfo->{doctype}->{$env}->{$filename}); + } + } elsif (!defined($doctype)) { + # change title via :title: attribute + $fileinfo->{titles}->{$env}->{$filename} = $title; + } + + if (defined($doctype) && ($env eq 'manvolnum') && ($doctype == 0)) { + if ($title =~ m/.*\(([1-8])\)\s*$/) { + $fileinfo->{mansection}->{$env}->{$filename} = $1; + } + } + + if ($blockid) { + die "internal error" + if !defined($fileinfo->{blockid}->{$env}->{$blockid}); + $fileinfo->{reftitle}->{$env}->{$blockid} = $title; + } +} + +sub scan_adoc_file { + my ($filename) = @_; + + reset_environment_stack(); + + # print "SCAN $filename\n"; + + my $fh = IO::File->new("$filename", "r") or + die "unable to open file '$filename' - $!\n"; + + my $env_last_line = {}; + my $env_last_blockid = {}; + + while (defined (my $line = <$fh>)) { + if ($line =~ m/^if(n?)def::(\S+)\[(.*)\]\s*$/) { + my ($not, $env, $text) = ($1, $2, $3); + die "unsuported ifdef usage - implement me" if $text; + push_environment($env, $not); + next; + } elsif ($line =~ m/^endif::(\S+)\[(.*)\]\s*$/) { + my ($env, $text) = ($1, $2); + die "unsuported ifdef usage - implement me" if $text; + pop_environment($env); + next; + } elsif ($line =~ m/^include::(\S+)\[.*\]\s*$/) { + register_include($filename, $1, $env_stack->[-1]); + next; + } + + # try to detect titles + foreach my $e (@{$env_stack->[-1]}) { + if ($line =~ m/^===+$/) { + register_title($filename, $e, 0, $env_last_line->{$e}, + $env_last_blockid->{$e}); + } elsif ($line =~ m/^---+$/) { + register_title($filename, $e, 1, $env_last_line->{$e}, + $env_last_blockid->{$e}); + } elsif ($line =~ m/^~~~+$/) { + register_title($filename, $e, 2, $env_last_line->{$e}, + $env_last_blockid->{$e}); + } elsif ($line =~ m/^\^\^\^+$/) { + register_title($filename, $e, 3, $env_last_line->{$e}, + $env_last_blockid->{$e}); + } elsif ($line =~ m/^= +(\S.*?)( +=)?$/) { + register_title($filename, $e, 0, $1, $env_last_blockid->{$e}); + } elsif ($line =~ m/^== +(\S.*?)( +==)?$/) { + register_title($filename, $e, 1, $1, $env_last_blockid->{$e}); + } elsif ($line =~ m/^=== +(\S.*?)( +===)?$/) { + register_title($filename, $e, 2, $1, $env_last_blockid->{$e}); + } elsif ($line =~ m/^==== +(\S.*?)( +====)?$/) { + register_title($filename, $e, 3, $1, $env_last_blockid->{$e}); + } + + $env_last_line->{$e} = $line; + chomp $env_last_line->{$e}; + } + + if ($line =~ m/^:(\S+?):\s*(.*\S)?\s*$/) { + my ($key, $value) = ($1, $2); + if ($key eq 'pmg-toplevel') { + + foreach my $e (@{$env_stack->[-1]}) { + my $title = $fileinfo->{titles}->{$e}->{$filename}; + die "not title for toplevel file '$filename' (env=$e)\n" + if !defined($title); + $fileinfo->{toplevel}->{$e}->{$filename} = 1; + } + } elsif ($key eq 'title') { + foreach my $e (@{$env_stack->[-1]}) { + register_title($filename, $e, undef, $value); + } + } + } + + if ($line =~ m/^\[\[(.*)\]\]\s*$/) { + my $blockid = $1; + die "implement me" if $blockid =~m/,/; + my $reftext = ''; + register_blockid($filename, $blockid, $reftext, $env_stack->[-1]); + foreach my $e (@{$env_stack->[-1]}) { + $env_last_blockid->{$e} = $blockid; + } + } + + if ($line =~ m/^\s*$/) { + foreach my $e (@{$env_stack->[-1]}) { + delete $env_last_blockid->{$e}; + } + } + + # fixme: "anchor:" + # bibliography anchors + if ($line =~ m/\[\[\[([^\]]*)\]\]\]/) { + my $blockid = $1; + die "implement me" if $blockid =~m/,/; + register_blockid($filename, $blockid, "[$blockid]", $env_stack->[-1]); + } + } +} + +my $scanned_files = {}; +while (my $filename = shift) { + next if $filename !~ m/\.adoc$/; # skip attributes.txt + next if $filename =~ m/-(opts|synopsis)\.adoc$/; + next if $scanned_files->{$filename}; + + scan_adoc_file($filename); + $scanned_files->{$filename} = 1; +} + +sub resolve_link_target { + my ($env, $filename) = @_; + + my $include_hash = $fileinfo->{include}->{$env}; + + my $repeat = 1; + + while ($repeat) { + $repeat = 0; + foreach my $fn (keys %$include_hash) { + if ($include_hash->{$fn}->{$filename}) { + next if ($fn eq 'pmg-admin-guide.adoc') && + $fileinfo->{outfile}->{$env}->{$filename}; + $filename = $fn; + $repeat = 1; + last; + } + } + } + + return $filename; +} + + +# try to generate output file mapping +foreach my $e (@$start_env) { + my $toplevel_hash = $fileinfo->{toplevel}->{$e}; + foreach my $fn (sort keys %$toplevel_hash) { + my $mansection = $fileinfo->{mansection}->{manvolnum}->{$fn}; + if ($e eq 'wiki') { + my $realfn = $fn; + $realfn =~ s/\.adoc$//; + if (defined($mansection) && ($mansection == 5)) { + $realfn .= ".$mansection"; + } + $realfn = "$realfn-plain.html"; + $fileinfo->{outfile}->{$e}->{$fn} = $realfn; + } elsif ($e eq 'manvolnum') { + my $realfn = $fn; + $realfn =~ s/\.adoc$//; + die "toplevel file '$fn' is not marked as manual page!" if !$mansection; + $realfn .= ".$mansection"; + $fileinfo->{outfile}->{$e}->{$fn} = $realfn; + } elsif ($e eq 'default') { + my $realfn = $fn; + $realfn =~ s/\.adoc$//; + if (defined($mansection) && ($mansection == 5)) { + $realfn .= ".$mansection"; + $realfn = "$realfn.html"; + } else { + if (($fn ne 'pmg-admin-guide.adoc') && + $fileinfo->{doctype}->{$e}->{$fn} == 0) { + $realfn = "chapter-$realfn.html"; + } else { + $realfn = "$realfn.html"; + } + } + $fileinfo->{outfile}->{$e}->{$fn} = $realfn; + } + } +} + +# now resolve blockids +foreach my $e (@$start_env) { + my $blockid_hash = $fileinfo->{blockid}->{$e}; + foreach my $blockid (keys %$blockid_hash) { + my $fn = resolve_link_target($e, $blockid_hash->{$blockid}); + if ($e eq 'wiki') { + my $title = $fileinfo->{titles}->{$e}->{$fn}; + $title =~ s/\s/_/g; + die "found not title for '$fn' in env '$e'" if !$title; + $fileinfo->{blockid_target}->{$e}->{$blockid} = "link:/wiki/$title#$blockid"; + + # we do not produce wiki pages for all content + #my $realfn = $fileinfo->{outfile}->{$e}->{$fn}; + #warn "no output file mapping for '$fn' ($e)\n" if !$realfn; + + } elsif ($e eq 'default') { + my $realfn = $fileinfo->{outfile}->{$e}->{$fn} || + die "no output file mapping for '$fn'\n"; + $fileinfo->{blockid_target}->{$e}->{$blockid} = "link:/pmg-docs/$realfn#$blockid"; + } elsif ($e eq 'manvolnum') { + # we do not produce manpages for all content + # my $realfn = $fileinfo->{outfile}->{$e}->{$fn} || + # warn "no output file mapping for '$fn'\n"; + $fileinfo->{blockid_target}->{$e}->{$blockid} = $fn; + } + } +} + +my $makevar_hash = {}; + +sub makevar_define { + my ($varname) = @_; + + die "makefile variable '$varname' already defined\n" + if exists($makevar_hash->{$varname}); + + $makevar_hash->{$varname} = {}; +} + +sub makevar_list_add { + my ($varname, $value) = @_; + + die "makefile variable '$varname' not defined\n" + if !exists($makevar_hash->{$varname}); + + $makevar_hash->{$varname}->{$value} = 1; +} + +sub makevar_dump { + my $txt = ''; + + foreach my $varname (sort keys %$makevar_hash) { + $txt .= "$varname ="; + foreach my $value (sort keys %{$makevar_hash->{$varname}}) { + $txt .= " \\\n\t$value"; + } + $txt .= "\n\n"; + } + + return $txt; +} + +if ($generate_depends) { + + my $tmpfilename = "${generate_depends}.tmp"; + my $outfh = IO::File->new($tmpfilename, "w") || + die "unable to open temporary file '$tmpfilename'\n"; + + my $depends = {}; + foreach my $e (@$start_env) { + my $env_data = $fileinfo->{include}->{$e}; + + my $add_depends; + + $add_depends = sub { + my ($fn, $dep) = @_; + + $depends->{$fn}->{$dep} = 1; + foreach my $nd (keys %{$env_data->{$dep}}) { + &$add_depends($fn, $nd); + } + }; + + foreach my $fn (keys %$env_data) { + foreach my $dep (keys %{$env_data->{$fn}}) { + &$add_depends($fn, $dep); + } + } + } + + my $depend_varname_hash = {}; + + foreach my $fn (sort keys %$depends) { + my $basename = uc($fn); + $basename =~s/\.adoc$//i; + $basename =~s/[^A-Za-z0-9]/_/g; + + my $varname1 = "${basename}_ADOCSOURCES"; + my $varname2 = "${basename}_ADOCDEPENDS"; + + makevar_define($varname1); + makevar_define($varname2); + + $depend_varname_hash->{$fn} = $varname2; + + makevar_list_add($varname1, $fn); + makevar_list_add($varname2, "\$\{$varname1\}"); + + foreach my $dep (sort keys %{$depends->{$fn}}) { + if ($dep =~ m/-(opts|synopsis).adoc$/) { + makevar_list_add($varname2, $dep); + } else { + makevar_list_add($varname1, $dep); + } + } + } + + my $man_sources_hash = {}; + foreach my $sourcefile (keys %{$fileinfo->{outfile}->{manvolnum}}) { + $man_sources_hash->{$sourcefile} = 1; + my $ihash = $fileinfo->{include}->{manvolnum}->{$sourcefile}; + foreach my $include (keys %$ihash) { + if ($include !~ m/-(opts|synopsis).adoc$/) { + $man_sources_hash->{$include} = 1; + } + } + } + + my $varname = "MANUAL_SOURCES"; + makevar_define($varname); + foreach my $sourcefile (sort keys %$man_sources_hash) { + makevar_list_add($varname, $sourcefile); + } + + $varname = "CHAPTER_LIST"; + makevar_define($varname); + my $filelist = $fileinfo->{outfile}->{default}; + foreach my $sourcefile (sort keys %$filelist) { + my $target = $filelist->{$sourcefile}; + makevar_list_add($varname, $target); + } + + $varname = "MANUAL_PAGES"; + makevar_define($varname); + $filelist = $fileinfo->{outfile}->{manvolnum}; + foreach my $manpage (sort keys %$filelist) { + my $target = $filelist->{$manpage}; + makevar_list_add($varname, $target); + } + + $varname = "WIKI_IMPORTS"; + makevar_define($varname); + $filelist = $fileinfo->{outfile}->{wiki}; + foreach my $sourcefile (sort keys %$filelist) { + my $target = $filelist->{$sourcefile}; + makevar_list_add($varname, $target); + } + + my $res = makevar_dump(); + + my $make_targets = {}; + foreach my $e (@$start_env) { + my $filelist = $fileinfo->{outfile}->{$e}; + foreach my $sourcefile (sort keys %$filelist) { + my $varname = $depend_varname_hash->{$sourcefile}; + next if !defined($varname); + my $target = $filelist->{$sourcefile}; + my $dep = "\$\{$varname\}"; + $make_targets->{$target} = $dep; + if ($e eq 'manvolnum') { + $make_targets->{"$target.html"} = $dep; + $make_targets->{"$target-plain.html"} = $dep; + } + } + } + foreach my $target (sort keys%$make_targets) { + my $dep = $make_targets->{$target}; + $res .= "$target: $dep\n\n"; + } + + print $outfh $res; + close($outfh); + + rename($tmpfilename, $generate_depends) || + die "rename failed - $!"; +} + +print to_json($fileinfo, { pretty => 1, canonical => 1 } );