50
50
import djorm_pgarray.fields
51
51
from maasserver import DefaultMeta
52
52
from maasserver.clusterrpc.dhcp import update_host_maps
53
from maasserver.clusterrpc.power import power_on_nodes
53
from maasserver.clusterrpc.power import (
54
57
from maasserver.enum import (
75
78
from maasserver.models.config import Config
76
79
from maasserver.models.dhcplease import DHCPLease
77
80
from maasserver.models.licensekey import LicenseKey
81
from maasserver.models.macaddress import update_mac_cluster_interfaces
78
82
from maasserver.models.staticipaddress import (
80
84
StaticIPAddressExhaustion,
91
95
from provisioningserver.drivers.osystem import OperatingSystemRegistry
92
96
from provisioningserver.logger import get_maas_logger
93
97
from provisioningserver.rpc.exceptions import MultipleFailures
94
from provisioningserver.tasks import (
98
from provisioningserver.tasks import remove_dhcp_host_map
98
99
from provisioningserver.utils import warn_deprecated
99
100
from provisioningserver.utils.enum import map_enum_reverse
100
101
from provisioningserver.utils.twisted import reactor_sync
399
400
:return: Those Nodes for which shutdown was actually requested.
402
maaslog.debug("Stopping node(s): %s", ids)
403
# Obtain node model objects for each node specified.
403
404
nodes = self.get_nodes(by_user, NODE_PERMISSION.EDIT, ids=ids)
406
power_params = node.get_effective_power_parameters()
408
node_power_type = node.get_effective_power_type()
409
except UnknownPowerType:
410
# Skip the rest of the loop to avoid creating a power
411
# event for a node that we can't power down.
413
"%s: Node has an unknown power type. Not creating "
414
"power down event.", node.hostname)
416
power_params['power_off_mode'] = stop_mode
417
# WAKE_ON_LAN does not support poweroff.
418
if node_power_type != 'ether_wake':
420
"%s: Asking cluster to power off node", node.hostname)
421
power_off.apply_async(
422
queue=node.work_queue, args=[node_power_type],
424
processed_nodes.append(node)
425
return processed_nodes
406
# Helper function to whittle the list of nodes down to those that we
407
# can actually stop, and keep hold of their power control info.
408
def gen_power_info(nodes):
410
power_info = node.get_effective_power_info()
411
if power_info.can_be_stopped:
412
# Smuggle in a hint about how to power-off the node.
413
power_info.power_parameters['power_off_mode'] = stop_mode
414
yield node, power_info
416
# Create info that we can pass into the reactor (no model objects).
417
nodes_start_info = list(
418
(node.system_id, node.hostname, node.nodegroup.uuid, power_info)
419
for node, power_info in gen_power_info(nodes))
421
# Request that these nodes be powered off.
422
deferreds = power_off_nodes(nodes_start_info)
424
# Cap these Deferreds off so that Twisted does not complain about
425
# unhandled errors. We just log errors for now; there are other
426
# channels that will report failures in more detail.
428
for system_id, d in deferreds.viewitems():
429
d.addErrback(twisted.python.log.err)
431
# Return a list of those nodes that we've send power commands for.
432
return list(node for node in nodes if node.system_id in deferreds)
427
434
def start_nodes(self, ids, by_user, user_data=None):
428
435
"""Request on given user's behalf that the given nodes be started up.
500
507
yield node, power_info
502
509
# Create info that we can pass into the reactor (no model objects)
510
nodes_start_info = list(
504
511
(node.system_id, node.hostname, node.nodegroup.uuid, power_info)
505
for node, power_info in gen_power_info(nodes)
512
for node, power_info in gen_power_info(nodes))
508
514
# Request that these nodes be powered on.
509
515
deferreds = power_on_nodes(nodes_start_info)
877
884
mac = MACAddress(mac_address=mac_address, node=self)
887
# See if there's a lease for this MAC and set its
888
# cluster_interface if so.
891
for lease in DHCPLease.objects.filter(nodegroup=self.nodegroup)}
892
update_mac_cluster_interfaces(nodegroup_leases, self.nodegroup)
881
896
def remove_mac_address(self, mac_address):