summaryrefslogtreecommitdiffstats
path: root/openshift-storage-libs/openshiftstoragelibs/node_ops.py
blob: 943ad194f08dcb697fe0db3720f0a5a0910fd920 (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
import time

from glustolibs.gluster.exceptions import ExecutionError
from glusto.core import Glusto as g
import six

from openshiftstoragelibs.cloundproviders.vmware import VmWare
from openshiftstoragelibs import command
from openshiftstoragelibs import exceptions
from openshiftstoragelibs import waiter


CLOUD_PROVIDER = None


def wait_for_ssh_connection(hostname, timeout=600, interval=10):
    """Wait for ssh conection to be ready within given timeout.

    Args:
        hostname (str): hostname of a machine.
    Returns:
        None
    Raises:
        CloudProviderError: In case of any failures.
    """
    for w in waiter.Waiter(timeout, interval):
        try:
            # Run random command to verify ssh connection
            g.run(hostname, 'ls')
            return
        except (exceptions.ExecutionError, ExecutionError):
            g.log.info("Waiting for ssh connection on host '%s'" % hostname)

    msg = 'Not able to connect with the %s' % hostname
    g.log.error(msg)
    raise exceptions.CloudProviderError(msg)


def node_reboot_by_command(
        node, timeout=600, wait_step=10, wait_for_connection=True):
    """Reboot node and wait to start for given timeout.

    Args:
        node (str)          : Node which needs to be rebooted.
        timeout (int)       : Seconds to wait before node to be started.
        wait_step (int)     : Interval in seconds to wait before checking
                              status of node again.
        wait_for_connection : Flag to wait for to check SSH connection to node.
    Raises:
        CloudProviderError: In case of any failures.
    """
    cmd = "sleep 3; /sbin/shutdown -r now 'Reboot triggered by Glusto'"
    ret, out, err = g.run(node, cmd)
    if ret != 255:
        err_msg = "failed to reboot host '{}' error {}".format(node, err)
        g.log.error(err_msg)
        raise AssertionError(err_msg)

    # added sleep as node will restart after 3 sec
    time.sleep(3)

    if wait_for_connection:
        wait_for_ssh_connection(node, timeout=timeout, interval=wait_step)


def _get_cloud_provider():
    """Gather cloud provider facts"""

    global CLOUD_PROVIDER
    if CLOUD_PROVIDER:
        return CLOUD_PROVIDER

    try:
        cloud_provider_name = g.config['cloud_provider']['name']
    except KeyError:
        msg = "Incorrect config file. Cloud provider name is missing."
        g.log.error(msg)
        raise exceptions.ConfigError(msg)

    if cloud_provider_name == 'vmware':
        CLOUD_PROVIDER = VmWare()
    else:
        msg = "Cloud Provider %s is not supported." % cloud_provider_name
        g.log.error(msg)
        raise NotImplementedError(msg)

    return CLOUD_PROVIDER


def find_vm_name_by_ip_or_hostname(ip_or_hostname):
    """Find VM name from the ip or hostname.

    Args:
        ip_or_hostname (str): IP address or hostname of VM.
    Returns:
        str: Name of the VM.
    """
    cloudProvider = _get_cloud_provider()
    g.log.info('getting the name of vm for ip or hostname %s' % ip_or_hostname)
    return cloudProvider.find_vm_name_by_ip_or_hostname(ip_or_hostname)


def get_power_state_of_vm_by_name(name):
    """Get the power state of VM.

    Args:
        name (str): name of the VM for which state has to be find.
    Returns:
        str: Power state of the VM.
    """
    cloudProvider = _get_cloud_provider()
    g.log.info('getting the power state of vm "%s"' % name)
    return cloudProvider.get_power_state_of_vm_by_name(name)


def power_off_vm_by_name(name):
    """Power off the virtual machine.

    Args:
        name (str): name of the VM which needs to be powered off.
    Returns:
        None
    """
    cloudProvider = _get_cloud_provider()
    g.log.info('powering off the vm "%s"' % name)
    cloudProvider.power_off_vm_by_name(name)
    g.log.info('powered off the vm "%s" successfully' % name)


def power_on_vm_by_name(name, timeout=600, interval=10):
    """Power on the virtual machine and wait for SSH ready within given
    timeout.

    Args:
        name (str): name of the VM which needs to be powered on.
    Returns:
        None
    Raises:
        CloudProviderError: In case of any failures.
    """
    cloudProvider = _get_cloud_provider()
    g.log.info('powering on the VM "%s"' % name)
    cloudProvider.power_on_vm_by_name(name)
    g.log.info('Powered on the VM "%s" successfully' % name)

    # Wait for hostname to get assigned
    _waiter = waiter.Waiter(timeout, interval)
    for w in _waiter:
        try:
            hostname = cloudProvider.wait_for_hostname(name, 1, 1)
            # NOTE(vponomar): Reset attempts for waiter to avoid redundant
            # sleep equal to 'interval' on the next usage.
            _waiter._attempt = 0
            break
        except Exception as e:
            g.log.info(e)
    if w.expired:
        raise exceptions.CloudProviderError(e)

    # Wait for hostname to ssh connection ready
    for w in _waiter:
        try:
            wait_for_ssh_connection(hostname, 1, 1)
            break
        except Exception as e:
            g.log.info(e)
    if w.expired:
        raise exceptions.CloudProviderError(e)


def node_add_iptables_rules(node, chain, rules, raise_on_error=True):
    """Append iptables rules

    Args:
        node (str): Node on which iptables rules should be added.
        chain (str): iptables chain in which rule(s) need to be appended.
        rules (str|tuple|list): Rule(s) which need(s) to be added to a chain.
    Reuturns:
        None
    Exception:
        AssertionError: In case command fails to execute and
                        raise_on_error set to True
    """
    rules = [rules] if isinstance(rules, six.string_types) else rules

    add_iptables_rule_cmd = "iptables --append %s %s"
    check_iptables_rule_cmd = "iptables --check %s %s"
    for rule in rules:
        try:
            command.cmd_run(check_iptables_rule_cmd % (chain, rule), node)
        except AssertionError:
            command.cmd_run(
                add_iptables_rule_cmd % (chain, rule), node,
                raise_on_error=raise_on_error)


def node_delete_iptables_rules(node, chain, rules, raise_on_error=True):
    """Delete iptables rules

    Args:
        node (str): Node on which iptables rules should be deleted.
        chain (str): iptables chain from which rule(s) need to be deleted.
        rules (str|tuple|list): Rule(s) which need(s) to be deleted from
                                a chain.
    Reuturns:
        None
    Exception:
        AssertionError: In case command fails to execute and
                        raise_on_error set to True
    """
    rules = [rules] if isinstance(rules, six.string_types) else rules

    delete_iptables_rule_cmd = "iptables --delete %s %s"
    for rule in rules:
        command.cmd_run(
            delete_iptables_rule_cmd % (chain, rule), node,
            raise_on_error=raise_on_error)