Revision 8764d304

b/snf-cyclades-app/synnefo/db/models.py
555 555
        pool.put(address)
556 556
        pool.save()
557 557

  
558
    @property
559
    def subnet4(self):
560
        return self.get_subnet(version=4)
561

  
562
    @property
563
    def subnet6(self):
564
        return self.get_subnet(version=6)
565

  
566
    def get_subnet(self, version=4):
567
        for subnet in self.subnets.all():
568
            if subnet.ipversion == version:
569
                return subnet.cidr
570

  
558 571
    class InvalidBackendIdError(Exception):
559 572
        def __init__(self, value):
560 573
            self.value = value
......
596 609
    dns_nameservers = fields.SeparatedValuesField('DNS Nameservers', null=True)
597 610

  
598 611
    def __unicode__(self):
599
        return "<Subnet %s, Network: %s>" % (self.id, self.network_id)
612
        msg = u"<Subnet %s, Network: %s, CIDR: %s>"
613
        return msg % (self.id, self.network_id, self.cidr)
600 614

  
601 615
    def get_pool(self, locked=True):
602 616
        if self.ipversion == 6:
......
769 783

  
770 784
    @property
771 785
    def ipv4_address(self):
772
        try:
773
            return self.ips.get(subnet__ipversion=4).address
774
        except IPAddress.DoesNotExist:
775
            return None
786
        return self.get_ip_address(version=4)
787

  
788
    @property
789
    def ipv6_address(self):
790
        return self.get_ip_address(version=6)
791

  
792
    def get_ip_address(self, version=4):
793
        for ip in self.ips.all():
794
            if ip.subnet.ipversion == version:
795
                return ip.address
796
        return None
776 797

  
777 798

  
778 799
class SecurityGroup(models.Model):
b/snf-cyclades-app/synnefo/db/models_factory.py
157 157
                                 models.Network.FLAVORS[a.flavor]['tags'])
158 158
    public = False
159 159
    deleted = False
160
    state = factory.Sequence(round_seq_first(models.Network.OPER_STATES))
160
    state = "ACTIVE"
161 161

  
162 162

  
163 163
class DeletedNetwork(NetworkFactory):
......
191 191
    size = 0
192 192

  
193 193

  
194
class IPv4SubnetFactory(factory.DjangoModelFactory):
194
class SubnetFactory(factory.DjangoModelFactory):
195 195
    FACTORY_FOR = models.Subnet
196

  
197 196
    network = factory.SubFactory(NetworkFactory, state="ACTIVE")
198 197
    name = factory.LazyAttribute(lambda self: random_string(30))
199
    ipversion = 4
200
    cidr = factory.Sequence(lambda n: '192.168.{0}.0/24'.format(n))
201 198
    dhcp = True
202
    gateway = factory.Sequence(lambda n: '192.168.{0}.1'.format(n))
203 199
    dns_nameservers = []
204 200
    host_routes = []
201

  
202

  
203
class IPv4SubnetFactory(SubnetFactory):
204
    ipversion = 4
205
    cidr = factory.Sequence(lambda n: '192.168.{0}.0/24'.format(n))
206
    gateway = factory.Sequence(lambda n: '192.168.{0}.1'.format(n))
205 207
    pool = factory.RelatedFactory(IPPoolTableFactory, 'subnet')
206 208

  
207 209

  
208
class IPv6SubnetFactory(IPv4SubnetFactory):
210
class IPv6SubnetFactory(SubnetFactory):
209 211
    ipversion = 6
210 212
    cidr = "2001:648:2ffc:1112::/64"
211 213
    gateway = None
212 214

  
213 215

  
216
class NetworkWithSubnetFactory(NetworkFactory):
217
    subnet = factory.RelatedFactory(IPv4SubnetFactory, 'network')
218
    subnet6 = factory.RelatedFactory(IPv6SubnetFactory, 'network')
219

  
220

  
214 221
class IPv4AddressFactory(factory.DjangoModelFactory):
215 222
    FACTORY_FOR = models.IPAddress
216 223

  
217
    subnet = factory.SubFactory(IPv4SubnetFactory)
218 224
    network = factory.SubFactory(NetworkFactory)
225
    subnet = factory.SubFactory(IPv4SubnetFactory,
226
                                network=factory.SelfAttribute('..network'))
219 227
    address =\
220 228
        factory.LazyAttributeSequence(lambda self, n: self.subnet.cidr[:-4] +
221 229
                                      '{0}'.format(int(n) + 2))
b/snf-cyclades-app/synnefo/logic/backend.py
35 35
from datetime import datetime, timedelta
36 36

  
37 37
from synnefo.db.models import (Backend, VirtualMachine, Network,
38
                               IPAddress,
39 38
                               BackendNetwork, BACKEND_STATUSES,
40 39
                               pooled_rapi_client, VirtualMachineDiagnostic,
41
                               Flavor)
40
                               Flavor, IPAddress)
