Add a "driver" field to the Register Nodes dialog
The choice of the driver determines the visibility of the driver-dependent fields. Partial-bug: #1342156 Change-Id: I7f68b47c46c12e7f2bf91e475a62e4740ecc3946
This commit is contained in:
parent
e67faf8c1f
commit
1865cf987a
|
@ -63,15 +63,10 @@ class IronicNode(base.APIResourceWrapper):
|
|||
|
||||
@classmethod
|
||||
def create(cls, request, ipmi_address, architecture, cpu, ram, local_disk,
|
||||
mac_addresses, ipmi_username=None, ipmi_password=None):
|
||||
mac_addresses, ipmi_username=None, ipmi_password=None,
|
||||
driver=None):
|
||||
"""Create a Node in Ironic
|
||||
|
||||
:param request: request object
|
||||
:type request: django.http.HttpRequest
|
||||
|
||||
:param ipmi_address: IPMI address
|
||||
:type ipmi_address: str
|
||||
|
||||
:param cpu: number of cores
|
||||
:type cpu: int
|
||||
|
||||
|
@ -84,12 +79,6 @@ class IronicNode(base.APIResourceWrapper):
|
|||
:param mac_addresses: list of mac addresses
|
||||
:type mac_addresses: list of str
|
||||
|
||||
:param ipmi_username: IPMI username
|
||||
:type ipmi_username: str
|
||||
|
||||
:param ipmi_password: IPMI password
|
||||
:type ipmi_password: str
|
||||
|
||||
:return: the created Node object
|
||||
:rtype: tuskar_ui.api.node.IronicNode
|
||||
"""
|
||||
|
@ -193,15 +182,10 @@ class BareMetalNode(base.APIResourceWrapper):
|
|||
|
||||
@classmethod
|
||||
def create(cls, request, ipmi_address, architecture, cpu, ram, local_disk,
|
||||
mac_addresses, ipmi_username=None, ipmi_password=None):
|
||||
mac_addresses, ipmi_username=None, ipmi_password=None,
|
||||
driver=None):
|
||||
"""Create a Nova BareMetalNode
|
||||
|
||||
:param request: request object
|
||||
:type request: django.http.HttpRequest
|
||||
|
||||
:param ipmi_address: IPMI address
|
||||
:type ipmi_address: str
|
||||
|
||||
:param cpu: number of cores
|
||||
:type cpu: int
|
||||
|
||||
|
@ -214,12 +198,6 @@ class BareMetalNode(base.APIResourceWrapper):
|
|||
:param mac_addresses: list of mac addresses
|
||||
:type mac_addresses: list of str
|
||||
|
||||
:param ipmi_username: IPMI username
|
||||
:type ipmi_username: str
|
||||
|
||||
:param ipmi_password: IPMI password
|
||||
:type ipmi_password: str
|
||||
|
||||
:return: the created BareMetalNode object
|
||||
:rtype: tuskar_ui.api.node.BareMetalNode
|
||||
"""
|
||||
|
@ -414,11 +392,12 @@ class Node(base.APIResourceWrapper):
|
|||
|
||||
@classmethod
|
||||
def create(cls, request, ipmi_address, architecture, cpu, ram, local_disk,
|
||||
mac_addresses, ipmi_username=None, ipmi_password=None):
|
||||
mac_addresses, ipmi_username=None, ipmi_password=None,
|
||||
driver=None):
|
||||
return cls(NodeClient(request).node_class.create(
|
||||
request, ipmi_address, architecture, cpu, ram, local_disk,
|
||||
mac_addresses, ipmi_username=ipmi_username,
|
||||
ipmi_password=ipmi_password))
|
||||
ipmi_password=ipmi_password, driver=driver))
|
||||
|
||||
@classmethod
|
||||
@handle_errors(_("Unable to retrieve node"))
|
||||
|
|
|
@ -24,6 +24,10 @@ ARCHITECTURE_CHOICES = [
|
|||
('x86', _("x86")),
|
||||
('x86_64', _("x86_64")),
|
||||
]
|
||||
DRIVER_CHOICES = [
|
||||
('ipmi', _("IPMI Driver")),
|
||||
('dummy', _("Dummy Driver")),
|
||||
]
|
||||
|
||||
|
||||
class NodeForm(django.forms.Form):
|
||||
|
@ -32,21 +36,43 @@ class NodeForm(django.forms.Form):
|
|||
required=False,
|
||||
widget=django.forms.HiddenInput(),
|
||||
)
|
||||
|
||||
driver = django.forms.ChoiceField(
|
||||
label=_("Driver"),
|
||||
choices=DRIVER_CHOICES,
|
||||
required=True,
|
||||
widget=django.forms.Select(attrs={
|
||||
'class': 'input input-medium switchable',
|
||||
'data-slug': 'driver',
|
||||
}),
|
||||
)
|
||||
|
||||
ipmi_address = django.forms.IPAddressField(
|
||||
label=_("IPMI Address"),
|
||||
required=False,
|
||||
widget=django.forms.TextInput(attrs={'class': 'input input-medium'}),
|
||||
widget=django.forms.TextInput(attrs={
|
||||
'class': 'switched',
|
||||
'data-switch-on': 'driver',
|
||||
'data-driver-ipmi': 'ipmi',
|
||||
}),
|
||||
)
|
||||
ipmi_username = django.forms.CharField(
|
||||
label=_("IPMI User"),
|
||||
required=False,
|
||||
widget=django.forms.TextInput(attrs={'class': 'input input-medium'}),
|
||||
widget=django.forms.TextInput(attrs={
|
||||
'class': 'input input-medium switched',
|
||||
'data-switch-on': 'driver',
|
||||
'data-driver-ipmi': 'ipmi',
|
||||
}),
|
||||
)
|
||||
ipmi_password = django.forms.CharField(
|
||||
label=_("IPMI Password"),
|
||||
required=False,
|
||||
widget=django.forms.PasswordInput(
|
||||
render_value=False, attrs={'class': 'input input-medium'}),
|
||||
widget=django.forms.PasswordInput(render_value=False, attrs={
|
||||
'class': 'input input-medium switched',
|
||||
'data-switch-on': 'driver',
|
||||
'data-driver-ipmi': 'ipmi',
|
||||
}),
|
||||
)
|
||||
mac_addresses = tuskar_ui.forms.MultiMACField(
|
||||
label=_("NIC MAC Addresses"),
|
||||
|
@ -102,17 +128,21 @@ class BaseNodeFormset(django.forms.formsets.BaseFormSet):
|
|||
def handle(self, request, data):
|
||||
success = True
|
||||
for form in self:
|
||||
data = form.cleaned_data
|
||||
try:
|
||||
api.node.Node.create(
|
||||
request,
|
||||
form.cleaned_data['ipmi_address'],
|
||||
form.cleaned_data.get('architecture'),
|
||||
form.cleaned_data.get('cpus'),
|
||||
form.cleaned_data.get('memory'),
|
||||
form.cleaned_data.get('local_disk'),
|
||||
form.cleaned_data['mac_addresses'].split(),
|
||||
form.cleaned_data.get('ipmi_username'),
|
||||
form.cleaned_data.get('ipmi_password'),
|
||||
# TODO(rdopieralski) If ipmi_address is no longer required,
|
||||
# then we will need to use something else here?
|
||||
ipmi_address=data['ipmi_address'],
|
||||
architecture=data.get('architecture'),
|
||||
cpu=data.get('cpus'),
|
||||
ram=data.get('memory'),
|
||||
local_disk=data.get('local_disk'),
|
||||
mac_addresses=data['mac_addresses'].split(),
|
||||
ipmi_username=data.get('ipmi_username'),
|
||||
ipmi_password=data.get('ipmi_password'),
|
||||
driver=form.cleaned_data.get('driver'),
|
||||
)
|
||||
except Exception:
|
||||
success = False
|
||||
|
@ -135,5 +165,6 @@ class BaseNodeFormset(django.forms.formsets.BaseFormSet):
|
|||
if not form.cleaned_data.get('ipmi_password'):
|
||||
form.cleaned_data['ipmi_password'] = None
|
||||
|
||||
|
||||
NodeFormset = django.forms.formsets.formset_factory(NodeForm, extra=1,
|
||||
formset=BaseNodeFormset)
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
<div class="well well-small tab-pane{% if active %} active{% endif %}"
|
||||
id="tab-{{ form.prefix }}">
|
||||
<div class="form form-inline">
|
||||
<div class="form form-inline"><fieldset>
|
||||
<div class="row-fluid">
|
||||
<h4>Node Detail</h4>
|
||||
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.node_tags %}
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<h5>Power Management</h5>
|
||||
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.driver required=True %}
|
||||
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.ipmi_address %}
|
||||
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.ipmi_username %}
|
||||
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.ipmi_password %}
|
||||
|
@ -29,7 +30,7 @@
|
|||
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.memory extra_text=_('MB') required=True %}
|
||||
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.local_disk extra_text=_('GB') required=True %}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset></div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
|
|
@ -164,6 +164,7 @@ class NodesTests(test.BaseAdminViewTests, helpers.APITestCase):
|
|||
'register_nodes-INITIAL_FORMS': 1,
|
||||
'register_nodes-MAX_NUM_FORMS': 1000,
|
||||
|
||||
'register_nodes-0-driver': 'ipmi',
|
||||
'register_nodes-0-ipmi_address': '127.0.0.1',
|
||||
'register_nodes-0-ipmi_username': 'username',
|
||||
'register_nodes-0-ipmi_password': 'password',
|
||||
|
@ -173,6 +174,7 @@ class NodesTests(test.BaseAdminViewTests, helpers.APITestCase):
|
|||
'register_nodes-0-memory': '2',
|
||||
'register_nodes-0-local_disk': '3',
|
||||
|
||||
'register_nodes-1-driver': 'ipmi',
|
||||
'register_nodes-1-ipmi_address': '127.0.0.2',
|
||||
'register_nodes-1-mac_addresses': 'de:ad:be:ef:ca:ff',
|
||||
'register_nodes-1-architecture': 'x86',
|
||||
|
@ -188,10 +190,30 @@ class NodesTests(test.BaseAdminViewTests, helpers.APITestCase):
|
|||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
request = Node.create.call_args_list[0][0][0] # This is a hack.
|
||||
self.assertListEqual(Node.create.call_args_list, [
|
||||
call(request, u'127.0.0.1', 'x86', 1, 2, 3,
|
||||
['DE:AD:BE:EF:CA:FE'], u'username', u'password'),
|
||||
call(request, u'127.0.0.2', 'x86', 4, 5, 6,
|
||||
['DE:AD:BE:EF:CA:FF'], None, None),
|
||||
call(
|
||||
request,
|
||||
ipmi_address=u'127.0.0.1',
|
||||
architecture='x86',
|
||||
cpu=1,
|
||||
ram=2,
|
||||
local_disk=3,
|
||||
mac_addresses=['DE:AD:BE:EF:CA:FE'],
|
||||
ipmi_username=u'username',
|
||||
ipmi_password=u'password',
|
||||
driver='ipmi',
|
||||
),
|
||||
call(
|
||||
request,
|
||||
ipmi_address=u'127.0.0.2',
|
||||
architecture='x86',
|
||||
cpu=4,
|
||||
ram=5,
|
||||
local_disk=6,
|
||||
mac_addresses=['DE:AD:BE:EF:CA:FF'],
|
||||
ipmi_username=None,
|
||||
ipmi_password=None,
|
||||
driver='ipmi',
|
||||
),
|
||||
])
|
||||
|
||||
def test_register_post_exception(self):
|
||||
|
@ -200,6 +222,7 @@ class NodesTests(test.BaseAdminViewTests, helpers.APITestCase):
|
|||
'register_nodes-INITIAL_FORMS': 1,
|
||||
'register_nodes-MAX_NUM_FORMS': 1000,
|
||||
|
||||
'register_nodes-0-driver': 'ipmi',
|
||||
'register_nodes-0-ipmi_address': '127.0.0.1',
|
||||
'register_nodes-0-ipmi_username': 'username',
|
||||
'register_nodes-0-ipmi_password': 'password',
|
||||
|
@ -209,6 +232,7 @@ class NodesTests(test.BaseAdminViewTests, helpers.APITestCase):
|
|||
'register_nodes-0-memory': '2',
|
||||
'register_nodes-0-local_disk': '3',
|
||||
|
||||
'register_nodes-1-driver': 'ipmi',
|
||||
'register_nodes-1-ipmi_address': '127.0.0.2',
|
||||
'register_nodes-1-mac_addresses': 'de:ad:be:ef:ca:ff',
|
||||
'register_nodes-1-architecture': 'x86',
|
||||
|
@ -224,10 +248,30 @@ class NodesTests(test.BaseAdminViewTests, helpers.APITestCase):
|
|||
self.assertEqual(res.status_code, 200)
|
||||
request = Node.create.call_args_list[0][0][0] # This is a hack.
|
||||
self.assertListEqual(Node.create.call_args_list, [
|
||||
call(request, u'127.0.0.1', 'x86', 1, 2, 3,
|
||||
['DE:AD:BE:EF:CA:FE'], u'username', u'password'),
|
||||
call(request, u'127.0.0.2', 'x86', 4, 5, 6,
|
||||
['DE:AD:BE:EF:CA:FF'], None, None),
|
||||
call(
|
||||
request,
|
||||
ipmi_address=u'127.0.0.1',
|
||||
architecture='x86',
|
||||
cpu=1,
|
||||
ram=2,
|
||||
local_disk=3,
|
||||
mac_addresses=['DE:AD:BE:EF:CA:FE'],
|
||||
ipmi_username=u'username',
|
||||
ipmi_password=u'password',
|
||||
driver='ipmi',
|
||||
),
|
||||
call(
|
||||
request,
|
||||
ipmi_address=u'127.0.0.2',
|
||||
architecture='x86',
|
||||
cpu=4,
|
||||
ram=5,
|
||||
local_disk=6,
|
||||
mac_addresses=['DE:AD:BE:EF:CA:FF'],
|
||||
ipmi_username=None,
|
||||
ipmi_password=None,
|
||||
driver='ipmi',
|
||||
),
|
||||
])
|
||||
self.assertTemplateUsed(
|
||||
res, 'infrastructure/nodes/register.html')
|
||||
|
|
|
@ -66,8 +66,16 @@
|
|||
.form label.checkbox {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
fieldset .form-field {
|
||||
input, textarea, select {
|
||||
width: 150px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#detail__overview {
|
||||
ul {
|
||||
list-style: disc;
|
||||
|
|
Loading…
Reference in New Issue