cc1  v2.1
CC1 source code docs
 All Classes Namespaces Files Functions Variables Pages
lease.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.views.user.network
22 # @author Maciej Nabożny <mn@mnabozny.pl>
23 #
24 #
25 # Database model describing single lease or mirco-network (depends on networking
26 # model) for VM
27 #
28 from django.db import models
29 from django.template import loader, Context
30 from netaddr import IPNetwork, IPAddress
31 
32 import socket
33 import libvirt
34 
35 from cm.utils.exception import CMException
36 from cm.utils import log
37 from cm.settings import DNS_DOMAIN
38 
39 
40 class Lease(models.Model):
41  address = models.CharField(max_length=20)
42  user_network = models.ForeignKey('UserNetwork')
43  vm = models.ForeignKey('VM', null=True, blank=True)
44 
45  class Meta:
46  app_label = 'cm'
47 
48  def __unicode__(self):
49  return self.address
50 
51  @property
52  def dict(self):
53  d = {}
54  d['lease_id'] = self.id
55  d['address'] = self.vm_address
56  d['user_network_id'] = self.user_network.id
57  if self.vm:
58  d['vm'] = self.vm.id
59  else:
60  d['vm'] = None
61  d['user_id'] = self.user_network.user.id
62  try:
63  d['public_ip'] = self.publicip_set.all()[0].dict
64  except:
65  d['public_ip'] = ''
66 
67  return d
68 
69  @property
70  def node_address(self):
71  network = IPNetwork('%s/30' % self.address)
72  return str(network.network + 1)
73 
74  @property
75  def vm_address(self):
76  network = IPNetwork('%s/30' % self.address)
77  return str(network.network + 2)
78 
79  @property
80  def cm_address(self):
81  if self.vm == None or self.vm.node == None:
82  raise CMException('lease_not_attached')
83  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
84  s.connect((self.vm.node.address, 22))
85  return s.getsockname()[0]
86 
87  @property
88  def domain_name(self):
89  return DNS_DOMAIN
90 
91  @property
92  def hostname(self):
93  return 'vm-%d' % self.vm.id
94 
95  @property
96  def mac(self):
97  ip_hex = '%08x' % IPAddress(self.address).value
98  return '00:02:%s:%s:%s:%s' % (ip_hex[0:2], ip_hex[2:4], ip_hex[4:6], ip_hex[6:8])
99 
100  def attach_node(self):
101  template = loader.get_template('networking/routed.xml')
102  context = Context({
103  'lease': self,
104  'vm': self.vm
105  })
106 
107  network_xml = template.render(context)
108  log.debug(self.user_network.user.id, "Rendered network template:\n%s" % network_xml)
109  conn = libvirt.open(self.vm.node.conn_string)
110  net = conn.networkDefineXML(network_xml)
111  net.create()
112 
113  ##
114  #
115  # @raises{lease_detached,CMException} Network was not defined
116  #
117  def detach_node(self):
118  if self.vm_id == None:
119  raise CMException('lease_detached')
120 
121  # Destroy network
122  try:
123  conn = libvirt.open(self.vm.node.conn_string)
124  except Exception, e:
125  log.exception(self.user_network.user_id, "Cannot connet to libvirt: ")
126  raise CMException('lease_detach')
127 
128  lv_network = None
129  try:
130  lv_network = conn.networkLookupByName('net-%d-%d' % (self.vm.id, self.id))
131  except Exception, e: # it's sad that network is missing, but if it was WN from init_head state farm, it's ok
132  log.error(self.user_network.user_id, "Cannotfind libvirt network: %s" % str(e))
133  lv_network = None
134 
135  if lv_network:
136  try:
137  lv_network.destroy()
138  lv_network.undefine()
139  except Exception, e: # it's sad that network is missing, but if it was WN from init_head state farm, it's ok
140  log.error(self.user_network.user_id, "Cannot destroy or undefine libvirt network: %s" % str(e))
141  # raise CMException('lease_detach')
142 
143  # Detach public ip
144  for public_lease in self.publicip_set.all():
145  log.debug(self.user_network.user.id, "\t...detaching public lease %s" % public_lease.address)
146  public_lease.unassign()
147 
148  conn.close()
149  self.vm_id = None
150  self.save()
151