~ubuntu-branches/ubuntu/raring/nova/raring-proposed

« back to all changes in this revision

Viewing changes to nova/compute/claims.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Adam Gandelman, Chuck Short
  • Date: 2012-11-23 09:04:58 UTC
  • mfrom: (1.1.66)
  • Revision ID: package-import@ubuntu.com-20121123090458-91565o7aev1i1h71
Tags: 2013.1~g1-0ubuntu1
[ Adam Gandelman ]
* debian/control: Ensure novaclient is upgraded with nova,
  require python-keystoneclient >= 1:2.9.0. (LP: #1073289)
* debian/patches/{ubuntu/*, rbd-security.patch}: Dropped, applied
  upstream.
* debian/control: Add python-testtools to Build-Depends.

[ Chuck Short ]
* New upstream version.
* Refreshed debian/patches/avoid_setuptools_git_dependency.patch.
* debian/rules: FTBFS if missing binaries.
* debian/nova-scheudler.install: Add missing rabbit-queues and
  nova-rpc-zmq-receiver.
* Remove nova-volume since it doesnt exist anymore, transition to cinder-*.
* debian/rules: install apport hook in the right place.
* debian/patches/ubuntu-show-tests.patch: Display test failures.
* debian/control: Add depends on genisoimage
* debian/control: Suggest guestmount.
* debian/control: Suggest websockify. (LP: #1076442)
* debian/nova.conf: Disable nova-volume service.
* debian/control: Depend on xen-system-* rather than the hypervisor.
* debian/control, debian/mans/nova-conductor.8, debian/nova-conductor.init,
  debian/nova-conductor.install, debian/nova-conductor.logrotate
  debian/nova-conductor.manpages, debian/nova-conductor.postrm
  debian/nova-conductor.upstart.in: Add nova-conductor service.
* debian/control: Add python-fixtures as a build deps.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2012 OpenStack, LLC.
 
2
# All Rights Reserved.
 
3
#
 
4
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
5
#    not use this file except in compliance with the License. You may obtain
 
6
#    a copy of the License at
 
7
#
 
8
#         http://www.apache.org/licenses/LICENSE-2.0
 
9
#
 
10
#    Unless required by applicable law or agreed to in writing, software
 
11
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
12
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
13
#    License for the specific language governing permissions and limitations
 
14
#    under the License.
 
15
 
 
16
"""
 
17
Claim objects for use with resource tracking.
 
18
"""
 
19
 
 
20
from nova.openstack.common import jsonutils
 
21
from nova.openstack.common import lockutils
 
22
from nova.openstack.common import log as logging
 
23
 
 
24
LOG = logging.getLogger(__name__)
 
25
COMPUTE_RESOURCE_SEMAPHORE = "compute_resources"
 
26
 
 
27
 
 
28
class NopClaim(object):
 
29
    """For use with compute drivers that do not support resource tracking"""
 
30
 
 
31
    def __init__(self, migration=None):
 
32
        self.migration = migration
 
33
 
 
34
    @property
 
35
    def disk_gb(self):
 
36
        return 0
 
37
 
 
38
    @property
 
39
    def memory_mb(self):
 
40
        return 0
 
41
 
 
42
    @property
 
43
    def vcpus(self):
 
44
        return 0
 
45
 
 
46
    def __enter__(self):
 
47
        return self
 
48
 
 
49
    def __exit__(self, exc_type, exc_val, exc_tb):
 
50
        if exc_type is not None:
 
51
            self.abort()
 
52
 
 
53
    def abort(self):
 
54
        pass
 
55
 
 
56
    def __str__(self):
 
57
        return "[Claim: %d MB memory, %d GB disk, %d VCPUS]" % (self.memory_mb,
 
58
                self.disk_gb, self.vcpus)
 
59
 
 
60
 
 
61
class Claim(NopClaim):
 
62
    """A declaration that a compute host operation will require free resources.
 
63
    Claims serve as marker objects that resources are being held until the
 
64
    update_available_resource audit process runs to do a full reconciliation
 
65
    of resource usage.
 
66
 
 
67
    This information will be used to help keep the local compute hosts's
 
68
    ComputeNode model in sync to aid the scheduler in making efficient / more
 
69
    correct decisions with respect to host selection.
 
70
    """
 
71
 
 
72
    def __init__(self, instance, tracker):
 
73
        super(Claim, self).__init__()
 
74
        self.instance = jsonutils.to_primitive(instance)
 
75
        self.tracker = tracker
 
76
 
 
77
    @property
 
78
    def disk_gb(self):
 
79
        return self.instance['root_gb'] + self.instance['ephemeral_gb']
 
80
 
 
81
    @property
 
82
    def memory_mb(self):
 
83
        return self.instance['memory_mb']
 
84
 
 
85
    @property
 
86
    def vcpus(self):
 
87
        return self.instance['vcpus']
 
88
 
 
89
    @lockutils.synchronized(COMPUTE_RESOURCE_SEMAPHORE, 'nova-')
 
90
    def abort(self):
 
91
        """Compute operation requiring claimed resources has failed or
 
92
        been aborted.
 
93
        """
 
94
        LOG.debug(_("Aborting claim: %s") % self, instance=self.instance)
 
95
        self.tracker.abort_instance_claim(self.instance)
 
96
 
 
97
    def test(self, resources, limits=None):
 
98
        """Test if this claim can be satisfied given available resources and
 
99
        optional oversubscription limits
 
100
 
 
101
        This should be called before the compute node actually consumes the
 
102
        resources required to execute the claim.
 
103
 
 
104
        :param resources: available local compute node resources
 
105
        :returns: Return true if resources are available to claim.
 
106
        """
 
107
        if not limits:
 
108
            limits = {}
 
109
 
 
110
        # If an individual limit is None, the resource will be considered
 
111
        # unlimited:
 
112
        memory_mb_limit = limits.get('memory_mb')
 
113
        disk_gb_limit = limits.get('disk_gb')
 
114
        vcpu_limit = limits.get('vcpu')
 
115
 
 
116
        msg = _("Attempting claim: memory %(memory_mb)d MB, disk %(disk_gb)d "
 
117
                "GB, VCPUs %(vcpus)d")
 
118
        params = {'memory_mb': self.memory_mb, 'disk_gb': self.disk_gb,
 
119
                  'vcpus': self.vcpus}
 
120
        LOG.audit(msg % params, instance=self.instance)
 
121
 
 
122
        # Test for resources:
 
123
        can_claim = (self._test_memory(resources, memory_mb_limit) and
 
124
                     self._test_disk(resources, disk_gb_limit) and
 
125
                     self._test_cpu(resources, vcpu_limit))
 
126
 
 
127
        if can_claim:
 
128
            LOG.audit(_("Claim successful"), instance=self.instance)
 
129
        else:
 
130
            LOG.audit(_("Claim failed"), instance=self.instance)
 
131
 
 
132
        return can_claim
 
133
 
 
134
    def _test_memory(self, resources, limit):
 
135
        type_ = _("Memory")
 
136
        unit = "MB"
 
137
        total = resources['memory_mb']
 
138
        used = resources['memory_mb_used']
 
139
        requested = self.memory_mb
 
140
 
 
141
        return self._test(type_, unit, total, used, requested, limit)
 
142
 
 
143
    def _test_disk(self, resources, limit):
 
144
        type_ = _("Disk")
 
145
        unit = "GB"
 
146
        total = resources['local_gb']
 
147
        used = resources['local_gb_used']
 
148
        requested = self.disk_gb
 
149
 
 
150
        return self._test(type_, unit, total, used, requested, limit)
 
151
 
 
152
    def _test_cpu(self, resources, limit):
 
153
        type_ = _("CPU")
 
154
        unit = "VCPUs"
 
155
        total = resources['vcpus']
 
156
        used = resources['vcpus_used']
 
157
        requested = self.vcpus
 
158
 
 
159
        return self._test(type_, unit, total, used, requested, limit)
 
160
 
 
161
    def _test(self, type_, unit, total, used, requested, limit):
 
162
        """Test if the given type of resource needed for a claim can be safely
 
163
        allocated.
 
164
        """
 
165
        msg = _("Total %(type_)s: %(total)d %(unit)s, used: %(used)d %(unit)s")
 
166
        LOG.audit(msg % locals(), instance=self.instance)
 
167
 
 
168
        if limit is None:
 
169
            # treat resource as unlimited:
 
170
            LOG.audit(_("%(type_)s limit not specified, defaulting to "
 
171
                        "unlimited") % locals(), instance=self.instance)
 
172
            return True
 
173
 
 
174
        free = limit - used
 
175
 
 
176
        # Oversubscribed resource policy info:
 
177
        msg = _("%(type_)s limit: %(limit)d %(unit)s, free: %(free)d "
 
178
                "%(unit)s") % locals()
 
179
        LOG.audit(msg, instance=self.instance)
 
180
 
 
181
        can_claim = requested <= free
 
182
 
 
183
        if not can_claim:
 
184
            msg = _("Unable to claim resources.  Free %(type_)s %(free)d "
 
185
                    "%(unit)s < requested %(requested)d %(unit)s") % locals()
 
186
            LOG.info(msg, instance=self.instance)
 
187
 
 
188
        return can_claim
 
189
 
 
190
 
 
191
class ResizeClaim(Claim):
 
192
    """Claim used for holding resources for an incoming resize/migration
 
193
    operation.
 
194
    """
 
195
    def __init__(self, instance, instance_type, tracker):
 
196
        super(ResizeClaim, self).__init__(instance, tracker)
 
197
        self.instance_type = instance_type
 
198
        self.migration = None
 
199
 
 
200
    @property
 
201
    def disk_gb(self):
 
202
        return (self.instance_type['root_gb'] +
 
203
                self.instance_type['ephemeral_gb'])
 
204
 
 
205
    @property
 
206
    def memory_mb(self):
 
207
        return self.instance_type['memory_mb']
 
208
 
 
209
    @property
 
210
    def vcpus(self):
 
211
        return self.instance_type['vcpus']
 
212
 
 
213
    @lockutils.synchronized(COMPUTE_RESOURCE_SEMAPHORE, 'nova-')
 
214
    def abort(self):
 
215
        """Compute operation requiring claimed resources has failed or
 
216
        been aborted.
 
217
        """
 
218
        LOG.debug(_("Aborting claim: %s") % self, instance=self.instance)
 
219
        self.tracker.abort_resize_claim(self.instance['uuid'],
 
220
                self.instance_type)