Merge lp:~rvb/maas/add-power-params-doc into lp:~maas-committers/maas/trunk

Proposed by Raphaël Badin
Status: Merged
Approved by: Raphaël Badin
Approved revision: no longer in the source branch.
Merged at revision: 2289
Proposed branch: lp:~rvb/maas/add-power-params-doc
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 183 lines (+86/-1)
4 files modified
src/maasserver/api.py (+9/-0)
src/maasserver/apidoc.py (+46/-0)
src/maasserver/tests/test_apidoc.py (+30/-0)
src/provisioningserver/power_schema.py (+1/-1)
To merge this branch: bzr merge lp:~rvb/maas/add-power-params-doc
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+216894@code.launchpad.net

Commit message

Add documentation about the power types and the related power parameters.

Description of the change

Here is how it looks like: http://people.canonical.com/~rvb/power_types_doc.png

The tests are minimal but testing the exact formatting would be a bit pointless I think. A test that the whole API doc can be translated from rST into HTML already exists.

To post a comment you must log in.
Revision history for this message
Julian Edwards (julian-edwards) wrote :

I don't think we should be documenting this like this, other than some
examples perhaps.

This is because clusters can and will have varying power types available
- it's not a heterogeneous environment, especially during staged cluster
upgrades.

What I think we should do is implement an API function that returns
available power types and each one's parameters based on the cluster and
encourage API users to derive from that when editing/adding nodes.

Revision history for this message
Raphaël Badin (rvb) wrote :

> I don't think we should be documenting this like this, other than some
> examples perhaps.
>
> This is because clusters can and will have varying power types available
> - it's not a heterogeneous environment, especially during staged cluster
> upgrades.
>
> What I think we should do is implement an API function that returns
> available power types and each one's parameters based on the cluster and
> encourage API users to derive from that when editing/adding nodes.

An API call is probably needed indeed since some of the power types are registered dynamically.

But I still think it's worth documentation all the built-in power types. I'll change the introduction sentence to make it clear that those are the *built-in* power types and that others can be dynamically registered using clusters.

What do you say?

Revision history for this message
Julian Edwards (julian-edwards) wrote :

On 24/04/14 16:53, Raphaël Badin wrote:
>> I don't think we should be documenting this like this, other than some
>> examples perhaps.
>>
>> This is because clusters can and will have varying power types available
>> - it's not a heterogeneous environment, especially during staged cluster
>> upgrades.
>>
>> What I think we should do is implement an API function that returns
>> available power types and each one's parameters based on the cluster and
>> encourage API users to derive from that when editing/adding nodes.
>
> An API call is probably needed indeed since some of the power types are registered dynamically.
>
> But I still think it's worth documentation all the built-in power types. I'll change the introduction sentence to make it clear that those are the *built-in* power types and that others can be dynamically registered using clusters.
>
> What do you say?
>

Well all power types are built in, that's how MAAS rolls. I still
prefer a simple example of the more common types and an example of how
to use this new API call in conjunction with adding a node.

But this is just my opinion, see what others say too.

Revision history for this message
Raphaël Badin (rvb) wrote :

> Well all power types are built in, that's how MAAS rolls.

Not really, if you're using a custom-made cluster controller that registers an extra power type, that power type will be available in MAAS and it's not "built-in".

> I still
> prefer a simple example of the more common types and an example of how
> to use this new API call in conjunction with adding a node.

I really think documenting all the power types and power parameters we know about is better.

Revision history for this message
Raphaël Badin (rvb) wrote :

> But I still think it's worth documentation all the built-in power types. I'll
> change the introduction sentence to make it clear that those are the *built-
> in* power types and that others can be dynamically registered using clusters.

Done:

78 + line(
79 + "This is the list of the built-in power types and their "
80 + "associated power parameters. Note that other power types "
81 + "can be registered, at runtime, by cluster controllers with "
82 + "extra capabilities.")

Revision history for this message
Gavin Panella (allenap) wrote :

I think having some static docs on maas.ubuntu.com has some value.

However, I also think we ought to make all the docs available via the MAAS UI too, including dynamically (re)generating the code-derived docs. This would complement the API call that Julian suggests.

Once we have the docs-in-UI, the docs on maas.ubuntu.com should then have a section explaining to use the docs on your local MAAS installation for the most accurate information.

