Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / network.py @ 809a055b

History | View | Annotate | Download (18.6 kB)

1 37dc17e3 Thomas Thrainer
#
2 37dc17e3 Thomas Thrainer
#
3 37dc17e3 Thomas Thrainer
4 37dc17e3 Thomas Thrainer
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc.
5 37dc17e3 Thomas Thrainer
#
6 37dc17e3 Thomas Thrainer
# This program is free software; you can redistribute it and/or modify
7 37dc17e3 Thomas Thrainer
# it under the terms of the GNU General Public License as published by
8 37dc17e3 Thomas Thrainer
# the Free Software Foundation; either version 2 of the License, or
9 37dc17e3 Thomas Thrainer
# (at your option) any later version.
10 37dc17e3 Thomas Thrainer
#
11 37dc17e3 Thomas Thrainer
# This program is distributed in the hope that it will be useful, but
12 37dc17e3 Thomas Thrainer
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 37dc17e3 Thomas Thrainer
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 37dc17e3 Thomas Thrainer
# General Public License for more details.
15 37dc17e3 Thomas Thrainer
#
16 37dc17e3 Thomas Thrainer
# You should have received a copy of the GNU General Public License
17 37dc17e3 Thomas Thrainer
# along with this program; if not, write to the Free Software
18 37dc17e3 Thomas Thrainer
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 37dc17e3 Thomas Thrainer
# 02110-1301, USA.
20 37dc17e3 Thomas Thrainer
21 37dc17e3 Thomas Thrainer
22 37dc17e3 Thomas Thrainer
"""Logical units dealing with networks."""
23 37dc17e3 Thomas Thrainer
24 37dc17e3 Thomas Thrainer
from ganeti import constants
25 37dc17e3 Thomas Thrainer
from ganeti import errors
26 37dc17e3 Thomas Thrainer
from ganeti import locking
27 37dc17e3 Thomas Thrainer
from ganeti import network
28 37dc17e3 Thomas Thrainer
from ganeti import objects
29 37dc17e3 Thomas Thrainer
from ganeti import utils
30 64981f25 Helga Velroyen
from ganeti.cmdlib.base import LogicalUnit
31 44ffd981 Helga Velroyen
from ganeti.cmdlib.common import CheckNodeGroupInstances
32 37dc17e3 Thomas Thrainer
33 37dc17e3 Thomas Thrainer
34 37dc17e3 Thomas Thrainer
def _BuildNetworkHookEnv(name, subnet, gateway, network6, gateway6,
35 37dc17e3 Thomas Thrainer
                         mac_prefix, tags):
36 37dc17e3 Thomas Thrainer
  """Builds network related env variables for hooks
37 37dc17e3 Thomas Thrainer

38 37dc17e3 Thomas Thrainer
  This builds the hook environment from individual variables.
39 37dc17e3 Thomas Thrainer

40 37dc17e3 Thomas Thrainer
  @type name: string
41 37dc17e3 Thomas Thrainer
  @param name: the name of the network
42 37dc17e3 Thomas Thrainer
  @type subnet: string
43 37dc17e3 Thomas Thrainer
  @param subnet: the ipv4 subnet
44 37dc17e3 Thomas Thrainer
  @type gateway: string
45 37dc17e3 Thomas Thrainer
  @param gateway: the ipv4 gateway
46 37dc17e3 Thomas Thrainer
  @type network6: string
47 37dc17e3 Thomas Thrainer
  @param network6: the ipv6 subnet
48 37dc17e3 Thomas Thrainer
  @type gateway6: string
49 37dc17e3 Thomas Thrainer
  @param gateway6: the ipv6 gateway
50 37dc17e3 Thomas Thrainer
  @type mac_prefix: string
51 37dc17e3 Thomas Thrainer
  @param mac_prefix: the mac_prefix
52 37dc17e3 Thomas Thrainer
  @type tags: list
53 37dc17e3 Thomas Thrainer
  @param tags: the tags of the network
54 37dc17e3 Thomas Thrainer

55 37dc17e3 Thomas Thrainer
  """
56 37dc17e3 Thomas Thrainer
  env = {}
57 37dc17e3 Thomas Thrainer
  if name:
58 37dc17e3 Thomas Thrainer
    env["NETWORK_NAME"] = name
59 37dc17e3 Thomas Thrainer
  if subnet:
60 37dc17e3 Thomas Thrainer
    env["NETWORK_SUBNET"] = subnet
61 37dc17e3 Thomas Thrainer
  if gateway:
62 37dc17e3 Thomas Thrainer
    env["NETWORK_GATEWAY"] = gateway
63 37dc17e3 Thomas Thrainer
  if network6:
64 37dc17e3 Thomas Thrainer
    env["NETWORK_SUBNET6"] = network6
65 37dc17e3 Thomas Thrainer
  if gateway6:
66 37dc17e3 Thomas Thrainer
    env["NETWORK_GATEWAY6"] = gateway6
67 37dc17e3 Thomas Thrainer
  if mac_prefix:
68 37dc17e3 Thomas Thrainer
    env["NETWORK_MAC_PREFIX"] = mac_prefix
69 37dc17e3 Thomas Thrainer
  if tags:
70 37dc17e3 Thomas Thrainer
    env["NETWORK_TAGS"] = " ".join(tags)
71 37dc17e3 Thomas Thrainer
72 37dc17e3 Thomas Thrainer
  return env
73 37dc17e3 Thomas Thrainer
74 37dc17e3 Thomas Thrainer
75 37dc17e3 Thomas Thrainer
class LUNetworkAdd(LogicalUnit):
76 37dc17e3 Thomas Thrainer
  """Logical unit for creating networks.
77 37dc17e3 Thomas Thrainer

78 37dc17e3 Thomas Thrainer
  """
79 37dc17e3 Thomas Thrainer
  HPATH = "network-add"
80 37dc17e3 Thomas Thrainer
  HTYPE = constants.HTYPE_NETWORK
81 37dc17e3 Thomas Thrainer
  REQ_BGL = False
