Commit c2cad011 by Chif Gergő

vm: Add is_master attribute to interface, add new operation to set master interface

Interfaces can be now "master interface" of a vm. The vm's primary host is the master interface's host. The SetMasterInterface operation sets the specified interface as master. A vm can have only one interface, validated in the Interface save method.
parent 6008ac97
Pipeline #675 passed with stage
in 0 seconds
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-10-29 13:39
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('vm', '0002_interface_model'),
]
operations = [
migrations.AddField(
model_name='interface',
name='is_master',
field=models.BooleanField(default=False),
),
]
......@@ -500,23 +500,34 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
@property
def primary_host(self):
interfaces = self.interface_set.select_related('host')
hosts = [i.host for i in interfaces if i.host]
if not hosts:
return None
hs = [h for h in hosts if h.ipv6]
if hs:
return hs[0]
hs = [h for h in hosts if not h.shared_ip]
if hs:
return hs[0]
return hosts[0]
"""Primary host of the instance.
If the master interface is not specified, the primary host is random.
"""
try:
master = self.interface_set.get(is_master=True)
if master.host:
return master.host
except Interface.DoesNotExist:
interfaces = self.interface_set.select_related('host')
hosts = [i.host for i in interfaces if i.host]
if not hosts:
return None
hs = [h for h in hosts if h.ipv6]
if hs:
return hs[0]
hs = [h for h in hosts if not h.shared_ip]
if hs:
return hs[0]
return hosts[0]
@property
def ipv4(self):
"""Primary IPv4 address of the instance.
"""
# return self.primary_host.ipv4 if self.primary_host else None
if self.primary_host:
return self.primary_host.ipv4
for i in self.interface_set.all():
if i.host:
return i.host.ipv4
......
......@@ -69,6 +69,7 @@ class Interface(Model):
host = ForeignKey(Host, verbose_name=_('host'), blank=True, null=True)
instance = ForeignKey('Instance', verbose_name=_('instance'),
related_name='interface_set')
is_master = BooleanField(default=False)
model = CharField(max_length=10, choices=MODEL_TYPES, default='virtio')
class Meta:
......@@ -163,6 +164,23 @@ class Interface(Model):
iface.save()
return iface
def save(self, *args, **kwargs):
"""Saves the Instance to the database
If the interface is master interface, sets
the another master interface to false.
"""
if self.is_master:
try:
temp = Interface.objects.get(instance=self.instance,
is_master=True)
if self != temp:
temp.is_master = False
temp.save()
except Interface.DoesNotExist:
pass
super(Interface, self).save(*args, **kwargs)
def deploy(self):
queue_name = self.instance.get_remote_queue_name('net', 'fast')
return net_tasks.create.apply_async(args=[self.get_vmnetwork_desc()],
......
......@@ -247,6 +247,29 @@ class AddInterfaceOperation(InstanceOperation):
@register_operation
class SetMasterInterfaceOperation(InstanceOperation):
id = 'set_master_interface'
name = _("set master interface")
description = _("Set the master interface of the VM.")
required_perms = ()
accept_states = ('STOPPED', 'PENDING')
def _operation(self, user, activity, interface):
if interface.host:
interface.is_master = True
interface.save()
else:
raise humanize_exception(ugettext_noop(
"Master interface must have host"),
Host.DoesNotExist())
def get_activity_name(self, kwargs):
return create_readable(ugettext_noop("set %(vlan)s interface"
" as master"),
vlan=kwargs['interface'].vlan)
@register_operation
class CreateDiskOperation(InstanceOperation):
id = 'create_disk'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment