cc1  v2.1
CC1 source code docs
 All Classes Namespaces Files Functions Variables Pages
available_network.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 # @COPYRIGHT_begin
3 #
4 # Copyright [2010-2014] Institute of Nuclear Physics PAN, Krakow, Poland
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 # @COPYRIGHT_end
19 
20 ##
21 # @package src.cm.models.available_netword
22 # @author Maciej Nabożny <mn@mnabozny.pl>
23 #
24 #
25 # Database model describing ip pool for user netwroks
26 #
27 
28 import traceback
29 
30 from django.db import models
31 
32 from cm.models.user_network import UserNetwork
33 from cm.utils import log
34 from cm.utils.exception import CMException
35 from common.states import available_network_states
36 from netaddr import IPNetwork
37 
38 
39 class AvailableNetwork(models.Model):
40  address = models.CharField(max_length=20)
41  mask = models.IntegerField()
42  state = models.IntegerField()
43 
44  class Meta:
45  app_label = 'cm'
46 
47  def __unicode__(self):
48  return "%s/%d" % (self.address, self.mask)
49 
50  @property
51  def dict(self):
52  d = {}
53  d['pool_id'] = self.id
54  d['address'] = self.address
55  d['mask'] = self.mask
56  d['state'] = self.state
57  return d
58 
59  def to_cidr(self):
60  return self.address + "/" + str(self.mask)
61 
62  def to_ipnetwork(self):
63  return IPNetwork(self.address + "/" + str(self.mask))
64 
65  ##
66  #
67  # Check if any vm uses this network
68  #
69  def is_in_use(self):
70  for net in self.usernetwork_set.all():
71  if net.is_in_use():
72  return True
73  return False
74 
75  ##
76  #
77  # Removes all user networks from this network
78  #
79  def release(self):
80  if self.is_in_use():
81  raise CMException('network_in_use')
82 
83  for net in self.usernetwork_set.all():
84  net.release()
85  net.delete()
86 
87  ##
88  #
89  # @returns Unused subnetwork represented by IPNetwork object
90  #
91  def get_unused_ipnetwork(self, mask):
92  networks = []
93  for network in self.usernetwork_set.all():
94  networks.append(network.to_ipnetwork())
95  networks = sorted(networks)
96 
97  log.debug(1, 'Networks: %s' % str(networks))
98 
99  if self.mask > mask:
100  raise CMException('network_to_large')
101 
102  if len(networks) == 0:
103  return IPNetwork(self.address + '/' + str(mask))
104 
105  if IPNetwork(self.address + '/' + str(mask)).network < networks[0].network:
106  return IPNetwork(self.address + '/' + str(mask))
107 
108  # Find matching hole in existing networks
109  for i in xrange(len(networks) - 1):
110  n = IPNetwork(str(networks[i].next().ip) + "/" + str(mask))
111  if networks[i] < n and n < networks[i + 1]:
112  return n
113 
114  # If previous fails, try to fit network at end of pool
115  n = IPNetwork(str(networks[-1].next().network) + "/" + str(mask))
116  log.debug(1, 'Trying: %s' % str(n))
117  if networks[-1].network < n.network and n.network < self.to_ipnetwork().next().network:
118  return n
119  else:
120  # or raise exception, if this is not possible
121  raise CMException("network_unavailable")
122 
123  @staticmethod
124  ##
125  #
126  # Get unused lease for given user and vm
127  #
128  def get_lease(user):
129  user_networks = UserNetwork.objects.filter(user=user).all()
130  lease = None
131 
132  for network in user_networks:
133  try:
134  lease = network.get_unused()
135  break
136  except:
137  log.debug(user.id, 'UserNetwork %s has no leases' % str(network.address))
138 
139  if lease == None:
140  log.debug(user.id, 'No lease found in existing networks. Allocating new UserNetwork')
141  for pool in AvailableNetwork.objects.filter(state=available_network_states['ok']):
142  try:
143  ipnet = pool.get_unused_ipnetwork(26)
144 
145  log.debug(user.id, 'Allocated new user_network: %s' % str(ipnet))
146  network = UserNetwork()
147  network.user = user
148  network.mask = ipnet.prefixlen
149  network.address = str(ipnet.network)
150  network.name = "Auto-generated network"
151  network.available_network = pool
152 
153  network.save()
154  network.allocate()
155 
156  lease = network.get_unused()
157  break
158  except Exception, e:
159  f = open('/tmp/trace', 'a')
160  traceback.print_exc(file=f)
161  f.close()
162  log.debug(user.id, "Cannot allocate new network in %s: %s" % (str(pool.address), str(e)))
163 
164  if lease == None:
165  raise CMException('available_network_not_found')
166  else:
167  return lease
168 
169  @classmethod
170  def network_exists(cls, ipnet):
171  networks = []
172  for net in cls.objects.all():
173  networks.append(net.to_ipnetwork())
174  networks.sort()
175 
176  # Find duplicate
177  for i in xrange(len(networks)):
178  if ipnet.prefixlen > networks[i].prefixlen and ipnet > networks[i].previous() and ipnet < networks[i].next():
179  return True
180  elif ipnet.prefixlen < networks[i].prefixlen and ipnet.previous() < networks[i] and ipnet.next() > networks[i]:
181  return True
182  return False
183