Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / quotas / __init__.py @ 6dbd90c0

History | View | Annotate | Download (10.5 kB)

1 bfe7ba3c Christos Stavrakakis
# Copyright 2012 GRNET S.A. All rights reserved.
2 bfe7ba3c Christos Stavrakakis
#
3 bfe7ba3c Christos Stavrakakis
# Redistribution and use in source and binary forms, with or without
4 bfe7ba3c Christos Stavrakakis
# modification, are permitted provided that the following conditions
5 bfe7ba3c Christos Stavrakakis
# are met:
6 bfe7ba3c Christos Stavrakakis
#
7 bfe7ba3c Christos Stavrakakis
#   1. Redistributions of source code must retain the above copyright
8 bfe7ba3c Christos Stavrakakis
#      notice, this list of conditions and the following disclaimer.
9 bfe7ba3c Christos Stavrakakis
#
10 bfe7ba3c Christos Stavrakakis
#  2. Redistributions in binary form must reproduce the above copyright
11 bfe7ba3c Christos Stavrakakis
#     notice, this list of conditions and the following disclaimer in the
12 bfe7ba3c Christos Stavrakakis
#     documentation and/or other materials provided with the distribution.
13 bfe7ba3c Christos Stavrakakis
#
14 bfe7ba3c Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
15 bfe7ba3c Christos Stavrakakis
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 bfe7ba3c Christos Stavrakakis
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 bfe7ba3c Christos Stavrakakis
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18 bfe7ba3c Christos Stavrakakis
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 bfe7ba3c Christos Stavrakakis
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 bfe7ba3c Christos Stavrakakis
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 bfe7ba3c Christos Stavrakakis
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 bfe7ba3c Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 bfe7ba3c Christos Stavrakakis
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 bfe7ba3c Christos Stavrakakis
# SUCH DAMAGE.
25 bfe7ba3c Christos Stavrakakis
#
26 bfe7ba3c Christos Stavrakakis
# The views and conclusions contained in the software and documentation are
27 bfe7ba3c Christos Stavrakakis
# those of the authors and should not be interpreted as representing official
28 bfe7ba3c Christos Stavrakakis
# policies, either expressed or implied, of GRNET S.A.
29 bfe7ba3c Christos Stavrakakis
30 bfe7ba3c Christos Stavrakakis
from functools import wraps
31 bfe7ba3c Christos Stavrakakis
from contextlib import contextmanager
32 bfe7ba3c Christos Stavrakakis
33 b14f55b5 Christos Stavrakakis
34 b14f55b5 Christos Stavrakakis
from synnefo.db.models import QuotaHolderSerial, VirtualMachine, Network
35 bfe7ba3c Christos Stavrakakis
from synnefo.api.faults import OverLimit
36 6dbd90c0 Christos Stavrakakis
from synnefo.settings import CYCLADES_USE_QUOTAHOLDER
37 6dbd90c0 Christos Stavrakakis
38 6dbd90c0 Christos Stavrakakis
if CYCLADES_USE_QUOTAHOLDER:
39 6dbd90c0 Christos Stavrakakis
    from synnefo.settings import (CYCLADES_QUOTAHOLDER_URL,
40 6dbd90c0 Christos Stavrakakis
                                  CYCLADES_QUOTAHOLDER_TOKEN)
41 6dbd90c0 Christos Stavrakakis
    from kamaki.clients.quotaholder import QuotaholderClient
42 6dbd90c0 Christos Stavrakakis
else:
43 6dbd90c0 Christos Stavrakakis
    from synnefo.settings import (VMS_USER_QUOTA, MAX_VMS_PER_USER,
44 6dbd90c0 Christos Stavrakakis
                                  NETWORKS_USER_QUOTA, MAX_NETWORKS_PER_USER)
45 bfe7ba3c Christos Stavrakakis
46 dba149f6 Christos Stavrakakis
from synnefo.lib.quotaholder.api import (NoCapacityError, NoQuantityError)
47 dba149f6 Christos Stavrakakis
from synnefo.lib.commissioning import CallError
48 bfe7ba3c Christos Stavrakakis
49 bfe7ba3c Christos Stavrakakis
import logging
50 bfe7ba3c Christos Stavrakakis
log = logging.getLogger(__name__)
51 bfe7ba3c Christos Stavrakakis
52 bfe7ba3c Christos Stavrakakis
53 b14f55b5 Christos Stavrakakis
class DummySerial(QuotaHolderSerial):
54 b14f55b5 Christos Stavrakakis
    accepted = True