42 41
from synnefo.logic import utils
43 42
from synnefo import quotas
44 43
from synnefo.api.util import release_resource
......
60 59
# stale and removed from DB.
61 60
BUILDING_NIC_TIMEOUT = timedelta(seconds=180)
62 61

  
63
NIC_FIELDS = ["state", "mac", "ipv4", "ipv6", "network", "firewall_profile",
64
              "index"]
62
NIC_FIELDS = ["state", "mac", "ipv4_address", "ipv6_address", "network",
63
              "firewall_profile", "index"]
65 64
UNKNOWN_NIC_PREFIX = "unknown-"
66 65

  
67 66

  
......
260 259
                      " valid name." % ganeti_nic
261 260
                log.error(msg)
262 261
                continue
263
            if ganeti_nic["ipv4"]:
264
                network = ganeti_nic["network"]
265
                network.reserve_address(ganeti_nic["ipv4"])
266
            vm.nics.create(id=nic_name, **ganeti_nic)
262
            ipaddress = None
263
            network = ganeti_nic["network"]
264
            ipv4_address = ganeti_nic["ipv4_address"]
265
            if ipv4_address:
266
                network.reserve_address(ipv4_address)
267
                subnet = network.subnets.get(ipversion=4)
268
                ipaddress = IPAddress.objects.create(address=ipv4_address,
269
                                                     network=network,
270
                                                     subnet=subnet,
271
                                                     userid=vm.userid)
272
            # TODO
273
            ganeti_nic.pop("ipv4_address")
274
            ganeti_nic.pop("ip", None)
275
            ganeti_nic.pop("ipv6_address")
276
            nic = vm.nics.create(id=nic_name, **ganeti_nic)
277
            if ipaddress is not None:
278
                ipaddress.nic = nic
279
                ipaddress.save()
267 280
        elif not nics_are_equal(db_nic, ganeti_nic):
268 281
            # Special case where the IPv4 address has changed, because you
269 282
            # need to release the old IPv4 address and reserve the new one
270
            if db_nic.ipv4 != ganeti_nic["ipv4"]:
283
            ipv4_address = ganeti_nic["ipv4_address"]
284
            if db_nic.ipv4_address != ipv4_address:
271 285
                release_nic_address(db_nic)
272
                if ganeti_nic["ipv4"]:
273
                    ganeti_nic["network"].reserve_address(ganeti_nic["ipv4"])
274

  
275
            # Update the NIC in DB with the values from Ganeti NIC
276
            [setattr(db_nic, f, ganeti_nic[f]) for f in NIC_FIELDS]
277
            db_nic.save()
286
                if ipv4_address:
287
                    network = ganeti_nic["network"]
288
                    network.reserve_address(ipv4_address)
289
                    subnet = network.subnets.get(ipversion=4)
290
                    ipaddress, _ =\
291
                        IPAddress.objects.get_or_create(network=network,
292
                                                        subnet=subnet,
293
                                                        userid=vm.userid,
294
                                                        address=ipv4_address)
295
                    ipaddress.nic = nic
296
                    ipaddress.save()
297

  
298
            for f in ["state", "mac", "network", "firewall_profile", "index"]:
299
                # Update the NIC in DB with the values from Ganeti NIC
300
                setattr(db_nic, f, ganeti_nic[f])
301
                db_nic.save()
278 302

  
279 303
            # Dummy update the network, to work with 'changed-since'
280 304
            db_nic.network.save()
......
308 332
        # Get the new nic info
309 333
        mac = gnic.get('mac')
310 334
        ipv4 = gnic.get('ip')
311
        ipv6 = mac2eui64(mac, network.subnet6)\
312
            if network.subnet6 is not None else None
335
        subnet6 = network.subnet6
336
        ipv6 = mac2eui64(mac, subnet6) if subnet6 else None
313 337

  
314 338
        firewall = gnic.get('firewall')
315 339
        firewall_profile = _reverse_tags.get(firewall)
......
320 344
            'index': index,
321 345
            'network': network,
322 346
            'mac': mac,
323
            'ipv4': ipv4,
324
            'ipv6': ipv6,
347
            'ipv4_address': ipv4,
348
            'ipv6_address': ipv6,
325 349
            'firewall_profile': firewall_profile,
326 350
            'state': 'ACTIVE'}