Right now these docs appear to be LISP by the count of braces.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/maasserver/api.py'
--- src/maasserver/api.py 2014-04-22 09:08:02 +0000
+++ src/maasserver/api.py 2014-04-24 08:03:14 +0000
@@ -149,6 +149,7 @@
149 describe_resource,149 describe_resource,
150 find_api_resources,150 find_api_resources,
151 generate_api_docs,151 generate_api_docs,
152 generate_power_types_doc,
152 )153 )
153from maasserver.clusterrpc.power_parameters import (154from maasserver.clusterrpc.power_parameters import (
154 get_all_power_types_from_clusters,155 get_all_power_types_from_clusters,
@@ -334,6 +335,8 @@
334 :param power_type: The new power type for this node. If you use the335 :param power_type: The new power type for this node. If you use the
335 default value, power_parameters will be set to the empty string.336 default value, power_parameters will be set to the empty string.
336 Available to admin users.337 Available to admin users.
338 See the `Power types`_ section for a list of the available power
339 types.
337 :type power_type: unicode340 :type power_type: unicode
338 :param power_parameters_{param1}: The new value for the 'param1'341 :param power_parameters_{param1}: The new value for the 'param1'
339 power parameter. Note that this is dynamic as the available342 power parameter. Note that this is dynamic as the available
@@ -342,6 +345,8 @@
342 parameter is 'power_address' so one would want to pass 'myaddress'345 parameter is 'power_address' so one would want to pass 'myaddress'
343 as the value of the 'power_parameters_power_address' parameter.346 as the value of the 'power_parameters_power_address' parameter.
344 Available to admin users.347 Available to admin users.
348 See the `Power types`_ section for a list of the available power
349 parameters for each power type.
345 :type power_parameters_{param1}: unicode350 :type power_parameters_{param1}: unicode
346 :param power_parameters_skip_check: Whether or not the new power351 :param power_parameters_skip_check: Whether or not the new power
347 parameters for this node should be checked against the expected352 parameters for this node should be checked against the expected
@@ -2293,6 +2298,10 @@
2293 line(" ", docline, sep="")2298 line(" ", docline, sep="")
2294 line()2299 line()
22952300
2301 line()
2302 line()
2303 line(generate_power_types_doc())
2304
2296 return output.getvalue()2305 return output.getvalue()
22972306
22982307
22992308
=== modified file 'src/maasserver/apidoc.py'
--- src/maasserver/apidoc.py 2014-03-27 15:12:48 +0000
+++ src/maasserver/apidoc.py 2014-04-24 08:03:14 +0000
@@ -19,6 +19,8 @@
19 "generate_api_docs",19 "generate_api_docs",
20 ]20 ]
2121
22from cStringIO import StringIO
23from functools import partial
22from inspect import getdoc24from inspect import getdoc
23from itertools import izip_longest25from itertools import izip_longest
2426
@@ -32,6 +34,7 @@
32from piston.doc import generate_doc34from piston.doc import generate_doc
33from piston.handler import BaseHandler35from piston.handler import BaseHandler
34from piston.resource import Resource36from piston.resource import Resource
37from provisioningserver.power_schema import JSON_POWER_TYPE_PARAMETERS
3538
3639
37def accumulate_api_resources(resolver, accumulator):40def accumulate_api_resources(resolver, accumulator):
@@ -67,6 +70,49 @@
67 return accumulator70 return accumulator
6871
6972
73def generate_power_types_doc():
74 """Generate ReST documentation for the supported power types.
75
76 The documentation is derived from the `JSON_POWER_TYPE_PARAMETERS`
77 object.
78 """
79 output = StringIO()
80 line = partial(print, file=output)
81
82 line('Power types')
83 line('-----------')
84 line()
85 line("This is the list of the supported power types and their "
86 "associated power parameters. Note that the list of usable "
87 "power types for a particular cluster might be a subset of this "
88 "list if the cluster in question is from an older version of "
89 "MAAS.")
90 line()
91 for item in JSON_POWER_TYPE_PARAMETERS:
92 title = "%s (%s)" % (item['name'], item['description'])
93 line(title)
94 line('=' * len(title))
95 line('')
96 line("Power parameters:")
97 line('')
98 for field in item['fields']:
99 field_description = []
100 field_description.append(
101 "* %s (%s)." % (field['name'], field['label']))
102 choices = field.get('choices', [])
103 if len(choices) > 0:
104 field_description.append(
105 " Choices: %s" % ', '.join(
106 "'%s' (%s)" % (choice[0], choice[1])
107 for choice in choices))
108 default = field.get('default', '')
109 if default is not '':
110 field_description.append(" Default: '%s'." % default)
111 line(''.join(field_description))
112 line('')
113 return output.getvalue()
114
115
70def generate_api_docs(resources):116def generate_api_docs(resources):
71 """Generate ReST documentation objects for the ReST API.117 """Generate ReST documentation objects for the ReST API.
72118
73119
=== modified file 'src/maasserver/tests/test_apidoc.py'
--- src/maasserver/tests/test_apidoc.py 2014-03-27 15:16:18 +0000
+++ src/maasserver/tests/test_apidoc.py 2014-04-24 08:03:14 +0000
@@ -25,6 +25,7 @@
25 )25 )
26from django.core.exceptions import ImproperlyConfigured26from django.core.exceptions import ImproperlyConfigured
27from django.core.urlresolvers import reverse27from django.core.urlresolvers import reverse
28from maasserver import apidoc
28from maasserver.api_support import (29from maasserver.api_support import (
29 operation,30 operation,
30 OperationsHandler,31 OperationsHandler,
@@ -35,6 +36,7 @@
35 describe_resource,36 describe_resource,
36 find_api_resources,37 find_api_resources,
37 generate_api_docs,38 generate_api_docs,
39 generate_power_types_doc,
38 )40 )
39from maasserver.testing.factory import factory41from maasserver.testing.factory import factory
40from maasserver.testing.testcase import MAASServerTestCase42from maasserver.testing.testcase import MAASServerTestCase
@@ -42,6 +44,8 @@
42from piston.doc import HandlerDocumentation44from piston.doc import HandlerDocumentation
43from piston.handler import BaseHandler45from piston.handler import BaseHandler
44from piston.resource import Resource46from piston.resource import Resource
47from provisioningserver.power_schema import make_json_field
48from testtools.matchers import ContainsAll
4549
4650
47class TestFindingResources(MAASServerTestCase):51class TestFindingResources(MAASServerTestCase):
@@ -306,3 +310,29 @@
306 "name": "ExampleHandler",310 "name": "ExampleHandler",
307 }311 }
308 self.assertEqual(expected, describe_resource(resource))312 self.assertEqual(expected, describe_resource(resource))
313
314
315class TestGeneratePowerTypesDoc(MAASServerTestCase):
316 """Tests for `generate_power_types_doc`."""
317
318 def test__generate_power_types_doc_generates_doc(self):
319 doc = generate_power_types_doc()
320 self.assertThat(doc, ContainsAll(["Power types", "IPMI"]))
321
322 def test__generate_power_types_doc_generates_describes_power_type(self):
323 name = factory.make_name('name')
324 description = factory.make_name('description')
325 param_name = factory.make_name('param_name')
326 param_description = factory.make_name('param_description')
327 json_fields = [{
328 'name': name,
329 'description': description,
330 'fields': [
331 make_json_field(param_name, param_description),
332 ],
333 }]
334 self.patch(apidoc, "JSON_POWER_TYPE_PARAMETERS", json_fields)
335 doc = generate_power_types_doc()
336 self.assertThat(
337 doc,
338 ContainsAll([name, description, param_name, param_description]))
309339
=== modified file 'src/provisioningserver/power_schema.py'
--- src/provisioningserver/power_schema.py 2014-04-22 08:27:47 +0000
+++ src/provisioningserver/power_schema.py 2014-04-24 08:03:14 +0000
@@ -164,7 +164,7 @@
164 },164 },
165 {165 {
166 'name': 'virsh',166 'name': 'virsh',
167 'description': 'virsh (virtual systems)',167 'description': 'Virsh (virtual systems)',
168 'fields': [168 'fields': [
169 make_json_field('power_address', "Power address"),169 make_json_field('power_address', "Power address"),
170 make_json_field('power_id', "Power ID"),170 make_json_field('power_id', "Power ID"),