python-senlinclient-1.7.0/0000775000175100017510000000000013234644002015547 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/0000775000175100017510000000000013234644002020240 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/0000775000175100017510000000000013234644002021540 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/_static/0000775000175100017510000000000013234644002023166 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/_static/.placeholder0000666000175100017510000000000013234643473025454 0ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/conf.py0000666000175100017510000002151413234643473023057 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. # Senlin Release Notes documentation build configuration file, created by # sphinx-quickstart on Tue Nov 3 17:40:50 2015. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'reno.sphinxext', 'openstackdocstheme', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Senlin Client Release Notes' copyright = u'2015, Senlin Developers' # Release notes are version independent. # The full version, including alpha/beta/rc tags. release = '' # The short X.Y version. version = '' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'openstackdocs' # openstackdocstheme options repository_name = 'openstack/python-senlinclient' bug_project = 'python-senlinclient' bug_tag = '' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # Must set this variable to include year, month, day, hours, and minutes. html_last_updated_fmt = '%Y-%m-%d %H:%M' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'SenlinClientReleaseNotesdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # 'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'SenlinClientReleaseNotes.tex', u'Senlin Client Release Notes Documentation', u'Senlin Developers', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'senlinclientreleasenotes', u'Senlin Client Release Notes Documentation', [u'Senlin Developers'], 1) ] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'SenlinClientReleaseNotes', u'Senlin Client Release Notes Documentation', u'Senlin Developers', 'SenlinClientReleaseNotes', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False # -- Options for Internationalization output ------------------------------ locale_dirs = ['locale/'] python-senlinclient-1.7.0/releasenotes/source/pike.rst0000666000175100017510000000021713234643473023237 0ustar zuulzuul00000000000000=================================== Pike Series Release Notes =================================== .. release-notes:: :branch: stable/pike python-senlinclient-1.7.0/releasenotes/source/index.rst0000666000175100017510000000024013234643473023412 0ustar zuulzuul00000000000000============================= Senlin Client Release Notes ============================= .. toctree:: :maxdepth: 1 unreleased pike ocata newton python-senlinclient-1.7.0/releasenotes/source/unreleased.rst0000666000175100017510000000016013234643473024433 0ustar zuulzuul00000000000000============================== Current Series Release Notes ============================== .. release-notes:: python-senlinclient-1.7.0/releasenotes/source/locale/0000775000175100017510000000000013234644002022777 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/locale/zh_CN/0000775000175100017510000000000013234644002024000 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/locale/zh_CN/LC_MESSAGES/0000775000175100017510000000000013234644002025565 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/locale/zh_CN/LC_MESSAGES/releasenotes.po0000666000175100017510000000224313234643473030634 0ustar zuulzuul00000000000000# zzxwill , 2016. #zanata msgid "" msgstr "" "Project-Id-Version: Senlin Client Release Notes 0.5.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-07-04 03:44+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2016-06-25 02:41+0000\n" "Last-Translator: zzxwill \n" "Language-Team: Chinese (China)\n" "Language: zh-CN\n" "X-Generator: Zanata 3.7.3\n" "Plural-Forms: nplurals=1; plural=0\n" msgid "0.5.0" msgstr "0.5.0" msgid "Added command for node-check and node-recover." msgstr "已为node-check和node-recover添加了命令。" msgid "Current Series Release Notes" msgstr "当前版本发布说明" msgid "New Features" msgstr "新特性" msgid "" "OSC commands for cluster scaling are changed from 'cluster scale in' and " "'cluster scale out' to 'cluster shrink' and 'cluster expand' respectively." msgstr "" "集群扩展的OSC命令分别从'cluster scale in'和'cluster scale out'改成了'cluster " "shrink'和'cluster expand'。" msgid "Senlin Client Release Notes" msgstr "Senlin Client发布说明" msgid "Upgrade Notes" msgstr "升级说明" python-senlinclient-1.7.0/releasenotes/source/locale/en_GB/0000775000175100017510000000000013234644002023751 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/locale/en_GB/LC_MESSAGES/0000775000175100017510000000000013234644002025536 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/locale/en_GB/LC_MESSAGES/releasenotes.po0000666000175100017510000001430513234643473030607 0ustar zuulzuul00000000000000# Andi Chandler , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: Senlin Client Release Notes 1.4.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-09-15 14:36+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2017-10-21 09:10+0000\n" "Last-Translator: Andi Chandler \n" "Language-Team: English (United Kingdom)\n" "Language: en-GB\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" msgid "0.5.0" msgstr "0.5.0" msgid "1.0.0" msgstr "1.0.0" msgid "1.1.0" msgstr "1.1.0" msgid "1.2.0" msgstr "1.2.0" msgid "" "A new CLI command 'senlin cluster-run' and a new OSC plugin command " "'openstack cluster run' have been added. Use the 'help' command to find out " "how to use it." msgstr "" "A new CLI command 'senlin cluster-run' and a new OSC plugin command " "'openstack cluster run' have been added. Use the 'help' command to find out " "how to use it." msgid "" "A new command 'senlin cluster-collect' and its corresponding OSC plugin " "command has been added. This new command can be used to aggregate a specific " "property across a cluster." msgstr "" "A new command 'senlin cluster-collect' and its corresponding OSC plugin " "command has been added. This new command can be used to aggregate a specific " "property across a cluster." msgid "" "A policy-validate command has been added to senlin command line. OSC support " "is added as well." msgstr "" "A policy-validate command has been added to Senlin command line. OSC support " "is added as well." msgid "" "A profile-validate command has been added to command line. It can be used " "for validating the spec of a profile without creating it." msgstr "" "A profile-validate command has been added to command line. It can be used " "for validating the spec of a profile without creating it." msgid "Add \"cluster_id\" colume for openstack cluster event list." msgstr "Add \"cluster_id\" column for openstack cluster event list." msgid "Add filter \"is_enabled\" for policy binding list." msgstr "Add filter \"is_enabled\" for policy binding list." msgid "Added command for node-check and node-recover." msgstr "Added command for node-check and node-recover." msgid "Bug Fixes" msgstr "Bug Fixes" msgid "Current Series Release Notes" msgstr "Current Series Release Notes" msgid "Enhance the parameter check for \"path\" in cluster collect operation." msgstr "Enhance the parameter check for \"path\" in cluster collect operation." msgid "Fix enabled option for senlin cluster-policy-detach command." msgstr "Fix enabled option for Senlin cluster-policy-detach command." msgid "Fix incorrect description of profile/policy validate operations." msgstr "Fix incorrect description of profile/policy validate operations." msgid "Fix metadata purging." msgstr "Fix metadata purging." msgid "Fix policy binding operations including attach, detach and update." msgstr "Fix policy binding operations including attach, detach and update." msgid "" "Fix project_id and user_id show bug for profile/policy validate and cluster " "policy show operations." msgstr "" "Fix project_id and user_id show bug for profile/policy validate and cluster " "policy show operations." msgid "Fix resource list operations for openstackclient." msgstr "Fix resource list operations for openstackclient." msgid "Fix resource update operations." msgstr "Fix resource update operations." msgid "Help message for metadata clean operations." msgstr "Help message for metadata clean operations." msgid "New Features" msgstr "New Features" msgid "Newton Series Release Notes" msgstr "Newton Series Release Notes" msgid "" "OSC commands for cluster scaling are changed from 'cluster scale in' and " "'cluster scale out' to 'cluster shrink' and 'cluster expand' respectively." msgstr "" "OSC commands for cluster scaling are changed from 'cluster scale in' and " "'cluster scale out' to 'cluster shrink' and 'cluster expand' respectively." msgid "Ocata Series Release Notes" msgstr "Ocata Series Release Notes" msgid "Other Notes" msgstr "Other Notes" msgid "Pike Series Release Notes" msgstr "Pike Series Release Notes" msgid "Remove unsupported sort key \"user\" for event-list." msgstr "Remove unsupported sort key \"user\" for event-list." msgid "Senlin Client Release Notes" msgstr "Senlin Client Release Notes" msgid "Support \"global_project\" arguments for action-list." msgstr "Support \"global_project\" arguments for action-list." msgid "Support node replace operation." msgstr "Support node replace operation." msgid "" "The 'senlin' CLI will be removed in April 2017. This message is now " "explicitly printed when senlin CLI commands are invoked." msgstr "" "The 'senlin' CLI will be removed in April 2017. This message is now " "explicitly printed when Senlin CLI commands are invoked." msgid "" "The cluster policy list command was broken by new SDK changes and then " "fixed. The 'enabled' field is now renamed to 'is_enabled'." msgstr "" "The cluster policy list command was broken by new SDK changes and then " "fixed. The 'enabled' field is now renamed to 'is_enabled'." msgid "" "The receiver creation command (both senlin CLI and OSC plugin command) now " "allow 'cluster' and 'action' to be left unspecified if the receiver type is " "not 'webhook'." msgstr "" "The receiver creation command (both Senlin CLI and OSC plugin command) now " "allow 'cluster' and 'action' to be left unspecified if the receiver type is " "not 'webhook'." msgid "" "The senlin CLI 'node-delete' and the OSC plugin command 'cluster node " "delete' now outputs the action IDs when successful. Error messages are " "printed when appropriate." msgstr "" "The Senlin CLI 'node-delete' and the OSC plugin command 'cluster node " "delete' now outputs the action IDs when successful. Error messages are " "printed when appropriate." msgid "" "The senlinclient now supports API micro-versioning. Current supported " "version is 'clustering 1.2'." msgstr "" "The senlinclient now supports API micro-versioning. Current supported " "version is 'clustering 1.2'." msgid "The support to python 3.5 has been verified and gated." msgstr "The support to python 3.5 has been verified and gated." msgid "Upgrade Notes" msgstr "Upgrade Notes" python-senlinclient-1.7.0/releasenotes/source/locale/fr/0000775000175100017510000000000013234644002023406 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/locale/fr/LC_MESSAGES/0000775000175100017510000000000013234644002025173 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/locale/fr/LC_MESSAGES/releasenotes.po0000666000175100017510000000177013234643473030246 0ustar zuulzuul00000000000000# Gérald LONLAS , 2016. #zanata msgid "" msgstr "" "Project-Id-Version: Senlin Client Release Notes 1.4.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-08-09 13:26+0000\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2016-10-22 06:14+0000\n" "Last-Translator: Gérald LONLAS \n" "Language-Team: French\n" "Language: fr\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n" msgid "0.5.0" msgstr "0.5.0" msgid "1.0.0" msgstr "1.0.0" msgid "Bug Fixes" msgstr "Corrections de bugs" msgid "Current Series Release Notes" msgstr "Note de la release actuelle" msgid "New Features" msgstr "Nouvelles fonctionnalités" msgid "Newton Series Release Notes" msgstr "Note de release pour Newton" msgid "Other Notes" msgstr "Autres notes" msgid "Senlin Client Release Notes" msgstr "Note de release du Client Senlin" msgid "Upgrade Notes" msgstr "Notes de mises à jours" python-senlinclient-1.7.0/releasenotes/source/_templates/0000775000175100017510000000000013234644002023675 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/_templates/.placeholder0000666000175100017510000000000013234643473026163 0ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/source/ocata.rst0000666000175100017510000000023013234643473023371 0ustar zuulzuul00000000000000=================================== Ocata Series Release Notes =================================== .. release-notes:: :branch: origin/stable/ocata python-senlinclient-1.7.0/releasenotes/source/newton.rst0000666000175100017510000000023213234643473023616 0ustar zuulzuul00000000000000=================================== Newton Series Release Notes =================================== .. release-notes:: :branch: origin/stable/newton python-senlinclient-1.7.0/releasenotes/notes/0000775000175100017510000000000013234644002021370 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/notes/micro-version-a292ce3b00d886af.yaml0000666000175100017510000000017113234643473027355 0ustar zuulzuul00000000000000--- features: - The senlinclient now supports API micro-versioning. Current supported version is 'clustering 1.2'. python-senlinclient-1.7.0/releasenotes/notes/deletion-output-a841931367a2689d.yaml0000666000175100017510000000030113234643473027432 0ustar zuulzuul00000000000000--- features: - The senlin CLI 'node-delete' and the OSC plugin command 'cluster node delete' now outputs the action IDs when successful. Error messages are printed when appropriate. python-senlinclient-1.7.0/releasenotes/notes/.placeholder0000666000175100017510000000000013234643473023656 0ustar zuulzuul00000000000000python-senlinclient-1.7.0/releasenotes/notes/receiver-create-8305d4efbdf35f35.yaml0000666000175100017510000000027513234643473027644 0ustar zuulzuul00000000000000--- other: - The receiver creation command (both senlin CLI and OSC plugin command) now allow 'cluster' and 'action' to be left unspecified if the receiver type is not 'webhook'. python-senlinclient-1.7.0/releasenotes/notes/fix-region-732c2be90e58c347.yaml0000666000175100017510000000012713234643473026501 0ustar zuulzuul00000000000000--- fixes: - Fixed a bug that region name is not respected when connecting to cloud. python-senlinclient-1.7.0/releasenotes/notes/senlinclient-1.2.0-4680ea85ba2dc6c8.yaml0000666000175100017510000000064413234643473027717 0ustar zuulzuul00000000000000--- features: - Support node replace operation. - Enhance the parameter check for "path" in cluster collect operation. - Help message for metadata clean operations. fixes: - Fix incorrect description of profile/policy validate operations. - Fix project_id and user_id show bug for profile/policy validate and cluster policy show operations. - Fix enabled option for senlin cluster-policy-detach command. python-senlinclient-1.7.0/releasenotes/notes/cluster-scaling-command-e0d96f2cd0c7ca5f.yaml0000666000175100017510000000025513234643473031443 0ustar zuulzuul00000000000000--- upgrade: - OSC commands for cluster scaling are changed from 'cluster scale in' and 'cluster scale out' to 'cluster shrink' and 'cluster expand' respectively. python-senlinclient-1.7.0/releasenotes/notes/force-delete-c8d6cf4d6f049cb2.yaml0000666000175100017510000000012313234643473027206 0ustar zuulzuul00000000000000--- fixes: - Fixed a bug that force deletion of cluster or node was not working. python-senlinclient-1.7.0/releasenotes/notes/profile-validate-587f1a964e93c0bf.yaml0000666000175100017510000000023213234643473027745 0ustar zuulzuul00000000000000--- features: - A profile-validate command has been added to command line. It can be used for validating the spec of a profile without creating it. python-senlinclient-1.7.0/releasenotes/notes/retire-senlin-cli-8ba21807b584993d.yaml0000666000175100017510000000024613234643473027706 0ustar zuulzuul00000000000000--- upgrade: - The `senlin` command line support is completely dropped. Users are expected to use `openstack cluster` commands to interact with Senlin service. python-senlinclient-1.7.0/releasenotes/notes/cluster-collect-a9d1bc8c2e799c7c.yaml0000666000175100017510000000031213234643473027762 0ustar zuulzuul00000000000000--- features: - A new command 'senlin cluster-collect' and its corresponding OSC plugin command has been added. This new command can be used to aggregate a specific property across a cluster. python-senlinclient-1.7.0/releasenotes/notes/senlinclient-1.1.0-daf1f24c73ee8b17.yaml0000666000175100017510000000065013234643473027772 0ustar zuulzuul00000000000000--- fixes: - Fix resource list operations for openstackclient. - Add filter "is_enabled" for policy binding list. - Fix policy binding operations including attach, detach and update. - Remove unsupported sort key "user" for event-list. - Fix metadata purging. - Add "cluster_id" colume for openstack cluster event list. - Support "global_project" arguments for action-list. - Fix resource update operations. python-senlinclient-1.7.0/releasenotes/notes/cluster-policy-list-42ff03ef25d64dd1.yaml0000666000175100017510000000022513234643473030512 0ustar zuulzuul00000000000000--- fixes: - The cluster policy list command was broken by new SDK changes and then fixed. The 'enabled' field is now renamed to 'is_enabled'. python-senlinclient-1.7.0/releasenotes/notes/cluster-run-210247ab70b289a5.yaml0000666000175100017510000000027113234643473026616 0ustar zuulzuul00000000000000--- features: - A new CLI command 'senlin cluster-run' and a new OSC plugin command 'openstack cluster run' have been added. Use the 'help' command to find out how to use it. python-senlinclient-1.7.0/releasenotes/notes/cli-deprecation-241b9569b85f8fbd.yaml0000666000175100017510000000022013234643473027561 0ustar zuulzuul00000000000000--- other: - The 'senlin' CLI will be removed in April 2017. This message is now explicitly printed when senlin CLI commands are invoked. python-senlinclient-1.7.0/releasenotes/notes/policy-validate-193a5ebb7db3440a.yaml0000666000175100017510000000016513234643473027643 0ustar zuulzuul00000000000000--- features: - A policy-validate command has been added to senlin command line. OSC support is added as well. python-senlinclient-1.7.0/releasenotes/notes/node-check-recover-469bf81db9f9f1ec.yaml0000666000175100017510000000010113234643473030322 0ustar zuulzuul00000000000000--- features: - Added command for node-check and node-recover. python-senlinclient-1.7.0/releasenotes/notes/python-3.5-c9fd8e34c4046357.yaml0000666000175100017510000000011113234643473026255 0ustar zuulzuul00000000000000--- features: - The support to python 3.5 has been verified and gated. python-senlinclient-1.7.0/ChangeLog0000664000175100017510000007000213234644000017316 0ustar zuulzuul00000000000000CHANGES ======= 1.7.0 ----- * Receiver update faild when action value None * Zuul: Remove project name 1.6.0 ----- * Q3 release note * Add basic functional tests * Updated from global requirements * Refactored make\_client * Add support for region\_name and interface for client connection * Updated from global requirements * Fix cluster/node force delete parameter location error * Update the home page * Delete TODO file support action create,delete operation * Retire senlin command line tool 1.5.0 ----- * Updated from global requirements * Avoid tox\_install.sh for constraints support * Remove setting of version/release from releasenotes * Updated from global requirements * Fix delete cluster/node miss force-delete parameter * Updated from global requirements * Fix the ineffective url links in python-senlinclient docs * Switch to Zuul v3 testing * Imported Translations from Zanata * Add force parameter for cluster and node deletion * Updated from global requirements * Add profile type ops cli * Updated from global requirements * Updated from global requirements * Support node-adopt/preview CLI * Imported Translations from Zanata * Fix unit test failure * Updated from global requirements * Update reno for stable/pike * fixes support for osprofiler 1.4.0 ----- * OSC command for node op and cluster op * Add an installation doc * Updated from global requirements * Updated from global requirements * Fix receiver-update mistake * Revise \`senlin service-list\` * Add --config option parameter for cluster-create command * Fix \`openstack cluster service\` * Revise service list help info * Updated from global requirements * Fix \`openstack cluster service\` Exception raised This patch fixes \`openstack cluster service\` Closes-bug: #1705069 * List services doc link cannot be found * Update and optimize documentation links * Fix senlin cluster policy list error * Updated from global requirements * Unify style of 'domain' field * Profile id or name is a default profile * fix setup.cfg cluster service path error * Fix openstackdocstheme settings * Cleanup sphinx building * import cli-reference from openstack-manuals * Support to cluster-op and node-op operations * Updated from global requirements * Updated from global requirements * Enable some off-by-default checks * Make --os-profile load from environment variables * Support receiver update operation * Add services list * Updated from global requirements * Fix html\_last\_updated\_fmt for Python3 * Updated from global requirements * Fix development document api-ref link error * Updated from global requirements * remove redundant value when cluster-show * Updated from global requirements * Delete TODO about event-delete, The event-delete has been abandoned * Check node status before do cluster-recover action * Updated from global requirements 1.3.0 ----- * Updated from global requirements * Updated from global requirements * Revise command reminder when we run \`openstack cluster resize\` * Revise command reminder when we run \`senlin cluster-resize\` * Remove log translations * Updated from global requirements * Param "response" is not used any more in python-senlinclient/senlinclient/tests/unit/v1/test\_build\_info.py * delete bash\_completion in subcommand * Support check before do node-recover action * Support profile-only to cluster update * Fix hacking requirement for testing * Updated from global requirements * Using fixtures.MockPatch instead of mockpatch.Patch * The python 3.4 support is removed * Initial test hooks for functional test * Fixed warnings when building docs * Fix cluster update failed problem * Avoid import internal classes from SDK (3) * Avoid import internal classes from SDK (2) * Avoid import internal classes from SDK * Update imoprt order * Replace six.itervalues with dict.values() * Enable coverage report in console output * Updated from global requirements * Print support status while listing policy types * Support status output for profile type list * Add oslo\_debug\_helper to tox.ini * Remove a py34 environment from tox * Replaces yaml.load() with yaml.safe\_load() * Revert "Revert "Revert "Revert "Fix \`openstack cluster profile validate\` bug"""" * Fix SDK version problem * Updated from global requirements * Update reno for stable/ocata 1.2.0 ----- * Release note for python-senlinclient 1.2.0 * Fix senlin cluster-policy-detach cannot disable * Fix cluster\_collect interface * Updated from global requirements * Add deprecation of cluster-run cli * Updated from global requirements * Add missing requirements * Updated from global requirements * Client support for "destroy\_after\_deletion" in cluster del nodes * Add filter "user\_id" for receiver list * Remove unnecessary coding format in the head of files * Add parameter in CLUSTER\_DEL\_NODES action * Add user\_id in receiver list * Trivial: Modify the description of policy validate * Updated from global requirements * Trivial: Modify the description of profile validate * Revert "Revert "Revert "Fix \`openstack cluster profile validate\` bug""" * Fix \`openstack cluster policy show\` bug * Fix \`openstack cluster policy vaildate\` bug * Revert "Revert "Fix \`openstack cluster profile validate\` bug"" * Revert "Revert "Get project\_id and user\_id when show profile"" * Add Constraints support * Revert "Fix \`openstack cluster profile validate\` bug" * Revise help string profile list * Revert "Get project\_id and user\_id when show profile" * Enhance the parameter check for "path" in cluster collect * Fix \`openstack cluster profile validate\` bug * Client support for node replace * Get project\_id and user\_id when show profile * Updated from global requirements * Add metadata clean help * Delete pbr generated files * Fix import method to follow community guideline 1.1.0 ----- * Release note for python-senlinclient 1.1.0 * Fix resource update issues * Correct deprecation of scale-in and scale-out cli * Show team and repo badges on README * Fix error in policy-show * Updated from global requirements * Fix project\_id show in 'senlin xyz\_list -g' * Delete python bytecode file * Trivial: Fix a typo in cluster-run's error message * Fix error in cluster collect * Point out valid filter keys in \`openstack cluster member list\` * Fix cluster\_id field when listing events * key=value should be key2=value2 * Revise the help message of cluster-collect * Revise the help info of cluster collect * Revise key1=value to key1=value1 * Support "global\_project" arguments for action-list * Point out valid sort keys in \`openstack cluster member list\` * Revise 'openstack cluster node members list' * The output of action list filtered by "target" returns empty * The output of event-list by filter "cluster\_id" return empty * Modify development doc url in CONTRIBUTING.rst * Updated from global requirements * Revise the help message of policy binding list * Add "cluster\_id" column to \`openstack cluster event list\` * Add sort key "oid" in event list * Remove unsupported sort key "user" * Updated from global requirements * Revise "enabled" related code in ClusterPolicyUpdate * cluster policy attach cannot work * policy binding update cannot work * Policy binding attach cannot work * Support xyz\_update purging metadata * Add filters "policy\_type" and "policy\_name" for policy binding list * Rework do\_action\_list function's "full\_id" handling * Updated from global requirements * Fix target ID display when listing actions * Add filter "is\_enabled" for policy binding list * Updated from global requirements * Show project\_id field when xyz-list with global-project * Add AUTHORS and ChangeLog into gitignore * All dictionary options need be a string * profile's name also can be use in some commands * Add receiver type instruction * Updated from global requirements * Rework take\_action function in class ListAction * Fix error in "action list" * Modify several marker's help * Change osprofiler option "--profile" to "--os-profile" * Add plug-in summary for osc doc * action-list's given id not event id * Change the type of the parameter "enabled" to boolean * event-list cannot display correctly according to the sort option * Fix the incorrect version and release details * Enable release notes translation * Changed the link to home-page * Fix list of event with timestamp field * Updated from global requirements * Fix doc build if git is absent * \`openstack cluster event list --help\` bug * revise the "cluster-policy-attach" * Fix help msg of node-check and node-recover * Updated from global requirements * Replace 'MagicMock' with 'Mock' * Fix error in build-info * Fix error in action list * Fix 'type\_name' in \`openstack cluster profile list\` * Fix profile list * Fix \`openstack cluster event list\` bug * Fix \`openstack cluster action list\` bug * Fix error in do\_profile\_type\_list * Profile list can not display the "type" column * Make shell main() specify return value in exit code * fix indentation of reno toctree * Remove six.moves module * Show 'dependents' property in node details * Fix receiver list * Updated from global requirements * Update reno for stable/newton * senlin profile-create has no argument -t 1.0.0 ----- * Release notes for newton-3 milestone * Clarify senlin CLI deprecation message * Fix output from cluster/node delete * Revise params of 'receiver create' command * Remove \*openstack/common\* from flake8 excclude list in tox.ini * OSC plugin command for cluster-run * Updated from global requirements * Fix "openstack cluster policy binding list " * Fix cluster-policy-list * Add 'cluster-run' command * Updated from global requirements * Updated from global requirements * Fix get\_node * Fix \_show\_node error * Remove mox3 in test-requirement.txt of senlinclient * py3:Rmove six.iteritems/iterkeys in python-senlinclient * Imported Translations from Zanata * Add policy validate operation to senlinclient * Add profile validate operation to senlinclient * Imported Translations from Zanata * Reorder required parameters * Remove 'ProfileAction' and related arguments * Remove local cached version of Resource class * Add cluster\_collect support * Add support to micro-version * Updated from global requirements * Remove discover from test-requirements * Fix typo * Fix nodes display in cluster-show * Update senlinclient for new sdk version * Updated from global requirements * Updated from global requirements * Add Python 3.5 classifier and venv * Updated from global requirements * Prints '-' instead of 'None' when data is None * Updated from global requirements * Updated from global requirements * Imported Translations from Zanata * Delete extra space * Use osc\_lib instead of cliff * Updated from global requirements * Use osc-lib instead of openstackclient * Enhance message related to OS\_PROJECT\_DOMAIN\_NAME * Imported Translations from Zanata * Imported Translations from Zanata * Fix openstack cluster resize * Remove unused POT file 0.5.0 ----- * Added release notes for a new release * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Add reno for release notes management * Trival fix: Update README * Updated from global requirements * Updated from global requirements * Correct some typos * Updated from global requirements * Pramater doesn't align to comments * Removed the invalid link for Module Index * Add link to API doc in client module * Revert "Remove senlin CLI commands" * Support more parameters for senlinclient creation * Rename cluster scaling command * Remove senlin CLI commands * Refactor osc support * Add deprecation warnings for senlin commands * Add OSC command for senlin node-check/recover * Spelling mistakes on 'Clustering service command-line client' page 0.4.1 ----- * Fix event list sorting * Add OSC command and enable more than one arguements * Add cluster check and recover into CLI * Updated from global requirements 0.4.0 ----- * Fix node update receive a assertion error * Sort resource show columns * Update OSC metavars * Add OSC plugin for openstack cluster build info * Add OSC plugin for openstack cluster action show * Add OSC plugin for openstack cluster action list * Add OSC plugin for openstack cluster event show * Add OSC plugin for openstack cluster event list * Add OSC plugin for openstack cluster receiver delete * Add OSC plugin for openstack cluster receiver create * Add OSC plugin for openstack cluster receiver show * Add OpenstackClient plugin for cluster members del * Add OpenstackClient plugin for cluster members add * Add OpenstackClient plugin for cluster members list * Add OpenstackClient plugin for cluster policy binding update * Add OpenstackClient plugin for cluster policy binding show * Add OpenstackClient plugin for cluster policy binding list * Add OSC plugin for openstack cluster policy detach * Add OSC plugin for openstack cluster policy attach * Add OSC plugin for openstack cluster scale out * Add OSC plugin for openstack cluster scale in * Add OSC plugin for openstack cluster resize * Add OSC plugin for openstack cluster delete * Add OSC plugin for openstack cluster receiver list * Fix senlin help receiver-list * Fix SDK exception parsing * Add OSC plugin for openstack cluster update * Add OSC plugin for cluster policy type show * OSC plugin for openstack cluster policy type list * Add OSC plugin for openstack cluster create * Add OSC plugin for openstack cluster show * Add OpenstackClient plugin for cluster policy delete * Add OpenstackClient plugin for cluster policy update * Add OpenstackClient plugin for cluster policy create * Add OpenstackClient plugin for cluster policy show * OSC plugin for openstack cluster list * Add "--filter" for command openstack cluster profile list * Add OpenstackClient plugin for cluster policy list * Add filters option to policy-list command * Fix translation setup * Ensure cluster is specified when creating receivers * Updated from global requirements * Add OpenstackClient plugin for cluster node delete * Add OpenstackClient plugin for cluster node update * Add OpenstackClient plugin for cluster node create * Add OpenstackClient plugin for cluster node show * Remove profile permission * Add OpenstackClient plugin for cluster profile update * Add OpenstackClient plugin for cluster node list * Add OpenstackClient plugin for cluster profile create * Add OpenstackClient plugin for cluster profile type show * Add OpenstackClient plugin for cluster profile delete * Add filters option to profile-list command * Add JsonFormat display option * Add OpenstackClient plugin for cluster profile type list * Add OpenstackClient plugin for cluster profile list * Updated from global requirements * Add OpenstackClient plugin for cluster profile show * Add node check and recover into CLI * Add the unit test for utils module * Apply list\_formatter on two properties * Handle ResourceNotFound when resource is not found * Make ignore\_missing False when deleting resource * Parse exceptions from openstacksdk * Updated from global requirements * Fix cluster\_update\_policy parameter passing error * Remove nested cluster support * Updated from global requirements * Change 'status\_code' to 'http\_status' to parse SDK's exception 0.3.0 ----- * Remove argparse from requirements * Updated from global requirements * Update the word 'Senin' to 'Senlin' * Add back show\_details for node-show * Unit test for v1 client * The param endpoint in doc string is deprecated * Updated from global requirements * Fix update\_policy parameter passing error * Remove cluster-policy-enable/disable * Fix meta var problem in cluster-policy-list * Remove node join/leave from senlinclient * Remove 'permission' from senlin client * Remove 'level', 'cooldown' and 'priority' properties in client * Replace deprecated library function os.popen() with subprocess * Revise client to support new sorting option * Remove references to oslo incubator modules * Add test case for common/utils * Remove usless models.py module 0.2.1 ----- * Make sort keys work for node-list and action-list * Fix cluster-policy-list command * Switch to use SDK calls in client * Put 'policy' out of params for do\_cluster\_policy\_attach * Rename timestamp fields according to server change * Remove 'show-deleted' from command line options * Make cluster action calls use SDK interface * Fix redundent paginated in senlinclient * Fix formatters used for listing actions * Fix shell message for action list * Make cluster CRUD calls invoke SDK * Directly use SDK calls in client (1) * Use SDK calls when possible * Unit test for /v1/shell.py part3 * Client support to receivers * Make event-list sort\_keys all workable * Replace inner methods with lambda function * Remove MANIFEST.in * Updated from global requirements * Don't show show\_deleted column in node-list when not needed * Deprecated tox -downloadcache option removed * Updated from global requirements * Make cluster-policy-update help message clear * Add test case for v1/shell.py part2 * Fix pep8 error about D300 * Try to show policy after policy created * Cluster's timeout is in seconds not minutes * Make desired\_capacity default to min\_size if min\_size specified * Add py34 to tox.ini * Add choices to -F argument * Fix profile/policy schema calls * Remove ClusterNode model from client side * Specify keystoneauth1 exception more * Fix nit in the help msg of cluster-node-del * Remove py26 support * Fix profile update parameters passing error * Fix help message error for node\_create * Updated from global requirements * Fix action api calls * Fix some wrong help messages * Add short id support to cluster-policy-list * Updated from global requirements * Fix parse\_exception to handle exception from keystoneauth1 * Remove Trigger related sources in client side 0.1.8 ----- * Fix 'action' call on cluster/node objects * Make '\_short\_id' method a public method 0.1.7 ----- * Fix 'endpoint missing' error caused by SDK's change 0.1.6 ----- * Fix bug introduced by openstacksdk * Add 'global\_project' option for cluster-list * Add test case for v1/shell module - part 1 * Updated from global requirements * Updated from global requirements * Remove spec file profile-update command * Fix typo s/beteen/between/ * Delete .pyc files before running test * Sync with oslo-incubator 0.1.5 ----- * Remove unused methods in client module * Revised client interface * Adapt resource path to server revision * Update gitignore file * Updated from global requirements * Delete deprecated 'policy' option for webhook create * Update .gitreview for new namespace * Strips off the quotes when showing nested table * Updated from global requirements * Fix help message for cluster\_scale\_in/out * Updated from global requirements 0.1.4 ----- * Fix client constructor for ease of use * Format list fields in action list * Remove default value when attaching a policy 0.1.3 ----- * Remove unused requirements * Update requirement of python-openstacksdk to openstacksdk 0.1.2 ----- * Fix misc errors in setup.cfg 0.1.1 ----- * Revise client constructor * Fix the sphinx build path in .gitignore file * Word error in the help info of cluster-create -m * Handle None value in formatter * Updated from global requirements * Add test case for shell(part2) * Fix a bug in do\_action\_show * Fix node-update behavior * Add resource\_key to event models * Shell unit test (1) 0.2 --- * v0.2 branch 0.1.0 ----- * Revise support to profile-create/show * Add short Id support to event list * Remove 'type' parameter for policy creation * Add resource\_key for Action resource * Initial support to triggers * Updated from global requirements * Add deleted\_time to webhook\_list * Avoid deleting metadata incorrectly when doing profile\_update * Fix crendential type problem in webhook operations in client side * Credential option should not be 'required' when creating webhook * Fix TypeError when doing cluster-scale-in * Sync ProfileAction implementation with latest SDK code * Updated from global requirements * Add unit test cases for sdk module * Unit test for client module * Unit test for cliargs module * Updated from global requirements * Remove private copy of clustering\_service * Fix filters param passing * Preparation for senlinclient test cases * Revise parse\_exception in the client side * Updated from global requirements * Use correct default domain name in senlinrc * Fix cluster-resize operation param checking * Updated from global requirements * Fix resource listing error * Fix profile name update error * Use PATCH method to update resources * Updated from global requirements * Parse exception from SDK * Fix list operation based on sdk interface * Updated from global requirements * Remove thin methods which is not used * Updated from global requirements * Updated from global requirements * Fix arg name for sort-dir * Replace 'start\_time' with 'created\_time' for sorting * Fix list sorting in command line * Fix some cluster-list option bugs * Make "--metadata" option "-M" instead of "-d" * Make --show-deleted and --sort-dir option names consistent * Fix minor error in node-list command * Remove profile-type-show command * Remove 'permission' from cli output * Fix senlinrc to support keystone v2 and v3 on the client side * Support keystone v2 and v3 * Updated from global requirements * Disable rollback by default * Updated from global requirements * Bump oslo.utils version to 1.6.0 * Handle AttributeError when creating a profile * Change max\_size's default value to -1 when creating a cluster * Revise webhook-create support in client * Sync with global requirements * Revise comment format in doc to pass pep8 check * Delete some dead code from client model * Replace sdk user\_reference module with profile * Try please flake8 for imports grouping * Resize operation support from client * Fixed an error in webhook\_show * Updated pot file * Rename 'tags' to 'metadata' * Add docs generated to version control * Sync package version requirements * Add min\_size and max\_size properties to Cluster * Replace cluster size with new property desired\_capacity * Remove '...' from short-id style listing * Add --details argument to node-show * Add webhook support * Add options for tennat\_id/tenant\_name * Fix initial gate errors * add context support for profile * Make update always do a node retrieval first * Added support to OS\_TRUST\_ID * Added support to list nodes with global tenant * Added support to cluster-policy-show operation * Make ; parsing optional * Revised cluster-policy-list operation * Fixed cluster\_update operation error * Ignore return value from update() * Revised cluster-update operation support * Added support to policy-update operation * Added support to profile-update operation * Allow profile to be updated * Fixed profile creation errors * Added support to project field in node objects * Revised event list/show support * Fixed PEP8 error * Improved Event object model * Removed support to profile/policy type template * Fix user name argument parsing * Bump six version to 1.9.0 * Always use block for YAML dumping * Added policy schema show support * Initial support to profile-type-schema * Make scale-out argument count optional * Added format\_output method * Make node-list ordered by created\_time by default * Added support to other useful fields when listing policies * Reworkd policy operations * Revised cluster model and clusterpolicy model * Cluster policy listing support * Initial support to policy operations * Initial support to node-join/leave operations * Added required constraints to some operations * Added del\_nodes support * Added one TODO item * Make profile a required argument * Support to cluster-node-add operation * Added formatter for ID fields * Make node\_create/node\_show work with new API design * Revised cluster-create and cluster-show commands * Make at least profile-create API work * Support profile resource\_key when do profile-show * Tolerate empty dict in print\_dict * Define UNVERSIONED=None in clustering\_service.py * Added short ID support for node-list * Enable client module to handle any exception * Remove unused imports * Make list\_short capable of handling other exceptions * Handle requests exception * Make deleted\_time show conditional * assign alias to client module * Remove init\_time from list show * Added cluster deletion support * Fixed one PEP8 error * Fixed cluster list column name error * Make error message more clear when username is assigned * Fixed object listing logic * Simplified exception translation * Basic support for cluster show * Added dict dump method for clusters * Added formatter for list in the context of a dict * Added feature to show IDs in short-form * Move senlinrc into tools subdir * Initial support to cluster create * Added trust-based authentication as TODO * New item about setting up senlin connection * Removed some items that were completed * Fixed flake8 errors * Major revision to shell main module * Revised listing functions to take advantage of exception handling * Implement exception handling for client module * Override print\_list function for exception catching * Added function to create connection via SDK * Major revision to client side exception handling * Added action-list and action-show support * Added node show support * Added node list command and fixed related errors * Fixed list() method errors * Added customization of create() method * Added exception support (WIP) * Bump oslo.i18n version requirement * Added support to bash completion * Add support to profile show * Add conversion to dict for profile * Added capabiity to print nested table * Revised profile list implementation * Introduce HTTP exception into common * Fixed typo in dictionary key * Removed non-existant fields from Profile * Fixed common client to return object from create * Fixed help message for API VERSION option * Make v3 the default backend for authentication * Added profile\_create and profile\_list operation * Remove dict translation for list operation * Remove dict translation for create action * Clarified help message * Added version information * Added support to both v2.0 and v3 authentication * Revised requirements file * Added utility functions to process spec files * Added FileFormatError exception * Fixed pbr version string error * Remove old client module * Added keystone V3 support * Fix oslo.i18n namespace error * Add heatclient to requirements.txt * Revised error message for project\_id validation * Added build info alike dictionary retrieval support * Senlin RC file initial version * Initial version of V1 client * New version of V1 shell * Fix error in service name imported * Top priority task: create os.senlin.stack profile * Reimplemented client shell * Added Versions to the client-side models * Initial version of command line argument parser * Added new item about checking identity arguments * Fix oslo namespace errors * Revised sdk interface * Revised common client to use session * Added TODO item about support to HTTPS * Revised TODO list * Remove http.py since we don't use this client * Modify i18n import * Clustering service module for openstacksdk * Fix import errors in cliutils * Remove deprecating apiclient module * Rename old client.py to old\_client.py * New object models for interacting with server * Remove old-style object models * Added sort\_keys and sort\_dirs support * Fixed error in original reference * New clusters file, replacing old ones * Remove clusters file, to be replaced * Placeholder for openstacksdk interface * Add openstacksdk to the dependency list * Revised TODO list * Bump oslo.utils to 1.2.0 * Added todos for apiclient migration * Removed httpretty as suggested in other projects * New item for unit tests * Remove node\_join and node\_leave operations * Replace enable/disable with policy\_update * Remove list\_nodes method from cluster * Removed enable/disable cluster policy operations * Added supported\_formats * Move exc module to common subdir * Added more operations to clusters * Added several TODO items * More operations added * Remove profile method, not needed now * Move exception file * Fix typo error * Initial version * Initial version * Initial version * Initial version * Initial version * Fixed left error * Initial version * Initial version * Initial version * Initial version * Initial version * Initial version * Initial commit python-senlinclient-1.7.0/tox.ini0000666000175100017510000000315713234643473017105 0ustar zuulzuul00000000000000[tox] envlist = py35,py27,pypy,pep8,releasenotes minversion = 2.0 skipsdist = True [testenv] setenv = VIRTUAL_ENV={envdir} CLIENT_NAME=python-senlinclient usedevelop = True install_command = pip install {opts} {packages} deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = find . -type f -name "*.py[c|o]" -delete python setup.py testr --slowest --testr-args='{posargs}' whitelist_externals = find [testenv:pep8] commands = flake8 # Check that .po and .pot files are valid: bash -c "find senlinclient -type f -regex '.*\.pot?' -print0|xargs -0 -n 1 --no-run-if-empty msgfmt --check-format -o /dev/null" whitelist_externals = bash [testenv:venv] commands = {posargs} [testenv:functional] setenv = {[testenv]setenv} OS_TEST_PATH = ./senlinclient/tests/functional passenv = OS_* [testenv:cover] commands = python setup.py testr --coverage --testr-args='{posargs}' coverage report [testenv:debug] commands = oslo_debug_helper -t senlinclient/tests {posargs} [testenv:docs] commands= python setup.py build_sphinx [testenv:releasenotes] commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [flake8] ignore = D100,D101,D102,D103,D104,D105,D200,D201,D202,D204,D205,D300,D301,D400,D401,I100,I201 show-source = True enable-extensions = H203,H106 exclude=.venv,.git,.tox,dist,*lib/python*,*egg,build max-complexity=20 [hacking] import_exceptions = senlinclient.common.i18n python-senlinclient-1.7.0/setup.py0000666000175100017510000000200613234643473017274 0ustar zuulzuul00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools # In python < 2.7.4, a lazy loading of package `pbr` will break # setuptools if some other modules registered functions in `atexit`. # solution from: http://bugs.python.org/issue15881#msg170215 try: import multiprocessing # noqa except ImportError: pass setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True) python-senlinclient-1.7.0/PKG-INFO0000664000175100017510000000331613234644002016647 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: python-senlinclient Version: 1.7.0 Summary: OpenStack Clustering API Client Library Home-page: https://docs.openstack.org/python-senlinclient/latest/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description-Content-Type: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/python-senlinclient.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on OpenStackClient Plugin for Senlin Clustering Service ==================================================== This is a client library for Senlin built on the Senlin clustering API. It provides a plugin for the openstackclient command-line tool. Development takes place via the usual OpenStack processes as outlined in the `developer guide `_. The master repository is in `Git `_. Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 python-senlinclient-1.7.0/requirements.txt0000666000175100017510000000114613234643473021052 0ustar zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. Babel!=2.4.0,>=2.3.4 # BSD pbr!=2.1.0,>=2.0.0 # Apache-2.0 PrettyTable<0.8,>=0.7.1 # BSD keystoneauth1>=3.3.0 # Apache-2.0 openstacksdk>=0.9.19 # Apache-2.0 osc-lib>=1.8.0 # Apache-2.0 oslo.i18n>=3.15.3 # Apache-2.0 oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0 python-heatclient>=1.10.0 # Apache-2.0 PyYAML>=3.10 # MIT requests>=2.14.2 # Apache-2.0 six>=1.10.0 # MIT python-senlinclient-1.7.0/AUTHORS0000664000175100017510000000511313234644000016615 0ustar zuulzuul00000000000000Aaron-DH Andreas Jaeger Ayush Garg Cao Xuan Hoang Christopher Stone Cindia-blue Doug Hellmann EldonZhao Erik Olof Gunnar Andersson Ethan Lynn Ethan Lynn Flavio Percoco ForestLee Haiwei Xu Haiwei Xu Hangdong Zhang Hoang Trung Hieu Jeffrey Guan Jeremy Liu Jeremy Stanley KATO Tomoyuki LiuNanke Liuqing Jing Lu lei Navneet Gupta Ondřej Nový OpenStack Release Bot PanFengyun QI ZHANG Qiming Qiming Teng Sharat Sharma Tang Chen Thomas Bechtold Tony Breeds Tovin Seven XueFeng Liu Yanyan Hu Yuanbin.Chen ZhongShengping Zuul bhavani.cr blue55 chenpengzi <1523688226@qq.com> chohoor dixiaoli gecong1973 gengchc2 howardlee huangtianhua jolie jonnary kavithahr lawrancejing liyi lvdongbing mathspanda miaohb pallavi pawnesh.kumar qinchunhua shangxiaobj shu-mutou tengqm venkatamahesh xiaolihope xiaozhuangqing xu-haiwei yanyanhu zhangguoqing zhangyanxian zhurong zzxwill python-senlinclient-1.7.0/senlinclient/0000775000175100017510000000000013234644002020236 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/senlinclient/v1/0000775000175100017510000000000013234644002020564 5ustar zuulzuul00000000000000python-senlinclient-1.7.0/senlinclient/v1/profile.py0000666000175100017510000003117413234643473022621 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Clustering v1 profile action implementations""" import logging import sys from openstack import exceptions as sdk_exc from osc_lib.command import command from osc_lib import exceptions as exc from osc_lib import utils from senlinclient.common.i18n import _ from senlinclient.common import utils as senlin_utils class ShowProfile(command.ShowOne): """Show profile details.""" log = logging.getLogger(__name__ + ".ShowProfile") def get_parser(self, prog_name): parser = super(ShowProfile, self).get_parser(prog_name) parser.add_argument( 'profile', metavar='', help='Name or ID of profile to show', ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering return _show_profile(senlin_client, profile_id=parsed_args.profile) def _show_profile(senlin_client, profile_id): try: data = senlin_client.get_profile(profile_id) except sdk_exc.ResourceNotFound: raise exc.CommandError('Profile not found: %s' % profile_id) else: formatters = {} formatters['metadata'] = senlin_utils.json_formatter formatters['spec'] = senlin_utils.nested_dict_formatter( ['type', 'version', 'properties'], ['property', 'value']) data = data.to_dict() columns = sorted(data.keys()) return columns, utils.get_dict_properties(data, columns, formatters=formatters) class ListProfile(command.Lister): """List profiles that meet the criteria.""" log = logging.getLogger(__name__ + ".ListProfile") def get_parser(self, prog_name): parser = super(ListProfile, self).get_parser(prog_name) parser.add_argument( '--limit', metavar='', help=_('Limit the number of profiles returned') ) parser.add_argument( '--marker', metavar='', help=_('Only return profiles that appear after the given profile ' 'ID') ) parser.add_argument( '--sort', metavar='[:]', help=_("Sorting option which is a string containing a list of keys" " separated by commas. Each key can be optionally appended " "by a sort direction (:asc or :desc). The valid sort_keys " "are:['type', 'name', 'created_at', 'updated_at']") ) parser.add_argument( '--filters', metavar='<"key1=value1;key2=value2...">', help=_("Filter parameters to apply on returned profiles. " "This can be specified multiple times, or once with " "parameters separated by a semicolon. The valid filter " "keys are: ['type', 'name']"), action='append' ) parser.add_argument( '--global-project', default=False, action="store_true", help=_('Indicate that the list should include profiles from' ' all projects. This option is subject to access policy ' 'checking. Default is False') ) parser.add_argument( '--full-id', default=False, action="store_true", help=_('Print full IDs in list') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering columns = ['id', 'name', 'type', 'created_at'] queries = { 'limit': parsed_args.limit, 'marker': parsed_args.marker, 'sort': parsed_args.sort, 'global_project': parsed_args.global_project, } if parsed_args.filters: queries.update(senlin_utils.format_parameters(parsed_args.filters)) data = senlin_client.profiles(**queries) formatters = {} if parsed_args.global_project: columns.append('project_id') if not parsed_args.full_id: formatters = { 'id': lambda x: x[:8], } if 'project_id' in columns: formatters['project_id'] = lambda x: x[:8] return ( columns, (utils.get_item_properties(p, columns, formatters=formatters) for p in data) ) class DeleteProfile(command.Command): """Delete profile(s).""" log = logging.getLogger(__name__ + ".DeleteProfile") def get_parser(self, prog_name): parser = super(DeleteProfile, self).get_parser(prog_name) parser.add_argument( 'profile', metavar='', nargs='+', help=_('Name or ID of profile(s) to delete') ) parser.add_argument( '--force', action='store_true', help=_('Skip yes/no prompt (assume yes)') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering try: if not parsed_args.force and sys.stdin.isatty(): sys.stdout.write( _("Are you sure you want to delete this profile(s)" " [y/N]?")) prompt_response = sys.stdin.readline().lower() if not prompt_response.startswith('y'): return except KeyboardInterrupt: # Ctrl-c self.log.info('Ctrl-c detected.') return except EOFError: # Ctrl-d self.log.info('Ctrl-d detected') return failure_count = 0 for pid in parsed_args.profile: try: senlin_client.delete_profile(pid, False) except Exception as ex: failure_count += 1 print(ex) if failure_count: raise exc.CommandError(_('Failed to delete %(count)s of the ' '%(total)s specified profile(s).') % {'count': failure_count, 'total': len(parsed_args.profile)}) print('Profile deleted: %s' % parsed_args.profile) class CreateProfile(command.ShowOne): """Create a profile.""" log = logging.getLogger(__name__ + ".CreateProfile") def get_parser(self, prog_name): parser = super(CreateProfile, self).get_parser(prog_name) parser.add_argument( '--metadata', metavar='<"key1=value1;key2=value2...">', help=_('Metadata values to be attached to the profile. ' 'This can be specified multiple times, or once with ' 'key-value pairs separated by a semicolon'), action='append' ) parser.add_argument( '--spec-file', metavar='', required=True, help=_('The spec file used to create the profile') ) parser.add_argument( 'name', metavar='', help=_('Name of the profile to create') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering spec = senlin_utils.get_spec_content(parsed_args.spec_file) type_name = spec.get('type', None) type_version = spec.get('version', None) properties = spec.get('properties', None) if type_name is None: raise exc.CommandError(_("Missing 'type' key in spec file.")) if type_version is None: raise exc.CommandError(_("Missing 'version' key in spec file.")) if properties is None: raise exc.CommandError(_("Missing 'properties' key in spec file.")) if type_name == 'os.heat.stack': stack_properties = senlin_utils.process_stack_spec(properties) spec['properties'] = stack_properties params = { 'name': parsed_args.name, 'spec': spec, 'metadata': senlin_utils.format_parameters(parsed_args.metadata), } profile = senlin_client.create_profile(**params) return _show_profile(senlin_client, profile_id=profile.id) class UpdateProfile(command.ShowOne): """Update a profile.""" log = logging.getLogger(__name__ + ".UpdateProfile") def get_parser(self, prog_name): parser = super(UpdateProfile, self).get_parser(prog_name) parser.add_argument( '--name', metavar='', help=_('The new name for the profile') ) parser.add_argument( '--metadata', metavar='<"key1=value1;key2=value2...">', help=_("Metadata values to be attached to the profile. " "This can be specified multiple times, or once with " "key-value pairs separated by a semicolon. Use '{}' " "can clean metadata "), action='append' ) parser.add_argument( 'profile', metavar='', help=_('Name or ID of the profile to update') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering params = { 'name': parsed_args.name, } if parsed_args.metadata: params['metadata'] = senlin_utils.format_parameters( parsed_args.metadata) # Find the profile first, we need its id profile = senlin_client.find_profile(parsed_args.profile) if profile is None: raise exc.CommandError(_('Profile not found: %s') % parsed_args.profile) senlin_client.update_profile(profile.id, **params) return _show_profile(senlin_client, profile_id=profile.id) class ValidateProfile(command.ShowOne): """Validate a profile.""" log = logging.getLogger(__name__ + ".ValidateProfile") def get_parser(self, prog_name): parser = super(ValidateProfile, self).get_parser(prog_name) parser.add_argument( '--spec-file', metavar='', required=True, help=_('The spec file of the profile to be validated') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering spec = senlin_utils.get_spec_content(parsed_args.spec_file) type_name = spec.get('type', None) type_version = spec.get('version', None) properties = spec.get('properties', None) if type_name is None: raise exc.CommandError(_("Missing 'type' key in spec file.")) if type_version is None: raise exc.CommandError(_("Missing 'version' key in spec file.")) if properties is None: raise exc.CommandError(_("Missing 'properties' key in spec file.")) if type_name == 'os.heat.stack': stack_properties = senlin_utils.process_stack_spec(properties) spec['properties'] = stack_properties params = { 'spec': spec, } profile = senlin_client.validate_profile(**params) formatters = {} formatters['metadata'] = senlin_utils.json_formatter formatters['spec'] = senlin_utils.nested_dict_formatter( ['type', 'version', 'properties'], ['property', 'value']) columns = [ 'created_at', 'domain', 'id', 'metadata', 'name', 'project_id', 'spec', 'type', 'updated_at', 'user_id' ] return columns, utils.get_dict_properties(profile.to_dict(), columns, formatters=formatters) python-senlinclient-1.7.0/senlinclient/v1/client.py0000666000175100017510000003675713234643473022453 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from openstack import exceptions from senlinclient.common import exc from senlinclient import plugin class Client(object): def __init__(self, prof=None, user_agent=None, **kwargs): try: conn = plugin.create_connection(prof=prof, user_agent=user_agent, **kwargs) except exceptions.HttpException as ex: exc.parse_exception(ex.details) self.conn = conn self.service = self.conn.cluster ###################################################################### # The following operations are interfaces exposed to other software # which invokes senlinclient today. # These methods form a temporary translation layer. This layer will be # useless when OpenStackSDK has been adopted all senlin resources. ###################################################################### def profile_types(self, **query): """List profile types Doc link: https://developer.openstack.org/api-ref/clustering/#list-profile-types """ return self.service.profile_types(**query) def get_profile_type(self, profile_type): """Show profile type details Doc link: https://developer.openstack.org/api-ref/clustering/ #show-profile-type-details """ return self.service.get_profile_type(profile_type) def list_profile_type_operations(self, profile_type): """Show profile type operations Doc link: https://developer.openstack.org/api-ref/clustering/ #show-profile-type-details """ return self.service.list_profile_type_operations(profile_type) def profiles(self, **query): """List profiles Doc link: https://developer.openstack.org/api-ref/clustering/#list-profiles """ return self.service.profiles(**query) def create_profile(self, **attrs): """Create a profile Doc link: https://developer.openstack.org/api-ref/clustering/#create-profile """ return self.service.create_profile(**attrs) def get_profile(self, profile): """Show profile details Doc link: https://developer.openstack.org/api-ref/clustering/#show-profile-details """ return self.service.get_profile(profile) def update_profile(self, profile, **attrs): """Update a profile Doc link: https://developer.openstack.org/api-ref/clustering/#update-profile """ return self.service.update_profile(profile, **attrs) def delete_profile(self, profile, ignore_missing=True): """Delete a profile Doc link: https://developer.openstack.org/api-ref/clustering/#delete-profile """ return self.service.delete_profile(profile, ignore_missing) def validate_profile(self, **attrs): """Validate a profile spec Doc link: https://developer.openstack.org/api-ref/clustering/#validate-profile """ return self.service.validate_profile(**attrs) def policy_types(self, **query): """List policy types Doc link: https://developer.openstack.org/api-ref/clustering/#list-policy-types """ return self.service.policy_types(**query) def get_policy_type(self, policy_type): """Show policy type details Doc link: https://developer.openstack.org/api-ref/clustering/ #show-policy-type-details """ return self.service.get_policy_type(policy_type) def policies(self, **query): """List policies Doc link: https://developer.openstack.org/api-ref/clustering/#list-policies """ return self.service.policies(**query) def create_policy(self, **attrs): """Create a policy Doc link: https://developer.openstack.org/api-ref/clustering/#create-policy """ return self.service.create_policy(**attrs) def get_policy(self, policy): """Show policy details Doc link: https://developer.openstack.org/api-ref/clustering/#show-policy-details """ return self.service.get_policy(policy) def update_policy(self, policy, **attrs): """Update policy Doc link: https://developer.openstack.org/api-ref/clustering/#update-policy """ return self.service.update_policy(policy, **attrs) def delete_policy(self, policy, ignore_missing=True): """Delete policy Doc link: https://developer.openstack.org/api-ref/clustering/#delete-policy """ return self.service.delete_policy(policy, ignore_missing) def validate_policy(self, **attrs): """validate a policy spec Doc link: https://developer.openstack.org/api-ref/clustering/#validate-policy """ return self.service.validate_policy(**attrs) def clusters(self, **queries): """List clusters Doc link: https://developer.openstack.org/api-ref/clustering/#list-clusters """ return self.service.clusters(**queries) def create_cluster(self, **attrs): """Create a cluster Doc link: https://developer.openstack.org/api-ref/clustering/#create-cluster """ return self.service.create_cluster(**attrs) def get_cluster(self, cluster): """Show cluster details Doc link: https://developer.openstack.org/api-ref/clustering/#show-cluster-details """ return self.service.get_cluster(cluster) def update_cluster(self, cluster, **attrs): """Update cluster Doc link: https://developer.openstack.org/api-ref/clustering/#update-cluster """ return self.service.update_cluster(cluster, **attrs) def delete_cluster(self, cluster, ignore_missing=True, force_delete=False): """Delete cluster Doc link: https://developer.openstack.org/api-ref/clustering/#delete-cluster """ return self.service.delete_cluster(cluster, ignore_missing, force_delete) def cluster_add_nodes(self, cluster, nodes): """Add a node to cluster Doc link: https://developer.openstack.org/api-ref/clustering/ #add-nodes-to-a-cluster """ return self.service.cluster_add_nodes(cluster, nodes) def cluster_del_nodes(self, cluster, nodes): """Delete a node belongs to cluster Doc link: https://developer.openstack.org/api-ref/clustering/ #remove-nodes-from-a-cluster """ return self.service.cluster_del_nodes(cluster, nodes) def cluster_replace_nodes(self, cluster, nodes): """Replace the nodes in a cluster with specified nodes Doc link: https://developer.openstack.org/api-ref/clustering/ #replace-nodes-in-a-cluster """ return self.service.cluster_replace_nodes(cluster, nodes) def cluster_resize(self, cluster, **params): """Resize cluster Doc link: https://developer.openstack.org/api-ref/clustering/#resize-a-cluster """ return self.service.cluster_resize(cluster, **params) def cluster_scale_out(self, cluster, count): """Scale out cluster Doc link: https://developer.openstack.org/api-ref/clustering/#scale-out-a-cluster """ return self.service.cluster_scale_out(cluster, count) def cluster_scale_in(self, cluster, count): """Scale in cluster Doc link: https://developer.openstack.org/api-ref/clustering/#scale-in-a-cluster """ return self.service.cluster_scale_in(cluster, count) def cluster_policies(self, cluster, **queries): """List all policies attached to cluster Doc link: https://developer.openstack.org/api-ref/clustering/ #list-all-cluster-policies """ return self.service.cluster_policies(cluster, **queries) def get_cluster_policy(self, policy, cluster): """Show details of a policy attached to cluster Doc link: https://developer.openstack.org/api-ref/clustering/ #show-cluster-policy-details """ return self.service.get_cluster_policy(policy, cluster) def cluster_attach_policy(self, cluster, policy, **attrs): """Attach a policy to cluster Doc link: https://developer.openstack.org/api-ref/clustering/ #attach-a-policy-to-a-cluster """ return self.service.cluster_attach_policy(cluster, policy, **attrs) def cluster_detach_policy(self, cluster, policy): """Detach a policy from cluster Doc link: https://developer.openstack.org/api-ref/clustering/ #detach-a-policy-from-a-cluster """ return self.service.cluster_detach_policy(cluster, policy) def cluster_update_policy(self, cluster, policy, **attrs): """Update the policy attachment Doc link: https://developer.openstack.org/api-ref/clustering/ #update-a-policy-on-a-cluster """ return self.service.cluster_update_policy(cluster, policy, **attrs) def collect_cluster_attrs(self, cluster, path): """Collect cluster attributes Doc link: https://developer.openstack.org/api-ref/clustering/ #collect-attributes-across-a-cluster """ return self.service.collect_cluster_attrs(cluster, path) def check_cluster(self, cluster, **params): """Check cluster's health status Doc link: https://developer.openstack.org/api-ref/clustering/ #check-a-cluster-s-health-status """ return self.service.check_cluster(cluster, **params) def recover_cluster(self, cluster, **params): """Recover cluster from failure state Doc link: https://developer.openstack.org/api-ref/clustering/ #recover-a-cluster-to-a-healthy-status """ return self.service.recover_cluster(cluster, **params) def perform_operation_on_cluster(self, cluster, operation, **params): """Perform an operation on a cluster. Doc link: https://developer.openstack.org/api-ref/clustering/ #perform-an-operation-on-a-cluster """ return self.service.perform_operation_on_cluster(cluster, operation, **params) def nodes(self, **queries): """List nodes Doc link: https://developer.openstack.org/api-ref/clustering/#list-nodes """ return self.service.nodes(**queries) def create_node(self, **attrs): """Create a node Doc link: https://developer.openstack.org/api-ref/clustering/#create-node """ return self.service.create_node(**attrs) def adopt_node(self, preview=False, **attrs): """Adopt a node Doc link: https://developer.openstack.org/api-ref/clustering/#adopt-node https://developer.openstack.org/api-ref/clustering/#adopt-node-preview """ return self.service.adopt_node(preview, **attrs) def get_node(self, node, details=False): """Show node details Doc link: https://developer.openstack.org/api-ref/clustering/#show-node-details """ return self.service.get_node(node, details=details) def update_node(self, node, **attrs): """Update node Doc link: https://developer.openstack.org/api-ref/clustering/#update-node """ return self.service.update_node(node, **attrs) def delete_node(self, node, ignore_missing=True, force_delete=False): """Delete node Doc link: https://developer.openstack.org/api-ref/clustering/#delete-node """ return self.service.delete_node(node, ignore_missing, force_delete) def check_node(self, node, **params): """Check node's health status Doc link: https://developer.openstack.org/api-ref/clustering/#check-a-node-s-health """ return self.service.check_node(node, **params) def recover_node(self, node, **params): """Recover node from failure state Doc link: https://developer.openstack.org/api-ref/clustering/ #recover-a-node-to-healthy-status """ return self.service.recover_node(node, **params) def perform_operation_on_node(self, node, operation, **params): """Perform an operation on a node. Doc link: https://developer.openstack.org/api-ref/clustering/ #perform-an-operation-on-a-node """ return self.service.perform_operation_on_node(node, operation, **params) def receivers(self, **queries): """List receivers Doc link: https://developer.openstack.org/api-ref/clustering/#list-receivers """ return self.service.receivers(**queries) def create_receiver(self, **attrs): """Creare a receiver Doc link: https://developer.openstack.org/api-ref/clustering/#create-receiver """ return self.service.create_receiver(**attrs) def get_receiver(self, receiver): """Show receiver details Doc link: https://developer.openstack.org/api-ref/clustering/#show-receiver-details """ return self.service.get_receiver(receiver) def update_receiver(self, receiver, **attrs): """Update receiver Doc link: http://developer.openstack.org/api-ref-clustering-v1.html#updateReceiver """ return self.service.update_receiver(receiver, **attrs) def delete_receiver(self, receiver, ignore_missing=True): """Delete receiver Doc link: https://developer.openstack.org/api-ref/clustering/#delete-receiver """ return self.service.delete_receiver(receiver, ignore_missing) def events(self, **queries): """List events Doc link: https://developer.openstack.org/api-ref/clustering/#list-events """ return self.service.events(**queries) def get_event(self, event): """Show event details Doc link: https://developer.openstack.org/api-ref/clustering/#shows-event-details """ return self.service.get_event(event) def actions(self, **queries): """List actions Doc link: https://developer.openstack.org/api-ref/clustering/#list-actions """ return self.service.actions(**queries) def get_action(self, action): """Show action details Doc link: https://developer.openstack.org/api-ref/clustering/#show-action-details """ return self.service.get_action(action) def services(self, **queries): """List services Doc link: https://developer.openstack.org/api-ref/clustering/#list-services """ return self.service.services(**queries) python-senlinclient-1.7.0/senlinclient/v1/receiver.py0000666000175100017510000002605513234643473022767 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Clustering v1 receiver action implementations""" import logging import sys from openstack import exceptions as sdk_exc from osc_lib.command import command from osc_lib import exceptions as exc from osc_lib import utils from senlinclient.common.i18n import _ from senlinclient.common import utils as senlin_utils class ListReceiver(command.Lister): """List receivers that meet the criteria.""" log = logging.getLogger(__name__ + ".ListReceiver") def get_parser(self, prog_name): parser = super(ListReceiver, self).get_parser(prog_name) parser.add_argument( '--filters', metavar='<"key1=value1;key2=value2...">', help=_("Filter parameters to apply on returned receivers. " "This can be specified multiple times, or once with " "parameters separated by a semicolon. The valid filter " "keys are: ['name', 'type', 'action', 'cluster_id', " "'user_id']"), action='append' ) parser.add_argument( '--limit', metavar='', help=_('Limit the number of receivers returned') ) parser.add_argument( '--marker', metavar='', help=_('Only return receivers that appear after the given ' 'receiver ID') ) parser.add_argument( '--sort', metavar='[:]', help=_("Sorting option which is a string containing a list of " "keys separated by commas. Each key can be optionally " "appended by a sort direction (:asc or :desc). The valid " "sort keys are: ['name', 'type', 'action', 'cluster_id', " "'created_at']") ) parser.add_argument( '--global-project', default=False, action="store_true", help=_('Indicate that the list should include receivers from' ' all projects. This option is subject to access policy ' 'checking. Default is False') ) parser.add_argument( '--full-id', default=False, action="store_true", help=_('Print full IDs in list') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering columns = ['id', 'name', 'type', 'cluster_id', 'action', 'created_at'] queries = { 'limit': parsed_args.limit, 'marker': parsed_args.marker, 'sort': parsed_args.sort, 'global_project': parsed_args.global_project, } if parsed_args.filters: queries.update(senlin_utils.format_parameters(parsed_args.filters)) receivers = senlin_client.receivers(**queries) formatters = {} if parsed_args.global_project: columns.append('project_id') columns.append('user_id') if not parsed_args.full_id: formatters = { 'id': lambda x: x[:8], 'cluster_id': lambda x: x[:8] if x else None, } if 'project_id' in columns: formatters['project_id'] = lambda x: x[:8] formatters['user_id'] = lambda x: x[:8] return ( columns, (utils.get_item_properties(r, columns, formatters=formatters) for r in receivers) ) class ShowReceiver(command.ShowOne): """Show the receiver details.""" log = logging.getLogger(__name__ + ".ShowReceiver") def get_parser(self, prog_name): parser = super(ShowReceiver, self).get_parser(prog_name) parser.add_argument( 'receiver', metavar='', help=_('Name or ID of the receiver to show') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering return _show_receiver(senlin_client, parsed_args.receiver) def _show_receiver(senlin_client, receiver_id): try: receiver = senlin_client.get_receiver(receiver_id) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Receiver not found: %s') % receiver_id) formatters = { 'actor': senlin_utils.json_formatter, 'params': senlin_utils.json_formatter, 'channel': senlin_utils.json_formatter, } data = receiver.to_dict() columns = sorted(data.keys()) return columns, utils.get_dict_properties(data, columns, formatters=formatters) class CreateReceiver(command.ShowOne): """Create a receiver.""" log = logging.getLogger(__name__ + ".CreateReceiver") def get_parser(self, prog_name): parser = super(CreateReceiver, self).get_parser(prog_name) parser.add_argument( '--type', metavar='', default='webhook', help=_('Type of the receiver to create. Receiver type can be ' '"webhook" or "message". Default to "webhook".') ) parser.add_argument( '--params', metavar='<"key1=value1;key2=value2...">', help=_('A dictionary of parameters that will be passed to target ' 'action when the receiver is triggered'), action='append' ) parser.add_argument( '--cluster', metavar='', help=_('Targeted cluster for this receiver. Required if ' 'receiver type is webhook') ) parser.add_argument( '--action', metavar='', help=_('Name or ID of the targeted action to be triggered. ' 'Required if receiver type is webhook') ) parser.add_argument( 'name', metavar='', help=_('Name of the receiver to create') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) if parsed_args.type == 'webhook': if (not parsed_args.cluster or not parsed_args.action): msg = _('cluster and action parameters are required to create ' 'webhook type of receiver.') raise exc.CommandError(msg) senlin_client = self.app.client_manager.clustering params = { 'name': parsed_args.name, 'type': parsed_args.type, 'cluster_id': parsed_args.cluster, 'action': parsed_args.action, 'params': senlin_utils.format_parameters(parsed_args.params) } receiver = senlin_client.create_receiver(**params) return _show_receiver(senlin_client, receiver.id) class UpdateReceiver(command.ShowOne): """Update a receiver.""" log = logging.getLogger(__name__ + ".UpdateReceiver") def get_parser(self, prog_name): parser = super(UpdateReceiver, self).get_parser(prog_name) parser.add_argument( '--name', metavar='', help=_('Name of the receiver to create') ) parser.add_argument( '--action', metavar='', help=_('Name or ID of the targeted action to be triggered. ' 'Required if receiver type is webhook') ) parser.add_argument( '--params', metavar='<"key1=value1;key2=value2...">', help=_('A dictionary of parameters that will be passed to target ' 'action when the receiver is triggered'), action='append' ) parser.add_argument( 'receiver', metavar='', help=_('Name or ID of receiver(s) to update') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering params = { 'name': parsed_args.name, 'params': senlin_utils.format_parameters(parsed_args.params) } if parsed_args.action: params['action'] = parsed_args.action receiver = senlin_client.find_receiver(parsed_args.receiver) if receiver is None: raise exc.CommandError(_('Receiver not found: %s') % parsed_args.receiver) senlin_client.update_receiver(receiver.id, **params) return _show_receiver(senlin_client, receiver_id=receiver.id) class DeleteReceiver(command.Command): """Delete receiver(s).""" log = logging.getLogger(__name__ + ".DeleteReceiver") def get_parser(self, prog_name): parser = super(DeleteReceiver, self).get_parser(prog_name) parser.add_argument( 'receiver', metavar='', nargs='+', help=_('Name or ID of receiver(s) to delete') ) parser.add_argument( '--force', action='store_true', help=_('Skip yes/no prompt (assume yes)') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering try: if not parsed_args.force and sys.stdin.isatty(): sys.stdout.write( _("Are you sure you want to delete this receiver(s)" " [y/N]?")) prompt_response = sys.stdin.readline().lower() if not prompt_response.startswith('y'): return except KeyboardInterrupt: # Ctrl-c self.log.info('Ctrl-c detected.') return except EOFError: # Ctrl-d self.log.info('Ctrl-d detected') return failure_count = 0 for rid in parsed_args.receiver: try: senlin_client.delete_receiver(rid, False) except Exception as ex: failure_count += 1 print(ex) if failure_count: raise exc.CommandError(_('Failed to delete %(count)s of the ' '%(total)s specified receiver(s).') % {'count': failure_count, 'total': len(parsed_args.receiver)}) print('Receiver deleted: %s' % parsed_args.receiver) python-senlinclient-1.7.0/senlinclient/v1/event.py0000666000175100017510000001201613234643473022274 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Clustering v1 event action implementations""" import logging from openstack import exceptions as sdk_exc from osc_lib.command import command from osc_lib import exceptions as exc from osc_lib import utils from senlinclient.common.i18n import _ from senlinclient.common import utils as senlin_utils class ListEvent(command.Lister): """List events.""" log = logging.getLogger(__name__ + ".ListEvent") def get_parser(self, prog_name): parser = super(ListEvent, self).get_parser(prog_name) parser.add_argument( '--filters', metavar='<"key1=value1;key2=value2...">', help=_("Filter parameters to apply on returned events. " "This can be specified multiple times, or once with " "parameters separated by a semicolon. The valid filter " "keys are: ['level', 'otype', 'oid' ,'cluster_id', " "'oname', 'action']. " "NOTICE: The value of 'oid' or 'cluster_id', " "if provided, must be a full ID."), action='append' ) parser.add_argument( '--limit', metavar='', help=_('Limit the number of events returned') ) parser.add_argument( '--marker', metavar='', help=_('Only return events that appear after the given event ID') ) parser.add_argument( '--sort', metavar='[:]', help=_("Sorting option which is a string containing a list of " "keys separated by commas. Each key can be optionally " "appended by a sort direction (:asc or :desc). The valid " "sort keys are: ['timestamp', 'level', 'oid', 'otype', " "'oname', 'action', 'status']") ) parser.add_argument( '--global-project', default=False, action="store_true", help=_('Whether events from all projects should be listed. ' ' Default to False. Setting this to True may demand ' 'for an admin privilege') ) parser.add_argument( '--full-id', default=False, action="store_true", help=_('Print full IDs in list') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering columns = ['id', 'generated_at', 'obj_type', 'obj_id', 'obj_name', 'action', 'status', 'level', 'cluster_id'] queries = { 'sort': parsed_args.sort, 'limit': parsed_args.limit, 'marker': parsed_args.marker, 'global_project': parsed_args.global_project, } if parsed_args.filters: queries.update(senlin_utils.format_parameters(parsed_args.filters)) formatters = {} if parsed_args.global_project: columns.append('project_id') if not parsed_args.full_id: formatters['id'] = lambda x: x[:8] formatters['obj_id'] = lambda x: x[:8] if x else '' if 'project_id' in columns: formatters['project_id'] = lambda x: x[:8] formatters['cluster_id'] = lambda x: x[:8] if x else '' events = senlin_client.events(**queries) return (columns, (utils.get_item_properties(e, columns, formatters=formatters) for e in events)) class ShowEvent(command.ShowOne): """Describe the event.""" log = logging.getLogger(__name__ + ".ShowEvent") def get_parser(self, prog_name): parser = super(ShowEvent, self).get_parser(prog_name) parser.add_argument( 'event', metavar='', help=_('ID of event to display details for') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering try: event = senlin_client.get_event(parsed_args.event) except sdk_exc.ResourceNotFound: raise exc.CommandError(_("Event not found: %s") % parsed_args.event) data = event.to_dict() columns = sorted(data.keys()) return columns, utils.get_dict_properties(data, columns) python-senlinclient-1.7.0/senlinclient/v1/profile_type.py0000666000175100017510000000710713234643473023661 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Clustering v1 profile type action implementations""" import logging from openstack import exceptions as sdk_exc from osc_lib.command import command from osc_lib import exceptions as exc from senlinclient.common import format_utils from senlinclient.common.i18n import _ class ProfileTypeList(command.Lister): """List the available profile types.""" log = logging.getLogger(__name__ + ".ProfileTypeList") def get_parser(self, prog_name): parser = super(ProfileTypeList, self).get_parser(prog_name) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering types = senlin_client.profile_types() columns = ['name', 'version', 'support_status'] results = [] for t in types: for v in t.support_status.keys(): st_list = '\n'.join([ ' since '.join((item['status'], item['since'])) for item in t.support_status[v] ]) results.append((t.name, v, st_list)) return columns, sorted(results) class ProfileTypeShow(format_utils.YamlFormat): """Show the details about a profile type.""" log = logging.getLogger(__name__ + ".ProfileTypeShow") def get_parser(self, prog_name): parser = super(ProfileTypeShow, self).get_parser(prog_name) parser.add_argument( 'type_name', metavar='', help=_('Profile type to retrieve') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering try: res = senlin_client.get_profile_type(parsed_args.type_name) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Profile Type not found: %s') % parsed_args.type_name) data = res.to_dict() rows = data.values() columns = data.keys() return columns, rows class ProfileTypeOperations(format_utils.YamlFormat): """Show the operations about a profile type.""" log = logging.getLogger(__name__ + ".ProfileTypeOperations") def get_parser(self, prog_name): parser = super(ProfileTypeOperations, self).get_parser(prog_name) parser.add_argument( 'type_name', metavar='', help=_('Profile type to retrieve') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering try: ops = senlin_client.list_profile_type_operations( parsed_args.type_name) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Profile Type not found: %s') % parsed_args.type_name) rows = ops.values() columns = ops.keys() return columns, rows python-senlinclient-1.7.0/senlinclient/v1/__init__.py0000666000175100017510000000000013234643473022700 0ustar zuulzuul00000000000000python-senlinclient-1.7.0/senlinclient/v1/policy_type.py0000666000175100017510000000514713234643473023522 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Clustering v1 policy type action implementations""" import logging from openstack import exceptions as sdk_exc from osc_lib.command import command from osc_lib import exceptions as exc from senlinclient.common import format_utils from senlinclient.common.i18n import _ class PolicyTypeList(command.Lister): """List the available policy types.""" log = logging.getLogger(__name__ + ".PolicyTypeList") def get_parser(self, prog_name): parser = super(PolicyTypeList, self).get_parser(prog_name) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering types = senlin_client.policy_types() columns = ['name', 'version', 'support_status'] results = [] for t in types: for v in t.support_status.keys(): st_list = '\n'.join([ ' since '.join((item['status'], item['since'])) for item in t.support_status[v] ]) results.append((t.name, v, st_list)) return columns, sorted(results) class PolicyTypeShow(format_utils.YamlFormat): """Get the details about a policy type.""" log = logging.getLogger(__name__ + ".PolicyTypeShow") def get_parser(self, prog_name): parser = super(PolicyTypeShow, self).get_parser(prog_name) parser.add_argument( 'type_name', metavar='', help=_('Policy type to retrieve') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering try: res = senlin_client.get_policy_type(parsed_args.type_name) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Policy Type not found: %s') % parsed_args.type_name) data = res.to_dict() rows = data.values() columns = data.keys() return columns, rows python-senlinclient-1.7.0/senlinclient/v1/node.py0000666000175100017510000004441413234643473022107 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Clustering v1 node action implementations""" import logging import sys from openstack import exceptions as sdk_exc from osc_lib.command import command from osc_lib import exceptions as exc from osc_lib import utils from oslo_utils import strutils import six from senlinclient.common.i18n import _ from senlinclient.common import utils as senlin_utils class ListNode(command.Lister): """Show list of nodes.""" log = logging.getLogger(__name__ + ".ListNode") def get_parser(self, prog_name): parser = super(ListNode, self).get_parser(prog_name) parser.add_argument( '--cluster', metavar='', help=_('ID or name of cluster from which nodes are to be listed') ) parser.add_argument( '--filters', metavar='<"key1=value1;key2=value2...">', help=_("Filter parameters to apply on returned nodes. " "This can be specified multiple times, or once with " "parameters separated by a semicolon. The valid filter" " keys are: ['status','name']"), action='append' ) parser.add_argument( '--sort', metavar='[:]', help=_("Sorting option which is a string containing a list of " "keys separated by commas. Each key can be optionally " "appended by a sort direction (:asc or :desc). The valid " "sort keys are:['index', 'name', 'status', 'init_at', " "'created_at', 'updated_at']") ) parser.add_argument( '--limit', metavar='', help=_('Limit the number of nodes returned') ) parser.add_argument( '--marker', metavar='', help=_('Only return nodes that appear after the given node ID') ) parser.add_argument( '--global-project', default=False, action="store_true", help=_('Indicate that this node list should include nodes from ' 'all projects. This option is subject to access policy ' 'checking. Default is False') ) parser.add_argument( '--full-id', default=False, action="store_true", help=_('Print full IDs in list') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering columns = ['id', 'name', 'index', 'status', 'cluster_id', 'physical_id', 'profile_name', 'created_at', 'updated_at'] queries = { 'cluster_id': parsed_args.cluster, 'sort': parsed_args.sort, 'limit': parsed_args.limit, 'marker': parsed_args.marker, 'global_project': parsed_args.global_project, } if parsed_args.filters: queries.update(senlin_utils.format_parameters(parsed_args.filters)) nodes = senlin_client.nodes(**queries) if parsed_args.global_project: columns.append('project_id') if not parsed_args.full_id: formatters = { 'id': lambda x: x[:8], 'cluster_id': lambda x: x[:8] if x else '', 'physical_id': lambda x: x[:8] if x else '' } if 'project_id' in columns: formatters['project_id'] = lambda x: x[:8] else: formatters = {} return ( columns, (utils.get_item_properties(n, columns, formatters=formatters) for n in nodes) ) class ShowNode(command.ShowOne): """Show detailed info about the specified node.""" log = logging.getLogger(__name__ + ".ShowNode") def get_parser(self, prog_name): parser = super(ShowNode, self).get_parser(prog_name) parser.add_argument( '--details', default=False, action="store_true", help=_('Include physical object details') ) parser.add_argument( 'node', metavar='', help=_('Name or ID of the node to show the details for') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering return _show_node(senlin_client, parsed_args.node, parsed_args.details) def _show_node(senlin_client, node_id, show_details=False): """Show detailed info about the specified node.""" try: node = senlin_client.get_node(node_id, details=show_details) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Node not found: %s') % node_id) formatters = { 'metadata': senlin_utils.json_formatter, 'data': senlin_utils.json_formatter, 'dependents': senlin_utils.json_formatter, } data = node.to_dict() if show_details and data['details']: formatters['details'] = senlin_utils.nested_dict_formatter( list(data['details'].keys()), ['property', 'value']) columns = sorted(data.keys()) return columns, utils.get_dict_properties(data, columns, formatters=formatters) class CreateNode(command.ShowOne): """Create the node.""" log = logging.getLogger(__name__ + ".CreateNode") def get_parser(self, prog_name): parser = super(CreateNode, self).get_parser(prog_name) parser.add_argument( '--cluster', metavar='', help=_('Cluster Id or Name for this node') ) parser.add_argument( '--role', metavar='', help=_('Role for this node in the specific cluster') ) parser.add_argument( '--metadata', metavar='<"key1=value1;key2=value2...">', help=_('Metadata values to be attached to the node. ' 'This can be specified multiple times, or once with ' 'key-value pairs separated by a semicolon'), action='append' ) parser.add_argument( '--profile', metavar='', required=True, help=_('Profile Id or Name used for this node') ) parser.add_argument( 'name', metavar='', help=_('Name of the node to create') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering attrs = { 'name': parsed_args.name, 'cluster_id': parsed_args.cluster, 'profile_id': parsed_args.profile, 'role': parsed_args.role, 'metadata': senlin_utils.format_parameters(parsed_args.metadata), } node = senlin_client.create_node(**attrs) return _show_node(senlin_client, node.id) class UpdateNode(command.ShowOne): """Update the node.""" log = logging.getLogger(__name__ + ".UpdateNode") def get_parser(self, prog_name): parser = super(UpdateNode, self).get_parser(prog_name) parser.add_argument( '--name', metavar='', help=_('New name for the node') ) parser.add_argument( '--profile', metavar='', help=_('ID or name of new profile to use') ) parser.add_argument( '--role', metavar='', help=_('Role for this node in the specific cluster') ) parser.add_argument( '--metadata', metavar='<"key1=value1;key2=value2...">', help=_("Metadata values to be attached to the node. " "This can be specified multiple times, or once with " "key-value pairs separated by a semicolon. Use '{}' " "can clean metadata "), action='append' ) parser.add_argument( 'node', metavar='', help=_('Name or ID of node to update') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering # Find the node first, we need its UUID node = senlin_client.find_node(parsed_args.node) if node is None: raise exc.CommandError(_('Node not found: %s') % parsed_args.node) attrs = { 'name': parsed_args.name, 'role': parsed_args.role, 'profile_id': parsed_args.profile, 'metadata': senlin_utils.format_parameters(parsed_args.metadata), } senlin_client.update_node(node.id, **attrs) return _show_node(senlin_client, node.id) class DeleteNode(command.Command): """Delete the node(s).""" log = logging.getLogger(__name__ + ".DeleteNode") def get_parser(self, prog_name): parser = super(DeleteNode, self).get_parser(prog_name) parser.add_argument( 'node', metavar='', nargs='+', help=_('Name or ID of node(s) to delete.') ) parser.add_argument( '--force-delete', action='store_true', help=_('Force to delete node(s).') ) parser.add_argument( '--force', action='store_true', help=_('Skip yes/no prompt (assume yes).') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering try: if not parsed_args.force and sys.stdin.isatty(): sys.stdout.write( _("Are you sure you want to delete this node(s)" " [y/N]?")) prompt_response = sys.stdin.readline().lower() if not prompt_response.startswith('y'): return except KeyboardInterrupt: # Ctrl-c self.log.info('Ctrl-c detected.') return except EOFError: # Ctrl-d self.log.info('Ctrl-d detected') return result = {} for nid in parsed_args.node: try: node = senlin_client.delete_node( nid, False, parsed_args.force_delete) result[nid] = ('OK', node.location.split('/')[-1]) except Exception as ex: result[nid] = ('ERROR', six.text_type(ex)) for rid, res in result.items(): senlin_utils.print_action_result(rid, res) class CheckNode(command.Command): """Check the node(s).""" log = logging.getLogger(__name__ + ".CheckNode") def get_parser(self, prog_name): parser = super(CheckNode, self).get_parser(prog_name) parser.add_argument( 'node', metavar='', nargs='+', help=_('ID or name of node(s) to check.') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering for nid in parsed_args.node: try: resp = senlin_client.check_node(nid) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Node not found: %s') % nid) print('Node check request on node %(nid)s is accepted by ' 'action %(action)s.' % {'nid': nid, 'action': resp['action']}) class RecoverNode(command.Command): """Recover the node(s).""" log = logging.getLogger(__name__ + ".RecoverNode") def get_parser(self, prog_name): parser = super(RecoverNode, self).get_parser(prog_name) parser.add_argument( '--check', metavar='', default=False, help=_('Whether the node(s) should check physical resource status ' 'before doing node recover. Default is false') ) parser.add_argument( 'node', metavar='', nargs='+', help=_('ID or name of node(s) to recover.') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering params = { 'check': strutils.bool_from_string(parsed_args.check, strict=True) } for nid in parsed_args.node: try: resp = senlin_client.recover_node(nid, **params) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Node not found: %s') % nid) print('Node recover request on node %(nid)s is accepted by ' 'action %(action)s.' % {'nid': nid, 'action': resp['action']}) class AdoptNode(command.ShowOne): """Adopt (or preview) the node.""" log = logging.getLogger(__name__ + ".AdoptNode") def get_parser(self, prog_name): parser = super(AdoptNode, self).get_parser(prog_name) parser.add_argument( '--identity', metavar='', required=True, help=_('Physical resource id.')) parser.add_argument( '--type', metavar='', required=True, help=_('The name of the profile type.') ) parser.add_argument( '--role', metavar='', help=_('Role for this node in the specific cluster.') ) parser.add_argument( '--metadata', metavar='<"key1=value1;key2=value2...">', help=_('Metadata values to be attached to the node. ' 'This can be specified multiple times, or once with ' 'key-value pairs separated by a semicolon.'), action='append' ) parser.add_argument( '--name', metavar='', help=_('Name of the node to adopt.') ) parser.add_argument( '--overrides', metavar='', help=_('JSON formatted specification for overriding this node ' 'properties.') ) parser.add_argument( '--preview', default=False, help=_('Whether preview the node adopt request. If set, ' 'only previewing this node and do not adopt.'), action='store_true', ) parser.add_argument( '--snapshot', default=False, help=_('Whether a shapshot of the existing physical object ' 'should be created before the object is adopted as ' 'a node.'), action='store_true' ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering preview = True if parsed_args.preview else False attrs = { 'identity': parsed_args.identity, 'overrides': senlin_utils.format_json_parameter( parsed_args.overrides), 'snapshot': parsed_args.snapshot, 'type': parsed_args.type } if not preview: attrs.update({ 'name': parsed_args.name, 'role': parsed_args.role, 'metadata': senlin_utils.format_parameters( parsed_args.metadata), }) node = senlin_client.adopt_node(preview, **attrs) if not preview: return _show_node(senlin_client, node.id) else: formatters = {} formatters['node_preview'] = senlin_utils.nested_dict_formatter( ['type', 'version', 'properties'], ['property', 'value']) data = node['node_profile'] columns = sorted(data.keys()) return columns, utils.get_dict_properties(data, columns, formatters=formatters) class NodeOp(command.Lister): """Perform an operation on a node.""" log = logging.getLogger(__name__ + ".NodeOp") def get_parser(self, prog_name): parser = super(NodeOp, self).get_parser(prog_name) parser.add_argument( '--operation', metavar='', required=True, help=_('Operation to be performed on the node.') ) parser.add_argument( '--params', metavar='', help=_("Parameters to for the specified operation. " "This can be specified multiple times, or once with " "parameters separated by a semicolon."), action="append" ) parser.add_argument( 'node', metavar='', help=_('ID or name the node operate on.') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering nid = parsed_args.node if parsed_args.params: params = senlin_utils.format_parameters(parsed_args.params) else: params = {} try: resp = senlin_client.perform_operation_on_node( nid, parsed_args.operation, **params) print('Request accepted by action: %s' % resp['action']) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Node not found: %s') % nid) python-senlinclient-1.7.0/senlinclient/v1/policy.py0000666000175100017510000002400513234643473022453 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Clustering v1 policy action implementations""" import logging import sys from openstack import exceptions as sdk_exc from osc_lib.command import command from osc_lib import exceptions as exc from osc_lib import utils from senlinclient.common.i18n import _ from senlinclient.common import utils as senlin_utils class ListPolicy(command.Lister): """List policies that meet the criteria.""" log = logging.getLogger(__name__ + ".ListPolicy") def get_parser(self, prog_name): parser = super(ListPolicy, self).get_parser(prog_name) parser.add_argument( '--limit', metavar='', help=_('Limit the number of policies returned') ) parser.add_argument( '--marker', metavar='', help=_('Only return policies that appear after the given policy ' 'ID') ) parser.add_argument( '--sort', metavar='[:]', help=_("Sorting option which is a string containing a list of " "keys separated by commas. Each key can be optionally " "appended by a sort direction (:asc or :desc). The valid " "sort keys are: ['type', 'name', 'created_at', " "'updated_at']") ) parser.add_argument( '--filters', metavar='<"key1=value1;key2=value2...">', help=_("Filter parameters to apply on returned policies. " "This can be specified multiple times, or once with " "parameters separated by a semicolon. The valid filter " "keys are: ['type', 'name']"), action='append' ) parser.add_argument( '--global-project', default=False, action="store_true", help=_('Indicate that the list should include policies from' ' all projects. This option is subject to access policy ' 'checking. Default is False') ) parser.add_argument( '--full-id', default=False, action="store_true", help=_('Print full IDs in list') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering columns = ['id', 'name', 'type', 'created_at'] queries = { 'limit': parsed_args.limit, 'marker': parsed_args.marker, 'sort': parsed_args.sort, 'global_project': parsed_args.global_project, } if parsed_args.filters: queries.update(senlin_utils.format_parameters(parsed_args.filters)) policies = senlin_client.policies(**queries) formatters = {} if parsed_args.global_project: columns.append('project_id') if not parsed_args.full_id: formatters = { 'id': lambda x: x[:8] } if 'project_id' in columns: formatters['project_id'] = lambda x: x[:8] return ( columns, (utils.get_item_properties(p, columns, formatters=formatters) for p in policies) ) class ShowPolicy(command.ShowOne): """Show the policy details.""" log = logging.getLogger(__name__ + ".ShowPolicy") def get_parser(self, prog_name): parser = super(ShowPolicy, self).get_parser(prog_name) parser.add_argument( 'policy', metavar='', help=_('Name or Id of the policy to show') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering return _show_policy(senlin_client, policy_id=parsed_args.policy) def _show_policy(senlin_client, policy_id): try: policy = senlin_client.get_policy(policy_id) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Policy not found: %s') % policy_id) formatters = { 'spec': senlin_utils.json_formatter } data = policy.to_dict() columns = sorted(data.keys()) return columns, utils.get_dict_properties(data, columns, formatters=formatters) class CreatePolicy(command.ShowOne): """Create a policy.""" log = logging.getLogger(__name__ + ".CreatePolicy") def get_parser(self, prog_name): parser = super(CreatePolicy, self).get_parser(prog_name) parser.add_argument( '--spec-file', metavar='', required=True, help=_('The spec file used to create the policy') ) parser.add_argument( 'name', metavar='', help=_('Name of the policy to create') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering spec = senlin_utils.get_spec_content(parsed_args.spec_file) attrs = { 'name': parsed_args.name, 'spec': spec, } policy = senlin_client.create_policy(**attrs) return _show_policy(senlin_client, policy.id) class UpdatePolicy(command.ShowOne): """Update a policy.""" log = logging.getLogger(__name__ + ".UpdatePolicy") def get_parser(self, prog_name): parser = super(UpdatePolicy, self).get_parser(prog_name) parser.add_argument( '--name', metavar='', help=_('New name of the policy to be updated') ) parser.add_argument( 'policy', metavar='', help=_('Name or ID of the policy to be updated') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering params = { 'name': parsed_args.name, } policy = senlin_client.find_policy(parsed_args.policy) if policy is None: raise exc.CommandError(_('Policy not found: %s') % parsed_args.policy) senlin_client.update_policy(policy.id, **params) return _show_policy(senlin_client, policy_id=policy.id) class DeletePolicy(command.Command): """Delete policy(s).""" log = logging.getLogger(__name__ + ".DeletePolicy") def get_parser(self, prog_name): parser = super(DeletePolicy, self).get_parser(prog_name) parser.add_argument( 'policy', metavar='', nargs='+', help=_('Name or ID of policy(s) to delete') ) parser.add_argument( '--force', action='store_true', help=_('Skip yes/no prompt (assume yes)') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering try: if not parsed_args.force and sys.stdin.isatty(): sys.stdout.write( _("Are you sure you want to delete this policy(s)" " [y/N]?")) prompt_response = sys.stdin.readline().lower() if not prompt_response.startswith('y'): return except KeyboardInterrupt: # Ctrl-c self.log.info('Ctrl-c detected.') return except EOFError: # Ctrl-d self.log.info('Ctrl-d detected') return failure_count = 0 for pid in parsed_args.policy: try: senlin_client.delete_policy(pid, False) except Exception as ex: failure_count += 1 print(ex) if failure_count: raise exc.CommandError(_('Failed to delete %(count)s of the ' '%(total)s specified policy(s).') % {'count': failure_count, 'total': len(parsed_args.policy)}) print('Policy deleted: %s' % parsed_args.policy) class ValidatePolicy(command.ShowOne): """Validate a policy.""" log = logging.getLogger(__name__ + ".ValidatePolicy") def get_parser(self, prog_name): parser = super(ValidatePolicy, self).get_parser(prog_name) parser.add_argument( '--spec-file', metavar='', required=True, help=_('The spec file of the policy to be validated') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering spec = senlin_utils.get_spec_content(parsed_args.spec_file) attrs = { 'spec': spec, } policy = senlin_client.validate_policy(**attrs) formatters = { 'spec': senlin_utils.json_formatter } columns = [ 'created_at', 'data', 'domain', 'id', 'name', 'project', 'spec', 'type', 'updated_at', 'user' ] return columns, utils.get_dict_properties(policy.to_dict(), columns, formatters=formatters) python-senlinclient-1.7.0/senlinclient/v1/cluster_policy.py0000666000175100017510000001273313234643473024221 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Clustering v1 cluster policy action implementations""" import logging from osc_lib.command import command from osc_lib import utils from oslo_utils import strutils from senlinclient.common.i18n import _ from senlinclient.common import utils as senlin_utils class ClusterPolicyList(command.Lister): """List policies from cluster.""" log = logging.getLogger(__name__ + ".ClusterPolicyList") def get_parser(self, prog_name): parser = super(ClusterPolicyList, self).get_parser(prog_name) parser.add_argument( '--filters', metavar='<"key1=value1;key2=value2...">', help=_("Filter parameters to apply on returned results. " "This can be specified multiple times, or once with " "parameters separated by a semicolon. The valid filter " "keys are: ['is_enabled', 'policy_type', 'policy_name']"), action='append' ) parser.add_argument( '--sort', metavar='[:]', help=_("Sorting option which is a string containing a list of " "keys separated by commas. Each key can be optionally " "appended by a sort direction (:asc or :desc). The valid " "sort keys are: ['enabled']") ) parser.add_argument( '--full-id', default=False, action="store_true", help=_('Print full IDs in list') ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to query on') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering columns = ['policy_id', 'policy_name', 'policy_type', 'is_enabled'] cluster = senlin_client.get_cluster(parsed_args.cluster) queries = { 'sort': parsed_args.sort, } if parsed_args.filters: queries.update(senlin_utils.format_parameters(parsed_args.filters)) policies = senlin_client.cluster_policies(cluster.id, **queries) formatters = {} if not parsed_args.full_id: formatters = { 'policy_id': lambda x: x[:8] } return ( columns, (utils.get_item_properties(p, columns, formatters=formatters) for p in policies) ) class ClusterPolicyShow(command.ShowOne): """Show a specific policy that is bound to the specified cluster.""" log = logging.getLogger(__name__ + ".ClusterPolicyShow") def get_parser(self, prog_name): parser = super(ClusterPolicyShow, self).get_parser(prog_name) parser.add_argument( '--policy', metavar='', required=True, help=_('ID or name of the policy to query on') ) parser.add_argument( 'cluster', metavar='', help=_('ID or name of the cluster to query on') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering policy = senlin_client.get_cluster_policy(parsed_args.policy, parsed_args.cluster) data = policy.to_dict() columns = sorted(data.keys()) return columns, utils.get_dict_properties(data, columns) class ClusterPolicyUpdate(command.Command): """Update a policy's properties on a cluster.""" log = logging.getLogger(__name__ + ".ClusterPolicyUpdate") def get_parser(self, prog_name): parser = super(ClusterPolicyUpdate, self).get_parser(prog_name) parser.add_argument( '--policy', metavar='', required=True, help=_('ID or name of policy to be updated') ) parser.add_argument( '--enabled', metavar='', required=True, help=_('Whether the policy should be enabled') ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to operate on') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering kwargs = { 'enabled': strutils.bool_from_string(parsed_args.enabled, strict=True), } resp = senlin_client.cluster_update_policy(parsed_args.cluster, parsed_args.policy, **kwargs) print('Request accepted by action: %s' % resp['action']) python-senlinclient-1.7.0/senlinclient/v1/service.py0000666000175100017510000000257513234643473022624 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import logging from osc_lib.command import command from osc_lib import utils class ListService(command.Lister): """Show a list of all running services.""" log = logging.getLogger(__name__ + ".ListService") def get_parser(self, prog_name): parser = super(ListService, self).get_parser(prog_name) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering columns = ['binary', 'host', 'status', 'state', 'updated_at', 'disabled_reason'] queries = {} result = senlin_client.services(**queries) formatters = {} return ( columns, (utils.get_item_properties(s, columns, formatters=formatters) for s in result) ) python-senlinclient-1.7.0/senlinclient/v1/cluster.py0000666000175100017510000012253113234643473022640 0ustar zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Clustering v1 cluster action implementations""" import logging import subprocess import sys import threading import time from openstack import exceptions as sdk_exc from osc_lib.command import command from osc_lib import exceptions as exc from osc_lib import utils from oslo_utils import strutils import six from senlinclient.common.i18n import _ from senlinclient.common import utils as senlin_utils class ListCluster(command.Lister): """List the user's clusters.""" log = logging.getLogger(__name__ + ".ListCluster") def get_parser(self, prog_name): parser = super(ListCluster, self).get_parser(prog_name) parser.add_argument( '--filters', metavar='<"key1=value1;key2=value2...">', help=_("Filter parameters to apply on returned clusters. " "This can be specified multiple times, or once with " "parameters separated by a semicolon. The valid filter" " keys are: ['status', 'name']"), action='append' ) parser.add_argument( '--sort', metavar='[:]', help=_("Sorting option which is a string containing a list of " "keys separated by commas. Each key can be optionally " "appended by a sort direction (:asc or :desc). The valid " "sort keys are: ['name', 'status', 'init_at', " "'created_at', 'updated_at']")) parser.add_argument( '--limit', metavar='', help=_('Limit the number of clusters returned') ) parser.add_argument( '--marker', metavar='', help=_('Only return clusters that appear after the given cluster ' 'ID') ) parser.add_argument( '--global-project', default=False, action="store_true", help=_('Indicate that the cluster list should include clusters ' 'from all projects. This option is subject to access ' 'policy checking. Default is False') ) parser.add_argument( '--full-id', default=False, action="store_true", help=_('Print full IDs in list') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering columns = ['id', 'name', 'status', 'created_at', 'updated_at'] queries = { 'limit': parsed_args.limit, 'marker': parsed_args.marker, 'sort': parsed_args.sort, 'global_project': parsed_args.global_project, } if parsed_args.filters: queries.update(senlin_utils.format_parameters(parsed_args.filters)) clusters = senlin_client.clusters(**queries) formatters = {} if parsed_args.global_project: columns.append('project_id') if not parsed_args.full_id: formatters = { 'id': lambda x: x[:8] } if 'project_id' in columns: formatters['project_id'] = lambda x: x[:8] return ( columns, (utils.get_item_properties(c, columns, formatters=formatters) for c in clusters) ) class ShowCluster(command.ShowOne): """Show details of the cluster.""" log = logging.getLogger(__name__ + ".ShowCluster") def get_parser(self, prog_name): parser = super(ShowCluster, self).get_parser(prog_name) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to show') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering return _show_cluster(senlin_client, parsed_args.cluster) def _show_cluster(senlin_client, cluster_id): try: cluster = senlin_client.get_cluster(cluster_id) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Cluster not found: %s') % cluster_id) formatters = { 'config': senlin_utils.json_formatter, 'metadata': senlin_utils.json_formatter, 'node_ids': senlin_utils.list_formatter } data = cluster.to_dict() if 'is_profile_only' in data: data.pop('is_profile_only') columns = sorted(data.keys()) return columns, utils.get_dict_properties(data, columns, formatters=formatters) class CreateCluster(command.ShowOne): """Create the cluster.""" log = logging.getLogger(__name__ + ".CreateCluster") def get_parser(self, prog_name): parser = super(CreateCluster, self).get_parser(prog_name) parser.add_argument( '--config', metavar='<"key1=value1;key2=value2...">', help=_('Configuration of the cluster. Default to {}. ' 'This can be specified multiple times, or once with ' 'key-value pairs separated by a semicolon.'), action='append' ) parser.add_argument( '--min-size', metavar='', default=0, help=_('Min size of the cluster. Default to 0') ) parser.add_argument( '--max-size', metavar='', default=-1, help=_('Max size of the cluster. Default to -1, means unlimited') ) parser.add_argument( '--desired-capacity', metavar='', default=0, help=_('Desired capacity of the cluster. Default to min_size if ' 'min_size is specified else 0.') ) parser.add_argument( '--timeout', metavar='', type=int, help=_('Cluster creation timeout in seconds') ) parser.add_argument( '--metadata', metavar='<"key1=value1;key2=value2...">', help=_('Metadata values to be attached to the cluster. ' 'This can be specified multiple times, or once with ' 'key-value pairs separated by a semicolon.'), action='append' ) parser.add_argument( '--profile', metavar='', required=True, help=_('Default profile Id or name used for this cluster') ) parser.add_argument( 'name', metavar='', help=_('Name of the cluster to create') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering if parsed_args.min_size and not parsed_args.desired_capacity: parsed_args.desired_capacity = parsed_args.min_size attrs = { 'config': senlin_utils.format_parameters(parsed_args.config), 'name': parsed_args.name, 'profile_id': parsed_args.profile, 'min_size': parsed_args.min_size, 'max_size': parsed_args.max_size, 'desired_capacity': parsed_args.desired_capacity, 'metadata': senlin_utils.format_parameters(parsed_args.metadata), 'timeout': parsed_args.timeout } cluster = senlin_client.create_cluster(**attrs) return _show_cluster(senlin_client, cluster.id) class UpdateCluster(command.ShowOne): """Update the cluster.""" log = logging.getLogger(__name__ + ".UpdateCluster") def get_parser(self, prog_name): parser = super(UpdateCluster, self).get_parser(prog_name) parser.add_argument( '--config', metavar='<"key1=value1;key2=value2...">', help=_('s of the cluster. Default to {}. ' 'This can be specified multiple times, or once with ' 'key-value pairs separated by a semicolon.'), action='append' ) parser.add_argument( '--profile', metavar='', help=_('ID or name of new profile to use') ) parser.add_argument( '--profile-only', default=False, metavar='', help=_("Whether the cluster should be updated profile only. " "If false, it will be applied to all existing nodes. " "If true, any newly created nodes will use the new profile," "but existing nodes will not be changed. Default is False.") ) parser.add_argument( '--timeout', metavar='', help=_('New timeout (in seconds) value for the cluster') ) parser.add_argument( '--metadata', metavar='<"key1=value1;key2=value2...">', help=_("Metadata values to be attached to the cluster. " "This can be specified multiple times, or once with " "key-value pairs separated by a semicolon. Use '{}' " "can clean metadata "), action='append' ) parser.add_argument( '--name', metavar='', help=_('New name for the cluster to update') ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to be updated') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering cluster = senlin_client.find_cluster(parsed_args.cluster) if cluster is None: raise exc.CommandError(_('Cluster not found: %s') % parsed_args.cluster) attrs = { 'name': parsed_args.name, 'profile_id': parsed_args.profile, 'profile_only': strutils.bool_from_string( parsed_args.profile_only, strict=True, ), 'metadata': senlin_utils.format_parameters(parsed_args.metadata), 'timeout': parsed_args.timeout, } senlin_client.update_cluster(cluster, **attrs) return _show_cluster(senlin_client, cluster.id) class DeleteCluster(command.Command): """Delete the cluster(s).""" log = logging.getLogger(__name__ + ".DeleteCluster") def get_parser(self, prog_name): parser = super(DeleteCluster, self).get_parser(prog_name) parser.add_argument( 'cluster', metavar='', nargs='+', help=_('Name or ID of cluster(s) to delete.') ) parser.add_argument( '--force-delete', action='store_true', help=_('Force to delete cluster(s).') ) parser.add_argument( '--force', action='store_true', help=_('Skip yes/no prompt (assume yes).') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering try: if not parsed_args.force and sys.stdin.isatty(): sys.stdout.write( _("Are you sure you want to delete this cluster(s)" " [y/N]?")) prompt_response = sys.stdin.readline().lower() if not prompt_response.startswith('y'): return except KeyboardInterrupt: # Ctrl-c self.log.info('Ctrl-c detected.') return except EOFError: # Ctrl-d self.log.info('Ctrl-d detected') return result = {} for cid in parsed_args.cluster: try: cluster = senlin_client.delete_cluster( cid, False, parsed_args.force_delete) result[cid] = ('OK', cluster.location.split('/')[-1]) except Exception as ex: result[cid] = ('ERROR', six.text_type(ex)) for rid, res in result.items(): senlin_utils.print_action_result(rid, res) class ResizeCluster(command.Command): """Resize a cluster.""" log = logging.getLogger(__name__ + ".ResizeCluster") def get_parser(self, prog_name): parser = super(ResizeCluster, self).get_parser(prog_name) parser.add_argument( '--capacity', metavar='', type=int, help=_('The desired number of nodes of the cluster') ) parser.add_argument( '--adjustment', metavar='', type=int, help=_('A positive integer meaning the number of nodes to add, ' 'or a negative integer indicating the number of nodes to ' 'remove') ) parser.add_argument( '--percentage', metavar='', type=float, help=_('A value that is interpreted as the percentage of size ' 'adjustment. This value can be positive or negative') ) parser.add_argument( '--min-step', metavar='', type=int, help=_('An integer specifying the number of nodes for adjustment ' 'when is specified') ) parser.add_argument( '--strict', action='store_true', default=False, help=_('A boolean specifying whether the resize should be ' 'performed on a best-effort basis when the new capacity ' 'may go beyond size constraints') ) parser.add_argument( '--min-size', metavar='min', type=int, help=_('New lower bound of cluster size') ) parser.add_argument( '--max-size', metavar='max', type=int, help=_('New upper bound of cluster size. A value of -1 indicates ' 'no upper limit on cluster size') ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to operate on') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering action_args = {} capacity = parsed_args.capacity adjustment = parsed_args.adjustment percentage = parsed_args.percentage min_size = parsed_args.min_size max_size = parsed_args.max_size min_step = parsed_args.min_step if sum(v is not None for v in (capacity, adjustment, percentage, min_size, max_size)) == 0: raise exc.CommandError(_("At least one parameter of 'capacity', " "'adjustment', 'percentage', 'min_size' " "and 'max_size' should be specified.")) if sum(v is not None for v in (capacity, adjustment, percentage)) > 1: raise exc.CommandError(_("Only one of 'capacity', 'adjustment' and" " 'percentage' can be specified.")) action_args['adjustment_type'] = None action_args['number'] = None if capacity is not None: if capacity < 0: raise exc.CommandError(_('Cluster capacity must be larger than' ' or equal to zero.')) action_args['adjustment_type'] = 'EXACT_CAPACITY' action_args['number'] = capacity if adjustment is not None: if adjustment == 0: raise exc.CommandError(_('Adjustment cannot be zero.')) action_args['adjustment_type'] = 'CHANGE_IN_CAPACITY' action_args['number'] = adjustment if percentage is not None: if (percentage == 0 or percentage == 0.0): raise exc.CommandError(_('Percentage cannot be zero.')) action_args['adjustment_type'] = 'CHANGE_IN_PERCENTAGE' action_args['number'] = percentage if min_step is not None: if percentage is None: raise exc.CommandError(_('Min step is only used with ' 'percentage.')) if min_size is not None: if min_size < 0: raise exc.CommandError(_('Min size cannot be less than zero.')) if max_size is not None and max_size >= 0 and min_size > max_size: raise exc.CommandError(_('Min size cannot be larger than ' 'max size.')) if capacity is not None and min_size > capacity: raise exc.CommandError(_('Min size cannot be larger than the ' 'specified capacity')) if max_size is not None: if capacity is not None and max_size > 0 and max_size < capacity: raise exc.CommandError(_('Max size cannot be less than the ' 'specified capacity.')) # do a normalization if max_size < 0: max_size = -1 action_args['min_size'] = min_size action_args['max_size'] = max_size action_args['min_step'] = min_step action_args['strict'] = parsed_args.strict resp = senlin_client.cluster_resize(parsed_args.cluster, **action_args) print('Request accepted by action: %s' % resp['action']) class ScaleInCluster(command.Command): """Scale in a cluster by the specified number of nodes.""" log = logging.getLogger(__name__ + ".ScaleInCluster") def get_parser(self, prog_name): parser = super(ScaleInCluster, self).get_parser(prog_name) parser.add_argument( '--count', metavar='', help=_('Number of nodes to be deleted from the specified cluster') ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to operate on') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering resp = senlin_client.cluster_scale_in(parsed_args.cluster, parsed_args.count) print('Request accepted by action %s' % resp['action']) class ScaleOutCluster(command.Command): """Scale out a cluster by the specified number of nodes.""" log = logging.getLogger(__name__ + ".ScaleOutCluster") def get_parser(self, prog_name): parser = super(ScaleOutCluster, self).get_parser(prog_name) parser.add_argument( '--count', metavar='', help=_('Number of nodes to be added to the specified cluster') ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to operate on') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering resp = senlin_client.cluster_scale_out(parsed_args.cluster, parsed_args.count) print('Request accepted by action %s' % resp['action']) class ClusterPolicyAttach(command.Command): """Attach policy to cluster.""" log = logging.getLogger(__name__ + ".ClusterPolicyAttach") def get_parser(self, prog_name): parser = super(ClusterPolicyAttach, self).get_parser(prog_name) parser.add_argument( '--enabled', metavar='', default=True, help=_('Whether the policy should be enabled once attached. ' 'Default to True') ) parser.add_argument( '--policy', metavar='', required=True, help=_('ID or name of policy to be attached') ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to operate on') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering kwargs = { 'enabled': strutils.bool_from_string(parsed_args.enabled, strict=True), } resp = senlin_client.cluster_attach_policy(parsed_args.cluster, parsed_args.policy, **kwargs) print('Request accepted by action: %s' % resp['action']) class ClusterPolicyDetach(command.Command): """Detach policy from cluster.""" log = logging.getLogger(__name__ + ".ClusterPolicyDetach") def get_parser(self, prog_name): parser = super(ClusterPolicyDetach, self).get_parser(prog_name) parser.add_argument( '--policy', metavar='', required=True, help=_('ID or name of policy to be detached') ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to operate on') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering resp = senlin_client.cluster_detach_policy(parsed_args.cluster, parsed_args.policy) print('Request accepted by action: %s' % resp['action']) class ClusterNodeList(command.Lister): """List nodes from cluster.""" log = logging.getLogger(__name__ + ".ClusterNodeList") def get_parser(self, prog_name): parser = super(ClusterNodeList, self).get_parser(prog_name) parser.add_argument( '--filters', metavar='', help=_("Filter parameters to apply on returned nodes. " "This can be specified multiple times, or once with " "parameters separated by a semicolon. The valid filter " "keys are: ['status', 'name']"), action='append' ) parser.add_argument( '--sort', metavar='[:]', help=_("Sorting option which is a string containing a list of " "keys separated by commas. Each key can be optionally " "appended by a sort direction (:asc or :desc)' The valid " "sort keys are:['index', 'name', 'status', 'init_at', " "'created_at', 'updated_at']") ) parser.add_argument( '--limit', metavar='', help=_('Limit the number of nodes returned') ) parser.add_argument( '--marker', metavar='', help=_('Only return nodes that appear after the given node ID') ) parser.add_argument( '--full-id', default=False, action="store_true", help=_('Print full IDs in list') ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to nodes from') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering queries = { 'cluster_id': parsed_args.cluster, 'sort': parsed_args.sort, 'limit': parsed_args.limit, 'marker': parsed_args.marker, } if parsed_args.filters: queries.update(senlin_utils.format_parameters(parsed_args.filters)) nodes = senlin_client.nodes(**queries) if not parsed_args.full_id: formatters = { 'id': lambda x: x[:8], 'physical_id': lambda x: x[:8] if x else '' } else: formatters = {} columns = ['id', 'name', 'index', 'status', 'physical_id', 'created_at'] return ( columns, (utils.get_item_properties(n, columns, formatters=formatters) for n in nodes) ) class ClusterNodeAdd(command.Command): """Add specified nodes to cluster.""" log = logging.getLogger(__name__ + ".ClusterNodeAdd") def get_parser(self, prog_name): parser = super(ClusterNodeAdd, self).get_parser(prog_name) parser.add_argument( '--nodes', metavar='', required=True, help=_('ID or name of nodes to be added; multiple nodes can be' ' separated with ","') ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to operate on') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering node_ids = parsed_args.nodes.split(',') resp = senlin_client.cluster_add_nodes(parsed_args.cluster, node_ids) print('Request accepted by action: %s' % resp['action']) class ClusterNodeDel(command.Command): """Delete specified nodes from cluster.""" log = logging.getLogger(__name__ + ".ClusterNodeDel") def get_parser(self, prog_name): parser = super(ClusterNodeDel, self).get_parser(prog_name) parser.add_argument( '--nodes', metavar='', required=True, help=_('Name or ID of nodes to be deleted; multiple nodes can be ' 'separated with ","') ) parser.add_argument( '-d', '--destroy-after-deletion', required=False, default=False, help=_('Whether nodes should be destroyed after deleted. ' 'Default is False.') ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to operate on') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering node_ids = parsed_args.nodes.split(',') destroy = parsed_args.destroy_after_deletion destroy = strutils.bool_from_string(destroy, strict=True) kwargs = {"destroy_after_deletion": destroy} resp = senlin_client.cluster_del_nodes(parsed_args.cluster, node_ids, **kwargs) print('Request accepted by action: %s' % resp['action']) class ClusterNodeReplace(command.Command): """Replace the nodes in a cluster with specified nodes.""" log = logging.getLogger(__name__ + ".ClusterNodeReplace") def get_parser(self, prog_name): parser = super(ClusterNodeReplace, self).get_parser(prog_name) parser.add_argument( '--nodes', metavar='', required=True, help=_("OLD_NODE is the name or ID of a node to be replaced, " "NEW_NODE is the name or ID of a node as replacement. " "This can be specified multiple times, or once with " "node-pairs separated by a comma ','."), action='append' ) parser.add_argument( 'cluster', metavar='', help=_('Name or ID of cluster to operate on') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering nodepairs = {} for nodepair in parsed_args.nodes: key = nodepair.split('=')[0] value = nodepair.split('=')[1] nodepairs[key] = value resp = senlin_client.cluster_replace_nodes(parsed_args.cluster, nodepairs) print('Request accepted by action: %s' % resp['action']) class CheckCluster(command.Command): """Check the cluster(s).""" log = logging.getLogger(__name__ + ".CheckCluster") def get_parser(self, prog_name): parser = super(CheckCluster, self).get_parser(prog_name) parser.add_argument( 'cluster', metavar='', nargs='+', help=_('ID or name of cluster(s) to operate on.') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering for cid in parsed_args.cluster: try: resp = senlin_client.check_cluster(cid) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Cluster not found: %s') % cid) print('Cluster check request on cluster %(cid)s is accepted by ' 'action %(action)s.' % {'cid': cid, 'action': resp['action']}) class RecoverCluster(command.Command): """Recover the cluster(s).""" log = logging.getLogger(__name__ + ".RecoverCluster") def get_parser(self, prog_name): parser = super(RecoverCluster, self).get_parser(prog_name) parser.add_argument( 'cluster', metavar='', nargs='+', help=_('ID or name of cluster(s) to operate on.') ) parser.add_argument( '--check', metavar='', default=False, help=_("Whether the cluster should check it's nodes status before " "doing cluster recover. Default is false") ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering params = { 'check': strutils.bool_from_string(parsed_args.check, strict=True) } for cid in parsed_args.cluster: try: resp = senlin_client.recover_cluster(cid, **params) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Cluster not found: %s') % cid) print('Cluster recover request on cluster %(cid)s is accepted by ' 'action %(action)s.' % {'cid': cid, 'action': resp['action']}) class ClusterCollect(command.Lister): """Collect attributes across a cluster.""" log = logging.getLogger(__name__ + ".ClusterCollect") def get_parser(self, prog_name): parser = super(ClusterCollect, self).get_parser(prog_name) parser.add_argument( '--full-id', default=False, action="store_true", help=_('Print full IDs in list') ) parser.add_argument( '--path', metavar='', required=True, help=_('JSON path expression for attribute to be collected') ) parser.add_argument( 'cluster', metavar='', help=_('ID or name of cluster(s) to operate on.') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering attrs = senlin_client.collect_cluster_attrs(parsed_args.cluster, parsed_args.path) columns = ['node_id', 'attr_value'] formatters = {} if not parsed_args.full_id: formatters = { 'node_id': lambda x: x[:8] } return (columns, (utils.get_item_properties(a, columns, formatters=formatters) for a in attrs)) class ClusterOp(command.Lister): """Perform an operation on all nodes across a cluster.""" log = logging.getLogger(__name__ + ".ClusterOp") def get_parser(self, prog_name): parser = super(ClusterOp, self).get_parser(prog_name) parser.add_argument( '--operation', metavar='', required=True, help=_('Operation to be performed on the cluster') ) parser.add_argument( '--params', metavar='', help=_("Parameters to for the specified operation. " "This can be specified multiple times, or once with " "parameters separated by a semicolon."), action='append' ) parser.add_argument( 'cluster', metavar='', help=_('ID or name of cluster to operate on.') ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) senlin_client = self.app.client_manager.clustering cid = parsed_args.cluster if parsed_args.params: params = senlin_utils.format_parameters(parsed_args.params) else: params = {} try: resp = senlin_client.perform_operation_on_cluster( cid, parsed_args.operation, **params) print('Request accepted by action: %s' % resp['action']) except sdk_exc.ResourceNotFound: raise exc.CommandError(_('Cluster not found: %s') % cid) class ClusterRun(command.Command): """Run scripts on cluster.""" log = logging.getLogger(__name__ + ".ClusterRun") def get_parser(self, prog_name): parser = super(ClusterRun, self).get_parser(prog_name) parser.add_argument( '--port', metavar='', type=int, default=22, help=_('The TCP port to use for SSH connection') ) parser.add_argument( '--address-type', metavar='', default='floating', help=_("The type of IP address to use. Possible values include " "'fixed' and 'floating' (the default)") ) parser.add_argument( '--network', metavar='', default='', help=_("The network to use for SSH connection") ) parser.add_argument( '--ipv6', action="store_true", default=False, help=_("Whether the IPv6 address should be used for SSH. Default " "to use IPv4 address.") ) parser.add_argument( '--user', metavar='', default='root', help=_("The login name to use for SSH connection. Default to " "'root'.") ) parser.add_argument( '--identity-file', metavar='', help=_("The private key file to use, same as the '-i' SSH option") ) parser.add_argument( '--ssh-options', metavar='', default="", help=_("Extra options to pass to SSH. See: man ssh.") ) parser.add_argument( '--script', metavar='