Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / instance_utils.py @ b6dd32db

History | View | Annotate | Download (19.2 kB)

1 22b7f6f8 Thomas Thrainer
#
2 22b7f6f8 Thomas Thrainer
#
3 22b7f6f8 Thomas Thrainer
4 22b7f6f8 Thomas Thrainer
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc.
5 22b7f6f8 Thomas Thrainer
#
6 22b7f6f8 Thomas Thrainer
# This program is free software; you can redistribute it and/or modify
7 22b7f6f8 Thomas Thrainer
# it under the terms of the GNU General Public License as published by
8 22b7f6f8 Thomas Thrainer
# the Free Software Foundation; either version 2 of the License, or
9 22b7f6f8 Thomas Thrainer
# (at your option) any later version.
10 22b7f6f8 Thomas Thrainer
#
11 22b7f6f8 Thomas Thrainer
# This program is distributed in the hope that it will be useful, but
12 22b7f6f8 Thomas Thrainer
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 22b7f6f8 Thomas Thrainer
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 22b7f6f8 Thomas Thrainer
# General Public License for more details.
15 22b7f6f8 Thomas Thrainer
#
16 22b7f6f8 Thomas Thrainer
# You should have received a copy of the GNU General Public License
17 22b7f6f8 Thomas Thrainer
# along with this program; if not, write to the Free Software
18 22b7f6f8 Thomas Thrainer
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 22b7f6f8 Thomas Thrainer
# 02110-1301, USA.
20 22b7f6f8 Thomas Thrainer
21 22b7f6f8 Thomas Thrainer
22 22b7f6f8 Thomas Thrainer
"""Utility function mainly, but not only used by instance LU's."""
23 22b7f6f8 Thomas Thrainer
24 22b7f6f8 Thomas Thrainer
import logging
25 22b7f6f8 Thomas Thrainer
import os
26 22b7f6f8 Thomas Thrainer
27 22b7f6f8 Thomas Thrainer
from ganeti import constants
28 22b7f6f8 Thomas Thrainer
from ganeti import errors
29 22b7f6f8 Thomas Thrainer
from ganeti import locking
30 22b7f6f8 Thomas Thrainer
from ganeti import network
31 22b7f6f8 Thomas Thrainer
from ganeti import objects
32 22b7f6f8 Thomas Thrainer
from ganeti import pathutils
33 22b7f6f8 Thomas Thrainer
from ganeti import utils
34 5eacbcae Thomas Thrainer
from ganeti.cmdlib.common import AnnotateDiskParams, \
35 1f7c8208 Helga Velroyen
  ComputeIPolicyInstanceViolation, CheckDiskTemplateEnabled
36 22b7f6f8 Thomas Thrainer
37 22b7f6f8 Thomas Thrainer
38 1c3231aa Thomas Thrainer
def BuildInstanceHookEnv(name, primary_node_name, secondary_node_names, os_type,
39 1c3231aa Thomas Thrainer
                         status, minmem, maxmem, vcpus, nics, disk_template,
40 1c3231aa Thomas Thrainer
                         disks, bep, hvp, hypervisor_name, tags):
41 22b7f6f8 Thomas Thrainer
  """Builds instance related env variables for hooks
42 22b7f6f8 Thomas Thrainer

43 22b7f6f8 Thomas Thrainer
  This builds the hook environment from individual variables.
44 22b7f6f8 Thomas Thrainer

45 22b7f6f8 Thomas Thrainer
  @type name: string
46 22b7f6f8 Thomas Thrainer
  @param name: the name of the instance
47 1c3231aa Thomas Thrainer
  @type primary_node_name: string
48 1c3231aa Thomas Thrainer
  @param primary_node_name: the name of the instance's primary node
49 1c3231aa Thomas Thrainer
  @type secondary_node_names: list
50 1c3231aa Thomas Thrainer
  @param secondary_node_names: list of secondary nodes as strings
51 22b7f6f8 Thomas Thrainer
  @type os_type: string
52 22b7f6f8 Thomas Thrainer
  @param os_type: the name of the instance's OS
53 22b7f6f8 Thomas Thrainer
  @type status: string
54 22b7f6f8 Thomas Thrainer
  @param status: the desired status of the instance
55 22b7f6f8 Thomas Thrainer
  @type minmem: string
56 22b7f6f8 Thomas Thrainer
  @param minmem: the minimum memory size of the instance
57 22b7f6f8 Thomas Thrainer
  @type maxmem: string
58 22b7f6f8 Thomas Thrainer
  @param maxmem: the maximum memory size of the instance
59 22b7f6f8 Thomas Thrainer
  @type vcpus: string
60 22b7f6f8 Thomas Thrainer
  @param vcpus: the count of VCPUs the instance has
61 22b7f6f8 Thomas Thrainer
  @type nics: list
62 d676dbea Sebastian Gebhard
  @param nics: list of tuples (name, uuid, ip, mac, mode, link, vlan, net,
63 d676dbea Sebastian Gebhard
      netinfo) representing the NICs the instance has
64 22b7f6f8 Thomas Thrainer
  @type disk_template: string
65 22b7f6f8 Thomas Thrainer
  @param disk_template: the disk template of the instance
66 22b7f6f8 Thomas Thrainer
  @type disks: list
67 22b7f6f8 Thomas Thrainer
  @param disks: list of tuples (name, uuid, size, mode)
68 22b7f6f8 Thomas Thrainer
  @type bep: dict
69 22b7f6f8 Thomas Thrainer
  @param bep: the backend parameters for the instance
70 22b7f6f8 Thomas Thrainer
  @type hvp: dict
71 22b7f6f8 Thomas Thrainer
  @param hvp: the hypervisor parameters for the instance
72 22b7f6f8 Thomas Thrainer
  @type hypervisor_name: string
73 22b7f6f8 Thomas Thrainer
  @param hypervisor_name: the hypervisor for the instance
74 22b7f6f8 Thomas Thrainer
  @type tags: list
75 22b7f6f8 Thomas Thrainer
  @param tags: list of instance tags as strings
76 22b7f6f8 Thomas Thrainer
  @rtype: dict
77 22b7f6f8 Thomas Thrainer
  @return: the hook environment for this instance
78 22b7f6f8 Thomas Thrainer

79 22b7f6f8 Thomas Thrainer
  """
