Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / instance_utils.py @ 763ad5be

History | View | Annotate | Download (14.1 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 763ad5be Thomas Thrainer
from ganeti.cmdlib.common import _AnnotateDiskParams, \
35 763ad5be Thomas Thrainer
  _ComputeIPolicyInstanceViolation
36 22b7f6f8 Thomas Thrainer
37 22b7f6f8 Thomas Thrainer
38 22b7f6f8 Thomas Thrainer
def _BuildInstanceHookEnv(name, primary_node, secondary_nodes, os_type, status,
39 22b7f6f8 Thomas Thrainer
                          minmem, maxmem, vcpus, nics, disk_template, disks,
40 22b7f6f8 Thomas Thrainer
                          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 22b7f6f8 Thomas Thrainer
  @type primary_node: string
48 22b7f6f8 Thomas Thrainer
  @param primary_node: the name of the instance's primary node
49 22b7f6f8 Thomas Thrainer
  @type secondary_nodes: list
50 22b7f6f8 Thomas Thrainer
  @param secondary_nodes: 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 22b7f6f8 Thomas Thrainer
  @param nics: list of tuples (name, uuid, ip, mac, mode, link, net, netinfo)
63 22b7f6f8 Thomas Thrainer
      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 22b7f6f8 Thomas Thrainer
    "INSTANCE_PRIMARY": primary_node,
84 22b7f6f8 Thomas Thrainer
    "INSTANCE_SECONDARIES": " ".join(secondary_nodes),
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 22b7f6f8 Thomas Thrainer
    for idx, (name, _, ip, mac, mode, link, net, netinfo) in enumerate(nics):
98 22b7f6f8 Thomas Thrainer
      if ip is None:
99 22b7f6f8 Thomas Thrainer
        ip = ""
100 22b7f6f8 Thomas Thrainer
      env["INSTANCE_NIC%d_NAME" % idx] = name
101 22b7f6f8 Thomas Thrainer
      env["INSTANCE_NIC%d_IP" % idx] = ip
102 22b7f6f8 Thomas Thrainer
      env["INSTANCE_NIC%d_MAC" % idx] = mac
103 22b7f6f8 Thomas Thrainer
      env["INSTANCE_NIC%d_MODE" % idx] = mode
104 22b7f6f8 Thomas Thrainer
      env["INSTANCE_NIC%d_LINK" % idx] = link
105 22b7f6f8 Thomas Thrainer
      if netinfo:
106 22b7f6f8 Thomas Thrainer
        nobj = objects.Network.FromDict(netinfo)
107 22b7f6f8 Thomas Thrainer
        env.update(nobj.HooksDict("INSTANCE_NIC%d_" % idx))
108 22b7f6f8 Thomas Thrainer
      elif network:
109 22b7f6f8 Thomas Thrainer
        # FIXME: broken network reference: the instance NIC specifies a
110 22b7f6f8 Thomas Thrainer
        # network, but the relevant network entry was not in the config. This
111 22b7f6f8 Thomas Thrainer
        # should be made impossible.
112 22b7f6f8 Thomas Thrainer
        env["INSTANCE_NIC%d_NETWORK_NAME" % idx] = net
113 22b7f6f8 Thomas Thrainer
      if mode == constants.NIC_MODE_BRIDGED:
114 22b7f6f8 Thomas Thrainer
        env["INSTANCE_NIC%d_BRIDGE" % idx] = link
115 22b7f6f8 Thomas Thrainer
  else:
116 22b7f6f8 Thomas Thrainer
    nic_count = 0
117 22b7f6f8 Thomas Thrainer
118 22b7f6f8 Thomas Thrainer
  env["INSTANCE_NIC_COUNT"] = nic_count
119 22b7f6f8 Thomas Thrainer
120 22b7f6f8 Thomas Thrainer
  if disks:
121 22b7f6f8 Thomas Thrainer
    disk_count = len(disks)
122 22b7f6f8 Thomas Thrainer
    for idx, (name, size, mode) in enumerate(disks):
123 22b7f6f8 Thomas Thrainer
      env["INSTANCE_DISK%d_NAME" % idx] = name
124 22b7f6f8 Thomas Thrainer
      env["INSTANCE_DISK%d_SIZE" % idx] = size
125 22b7f6f8 Thomas Thrainer
      env["INSTANCE_DISK%d_MODE" % idx] = mode
126 22b7f6f8 Thomas Thrainer
  else:
127 22b7f6f8 Thomas Thrainer
    disk_count = 0
128 22b7f6f8 Thomas Thrainer
129 22b7f6f8 Thomas Thrainer
  env["INSTANCE_DISK_COUNT"] = disk_count
130 22b7f6f8 Thomas Thrainer
131 22b7f6f8 Thomas Thrainer
  if not tags:
132 22b7f6f8 Thomas Thrainer
    tags = []
133 22b7f6f8 Thomas Thrainer
134 22b7f6f8 Thomas Thrainer
  env["INSTANCE_TAGS"] = " ".join(tags)
135 22b7f6f8 Thomas Thrainer
136 22b7f6f8 Thomas Thrainer
  for source, kind in [(bep, "BE"), (hvp, "HV")]:
137 22b7f6f8 Thomas Thrainer
    for key, value in source.items():
138 22b7f6f8 Thomas Thrainer
      env["INSTANCE_%s_%s" % (kind, key)] = value
139 22b7f6f8 Thomas Thrainer
140 22b7f6f8 Thomas Thrainer
  return env
141 22b7f6f8 Thomas Thrainer
142 22b7f6f8 Thomas Thrainer
143 22b7f6f8 Thomas Thrainer
def _BuildInstanceHookEnvByObject(lu, instance, override=None):
144 22b7f6f8 Thomas Thrainer
  """Builds instance related env variables for hooks from an object.
145 22b7f6f8 Thomas Thrainer

146 22b7f6f8 Thomas Thrainer
  @type lu: L{LogicalUnit}
147 22b7f6f8 Thomas Thrainer
  @param lu: the logical unit on whose behalf we execute
148 22b7f6f8 Thomas Thrainer
  @type instance: L{objects.Instance}
149 22b7f6f8 Thomas Thrainer
  @param instance: the instance for which we should build the
150 22b7f6f8 Thomas Thrainer
      environment
151 22b7f6f8 Thomas Thrainer
  @type override: dict
152 22b7f6f8 Thomas Thrainer
  @param override: dictionary with key/values that will override
153 22b7f6f8 Thomas Thrainer
      our values
154 22b7f6f8 Thomas Thrainer
  @rtype: dict
155 22b7f6f8 Thomas Thrainer
  @return: the hook environment dictionary
156 22b7f6f8 Thomas Thrainer

157 22b7f6f8 Thomas Thrainer
  """
158 22b7f6f8 Thomas Thrainer
  cluster = lu.cfg.GetClusterInfo()
159 22b7f6f8 Thomas Thrainer
  bep = cluster.FillBE(instance)
160 22b7f6f8 Thomas Thrainer
  hvp = cluster.FillHV(instance)
161 22b7f6f8 Thomas Thrainer
  args = {
162 22b7f6f8 Thomas Thrainer
    "name": instance.name,
163 22b7f6f8 Thomas Thrainer
    "primary_node": instance.primary_node,
164 22b7f6f8 Thomas Thrainer
    "secondary_nodes": instance.secondary_nodes,
165 22b7f6f8 Thomas Thrainer
    "os_type": instance.os,
166 22b7f6f8 Thomas Thrainer
    "status": instance.admin_state,
167 22b7f6f8 Thomas Thrainer
    "maxmem": bep[constants.BE_MAXMEM],
168 22b7f6f8 Thomas Thrainer
    "minmem": bep[constants.BE_MINMEM],
169 22b7f6f8 Thomas Thrainer
    "vcpus": bep[constants.BE_VCPUS],
170 22b7f6f8 Thomas Thrainer
    "nics": _NICListToTuple(lu, instance.nics),
171 22b7f6f8 Thomas Thrainer
    "disk_template": instance.disk_template,
172 22b7f6f8 Thomas Thrainer
    "disks": [(disk.name, disk.size, disk.mode)
173 22b7f6f8 Thomas Thrainer
              for disk in instance.disks],
174 22b7f6f8 Thomas Thrainer
    "bep": bep,
175 22b7f6f8 Thomas Thrainer
    "hvp": hvp,
176 22b7f6f8 Thomas Thrainer
    "hypervisor_name": instance.hypervisor,
177 22b7f6f8 Thomas Thrainer
    "tags": instance.tags,
178 22b7f6f8 Thomas Thrainer
  }
179 22b7f6f8 Thomas Thrainer
  if override:
180 22b7f6f8 Thomas Thrainer
    args.update(override)
181 22b7f6f8 Thomas Thrainer
  return _BuildInstanceHookEnv(**args) # pylint: disable=W0142
182 22b7f6f8 Thomas Thrainer
183 22b7f6f8 Thomas Thrainer
184 22b7f6f8 Thomas Thrainer
def _GetClusterDomainSecret():
185 22b7f6f8 Thomas Thrainer
  """Reads the cluster domain secret.
186 22b7f6f8 Thomas Thrainer

187 22b7f6f8 Thomas Thrainer
  """
188 22b7f6f8 Thomas Thrainer
  return utils.ReadOneLineFile(pathutils.CLUSTER_DOMAIN_SECRET_FILE,
189 22b7f6f8 Thomas Thrainer
                               strict=True)
190 22b7f6f8 Thomas Thrainer
191 22b7f6f8 Thomas Thrainer
192 22b7f6f8 Thomas Thrainer
def _CheckNodeNotDrained(lu, node):
193 22b7f6f8 Thomas Thrainer
  """Ensure that a given node is not drained.
194 22b7f6f8 Thomas Thrainer

195 22b7f6f8 Thomas Thrainer
  @param lu: the LU on behalf of which we make the check
196 22b7f6f8 Thomas Thrainer
  @param node: the node to check
197 22b7f6f8 Thomas Thrainer
  @raise errors.OpPrereqError: if the node is drained
198 22b7f6f8 Thomas Thrainer

199 22b7f6f8 Thomas Thrainer
  """
200 22b7f6f8 Thomas Thrainer
  if lu.cfg.GetNodeInfo(node).drained:
201 22b7f6f8 Thomas Thrainer
    raise errors.OpPrereqError("Can't use drained node %s" % node,
202 22b7f6f8 Thomas Thrainer
                               errors.ECODE_STATE)
203 22b7f6f8 Thomas Thrainer
204 22b7f6f8 Thomas Thrainer
205 763ad5be Thomas Thrainer
def _CheckNodeVmCapable(lu, node):
206 763ad5be Thomas Thrainer
  """Ensure that a given node is vm capable.
207 22b7f6f8 Thomas Thrainer

208 763ad5be Thomas Thrainer
  @param lu: the LU on behalf of which we make the check
209 763ad5be Thomas Thrainer
  @param node: the node to check
210 763ad5be Thomas Thrainer
  @raise errors.OpPrereqError: if the node is not vm capable
211 22b7f6f8 Thomas Thrainer

212 22b7f6f8 Thomas Thrainer
  """
213 763ad5be Thomas Thrainer
  if not lu.cfg.GetNodeInfo(node).vm_capable:
214 763ad5be Thomas Thrainer
    raise errors.OpPrereqError("Can't use non-vm_capable node %s" % node,
215 763ad5be Thomas Thrainer
                               errors.ECODE_STATE)
216 22b7f6f8 Thomas Thrainer
217 22b7f6f8 Thomas Thrainer
218 22b7f6f8 Thomas Thrainer
def _RemoveInstance(lu, feedback_fn, instance, ignore_failures):
219 22b7f6f8 Thomas Thrainer
  """Utility function to remove an instance.
220 22b7f6f8 Thomas Thrainer

221 22b7f6f8 Thomas Thrainer
  """
222 22b7f6f8 Thomas Thrainer
  logging.info("Removing block devices for instance %s", instance.name)
223 22b7f6f8 Thomas Thrainer
224 22b7f6f8 Thomas Thrainer
  if not _RemoveDisks(lu, instance, ignore_failures=ignore_failures):
225 22b7f6f8 Thomas Thrainer
    if not ignore_failures:
226 22b7f6f8 Thomas Thrainer
      raise errors.OpExecError("Can't remove instance's disks")
227 22b7f6f8 Thomas Thrainer
    feedback_fn("Warning: can't remove instance's disks")
228 22b7f6f8 Thomas Thrainer
229 22b7f6f8 Thomas Thrainer
  logging.info("Removing instance %s out of cluster config", instance.name)
230 22b7f6f8 Thomas Thrainer
231 22b7f6f8 Thomas Thrainer
  lu.cfg.RemoveInstance(instance.name)
232 22b7f6f8 Thomas Thrainer
233 22b7f6f8 Thomas Thrainer
  assert not lu.remove_locks.get(locking.LEVEL_INSTANCE), \
234 22b7f6f8 Thomas Thrainer
    "Instance lock removal conflict"
235 22b7f6f8 Thomas Thrainer
236 22b7f6f8 Thomas Thrainer
  # Remove lock for the instance
237 22b7f6f8 Thomas Thrainer
  lu.remove_locks[locking.LEVEL_INSTANCE] = instance.name
238 22b7f6f8 Thomas Thrainer
239 22b7f6f8 Thomas Thrainer
240 22b7f6f8 Thomas Thrainer
def _RemoveDisks(lu, instance, target_node=None, ignore_failures=False):
241 22b7f6f8 Thomas Thrainer
  """Remove all disks for an instance.
242 22b7f6f8 Thomas Thrainer

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

247 22b7f6f8 Thomas Thrainer
  @type lu: L{LogicalUnit}
248 22b7f6f8 Thomas Thrainer
  @param lu: the logical unit on whose behalf we execute
249 22b7f6f8 Thomas Thrainer
  @type instance: L{objects.Instance}
250 22b7f6f8 Thomas Thrainer
  @param instance: the instance whose disks we should remove
251 22b7f6f8 Thomas Thrainer
  @type target_node: string
252 22b7f6f8 Thomas Thrainer
  @param target_node: used to override the node on which to remove the disks
253 22b7f6f8 Thomas Thrainer
  @rtype: boolean
254 22b7f6f8 Thomas Thrainer
  @return: the success of the removal
255 22b7f6f8 Thomas Thrainer

256 22b7f6f8 Thomas Thrainer
  """
257 22b7f6f8 Thomas Thrainer
  logging.info("Removing block devices for instance %s", instance.name)
258 22b7f6f8 Thomas Thrainer
259 22b7f6f8 Thomas Thrainer
  all_result = True
260 22b7f6f8 Thomas Thrainer
  ports_to_release = set()
261 22b7f6f8 Thomas Thrainer
  anno_disks = _AnnotateDiskParams(instance, instance.disks, lu.cfg)
262 22b7f6f8 Thomas Thrainer
  for (idx, device) in enumerate(anno_disks):
263 22b7f6f8 Thomas Thrainer
    if target_node:
264 22b7f6f8 Thomas Thrainer
      edata = [(target_node, device)]
265 22b7f6f8 Thomas Thrainer
    else:
266 22b7f6f8 Thomas Thrainer
      edata = device.ComputeNodeTree(instance.primary_node)
267 22b7f6f8 Thomas Thrainer
    for node, disk in edata:
268 22b7f6f8 Thomas Thrainer
      lu.cfg.SetDiskID(disk, node)
269 22b7f6f8 Thomas Thrainer
      result = lu.rpc.call_blockdev_remove(node, disk)
270 22b7f6f8 Thomas Thrainer
      if result.fail_msg:
271 22b7f6f8 Thomas Thrainer
        lu.LogWarning("Could not remove disk %s on node %s,"
272 22b7f6f8 Thomas Thrainer
                      " continuing anyway: %s", idx, node, result.fail_msg)
273 22b7f6f8 Thomas Thrainer
        if not (result.offline and node != instance.primary_node):
274 22b7f6f8 Thomas Thrainer
          all_result = False
275 22b7f6f8 Thomas Thrainer
276 22b7f6f8 Thomas Thrainer
    # if this is a DRBD disk, return its port to the pool
277 22b7f6f8 Thomas Thrainer
    if device.dev_type in constants.LDS_DRBD:
278 22b7f6f8 Thomas Thrainer
      ports_to_release.add(device.logical_id[2])
279 22b7f6f8 Thomas Thrainer
280 22b7f6f8 Thomas Thrainer
  if all_result or ignore_failures:
281 22b7f6f8 Thomas Thrainer
    for port in ports_to_release:
282 22b7f6f8 Thomas Thrainer
      lu.cfg.AddTcpUdpPort(port)
283 22b7f6f8 Thomas Thrainer
284 22b7f6f8 Thomas Thrainer
  if instance.disk_template in constants.DTS_FILEBASED:
285 22b7f6f8 Thomas Thrainer
    file_storage_dir = os.path.dirname(instance.disks[0].logical_id[1])
286 22b7f6f8 Thomas Thrainer
    if target_node:
287 22b7f6f8 Thomas Thrainer
      tgt = target_node
288 22b7f6f8 Thomas Thrainer
    else:
289 22b7f6f8 Thomas Thrainer
      tgt = instance.primary_node
290 22b7f6f8 Thomas Thrainer
    result = lu.rpc.call_file_storage_dir_remove(tgt, file_storage_dir)
291 22b7f6f8 Thomas Thrainer
    if result.fail_msg:
292 22b7f6f8 Thomas Thrainer
      lu.LogWarning("Could not remove directory '%s' on node %s: %s",
293 22b7f6f8 Thomas Thrainer
                    file_storage_dir, instance.primary_node, result.fail_msg)
294 22b7f6f8 Thomas Thrainer
      all_result = False
295 22b7f6f8 Thomas Thrainer
296 22b7f6f8 Thomas Thrainer
  return all_result
297 22b7f6f8 Thomas Thrainer
298 22b7f6f8 Thomas Thrainer
299 22b7f6f8 Thomas Thrainer
def _NICToTuple(lu, nic):
300 22b7f6f8 Thomas Thrainer
  """Build a tupple of nic information.
301 22b7f6f8 Thomas Thrainer

302 22b7f6f8 Thomas Thrainer
  @type lu:  L{LogicalUnit}
303 22b7f6f8 Thomas Thrainer
  @param lu: the logical unit on whose behalf we execute
304 22b7f6f8 Thomas Thrainer
  @type nic: L{objects.NIC}
305 22b7f6f8 Thomas Thrainer
  @param nic: nic to convert to hooks tuple
306 22b7f6f8 Thomas Thrainer

307 22b7f6f8 Thomas Thrainer
  """
308 22b7f6f8 Thomas Thrainer
  cluster = lu.cfg.GetClusterInfo()
309 22b7f6f8 Thomas Thrainer
  filled_params = cluster.SimpleFillNIC(nic.nicparams)
310 22b7f6f8 Thomas Thrainer
  mode = filled_params[constants.NIC_MODE]
311 22b7f6f8 Thomas Thrainer
  link = filled_params[constants.NIC_LINK]
312 22b7f6f8 Thomas Thrainer
  netinfo = None
313 22b7f6f8 Thomas Thrainer
  if nic.network:
314 22b7f6f8 Thomas Thrainer
    nobj = lu.cfg.GetNetwork(nic.network)
315 22b7f6f8 Thomas Thrainer
    netinfo = objects.Network.ToDict(nobj)
316 22b7f6f8 Thomas Thrainer
  return (nic.name, nic.uuid, nic.ip, nic.mac, mode, link, nic.network, netinfo)
317 22b7f6f8 Thomas Thrainer
318 22b7f6f8 Thomas Thrainer
319 22b7f6f8 Thomas Thrainer
def _NICListToTuple(lu, nics):
320 22b7f6f8 Thomas Thrainer
  """Build a list of nic information tuples.
321 22b7f6f8 Thomas Thrainer

322 22b7f6f8 Thomas Thrainer
  This list is suitable to be passed to _BuildInstanceHookEnv or as a return
323 22b7f6f8 Thomas Thrainer
  value in LUInstanceQueryData.
324 22b7f6f8 Thomas Thrainer

325 22b7f6f8 Thomas Thrainer
  @type lu:  L{LogicalUnit}
326 22b7f6f8 Thomas Thrainer
  @param lu: the logical unit on whose behalf we execute
327 22b7f6f8 Thomas Thrainer
  @type nics: list of L{objects.NIC}
328 22b7f6f8 Thomas Thrainer
  @param nics: list of nics to convert to hooks tuples
329 22b7f6f8 Thomas Thrainer

330 22b7f6f8 Thomas Thrainer
  """
331 22b7f6f8 Thomas Thrainer
  hooks_nics = []
332 22b7f6f8 Thomas Thrainer
  for nic in nics:
333 22b7f6f8 Thomas Thrainer
    hooks_nics.append(_NICToTuple(lu, nic))
334 22b7f6f8 Thomas Thrainer
  return hooks_nics
335 763ad5be Thomas Thrainer
336 763ad5be Thomas Thrainer
337 763ad5be Thomas Thrainer
def _CopyLockList(names):
338 763ad5be Thomas Thrainer
  """Makes a copy of a list of lock names.
339 763ad5be Thomas Thrainer

340 763ad5be Thomas Thrainer
  Handles L{locking.ALL_SET} correctly.
341 763ad5be Thomas Thrainer

342 763ad5be Thomas Thrainer
  """
343 763ad5be Thomas Thrainer
  if names == locking.ALL_SET:
344 763ad5be Thomas Thrainer
    return locking.ALL_SET
345 763ad5be Thomas Thrainer
  else:
346 763ad5be Thomas Thrainer
    return names[:]
347 763ad5be Thomas Thrainer
348 763ad5be Thomas Thrainer
349 763ad5be Thomas Thrainer
def _ReleaseLocks(lu, level, names=None, keep=None):
350 763ad5be Thomas Thrainer
  """Releases locks owned by an LU.
351 763ad5be Thomas Thrainer

352 763ad5be Thomas Thrainer
  @type lu: L{LogicalUnit}
353 763ad5be Thomas Thrainer
  @param level: Lock level
354 763ad5be Thomas Thrainer
  @type names: list or None
355 763ad5be Thomas Thrainer
  @param names: Names of locks to release
356 763ad5be Thomas Thrainer
  @type keep: list or None
357 763ad5be Thomas Thrainer
  @param keep: Names of locks to retain
358 763ad5be Thomas Thrainer

359 763ad5be Thomas Thrainer
  """
360 763ad5be Thomas Thrainer
  assert not (keep is not None and names is not None), \
361 763ad5be Thomas Thrainer
         "Only one of the 'names' and the 'keep' parameters can be given"
362 763ad5be Thomas Thrainer
363 763ad5be Thomas Thrainer
  if names is not None:
364 763ad5be Thomas Thrainer
    should_release = names.__contains__
365 763ad5be Thomas Thrainer
  elif keep:
366 763ad5be Thomas Thrainer
    should_release = lambda name: name not in keep
367 763ad5be Thomas Thrainer
  else:
368 763ad5be Thomas Thrainer
    should_release = None
369 763ad5be Thomas Thrainer
370 763ad5be Thomas Thrainer
  owned = lu.owned_locks(level)
371 763ad5be Thomas Thrainer
  if not owned:
372 763ad5be Thomas Thrainer
    # Not owning any lock at this level, do nothing
373 763ad5be Thomas Thrainer
    pass
374 763ad5be Thomas Thrainer
375 763ad5be Thomas Thrainer
  elif should_release:
376 763ad5be Thomas Thrainer
    retain = []
377 763ad5be Thomas Thrainer
    release = []
378 763ad5be Thomas Thrainer
379 763ad5be Thomas Thrainer
    # Determine which locks to release
380 763ad5be Thomas Thrainer
    for name in owned:
381 763ad5be Thomas Thrainer
      if should_release(name):
382 763ad5be Thomas Thrainer
        release.append(name)
383 763ad5be Thomas Thrainer
      else:
384 763ad5be Thomas Thrainer
        retain.append(name)
385 763ad5be Thomas Thrainer
386 763ad5be Thomas Thrainer
    assert len(lu.owned_locks(level)) == (len(retain) + len(release))
387 763ad5be Thomas Thrainer
388 763ad5be Thomas Thrainer
    # Release just some locks
389 763ad5be Thomas Thrainer
    lu.glm.release(level, names=release)
390 763ad5be Thomas Thrainer
391 763ad5be Thomas Thrainer
    assert frozenset(lu.owned_locks(level)) == frozenset(retain)
392 763ad5be Thomas Thrainer
  else:
393 763ad5be Thomas Thrainer
    # Release everything
394 763ad5be Thomas Thrainer
    lu.glm.release(level)
395 763ad5be Thomas Thrainer
396 763ad5be Thomas Thrainer
    assert not lu.glm.is_owned(level), "No locks should be owned"
397 763ad5be Thomas Thrainer
398 763ad5be Thomas Thrainer
399 763ad5be Thomas Thrainer
def _ComputeIPolicyNodeViolation(ipolicy, instance, current_group,
400 763ad5be Thomas Thrainer
                                 target_group, cfg,
401 763ad5be Thomas Thrainer
                                 _compute_fn=_ComputeIPolicyInstanceViolation):
402 763ad5be Thomas Thrainer
  """Compute if instance meets the specs of the new target group.
403 763ad5be Thomas Thrainer

404 763ad5be Thomas Thrainer
  @param ipolicy: The ipolicy to verify
405 763ad5be Thomas Thrainer
  @param instance: The instance object to verify
406 763ad5be Thomas Thrainer
  @param current_group: The current group of the instance
407 763ad5be Thomas Thrainer
  @param target_group: The new group of the instance
408 763ad5be Thomas Thrainer
  @type cfg: L{config.ConfigWriter}
409 763ad5be Thomas Thrainer
  @param cfg: Cluster configuration
410 763ad5be Thomas Thrainer
  @param _compute_fn: The function to verify ipolicy (unittest only)
411 763ad5be Thomas Thrainer
  @see: L{ganeti.cmdlib.common._ComputeIPolicySpecViolation}
412 763ad5be Thomas Thrainer

413 763ad5be Thomas Thrainer
  """
414 763ad5be Thomas Thrainer
  if current_group == target_group:
415 763ad5be Thomas Thrainer
    return []
416 763ad5be Thomas Thrainer
  else:
417 763ad5be Thomas Thrainer
    return _compute_fn(ipolicy, instance, cfg)
418 763ad5be Thomas Thrainer
419 763ad5be Thomas Thrainer
420 763ad5be Thomas Thrainer
def _CheckTargetNodeIPolicy(lu, ipolicy, instance, node, cfg, ignore=False,
421 763ad5be Thomas Thrainer
                            _compute_fn=_ComputeIPolicyNodeViolation):
422 763ad5be Thomas Thrainer
  """Checks that the target node is correct in terms of instance policy.
423 763ad5be Thomas Thrainer

424 763ad5be Thomas Thrainer
  @param ipolicy: The ipolicy to verify
425 763ad5be Thomas Thrainer
  @param instance: The instance object to verify
426 763ad5be Thomas Thrainer
  @param node: The new node to relocate
427 763ad5be Thomas Thrainer
  @type cfg: L{config.ConfigWriter}
428 763ad5be Thomas Thrainer
  @param cfg: Cluster configuration
429 763ad5be Thomas Thrainer
  @param ignore: Ignore violations of the ipolicy
430 763ad5be Thomas Thrainer
  @param _compute_fn: The function to verify ipolicy (unittest only)
431 763ad5be Thomas Thrainer
  @see: L{ganeti.cmdlib.common._ComputeIPolicySpecViolation}
432 763ad5be Thomas Thrainer

433 763ad5be Thomas Thrainer
  """
434 763ad5be Thomas Thrainer
  primary_node = lu.cfg.GetNodeInfo(instance.primary_node)
435 763ad5be Thomas Thrainer
  res = _compute_fn(ipolicy, instance, primary_node.group, node.group, cfg)
436 763ad5be Thomas Thrainer
437 763ad5be Thomas Thrainer
  if res:
438 763ad5be Thomas Thrainer
    msg = ("Instance does not meet target node group's (%s) instance"
439 763ad5be Thomas Thrainer
           " policy: %s") % (node.group, utils.CommaJoin(res))
440 763ad5be Thomas Thrainer
    if ignore:
441 763ad5be Thomas Thrainer
      lu.LogWarning(msg)
442 763ad5be Thomas Thrainer
    else:
443 763ad5be Thomas Thrainer
      raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
444 763ad5be Thomas Thrainer
445 763ad5be Thomas Thrainer
446 763ad5be Thomas Thrainer
def _GetInstanceInfoText(instance):
447 763ad5be Thomas Thrainer
  """Compute that text that should be added to the disk's metadata.
448 763ad5be Thomas Thrainer

449 763ad5be Thomas Thrainer
  """
450 763ad5be Thomas Thrainer
  return "originstname+%s" % instance.name