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 """Functions for running helper virtual machines to perform tasks on instances.
32
33 """
34
35 import contextlib
36
37 from ganeti import constants
38 from ganeti import errors
39 from ganeti.utils import retry
40
41 from ganeti.cmdlib.common import IsInstanceRunning, DetermineImageSize
42 from ganeti.cmdlib.instance_storage import StartInstanceDisks, \
43 TemporaryDisk, ImageDisks
44
45
46 @contextlib.contextmanager
47 -def HelperVM(lu, instance, vm_image, startup_timeout, vm_timeout,
48 log_prefix=None, feedback_fn=None):
49 """Runs a given helper VM for a given instance.
50
51 @type lu: L{LogicalUnit}
52 @param lu: the lu on whose behalf we execute
53 @type instance: L{objects.Instance}
54 @param instance: the instance definition
55 @type vm_image: string
56 @param vm_image: the name of the helper VM image to dump on a temporary disk
57 @type startup_timeout: int
58 @param startup_timeout: how long to wait for the helper VM to start up
59 @type vm_timeout: int
60 @param vm_timeout: how long to wait for the helper VM to finish its work
61 @type log_prefix: string
62 @param log_prefix: a prefix for all log messages
63 @type feedback_fn: function
64 @param feedback_fn: Function used to log progress
65
66 """
67 if log_prefix:
68 add_prefix = lambda msg: "%s: %s" % (log_prefix, msg)
69 else:
70 add_prefix = lambda msg: msg
71
72 if feedback_fn is not None:
73 log_feedback = lambda msg: feedback_fn(add_prefix(msg))
74 else:
75 log_feedback = lambda _: None
76
77 try:
78 disk_size = DetermineImageSize(lu, vm_image, instance.primary_node)
79 except errors.OpExecError, err:
80 raise errors.OpExecError("Could not create temporary disk: %s", err)
81
82 with TemporaryDisk(lu,
83 instance,
84 [(constants.DT_PLAIN, constants.DISK_RDWR, disk_size)],
85 log_feedback):
86 log_feedback("Activating helper VM's temporary disks")
87 StartInstanceDisks(lu, instance, False)
88
89 log_feedback("Imaging temporary disks with image %s" % (vm_image, ))
90 ImageDisks(lu, instance, vm_image)
91
92 log_feedback("Starting helper VM")
93 result = lu.rpc.call_instance_start(instance.primary_node,
94 (instance, [], []),
95 False, lu.op.reason)
96 result.Raise(add_prefix("Could not start helper VM with image %s" %
97 (vm_image, )))
98
99
100 running_check = lambda: IsInstanceRunning(lu, instance, prereq=False)
101 instance_up = retry.SimpleRetry(True, running_check, 5.0,
102 startup_timeout)
103 if not instance_up:
104 raise errors.OpExecError(add_prefix("Could not boot instance using"
105 " image %s" % (vm_image, )))
106
107 log_feedback("Helper VM is up")
108
109 def cleanup():
110 log_feedback("Waiting for helper VM to finish")
111
112
113 instance_up = retry.SimpleRetry(False, running_check, 20.0, vm_timeout)
114 if instance_up:
115 lu.LogWarning(add_prefix("Helper VM has not finished within the"
116 " timeout; shutting it down forcibly"))
117 return \
118 lu.rpc.call_instance_shutdown(instance.primary_node,
119 instance,
120 constants.DEFAULT_SHUTDOWN_TIMEOUT,
121 lu.op.reason)
122 else:
123 return None
124
125
126 try:
127 yield
128 except Exception:
129
130 result = cleanup()
131 if result:
132 result.Warn(add_prefix("Could not shut down helper VM with image"
133 " %s within timeout" % (vm_image, )))
134 log_feedback("Error running helper VM with image %s" %
135 (vm_image, ))
136 raise
137 else:
138 result = cleanup()
139
140 if result:
141 result.Raise(add_prefix("Could not shut down helper VM with image %s"
142 " within timeout" % (vm_image, )))
143 raise errors.OpExecError("Error running helper VM with image %s" %
144 (vm_image, ))
145
146 log_feedback("Helper VM execution completed")
147
148
149 -def RunWithHelperVM(lu, instance, vm_image, startup_timeout, vm_timeout,
150 log_prefix=None, feedback_fn=None):
151 """Runs a given helper VM for a given instance.
152
153 @type lu: L{LogicalUnit}
154 @param lu: the lu on whose behalf we execute
155 @type instance: L{objects.Instance}
156 @param instance: the instance definition
157 @type vm_image: string
158 @param vm_image: the name of the helper VM image to dump on a temporary disk
159 @type startup_timeout: int
160 @param startup_timeout: how long to wait for the helper VM to start up
161 @type vm_timeout: int
162 @param vm_timeout: how long to wait for the helper VM to finish its work
163 @type log_prefix: string
164 @param log_prefix: a prefix for all log messages
165 @type feedback_fn: function
166 @param feedback_fn: Function used to log progress
167
168
169 """
170 with HelperVM(lu, instance, vm_image, startup_timeout, vm_timeout,
171 log_prefix=log_prefix, feedback_fn=feedback_fn):
172 pass
173