55 b14f55b5 Christos Stavrakakis
    rejected = True
56 b14f55b5 Christos Stavrakakis
    pending = True
57 b14f55b5 Christos Stavrakakis
    id = None
58 b14f55b5 Christos Stavrakakis
59 b14f55b5 Christos Stavrakakis
    def save(*args, **kwargs):
60 b14f55b5 Christos Stavrakakis
        pass
61 b14f55b5 Christos Stavrakakis
62 b14f55b5 Christos Stavrakakis
63 b14f55b5 Christos Stavrakakis
class DummyQuotaholderClient(object):
64 b14f55b5 Christos Stavrakakis
    def issue_commission(self, **commission_info):
65 b14f55b5 Christos Stavrakakis
        provisions = commission_info["provisions"]
66 b14f55b5 Christos Stavrakakis
        userid = commission_info["target"]
67 b14f55b5 Christos Stavrakakis
        for provision in provisions:
68 b14f55b5 Christos Stavrakakis
            entity, resource, size = provision
69 b14f55b5 Christos Stavrakakis
            if resource == "cyclades.vm":
70 b14f55b5 Christos Stavrakakis
                user_vms = VirtualMachine.objects.filter(userid=userid,
71 b14f55b5 Christos Stavrakakis
                                                         deleted=False).count()
72 b14f55b5 Christos Stavrakakis
                user_vm_limit = VMS_USER_QUOTA.get(userid, MAX_VMS_PER_USER)
73 718a601d root
                log.debug("Users VMs %s User Limits %s", user_vms,
74 718a601d root
                          user_vm_limit)
75 b14f55b5 Christos Stavrakakis
                if user_vms + size >= user_vm_limit:
76 b14f55b5 Christos Stavrakakis
                    raise NoQuantityError()
77 b14f55b5 Christos Stavrakakis
            if resource == "cyclades.network.private":
78 b14f55b5 Christos Stavrakakis
                user_networks = Network.objects.filter(userid=userid,
79 b14f55b5 Christos Stavrakakis
                                                       deleted=False).count()
80 b14f55b5 Christos Stavrakakis
                user_network_limit = NETWORKS_USER_QUOTA.get(userid,
81 b14f55b5 Christos Stavrakakis
                                                         MAX_NETWORKS_PER_USER)
82 b14f55b5 Christos Stavrakakis
                if user_networks + size >= user_network_limit:
83 b14f55b5 Christos Stavrakakis
                    raise NoQuantityError()
84 b14f55b5 Christos Stavrakakis
85 b14f55b5 Christos Stavrakakis
        return None
86 b14f55b5 Christos Stavrakakis
87 b14f55b5 Christos Stavrakakis
    def accept_commission(self, *args, **kwargs):
88 b14f55b5 Christos Stavrakakis
        pass
89 b14f55b5 Christos Stavrakakis
90 b14f55b5 Christos Stavrakakis
    def reject_commission(self, *args, **kwargs):
91 b14f55b5 Christos Stavrakakis
        pass
92 b14f55b5 Christos Stavrakakis
93 b14f55b5 Christos Stavrakakis
    def get_pending_commissions(self, *args, **kwargs):
94 b14f55b5 Christos Stavrakakis
        return []
95 b14f55b5 Christos Stavrakakis
96 b14f55b5 Christos Stavrakakis
97 bfe7ba3c Christos Stavrakakis
@contextmanager
98 bfe7ba3c Christos Stavrakakis
def get_quota_holder():
99 bfe7ba3c Christos Stavrakakis
    """Context manager for using a QuotaHolder."""
100 45855947 Georgios D. Tsoukalas
    if CYCLADES_USE_QUOTAHOLDER:
101 45855947 Georgios D. Tsoukalas
        quotaholder = QuotaholderClient(CYCLADES_QUOTAHOLDER_URL,
102 45855947 Georgios D. Tsoukalas
                                        token=CYCLADES_QUOTAHOLDER_TOKEN)
