Revision fd65ab41 snf-cyclades-app/synnefo/db/models.py
b/snf-cyclades-app/synnefo/db/models.py | ||
---|---|---|
184 | 184 |
"with backend: %s" % self) |
185 | 185 |
else: |
186 | 186 |
# ON_DELETE = SET NULL |
187 |
self.virtual_machines.all().backend=None
|
|
187 |
self.virtual_machines.all().backend = None
|
|
188 | 188 |
super(Backend, self).delete(*args, **kwargs) |
189 | 189 |
|
190 | 190 |
|
191 |
# A backend job may be in one of the following possible states |
|
192 |
BACKEND_STATUSES = ( |
|
193 |
('queued', 'request queued'), |
|
194 |
('waiting', 'request waiting for locks'), |
|
195 |
('canceling', 'request being canceled'), |
|
196 |
('running', 'request running'), |
|
197 |
('canceled', 'request canceled'), |
|
198 |
('success', 'request completed successfully'), |
|
199 |
('error', 'request returned error') |
|
200 |
) |
|
201 |
|
|
202 |
|
|
191 | 203 |
class VirtualMachine(models.Model): |
192 | 204 |
# The list of possible actions for a VM |
193 | 205 |
ACTIONS = ( |
... | ... | |
230 | 242 |
('OP_INSTANCE_FAILOVER', 'Failover Instance') |
231 | 243 |
) |
232 | 244 |
|
233 |
# A backend job may be in one of the following possible states |
|
234 |
BACKEND_STATUSES = ( |
|
235 |
('queued', 'request queued'), |
|
236 |
('waiting', 'request waiting for locks'), |
|
237 |
('canceling', 'request being canceled'), |
|
238 |
('running', 'request running'), |
|
239 |
('canceled', 'request canceled'), |
|
240 |
('success', 'request completed successfully'), |
|
241 |
('error', 'request returned error') |
|
242 |
) |
|
243 | 245 |
|
244 | 246 |
# The operating state of a VM, |
245 | 247 |
# upon the successful completion of a backend operation. |
... | ... | |
406 | 408 |
('DESTROY', 'Destroy Network'), |
407 | 409 |
) |
408 | 410 |
|
409 |
# The list of possible operations on the backend |
|
410 |
BACKEND_OPCODES = ( |
|
411 |
('OP_NETWORK_ADD', 'Create Network'), |
|
412 |
('OP_NETWORK_CONNECT', 'Activate Network'), |
|
413 |
('OP_NETWORK_DISCONNECT', 'Deactivate Network'), |
|
414 |
('OP_NETWORK_REMOVE', 'Remove Network') |
|
415 |
) |
|
416 |
|
|
417 |
# A backend job may be in one of the following possible states |
|
418 |
BACKEND_STATUSES = ( |
|
419 |
('success', 'request completed successfully'), |
|
420 |
('error', 'request returned error') |
|
421 |
) |
|
422 |
|
|
423 |
# The operating state of a Network, |
|
424 |
# upon the successful completion of a backend operation. |
|
425 |
# IMPORTANT: Make sure all keys have a corresponding |
|
426 |
# entry in BACKEND_OPCODES if you update this field, see #1035, #1111. |
|
427 |
OPER_STATE_FROM_OPCODE = { |
|
428 |
'OP_NETWORK_ADD': 'PENDING', |
|
429 |
'OP_NETWORK_CONNECT': 'ACTIVE', |
|
430 |
'OP_NETWORK_DISCONNECT': 'PENDING', |
|
431 |
'OP_NETWORK_REMOVE': 'DELETED' |
|
432 |
} |
|
433 |
|
|
434 | 411 |
RSAPI_STATE_FROM_OPER_STATE = { |
435 | 412 |
'PENDING': 'PENDING', |
436 | 413 |
'ACTIVE': 'ACTIVE', |
... | ... | |
445 | 422 |
) |
446 | 423 |
|
447 | 424 |
NETWORK_TAGS = { |
448 |
'PUBLIC_ROUTED': ['public-routed'],
|
|
449 |
'PRIVATE_VLAN': ['private-vlan'],
|
|
450 |
'PRIVATE_FILTERED': ['private-filtered']
|
|
425 |
'PUBLIC_ROUTED': ['ip-less-routed'],
|
|
426 |
'PRIVATE_VLAN': ['physical-vlan'],
|
|
427 |
'PRIVATE_FILTERED': ['mac-filtered']
|
|
451 | 428 |
} |
452 | 429 |
|
453 | 430 |
name = models.CharField('Network Name', max_length=128) |
... | ... | |
457 | 434 |
dhcp = models.BooleanField('DHCP', default=True) |
458 | 435 |
type = models.CharField(choices=NETWORK_TYPES, max_length=50, default='PRIVATE_VLAN') |
459 | 436 |
link = models.CharField('Network Link', max_length=128, null=True) |
460 |
mac_prefix = models.CharField('MAC Prefix', max_length=128, null=True)
|
|
437 |
mac_prefix = models.CharField('MAC Prefix', max_length=32, null=True)
|
|
461 | 438 |
public = models.BooleanField(default=False) |
462 | 439 |
created = models.DateTimeField(auto_now_add=True) |
463 | 440 |
updated = models.DateTimeField(auto_now=True) |
464 | 441 |
deleted = models.BooleanField('Deleted', default=False) |
465 |
state = models.CharField(choices=OPER_STATES, max_length=30, default='PENDING') |
|
442 |
state = models.CharField(choices=OPER_STATES, max_length=32, |
|
443 |
default='PENDING') |
|
466 | 444 |
machines = models.ManyToManyField(VirtualMachine, |
467 | 445 |
through='NetworkInterface') |
468 |
|
|
469 |
action = models.CharField(choices=ACTIONS, max_length=30, null=True) |
|
470 |
backendjobid = models.PositiveIntegerField(null=True) |
|
471 |
backendopcode = models.CharField(choices=BACKEND_OPCODES, max_length=30, |
|
472 |
null=True) |
|
473 |
backendjobstatus = models.CharField(choices=BACKEND_STATUSES, |
|
474 |
max_length=30, null=True) |
|
475 |
backendlogmsg = models.TextField(null=True) |
|
476 |
backendtime = models.DateTimeField(default=datetime.datetime.min) |
|
477 |
|
|
446 |
action = models.CharField(choices=ACTIONS, max_length=32, null=True, |
|
447 |
default=None) |
|
478 | 448 |
|
479 | 449 |
class InvalidBackendIdError(Exception): |
480 |
def __init__(self, value):
|
|
450 |
def __init__(self, value): |
|
481 | 451 |
self.value = value |
482 |
def __str__(self): |
|
452 |
|
|
453 |
def __str__(self): |
|
483 | 454 |
return repr(self.value) |
484 | 455 |
|
485 | 456 |
|
486 | 457 |
class InvalidBackendMsgError(Exception): |
487 |
def __init__(self, opcode, status):
|
|
458 |
def __init__(self, opcode, status): |
|
488 | 459 |
self.opcode = opcode |
489 | 460 |
self.status = status |
490 |
def __str__(self): |
|
461 |
|
|
462 |
def __str__(self): |
|
491 | 463 |
return repr('<opcode: %s, status: %s>' % (self.opcode, |
492 | 464 |
self.status)) |
493 | 465 |
|
494 | 466 |
class InvalidActionError(Exception): |
495 |
def __init__(self, action):
|
|
467 |
def __init__(self, action): |
|
496 | 468 |
self._action = action |
497 |
def __str__(self): |
|
498 |
return repr(str(self._action)) |
|
499 | 469 |
|
500 |
def __init__(self, *args, **kw): |
|
501 |
"""Initialize state for just created Network instances.""" |
|
502 |
super(Network, self).__init__(*args, **kw) |
|
503 |
# This gets called BEFORE an instance gets save()d for |
|
504 |
# the first time. |
|
505 |
if not self.pk: |
|
506 |
self.action = None |
|
507 |
self.backendjobid = None |
|
508 |
self.backendjobstatus = None |
|
509 |
self.backendopcode = None |
|
510 |
self.backendlogmsg = None |
|
511 |
self.backendtime = datetime.datetime.min |
|
470 |
def __str__(self): |
|
471 |
return repr(str(self._action)) |
|
512 | 472 |
|
513 | 473 |
@property |
514 | 474 |
def backend_id(self): |
515 |
"""Returns the backend id for this Network by prepending backend-prefix."""
|
|
475 |
"""Return the backend id by prepending backend-prefix."""
|
|
516 | 476 |
if not self.id: |
517 | 477 |
raise Network.InvalidBackendIdError("self.id is None") |
518 | 478 |
return '%s%s' % (settings.BACKEND_PREFIX_ID, self.id) |
... | ... | |
527 | 487 |
def __unicode__(self): |
528 | 488 |
return self.name |
529 | 489 |
|
490 |
def update_oper_state(self): |
|
491 |
"""Update operstate of the Network. |
|
492 |
|
|
493 |
Update the operstate of the Network depending on the related |
|
494 |
backend_networks. When backend networks do not have the same operstate, |
|
495 |
the Network's operstate is PENDING. Otherwise it is the same with |
|
496 |
the BackendNetworks operstate. |
|
497 |
|
|
498 |
""" |
|
499 |
backend_states = [s.operstate for s in self.backend_networks.all()] |
|
500 |
if not backend_states: |
|
501 |
self.operstate = 'PENDING' |
|
502 |
self.save() |
|
503 |
return |
|
504 |
|
|
505 |
all_equal = len(set(backend_states)) <= 1 |
|
506 |
self.operstate = all_equal and backend_states[0] or 'PENDING' |
|
507 |
|
|
508 |
if self.operstate == 'DELETED': |
|
509 |
self.deleted = True |
|
510 |
|
|
511 |
self.save() |
|
512 |
|
|
513 |
def save(self, *args, **kwargs): |
|
514 |
pk = self.pk |
|
515 |
super(Network, self).save(*args, **kwargs) |
|
516 |
if not pk: |
|
517 |
# In case of a new Network, corresponding BackendNetwork's must |
|
518 |
# be created! |
|
519 |
for back in Backend.objects.all(): |
|
520 |
BackendNetwork.objects.create(backend=back, network=self) |
|
521 |
|
|
522 |
|
|
523 |
class BackendNetwork(models.Model): |
|
524 |
OPER_STATES = ( |
|
525 |
('PENDING', 'Pending'), |
|
526 |
('ACTIVE', 'Active'), |
|
527 |
('DELETED', 'Deleted'), |
|
528 |
('ERROR', 'Error') |
|
529 |
) |
|
530 |
|
|
531 |
# The list of possible operations on the backend |
|
532 |
BACKEND_OPCODES = ( |
|
533 |
('OP_NETWORK_ADD', 'Create Network'), |
|
534 |
('OP_NETWORK_CONNECT', 'Activate Network'), |
|
535 |
('OP_NETWORK_DISCONNECT', 'Deactivate Network'), |
|
536 |
('OP_NETWORK_REMOVE', 'Remove Network'), |
|
537 |
# These are listed here for completeness, |
|
538 |
# and are ignored for the time being |
|
539 |
('OP_NETWORK_SET_PARAMS', 'Set Network Parameters'), |
|
540 |
('OP_NETWORK_QUERY_DATA', 'Query Network Data') |
|
541 |
) |
|
542 |
|
|
543 |
# The operating state of a Netowork, |
|
544 |
# upon the successful completion of a backend operation. |
|
545 |
# IMPORTANT: Make sure all keys have a corresponding |
|
546 |
# entry in BACKEND_OPCODES if you update this field, see #1035, #1111. |
|
547 |
OPER_STATE_FROM_OPCODE = { |
|
548 |
'OP_NETWORK_ADD': 'PENDING', |
|
549 |
'OP_NETWORK_CONNECT': 'ACTIVE', |
|
550 |
'OP_NETWORK_DISCONNECT': 'PENDING', |
|
551 |
'OP_NETWORK_REMOVE': 'DELETED', |
|
552 |
'OP_NETWORK_SET_PARAMS': None, |
|
553 |
'OP_NETWORK_QUERY_DATA': None |
|
554 |
} |
|
555 |
|
|
556 |
network = models.ForeignKey(Network, related_name='backend_networks') |
|
557 |
backend = models.ForeignKey(Backend, related_name='networks') |
|
558 |
created = models.DateTimeField(auto_now_add=True) |
|
559 |
updated = models.DateTimeField(auto_now=True) |
|
560 |
deleted = models.BooleanField('Deleted', default=False) |
|
561 |
operstate = models.CharField(choices=OPER_STATES, max_length=30, |
|
562 |
default='PENDING') |
|
563 |
backendjobid = models.PositiveIntegerField(null=True) |
|
564 |
backendopcode = models.CharField(choices=BACKEND_OPCODES, max_length=30, |
|
565 |
null=True) |
|
566 |
backendjobstatus = models.CharField(choices=BACKEND_STATUSES, |
|
567 |
max_length=30, null=True) |
|
568 |
backendlogmsg = models.TextField(null=True) |
|
569 |
backendtime = models.DateTimeField(null=False, |
|
570 |
default=datetime.datetime.min) |
|
571 |
|
|
572 |
def save(self, *args, **kwargs): |
|
573 |
super(BackendNetwork, self).save(*args, **kwargs) |
|
574 |
self.network.update_oper_state() |
|
575 |
|
|
576 |
def delete(self, *args, **kwargs): |
|
577 |
super(BackendNetwork, self).delete(*args, **kwargs) |
|
578 |
self.network.update_oper_state() |
|
579 |
|
|
530 | 580 |
|
531 | 581 |
class NetworkInterface(models.Model): |
532 | 582 |
FIREWALL_PROFILES = ( |
Also available in: Unified diff