80 22b7f6f8 Thomas Thrainer
  env = {
81 22b7f6f8 Thomas Thrainer
    "OP_TARGET": name,
82 22b7f6f8 Thomas Thrainer
    "INSTANCE_NAME": name,
83 1c3231aa Thomas Thrainer
    "INSTANCE_PRIMARY": primary_node_name,
84 1c3231aa Thomas Thrainer
    "INSTANCE_SECONDARIES": " ".join(secondary_node_names),
85 22b7f6f8 Thomas Thrainer
    "INSTANCE_OS_TYPE": os_type,
86 22b7f6f8 Thomas Thrainer
    "INSTANCE_STATUS": status,
87 22b7f6f8 Thomas Thrainer
    "INSTANCE_MINMEM": minmem,
88 22b7f6f8 Thomas Thrainer
    "INSTANCE_MAXMEM": maxmem,
89 22b7f6f8 Thomas Thrainer
    # TODO(2.9) remove deprecated "memory" value
90 22b7f6f8 Thomas Thrainer
    "INSTANCE_MEMORY": maxmem,
91 22b7f6f8 Thomas Thrainer
    "INSTANCE_VCPUS": vcpus,
92 22b7f6f8 Thomas Thrainer
    "INSTANCE_DISK_TEMPLATE": disk_template,
93 22b7f6f8 Thomas Thrainer
    "INSTANCE_HYPERVISOR": hypervisor_name,
94 22b7f6f8 Thomas Thrainer
    }
95 22b7f6f8 Thomas Thrainer
  if nics:
96 22b7f6f8 Thomas Thrainer
    nic_count = len(nics)
97 d676dbea Sebastian Gebhard
    for idx, (name, uuid, ip, mac, mode, link, vlan, net, netinfo) \
98 d676dbea Sebastian Gebhard
        in enumerate(nics):
99 22b7f6f8 Thomas Thrainer
      if ip is None:
100 22b7f6f8 Thomas Thrainer
        ip = ""
101 8a348b15 Christos Stavrakakis
      if name:
102 8a348b15 Christos Stavrakakis
        env["INSTANCE_NIC%d_NAME" % idx] = name
103 8a348b15 Christos Stavrakakis
      env["INSTANCE_NIC%d_UUID" % idx] = uuid
104 22b7f6f8 Thomas Thrainer
      env["INSTANCE_NIC%d_IP" % idx] = ip
105 22b7f6f8 Thomas Thrainer
      env["INSTANCE_NIC%d_MAC" % idx] = mac
106 22b7f6f8 Thomas Thrainer
      env["INSTANCE_NIC%d_MODE" % idx] = mode
107 22b7f6f8 Thomas Thrainer
      env["INSTANCE_NIC%d_LINK" % idx] = link
108 d676dbea Sebastian Gebhard
      env["INSTANCE_NIC%d_VLAN" % idx] = vlan
109 22b7f6f8 Thomas Thrainer
      if netinfo:
110 22b7f6f8 Thomas Thrainer
        nobj = objects.Network.FromDict(netinfo)
111 22b7f6f8 Thomas Thrainer
        env.update(nobj.HooksDict("INSTANCE_NIC%d_" % idx))
112 22b7f6f8 Thomas Thrainer
      elif network:
113 22b7f6f8 Thomas Thrainer
        # FIXME: broken network reference: the instance NIC specifies a
114 22b7f6f8 Thomas Thrainer
        # network, but the relevant network entry was not in the config. This
115 22b7f6f8 Thomas Thrainer
        # should be made impossible.
116 22b7f6f8 Thomas Thrainer
        env["INSTANCE_NIC%d_NETWORK_NAME" % idx] = net
117 d676dbea Sebastian Gebhard
      if mode == constants.NIC_MODE_BRIDGED or \
118 d676dbea Sebastian Gebhard
         mode == constants.NIC_MODE_OVS:
119 22b7f6f8 Thomas Thrainer
        env["INSTANCE_NIC%d_BRIDGE" % idx] = link
120 22b7f6f8 Thomas Thrainer
  else:
121 22b7f6f8 Thomas Thrainer
    nic_count = 0
122 22b7f6f8 Thomas Thrainer
123 22b7f6f8 Thomas Thrainer
  env["INSTANCE_NIC_COUNT"] = nic_count
124 22b7f6f8 Thomas Thrainer
125 22b7f6f8 Thomas Thrainer
  if disks:
126 22b7f6f8 Thomas Thrainer
    disk_count = len(disks)
127 8a348b15 Christos Stavrakakis
    for idx, (name, uuid, size, mode) in enumerate(disks):
128 8a348b15 Christos Stavrakakis
      if name:
129 8a348b15 Christos Stavrakakis
        env["INSTANCE_DISK%d_NAME" % idx] = name
130 8a348b15 Christos Stavrakakis
      env["INSTANCE_DISK%d_UUID" % idx] = uuid
131 22b7f6f8 Thomas Thrainer
      env["INSTANCE_DISK%d_SIZE" % idx] = size
132 22b7f6f8 Thomas Thrainer
      env["INSTANCE_DISK%d_MODE" % idx] = mode
133 22b7f6f8 Thomas Thrainer
  else:
134 22b7f6f8 Thomas Thrainer
    disk_count = 0
135 22b7f6f8 Thomas Thrainer
136 22b7f6f8 Thomas Thrainer
  env["INSTANCE_DISK_COUNT"] = disk_count
137 22b7f6f8 Thomas Thrainer
138 22b7f6f8 Thomas Thrainer
  if not tags:
139 22b7f6f8 Thomas Thrainer
    tags = []