82 37dc17e3 Thomas Thrainer
83 37dc17e3 Thomas Thrainer
  def BuildHooksNodes(self):
84 37dc17e3 Thomas Thrainer
    """Build hooks nodes.
85 37dc17e3 Thomas Thrainer

86 37dc17e3 Thomas Thrainer
    """
87 37dc17e3 Thomas Thrainer
    mn = self.cfg.GetMasterNode()
88 37dc17e3 Thomas Thrainer
    return ([mn], [mn])
89 37dc17e3 Thomas Thrainer
90 37dc17e3 Thomas Thrainer
  def CheckArguments(self):
91 37dc17e3 Thomas Thrainer
    if self.op.mac_prefix:
92 37dc17e3 Thomas Thrainer
      self.op.mac_prefix = \
93 37dc17e3 Thomas Thrainer
        utils.NormalizeAndValidateThreeOctetMacPrefix(self.op.mac_prefix)
94 37dc17e3 Thomas Thrainer
95 37dc17e3 Thomas Thrainer
  def ExpandNames(self):
96 37dc17e3 Thomas Thrainer
    self.network_uuid = self.cfg.GenerateUniqueID(self.proc.GetECId())
97 37dc17e3 Thomas Thrainer
98 37dc17e3 Thomas Thrainer
    if self.op.conflicts_check:
99 37dc17e3 Thomas Thrainer
      self.share_locks[locking.LEVEL_NODE] = 1
100 37dc17e3 Thomas Thrainer
      self.share_locks[locking.LEVEL_NODE_ALLOC] = 1
101 37dc17e3 Thomas Thrainer
      self.needed_locks = {
102 37dc17e3 Thomas Thrainer
        locking.LEVEL_NODE: locking.ALL_SET,
103 37dc17e3 Thomas Thrainer
        locking.LEVEL_NODE_ALLOC: locking.ALL_SET,
104 37dc17e3 Thomas Thrainer
        }
105 37dc17e3 Thomas Thrainer
    else:
106 37dc17e3 Thomas Thrainer
      self.needed_locks = {}
107 37dc17e3 Thomas Thrainer
108 37dc17e3 Thomas Thrainer
    self.add_locks[locking.LEVEL_NETWORK] = self.network_uuid
109 37dc17e3 Thomas Thrainer
110 37dc17e3 Thomas Thrainer
  def CheckPrereq(self):
111 37dc17e3 Thomas Thrainer
    if self.op.network is None:
112 37dc17e3 Thomas Thrainer
      raise errors.OpPrereqError("Network must be given",
113 37dc17e3 Thomas Thrainer
                                 errors.ECODE_INVAL)
114 37dc17e3 Thomas Thrainer
115 37dc17e3 Thomas Thrainer
    try:
116 37dc17e3 Thomas Thrainer
      existing_uuid = self.cfg.LookupNetwork(self.op.network_name)
117 37dc17e3 Thomas Thrainer
    except errors.OpPrereqError:
118 37dc17e3 Thomas Thrainer
      pass
119 37dc17e3 Thomas Thrainer
    else:
120 37dc17e3 Thomas Thrainer
      raise errors.OpPrereqError("Desired network name '%s' already exists as a"
121 37dc17e3 Thomas Thrainer
                                 " network (UUID: %s)" %
122 37dc17e3 Thomas Thrainer
                                 (self.op.network_name, existing_uuid),
123 37dc17e3 Thomas Thrainer
                                 errors.ECODE_EXISTS)
124 37dc17e3 Thomas Thrainer
125 37dc17e3 Thomas Thrainer
    # Check tag validity
126 37dc17e3 Thomas Thrainer
    for tag in self.op.tags:
127 37dc17e3 Thomas Thrainer
      objects.TaggableObject.ValidateTag(tag)
128 37dc17e3 Thomas Thrainer
129 37dc17e3 Thomas Thrainer
  def BuildHooksEnv(self):
130 37dc17e3 Thomas Thrainer
    """Build hooks env.
131 37dc17e3 Thomas Thrainer

132 37dc17e3 Thomas Thrainer
    """
133 37dc17e3 Thomas Thrainer
    args = {
134 37dc17e3 Thomas Thrainer
      "name": self.op.network_name,
135 37dc17e3 Thomas Thrainer
      "subnet": self.op.network,
136 37dc17e3 Thomas Thrainer
      "gateway": self.op.gateway,
137 37dc17e3 Thomas Thrainer
      "network6": self.op.network6,
138 37dc17e3 Thomas Thrainer
      "gateway6": self.op.gateway6,
139 37dc17e3 Thomas Thrainer
      "mac_prefix": self.op.mac_prefix,
140 37dc17e3 Thomas Thrainer
      "tags": self.op.tags,
141 37dc17e3 Thomas Thrainer
      }
142 37dc17e3 Thomas Thrainer
    return _BuildNetworkHookEnv(**args) # pylint: disable=W0142
143 37dc17e3 Thomas Thrainer
144 37dc17e3 Thomas Thrainer
  def Exec(self, feedback_fn):
145 37dc17e3 Thomas Thrainer
    """Add the ip pool to the cluster.
146 37dc17e3 Thomas Thrainer

147 37dc17e3 Thomas Thrainer
    """
148 37dc17e3 Thomas Thrainer
    nobj = objects.Network(name=self.op.network_name,
149 37dc17e3 Thomas Thrainer
                           network=self.op.network,
150 37dc17e3 Thomas Thrainer
                           gateway=self.op.gateway,
151 37dc17e3 Thomas Thrainer
                           network6=self.op.network6,
152 37dc17e3 Thomas Thrainer
                           gateway6=self.op.gateway6,
153 37dc17e3 Thomas Thrainer
                           mac_prefix=self.op.mac_prefix,
154 37dc17e3 Thomas Thrainer
                           uuid=self.network_uuid)
155 37dc17e3 Thomas Thrainer
    # Initialize the associated address pool
156 37dc17e3 Thomas Thrainer
    try:
157 37dc17e3 Thomas Thrainer
      pool = network.AddressPool.InitializeNetwork(nobj)
158 37dc17e3 Thomas Thrainer
    except errors.AddressPoolError, err:
159 37dc17e3 Thomas Thrainer
      raise errors.OpExecError("Cannot create IP address pool for network"
160 37dc17e3 Thomas Thrainer
                               " '%s': %s" % (self.op.network_name, err))
161 37dc17e3 Thomas Thrainer
162 37dc17e3 Thomas Thrainer
    # Check if we need to reserve the nodes and the cluster master IP
163 37dc17e3 Thomas Thrainer
    # These may not be allocated to any instances in routed mode, as
164 37dc17e3 Thomas Thrainer
    # they wouldn't function anyway.
165 37dc17e3 Thomas Thrainer
    if self.op.conflicts_check:
166 37dc17e3 Thomas Thrainer
      for node in self.cfg.GetAllNodesInfo().values():
167 37dc17e3 Thomas Thrainer
        for ip in [node.primary_ip, node.secondary_ip]:
168 37dc17e3 Thomas Thrainer
          try:
169 37dc17e3 Thomas Thrainer
            if pool.Contains(ip):
170 28d466dc Dimitris Aragiorgis
              pool.Reserve(ip, external=True)
171 37dc17e3 Thomas Thrainer
              self.LogInfo("Reserved IP address of node '%s' (%s)",
172 37dc17e3 Thomas Thrainer
                           node.name, ip)
173 37dc17e3 Thomas Thrainer
          except errors.AddressPoolError, err:
174 37dc17e3 Thomas Thrainer
            self.LogWarning("Cannot reserve IP address '%s' of node '%s': %s",
175 37dc17e3 Thomas Thrainer
                            ip, node.name, err)
176 37dc17e3 Thomas Thrainer
177 37dc17e3 Thomas Thrainer
      master_ip = self.cfg.GetClusterInfo().master_ip
178 37dc17e3 Thomas Thrainer
      try:
179 37dc17e3 Thomas Thrainer
        if pool.Contains(master_ip):
180 28d466dc Dimitris Aragiorgis
          pool.Reserve(master_ip, external=True)
181 37dc17e3 Thomas Thrainer
          self.LogInfo("Reserved cluster master IP address (%s)", master_ip)
182 37dc17e3 Thomas Thrainer
      except errors.AddressPoolError, err:
183 37dc17e3 Thomas Thrainer
        self.LogWarning("Cannot reserve cluster master IP address (%s): %s",
184 37dc17e3 Thomas Thrainer
                        master_ip, err)
185 37dc17e3 Thomas Thrainer
186 37dc17e3 Thomas Thrainer
    if self.op.add_reserved_ips:
187 37dc17e3 Thomas Thrainer
      for ip in self.op.add_reserved_ips:
188 37dc17e3 Thomas Thrainer
        try:
189 37dc17e3 Thomas Thrainer
          pool.Reserve(ip, external=True)
190 37dc17e3 Thomas Thrainer
        except errors.AddressPoolError, err:
191 37dc17e3 Thomas Thrainer
          raise errors.OpExecError("Cannot reserve IP address '%s': %s" %
192 37dc17e3 Thomas Thrainer
                                   (ip, err))
193 37dc17e3 Thomas Thrainer
194 37dc17e3 Thomas Thrainer
    if self.op.tags:
195 37dc17e3 Thomas Thrainer
      for tag in self.op.tags:
196 37dc17e3 Thomas Thrainer
        nobj.AddTag(tag)
197 37dc17e3 Thomas Thrainer
198 37dc17e3 Thomas Thrainer
    self.cfg.AddNetwork(nobj, self.proc.GetECId(), check_uuid=False)
199 37dc17e3 Thomas Thrainer
200 37dc17e3 Thomas Thrainer
201 37dc17e3 Thomas Thrainer
class LUNetworkRemove(LogicalUnit):
202 37dc17e3 Thomas Thrainer
  HPATH = "network-remove"
203 37dc17e3 Thomas Thrainer
  HTYPE = constants.HTYPE_NETWORK
204 37dc17e3 Thomas Thrainer
  REQ_BGL = False
205 37dc17e3 Thomas Thrainer
206 37dc17e3 Thomas Thrainer
  def ExpandNames(self):
207 37dc17e3 Thomas Thrainer
    self.network_uuid = self.cfg.LookupNetwork(self.op.network_name)
208 37dc17e3 Thomas Thrainer
209 37dc17e3 Thomas Thrainer
    self.share_locks[locking.LEVEL_NODEGROUP] = 1
210 37dc17e3 Thomas Thrainer
    self.needed_locks = {
211 37dc17e3 Thomas Thrainer
      locking.LEVEL_NETWORK: [self.network_uuid],
212 37dc17e3 Thomas Thrainer
      locking.LEVEL_NODEGROUP: locking.ALL_SET,
213 37dc17e3 Thomas Thrainer
      }
214 37dc17e3 Thomas Thrainer
215 37dc17e3 Thomas Thrainer
  def CheckPrereq(self):
216 37dc17e3 Thomas Thrainer
    """Check prerequisites.
217 37dc17e3 Thomas Thrainer

218 37dc17e3 Thomas Thrainer
    This checks that the given network name exists as a network, that is
219 37dc17e3 Thomas Thrainer
    empty (i.e., contains no nodes), and that is not the last group of the
220 37dc17e3 Thomas Thrainer
    cluster.
221 37dc17e3 Thomas Thrainer

222 37dc17e3 Thomas Thrainer
    """
223 37dc17e3 Thomas Thrainer
    # Verify that the network is not conncted.
224 37dc17e3 Thomas Thrainer
    node_groups = [group.name
225 37dc17e3 Thomas Thrainer
                   for group in self.cfg.GetAllNodeGroupsInfo().values()
226 37dc17e3 Thomas Thrainer
                   if self.network_uuid in group.networks]
227 37dc17e3 Thomas Thrainer
228 37dc17e3 Thomas Thrainer
    if node_groups:
