1524 |
1524 |
|
1525 |
1525 |
def _q_terminated(self):
|
1526 |
1526 |
return Q(state=Project.TERMINATED)
|
|
1527 |
def _q_suspended(self):
|
|
1528 |
return Q(state=Project.SUSPENDED)
|
|
1529 |
def _q_deactivated(self):
|
|
1530 |
return self._q_terminated() | self._q_suspended()
|
1527 |
1531 |
|
1528 |
1532 |
def terminated_projects(self):
|
1529 |
1533 |
q = self._q_terminated()
|
... | ... | |
1537 |
1541 |
q = self._q_terminated() & Q(is_active=True)
|
1538 |
1542 |
return self.filter(q)
|
1539 |
1543 |
|
|
1544 |
def deactivated_projects(self):
|
|
1545 |
q = self._q_deactivated()
|
|
1546 |
return self.filter(q)
|
|
1547 |
|
|
1548 |
def deactivating_projects(self):
|
|
1549 |
q = self._q_deactivated() & Q(is_active=True)
|
|
1550 |
return self.filter(q)
|
|
1551 |
|
1540 |
1552 |
def modified_projects(self):
|
1541 |
1553 |
return self.filter(is_modified=True)
|
1542 |
1554 |
|
|
1555 |
def reactivating_projects(self):
|
|
1556 |
return self.filter(state=Project.APPROVED, is_active=False)
|
1543 |
1557 |
|
1544 |
1558 |
class Project(models.Model):
|
1545 |
1559 |
|
... | ... | |
1603 |
1617 |
self.deactivation_date = datetime.now()
|
1604 |
1618 |
self.is_active = False
|
1605 |
1619 |
|
|
1620 |
def reactivate(self):
|
|
1621 |
self.deactivation_date = None
|
|
1622 |
self.is_active = True
|
|
1623 |
|
1606 |
1624 |
def terminate(self):
|
1607 |
1625 |
self.deactivation_reason = 'TERMINATED'
|
1608 |
1626 |
self.state = self.TERMINATED
|
1609 |
1627 |
self.save()
|
1610 |
1628 |
|
|
1629 |
def suspend(self):
|
|
1630 |
self.deactivation_reason = 'SUSPENDED'
|
|
1631 |
self.state = self.SUSPENDED
|
|
1632 |
self.save()
|
|
1633 |
|
|
1634 |
def resume(self):
|
|
1635 |
self.deactivation_reason = None
|
|
1636 |
self.state = self.APPROVED
|
|
1637 |
self.save()
|
1611 |
1638 |
|
1612 |
1639 |
### Logical checks
|
1613 |
1640 |
|
... | ... | |
1621 |
1648 |
def is_active_strict(self):
|
1622 |
1649 |
return self.is_active and self.state == self.APPROVED
|
1623 |
1650 |
|
|
1651 |
def is_approved(self):
|
|
1652 |
return self.state == self.APPROVED
|
|
1653 |
|
1624 |
1654 |
@property
|
1625 |
1655 |
def is_alive(self):
|
1626 |
1656 |
return self.is_active_strict()
|
... | ... | |
1631 |
1661 |
|
1632 |
1662 |
@property
|
1633 |
1663 |
def is_suspended(self):
|
1634 |
|
return False
|
|
1664 |
return self.is_deactivated(self.SUSPENDED)
|
1635 |
1665 |
|
1636 |
1666 |
def violates_resource_grants(self):
|
1637 |
1667 |
return False
|
... | ... | |
1687 |
1717 |
pass
|
1688 |
1718 |
|
1689 |
1719 |
|
|
1720 |
class ProjectMembershipManager(ForUpdateManager):
|
|
1721 |
pass
|
|
1722 |
|
1690 |
1723 |
class ProjectMembership(models.Model):
|
1691 |
1724 |
|
1692 |
1725 |
person = models.ForeignKey(AstakosUser)
|
1693 |
1726 |
request_date = models.DateField(auto_now_add=True)
|
1694 |
1727 |
project = models.ForeignKey(Project)
|
1695 |
1728 |
|
1696 |
|
REQUESTED = 0
|
1697 |
|
ACCEPTED = 1
|
1698 |
|
SUSPENDED = 10
|
1699 |
|
TERMINATED = 100
|
1700 |
|
REMOVED = 200
|
|
1729 |
REQUESTED = 0
|
|
1730 |
ACCEPTED = 1
|
|
1731 |
# User deactivation
|
|
1732 |
USER_SUSPENDED = 10
|
|
1733 |
# Project deactivation
|
|
1734 |
PROJECT_DEACTIVATED = 100
|
1701 |
1735 |
|
1702 |
|
ASSOCIATED_STATES = set([REQUESTED, ACCEPTED, SUSPENDED, TERMINATED])
|
1703 |
|
ACCEPTED_STATES = set([ACCEPTED, SUSPENDED, TERMINATED])
|
|
1736 |
REMOVED = 200
|
|
1737 |
|
|
1738 |
ASSOCIATED_STATES = set([REQUESTED,
|
|
1739 |
ACCEPTED,
|
|
1740 |
USER_SUSPENDED,
|
|
1741 |
PROJECT_DEACTIVATED])
|
|
1742 |
|
|
1743 |
ACCEPTED_STATES = set([ACCEPTED,
|
|
1744 |
USER_SUSPENDED,
|
|
1745 |
PROJECT_DEACTIVATED])
|
1704 |
1746 |
|
1705 |
1747 |
state = models.IntegerField(default=REQUESTED,
|
1706 |
1748 |
db_index=True)
|
... | ... | |
1719 |
1761 |
acceptance_date = models.DateField(null=True, db_index=True)
|
1720 |
1762 |
leave_request_date = models.DateField(null=True)
|
1721 |
1763 |
|
1722 |
|
objects = ForUpdateManager()
|
|
1764 |
objects = ProjectMembershipManager()
|
1723 |
1765 |
|
1724 |
1766 |
|
1725 |
1767 |
def get_combined_state(self):
|
... | ... | |
1770 |
1812 |
now = datetime.now()
|
1771 |
1813 |
self.acceptance_date = now
|
1772 |
1814 |
self._set_history_item(reason='ACCEPT', date=now)
|
1773 |
|
if self.project.is_active_strict():
|
|
1815 |
if self.project.is_approved():
|
1774 |
1816 |
self.state = self.ACCEPTED
|
1775 |
1817 |
self.is_pending = True
|
1776 |
1818 |
else:
|
1777 |
|
self.state = self.TERMINATED
|
|
1819 |
self.state = self.PROJECT_DEACTIVATED
|
1778 |
1820 |
|
1779 |
1821 |
self.save()
|
1780 |
1822 |
|
... | ... | |
1784 |
1826 |
raise AssertionError(m)
|
1785 |
1827 |
|
1786 |
1828 |
state = self.state
|
1787 |
|
if state not in [self.ACCEPTED, self.TERMINATED]:
|
|
1829 |
if state not in self.ACCEPTED_STATES:
|
1788 |
1830 |
m = _("%s: attempt to remove in state '%s'") % (self, state)
|
1789 |
1831 |
raise AssertionError(m)
|
1790 |
1832 |
|
... | ... | |
1869 |
1911 |
self.is_pending = False
|
1870 |
1912 |
self.save()
|
1871 |
1913 |
|
1872 |
|
elif state == self.TERMINATED:
|
|
1914 |
elif state == self.PROJECT_DEACTIVATED:
|
1873 |
1915 |
if self.pending_application:
|
1874 |
1916 |
m = _("%s: attempt to sync in state '%s' "
|
1875 |
1917 |
"with a pending application") % (self, state)
|
... | ... | |
1893 |
1935 |
raise AssertionError(m)
|
1894 |
1936 |
|
1895 |
1937 |
state = self.state
|
1896 |
|
if state in [self.ACCEPTED, self.TERMINATED, self.REMOVED]:
|
|
1938 |
if state in [self.ACCEPTED, self.PROJECT_DEACTIVATED, self.REMOVED]:
|
1897 |
1939 |
self.pending_application = None
|
1898 |
1940 |
self.pending_serial = None
|
1899 |
1941 |
self.save()
|
... | ... | |
1933 |
1975 |
|
1934 |
1976 |
def pre_sync():
|
1935 |
1977 |
ACCEPTED = ProjectMembership.ACCEPTED
|
1936 |
|
TERMINATED = ProjectMembership.TERMINATED
|
|
1978 |
PROJECT_DEACTIVATED = ProjectMembership.PROJECT_DEACTIVATED
|
1937 |
1979 |
psfu = Project.objects.select_for_update()
|
1938 |
1980 |
|
1939 |
1981 |
modified = psfu.modified_projects()
|
... | ... | |
1945 |
1987 |
membership.is_pending = True
|
1946 |
1988 |
membership.save()
|
1947 |
1989 |
|
1948 |
|
terminating = psfu.terminating_projects()
|
1949 |
|
for project in terminating:
|
|
1990 |
reactivating = psfu.reactivating_projects()
|
|
1991 |
for project in reactivating:
|
|
1992 |
objects = project.projectmembership_set.select_for_update()
|
|
1993 |
memberships = objects.filter(state=PROJECT_DEACTIVATED)
|
|
1994 |
for membership in memberships:
|
|
1995 |
membership.is_pending = True
|
|
1996 |
membership.state = ACCEPTED
|
|
1997 |
membership.save()
|
|
1998 |
|
|
1999 |
deactivating = psfu.deactivating_projects()
|
|
2000 |
for project in deactivating:
|
1950 |
2001 |
objects = project.projectmembership_set.select_for_update()
|
1951 |
2002 |
|
|
2003 |
# Note: we keep a user-level deactivation (e.g. USER_SUSPENDED) intact
|
1952 |
2004 |
memberships = objects.filter(state=ACCEPTED)
|
1953 |
2005 |
for membership in memberships:
|
1954 |
2006 |
membership.is_pending = True
|
1955 |
|
membership.state = TERMINATED
|
|
2007 |
membership.state = PROJECT_DEACTIVATED
|
1956 |
2008 |
membership.save()
|
1957 |
2009 |
|
1958 |
2010 |
def do_sync():
|
... | ... | |
1998 |
2050 |
|
1999 |
2051 |
def post_sync():
|
2000 |
2052 |
ACCEPTED = ProjectMembership.ACCEPTED
|
|
2053 |
PROJECT_DEACTIVATED = ProjectMembership.PROJECT_DEACTIVATED
|
2001 |
2054 |
psfu = Project.objects.select_for_update()
|
2002 |
2055 |
|
2003 |
2056 |
modified = psfu.modified_projects()
|
... | ... | |
2009 |
2062 |
project.is_modified = False
|
2010 |
2063 |
project.save()
|
2011 |
2064 |
|
2012 |
|
terminating = psfu.terminating_projects()
|
2013 |
|
for project in terminating:
|
|
2065 |
reactivating = psfu.reactivating_projects()
|
|
2066 |
for project in reactivating:
|
|
2067 |
objects = project.projectmembership_set.select_for_update()
|
|
2068 |
memberships = list(objects.filter(Q(state=PROJECT_DEACTIVATED) |
|
|
2069 |
Q(is_pending=True)))
|
|
2070 |
if not memberships:
|
|
2071 |
project.reactivate()
|
|
2072 |
project.save()
|
|
2073 |
|
|
2074 |
deactivating = psfu.deactivating_projects()
|
|
2075 |
for project in deactivating:
|
2014 |
2076 |
objects = project.projectmembership_set.select_for_update()
|
2015 |
2077 |
|
2016 |
2078 |
memberships = list(objects.filter(Q(state=ACCEPTED) |
|