140 22b7f6f8 Thomas Thrainer
141 22b7f6f8 Thomas Thrainer
  env["INSTANCE_TAGS"] = " ".join(tags)
142 22b7f6f8 Thomas Thrainer
143 22b7f6f8 Thomas Thrainer
  for source, kind in [(bep, "BE"), (hvp, "HV")]:
144 22b7f6f8 Thomas Thrainer
    for key, value in source.items():
145 22b7f6f8 Thomas Thrainer
      env["INSTANCE_%s_%s" % (kind, key)] = value
146 22b7f6f8 Thomas Thrainer
147 22b7f6f8 Thomas Thrainer
  return env
148 22b7f6f8 Thomas Thrainer
149 22b7f6f8 Thomas Thrainer
150 5eacbcae Thomas Thrainer
def BuildInstanceHookEnvByObject(lu, instance, override=None):
151 22b7f6f8 Thomas Thrainer
  """Builds instance related env variables for hooks from an object.
152 22b7f6f8 Thomas Thrainer

153 22b7f6f8 Thomas Thrainer
  @type lu: L{LogicalUnit}
154 22b7f6f8 Thomas Thrainer
  @param lu: the logical unit on whose behalf we execute
155 22b7f6f8 Thomas Thrainer
  @type instance: L{objects.Instance}
156 22b7f6f8 Thomas Thrainer
  @param instance: the instance for which we should build the
157 22b7f6f8 Thomas Thrainer
      environment
158 22b7f6f8 Thomas Thrainer
  @type override: dict
159 22b7f6f8 Thomas Thrainer
  @param override: dictionary with key/values that will override
160 22b7f6f8 Thomas Thrainer
      our values
161 22b7f6f8 Thomas Thrainer
  @rtype: dict
162 22b7f6f8 Thomas Thrainer
  @return: the hook environment dictionary
163 22b7f6f8 Thomas Thrainer

164 22b7f6f8 Thomas Thrainer
  """
165 22b7f6f8 Thomas Thrainer
  cluster = lu.cfg.GetClusterInfo()
166 22b7f6f8 Thomas Thrainer
  bep = cluster.FillBE(instance)
167 22b7f6f8 Thomas Thrainer
  hvp = cluster.FillHV(instance)
168 6ccce5d4 Ilias Tsitsimpis
  secondary_nodes = lu.cfg.GetInstanceSecondaryNodes(instance)
169 22b7f6f8 Thomas Thrainer
  args = {
170 22b7f6f8 Thomas Thrainer
    "name": instance.name,
171 1c3231aa Thomas Thrainer
    "primary_node_name": lu.cfg.GetNodeName(instance.primary_node),
172 6ccce5d4 Ilias Tsitsimpis
    "secondary_node_names": lu.cfg.GetNodeNames(secondary_nodes),
173 22b7f6f8 Thomas Thrainer
    "os_type": instance.os,
174 22b7f6f8 Thomas Thrainer
    "status": instance.admin_state,
175 22b7f6f8 Thomas Thrainer
    "maxmem": bep[constants.BE_MAXMEM],
176 22b7f6f8 Thomas Thrainer
    "minmem": bep[constants.BE_MINMEM],
177 22b7f6f8 Thomas Thrainer
    "vcpus": bep[constants.BE_VCPUS],
178 5eacbcae Thomas Thrainer
    "nics": NICListToTuple(lu, instance.nics),
179 22b7f6f8 Thomas Thrainer
    "disk_template": instance.disk_template,
180 8a348b15 Christos Stavrakakis
    "disks": [(disk.name, disk.uuid, disk.size, disk.mode)
181 22b7f6f8 Thomas Thrainer
              for disk in instance.disks],
182 22b7f6f8 Thomas Thrainer
    "bep": bep,
183 22b7f6f8 Thomas Thrainer
    "hvp": hvp,
184 22b7f6f8 Thomas Thrainer
    "hypervisor_name": instance.hypervisor,
185 22b7f6f8 Thomas Thrainer
    "tags": instance.tags,
186 22b7f6f8 Thomas Thrainer
  }
187 22b7f6f8 Thomas Thrainer
  if override:
188 22b7f6f8 Thomas Thrainer
    args.update(override)
189 5eacbcae Thomas Thrainer
  return BuildInstanceHookEnv(**args) # pylint: disable=W0142
190 22b7f6f8 Thomas Thrainer
191 22b7f6f8 Thomas Thrainer
192 5eacbcae Thomas Thrainer
def GetClusterDomainSecret():
193 22b7f6f8 Thomas Thrainer
  """Reads the cluster domain secret.
194 22b7f6f8 Thomas Thrainer

195 22b7f6f8 Thomas Thrainer
  """
196 22b7f6f8 Thomas Thrainer
  return utils.ReadOneLineFile(pathutils.CLUSTER_DOMAIN_SECRET_FILE,
197 22b7f6f8 Thomas Thrainer
                               strict=True)
198 22b7f6f8 Thomas Thrainer
199 22b7f6f8 Thomas Thrainer
200 1c3231aa Thomas Thrainer
def CheckNodeNotDrained(lu, node_uuid):
201 22b7f6f8 Thomas Thrainer
  """Ensure that a given node is not drained.
202 22b7f6f8 Thomas Thrainer

203 22b7f6f8 Thomas Thrainer
  @param lu: the LU on behalf of which we make the check
204 1c3231aa Thomas Thrainer
  @param node_uuid: the node to check
205 22b7f6f8 Thomas Thrainer
  @raise errors.OpPrereqError: if the node is drained
206 22b7f6f8 Thomas Thrainer

207 22b7f6f8 Thomas Thrainer
  """
208 c214896c Thomas Thrainer
  node = lu.cfg.GetNodeInfo(node_uuid)
209 c214896c Thomas Thrainer
  if node.drained:
210 c214896c Thomas Thrainer
    raise errors.OpPrereqError("Can't use drained node %s" % node.name,
211 22b7f6f8 Thomas Thrainer
                               errors.ECODE_STATE)
