Revision 7c714455
b/snf-cyclades-app/synnefo/api/servers.py | ||
---|---|---|
154 | 154 |
metadata = dict((m.meta_key, m.meta_value) for m in vm.metadata.all()) |
155 | 155 |
d['metadata'] = metadata |
156 | 156 |
|
157 |
vm_nics = vm.nics.filter(state="ACTIVE").order_by("index")
|
|
157 |
vm_nics = vm.nics.filter(state="ACTIVE").order_by("id")
|
|
158 | 158 |
attachments = map(nic_to_dict, vm_nics) |
159 | 159 |
d['attachments'] = attachments |
160 | 160 |
d['addresses'] = attachments_to_addresses(attachments) |
... | ... | |
515 | 515 |
log.debug('list_addresses_by_network %s %s', server_id, network_id) |
516 | 516 |
machine = util.get_vm(server_id, request.user_uniq) |
517 | 517 |
network = util.get_network(network_id, request.user_uniq) |
518 |
nics = machine.nics.filter(network=network, state="ACTIVE").all()
|
|
518 |
nics = machine.nics.filter(network=network, state="ACTIVE") |
|
519 | 519 |
addresses = attachments_to_addresses(map(nic_to_dict, nics)) |
520 | 520 |
|
521 | 521 |
if request.serialization == 'xml': |
... | ... | |
871 | 871 |
if attachment is None: |
872 | 872 |
raise faults.BadRequest("Missing 'attachment' attribute.") |
873 | 873 |
try: |
874 |
# attachment string: nic-<vm-id>-<nic-index>
|
|
875 |
_, server_id, nic_index = attachment.split("-", 2)
|
|
874 |
# attachment string: nic-<vm-id>-<nic-id>
|
|
875 |
_, server_id, nic_id = attachment.split("-", 2)
|
|
876 | 876 |
server_id = int(server_id) |
877 |
nic_index = int(nic_index)
|
|
877 |
nic_id = int(nic_id)
|
|
878 | 878 |
except (ValueError, TypeError): |
879 | 879 |
raise faults.BadRequest("Invalid 'attachment' attribute.") |
880 | 880 |
|
881 | 881 |
vm = util.get_vm(server_id, request.user_uniq, non_suspended=True) |
882 |
servers.disconnect(vm, nic_index=nic_index) |
|
882 |
nic = util.get_nic(vm, nic_id) |
|
883 |
servers.disconnect(vm, nic) |
|
883 | 884 |
|
884 | 885 |
return HttpResponse(status=202) |
885 | 886 |
|
b/snf-cyclades-app/synnefo/api/tests/networks.py | ||
---|---|---|
93 | 93 |
self.assertEqual(db_net.gateway6, api_net['gateway6']) |
94 | 94 |
self.assertEqual(db_net.dhcp, api_net['dhcp']) |
95 | 95 |
self.assertEqual(db_net.public, api_net['public']) |
96 |
db_nics = ["nic-%d-%d" % (nic.machine.id, nic.index) for nic in
|
|
96 |
db_nics = ["nic-%d-%d" % (nic.machine.id, nic.id) for nic in
|
|
97 | 97 |
db_net.nics.filter(machine__userid=db_net.userid)] |
98 | 98 |
self.assertEqual(db_nics, api_net['attachments']) |
99 | 99 |
|
... | ... | |
407 | 407 |
net = mfactory.NetworkFactory(state='ACTIVE', userid=user) |
408 | 408 |
nic = mfactory.NetworkInterfaceFactory(machine=vm, network=net) |
409 | 409 |
mrapi().ModifyInstance.return_value = 1 |
410 |
request = {'remove': {'attachment': 'nic-%s-%s' % (vm.id, nic.index)}}
|
|
410 |
request = {'remove': {'attachment': 'nic-%s-%s' % (vm.id, nic.id)}}
|
|
411 | 411 |
response = self.mypost('networks/%d/action' % net.id, |
412 | 412 |
net.userid, json.dumps(request), 'json') |
413 | 413 |
self.assertEqual(response.status_code, 202) |
414 |
self.assertTrue(NetworkInterface.objects.get(id=nic.id).dirty) |
|
415 | 414 |
vm.task = None |
416 | 415 |
vm.task_job_id = None |
417 | 416 |
vm.save() |
418 |
# Remove dirty nic |
|
419 |
response = self.mypost('networks/%d/action' % net.id, |
|
420 |
net.userid, json.dumps(request), 'json') |
|
421 |
self.assertFault(response, 409, 'buildInProgress') |
|
422 | 417 |
|
423 | 418 |
def test_remove_nic_malformed(self, mrapi): |
424 | 419 |
user = 'userr' |
... | ... | |
426 | 421 |
net = mfactory.NetworkFactory(state='ACTIVE', userid=user) |
427 | 422 |
nic = mfactory.NetworkInterfaceFactory(machine=vm, network=net) |
428 | 423 |
request = {'remove': |
429 |
{'att234achment': 'nic-%s-%s' % (vm.id, nic.index)}
|
|
424 |
{'att234achment': 'nic-%s-%s' % (vm.id, nic.id)}
|
|
430 | 425 |
} |
431 | 426 |
response = self.mypost('networks/%d/action' % net.id, |
432 | 427 |
net.userid, json.dumps(request), 'json') |
b/snf-cyclades-app/synnefo/api/tests/servers.py | ||
---|---|---|
144 | 144 |
self.assertEqual(api_nic['ipv4'], nic.ipv4) |
145 | 145 |
self.assertEqual(api_nic['ipv6'], nic.ipv6) |
146 | 146 |
self.assertEqual(api_nic['OS-EXT-IPS:type'], "fixed") |
147 |
self.assertEqual(api_nic['id'], 'nic-%s-%s' % (db_vm.id, nic.index))
|
|
147 |
self.assertEqual(api_nic['id'], 'nic-%s-%s' % (db_vm.id, nic.id))
|
|
148 | 148 |
api_address = server["addresses"] |
149 | 149 |
self.assertEqual(api_address[str(net.id)], [ |
150 | 150 |
{"version": 4, "addr": nic.ipv4, "OS-EXT-IPS:type": "fixed"}, |
b/snf-cyclades-app/synnefo/api/util.py | ||
---|---|---|
285 | 285 |
return address |
286 | 286 |
|
287 | 287 |
|
288 |
def get_nic(machine, network):
|
|
288 |
def get_nic(vm, nic_id):
|
|
289 | 289 |
try: |
290 |
return NetworkInterface.objects.get(machine=machine, network=network)
|
|
290 |
return vm.nics.get(id=nic_id)
|
|
291 | 291 |
except NetworkInterface.DoesNotExist: |
292 | 292 |
raise faults.ItemNotFound('Server not connected to this network.') |
293 | 293 |
|
294 | 294 |
|
295 |
def get_nic_from_index(vm, nic_index): |
|
296 |
"""Returns the nic_index-th nic of a vm |
|
297 |
Error Response Codes: itemNotFound (404), badMediaType (415) |
|
298 |
""" |
|
299 |
matching_nics = vm.nics.filter(index=nic_index) |
|
300 |
matching_nics_len = len(matching_nics) |
|
301 |
if matching_nics_len < 1: |
|
302 |
raise faults.ItemNotFound('NIC not found on VM') |
|
303 |
elif matching_nics_len > 1: |
|
304 |
raise faults.BadMediaType('NIC index conflict on VM') |
|
305 |
nic = matching_nics[0] |
|
306 |
return nic |
|
307 |
|
|
308 |
|
|
309 | 295 |
def render_metadata(request, metadata, use_values=False, status=200): |
310 | 296 |
if request.serialization == 'xml': |
311 | 297 |
data = render_to_string('metadata.xml', {'metadata': metadata}) |
... | ... | |
328 | 314 |
|
329 | 315 |
|
330 | 316 |
def construct_nic_id(nic): |
331 |
return "-".join(["nic", unicode(nic.machine.id), unicode(nic.index)])
|
|
317 |
return "-".join(["nic", unicode(nic.machine.id), unicode(nic.id)])
|
|
332 | 318 |
|
333 | 319 |
|
334 | 320 |
def verify_personality(personality): |
b/snf-cyclades-app/synnefo/db/models.py | ||
---|---|---|
374 | 374 |
get_latest_by = 'created' |
375 | 375 |
|
376 | 376 |
def __unicode__(self): |
377 |
return "<vm: %s>" % str(self.id)
|
|
377 |
return u"<vm:%s@backend:%s>" % (self.id, self.backend_id)
|
|
378 | 378 |
|
379 | 379 |
# Error classes |
380 | 380 |
class InvalidBackendIdError(Exception): |
... | ... | |
687 | 687 |
ipv6 = models.CharField(max_length=100, null=True) |
688 | 688 |
firewall_profile = models.CharField(choices=FIREWALL_PROFILES, |
689 | 689 |
max_length=30, null=True) |
690 |
dirty = models.BooleanField(default=False) |
|
691 | 690 |
state = models.CharField(max_length=32, null=False, default="ACTIVE", |
692 | 691 |
choices=STATES) |
693 | 692 |
|
693 |
@property |
|
694 |
def backend_uuid(self): |
|
695 |
"""Return the backend id by prepending backend-prefix.""" |
|
696 |
return "%snic-%s" % (settings.BACKEND_PREFIX_ID, str(self.id)) |
|
697 |
|
|
694 | 698 |
def __unicode__(self): |
695 | 699 |
return "<%s:vm:%s network:%s ipv4:%s ipv6:%s>" % \ |
696 |
(self.index, self.machine_id, self.network_id, self.ipv4,
|
|
700 |
(self.id, self.machine_id, self.network_id, self.ipv4,
|
|
697 | 701 |
self.ipv6) |
698 | 702 |
|
699 | 703 |
@property |
b/snf-cyclades-app/synnefo/logic/backend.py | ||
---|---|---|
239 | 239 |
if ipv4: |
240 | 240 |
net.reserve_address(ipv4) |
241 | 241 |
|
242 |
nic['dirty'] = False |
|
243 | 242 |
vm.nics.create(**nic) |
244 | 243 |
# Dummy save the network, because UI uses changed-since for VMs |
245 | 244 |
# and Networks in order to show the VM NICs |
... | ... | |
512 | 511 |
kw['disks'][0]['provider'] = provider |
513 | 512 |
kw['disks'][0]['origin'] = flavor.disk_origin |
514 | 513 |
|
515 |
kw['nics'] = [{"network": nic.network.backend_id, "ip": nic.ipv4} |
|
514 |
kw['nics'] = [{"name": nic.backend_uuid, |
|
515 |
"network": nic.network.backend_id, |
|
516 |
"ip": nic.ipv4} |
|
516 | 517 |
for nic in nics] |
517 | 518 |
backend = vm.backend |
518 | 519 |
depend_jobs = [] |
... | ... | |
779 | 780 |
|
780 | 781 |
depends = [[job, ["success", "error", "canceled"]] for job in depend_jobs] |
781 | 782 |
|
782 |
nic = {'ip': nic.ipv4, 'network': network.backend_id} |
|
783 |
nic = {'name': nic.backend_uuid, |
|
784 |
'network': network.backend_id, |
|
785 |
'ip': nic.ipv4} |
|
783 | 786 |
|
784 |
log.debug("Connecting NIC %s to VM %s", nic, vm)
|
|
787 |
log.debug("Adding NIC %s to VM %s", nic, vm)
|
|
785 | 788 |
|
786 | 789 |
kwargs = { |
787 | 790 |
"instance": vm.backend_vm_id, |
... | ... | |
798 | 801 |
|
799 | 802 |
|
800 | 803 |
def disconnect_from_network(vm, nic): |
801 |
log.debug("Removing nic of VM %s, with index %s", vm, str(nic.index))
|
|
804 |
log.debug("Removing NIC %s of VM %s", nic, vm)
|
|
802 | 805 |
|
803 | 806 |
kwargs = { |
804 | 807 |
"instance": vm.backend_vm_id, |
b/snf-cyclades-app/synnefo/logic/servers.py | ||
---|---|---|
355 | 355 |
if network.subnet is not None and network.dhcp: |
356 | 356 |
# Get a free IP from the address pool. |
357 | 357 |
address = util.get_network_free_address(network) |
358 |
|
|
359 |
log.info("Connecting VM %s to Network %s(%s)", vm, network, address) |
|
360 |
|
|
361 |
nic = NetworkInterface.objects.create(machine=vm, |
|
362 |
network=network, |
|
363 |
ipv4=address, |
|
364 |
state="BUILDING") |
|
358 |
nic = NetworkInterface.objects.create(machine=vm, network=network, |
|
359 |
ipv4=address, state="BUILDING") |
|
360 |
log.info("Connecting VM %s to Network %s. NIC: %s", vm, network, nic) |
|
365 | 361 |
|
366 | 362 |
return backend.connect_to_network(vm, nic) |
367 | 363 |
|
368 | 364 |
|
369 | 365 |
@server_command("DISCONNECT") |
370 |
def disconnect(vm, nic_index): |
|
371 |
nic = util.get_nic_from_index(vm, nic_index) |
|
372 |
|
|
373 |
log.info("Removing NIC %s from VM %s", str(nic.index), vm) |
|
374 |
|
|
375 |
if nic.dirty: |
|
376 |
raise faults.BuildInProgress('Machine is busy.') |
|
377 |
else: |
|
378 |
vm.nics.all().update(dirty=True) |
|
379 |
|
|
366 |
def disconnect(vm, nic): |
|
367 |
log.info("Removing NIC %s from VM %s", nic, vm) |
|
380 | 368 |
return backend.disconnect_from_network(vm, nic) |
381 | 369 |
|
382 | 370 |
|
Also available in: Unified diff