cc1  v2.1
CC1 source code docs
 All Classes Namespaces Files Functions Variables Pages
storage.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.storage
22 #
23 # @author Maciej Nabożny <di.dijo@gmail.com>
24 #
25 
26 from django.db import models
27 from django.db.models import Sum
28 from django.template import loader, Context
29 
30 from cm.utils.exception import CMException
31 from common.states import storage_states
32 import libvirt
33 
34 
35 ##
36 #
37 # @model{STORAGE} Class for storages
38 #
39 # This class controlls cluster's Storage - where Images are stored.
40 # Storage is mounted to Node physical machine via web interface.
41 #
42 class Storage(models.Model):
43  name = models.CharField(max_length=256)
44  capacity = models.IntegerField()
45  state = models.IntegerField(default=0)
46  address = models.CharField(max_length=64, null=True)
47  dir = models.CharField(max_length=256, null=True)
48  transport = models.CharField(max_length=20, default="netfs")
49 
50  class Meta:
51  app_label = 'cm'
52 
53  # method for printing object instance
54  def __unicode__(self):
55  return self.name
56 
57  @property
58  ##
59  #
60  # @returns{dict} this Storage's data
61  # \n fields:
62  # @dictkey{id,int}
63  # @dictkey{state} @seealso{src.common.states.storage_states}
64  # @dictkey{name,string} human-readable name of this Storage
65  # @dictkey{capacity,int} space total [MB] of this Storage
66  # @dictkey{used_space,int} space used [MB]
67  # @dictkey{mountpoint,string} mountpoint path to this Storage on the CM
68  # @dictkey{dir,string} export path on the NFC server
69  # @dictkey{address,string} NFC server address
70  #
71  def dict(self):
72  d = {}
73  d['storage_id'] = self.id
74  d['state'] = self.state
75  d['name'] = self.name
76  d['capacity'] = self.capacity
77  d['used_space'] = self.used_space
78  # TODO: zmienic
79  d['mountpoint'] = self.path
80  d['dir'] = self.dir
81  d['address'] = self.address
82  return d
83 
84  @property
85  ##
86  #
87  # @returns{string} total mountpoint path to this Storage on the CM
88  #
89  def path(self):
90  # TODO: zmienic/change
91  # try:
92  # vol = pool.storageVolLookupByName('info')
93  # except:
94  # template = loader.get_template("volumes/file.xml")
95  # c = Context({'name': 'info',
96  # 'size': 1})
97  # vol = pool.createXML(template.render(c), 0)
98  #
99  # path = vol.path().replace('/info', '/')
100  try:
101  conn = libvirt.open('qemu:///system')
102  conn.storagePoolLookupByName(self.name)
103  except:
104  pass
105  # raise CMException('storage_not_mounted')
106  return '/var/lib/cc1/storages/%s/' % self.name
107 
108  @property
109  ##
110  #
111  # Returns total size of images space (system, disks and cds) used on this Storage [MB]
112  # @returns{int} used space on storage
113  #
114  def used_space(self):
115 
116  return self.image_set.aggregate(Sum('size'))['size__sum'] or 0
117 
118  @property
119  ##
120  #
121  # @returns{int} free space on this Storage [MB]
122  #
123  def free_space(self):
124  return self.capacity - self.used_space
125 
126  @staticmethod
127  ##
128  #
129  # Returns the Storage with the most amount of free space
130  # @returns{Storage} instance of Storage with the most amount of free space
131  #
132  # @raises{storage_no_storage,CMException} no Storages mounted
133  #
134  def get():
135 
136  storages = Storage.objects.filter(state__exact=storage_states['ok'])
137 
138  # if len(storages) == 0:
139  if storages.count() == 0:
140  raise CMException("storage_no_storage")
141 
142  # order storages by free_space, which is a property method, not a field
143  # storages.sort(key=lambda storage: storage.free_space)
144  sorted(storages, key=lambda storage: storage.free_space)
145 
146  # return the first
147  return storages[0]
148 
149  ##
150  #
151  # Method sets this Storage's state as "locked". Nothing can be read from
152  # or written to this Storage. Images saved on this Storage are displayed
153  # on the Web Interface as unavailable.
154  #
155  def lock(self):
156  self.state = storage_states['locked']
157 
158  ##
159  #
160  # Method sets this Storage's state as "ok". Storage may be used as usual.
161  #
162  def unlock(self):
163  self.state = storage_states['ok']
164 
165  def libvirt_template(self):
166  template = loader.get_template("pools/%s.xml" % self.transport)
167  c = Context({'storage': self,
168  'cc_userid': 331,
169  'cc_groupid': 331})
170  return template.render(c)
171