
If node introspection fails, there is no way to re-run the process within the UI. This patch adds a button to the maintenance tab to allow a user to re-run the process. Change-Id: I16645643de83f212e89f858a85589d425474c5cd
270 lines
9.0 KiB
Python
270 lines
9.0 KiB
Python
# -*- coding: utf8 -*-
|
|
#
|
|
# 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 django.core.urlresolvers import reverse
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from horizon import messages
|
|
from horizon import tables
|
|
from horizon.utils import memoized
|
|
|
|
from tuskar_ui import api
|
|
|
|
|
|
class DeleteNode(tables.BatchAction):
|
|
name = "delete"
|
|
action_present = _("Delete")
|
|
action_past = _("Deleting")
|
|
data_type_singular = _("Node")
|
|
data_type_plural = _("Nodes")
|
|
classes = ('btn-danger',)
|
|
|
|
def allowed(self, request, obj=None):
|
|
if not obj:
|
|
# this is necessary because table actions use this function
|
|
# with obj=None
|
|
return True
|
|
return (getattr(obj, 'instance_uuid', None) is None and
|
|
obj.power_state not in api.node.POWER_ON_STATES)
|
|
|
|
def action(self, request, obj_id):
|
|
if obj_id is None:
|
|
messages.error(request, _("Select some nodes to delete."))
|
|
return
|
|
api.node.Node.delete(request, obj_id)
|
|
|
|
|
|
class ActivateNode(tables.BatchAction):
|
|
name = "activate"
|
|
action_present = _("Activate")
|
|
action_past = _("Activated")
|
|
data_type_singular = _("Node")
|
|
data_type_plural = _("Nodes")
|
|
|
|
def allowed(self, request, obj=None):
|
|
if not obj:
|
|
# this is necessary because table actions use this function
|
|
# with obj=None
|
|
return True
|
|
return (obj.cpus and obj.memory_mb and obj.local_gb and
|
|
obj.cpu_arch)
|
|
|
|
def action(self, request, obj_id):
|
|
if obj_id is None:
|
|
messages.error(request, _("Select some nodes to activate."))
|
|
return
|
|
api.node.Node.set_maintenance(request, obj_id, False)
|
|
api.node.Node.set_power_state(request, obj_id, 'off')
|
|
|
|
|
|
class SetPowerStateOn(tables.BatchAction):
|
|
name = "set_power_state_on"
|
|
action_present = _("Power On")
|
|
action_past = _("Powering On")
|
|
data_type_singular = _("Node")
|
|
data_type_plural = _("Nodes")
|
|
|
|
def allowed(self, request, obj=None):
|
|
if not obj:
|
|
# this is necessary because table actions use this function
|
|
# with obj=None
|
|
return True
|
|
return obj.power_state not in api.node.POWER_ON_STATES
|
|
|
|
def action(self, request, obj_id):
|
|
if obj_id is None:
|
|
messages.error(request, _("Select some nodes to power on."))
|
|
return
|
|
api.node.Node.set_power_state(request, obj_id, 'on')
|
|
|
|
|
|
class SetPowerStateOff(tables.BatchAction):
|
|
name = "set_power_state_off"
|
|
action_present = _("Power Off")
|
|
action_past = _("Powering Off")
|
|
data_type_singular = _("Node")
|
|
data_type_plural = _("Nodes")
|
|
|
|
def allowed(self, request, obj=None):
|
|
if not obj:
|
|
# this is necessary because table actions use this function
|
|
# with obj=None
|
|
return True
|
|
return (
|
|
obj.power_state in api.node.POWER_ON_STATES and
|
|
getattr(obj, 'instance_uuid', None) is None
|
|
)
|
|
|
|
def action(self, request, obj_id):
|
|
if obj_id is None:
|
|
messages.error(request, _("Select some nodes to power off."))
|
|
return
|
|
api.node.Node.set_power_state(request, obj_id, 'off')
|
|
|
|
|
|
class NodeFilterAction(tables.FilterAction):
|
|
def filter(self, table, nodes, filter_string):
|
|
"""Really naive case-insensitive search."""
|
|
q = filter_string.lower()
|
|
|
|
def comp(node):
|
|
return any(q in unicode(value).lower() for value in (
|
|
node.ip_address,
|
|
node.cpus,
|
|
node.memory_mb,
|
|
node.local_gb,
|
|
))
|
|
|
|
return filter(comp, nodes)
|
|
|
|
|
|
class DiscoverNode(tables.BatchAction):
|
|
name = "discover_nodes"
|
|
action_present = _("Discover")
|
|
action_past = _("Discovered")
|
|
data_type_singular = _("Node")
|
|
data_type_plural = _("Nodes")
|
|
|
|
def allowed(self, request, obj=None):
|
|
if not obj:
|
|
# this is necessary because table actions use this function
|
|
# with obj=None
|
|
return True
|
|
return obj.state == api.node.MAINTENANCE_STATE
|
|
|
|
def action(self, request, obj_id):
|
|
if obj_id is None:
|
|
messages.error(request, _("Select some nodes to discover."))
|
|
return
|
|
api.node.Node.discover(request, [obj_id])
|
|
|
|
|
|
@memoized.memoized
|
|
def _get_role_link(role_id):
|
|
if role_id:
|
|
return reverse('horizon:infrastructure:roles:detail',
|
|
kwargs={'role_id': role_id})
|
|
|
|
|
|
def get_role_link(datum):
|
|
return _get_role_link(getattr(datum, 'role_id', None))
|
|
|
|
|
|
def get_power_state_with_transition(node):
|
|
if node.target_power_state and (
|
|
node.power_state != node.target_power_state):
|
|
return "{0} -> {1}".format(
|
|
node.power_state, node.target_power_state)
|
|
return node.power_state
|
|
|
|
|
|
def get_state_string(node):
|
|
state_dict = {
|
|
api.node.DISCOVERING_STATE: _('Discovering'),
|
|
api.node.DISCOVERED_STATE: _('Discovered'),
|
|
api.node.PROVISIONED_STATE: _('Provisioned'),
|
|
api.node.PROVISIONING_FAILED_STATE: _('Provisioning Failed'),
|
|
api.node.PROVISIONING_STATE: _('Provisioning'),
|
|
api.node.FREE_STATE: _('Free'),
|
|
}
|
|
|
|
node_state = node.state
|
|
return state_dict.get(node_state, node_state)
|
|
|
|
|
|
class BaseNodesTable(tables.DataTable):
|
|
node = tables.Column('uuid',
|
|
link="horizon:infrastructure:nodes:node_detail",
|
|
verbose_name=_("Node Name"))
|
|
role_name = tables.Column('role_name',
|
|
link=get_role_link,
|
|
verbose_name=_("Deployment Role"))
|
|
cpus = tables.Column('cpus',
|
|
verbose_name=_("CPU (cores)"))
|
|
memory_mb = tables.Column('memory_mb',
|
|
verbose_name=_("Memory (MB)"))
|
|
local_gb = tables.Column('local_gb',
|
|
verbose_name=_("Disk (GB)"))
|
|
power_status = tables.Column(get_power_state_with_transition,
|
|
verbose_name=_("Power Status"))
|
|
state = tables.Column(get_state_string,
|
|
verbose_name=_("Status"))
|
|
|
|
class Meta(object):
|
|
name = "nodes_table"
|
|
verbose_name = _("Nodes")
|
|
table_actions = (NodeFilterAction, SetPowerStateOn, SetPowerStateOff,
|
|
DeleteNode)
|
|
row_actions = (SetPowerStateOn, SetPowerStateOff, DeleteNode)
|
|
template = "horizon/common/_enhanced_data_table.html"
|
|
|
|
def get_object_id(self, datum):
|
|
return datum.uuid
|
|
|
|
def get_object_display(self, datum):
|
|
return datum.uuid
|
|
|
|
|
|
class AllNodesTable(BaseNodesTable):
|
|
|
|
class Meta(object):
|
|
name = "all_nodes_table"
|
|
verbose_name = _("All")
|
|
hidden_title = False
|
|
columns = ('node', 'cpus', 'memory_mb', 'local_gb', 'power_status',
|
|
'state')
|
|
table_actions = (NodeFilterAction, SetPowerStateOn, SetPowerStateOff,
|
|
DeleteNode)
|
|
row_actions = (SetPowerStateOn, SetPowerStateOff, DeleteNode)
|
|
template = "horizon/common/_enhanced_data_table.html"
|
|
|
|
|
|
class ProvisionedNodesTable(BaseNodesTable):
|
|
|
|
class Meta(object):
|
|
name = "provisioned_nodes_table"
|
|
verbose_name = _("Provisioned")
|
|
hidden_title = False
|
|
table_actions = (NodeFilterAction, SetPowerStateOn, SetPowerStateOff,
|
|
DeleteNode)
|
|
row_actions = (SetPowerStateOn, SetPowerStateOff, DeleteNode)
|
|
template = "horizon/common/_enhanced_data_table.html"
|
|
|
|
|
|
class FreeNodesTable(BaseNodesTable):
|
|
|
|
class Meta(object):
|
|
name = "free_nodes_table"
|
|
verbose_name = _("Free")
|
|
hidden_title = False
|
|
columns = ('node', 'cpus', 'memory_mb', 'local_gb', 'power_status')
|
|
table_actions = (NodeFilterAction, SetPowerStateOn, SetPowerStateOff,
|
|
DeleteNode)
|
|
row_actions = (SetPowerStateOn, SetPowerStateOff, DeleteNode,)
|
|
template = "horizon/common/_enhanced_data_table.html"
|
|
|
|
|
|
class MaintenanceNodesTable(BaseNodesTable):
|
|
|
|
class Meta(object):
|
|
name = "maintenance_nodes_table"
|
|
verbose_name = _("Maintenance")
|
|
hidden_title = False
|
|
columns = ('node', 'cpus', 'memory_mb', 'local_gb', 'power_status',
|
|
'state')
|
|
table_actions = (NodeFilterAction, ActivateNode, SetPowerStateOn,
|
|
SetPowerStateOff, DiscoverNode, DeleteNode)
|
|
row_actions = (ActivateNode, SetPowerStateOn, SetPowerStateOff,
|
|
DeleteNode)
|
|
template = "horizon/common/_enhanced_data_table.html"
|