212 22b7f6f8 Thomas Thrainer
213 22b7f6f8 Thomas Thrainer
214 1c3231aa Thomas Thrainer
def CheckNodeVmCapable(lu, node_uuid):
215 763ad5be Thomas Thrainer
  """Ensure that a given node is vm capable.
216 22b7f6f8 Thomas Thrainer

217 763ad5be Thomas Thrainer
  @param lu: the LU on behalf of which we make the check
218 1c3231aa Thomas Thrainer
  @param node_uuid: the node to check
219 763ad5be Thomas Thrainer
  @raise errors.OpPrereqError: if the node is not vm capable
220 22b7f6f8 Thomas Thrainer

221 22b7f6f8 Thomas Thrainer
  """
222 1c3231aa Thomas Thrainer
  if not lu.cfg.GetNodeInfo(node_uuid).vm_capable:
223 1c3231aa Thomas Thrainer
    raise errors.OpPrereqError("Can't use non-vm_capable node %s" % node_uuid,
224 763ad5be Thomas Thrainer
                               errors.ECODE_STATE)
225 22b7f6f8 Thomas Thrainer
226 22b7f6f8 Thomas Thrainer
227 5eacbcae Thomas Thrainer
def RemoveInstance(lu, feedback_fn, instance, ignore_failures):
228 22b7f6f8 Thomas Thrainer
  """Utility function to remove an instance.
229 22b7f6f8 Thomas Thrainer

230 22b7f6f8 Thomas Thrainer
  """
231 22b7f6f8 Thomas Thrainer
  logging.info("Removing block devices for instance %s", instance.name)
232 22b7f6f8 Thomas Thrainer
233 5eacbcae Thomas Thrainer
  if not RemoveDisks(lu, instance, ignore_failures=ignore_failures):
234 22b7f6f8 Thomas Thrainer
    if not ignore_failures:
235 22b7f6f8 Thomas Thrainer
      raise errors.OpExecError("Can't remove instance's disks")
236 22b7f6f8 Thomas Thrainer
    feedback_fn("Warning: can't remove instance's disks")
237 22b7f6f8 Thomas Thrainer
238 22b7f6f8 Thomas Thrainer
  logging.info("Removing instance %s out of cluster config", instance.name)
239 22b7f6f8 Thomas Thrainer
240 da4a52a3 Thomas Thrainer
  lu.cfg.RemoveInstance(instance.uuid)
241 22b7f6f8 Thomas Thrainer
242 22b7f6f8 Thomas Thrainer
  assert not lu.remove_locks.get(locking.LEVEL_INSTANCE), \
243 22b7f6f8 Thomas Thrainer
    "Instance lock removal conflict"
244 22b7f6f8 Thomas Thrainer
245 22b7f6f8 Thomas Thrainer
  # Remove lock for the instance
246 22b7f6f8 Thomas Thrainer
  lu.remove_locks[locking.LEVEL_INSTANCE] = instance.name
247 22b7f6f8 Thomas Thrainer
248 22b7f6f8 Thomas Thrainer
249 1c3231aa Thomas Thrainer
def RemoveDisks(lu, instance, target_node_uuid=None, ignore_failures=False):
250 22b7f6f8 Thomas Thrainer
  """Remove all disks for an instance.
251 22b7f6f8 Thomas Thrainer

252 22b7f6f8 Thomas Thrainer
  This abstracts away some work from `AddInstance()` and
253 22b7f6f8 Thomas Thrainer
  `RemoveInstance()`. Note that in case some of the devices couldn't
254 22b7f6f8 Thomas Thrainer
  be removed, the removal will continue with the other ones.
255 22b7f6f8 Thomas Thrainer

256 22b7f6f8 Thomas Thrainer
  @type lu: L{LogicalUnit}
257 22b7f6f8 Thomas Thrainer
  @param lu: the logical unit on whose behalf we execute
258 22b7f6f8 Thomas Thrainer
  @type instance: L{objects.Instance}
259 22b7f6f8 Thomas Thrainer
  @param instance: the instance whose disks we should remove
260 1c3231aa Thomas Thrainer
  @type target_node_uuid: string
261 1c3231aa Thomas Thrainer
  @param target_node_uuid: used to override the node on which to remove the
262 1c3231aa Thomas Thrainer
          disks
263 22b7f6f8 Thomas Thrainer
  @rtype: boolean
264 22b7f6f8 Thomas Thrainer
  @return: the success of the removal
265 22b7f6f8 Thomas Thrainer

266 22b7f6f8 Thomas Thrainer
  """
267 22b7f6f8 Thomas Thrainer
  logging.info("Removing block devices for instance %s", instance.name)
268 22b7f6f8 Thomas Thrainer
269 22b7f6f8 Thomas Thrainer
  all_result = True
270 22b7f6f8 Thomas Thrainer
  ports_to_release = set()
271 5eacbcae Thomas Thrainer
  anno_disks = AnnotateDiskParams(instance, instance.disks, lu.cfg)
272 22b7f6f8 Thomas Thrainer
  for (idx, device) in enumerate(anno_disks):
273 1c3231aa Thomas Thrainer
    if target_node_uuid:
274 1c3231aa Thomas Thrainer
      edata = [(target_node_uuid, device)]
275 22b7f6f8 Thomas Thrainer
    else:
276 22b7f6f8 Thomas Thrainer
      edata = device.ComputeNodeTree(instance.primary_node)
277 1c3231aa Thomas Thrainer
    for node_uuid, disk in edata:
278 0c3d9c7c Thomas Thrainer
      result = lu.rpc.call_blockdev_remove(node_uuid, (disk, instance))
279 22b7f6f8 Thomas Thrainer
      if result.fail_msg:
280 22b7f6f8 Thomas Thrainer
        lu.LogWarning("Could not remove disk %s on node %s,"
281 1c3231aa Thomas Thrainer
                      " continuing anyway: %s", idx,
282 1c3231aa Thomas Thrainer
                      lu.cfg.GetNodeName(node_uuid), result.fail_msg)
