Revision d2b32360 snf-astakos-app/astakos/im/models.py
b/snf-astakos-app/astakos/im/models.py | ||
---|---|---|
1501 | 1501 |
self.state = APPROVED |
1502 | 1502 |
self.save() |
1503 | 1503 |
|
1504 |
transaction.commit() |
|
1505 |
trigger_sync() |
|
1506 |
|
|
1507 | 1504 |
|
1508 | 1505 |
class ProjectResourceGrant(models.Model): |
1509 | 1506 |
|
... | ... | |
1682 | 1679 |
# logger.error(e.messages) |
1683 | 1680 |
|
1684 | 1681 |
|
1685 |
|
|
1686 |
class ExclusiveOrRaise(object): |
|
1687 |
"""Context Manager to exclusively execute a critical code section. |
|
1688 |
The exclusion must be global. |
|
1689 |
(IPC semaphores will not protect across OS, |
|
1690 |
DB locks will if it's the same DB) |
|
1691 |
""" |
|
1692 |
|
|
1693 |
class Busy(Exception): |
|
1694 |
pass |
|
1695 |
|
|
1696 |
def __init__(self, locked=False): |
|
1697 |
init = 0 if locked else 1 |
|
1698 |
from multiprocessing import Semaphore |
|
1699 |
self._sema = Semaphore(init) |
|
1700 |
|
|
1701 |
def enter(self): |
|
1702 |
acquired = self._sema.acquire(False) |
|
1703 |
if not acquired: |
|
1704 |
raise self.Busy() |
|
1705 |
|
|
1706 |
def leave(self): |
|
1707 |
self._sema.release() |
|
1708 |
|
|
1709 |
def __enter__(self): |
|
1710 |
self.enter() |
|
1711 |
return self |
|
1712 |
|
|
1713 |
def __exit__(self, exc_type, exc_value, exc_traceback): |
|
1714 |
self.leave() |
|
1715 |
|
|
1716 |
|
|
1717 |
exclusive_or_raise = ExclusiveOrRaise(locked=False) |
|
1718 |
|
|
1719 |
|
|
1720 | 1682 |
class ProjectMembership(models.Model): |
1721 | 1683 |
|
1722 | 1684 |
person = models.ForeignKey(AstakosUser) |
... | ... | |
1783 | 1745 |
self._set_history_item(reason='ACCEPT', date=now) |
1784 | 1746 |
self.state = self.PENDING |
1785 | 1747 |
self.save() |
1786 |
trigger_sync() |
|
1787 | 1748 |
|
1788 | 1749 |
def remove(self): |
1789 | 1750 |
if state != self.ACCEPTED: |
... | ... | |
1793 | 1754 |
self._set_history_item(reason='REMOVE') |
1794 | 1755 |
self.state = self.REMOVING |
1795 | 1756 |
self.save() |
1796 |
trigger_sync() |
|
1797 | 1757 |
|
1798 | 1758 |
def reject(self): |
1799 | 1759 |
if state != self.REQUESTED: |
... | ... | |
1805 | 1765 |
self._set_history_item(reason='REJECT') |
1806 | 1766 |
self.delete() |
1807 | 1767 |
|
1808 |
def get_diff_quotas(self, limits_list=None, remove=False): |
|
1809 |
if limits_list is None: |
|
1810 |
limits_list = [] |
|
1768 |
def get_diff_quotas(self, sub_list=None, add_list=None, remove=False): |
|
1769 |
if sub_list is None: |
|
1770 |
sub_list = [] |
|
1771 |
|
|
1772 |
if add_list is None: |
|
1773 |
add_list = [] |
|
1811 | 1774 |
|
1812 |
append = limits_list.append |
|
1775 |
sub_append = sub_list.append |
|
1776 |
add_append = add_list.append |
|
1813 | 1777 |
holder = self.person.username |
1814 |
key = "1" |
|
1815 | 1778 |
|
1816 |
tmp_grants = {} |
|
1817 | 1779 |
synced_application = self.application |
1818 | 1780 |
if synced_application is not None: |
1819 | 1781 |
# first, inverse all current limits, and index them by resource name |
1820 | 1782 |
cur_grants = synced_application.resource_grants.all() |
1821 |
f = -1 |
|
1822 | 1783 |
for grant in cur_grants: |
1823 |
name = grant.resource.name |
|
1824 |
tmp_grants[name] = QuotaLimits( |
|
1825 |
holder = holder, |
|
1826 |
resource = name, |
|
1827 |
capacity = f * grant.member_capacity, |
|
1828 |
import_limit = f * grant.member_import_limit, |
|
1829 |
export_limit = f * grant.member_export_limit) |
|
1784 |
sub_append(QuotaLimits( |
|
1785 |
holder = holder, |
|
1786 |
resource = grant.resource.name, |
|
1787 |
capacity = grant.member_capacity, |
|
1788 |
import_limit = grant.member_import_limit, |
|
1789 |
export_limit = grant.member_export_limit)) |
|
1830 | 1790 |
|
1831 | 1791 |
if not remove: |
1832 | 1792 |
# second, add each new limit to its inverted current |
1833 | 1793 |
new_grants = self.pending_application.projectresourcegrant_set.all() |
1834 | 1794 |
for new_grant in new_grants: |
1835 |
name = new_grant.resource.name |
|
1836 |
cur_grant = tmp_grants.pop(name, None) |
|
1837 |
if cur_grant is None: |
|
1838 |
# if limits on a new resource, set 0 current values |
|
1839 |
capacity = 0 |
|
1840 |
import_limit = 0 |
|
1841 |
export_limit = 0 |
|
1842 |
else: |
|
1843 |
capacity = cur_grant.capacity |
|
1844 |
import_limit = cur_grant.import_limit |
|
1845 |
export_limit = cur_grant.export_limit |
|
1846 |
|
|
1847 |
capacity += new_grant.member_capacity |
|
1848 |
import_limit += new_grant.member_import_limit |
|
1849 |
export_limit += new_grant.member_export_limit |
|
1795 |
add_append(QuotaLimits( |
|
1796 |
holder = holder, |
|
1797 |
resource = new_grant.resource.name, |
|
1798 |
capacity = new_grant.capacity, |
|
1799 |
import_limit = new_grant.import_limit, |
|
1800 |
export_limit = new_grant.export_limit)) |
|
1850 | 1801 |
|
1851 |
append(QuotaLimits(holder = holder, |
|
1852 |
key = key, |
|
1853 |
resource = name, |
|
1854 |
capacity = capacity, |
|
1855 |
import_limit = import_limit, |
|
1856 |
export_limit = export_limit)) |
|
1857 |
|
|
1858 |
# third, append all the inverted current limits for removed resources |
|
1859 |
limits_list.extend(tmp_grants.itervalues()) |
|
1860 |
return limits_list |
|
1802 |
return (sub_list, add_list) |
|
1861 | 1803 |
|
1862 | 1804 |
def set_sync(self): |
1863 | 1805 |
state = self.state |
... | ... | |
1914 | 1856 |
REMOVING = ProjectMembership.REMOVING |
1915 | 1857 |
objects = ProjectMembership.objects.select_for_update() |
1916 | 1858 |
|
1917 |
quotas = []
|
|
1859 |
sub_quota, add_quota = [], []
|
|
1918 | 1860 |
|
1919 | 1861 |
serial = new_serial() |
1920 | 1862 |
|
... | ... | |
1932 | 1874 |
|
1933 | 1875 |
membership.pending_application = membership.project.application |
1934 | 1876 |
membership.pending_serial = serial |
1935 |
membership.get_diff_quotas(quotas)
|
|
1877 |
membership.get_diff_quotas(sub_quota, add_quota)
|
|
1936 | 1878 |
membership.save() |
1937 | 1879 |
|
1938 | 1880 |
removing = objects.filter(state=REMOVING) |
... | ... | |
1948 | 1890 |
raise AssertionError(m) |
1949 | 1891 |
|
1950 | 1892 |
membership.pending_serial = serial |
1951 |
membership.get_diff_quotas(quotas, remove=True)
|
|
1893 |
membership.get_diff_quotas(sub_quota, add_quota, remove=True)
|
|
1952 | 1894 |
membership.save() |
1953 | 1895 |
|
1954 | 1896 |
transaction.commit() |
... | ... | |
1957 | 1899 |
# which has been scheduled to sync with the old project.application |
1958 | 1900 |
# Need to check in ProjectMembership.set_sync() |
1959 | 1901 |
|
1960 |
qh_add_quota(serial, quotas)
|
|
1902 |
qh_add_quota(serial, sub_quota, add_quota)
|
|
1961 | 1903 |
sync_finish_serials() |
1962 | 1904 |
|
1963 | 1905 |
|
... | ... | |
2136 | 2078 |
instance.renew_token() |
2137 | 2079 |
pre_save.connect(renew_token, sender=AstakosUser) |
2138 | 2080 |
pre_save.connect(renew_token, sender=Service) |
2081 |
|
Also available in: Unified diff