Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / network.py @ 1c4910f7

History | View | Annotate | Download (18.7 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
    del self.remove_locks[locking.LEVEL_NETWORK]
200 37dc17e3 Thomas Thrainer
201 37dc17e3 Thomas Thrainer
202 37dc17e3 Thomas Thrainer
class LUNetworkRemove(LogicalUnit):
203 37dc17e3 Thomas Thrainer
  HPATH = "network-remove"
204 37dc17e3 Thomas Thrainer
  HTYPE = constants.HTYPE_NETWORK
205 37dc17e3 Thomas Thrainer
  REQ_BGL = False
206 37dc17e3 Thomas Thrainer
207 37dc17e3 Thomas Thrainer
  def ExpandNames(self):
208 37dc17e3 Thomas Thrainer
    self.network_uuid = self.cfg.LookupNetwork(self.op.network_name)
209 37dc17e3 Thomas Thrainer
210 37dc17e3 Thomas Thrainer
    self.share_locks[locking.LEVEL_NODEGROUP] = 1
211 37dc17e3 Thomas Thrainer
    self.needed_locks = {
212 37dc17e3 Thomas Thrainer
      locking.LEVEL_NETWORK: [self.network_uuid],
213 37dc17e3 Thomas Thrainer
      locking.LEVEL_NODEGROUP: locking.ALL_SET,
214 37dc17e3 Thomas Thrainer
      }
215 37dc17e3 Thomas Thrainer
216 37dc17e3 Thomas Thrainer
  def CheckPrereq(self):
217 37dc17e3 Thomas Thrainer
    """Check prerequisites.
218 37dc17e3 Thomas Thrainer

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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