Revision 123be68a snf-astakos-app/astakos/im/models.py
b/snf-astakos-app/astakos/im/models.py | ||
---|---|---|
1392 | 1392 |
unique_together = ("resource", "project_application") |
1393 | 1393 |
|
1394 | 1394 |
|
1395 |
class ProjectManager(ForUpdateManager): |
|
1396 |
|
|
1397 |
def deactivating_projects(self): |
|
1398 |
return self.filter(state__gt=Project.ACTIVE) |
|
1399 |
|
|
1400 |
def _q_terminated(self): |
|
1401 |
return Q(state=Project.TERMINATED) | Q(state=Project.TERMINATING) |
|
1402 |
|
|
1403 |
def terminated_projects(self): |
|
1404 |
q = self._q_terminated() |
|
1405 |
return self.filter(q) |
|
1406 |
|
|
1407 |
def not_terminated_projects(self): |
|
1408 |
q = ~self._q_terminated() |
|
1409 |
return self.filter(q) |
|
1410 |
|
|
1395 | 1411 |
class Project(models.Model): |
1396 | 1412 |
|
1397 | 1413 |
application = models.OneToOneField( |
... | ... | |
1404 | 1420 |
through='ProjectMembership') |
1405 | 1421 |
|
1406 | 1422 |
deactivation_reason = models.CharField(max_length=255, null=True) |
1407 |
deactivation_start_date = models.DateTimeField(null=True) |
|
1408 | 1423 |
deactivation_date = models.DateTimeField(null=True) |
1409 | 1424 |
|
1410 | 1425 |
creation_date = models.DateTimeField() |
... | ... | |
1413 | 1428 |
db_index=True, |
1414 | 1429 |
unique=True) |
1415 | 1430 |
|
1416 |
TERMINATED = 'TERMINATED' |
|
1417 |
SUSPENDED = 'SUSPENDED' |
|
1431 |
ACTIVE = 1 << 8 |
|
1432 |
TERMINATED = 1 |
|
1433 |
SUSPENDED = 2 |
|
1418 | 1434 |
|
1419 |
objects = ForUpdateManager() |
|
1435 |
INACTIVE = 0 |
|
1436 |
TERMINATING = TERMINATED | ACTIVE |
|
1437 |
SUSPENDING = SUSPENDED | ACTIVE |
|
1438 |
|
|
1439 |
state = models.IntegerField(default=ACTIVE, |
|
1440 |
db_index=True) |
|
1441 |
|
|
1442 |
objects = ProjectManager() |
|
1420 | 1443 |
|
1421 | 1444 |
def __str__(self): |
1422 | 1445 |
return _("<project %s '%s'>") % (self.id, self.application.name) |
1423 | 1446 |
|
1424 | 1447 |
__repr__ = __str__ |
1425 | 1448 |
|
1426 |
def is_deactivating(self): |
|
1427 |
return bool(self.deactivation_start_date) |
|
1428 | 1449 |
|
1429 |
def is_deactivated_synced(self): |
|
1430 |
return bool(self.deactivation_date) |
|
1450 |
### Internal state manipulation |
|
1431 | 1451 |
|
1432 |
def is_deactivated(self):
|
|
1433 |
return self.is_deactivated_synced() or self.is_deactivating()
|
|
1452 |
def _active_bit(self):
|
|
1453 |
return self.state & self.ACTIVE
|
|
1434 | 1454 |
|
1435 |
def is_still_approved(self):
|
|
1436 |
return bool(self.last_approval_date)
|
|
1455 |
def is_active_bit(self):
|
|
1456 |
return self._active_bit() == self.ACTIVE
|
|
1437 | 1457 |
|
1438 |
def is_active(self): |
|
1439 |
return not(self.is_deactivated()) |
|
1458 |
def is_active_strict(self): |
|
1459 |
return self.state == self.ACTIVE |
|
1460 |
|
|
1461 |
def is_modulo_active(self, s): |
|
1462 |
return self.state & (~self.ACTIVE) == s |
|
1463 |
|
|
1464 |
def set_modulo_active(self, s): |
|
1465 |
self.state = s | self._active_bit() |
|
1466 |
|
|
1467 |
def set_inactive(self): |
|
1468 |
self.state &= (~self.ACTIVE) |
|
1469 |
|
|
1470 |
def is_deactivating(self, reason=None): |
|
1471 |
return (self.is_active_bit() and |
|
1472 |
(self.is_modulo_active(reason) if reason |
|
1473 |
else not self.is_active_strict())) |
|
1474 |
|
|
1475 |
def is_deactivated_synced(self, reason=None): |
|
1476 |
if reason: |
|
1477 |
return self.state == reason |
|
1478 |
return not self.is_active_bit() |
|
1479 |
|
|
1480 |
def is_deactivated(self, reason=None): |
|
1481 |
return (self.is_deactivated_synced(reason) or |
|
1482 |
self.is_deactivating(reason)) |
|
1483 |
|
|
1484 |
|
|
1485 |
### Deactivation calls |
|
1486 |
|
|
1487 |
def set_deactivation_date(self): |
|
1488 |
self.deactivation_date = datetime.now() |
|
1489 |
|
|
1490 |
def deactivate(self): |
|
1491 |
self.set_deactivation_date() |
|
1492 |
self.set_inactive() |
|
1493 |
|
|
1494 |
def terminate(self): |
|
1495 |
self.deactivation_reason = 'TERMINATED' |
|
1496 |
self.set_modulo_active(self.TERMINATED) |
|
1497 |
self.save() |
|
1498 |
|
|
1499 |
|
|
1500 |
### Logical checks |
|
1440 | 1501 |
|
1441 | 1502 |
def is_inconsistent(self): |
1442 | 1503 |
now = datetime.now() |
1443 | 1504 |
dates = [self.creation_date, |
1444 | 1505 |
self.last_approval_date, |
1445 |
self.deactivation_start_date, |
|
1446 | 1506 |
self.deactivation_date] |
1447 | 1507 |
return any([date > now for date in dates]) |
1448 | 1508 |
|
1449 |
def set_deactivation_start_date(self):
|
|
1450 |
self.deactivation_start_date = datetime.now()
|
|
1509 |
def is_active(self):
|
|
1510 |
return self.is_active_strict()
|
|
1451 | 1511 |
|
1452 |
def set_deactivation_date(self): |
|
1453 |
self.deactivation_start_date = None |
|
1454 |
self.deactivation_date = datetime.now() |
|
1512 |
@property |
|
1513 |
def is_alive(self): |
|
1514 |
return self.is_active() |
|
1515 |
|
|
1516 |
@property |
|
1517 |
def is_terminated(self): |
|
1518 |
return self.is_deactivated(self.TERMINATED) |
|
1519 |
|
|
1520 |
@property |
|
1521 |
def is_suspended(self): |
|
1522 |
return False |
|
1455 | 1523 |
|
1456 | 1524 |
def violates_resource_grants(self): |
1457 | 1525 |
return False |
... | ... | |
1461 | 1529 |
return (len(self.approved_members) + adding > |
1462 | 1530 |
application.limit_on_members_number) |
1463 | 1531 |
|
1464 |
@property |
|
1465 |
def is_alive(self): |
|
1466 |
return self.is_active() |
|
1532 |
|
|
1533 |
### Other |
|
1467 | 1534 |
|
1468 | 1535 |
@property |
1469 | 1536 |
def approved_memberships(self): |
... | ... | |
1510 | 1577 |
m = ProjectMembership.objects.get(person=user, project=self) |
1511 | 1578 |
m.remove() |
1512 | 1579 |
|
1513 |
def terminate(self): |
|
1514 |
self.set_deactivation_start_date() |
|
1515 |
self.deactivation_reason = self.TERMINATED |
|
1516 |
self.save() |
|
1517 |
|
|
1518 |
@property |
|
1519 |
def is_terminated(self): |
|
1520 |
return (self.is_deactivated() and |
|
1521 |
self.deactivation_reason == self.TERMINATED) |
|
1522 |
|
|
1523 |
@property |
|
1524 |
def is_suspended(self): |
|
1525 |
return False |
|
1526 |
|
|
1527 | 1580 |
class ProjectMembership(models.Model): |
1528 | 1581 |
|
1529 | 1582 |
person = models.ForeignKey(AstakosUser) |
... | ... | |
1793 | 1846 |
REMOVING = ProjectMembership.REMOVING |
1794 | 1847 |
|
1795 | 1848 |
psfu = Project.objects.select_for_update() |
1796 |
projects = psfu.filter(deactivation_start_date__isnull=False)
|
|
1849 |
projects = psfu.deactivating_projects()
|
|
1797 | 1850 |
|
1798 | 1851 |
if not projects: |
1799 | 1852 |
return |
... | ... | |
1835 | 1888 |
sync_finish_serials([serial]) |
1836 | 1889 |
|
1837 | 1890 |
# finalize deactivating projects |
1838 |
deactivating_projects = psfu.filter(deactivation_start_date__isnull=False)
|
|
1891 |
deactivating_projects = psfu.deactivating_projects()
|
|
1839 | 1892 |
for project in deactivating_projects: |
1840 | 1893 |
objects = project.projectmembership_set.select_for_update() |
1841 | 1894 |
memberships = list(objects.filter(Q(state=ACCEPTED) | |
Also available in: Unified diff