327 351

  
......
338 362

  
339 363
    """
340 364

  
341
    if nic.ipv4:
342
        if nic.ip_type == "FLOATING":
343
            IPAddress.objects.filter(machine=nic.machine_id,
344
                                     network=nic.network_id,
345
                                     ipv4=nic.ipv4).update(machine=None)
365
    for ip in nic.ips.all():
366
        if ip.subnet.ipversion == 4:
367
            if ip.floating_ip:
368
                ip.nic = None
369
                ip.save()
370
            else:
371
                ip.network.release_address(ip.address)
372
                ip.delete()
346 373
        else:
347
            nic.network.release_address(nic.ipv4)
374
            ip.delete()
348 375

  
349 376

  
350 377
@transaction.commit_on_success
......
718 745
    subnet6 = None
719 746
    gateway = None
720 747
    gateway6 = None
721
    for subnet in network.subnets.all():
722
        if subnet.ipversion == 4:
723
            if subnet.dhcp:
748
    for dbsubnet in network.subnets.all():
749
        if dbsubnet.ipversion == 4:
750
            if dbsubnet.dhcp:
724 751
                tags.append('nfdhcpd')
725
                subnet = subnet.cidr
726
                gateway = subnet.gateway
727
        elif subnet.ipversion == 6:
728
                subnet6 = subnet.cidr
729
                gateway6 = subnet.gateway
752
                subnet = dbsubnet.cidr
753
                gateway = dbsubnet.gateway
754
        elif dbsubnet.ipversion == 6:
755
                subnet6 = dbsubnet.cidr
756
                gateway6 = dbsubnet.gateway
730 757

  
731 758
    if network.public:
732 759
        conflicts_check = True
......
823 850

  
824 851
    nic = {'name': nic.backend_uuid,
825 852
           'network': network.backend_id,
826
           'ip': nic.ipv4}
853
           'ip': nic.ipv4_address}
827 854

  
828 855
    log.debug("Adding NIC %s to VM %s", nic, vm)
829 856

  
b/snf-cyclades-app/synnefo/logic/networks.py
39 39
from snf_django.lib.api import faults
40 40
from synnefo.api import util
41 41
from synnefo import quotas
42
from synnefo.db.models import Network, Backend
42
from synnefo.db.models import Network, Backend, Subnet
43 43
from synnefo.db.utils import validate_mac
44 44
from synnefo.db.pools import EmptyPool
45 45
from synnefo.logic import backend as backend_mod
......
108 108
    network = Network.objects.create(
109 109
        name=name,
110 110
        userid=user_id,
111
        subnet=subnet,
112
        subnet6=subnet6,
113
        gateway=gateway,
114
        gateway6=gateway6,
115
        dhcp=dhcp,
116 111
        flavor=flavor,
117 112
        mode=mode,
118 113
        link=link,
......
123 118
        action='CREATE',
124 119
        state='ACTIVE')
125 120

  
121
    if subnet:
122
        Subnet.objects.create(network=network,
123
                              ipversion=4,
124
                              cidr=subnet,
125
                              gateway=gateway,
126
                              dhcp=dhcp)
127
    if subnet6:
128
        Subnet.objects.create(network=network,
129
                              ipversion=6,
130
                              cidr=subnet6,
131
                              gateway=gateway6,
132
                              dhcp=dhcp)
133

  
126 134
    # Issue commission to Quotaholder and accept it since at the end of
127 135
    # this transaction the Network object will be created in the DB.
128 136
    # Note: the following call does a commit!
b/snf-cyclades-app/synnefo/logic/reconciliation.py
341 341

  
342 342

  
343 343
def format_db_nic(nic):
344
    return NIC_MSG % (nic.id, nic.state, nic.ipv4, nic.network_id, nic.mac,
345
                      nic.index, nic.firewall_profile)
344
    return NIC_MSG % (nic.id, nic.state, nic.ipv4_address, nic.network_id,
345
                      nic.mac, nic.index, nic.firewall_profile)
346 346

  
347 347

  
348 348
def format_gnt_nic(nic):
349 349
    nic_name, nic = nic
350
    return NIC_MSG % (nic_name, nic["state"], nic["ipv4"], nic["network"].id,
351
                      nic["mac"], nic["index"], nic["firewall_profile"])
350
    return NIC_MSG % (nic_name, nic["state"], nic["ipv4_address"],
351
                      nic["network"].id, nic["mac"], nic["index"],
352
                      nic["firewall_profile"])
352 353

  
353 354

  
354 355
#
b/snf-cyclades-app/synnefo/logic/servers.py
357 357
        raise faults.BuildInProgress('Network not active yet')
358 358

  
359 359
    address = None
360
    if network.subnet is not None and network.dhcp:
361
        # Get a free IP from the address pool.
362
        address = util.get_network_free_address(network)
360
    try:
361
        subnet = network.subnets.get(ipversion=4, dhcp=True)
362
        address = util.get_network_free_address(subnet, userid=vm.userid)
363
    except Subnet.DoesNotExist:
364
        subnet = None
365

  
363 366
    nic = NetworkInterface.objects.create(machine=vm, network=network,
364
                                          ip_type="STATIC", ipv4=address,
365 367
                                          state="BUILDING")
368
    if address is not None:
369
        address.nic = nic
370
        address.save()
366 371
    log.info("Connecting VM %s to Network %s. NIC: %s", vm, network, nic)
367 372

  
368 373
    return backend.connect_to_network(vm, nic)
b/snf-cyclades-app/synnefo/logic/tests/__init__.py
3 3
from .utils_tests import *
4 4
from .rapi_pool_tests import *
5 5
from .reconciliation import *
6
from .callbacks import *
b/snf-cyclades-app/synnefo/logic/tests/callbacks.py
136 136
    def test_remove(self, client):
137 137
        vm = mfactory.VirtualMachineFactory()
138 138
        # Also create a NIC
139
        nic = mfactory.NetworkInterfaceFactory(machine=vm)
140
        nic.network.get_pool().reserve(nic.ipv4)
139
        ip = mfactory.IPv4AddressFactory(nic__machine=vm)
140
        nic = ip.nic
141
        nic.network.get_pool().reserve(nic.ipv4_address)
141 142
        msg = self.create_msg(operation='OP_INSTANCE_REMOVE',
142 143
                              instance=vm.backend_vm_id)
143 144
        with mocked_quotaholder():
......
148 149
        self.assertTrue(db_vm.deleted)
149 150
        # Check that nics are deleted
150 151
        self.assertFalse(db_vm.nics.all())
151
        self.assertTrue(nic.network.get_pool().is_available(nic.ipv4))
152
        self.assertTrue(nic.network.get_pool().is_available(ip.address))
152 153
        vm2 = mfactory.VirtualMachineFactory()
153
        network = mfactory.NetworkFactory(floating_ip_pool=True)
154
        fp1 = mfactory.IPAddressFactory(machine=vm2, network=network)
155
        fp2 = mfactory.IPAddressFactory(machine=vm2, network=network)
156
        mfactory.NetworkInterfaceFactory(machine=vm2, network=network,
157
                                         ipv4=fp1.ipv4)
158
        mfactory.NetworkInterfaceFactory(machine=vm2, network=network,
159
                                         ipv4=fp2.ipv4)
154
        fp1 = mfactory.IPv4AddressFactory(nic__machine=vm2, floating_ip=True,
155
                                          network__floating_ip_pool=True)
156
        network = fp1.network
157
        nic1 = mfactory.NetworkInterfaceFactory(machine=vm2)
158
        fp1.nic = nic1
159
        fp1.save()
160 160
        pool = network.get_pool()
161
        pool.reserve(fp1.ipv4)
162
        pool.reserve(fp2.ipv4)
161
        pool.reserve(fp1.address)
163 162
        pool.save()
164 163
        msg = self.create_msg(operation='OP_INSTANCE_REMOVE',
165 164
                              instance=vm2.backend_vm_id)
......
169 168
        db_vm = VirtualMachine.objects.get(id=vm.id)
170 169
        self.assertEqual(db_vm.operstate, 'DESTROYED')
171 170
        self.assertTrue(db_vm.deleted)
172
        self.assertEqual(IPAddress.objects.get(id=fp1.id).machine, None)
173
        self.assertEqual(IPAddress.objects.get(id=fp2.id).machine, None)
171
        self.assertEqual(IPAddress.objects.get(id=fp1.id).nic, None)
174 172
        pool = network.get_pool()
175 173
        # Test that floating ips are not released
176
        self.assertFalse(pool.is_available(fp1.ipv4))
177
        self.assertFalse(pool.is_available(fp2.ipv4))
174
        self.assertFalse(pool.is_available(fp1.address))
178 175

  
179 176
    @patch("synnefo.logic.rapi_pool.GanetiRapiClient")
180 177
    def test_remove_error(self, rapi, client):
......
255 252
        for status in ["success", "error"]:
256 253
            msg = self.create_msg(operation='OP_INSTANCE_SET_PARAMS',
257 254
                                  instance=vm.backend_vm_id,
258
                                  beparams={},
255
                                  job_fields={"beparams": {}},
259 256
                                  status=status)
260 257
            client.reset_mock()
261 258
            with mocked_quotaholder():
......
267 264
        vm.operstate = "STOPPED"
268 265
        vm.save()
269 266
        for status in ["queued", "waiting", "running"]:
267
            beparams = {"vcpus": 4, "minmem": 2048, "maxmem": 2048}
270 268
            msg = self.create_msg(operation='OP_INSTANCE_SET_PARAMS',
271 269
                                  instance=vm.backend_vm_id,
272
                                  beparams={"vcpus": 4, "minmem": 2048,
273
                                            "maxmem": 2048},
270
                                  job_fields={"beparams": beparams},
274 271
                                  status=status)
275 272
            client.reset_mock()
276 273
            update_db(client, msg)
......
295 292
        vm.save()
296 293
        f2 = mfactory.FlavorFactory(cpu=8, ram=2048, disk_template="drbd",
297 294
                                    disk=1024)
295
        beparams = {"vcpus": 8, "minmem": 2048, "maxmem": 2048}
298 296
        msg = self.create_msg(operation='OP_INSTANCE_SET_PARAMS',
299 297
                              instance=vm.backend_vm_id,
300
                              beparams={"vcpus": 8, "minmem": 2048,
301
                                        "maxmem": 2048},
298
                              job_fields={"beparams": beparams},
302 299
                              status="success")
303 300
        client.reset_mock()
304 301
        with mocked_quotaholder():
......
307 304
        db_vm = VirtualMachine.objects.get(id=vm.id)
308 305
        self.assertEqual(db_vm.operstate, "STOPPED")
309 306
        self.assertEqual(db_vm.flavor, f2)
307
        beparams = {"vcpus": 100, "minmem": 2048, "maxmem": 2048}
310 308
        msg = self.create_msg(operation='OP_INSTANCE_SET_PARAMS',
311 309
                              instance=vm.backend_vm_id,
312
                              beparams={"vcpus": 100, "minmem": 2048,
313
                                        "maxmem": 2048},
310
                              job_fields={"beparams": beparams},
314 311
                              status="success")
315 312
        client.reset_mock()
316 313
        with mocked_quotaholder():
......
354 351

  
355 352
    def test_no_nics(self, client):
356 353
        vm = mfactory.VirtualMachineFactory(operstate='ERROR')
357
        mfactory.NetworkInterfaceFactory(machine=vm)
358
        mfactory.NetworkInterfaceFactory(machine=vm)
359
        mfactory.NetworkInterfaceFactory(machine=vm)
354
        mfactory.NetworkInterfaceFactory(machine=vm, state="ACTIVE")
355
        mfactory.NetworkInterfaceFactory(machine=vm, state="ACTIVE")
356
        mfactory.NetworkInterfaceFactory(machine=vm, state="ACTIVE")
360 357
        self.assertEqual(len(vm.nics.all()), 3)
361
        msg = self.create_msg(nics=[],
358
        msg = self.create_msg(instance_nics=[],
362 359
                              instance=vm.backend_vm_id)
363 360
        update_db(client, msg)
364 361
        self.assertTrue(client.basic_ack.called)
......
368 365
    def test_empty_nic(self, client):
369 366
        vm = mfactory.VirtualMachineFactory(operstate='ERROR')
370 367
        for public in [True, False]:
371
            net = mfactory.NetworkFactory(public=public, subnet6=None)
372
            msg = self.create_msg(nics=[{'network': net.backend_id}],
368
            net = mfactory.NetworkFactory(public=public)
369
            msg = self.create_msg(instance_nics=[{'network': net.backend_id,
370
                                                  'name': 'snf-nic-100'}],
373 371
                                  instance=vm.backend_vm_id)
374 372
            update_db(client, msg)
375 373
            self.assertTrue(client.basic_ack.called)
......
377 375
            nics = db_vm.nics.all()
378 376
            self.assertEqual(len(nics), 1)
379 377
            self.assertEqual(nics[0].index, 0)
380
            self.assertEqual(nics[0].ipv4, None)
381
            self.assertEqual(nics[0].ipv6, None)
378
            self.assertEqual(nics[0].ipv4_address, None)
379
            self.assertEqual(nics[0].ipv6_address, None)
382 380
            self.assertEqual(nics[0].mac, None)
383 381
            if public:
384 382
                self.assertEqual(nics[0].firewall_profile,
......
388 386

  
389 387
    def test_full_nic(self, client):
390 388
        vm = mfactory.VirtualMachineFactory(operstate='ERROR')
391
        net = mfactory.NetworkFactory(subnet='10.0.0.0/24', subnet6=None)
389
        net = mfactory.NetworkWithSubnetFactory(subnet__cidr='10.0.0.0/24',
390
                                                subnet__gateway="10.0.0.1",
391
                                                subnet6=None)
392 392
        pool = net.get_pool()
393 393
        self.assertTrue(pool.is_available('10.0.0.22'))
394 394
        pool.save()
395
        msg = self.create_msg(nics=[{'network': net.backend_id,
396
                                     'ip': '10.0.0.22',
397
                                     'mac': 'aa:bb:cc:00:11:22'}],
395
        msg = self.create_msg(instance_nics=[{'network': net.backend_id,
396
                                              'ip': '10.0.0.22',
397
                                              'mac': 'aa:bb:cc:00:11:22',
398
                                              'name': 'snf-nic-200'}],
398 399
                              instance=vm.backend_vm_id)
399 400
        update_db(client, msg)
400 401
        self.assertTrue(client.basic_ack.called)
......
402 403
        nics = db_vm.nics.all()
403 404
        self.assertEqual(len(nics), 1)
404 405
        self.assertEqual(nics[0].index, 0)
405
        self.assertEqual(nics[0].ipv4, '10.0.0.22')
406
        self.assertEqual(nics[0].ipv6, None)
406
        self.assertEqual(nics[0].ipv4_address, '10.0.0.22')
407
        self.assertEqual(nics[0].ipv6_address, None)
407 408
        self.assertEqual(nics[0].mac, 'aa:bb:cc:00:11:22')
408 409
        pool = net.get_pool()
409 410
        self.assertFalse(pool.is_available('10.0.0.22'))
......
609 610
                self.assertEqual(bn.network.state, db_bnet.network.state)
610 611

  
611 612
    def test_ips(self, client):
612
        network = mfactory.NetworkFactory(subnet='10.0.0.0/24')
613
        network = mfactory.NetworkWithSubnetFactory(subnet__cidr='10.0.0.0/24',
614
                                                    subnet__gateway="10.0.0.1")
613 615
        bn = mfactory.BackendNetworkFactory(network=network)
614 616
        msg = self.create_msg(operation='OP_NETWORK_SET_PARAMS',
615 617
                              network=network.backend_id,
616 618
                              cluster=bn.backend.clustername,
617 619
                              status='success',
618
                              add_reserved_ips=['10.0.0.10', '10.0.0.20'],
619
                              remove_reserved_ips=[])
620
                              job_fields={"add_reserved_ips": ["10.0.0.10",
621
                                                               "10.0.0.20"]})
620 622
        update_network(client, msg)
621 623
        self.assertTrue(client.basic_ack.called)
622 624
        pool = network.get_pool()
623 625
        self.assertTrue(pool.is_reserved('10.0.0.10'))
624 626
        self.assertTrue(pool.is_reserved('10.0.0.20'))
625 627
        pool.save()
626
        # Release them
628
        # Check that they are not released
627 629
        msg = self.create_msg(operation='OP_NETWORK_SET_PARAMS',
628 630
                              network=network.backend_id,
629 631
                              cluster=bn.backend.clustername,
630
                              add_reserved_ips=[],
631
                              remove_reserved_ips=['10.0.0.10', '10.0.0.20'])
632
                              job_fields={
633
                                  "remove_reserved_ips": ["10.0.0.10",
634
                                                          "10.0.0.20"]})
632 635
        update_network(client, msg)
633
        self.assertTrue(client.basic_ack.called)
636
        #self.assertTrue(client.basic_ack.called)
634 637
        pool = network.get_pool()
635
        self.assertFalse(pool.is_reserved('10.0.0.10'))
636
        self.assertFalse(pool.is_reserved('10.0.0.20'))
638
        self.assertTrue(pool.is_reserved('10.0.0.10'))
639
        self.assertTrue(pool.is_reserved('10.0.0.20'))
637 640

  
638 641

  
639 642
@patch('synnefo.lib.amqp.AMQPClient')
b/snf-cyclades-app/synnefo/logic/tests/networks.py
70 70
        kwargs["dhcp"] = False
71 71
        with mocked_quotaholder():
72 72
            net = networks.create(**kwargs)
73
        self.assertEqual(net.subnet, "192.168.20.0/24")
74
        self.assertEqual(net.gateway, "192.168.20.1")
73
        self.assertEqual(net.subnet4, "192.168.20.0/24")
74
        self.assertEqual(net.subnets.get(ipversion=4).gateway, "192.168.20.1")
75 75
        self.assertEqual(net.public, True)
76 76
        self.assertEqual(net.flavor, "CUSTOM")
77
        self.assertEqual(net.dhcp, False)
77
        self.assertEqual(net.subnets.get(ipversion=4).dhcp, False)
78 78
        self.assertEqual(net.action, "CREATE")
79 79
        self.assertEqual(net.state, "ACTIVE")
80 80
        self.assertEqual(net.name, "test")
......
149 149
        kwargs["gateway6"] = "2001:648:2ffc:1112::1"
150 150
        with mocked_quotaholder():
151 151
            net = networks.create(**kwargs)
152
        self.assertEqual(net.subnet6, "2001:648:2ffc:1112::/64")
153
        self.assertEqual(net.gateway6, "2001:648:2ffc:1112::1")
152
        subnet6 = net.subnets.get(ipversion=6)
153
        self.assertEqual(subnet6.cidr, "2001:648:2ffc:1112::/64")
154
        self.assertEqual(subnet6.gateway, "2001:648:2ffc:1112::1")
154 155
        self.assertRaises(Exception, net.get_pool)
b/snf-cyclades-app/synnefo/logic/tests/reconciliation.py
181 181
        self.assertEqual(vm1.operstate, "STARTED")
182 182

  
183 183
    def test_unsynced_nics(self, mrapi):
184
        network1 = mfactory.NetworkFactory(subnet="10.0.0.0/24")
185
        network2 = mfactory.NetworkFactory(subnet="192.168.2.0/24")
184
        network1 = mfactory.NetworkWithSubnetFactory(
185
            subnet__cidr="10.0.0.0/24", subnet__gateway="10.0.0.2")
186
        network2 = mfactory.NetworkWithSubnetFactory(
187
            subnet__cidr="192.168.2.0/24", subnet__gateway="192.168.2.2")
186 188
        vm1 = mfactory.VirtualMachineFactory(backend=self.backend,
187 189
                                             deleted=False,
188 190
                                             operstate="STOPPED")
189
        nic = mfactory.NetworkInterfaceFactory(machine=vm1, network=network1,
190
                                               ipv4="10.0.0.0")
191
        subnet = network1.subnets.get(ipversion=4)
192
        ip = mfactory.IPv4AddressFactory(nic__machine=vm1, network=network1,
193
                                         subnet=subnet,
194
                                         address="10.0.0.3")
195
        nic = ip.nic
191 196
        mrapi().GetInstances.return_value =\
192 197
            [{"name": vm1.backend_vm_id,
193 198
             "beparams": {"maxmem": 2048,
......
207 212
        self.assertEqual(vm1.operstate, "STARTED")
208 213
        nic = vm1.nics.all()[0]
209 214
        self.assertEqual(nic.network, network2)
210
        self.assertEqual(nic.ipv4, "192.168.2.1")
215
        self.assertEqual(nic.ipv4_address, "192.168.2.1")
211 216
        self.assertEqual(nic.mac, "aa:00:bb:cc:dd:ee")
212 217

  
213 218

  
......
221 226
            fix=True)
222 227

  
223 228
    def test_parted_network(self, mrapi):
224
        net1 = mfactory.NetworkFactory(subnet="192.168.0.0/30", public=False)
229
        net1 = mfactory.NetworkWithSubnetFactory(public=False)
225 230
        mrapi().GetNetworks.return_value = []
226 231
        # Test nothing if Ganeti returns nothing
227 232
        self.assertEqual(net1.backend_networks.count(), 0)
......
234 239
                                             "group_list": [["default",
235 240
                                                             "bridged",
236 241
                                                             "prv0"]],
237
                                             "network": net1.subnet,
242
                                             "network": net1.subnet4,
238 243
                                             "map": "....",
239 244
                                             "external_reservations": ""}]
240 245
        self.reconciler.reconcile_networks()
......
255 260
        self.assertFalse(net1.backend_networks
256 261
                             .filter(backend=self.backend).exists())
257 262
        # Test creation if network is a floating IP pool
258
        net2 = mfactory.NetworkFactory(subnet="192.168.0.0/30",
259
                                       floating_ip_pool=True)
263
        net2 = mfactory.NetworkWithSubnetFactory(floating_ip_pool=True)
260 264
        mrapi().GetNetworks.return_value = []
261 265
        self.assertEqual(net2.backend_networks.count(), 0)
262 266
        self.reconciler.reconcile_networks()
......
266 270
    def test_stale_network(self, mrapi):
267 271
        # Test that stale network will be deleted from DB, if network action is
268 272
        # destroy
269
        net1 = mfactory.NetworkFactory(subnet="192.168.0.0/30", public=False,
270
                                       flavor="IP_LESS_ROUTED",
271
                                       action="DESTROY", deleted=False)
273
        net1 = mfactory.NetworkWithSubnetFactory(public=False,
274
                                                 flavor="IP_LESS_ROUTED",
275
                                                 action="DESTROY",
276
                                                 deleted=False)
272 277
        bn1 = mfactory.BackendNetworkFactory(network=net1,
273 278
                                             backend=self.backend,
274 279
                                             operstate="ACTIVE")
......
281 286
        self.assertEqual(bn1.operstate, "DELETED")
282 287
        self.assertTrue(net1.deleted)
283 288
        # But not if action is not DESTROY
284
        net2 = mfactory.NetworkFactory(subnet="192.168.0.0/30", public=False,
285
                                       action="CREATE")
289
        net2 = mfactory.NetworkWithSubnetFactory(public=False, action="CREATE")
286 290
        mfactory.BackendNetworkFactory(network=net2, backend=self.backend)
287 291
        self.assertFalse(net2.deleted)
288 292
        self.reconciler.reconcile_networks()
289 293
        self.assertFalse(net2.deleted)
290 294

  
291 295
    def test_missing_network(self, mrapi):
292
        net2 = mfactory.NetworkFactory(subnet="192.168.0.0/30", public=False,
293
                                       action="CREATE")
296
        net2 = mfactory.NetworkWithSubnetFactory(public=False, action="CREATE")
294 297
        mfactory.BackendNetworkFactory(network=net2, backend=self.backend)
295 298
        mrapi().GetNetworks.return_value = []
296 299
        self.reconciler.reconcile_networks()
......
300 303
    #    pass
301 304

  
302 305
    def test_unsynced_networks(self, mrapi):
303
        net = mfactory.NetworkFactory(subnet="192.168.0.0/30", public=False,
304
                                      state="PENDING",
305
                                      action="CREATE", deleted=False)
306
        net = mfactory.NetworkWithSubnetFactory(public=False, state="PENDING",
307
                                                action="CREATE", deleted=False)
306 308
        bn = mfactory.BackendNetworkFactory(network=net, backend=self.backend,
307 309
                                            operstate="PENDING")
308 310
        mrapi().GetNetworks.return_value = [{"name": net.backend_id,
309 311
                                             "group_list": [],
310
                                             "network": net.subnet,
312
                                             "network": net.subnet4,
311 313
                                             "map": "....",
312 314
                                             "external_reservations": ""}]
313 315
        self.assertEqual(bn.operstate, "PENDING")
......
316 318
        self.assertEqual(bn.operstate, "ACTIVE")
317 319

  
318 320
    def test_orphan_networks(self, mrapi):
319
        net = mfactory.NetworkFactory(subnet="192.168.0.0/30", public=False,
320
                                      action="CREATE", deleted=True)
321
        net = mfactory.NetworkWithSubnetFactory(public=False, action="CREATE",
322
                                                deleted=True)
321 323
        mrapi().GetNetworks.return_value = [{"name": net.backend_id,
322 324
                                             "group_list": [],
323
                                             "network": net.subnet,
325
                                             "network": net.subnet4,
324 326
                                             "map": "....",
325 327
                                             "external_reservations": ""}]
326 328
        self.reconciler.reconcile_networks()
b/snf-cyclades-app/synnefo/logic/tests/servers.py
60 60
        self.assertRaises(faults.ServiceUnavailable, servers.create, **kwargs)
61 61
        self.assertEqual(models.VirtualMachine.objects.count(), 0)
62 62

  
63
        mfactory.BackendFactory(drained=False)
64
        mfactory.BackendNetworkFactory(network__public=True)
63
        subnet = mfactory.IPv4SubnetFactory(network__public=True)
64
        mfactory.BackendNetworkFactory(network=subnet.network)
65 65

  
66 66
        # error in nics
67 67
        req = deepcopy(kwargs)
......
94 94
        self.assertEqual(vm.task, "BUILD")
95 95

  
96 96
        # test connect in IPv6 only network
97
        net = mfactory.IPv6NetworkFactory(state="ACTIVE")
97
        subnet = mfactory.IPv6SubnetFactory()
98
        net = subnet.network
98 99
        mfactory.BackendNetworkFactory(network=net)
99 100
        with override_settings(settings,
100 101
                               DEFAULT_INSTANCE_NETWORKS=[str(net.id)]):
......
102 103
                vm = servers.create(**kwargs)
103 104
        nics = vm.nics.all()
104 105
        self.assertEqual(len(nics), 1)
105
        self.assertEqual(nics[0].ipv4, None)
106
        self.assertFalse(nics[0].ips.filter(subnet__ipversion=4).exists())
106 107
        args, kwargs = mrapi().CreateInstance.call_args
107 108
        ganeti_nic = kwargs["nics"][0]
108 109
        self.assertEqual(ganeti_nic["ip"], None)
......
113 114
class ServerTest(TransactionTestCase):
114 115
    def test_connect_network(self, mrapi):
115 116
        # Common connect
116
        net = mfactory.NetworkFactory(subnet="192.168.2.0/24",
117
                                      gateway="192.168.2.1",
118
                                      state="ACTIVE",
119
                                      dhcp=True,
120
                                      flavor="CUSTOM")
117
        subnet = mfactory.IPv4SubnetFactory(network__flavor="CUSTOM",
118
                                            cidr="192.168.2.0/24",
119
                                            gateway="192.168.2.1",
120
                                            dhcp=True)
121
        net = subnet.network
121 122
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
122 123
        mfactory.BackendNetworkFactory(network=net, backend=vm.backend)
123 124
        mrapi().ModifyInstance.return_value = 42
......
132 133
        self.assertEqual(nics[2]["ip"], "192.168.2.2")
133 134
        self.assertEqual(nics[2]["network"], net.backend_id)
134 135

  
135
        # No dhcp
136
        # no dhcp
136 137
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
137
        net = mfactory.NetworkFactory(subnet="192.168.2.0/24",
138
                                      gateway="192.168.2.1",
139
                                      state="ACTIVE",
140
                                      dhcp=False)
138
        subnet = mfactory.IPv4SubnetFactory(cidr="192.168.2.0/24",
139
                                            gateway="192.168.2.1",
140
                                            dhcp=False)
141
        net = subnet.network
141 142
        mfactory.BackendNetworkFactory(network=net, backend=vm.backend)
142 143
        servers.connect(vm, net)
143 144
        pool = net.get_pool(locked=False)
......
152 153

  
153 154
        # Test connect to IPv6 only network
154 155
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
155
        net = mfactory.NetworkFactory(subnet6="2000::/64",
156
                                      state="ACTIVE",
157
                                      gateway="2000::1")
156
        subnet = mfactory.IPv6SubnetFactory(cidr="2000::/64",
157
                                            gateway="2000::1")
158
        net = subnet.network
158 159
        mfactory.BackendNetworkFactory(network=net, backend=vm.backend)
159 160
        servers.connect(vm, net)
160 161
        args, kwargs = mrapi().ModifyInstance.call_args

Also available in: Unified diff