229 37dc17e3 Thomas Thrainer
      self.LogWarning("Network '%s' is connected to the following"
230 37dc17e3 Thomas Thrainer
                      " node groups: %s" %
231 37dc17e3 Thomas Thrainer
                      (self.op.network_name,
232 37dc17e3 Thomas Thrainer
                       utils.CommaJoin(utils.NiceSort(node_groups))))
233 37dc17e3 Thomas Thrainer
      raise errors.OpPrereqError("Network still connected", errors.ECODE_STATE)
234 37dc17e3 Thomas Thrainer
235 37dc17e3 Thomas Thrainer
  def BuildHooksEnv(self):
236 37dc17e3 Thomas Thrainer
    """Build hooks env.
237 37dc17e3 Thomas Thrainer

238 37dc17e3 Thomas Thrainer
    """
239 37dc17e3 Thomas Thrainer
    return {
240 37dc17e3 Thomas Thrainer
      "NETWORK_NAME": self.op.network_name,
241 37dc17e3 Thomas Thrainer
      }
242 37dc17e3 Thomas Thrainer
243 37dc17e3 Thomas Thrainer
  def BuildHooksNodes(self):
244 37dc17e3 Thomas Thrainer
    """Build hooks nodes.
245 37dc17e3 Thomas Thrainer

246 37dc17e3 Thomas Thrainer
    """
247 37dc17e3 Thomas Thrainer
    mn = self.cfg.GetMasterNode()
248 37dc17e3 Thomas Thrainer
    return ([mn], [mn])
249 37dc17e3 Thomas Thrainer
250 37dc17e3 Thomas Thrainer
  def Exec(self, feedback_fn):
251 37dc17e3 Thomas Thrainer
    """Remove the network.
252 37dc17e3 Thomas Thrainer

253 37dc17e3 Thomas Thrainer
    """
254 37dc17e3 Thomas Thrainer
    try:
255 37dc17e3 Thomas Thrainer
      self.cfg.RemoveNetwork(self.network_uuid)
256 37dc17e3 Thomas Thrainer
    except errors.ConfigurationError:
257 37dc17e3 Thomas Thrainer
      raise errors.OpExecError("Network '%s' with UUID %s disappeared" %
258 37dc17e3 Thomas Thrainer
                               (self.op.network_name, self.network_uuid))
259 37dc17e3 Thomas Thrainer
260 37dc17e3 Thomas Thrainer
261 37dc17e3 Thomas Thrainer
class LUNetworkSetParams(LogicalUnit):
262 37dc17e3 Thomas Thrainer
  """Modifies the parameters of a network.
263 37dc17e3 Thomas Thrainer

264 37dc17e3 Thomas Thrainer
  """
265 37dc17e3 Thomas Thrainer
  HPATH = "network-modify"
266 37dc17e3 Thomas Thrainer
  HTYPE = constants.HTYPE_NETWORK
267 37dc17e3 Thomas Thrainer
  REQ_BGL = False
268 37dc17e3 Thomas Thrainer
269 37dc17e3 Thomas Thrainer
  def CheckArguments(self):
270 37dc17e3 Thomas Thrainer
    if (self.op.gateway and
271 37dc17e3 Thomas Thrainer
        (self.op.add_reserved_ips or self.op.remove_reserved_ips)):
272 37dc17e3 Thomas Thrainer
      raise errors.OpPrereqError("Cannot modify gateway and reserved ips"
273 37dc17e3 Thomas Thrainer
                                 " at once", errors.ECODE_INVAL)
274 37dc17e3 Thomas Thrainer
275 37dc17e3 Thomas Thrainer
  def ExpandNames(self):
276 37dc17e3 Thomas Thrainer
    self.network_uuid = self.cfg.LookupNetwork(self.op.network_name)
277 37dc17e3 Thomas Thrainer
278 37dc17e3 Thomas Thrainer
    self.needed_locks = {
279 37dc17e3 Thomas Thrainer
      locking.LEVEL_NETWORK: [self.network_uuid],
280 37dc17e3 Thomas Thrainer
      }
281 37dc17e3 Thomas Thrainer
282 37dc17e3 Thomas Thrainer
  def CheckPrereq(self):
283 37dc17e3 Thomas Thrainer
    """Check prerequisites.
284 37dc17e3 Thomas Thrainer

285 37dc17e3 Thomas Thrainer
    """
286 37dc17e3 Thomas Thrainer
    self.network = self.cfg.GetNetwork(self.network_uuid)
287 37dc17e3 Thomas Thrainer
    self.gateway = self.network.gateway
288 37dc17e3 Thomas Thrainer
    self.mac_prefix = self.network.mac_prefix
289 37dc17e3 Thomas Thrainer
    self.network6 = self.network.network6
290 37dc17e3 Thomas Thrainer
    self.gateway6 = self.network.gateway6
291 37dc17e3 Thomas Thrainer
    self.tags = self.network.tags
292 37dc17e3 Thomas Thrainer
293 37dc17e3 Thomas Thrainer
    self.pool = network.AddressPool(self.network)
294 37dc17e3 Thomas Thrainer
295 37dc17e3 Thomas Thrainer
    if self.op.gateway:
296 37dc17e3 Thomas Thrainer
      if self.op.gateway == constants.VALUE_NONE:
297 37dc17e3 Thomas Thrainer
        self.gateway = None
298 37dc17e3 Thomas Thrainer
      else:
299 37dc17e3 Thomas Thrainer
        self.gateway = self.op.gateway
300 37dc17e3 Thomas Thrainer
        if self.pool.IsReserved(self.gateway):
301 37dc17e3 Thomas Thrainer
          raise errors.OpPrereqError("Gateway IP address '%s' is already"
302 37dc17e3 Thomas Thrainer
                                     " reserved" % self.gateway,
303 37dc17e3 Thomas Thrainer
                                     errors.ECODE_STATE)
304 37dc17e3 Thomas Thrainer
305 37dc17e3 Thomas Thrainer
    if self.op.mac_prefix:
306 37dc17e3 Thomas Thrainer
      if self.op.mac_prefix == constants.VALUE_NONE:
307 37dc17e3 Thomas Thrainer
        self.mac_prefix = None
308 37dc17e3 Thomas Thrainer
      else:
309 37dc17e3 Thomas Thrainer
        self.mac_prefix = \
310 37dc17e3 Thomas Thrainer
          utils.NormalizeAndValidateThreeOctetMacPrefix(self.op.mac_prefix)
311 37dc17e3 Thomas Thrainer
312 37dc17e3 Thomas Thrainer
    if self.op.gateway6:
313 37dc17e3 Thomas Thrainer
      if self.op.gateway6 == constants.VALUE_NONE:
314 37dc17e3 Thomas Thrainer
        self.gateway6 = None
315 37dc17e3 Thomas Thrainer
      else:
316 37dc17e3 Thomas Thrainer
        self.gateway6 = self.op.gateway6
317 37dc17e3 Thomas Thrainer
318 37dc17e3 Thomas Thrainer
    if self.op.network6:
319 37dc17e3 Thomas Thrainer
      if self.op.network6 == constants.VALUE_NONE:
320 37dc17e3 Thomas Thrainer
        self.network6 = None
321 37dc17e3 Thomas Thrainer
      else:
322 37dc17e3 Thomas Thrainer
        self.network6 = self.op.network6
323 37dc17e3 Thomas Thrainer
324 37dc17e3 Thomas Thrainer
  def BuildHooksEnv(self):
325 37dc17e3 Thomas Thrainer
    """Build hooks env.
326 37dc17e3 Thomas Thrainer

327 37dc17e3 Thomas Thrainer
    """
328 37dc17e3 Thomas Thrainer
    args = {
329 37dc17e3 Thomas Thrainer
      "name": self.op.network_name,
330 37dc17e3 Thomas Thrainer
      "subnet": self.network.network,
331 37dc17e3 Thomas Thrainer
      "gateway": self.gateway,
332 37dc17e3 Thomas Thrainer
      "network6": self.network6,
333 37dc17e3 Thomas Thrainer
      "gateway6": self.gateway6,
334 37dc17e3 Thomas Thrainer
      "mac_prefix": self.mac_prefix,
335 37dc17e3 Thomas Thrainer
      "tags": self.tags,
336 37dc17e3 Thomas Thrainer
      }
337 37dc17e3 Thomas Thrainer
    return _BuildNetworkHookEnv(**args) # pylint: disable=W0142
338 37dc17e3 Thomas Thrainer
339 37dc17e3 Thomas Thrainer
  def BuildHooksNodes(self):
340 37dc17e3 Thomas Thrainer
    """Build hooks nodes.
341 37dc17e3 Thomas Thrainer

342 37dc17e3 Thomas Thrainer
    """
343 37dc17e3 Thomas Thrainer
    mn = self.cfg.GetMasterNode()
344 37dc17e3 Thomas Thrainer
    return ([mn], [mn])
345 37dc17e3 Thomas Thrainer
346 37dc17e3 Thomas Thrainer
  def Exec(self, feedback_fn):
347 37dc17e3 Thomas Thrainer
    """Modifies the network.
348 37dc17e3 Thomas Thrainer

349 37dc17e3 Thomas Thrainer
    """
350 37dc17e3 Thomas Thrainer
    #TODO: reserve/release via temporary reservation manager
351 37dc17e3 Thomas Thrainer
    #      extend cfg.ReserveIp/ReleaseIp with the external flag
352 37dc17e3 Thomas Thrainer
    if self.op.gateway:
353 37dc17e3 Thomas Thrainer
      if self.gateway == self.network.gateway:
354 37dc17e3 Thomas Thrainer
        self.LogWarning("Gateway is already %s", self.gateway)
355 37dc17e3 Thomas Thrainer
      else:
356 37dc17e3 Thomas Thrainer
        if self.gateway:
357 37dc17e3 Thomas Thrainer
          self.pool.Reserve(self.gateway, external=True)
358 37dc17e3 Thomas Thrainer
        if self.network.gateway:
359 37dc17e3 Thomas Thrainer
          self.pool.Release(self.network.gateway, external=True)
360 37dc17e3 Thomas Thrainer
        self.network.gateway = self.gateway
361 37dc17e3 Thomas Thrainer
362 37dc17e3 Thomas Thrainer
    if self.op.add_reserved_ips:
363 37dc17e3 Thomas Thrainer
      for ip in self.op.add_reserved_ips:
364 37dc17e3 Thomas Thrainer
        try:
365 031d2db1 Dimitris Aragiorgis
          self.pool.Reserve(ip, external=True)
366 37dc17e3 Thomas Thrainer
        except errors.AddressPoolError, err:
367 37dc17e3 Thomas Thrainer
          self.LogWarning("Cannot reserve IP address %s: %s", ip, err)
368 37dc17e3 Thomas Thrainer
369 37dc17e3 Thomas Thrainer
    if self.op.remove_reserved_ips:
370 37dc17e3 Thomas Thrainer
      for ip in self.op.remove_reserved_ips:
371 37dc17e3 Thomas Thrainer
        if ip == self.network.gateway:
372 37dc17e3 Thomas Thrainer
          self.LogWarning("Cannot unreserve Gateway's IP")
373 37dc17e3 Thomas Thrainer
          continue
374 37dc17e3 Thomas Thrainer
        try:
375 031d2db1 Dimitris Aragiorgis
          self.pool.Release(ip, external=True)
376 37dc17e3 Thomas Thrainer
        except errors.AddressPoolError, err:
377 37dc17e3 Thomas Thrainer
          self.LogWarning("Cannot release IP address %s: %s", ip, err)
378 37dc17e3 Thomas Thrainer
379 37dc17e3 Thomas Thrainer
    if self.op.mac_prefix:
380 37dc17e3 Thomas Thrainer
      self.network.mac_prefix = self.mac_prefix
381 37dc17e3 Thomas Thrainer
382 37dc17e3 Thomas Thrainer
    if self.op.network6:
383 37dc17e3 Thomas Thrainer
      self.network.network6 = self.network6
384 37dc17e3 Thomas Thrainer
385 37dc17e3 Thomas Thrainer
    if self.op.gateway6:
386 37dc17e3 Thomas Thrainer
      self.network.gateway6 = self.gateway6
387 37dc17e3 Thomas Thrainer
388 37dc17e3 Thomas Thrainer
    self.pool.Validate()
389 37dc17e3 Thomas Thrainer
390 37dc17e3 Thomas Thrainer
    self.cfg.Update(self.network, feedback_fn)
391 37dc17e3 Thomas Thrainer
392 37dc17e3 Thomas Thrainer
393 37dc17e3 Thomas Thrainer
def _FmtNetworkConflict(details):
394 37dc17e3 Thomas Thrainer
  """Utility for L{_NetworkConflictCheck}.
395 37dc17e3 Thomas Thrainer

396 37dc17e3 Thomas Thrainer
  """
397 37dc17e3 Thomas Thrainer
  return utils.CommaJoin("nic%s/%s" % (idx, ipaddr)
398 37dc17e3 Thomas Thrainer
                         for (idx, ipaddr) in details)
399 37dc17e3 Thomas Thrainer
400 37dc17e3 Thomas Thrainer
401 37dc17e3 Thomas Thrainer
def _NetworkConflictCheck(lu, check_fn, action, instances):
402 37dc17e3 Thomas Thrainer
  """Checks for network interface conflicts with a network.
403 37dc17e3 Thomas Thrainer

404 37dc17e3 Thomas Thrainer
  @type lu: L{LogicalUnit}
405 37dc17e3 Thomas Thrainer
  @type check_fn: callable receiving one parameter (L{objects.NIC}) and
406 37dc17e3 Thomas Thrainer
    returning boolean
407 37dc17e3 Thomas Thrainer
  @param check_fn: Function checking for conflict
408 37dc17e3 Thomas Thrainer
  @type action: string
409 37dc17e3 Thomas Thrainer
  @param action: Part of error message (see code)
410 3fe41221 Klaus Aehlig
  @param instances: the instances to check
411 3fe41221 Klaus Aehlig
  @type instances: list of instance objects
412 37dc17e3 Thomas Thrainer
  @raise errors.OpPrereqError: If conflicting IP addresses are found.
413 37dc17e3 Thomas Thrainer

414 37dc17e3 Thomas Thrainer
  """
415 37dc17e3 Thomas Thrainer
  conflicts = []
416 37dc17e3 Thomas Thrainer
417 da4a52a3 Thomas Thrainer
  for instance in instances:
418 37dc17e3 Thomas Thrainer
    instconflicts = [(idx, nic.ip)
419 37dc17e3 Thomas Thrainer
                     for (idx, nic) in enumerate(instance.nics)
420 37dc17e3 Thomas Thrainer
                     if check_fn(nic)]
421 37dc17e3 Thomas Thrainer
422 37dc17e3 Thomas Thrainer
    if instconflicts:
423 37dc17e3 Thomas Thrainer
      conflicts.append((instance.name, instconflicts))
424 37dc17e3 Thomas Thrainer
425 37dc17e3 Thomas Thrainer
  if conflicts:
426 37dc17e3 Thomas Thrainer
    lu.LogWarning("IP addresses from network '%s', which is about to %s"
427 37dc17e3 Thomas Thrainer
                  " node group '%s', are in use: %s" %
428 37dc17e3 Thomas Thrainer
                  (lu.network_name, action, lu.group.name,
429 37dc17e3 Thomas Thrainer
                   utils.CommaJoin(("%s: %s" %
430 37dc17e3 Thomas Thrainer
                                    (name, _FmtNetworkConflict(details)))
431 37dc17e3 Thomas Thrainer
                                   for (name, details) in conflicts)))
432 37dc17e3 Thomas Thrainer
433 37dc17e3 Thomas Thrainer
    raise errors.OpPrereqError("Conflicting IP addresses found; "
434 37dc17e3 Thomas Thrainer
                               " remove/modify the corresponding network"
435 37dc17e3 Thomas Thrainer
                               " interfaces", errors.ECODE_STATE)
436 37dc17e3 Thomas Thrainer
437 37dc17e3 Thomas Thrainer
438 37dc17e3 Thomas Thrainer
class LUNetworkConnect(LogicalUnit):
439 37dc17e3 Thomas Thrainer
  """Connect a network to a nodegroup
440 37dc17e3 Thomas Thrainer

441 37dc17e3 Thomas Thrainer
  """
442 37dc17e3 Thomas Thrainer
  HPATH = "network-connect"
443 37dc17e3 Thomas Thrainer
  HTYPE = constants.HTYPE_NETWORK
444 37dc17e3 Thomas Thrainer
  REQ_BGL = False
445 37dc17e3 Thomas Thrainer
446 37dc17e3 Thomas Thrainer
  def ExpandNames(self):
447 37dc17e3 Thomas Thrainer
    self.network_name = self.op.network_name
448 37dc17e3 Thomas Thrainer
    self.group_name = self.op.group_name
449 37dc17e3 Thomas Thrainer
    self.network_mode = self.op.network_mode
450 37dc17e3 Thomas Thrainer
    self.network_link = self.op.network_link
451 37dc17e3 Thomas Thrainer
452 37dc17e3 Thomas Thrainer
    self.network_uuid = self.cfg.LookupNetwork(self.network_name)
453 37dc17e3 Thomas Thrainer
    self.group_uuid = self.cfg.LookupNodeGroup(self.group_name)
454 37dc17e3 Thomas Thrainer
455 37dc17e3 Thomas Thrainer
    self.needed_locks = {
456 37dc17e3 Thomas Thrainer
      locking.LEVEL_INSTANCE: [],
457 37dc17e3 Thomas Thrainer
      locking.LEVEL_NODEGROUP: [self.group_uuid],
458 37dc17e3 Thomas Thrainer
      }
