cc1  v2.1
CC1 source code docs
 All Classes Namespaces Files Functions Variables Pages
vm.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.utils.vm_threads
22 # @author Tomek Sośnicki <tom.sosnicki@gmail.com>
23 # @author Maciej Nabożny <mn@mnabozny.pl>
24 #
25 import threading
26 import libvirt
27 
28 from common.states import farm_states # ,vm_states
29 from cm.models.vm import VM
30 from cm.utils import log
31 from django.db import transaction
32 from cm.utils import message
33 
34 #TODO:add global threads
35 #threads = {}
36 
37 
38 class VMThread(threading.Thread):
39  def __init__(self, vm, action, shared=None):
40  threading.Thread.__init__(self)
41  self.vm = vm
42  self.action = action
43  self.shared = shared
44 
45  def terminate(self):
46  log.info(0, "Terminate vm %d" % (self.vm.id))
47  return self._Thread__stop()
48 
49  ##
50  #
51  # Starts VM's thread.
52  # -# Gets VM's record from database (basing on vm_id) (if exists).
53  # -# Copies image chosen for this VM.
54  # -# Connects to Libvirt and generate template for it.
55  # -# Creates Libvirt domain.
56  # -# Sets VM's state as *running*
57  # -# If VM is element of farm, it sets proper farm state.
58  #
59  def create(self):
60  # TODO: Assign ip address from node ip addresses
61  # try:
62  # vm = VM.objects.get(id=self.vm)
63  # except Exception, e:
64  # log.exception(0, 'Cannot find vm %d: %s'%(self.vm, e))
65  # return
66  try:
67  log.info(self.vm.user_id, "Copy image from %s to %s" % (self.vm.system_image.path, self.vm.path))
68  self.vm.system_image.copy_to_node(self.vm)
69  except Exception, e:
70  log.exception(self.vm.user_id, 'Libvirt error for %d: %s' % (self.vm.id, e))
71  self.vm.set_state('failed')
72  message.error(self.vm.user_id, 'vm_create', {'id': self.vm.id, 'name': self.vm.name})
73  self.vm.node.lock()
74  self.vm.save(update_fields=['state'])
75  return
76 
77  #TODO: network part
78  log.debug(self.vm.user_id, "Attaching network")
79  try:
80  for lease in self.vm.lease_set.all():
81  lease.attach_node()
82  except Exception, e:
83  log.exception(self.vm.user_id, "Cannot create network")
84  self.vm.set_state('failed')
85  self.vm.save(update_fields=['state'])
86  message.error(self.vm.user_id, 'vm_create', {'id': self.vm.id, 'name': self.vm.name})
87  self.vm.node.lock()
88  self.vm.node.save()
89  return
90 
91  log.info(self.vm.user_id, "Connecting libvirt and generating template")
92  try:
93  conn = libvirt.open(self.vm.node.conn_string)
94  tmpl = self.vm.libvirt_template()
95  log.debug(self.vm.user_id, "Create from template: %s" % tmpl)
96  except Exception, e:
97  log.exception(self.vm.user_id, "Cannot connect to libvirt")
98  self.vm.set_state('failed')
99  message.error(self.vm.user_id, 'vm_create', {'id': self.vm.id, 'name': self.vm.name})
100  self.vm.node.lock()
101  self.vm.save(update_fields=['state'])
102  return
103 
104  log.info(self.vm.user_id, "Creating libvirt domain")
105  try:
106  domain = conn.createXML(tmpl, 0)
107  self.vm.libvirt_id = domain.ID()
108  self.vm.save(update_fields=['libvirt_id'])
109  log.debug(self.vm.user_id, "New domain id: %d" % domain.ID())
110  except Exception, e:
111  log.exception(self.vm.user_id, 'Libvirt error: %s' % e)
112  self.vm.set_state('failed')
113  message.error(self.vm.user_id, 'vm_create', {'id': self.vm.id, 'name': self.vm.name})
114  self.vm.node.lock()
115  self.vm.save(update_fields=['state'])
116  return
117 
118  try:
119  self.vm.set_state('running')
120  if self.vm.is_head():
121  #TODO: farm.set_state
122  self.vm.farm.state = farm_states['init_head']
123  self.vm.farm.save()
124  # elif self.vm.is_farm():
125  # self.shared['lock'].acquire()
126  # self.shared['counter'] = self.shared['counter'] - 1
127  # if self.shared['counter'] == 0:
128  # self.vm.farm.state = farm_states['nodes_copied']
129  # self.shared['lock'].release()
130  except Exception, e:
131  self.vm.set_state('failed')
132  self.vm.node.lock()
133  message.error(self.vm.user_id, 'vm_create', {'id': self.vm.id, 'name': self.vm.name})
134  log.exception(self.vm.user_id, 'Domain not started: %s' % str(e))
135  self.vm.save(update_fields=['state'])
136  return
137 
138  try:
139  self.vm.save(update_fields=['state'])
140  except Exception, e:
141  log.exception(self.vm.user_id, 'Cannot update database: %s' % str(e))
142  return
143 
144  ##
145  #
146  # Ends VM's thread.
147  #
148  # -# Unassigns public IP.
149  # -# Deletes VM.
150  #
151  def delete(self):
152  try:
153  VM.objects.update()
154  vm = VM.objects.get(pk=self.vm.id)
155  except Exception, e:
156  log.exception(0, 'Cannot find vm %d: %s' % (self.vm.id, e))
157  return
158  log.debug(vm.user_id, "VM Destroy")
159 
160  #TODO: Move to entites.vm release resources
161  #for lease in vm.public_leases:
162  # lease.unassign()
163 
164  vm.delete()
165  return
166 
167  ##
168  #
169  # Restarts VM.
170  #
171  # -# Connects to Libvirt.
172  # -# Sets VM's state as *restart*.
173  # -# Restarts it.
174  # -# Sets VM's state back as *running*.
175  #
176  def reset(self):
177  log.debug(self.vm.user_id, "VM Reboot")
178 
179  self.vm.set_state('restart')
180  try:
181  self.vm.save()
182  except:
183  log.exception(self.vm.user_id, 'Cannot set vm state')
184  return
185 
186  try:
187  domain = self.vm.lv_domain()
188  domain.reset(0)
189  self.vm.libvirt_id = domain.ID()
190  except:
191  self.vm.node.lock()
192  message.error(self.vm.user_id, 'vm_restart', {'id': self.vm.id, 'name': self.vm.name})
193  self.vm.set_state('failed')
194  log.exception(self.vm.user_id, 'Cannot restart machine')
195 
196  try:
197  self.vm.save()
198  except:
199  log.exception(self.vm.user_id, 'Cannot update libvirt ID')
200  return
201 
202  return
203 
204  # Update state state
205  self.vm.set_state('running')
206  try:
207  self.vm.save()
208  except:
209  log.exception(self.vm.user_id, 'Cannot set vm state')
210  return
211 
212  ##
213  #
214  # Runs proper action depending on \ self.action.
215  #
216  def run(self):
217  #TODO:
218  #global threads
219  #threads[self.vm_id] = self
220  #time.sleep(5)
221  with transaction.commit_manually():
222  try:
223  if self.action == 'create':
224  self.create()
225  elif self.action == 'delete':
226  self.delete()
227  elif self.action == 'reset':
228  self.reset()
229  transaction.commit()
230  except:
231  log.exception(0, 'thread_exception')
232  transaction.rollback()
233  #TODO:
234  #del threads[self.vm_id]
235