103 b14f55b5 Christos Stavrakakis
    else:
104 b14f55b5 Christos Stavrakakis
        quotaholder = DummyQuotaholderClient()
105 bfe7ba3c Christos Stavrakakis
106 bfe7ba3c Christos Stavrakakis
    try:
107 bfe7ba3c Christos Stavrakakis
        yield quotaholder
108 bfe7ba3c Christos Stavrakakis
    finally:
109 bfe7ba3c Christos Stavrakakis
        pass
110 bfe7ba3c Christos Stavrakakis
111 bfe7ba3c Christos Stavrakakis
112 bfe7ba3c Christos Stavrakakis
def uses_commission(func):
113 bfe7ba3c Christos Stavrakakis
    """Decorator for wrapping functions that needs commission.
114 bfe7ba3c Christos Stavrakakis

115 bfe7ba3c Christos Stavrakakis
    All decorated functions must take as first argument the `serials` list in
116 bfe7ba3c Christos Stavrakakis
    order to extend them with the needed serial numbers, as return by the
117 bfe7ba3c Christos Stavrakakis
    Quotaholder
118 bfe7ba3c Christos Stavrakakis

119 bfe7ba3c Christos Stavrakakis
    On successful competition of the decorated function, all serials are
120 bfe7ba3c Christos Stavrakakis
    accepted to the quotaholder, otherwise they are rejected.
121 bfe7ba3c Christos Stavrakakis

122 bfe7ba3c Christos Stavrakakis
    """
123 bfe7ba3c Christos Stavrakakis
124 bfe7ba3c Christos Stavrakakis
    @wraps(func)
125 bfe7ba3c Christos Stavrakakis
    def wrapper(*args, **kwargs):
126 bfe7ba3c Christos Stavrakakis
        try:
127 bfe7ba3c Christos Stavrakakis
            serials = []
128 bfe7ba3c Christos Stavrakakis
            ret = func(serials, *args, **kwargs)
129 bfe7ba3c Christos Stavrakakis
            if serials:
130 bfe7ba3c Christos Stavrakakis
                accept_commission(serials)
131 bfe7ba3c Christos Stavrakakis
            return ret
132 e8f2d02d Christos Stavrakakis
        except CallError:
133 bfe7ba3c Christos Stavrakakis
            log.exception("Unexpected error")
134 b14f55b5 Christos Stavrakakis
            raise
135 bfe7ba3c Christos Stavrakakis
        except:
136 bfe7ba3c Christos Stavrakakis
            if serials:
137 bfe7ba3c Christos Stavrakakis
                reject_commission(serials=serials)
138 bfe7ba3c Christos Stavrakakis
            raise
139 bfe7ba3c Christos Stavrakakis
    return wrapper
140 bfe7ba3c Christos Stavrakakis
141 bfe7ba3c Christos Stavrakakis
142 bfe7ba3c Christos Stavrakakis
## FIXME: Wrap the following two functions inside transaction ?
143 11a54cb9 Christos Stavrakakis
def accept_commission(serials, update_db=True):
144 bfe7ba3c Christos Stavrakakis
    """Accept a list of pending commissions.
145 bfe7ba3c Christos Stavrakakis

146 bfe7ba3c Christos Stavrakakis
    @param serials: List of QuotaHolderSerial objects
147 bfe7ba3c Christos Stavrakakis

148 bfe7ba3c Christos Stavrakakis
    """
149 11a54cb9 Christos Stavrakakis
    if update_db:
150 11a54cb9 Christos Stavrakakis
        for s in serials:
151 11a54cb9 Christos Stavrakakis
            if s.pending:
152 11a54cb9 Christos Stavrakakis
                s.accepted = True
153 11a54cb9 Christos Stavrakakis
                s.save()
154 bfe7ba3c Christos Stavrakakis
155 bfe7ba3c Christos Stavrakakis
    with get_quota_holder() as qh:
156 bfe7ba3c Christos Stavrakakis
        qh.accept_commission(context={},
157 bfe7ba3c Christos Stavrakakis
                             clientkey='cyclades',
158 bfe7ba3c Christos Stavrakakis
                             serials=[s.serial for s in serials])