459 37dc17e3 Thomas Thrainer
    self.share_locks[locking.LEVEL_INSTANCE] = 1
460 37dc17e3 Thomas Thrainer
461 37dc17e3 Thomas Thrainer
    if self.op.conflicts_check:
462 37dc17e3 Thomas Thrainer
      self.needed_locks[locking.LEVEL_NETWORK] = [self.network_uuid]
463 37dc17e3 Thomas Thrainer
      self.share_locks[locking.LEVEL_NETWORK] = 1
464 37dc17e3 Thomas Thrainer
465 37dc17e3 Thomas Thrainer
  def DeclareLocks(self, level):
466 37dc17e3 Thomas Thrainer
    if level == locking.LEVEL_INSTANCE:
467 37dc17e3 Thomas Thrainer
      assert not self.needed_locks[locking.LEVEL_INSTANCE]
468 37dc17e3 Thomas Thrainer
469 37dc17e3 Thomas Thrainer
      # Lock instances optimistically, needs verification once group lock has
470 37dc17e3 Thomas Thrainer
      # been acquired
471 37dc17e3 Thomas Thrainer
      if self.op.conflicts_check:
472 37dc17e3 Thomas Thrainer
        self.needed_locks[locking.LEVEL_INSTANCE] = \
473 da4a52a3 Thomas Thrainer
          self.cfg.GetInstanceNames(
474 da4a52a3 Thomas Thrainer
            self.cfg.GetNodeGroupInstances(self.group_uuid))
475 37dc17e3 Thomas Thrainer
476 37dc17e3 Thomas Thrainer
  def BuildHooksEnv(self):
477 37dc17e3 Thomas Thrainer
    ret = {
478 37dc17e3 Thomas Thrainer
      "GROUP_NAME": self.group_name,
479 37dc17e3 Thomas Thrainer
      "GROUP_NETWORK_MODE": self.network_mode,
480 37dc17e3 Thomas Thrainer
      "GROUP_NETWORK_LINK": self.network_link,
481 37dc17e3 Thomas Thrainer
      }
482 37dc17e3 Thomas Thrainer
    return ret
483 37dc17e3 Thomas Thrainer
484 37dc17e3 Thomas Thrainer
  def BuildHooksNodes(self):
485 1c3231aa Thomas Thrainer
    node_uuids = self.cfg.GetNodeGroup(self.group_uuid).members
486 1c3231aa Thomas Thrainer
    return (node_uuids, node_uuids)
487 37dc17e3 Thomas Thrainer
488 37dc17e3 Thomas Thrainer
  def CheckPrereq(self):
489 37dc17e3 Thomas Thrainer
    owned_groups = frozenset(self.owned_locks(locking.LEVEL_NODEGROUP))
490 37dc17e3 Thomas Thrainer
491 37dc17e3 Thomas Thrainer
    assert self.group_uuid in owned_groups
492 37dc17e3 Thomas Thrainer
493 37dc17e3 Thomas Thrainer
    # Check if locked instances are still correct
494 da4a52a3 Thomas Thrainer
    owned_instance_names = frozenset(self.owned_locks(locking.LEVEL_INSTANCE))
495 37dc17e3 Thomas Thrainer
    if self.op.conflicts_check:
496 da4a52a3 Thomas Thrainer
      CheckNodeGroupInstances(self.cfg, self.group_uuid, owned_instance_names)
497 37dc17e3 Thomas Thrainer
498 37dc17e3 Thomas Thrainer
    self.netparams = {
499 37dc17e3 Thomas Thrainer
      constants.NIC_MODE: self.network_mode,
500 37dc17e3 Thomas Thrainer
      constants.NIC_LINK: self.network_link,
501 37dc17e3 Thomas Thrainer
      }
502 37dc17e3 Thomas Thrainer
    objects.NIC.CheckParameterSyntax(self.netparams)
503 37dc17e3 Thomas Thrainer
504 37dc17e3 Thomas Thrainer
    self.group = self.cfg.GetNodeGroup(self.group_uuid)
505 37dc17e3 Thomas Thrainer
    #if self.network_mode == constants.NIC_MODE_BRIDGED:
506 37dc17e3 Thomas Thrainer
    #  _CheckNodeGroupBridgesExist(self, self.network_link, self.group_uuid)
507 37dc17e3 Thomas Thrainer
    self.connected = False
508 37dc17e3 Thomas Thrainer
    if self.network_uuid in self.group.networks:
509 37dc17e3 Thomas Thrainer
      self.LogWarning("Network '%s' is already mapped to group '%s'" %
510 37dc17e3 Thomas Thrainer
                      (self.network_name, self.group.name))
511 37dc17e3 Thomas Thrainer
      self.connected = True
512 37dc17e3 Thomas Thrainer
513 37dc17e3 Thomas Thrainer
    # check only if not already connected
514 37dc17e3 Thomas Thrainer
    elif self.op.conflicts_check:
515 37dc17e3 Thomas Thrainer
      pool = network.AddressPool(self.cfg.GetNetwork(self.network_uuid))
516 37dc17e3 Thomas Thrainer
517 da4a52a3 Thomas Thrainer
      _NetworkConflictCheck(
518 da4a52a3 Thomas Thrainer
        self, lambda nic: pool.Contains(nic.ip), "connect to",
519 3fe41221 Klaus Aehlig
        [instance_info for (_, instance_info) in
520 3fe41221 Klaus Aehlig
         self.cfg.GetMultiInstanceInfoByName(owned_instance_names)])
521 37dc17e3 Thomas Thrainer
522 37dc17e3 Thomas Thrainer
  def Exec(self, feedback_fn):
523 37dc17e3 Thomas Thrainer
    # Connect the network and update the group only if not already connected
524 37dc17e3 Thomas Thrainer
    if not self.connected:
525 37dc17e3 Thomas Thrainer
      self.group.networks[self.network_uuid] = self.netparams