283 1c3231aa Thomas Thrainer
        if not (result.offline and node_uuid != instance.primary_node):
284 22b7f6f8 Thomas Thrainer
          all_result = False
285 22b7f6f8 Thomas Thrainer
286 22b7f6f8 Thomas Thrainer
    # if this is a DRBD disk, return its port to the pool
287 66a37e7a Helga Velroyen
    if device.dev_type in constants.DTS_DRBD:
288 22b7f6f8 Thomas Thrainer
      ports_to_release.add(device.logical_id[2])
289 22b7f6f8 Thomas Thrainer
290 22b7f6f8 Thomas Thrainer
  if all_result or ignore_failures:
291 22b7f6f8 Thomas Thrainer
    for port in ports_to_release:
292 22b7f6f8 Thomas Thrainer
      lu.cfg.AddTcpUdpPort(port)
293 22b7f6f8 Thomas Thrainer
294 1f7c8208 Helga Velroyen
  CheckDiskTemplateEnabled(lu.cfg.GetClusterInfo(), instance.disk_template)
295 1f7c8208 Helga Velroyen
296 845b7ed1 Santi Raffa
  if instance.disk_template in [constants.DT_FILE, constants.DT_SHARED_FILE]:
297 7e219d1b Klaus Aehlig
    if len(instance.disks) > 0:
298 7e219d1b Klaus Aehlig
      file_storage_dir = os.path.dirname(instance.disks[0].logical_id[1])
299 7e219d1b Klaus Aehlig
    else:
300 7e219d1b Klaus Aehlig
      if instance.disk_template == constants.DT_SHARED_FILE:
301 7e219d1b Klaus Aehlig
        file_storage_dir = utils.PathJoin(lu.cfg.GetSharedFileStorageDir(),
302 7e219d1b Klaus Aehlig
                                          instance.name)
303 7e219d1b Klaus Aehlig
      else:
304 7e219d1b Klaus Aehlig
        file_storage_dir = utils.PathJoin(lu.cfg.GetFileStorageDir(),
305 7e219d1b Klaus Aehlig
                                          instance.name)
306 1c3231aa Thomas Thrainer
    if target_node_uuid:
307 1c3231aa Thomas Thrainer
      tgt = target_node_uuid
308 22b7f6f8 Thomas Thrainer
    else:
309 22b7f6f8 Thomas Thrainer
      tgt = instance.primary_node
310 22b7f6f8 Thomas Thrainer
    result = lu.rpc.call_file_storage_dir_remove(tgt, file_storage_dir)
311 22b7f6f8 Thomas Thrainer
    if result.fail_msg:
312 22b7f6f8 Thomas Thrainer
      lu.LogWarning("Could not remove directory '%s' on node %s: %s",
313 1c3231aa Thomas Thrainer
                    file_storage_dir, lu.cfg.GetNodeName(tgt), result.fail_msg)
314 22b7f6f8 Thomas Thrainer
      all_result = False
315 22b7f6f8 Thomas Thrainer
316 22b7f6f8 Thomas Thrainer
  return all_result
317 22b7f6f8 Thomas Thrainer
318 22b7f6f8 Thomas Thrainer
319 5eacbcae Thomas Thrainer
def NICToTuple(lu, nic):
320 22b7f6f8 Thomas Thrainer
  """Build a tupple of nic information.
321 22b7f6f8 Thomas Thrainer

322 22b7f6f8 Thomas Thrainer
  @type lu:  L{LogicalUnit}
323 22b7f6f8 Thomas Thrainer
  @param lu: the logical unit on whose behalf we execute
324 22b7f6f8 Thomas Thrainer
  @type nic: L{objects.NIC}
325 22b7f6f8 Thomas Thrainer
  @param nic: nic to convert to hooks tuple
326 22b7f6f8 Thomas Thrainer

327 22b7f6f8 Thomas Thrainer
  """
328 22b7f6f8 Thomas Thrainer
  cluster = lu.cfg.GetClusterInfo()
329 22b7f6f8 Thomas Thrainer
  filled_params = cluster.SimpleFillNIC(nic.nicparams)
330 22b7f6f8 Thomas Thrainer
  mode = filled_params[constants.NIC_MODE]
331 22b7f6f8 Thomas Thrainer
  link = filled_params[constants.NIC_LINK]
332 d676dbea Sebastian Gebhard
  vlan = filled_params[constants.NIC_VLAN]
333 22b7f6f8 Thomas Thrainer
  netinfo = None
334 22b7f6f8 Thomas Thrainer
  if nic.network:
335 22b7f6f8 Thomas Thrainer
    nobj = lu.cfg.GetNetwork(nic.network)
336 22b7f6f8 Thomas Thrainer
    netinfo = objects.Network.ToDict(nobj)
337 d676dbea Sebastian Gebhard
  return (nic.name, nic.uuid, nic.ip, nic.mac, mode, link, vlan,
338 d676dbea Sebastian Gebhard
          nic.network, netinfo)
339 22b7f6f8 Thomas Thrainer
340 22b7f6f8 Thomas Thrainer
341 5eacbcae Thomas Thrainer
def NICListToTuple(lu, nics):
342 22b7f6f8 Thomas Thrainer
  """Build a list of nic information tuples.
343 22b7f6f8 Thomas Thrainer

344 22b7f6f8 Thomas Thrainer
  This list is suitable to be passed to _BuildInstanceHookEnv or as a return
345 22b7f6f8 Thomas Thrainer
  value in LUInstanceQueryData.
346 22b7f6f8 Thomas Thrainer

347 22b7f6f8 Thomas Thrainer
  @type lu:  L{LogicalUnit}
348 22b7f6f8 Thomas Thrainer
  @param lu: the logical unit on whose behalf we execute
349 22b7f6f8 Thomas Thrainer
  @type nics: list of L{objects.NIC}
350 22b7f6f8 Thomas Thrainer
  @param nics: list of nics to convert to hooks tuples
351 22b7f6f8 Thomas Thrainer

352 22b7f6f8 Thomas Thrainer
  """