159 bfe7ba3c Christos Stavrakakis
160 bfe7ba3c Christos Stavrakakis
161 11a54cb9 Christos Stavrakakis
def reject_commission(serials, update_db=True):
162 bfe7ba3c Christos Stavrakakis
    """Reject a list of pending commissions.
163 bfe7ba3c Christos Stavrakakis

164 bfe7ba3c Christos Stavrakakis
    @param serials: List of QuotaHolderSerial objects
165 bfe7ba3c Christos Stavrakakis

166 bfe7ba3c Christos Stavrakakis
    """
167 11a54cb9 Christos Stavrakakis
    if update_db:
168 11a54cb9 Christos Stavrakakis
        for s in serials:
169 11a54cb9 Christos Stavrakakis
            if s.pending:
170 11a54cb9 Christos Stavrakakis
                s.rejected = True
171 11a54cb9 Christos Stavrakakis
                s.save()
172 bfe7ba3c Christos Stavrakakis
173 bfe7ba3c Christos Stavrakakis
    with get_quota_holder() as qh:
174 bfe7ba3c Christos Stavrakakis
        qh.reject_commission(context={},
175 bfe7ba3c Christos Stavrakakis
                             clientkey='cyclades',
176 bfe7ba3c Christos Stavrakakis
                             serials=[s.serial for s in serials])
177 bfe7ba3c Christos Stavrakakis
178 bfe7ba3c Christos Stavrakakis
179 bfe7ba3c Christos Stavrakakis
def issue_commission(**commission_info):
180 bfe7ba3c Christos Stavrakakis
    """Issue a new commission to the quotaholder.
181 bfe7ba3c Christos Stavrakakis

182 bfe7ba3c Christos Stavrakakis
    Issue a new commission to the quotaholder, and create the
183 bfe7ba3c Christos Stavrakakis
    corresponing QuotaHolderSerial object in DB.
184 bfe7ba3c Christos Stavrakakis

185 bfe7ba3c Christos Stavrakakis
    """
186 bfe7ba3c Christos Stavrakakis
187 bfe7ba3c Christos Stavrakakis
    with get_quota_holder() as qh:
188 bfe7ba3c Christos Stavrakakis
        try:
189 bfe7ba3c Christos Stavrakakis
            serial = qh.issue_commission(**commission_info)
190 bfe7ba3c Christos Stavrakakis
        except (NoCapacityError, NoQuantityError):
191 bfe7ba3c Christos Stavrakakis
            raise OverLimit("Limit exceeded for your account")
192 e8f2d02d Christos Stavrakakis
        except CallError as e:
193 e8f2d02d Christos Stavrakakis
            if e.call_error in ["NoCapacityError", "NoQuantityError"]:
194 e8f2d02d Christos Stavrakakis
                raise OverLimit("Limit exceeded for your account")
195 6dbd90c0 Christos Stavrakakis
            raise
196 bfe7ba3c Christos Stavrakakis
197 b14f55b5 Christos Stavrakakis
    if serial:
198 b14f55b5 Christos Stavrakakis
        return QuotaHolderSerial.objects.create(serial=serial)
199 718a601d root
    elif not CYCLADES_USE_QUOTAHOLDER:
200 b14f55b5 Christos Stavrakakis
        return DummySerial()
201 b14f55b5 Christos Stavrakakis
    else:
202 b14f55b5 Christos Stavrakakis
        raise Exception("No serial")
203 bfe7ba3c Christos Stavrakakis
204 bfe7ba3c Christos Stavrakakis
205 bfe7ba3c Christos Stavrakakis
# Wrapper functions for issuing commissions for each resource type.  Each
206 bfe7ba3c Christos Stavrakakis
# functions creates the `commission_info` dictionary as expected by the
207 bfe7ba3c Christos Stavrakakis
# `issue_commision` function. Commissions for deleting a resource, are the same
208 bfe7ba3c Christos Stavrakakis
# as for creating the same resource, but with negative resource sizes.
209 bfe7ba3c Christos Stavrakakis
210 bfe7ba3c Christos Stavrakakis
211 bfe7ba3c Christos Stavrakakis
def issue_vm_commission(user, flavor, delete=False):
212 bfe7ba3c Christos Stavrakakis
    resources = get_server_resources(flavor)