526 37dc17e3 Thomas Thrainer
      self.cfg.Update(self.group, feedback_fn)
527 37dc17e3 Thomas Thrainer
528 37dc17e3 Thomas Thrainer
529 37dc17e3 Thomas Thrainer
class LUNetworkDisconnect(LogicalUnit):
530 37dc17e3 Thomas Thrainer
  """Disconnect a network to a nodegroup
531 37dc17e3 Thomas Thrainer

532 37dc17e3 Thomas Thrainer
  """
533 37dc17e3 Thomas Thrainer
  HPATH = "network-disconnect"
534 37dc17e3 Thomas Thrainer
  HTYPE = constants.HTYPE_NETWORK
535 37dc17e3 Thomas Thrainer
  REQ_BGL = False
536 37dc17e3 Thomas Thrainer
537 37dc17e3 Thomas Thrainer
  def ExpandNames(self):
538 37dc17e3 Thomas Thrainer
    self.network_name = self.op.network_name
539 37dc17e3 Thomas Thrainer
    self.group_name = self.op.group_name
540 37dc17e3 Thomas Thrainer
541 37dc17e3 Thomas Thrainer
    self.network_uuid = self.cfg.LookupNetwork(self.network_name)
542 37dc17e3 Thomas Thrainer
    self.group_uuid = self.cfg.LookupNodeGroup(self.group_name)
543 37dc17e3 Thomas Thrainer
544 37dc17e3 Thomas Thrainer
    self.needed_locks = {
545 37dc17e3 Thomas Thrainer
      locking.LEVEL_INSTANCE: [],
546 37dc17e3 Thomas Thrainer
      locking.LEVEL_NODEGROUP: [self.group_uuid],
547 37dc17e3 Thomas Thrainer
      }
548 37dc17e3 Thomas Thrainer
    self.share_locks[locking.LEVEL_INSTANCE] = 1
549 37dc17e3 Thomas Thrainer
550 37dc17e3 Thomas Thrainer
  def DeclareLocks(self, level):
551 37dc17e3 Thomas Thrainer
    if level == locking.LEVEL_INSTANCE:
552 37dc17e3 Thomas Thrainer
      assert not self.needed_locks[locking.LEVEL_INSTANCE]
553 37dc17e3 Thomas Thrainer
554 37dc17e3 Thomas Thrainer
      # Lock instances optimistically, needs verification once group lock has
555 37dc17e3 Thomas Thrainer
      # been acquired
556 37dc17e3 Thomas Thrainer
      self.needed_locks[locking.LEVEL_INSTANCE] = \
557 da4a52a3 Thomas Thrainer
        self.cfg.GetInstanceNames(
558 da4a52a3 Thomas Thrainer
          self.cfg.GetNodeGroupInstances(self.group_uuid))
559 37dc17e3 Thomas Thrainer
560 37dc17e3 Thomas Thrainer
  def BuildHooksEnv(self):
561 37dc17e3 Thomas Thrainer
    ret = {
562 37dc17e3 Thomas Thrainer
      "GROUP_NAME": self.group_name,
563 37dc17e3 Thomas Thrainer
      }
564 37dc17e3 Thomas Thrainer
    return ret
565 37dc17e3 Thomas Thrainer
566 37dc17e3 Thomas Thrainer
  def BuildHooksNodes(self):
567 37dc17e3 Thomas Thrainer
    nodes = self.cfg.GetNodeGroup(self.group_uuid).members
568 37dc17e3 Thomas Thrainer
    return (nodes, nodes)
569 37dc17e3 Thomas Thrainer
570 37dc17e3 Thomas Thrainer
  def CheckPrereq(self):
571 37dc17e3 Thomas Thrainer
    owned_groups = frozenset(self.owned_locks(locking.LEVEL_NODEGROUP))
572 37dc17e3 Thomas Thrainer
573 37dc17e3 Thomas Thrainer
    assert self.group_uuid in owned_groups
574 37dc17e3 Thomas Thrainer
575 37dc17e3 Thomas Thrainer
    # Check if locked instances are still correct
576 37dc17e3 Thomas Thrainer
    owned_instances = frozenset(self.owned_locks(locking.LEVEL_INSTANCE))
577 5eacbcae Thomas Thrainer
    CheckNodeGroupInstances(self.cfg, self.group_uuid, owned_instances)
578 37dc17e3 Thomas Thrainer
579 37dc17e3 Thomas Thrainer
    self.group = self.cfg.GetNodeGroup(self.group_uuid)
580 37dc17e3 Thomas Thrainer
    self.connected = True
581 37dc17e3 Thomas Thrainer
    if self.network_uuid not in self.group.networks:
582 37dc17e3 Thomas Thrainer
      self.LogWarning("Network '%s' is not mapped to group '%s'",
583 37dc17e3 Thomas Thrainer
                      self.network_name, self.group.name)
584 37dc17e3 Thomas Thrainer
      self.connected = False
585 37dc17e3 Thomas Thrainer
586 37dc17e3 Thomas Thrainer
    # We need this check only if network is not already connected
587 37dc17e3 Thomas Thrainer
    else:
588 da4a52a3 Thomas Thrainer
      _NetworkConflictCheck(
589 da4a52a3 Thomas Thrainer
        self, lambda nic: nic.network == self.network_uuid, "disconnect from",
590 32449822 Dimitris Aragiorgis
        [instance_info for (_, instance_info) in
591 e0e44476 Michele Tartara
         self.cfg.GetMultiInstanceInfoByName(owned_instances)])
592 37dc17e3 Thomas Thrainer
593 37dc17e3 Thomas Thrainer
  def Exec(self, feedback_fn):
594 37dc17e3 Thomas Thrainer
    # Disconnect the network and update the group only if network is connected
595 37dc17e3 Thomas Thrainer
    if self.connected:
596 37dc17e3 Thomas Thrainer
      del self.group.networks[self.network_uuid]
597 37dc17e3 Thomas Thrainer
      self.cfg.Update(self.group, feedback_fn)