summaryrefslogtreecommitdiff
path: root/nova/virt/baremetal/iboot_pdu.py
blob: 134c926ac291bbc9f6fd688f01bb63ac00e1685d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# Copyright 2013 Red Hat Inc.
# All Rights Reserved.
#
#    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.
#
# iBoot Power Driver

from oslo.utils import importutils

from nova import exception
from nova.i18n import _
from nova.openstack.common import log as logging
from nova.virt.baremetal import baremetal_states
from nova.virt.baremetal import base

iboot = importutils.try_import('iboot')


LOG = logging.getLogger(__name__)


class IBootManager(base.PowerManager):
    """iBoot Power Driver for Baremetal Nova Compute

    This PowerManager class provides a mechanism for controlling power state
    via an iBoot capable device (tested with an iBoot G2).

    Requires installation of python-iboot:

        https://github.com/darkip/python-iboot

    """
    def __init__(self, **kwargs):
        node = kwargs.pop('node', {})
        addr_relay = str(node['pm_address']).split(',')

        if len(addr_relay) > 1:
            try:
                self.relay_id = int(addr_relay[1])
            except ValueError:
                msg = _("iboot PDU relay ID must be an integer.")
                raise exception.InvalidParameterValue(msg)
        else:
            self.relay_id = 1

        addr_port = addr_relay[0].split(':')
        self.address = addr_port[0]
        if len(addr_port) > 1:
            try:
                self.port = int(addr_port[1])
            except ValueError:
                msg = _("iboot PDU port must be an integer.")
                raise exception.InvalidParameterValue(msg)
        else:
            self.port = 9100

        self.user = str(node['pm_user'])
        self.password = str(node['pm_password'])
        instance = kwargs.pop('instance', {})
        self.node_name = instance.get('hostname', "")
        self.state = None
        self.conn = None

    def _create_connection(self):
        if not self.conn:
            self.conn = iboot.iBootInterface(self.address, self.user,
                                             self.password, port=self.port,
                                             num_relays=self.relay_id)
        return self.conn

    def _switch(self, relay_id, enabled):
        return self.conn.switch(relay_id, enabled)

    def _get_relay(self, relay_id):
        return self.conn.get_relays()[relay_id - 1]

    def activate_node(self):
        LOG.info(_("activate_node name %s"), self.node_name)
        self._create_connection()
        self._switch(self.relay_id, True)

        if self.is_power_on():
            self.state = baremetal_states.ACTIVE
        else:
            self.state = baremetal_states.ERROR

        return self.state

    def reboot_node(self):
        LOG.info(_("reboot_node: %s"), self.node_name)
        self._create_connection()
        self._switch(self.relay_id, False)
        self._switch(self.relay_id, True)

        if self.is_power_on():
            self.state = baremetal_states.ACTIVE
        else:
            self.state = baremetal_states.ERROR

        return self.state

    def deactivate_node(self):
        LOG.info(_("deactivate_node name %s"), self.node_name)
        self._create_connection()
        if self.is_power_on():
            self._switch(self.relay_id, False)

        if self.is_power_on():
            self.state = baremetal_states.ERROR
        else:
            self.state = baremetal_states.DELETED

        return self.state

    def is_power_on(self):
        LOG.debug("Checking if %s is running", self.node_name)
        self._create_connection()
        return self._get_relay(self.relay_id)