353 22b7f6f8 Thomas Thrainer
  hooks_nics = []
354 22b7f6f8 Thomas Thrainer
  for nic in nics:
355 5eacbcae Thomas Thrainer
    hooks_nics.append(NICToTuple(lu, nic))
356 22b7f6f8 Thomas Thrainer
  return hooks_nics
357 763ad5be Thomas Thrainer
358 763ad5be Thomas Thrainer
359 5eacbcae Thomas Thrainer
def CopyLockList(names):
360 763ad5be Thomas Thrainer
  """Makes a copy of a list of lock names.
361 763ad5be Thomas Thrainer

362 763ad5be Thomas Thrainer
  Handles L{locking.ALL_SET} correctly.
363 763ad5be Thomas Thrainer

364 763ad5be Thomas Thrainer
  """
365 763ad5be Thomas Thrainer
  if names == locking.ALL_SET:
366 763ad5be Thomas Thrainer
    return locking.ALL_SET
367 763ad5be Thomas Thrainer
  else:
368 763ad5be Thomas Thrainer
    return names[:]
369 763ad5be Thomas Thrainer
370 763ad5be Thomas Thrainer
371 5eacbcae Thomas Thrainer
def ReleaseLocks(lu, level, names=None, keep=None):
372 763ad5be Thomas Thrainer
  """Releases locks owned by an LU.
373 763ad5be Thomas Thrainer

374 763ad5be Thomas Thrainer
  @type lu: L{LogicalUnit}
375 763ad5be Thomas Thrainer
  @param level: Lock level
376 763ad5be Thomas Thrainer
  @type names: list or None
377 763ad5be Thomas Thrainer
  @param names: Names of locks to release
378 763ad5be Thomas Thrainer
  @type keep: list or None
379 763ad5be Thomas Thrainer
  @param keep: Names of locks to retain
380 763ad5be Thomas Thrainer

381 763ad5be Thomas Thrainer
  """
382 763ad5be Thomas Thrainer
  assert not (keep is not None and names is not None), \
383 763ad5be Thomas Thrainer
         "Only one of the 'names' and the 'keep' parameters can be given"
384 763ad5be Thomas Thrainer
385 763ad5be Thomas Thrainer
  if names is not None:
386 763ad5be Thomas Thrainer
    should_release = names.__contains__
387 763ad5be Thomas Thrainer
  elif keep:
388 763ad5be Thomas Thrainer
    should_release = lambda name: name not in keep
389 763ad5be Thomas Thrainer
  else:
390 763ad5be Thomas Thrainer
    should_release = None
391 763ad5be Thomas Thrainer
392 763ad5be Thomas Thrainer
  owned = lu.owned_locks(level)
393 763ad5be Thomas Thrainer
  if not owned:
394 763ad5be Thomas Thrainer
    # Not owning any lock at this level, do nothing
395 763ad5be Thomas Thrainer
    pass
396 763ad5be Thomas Thrainer
397 763ad5be Thomas Thrainer
  elif should_release:
398 763ad5be Thomas Thrainer
    retain = []
399 763ad5be Thomas Thrainer
    release = []
400 763ad5be Thomas Thrainer
401 763ad5be Thomas Thrainer
    # Determine which locks to release
402 763ad5be Thomas Thrainer
    for name in owned:
403 763ad5be Thomas Thrainer
      if should_release(name):
404 763ad5be Thomas Thrainer
        release.append(name)
405 763ad5be Thomas Thrainer
      else:
406 763ad5be Thomas Thrainer
        retain.append(name)
407 763ad5be Thomas Thrainer
408 763ad5be Thomas Thrainer
    assert len(lu.owned_locks(level)) == (len(retain) + len(release))
409 763ad5be Thomas Thrainer
410 763ad5be Thomas Thrainer
    # Release just some locks
411 763ad5be Thomas Thrainer
    lu.glm.release(level, names=release)
412 763ad5be Thomas Thrainer
413 763ad5be Thomas Thrainer
    assert frozenset(lu.owned_locks(level)) == frozenset(retain)
414 763ad5be Thomas Thrainer
  else:
415 763ad5be Thomas Thrainer
    # Release everything
416 763ad5be Thomas Thrainer
    lu.glm.release(level)
417 763ad5be Thomas Thrainer
418 763ad5be Thomas Thrainer
    assert not lu.glm.is_owned(level), "No locks should be owned"
419 763ad5be Thomas Thrainer
420 763ad5be Thomas Thrainer
421 763ad5be Thomas Thrainer
def _ComputeIPolicyNodeViolation(ipolicy, instance, current_group,
422 763ad5be Thomas Thrainer
                                 target_group, cfg,
423 5eacbcae Thomas Thrainer
                                 _compute_fn=ComputeIPolicyInstanceViolation):
424 763ad5be Thomas Thrainer
  """Compute if instance meets the specs of the new target group.
425 763ad5be Thomas Thrainer

426 763ad5be Thomas Thrainer
  @param ipolicy: The ipolicy to verify
427 763ad5be Thomas Thrainer
  @param instance: The instance object to verify
428 763ad5be Thomas Thrainer
  @param current_group: The current group of the instance
429 763ad5be Thomas Thrainer
  @param target_group: The new group of the instance
430 763ad5be Thomas Thrainer
  @type cfg: L{config.ConfigWriter}
431 763ad5be Thomas Thrainer
  @param cfg: Cluster configuration
432 763ad5be Thomas Thrainer
  @param _compute_fn: The function to verify ipolicy (unittest only)
433 5eacbcae Thomas Thrainer
  @see: L{ganeti.cmdlib.common.ComputeIPolicySpecViolation}
434 763ad5be Thomas Thrainer

435 763ad5be Thomas Thrainer
  """
436 763ad5be Thomas Thrainer
  if current_group == target_group:
437 763ad5be Thomas Thrainer
    return []
