archipelago: Add blktap support
[archipelago] / python / archipelago / archipelago.py
1 #!/usr/bin/env python
2
3 # Copyright 2012 GRNET S.A. All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or
6 # without modification, are permitted provided that the following
7 # conditions are met:
8 #
9 #   1. Redistributions of source code must retain the above
10 #      copyright notice, this list of conditions and the following
11 #      disclaimer.
12 #
13 #   2. Redistributions in binary form must reproduce the above
14 #      copyright notice, this list of conditions and the following
15 #      disclaimer in the documentation and/or other materials
16 #      provided with the distribution.
17 #
18 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 # POSSIBILITY OF SUCH DAMAGE.
30 #
31 # The views and conclusions contained in the software and
32 # documentation are those of the authors and should not be
33 # interpreted as representing official policies, either expressed
34 # or implied, of GRNET S.A.
35 #
36
37
38 import os
39 import sys
40 import time
41 import errno
42 from subprocess import check_call
43
44 from .common import *
45 from .vlmc import showmapped as vlmc_showmapped
46 from .vlmc import get_mapped as vlmc_get_mapped
47
48
49 def start_peer(peer, cli=False):
50     if peer.is_running():
51         raise Error("Cannot start peer %s. Peer already running" % peer.role)
52     if cli:
53         s = "Starting %s " % peer.role
54         sys.stdout.write(s.ljust(FIRST_COLUMN_WIDTH))
55     try:
56         peer.start()
57     except Error as e:
58         if cli:
59             sys.stdout.write(red("FAILED".ljust(SECOND_COLUMN_WIDTH)))
60             sys.stdout.write("\n")
61         raise e
62     except Exception as e:
63         if cli:
64             print e
65             sys.stdout.write(red("FAILED".ljust(SECOND_COLUMN_WIDTH)))
66             sys.stdout.write("\n")
67         raise Error("Cannot start %s" % peer.role)
68
69 #TODO configurable
70     i = 0
71     while not peer.is_running():
72         time.sleep(0.1)
73         i += 1
74         if i > 30: #3secs
75             if cli:
76                 sys.stdout.write(red("FAILED".ljust(SECOND_COLUMN_WIDTH)))
77                 sys.stdout.write("\n")
78             raise Error("Couldn't start %s" % peer.role)
79
80     if cli:
81         sys.stdout.write(green("OK".ljust(SECOND_COLUMN_WIDTH)))
82         sys.stdout.write("\n")
83
84
85 def stop_peer(peer, cli=False):
86     try:
87         peer.stop()
88     except Error:
89         if cli:
90             pretty_print(peer.role, yellow("Not running"))
91         return
92     if cli:
93         s = "Stopping %s " % peer.role
94         sys.stdout.write(s.ljust(FIRST_COLUMN_WIDTH))
95
96     i = 0
97     while peer.get_pid():
98         time.sleep(0.1)
99         i += 1
100         if i > 150:
101             if cli:
102                 sys.stdout.write(red("FAILED".ljust(SECOND_COLUMN_WIDTH)))
103                 sys.stdout.write("\n")
104             raise Error("Failed to stop peer %s." % peer.role)
105     if cli:
106         sys.stdout.write(green("OK".ljust(SECOND_COLUMN_WIDTH)))
107         sys.stdout.write("\n")
108
109
110 def peer_running(peer, cli):
111     try:
112         if peer.is_running():
113             if cli:
114                 pretty_print(peer.role, green('running'))
115             return True
116         else:
117             if cli:
118                 pretty_print(peer.role, red('not running'))
119             return False
120     except Error:
121         if cli:
122             pretty_print(peer.role, yellow("Has valid pidfile but does not "
123                                            "seem to be active"))
124         return False
125
126
127 def start_peers(peers, cli=False):
128     for m in modules:
129         if not loaded_module(m):
130             raise Error("Cannot start userspace peers. " + m +
131                         " module not loaded")
132     for r, _ in config['roles']:
133         p = peers[r]
134         start_peer(p, cli)
135
136
137 def stop_peers(peers, cli=False):
138     for r, _ in reversed(config['roles']):
139         p = peers[r]
140         stop_peer(p, cli)
141
142
143 def start(user=False, role=None, cli=False, **kwargs):
144     if role:
145         try:
146             p = peers[role]
147         except KeyError:
148             raise Error("Invalid peer %s" % role)
149         return start_peer(p, cli)
150
151     if user:
152         return start_peers(peers, cli)
153
154     if status() > 0:
155         raise Error("Cannot start. Try stopping first")
156
157     if cli:
158         print "===================="
159         print "Starting archipelago"
160         print "===================="
161         print ""
162     try:
163         get_segment().create()
164         time.sleep(0.5)
165         start_peers(peers, cli)
166         load_module("blktap", None)
167     except Exception as e:
168         if cli:
169             print red(e)
170         stop(user, role, cli)
171
172
173 def stop(user=False, role=None, cli=False, **kwargs):
174     if role:
175         try:
176             p = peers[role]
177         except KeyError:
178             raise Error("Invalid peer %s" % role)
179         return stop_peer(p, cli)
180     if user:
181         return stop_peers(peers, cli)
182     #check devices
183     if cli:
184         print "===================="
185         print "Stoping archipelago"
186         print "===================="
187         print ""
188     if cli:
189         if vlmc_showmapped() > 0:
190             raise Error("Cannot stop archipelago. Mapped volumes exist")
191     else:
192         mapped = vlmc_get_mapped()
193         if mapped and len(mapped) > 0:
194             raise Error("Cannot stop archipelago. Mapped volumes exist")
195     stop_peers(peers, cli)
196
197
198 def status(cli=False, **kwargs):
199     r = 0
200     if cli:
201         if vlmc_showmapped() > 0:
202             r += 1
203     else:
204         mapped = vlmc_get_mapped()
205         if mapped and len(mapped) > 0:
206             r += 1
207     if loaded_module("blktap"):
208         if cli:
209             pretty_print("blktap", green('Loaded'))
210         r += 1
211     else:
212         if cli:
213             pretty_print("blktap", red('Not loaded'))
214     for role, _ in reversed(config['roles']):
215         p = peers[role]
216         if peer_running(p, cli):
217             r += 1
218     return r
219
220
221 def restart(**kwargs):
222     stop(**kwargs)
223     start(**kwargs)