213 bfe7ba3c Christos Stavrakakis
    commission_info = create_commission(user, resources, delete)
214 bfe7ba3c Christos Stavrakakis
215 bfe7ba3c Christos Stavrakakis
    return issue_commission(**commission_info)
216 bfe7ba3c Christos Stavrakakis
217 bfe7ba3c Christos Stavrakakis
218 bfe7ba3c Christos Stavrakakis
def get_server_resources(flavor):
219 bfe7ba3c Christos Stavrakakis
    return {'vm': 1,
220 bfe7ba3c Christos Stavrakakis
            'cpu': flavor.cpu,
221 457a8ada Christos Stavrakakis
            'disk': 1073741824 * flavor.disk,  # flavor.disk is in GB
222 bfe7ba3c Christos Stavrakakis
            # 'public_ip': 1,
223 bfe7ba3c Christos Stavrakakis
            #'disk_template': flavor.disk_template,
224 5805fbb1 Christos Stavrakakis
            'ram': 1048576 * flavor.ram}  # flavor.ram is in MB
225 bfe7ba3c Christos Stavrakakis
226 bfe7ba3c Christos Stavrakakis
227 bfe7ba3c Christos Stavrakakis
def issue_network_commission(user, delete=False):
228 bfe7ba3c Christos Stavrakakis
    resources = get_network_resources()
229 bfe7ba3c Christos Stavrakakis
    commission_info = create_commission(user, resources, delete)
230 bfe7ba3c Christos Stavrakakis
231 bfe7ba3c Christos Stavrakakis
    return issue_commission(**commission_info)
232 bfe7ba3c Christos Stavrakakis
233 bfe7ba3c Christos Stavrakakis
234 bfe7ba3c Christos Stavrakakis
def get_network_resources():
235 bfe7ba3c Christos Stavrakakis
    return {"network.private": 1}
236 bfe7ba3c Christos Stavrakakis
237 bfe7ba3c Christos Stavrakakis
238 bfe7ba3c Christos Stavrakakis
def invert_resources(resources_dict):
239 bfe7ba3c Christos Stavrakakis
    return dict((r, -s) for r, s in resources_dict.items())
240 bfe7ba3c Christos Stavrakakis
241 bfe7ba3c Christos Stavrakakis
242 bfe7ba3c Christos Stavrakakis
def create_commission(user, resources, delete=False):
243 bfe7ba3c Christos Stavrakakis
    if delete:
244 bfe7ba3c Christos Stavrakakis
        resources = invert_resources(resources)
245 4ac68aaf Christos Stavrakakis
    provisions = [('cyclades', 'cyclades.' + r, s)
246 bfe7ba3c Christos Stavrakakis
                  for r, s in resources.items()]
247 bfe7ba3c Christos Stavrakakis
    return  {"context":    {},
248 bfe7ba3c Christos Stavrakakis
             "target":     user,
249 4ac68aaf Christos Stavrakakis
             "key":        "1",
250 bfe7ba3c Christos Stavrakakis
             "clientkey":  "cyclades",
251 7ced3e6b Christos Stavrakakis
             #"owner":      "",
252 7ced3e6b Christos Stavrakakis
             #"ownerkey":   "1",
253 bfe7ba3c Christos Stavrakakis
             "name":       "",
254 bfe7ba3c Christos Stavrakakis
             "provisions": provisions}
255 11a54cb9 Christos Stavrakakis
256 11a54cb9 Christos Stavrakakis
##
257 11a54cb9 Christos Stavrakakis
## Reconcile pending commissions
258 11a54cb9 Christos Stavrakakis
##
259 11a54cb9 Christos Stavrakakis
260 11a54cb9 Christos Stavrakakis
261 11a54cb9 Christos Stavrakakis
def accept_commissions(accepted):
262 11a54cb9 Christos Stavrakakis
    with get_quota_holder() as qh:
263 11a54cb9 Christos Stavrakakis
        qh.accept_commission(context={},
264 11a54cb9 Christos Stavrakakis
                             clientkey='cyclades',
265 11a54cb9 Christos Stavrakakis
                             serials=accepted)