438 763ad5be Thomas Thrainer
  else:
439 763ad5be Thomas Thrainer
    return _compute_fn(ipolicy, instance, cfg)
440 763ad5be Thomas Thrainer
441 763ad5be Thomas Thrainer
442 5eacbcae Thomas Thrainer
def CheckTargetNodeIPolicy(lu, ipolicy, instance, node, cfg, ignore=False,
443 5eacbcae Thomas Thrainer
                           _compute_fn=_ComputeIPolicyNodeViolation):
444 763ad5be Thomas Thrainer
  """Checks that the target node is correct in terms of instance policy.
445 763ad5be Thomas Thrainer

446 763ad5be Thomas Thrainer
  @param ipolicy: The ipolicy to verify
447 763ad5be Thomas Thrainer
  @param instance: The instance object to verify
448 763ad5be Thomas Thrainer
  @param node: The new node to relocate
449 763ad5be Thomas Thrainer
  @type cfg: L{config.ConfigWriter}
450 763ad5be Thomas Thrainer
  @param cfg: Cluster configuration
451 763ad5be Thomas Thrainer
  @param ignore: Ignore violations of the ipolicy
452 763ad5be Thomas Thrainer
  @param _compute_fn: The function to verify ipolicy (unittest only)
453 5eacbcae Thomas Thrainer
  @see: L{ganeti.cmdlib.common.ComputeIPolicySpecViolation}
454 763ad5be Thomas Thrainer

455 763ad5be Thomas Thrainer
  """
456 763ad5be Thomas Thrainer
  primary_node = lu.cfg.GetNodeInfo(instance.primary_node)
457 763ad5be Thomas Thrainer
  res = _compute_fn(ipolicy, instance, primary_node.group, node.group, cfg)
458 763ad5be Thomas Thrainer
459 763ad5be Thomas Thrainer
  if res:
460 763ad5be Thomas Thrainer
    msg = ("Instance does not meet target node group's (%s) instance"
461 763ad5be Thomas Thrainer
           " policy: %s") % (node.group, utils.CommaJoin(res))
462 763ad5be Thomas Thrainer
    if ignore:
463 763ad5be Thomas Thrainer
      lu.LogWarning(msg)
464 763ad5be Thomas Thrainer
    else:
465 763ad5be Thomas Thrainer
      raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
466 763ad5be Thomas Thrainer
467 763ad5be Thomas Thrainer
468 5eacbcae Thomas Thrainer
def GetInstanceInfoText(instance):
469 763ad5be Thomas Thrainer
  """Compute that text that should be added to the disk's metadata.
470 763ad5be Thomas Thrainer

471 763ad5be Thomas Thrainer
  """
472 763ad5be Thomas Thrainer
  return "originstname+%s" % instance.name
473 87e25be1 Thomas Thrainer
474 87e25be1 Thomas Thrainer
475 1c3231aa Thomas Thrainer
def CheckNodeFreeMemory(lu, node_uuid, reason, requested, hvname, hvparams):
476 87e25be1 Thomas Thrainer
  """Checks if a node has enough free memory.
477 87e25be1 Thomas Thrainer

478 87e25be1 Thomas Thrainer
  This function checks if a given node has the needed amount of free
479 87e25be1 Thomas Thrainer
  memory. In case the node has less memory or we cannot get the
480 87e25be1 Thomas Thrainer
  information from the node, this function raises an OpPrereqError
481 87e25be1 Thomas Thrainer
  exception.
482 87e25be1 Thomas Thrainer

483 87e25be1 Thomas Thrainer
  @type lu: C{LogicalUnit}
484 87e25be1 Thomas Thrainer
  @param lu: a logical unit from which we get configuration data
485 1c3231aa Thomas Thrainer
  @type node_uuid: C{str}
486 1c3231aa Thomas Thrainer
  @param node_uuid: the node to check
487 87e25be1 Thomas Thrainer
  @type reason: C{str}
488 87e25be1 Thomas Thrainer
  @param reason: string to use in the error message
489 87e25be1 Thomas Thrainer
  @type requested: C{int}
490 87e25be1 Thomas Thrainer
  @param requested: the amount of memory in MiB to check for
491 a295eb80 Helga Velroyen
  @type hvname: string
492 a295eb80 Helga Velroyen
  @param hvname: the hypervisor's name
493 a295eb80 Helga Velroyen
  @type hvparams: dict of strings
494 a295eb80 Helga Velroyen
  @param hvparams: the hypervisor's parameters
495 87e25be1 Thomas Thrainer
  @rtype: integer
496 87e25be1 Thomas Thrainer
  @return: node current free memory
497 87e25be1 Thomas Thrainer
  @raise errors.OpPrereqError: if the node doesn't have enough memory, or
498 87e25be1 Thomas Thrainer
      we cannot check the node
499 87e25be1 Thomas Thrainer

500 87e25be1 Thomas Thrainer
  """
501 1c3231aa Thomas Thrainer
  node_name = lu.cfg.GetNodeName(node_uuid)
502 da803ff1 Helga Velroyen
  nodeinfo = lu.rpc.call_node_info([node_uuid], None, [(hvname, hvparams)])
503 1c3231aa Thomas Thrainer
  nodeinfo[node_uuid].Raise("Can't get data from node %s" % node_name,
504 1c3231aa Thomas Thrainer
                            prereq=True, ecode=errors.ECODE_ENVIRON)
505 1c3231aa Thomas Thrainer
  (_, _, (hv_info, )) = nodeinfo[node_uuid].payload
506 87e25be1 Thomas Thrainer
507 87e25be1 Thomas Thrainer
  free_mem = hv_info.get("memory_free", None)
508 87e25be1 Thomas Thrainer
  if not isinstance(free_mem, int):
509 87e25be1 Thomas Thrainer
    raise errors.OpPrereqError("Can't compute free memory on node %s, result"
510 1c3231aa Thomas Thrainer
                               " was '%s'" % (node_name, free_mem),
511 87e25be1 Thomas Thrainer
                               errors.ECODE_ENVIRON)
512 87e25be1 Thomas Thrainer
  if requested > free_mem:
513 87e25be1 Thomas Thrainer
    raise errors.OpPrereqError("Not enough memory on node %s for %s:"
514 87e25be1 Thomas Thrainer
                               " needed %s MiB, available %s MiB" %
515 1c3231aa Thomas Thrainer
                               (node_name, reason, requested, free_mem),
516 87e25be1 Thomas Thrainer
                               errors.ECODE_NORES)
517 87e25be1 Thomas Thrainer
  return free_mem
518 87e25be1 Thomas Thrainer
519 87e25be1 Thomas Thrainer
520 1c3231aa Thomas Thrainer
def CheckInstanceBridgesExist(lu, instance, node_uuid=None):
521 87e25be1 Thomas Thrainer
  """Check that the brigdes needed by an instance exist.
522 87e25be1 Thomas Thrainer

523 87e25be1 Thomas Thrainer
  """
524 1c3231aa Thomas Thrainer
  if node_uuid is None:
525 1c3231aa Thomas Thrainer
    node_uuid = instance.primary_node
526 1c3231aa Thomas Thrainer
  CheckNicsBridgesExist(lu, instance.nics, node_uuid)
527 87e25be1 Thomas Thrainer
528 87e25be1 Thomas Thrainer
529 1c3231aa Thomas Thrainer
def CheckNicsBridgesExist(lu, nics, node_uuid):
530 87e25be1 Thomas Thrainer
  """Check that the brigdes needed by a list of nics exist.
531 87e25be1 Thomas Thrainer

532 87e25be1 Thomas Thrainer
  """
533 87e25be1 Thomas Thrainer
  cluster = lu.cfg.GetClusterInfo()
534 1c3231aa Thomas Thrainer
  paramslist = [cluster.SimpleFillNIC(nic.nicparams) for nic in nics]
535 87e25be1 Thomas Thrainer
  brlist = [params[constants.NIC_LINK] for params in paramslist
536 87e25be1 Thomas Thrainer
            if params[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED]
537 87e25be1 Thomas Thrainer
  if brlist:
538 1c3231aa Thomas Thrainer
    result = lu.rpc.call_bridges_exist(node_uuid, brlist)
539 87e25be1 Thomas Thrainer
    result.Raise("Error checking bridges on destination node '%s'" %
540 1c3231aa Thomas Thrainer
                 lu.cfg.GetNodeName(node_uuid), prereq=True,
541 1c3231aa Thomas Thrainer
                 ecode=errors.ECODE_ENVIRON)
542 13f6af81 Thomas Thrainer
543 13f6af81 Thomas Thrainer
544 1c3231aa Thomas Thrainer
def CheckNodeHasOS(lu, node_uuid, os_name, force_variant):
545 13f6af81 Thomas Thrainer
  """Ensure that a node supports a given OS.
546 13f6af81 Thomas Thrainer

547 13f6af81 Thomas Thrainer
  @param lu: the LU on behalf of which we make the check
548 1c3231aa Thomas Thrainer
  @param node_uuid: the node to check
549 13f6af81 Thomas Thrainer
  @param os_name: the OS to query about
550 13f6af81 Thomas Thrainer
  @param force_variant: whether to ignore variant errors
551 13f6af81 Thomas Thrainer
  @raise errors.OpPrereqError: if the node is not supporting the OS
552 13f6af81 Thomas Thrainer

553 13f6af81 Thomas Thrainer
  """
554 1c3231aa Thomas Thrainer
  result = lu.rpc.call_os_get(node_uuid, os_name)
555 13f6af81 Thomas Thrainer
  result.Raise("OS '%s' not in supported OS list for node %s" %
556 1c3231aa Thomas Thrainer
               (os_name, lu.cfg.GetNodeName(node_uuid)),
557 13f6af81 Thomas Thrainer
               prereq=True, ecode=errors.ECODE_INVAL)
558 13f6af81 Thomas Thrainer
  if not force_variant:
559 13f6af81 Thomas Thrainer
    _CheckOSVariant(result.payload, os_name)
560 13f6af81 Thomas Thrainer
561 13f6af81 Thomas Thrainer
562 13f6af81 Thomas Thrainer
def _CheckOSVariant(os_obj, name):
563 13f6af81 Thomas Thrainer
  """Check whether an OS name conforms to the os variants specification.
564 13f6af81 Thomas Thrainer

565 13f6af81 Thomas Thrainer
  @type os_obj: L{objects.OS}
566 13f6af81 Thomas Thrainer
  @param os_obj: OS object to check
567 13f6af81 Thomas Thrainer
  @type name: string
568 13f6af81 Thomas Thrainer
  @param name: OS name passed by the user, to check for validity
569 13f6af81 Thomas Thrainer

570 13f6af81 Thomas Thrainer
  """
571 13f6af81 Thomas Thrainer
  variant = objects.OS.GetVariant(name)
572 13f6af81 Thomas Thrainer
  if not os_obj.supported_variants:
573 13f6af81 Thomas Thrainer
    if variant:
574 13f6af81 Thomas Thrainer
      raise errors.OpPrereqError("OS '%s' doesn't support variants ('%s'"
575 13f6af81 Thomas Thrainer
                                 " passed)" % (os_obj.name, variant),
576 13f6af81 Thomas Thrainer
                                 errors.ECODE_INVAL)
577 13f6af81 Thomas Thrainer
    return
578 13f6af81 Thomas Thrainer
  if not variant:
579 13f6af81 Thomas Thrainer
    raise errors.OpPrereqError("OS name must include a variant",
580 13f6af81 Thomas Thrainer
                               errors.ECODE_INVAL)
581 13f6af81 Thomas Thrainer
582 13f6af81 Thomas Thrainer
  if variant not in os_obj.supported_variants:
583 13f6af81 Thomas Thrainer
    raise errors.OpPrereqError("Unsupported OS variant", errors.ECODE_INVAL)