266 11a54cb9 Christos Stavrakakis
267 11a54cb9 Christos Stavrakakis
268 11a54cb9 Christos Stavrakakis
def reject_commissions(rejected):
269 11a54cb9 Christos Stavrakakis
    with get_quota_holder() as qh:
270 11a54cb9 Christos Stavrakakis
            qh.reject_commission(context={},
271 11a54cb9 Christos Stavrakakis
                                 clientkey='cyclades',
272 11a54cb9 Christos Stavrakakis
                                 serials=rejected)
273 11a54cb9 Christos Stavrakakis
274 11a54cb9 Christos Stavrakakis
275 11a54cb9 Christos Stavrakakis
def fix_pending_commissions():
276 11a54cb9 Christos Stavrakakis
    (accepted, rejected) = resolve_pending_commissions()
277 11a54cb9 Christos Stavrakakis
278 11a54cb9 Christos Stavrakakis
    with get_quota_holder() as qh:
279 11a54cb9 Christos Stavrakakis
        if accepted:
280 11a54cb9 Christos Stavrakakis
            qh.accept_commission(context={},
281 11a54cb9 Christos Stavrakakis
                                 clientkey='cyclades',
282 11a54cb9 Christos Stavrakakis
                                 serials=accepted)
283 11a54cb9 Christos Stavrakakis
        if rejected:
284 11a54cb9 Christos Stavrakakis
            qh.reject_commission(context={},
285 11a54cb9 Christos Stavrakakis
                                 clientkey='cyclades',
286 11a54cb9 Christos Stavrakakis
                                 serials=rejected)
287 11a54cb9 Christos Stavrakakis
288 11a54cb9 Christos Stavrakakis
289 11a54cb9 Christos Stavrakakis
def resolve_pending_commissions():
290 11a54cb9 Christos Stavrakakis
    """Resolve quotaholder pending commissions.
291 11a54cb9 Christos Stavrakakis

292 11a54cb9 Christos Stavrakakis
    Get pending commissions from the quotaholder and resolve them
293 11a54cb9 Christos Stavrakakis
    to accepted and rejected, according to the state of the
294 11a54cb9 Christos Stavrakakis
    QuotaHolderSerial DB table. A pending commission in the quotaholder
295 11a54cb9 Christos Stavrakakis
    can exist in the QuotaHolderSerial table and be either accepted or
296 11a54cb9 Christos Stavrakakis
    rejected, or can not exist in this table, so it is rejected.
297 11a54cb9 Christos Stavrakakis

298 11a54cb9 Christos Stavrakakis
    """
299 11a54cb9 Christos Stavrakakis
300 11a54cb9 Christos Stavrakakis
    qh_pending = get_quotaholder_pending()
301 11a54cb9 Christos Stavrakakis
    if not qh_pending:
302 11a54cb9 Christos Stavrakakis
        return ([], [])
303 11a54cb9 Christos Stavrakakis
304 11a54cb9 Christos Stavrakakis
    qh_pending.sort()
305 11a54cb9 Christos Stavrakakis
    min_ = qh_pending[0]
306 11a54cb9 Christos Stavrakakis
307 11a54cb9 Christos Stavrakakis
    serials = QuotaHolderSerial.objects.filter(serial__gte=min_, pending=False)
308 11a54cb9 Christos Stavrakakis
    accepted = serials.filter(accepted=True).values_list('serial', flat=True)
309 11a54cb9 Christos Stavrakakis
    accepted = filter(lambda x: x in qh_pending, accepted)
310 11a54cb9 Christos Stavrakakis
311 11a54cb9 Christos Stavrakakis
    rejected = list(set(qh_pending) - set(accepted))
312 11a54cb9 Christos Stavrakakis
313 11a54cb9 Christos Stavrakakis
    return (accepted, rejected)
314 11a54cb9 Christos Stavrakakis
315 11a54cb9 Christos Stavrakakis
316 11a54cb9 Christos Stavrakakis
def get_quotaholder_pending():
317 11a54cb9 Christos Stavrakakis
    with get_quota_holder() as qh:
318 11a54cb9 Christos Stavrakakis
        pending_serials = qh.get_pending_commissions(context={},
319 11a54cb9 Christos Stavrakakis
                                                     clientkey='cyclades')
320 11a54cb9 Christos Stavrakakis
    return pending_serials