Skip to content

Commit f60f3ce

Browse files
authored
router: Fixes #2789 fix proper mark based packet routing across interfaces (#2791)
Previously, the ethernet device index was used as rt_table index and packet marking id/integer. With eth0 that is sometimes used as link-local interface, the rt_table index `0` would fail as `0` is already defined as a catchall (unspecified). The fwmarking on packets on eth0 with 0x0 would also fail. This fixes the routing issues, by adding 100 to the ethernet device index so the value is a non-zero, for example then the relationship between rt_table index and ethernet would be like: 100 -> Table_eth0 -> eth0 -> fwmark 100 or 0x64 101 -> Table_eth1 -> eth1 -> fwmark 101 or 0x65 102 -> Table_eth2 -> eth2 -> fwmark 102 or 0x66 This would maintain the legacy design of routing based on packet mark and appropriate routing table rules per table/ids. This also fixes a minor NPE issue around listing of snapshots. This also backports fixes to smoketests from master. Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
1 parent 33a6ea0 commit f60f3ce

File tree

9 files changed

+56
-60
lines changed

9 files changed

+56
-60
lines changed

server/src/com/cloud/api/ApiResponseHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ public SnapshotResponse createSnapshotResponse(Snapshot snapshot) {
501501
snapshotResponse.setZoneId(zone.getUuid());
502502
}
503503

504-
if (volume.getVolumeType() == Volume.Type.ROOT) {
504+
if (volume.getVolumeType() == Volume.Type.ROOT && volume.getInstanceId() != null) {
505505
//TODO combine lines and 489 into a join in the volume dao
506506
VMInstanceVO instance = ApiDBUtils.findVMInstanceById(volume.getInstanceId());
507507
if (instance != null) {

systemvm/debian/opt/cloud/bin/cloud-nic.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ unplug_nic() {
6969

7070
action=$1
7171
dev=$2
72-
tableNo=${dev:3}
72+
tableNo=$((100+${dev:3}))
7373
tableName="Table_$dev"
7474

7575
if [ $action == 'add' ]

systemvm/debian/opt/cloud/bin/cs/CsNetfilter.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ def compare(self, list):
189189
def add_chain(self, rule):
190190
""" Add the given chain if it is not already present """
191191
if not self.has_chain(rule.get_table(), rule.get_chain()):
192-
CsHelper.execute("iptables -t %s -N %s" % (rule.get_table(), rule.get_chain()))
192+
if rule.get_chain():
193+
CsHelper.execute("iptables -t %s -N %s" % (rule.get_table(), rule.get_chain()))
193194
self.chain.add(rule.get_table(), rule.get_chain())
194195

195196
def del_standard(self):

systemvm/debian/opt/cloud/bin/cs/CsRoute.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def get_tablename(self, name):
3030
return self.table_prefix + name
3131

3232
def add_table(self, devicename):
33-
tablenumber = devicename[3:]
33+
tablenumber = 100 + int(devicename[3:])
3434
tablename = self.get_tablename(devicename)
3535
str = "%s %s" % (tablenumber, tablename)
3636
filename = "/etc/iproute2/rt_tables"

systemvm/debian/opt/cloud/bin/cs/CsRule.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class CsRule:
2727

2828
def __init__(self, dev):
2929
self.dev = dev
30-
self.tableNo = int(dev[3:])
30+
self.tableNo = 100 + int(dev[3:])
3131
self.table = "Table_%s" % (dev)
3232

3333
def addRule(self, rule):

systemvm/debian/opt/cloud/bin/ipassoc.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ remove_routing() {
103103
logger -t cloud "$(basename $0):Remove routing $pubIp on interface $ethDev"
104104
local ipNoMask=$(echo $pubIp | awk -F'/' '{print $1}')
105105
local mask=$(echo $pubIp | awk -F'/' '{print $2}')
106-
local tableNo=$(echo $ethDev | awk -F'eth' '{print $2}')
106+
local tableNo=$((100+$(echo $ethDev | awk -F'eth' '{print $2}')))
107107

108108
local tableName="Table_$ethDev"
109109
local remainip=`ip addr show $ethDev | grep "inet "`
@@ -149,7 +149,7 @@ add_routing() {
149149

150150
local tableName="Table_$ethDev"
151151
local tablePresent=$(grep $tableName /etc/iproute2/rt_tables)
152-
local tableNo=$(echo $ethDev | awk -F'eth' '{print $2}')
152+
local tableNo=$((100+$(echo $ethDev | awk -F'eth' '{print $2}')))
153153
if [ "$tablePresent" == "" ]
154154
then
155155
if [ "$tableNo" == "" ]

systemvm/debian/opt/cloud/bin/update_config.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
# first commandline argument should be the file to process
3232
if (len(sys.argv) != 2):
33-
print "[ERROR]: Invalid usage"
33+
logging.error("Invalid usage, args passed: %s" % sys.argv)
3434
sys.exit(1)
3535

3636
# FIXME we should get this location from a configuration class
@@ -47,7 +47,7 @@ def finish_config():
4747

4848

4949
def process_file():
50-
print "[INFO] Processing JSON file %s" % sys.argv[1]
50+
logging.info("Processing JSON file %s" % sys.argv[1])
5151
qf = QueueFile()
5252
qf.setFile(sys.argv[1])
5353
qf.load(None)
@@ -70,7 +70,7 @@ def is_guestnet_configured(guestnet_dict, keys):
7070
'''
7171
It seems all the interfaces have been removed. Let's allow a new configuration to come in.
7272
'''
73-
print "[WARN] update_config.py :: Reconfiguring guest network..."
73+
logging.warn("update_config.py :: Reconfiguring guest network...")
7474
return False
7575

7676
file = open(jsonConfigFile)
@@ -80,7 +80,7 @@ def is_guestnet_configured(guestnet_dict, keys):
8080
'''
8181
Guest network has to be removed.
8282
'''
83-
print "[INFO] update_config.py :: Removing guest network..."
83+
logging.info("update_config.py :: Removing guest network...")
8484
return False
8585

8686
'''
@@ -121,7 +121,10 @@ def is_guestnet_configured(guestnet_dict, keys):
121121
qf.load(None)
122122

123123
if not (os.path.isfile(jsonConfigFile) and os.access(jsonConfigFile, os.R_OK)):
124-
print "[ERROR] update_config.py :: Unable to read and access %s to process it" % jsonConfigFile
124+
# Ignore if file is already processed
125+
if os.path.isfile(jsonPath % ("processed/" + jsonFilename + ".gz")):
126+
sys.exit(0)
127+
logging.error("update_config.py :: Unable to read and access %s to process it" % jsonConfigFile)
125128
sys.exit(1)
126129

127130
# If the guest network is already configured and have the same IP, do not try to configure it again otherwise it will break
@@ -131,14 +134,14 @@ def is_guestnet_configured(guestnet_dict, keys):
131134
guestnet_dict = json.load(file)
132135

133136
if not is_guestnet_configured(guestnet_dict, ['eth1', 'eth2', 'eth3', 'eth4', 'eth5', 'eth6', 'eth7', 'eth8', 'eth9']):
134-
print "[INFO] update_config.py :: Processing Guest Network."
137+
logging.info("update_config.py :: Processing Guest Network.")
135138
process_file()
136139
else:
137-
print "[INFO] update_config.py :: No need to process Guest Network."
140+
logging.info("update_config.py :: No need to process Guest Network.")
138141
finish_config()
139142
else:
140-
print "[INFO] update_config.py :: No GuestNetwork configured yet. Configuring first one now."
143+
logging.info("update_config.py :: No GuestNetwork configured yet. Configuring first one now.")
141144
process_file()
142145
else:
143-
print "[INFO] update_config.py :: Processing incoming file => %s" % sys.argv[1]
146+
logging.info("update_config.py :: Processing incoming file => %s" % sys.argv[1])
144147
process_file()

test/integration/smoke/test_deploy_virtio_scsi_vm.py

Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -25,35 +25,30 @@
2525
# base - contains all resources as entities and defines create, delete,
2626
# list operations on them
2727
from marvin.lib.base import (Account,
28-
VirtualMachine,
29-
ServiceOffering,
30-
NetworkOffering,
31-
Network,
32-
Template,
33-
DiskOffering,
34-
StoragePool,
35-
Volume,
36-
Host,
37-
GuestOs)
38-
39-
28+
VirtualMachine,
29+
ServiceOffering,
30+
Template,
31+
DiskOffering,
32+
Volume,
33+
Host,
34+
GuestOs)
4035

4136
# utils - utility classes for common cleanup, external library wrappers etc
4237
from marvin.lib.utils import cleanup_resources, get_hypervisor_type, validateList
4338

4439
# common - commonly used methods for all tests are listed here
45-
from marvin.lib.common import get_zone, get_domain, get_template, list_hosts, get_pod
40+
from marvin.lib.common import get_zone, get_domain, get_pod
4641

4742
from marvin.sshClient import SshClient
4843

49-
from marvin.codes import FAILED, PASS
44+
from marvin.codes import FAILED
5045

5146
from nose.plugins.attrib import attr
5247

5348
import xml.etree.ElementTree as ET
54-
import code
5549
import logging
5650

51+
5752
class Templates:
5853
"""Test data for templates
5954
"""
@@ -75,11 +70,12 @@ def __init__(self):
7570
}
7671
}
7772

78-
class TestDeployVirtioSCSIVM(cloudstackTestCase):
7973

74+
class TestDeployVirtioSCSIVM(cloudstackTestCase):
8075
"""
8176
Test deploy a kvm virtio scsi template
8277
"""
78+
8379
@classmethod
8480
def setUpClass(cls):
8581
cls.logger = logging.getLogger('TestDeployVirtioSCSIVM')
@@ -100,7 +96,6 @@ def setUpClass(cls):
10096
cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
10197
cls.pod = get_pod(cls.apiclient, cls.zone.id)
10298
cls.services['mode'] = cls.zone.networktype
103-
cls._cleanup = []
10499
if cls.hypervisor.lower() not in ['kvm']:
105100
cls.hypervisorNotSupported = True
106101
return
@@ -153,41 +148,38 @@ def setUpClass(cls):
153148

154149
cls.vmhost = hosts[0]
155150

156-
151+
# Stop VM to reset password
152+
cls.virtual_machine.stop(cls.apiclient)
157153

158154
password = cls.virtual_machine.resetPassword(cls.apiclient)
159155
cls.virtual_machine.username = "ubuntu"
160156
cls.virtual_machine.password = password
161-
cls._cleanup = [
157+
158+
# Start VM after password reset
159+
cls.virtual_machine.start(cls.apiclient)
160+
161+
cls.cleanup = [
162162
cls.template,
163163
cls.service_offering,
164164
cls.sparse_disk_offering,
165165
cls.account
166166
]
167167

168-
169168
@classmethod
170169
def tearDownClass(cls):
171170
try:
171+
cls.apiclient = super(
172+
TestDeployVirtioSCSIVM,
173+
cls
174+
).getClsTestClient().getApiClient()
172175
# Cleanup resources used
173-
cleanup_resources(cls.apiclient, cls._cleanup)
176+
cleanup_resources(cls.apiclient, cls.cleanup)
174177
except Exception as e:
175178
raise Exception("Warning: Exception during cleanup : %s" % e)
176-
return
177179

178180
def setUp(self):
179181
self.apiclient = self.testClient.getApiClient()
180182
self.dbclient = self.testClient.getDbConnection()
181-
self.cleanup = []
182-
return
183-
184-
def tearDown(self):
185-
try:
186-
# Clean up, terminate the created instance, volumes and snapshots
187-
cleanup_resources(self.apiclient, self.cleanup)
188-
except Exception as e:
189-
raise Exception("Warning: Exception during cleanup : %s" % e)
190-
return
191183

192184
def verifyVirshState(self, diskcount):
193185
host = self.vmhost.ipaddress
@@ -212,14 +204,14 @@ def verifyVirshState(self, diskcount):
212204
for child in disk:
213205
if child.tag.lower() == "target":
214206
dev = child.get("dev")
215-
self.assert_(dev != None and dev.startswith("sd"), "disk dev is invalid")
207+
self.assert_(dev is not None and dev.startswith("sd"), "disk dev is invalid")
216208
elif child.tag.lower() == "address":
217209
con = child.get("controller")
218210
self.assertEqual(con, scsiindex, "disk controller not equal to SCSI " \
219-
"controller index")
211+
"controller index")
220212
elif child.tag.lower() == "driver":
221213
discard = child.get("discard")
222-
if discard: # may not be defined by older qemu/libvirt
214+
if discard: # may not be defined by older qemu/libvirt
223215
self.assertEqual(discard, "unmap", "discard settings not unmap")
224216

225217
def verifyGuestState(self, diskcount):
@@ -234,21 +226,21 @@ def verifyGuestState(self, diskcount):
234226
"Could not find appropriate number of scsi disks in guest")
235227

236228
def getVirshXML(self, host, instancename):
237-
if host == None:
229+
if host is None:
238230
self.logger.debug("getVirshXML: host is none")
239231
return ""
240232
else:
241233
self.logger.debug("host is: " + host)
242-
if instancename == None:
234+
if instancename is None:
243235
self.logger.debug("getVirshXML: instancename is none")
244236
return ""
245237
else:
246238
self.logger.debug("instancename is: " + instancename)
247239
sshc = SshClient(
248-
host=host,
249-
port=self.services['configurableData']['host']["publicport"],
250-
user=self.hostConfig['username'],
251-
passwd=self.hostConfig['password'])
240+
host=host,
241+
port=self.services['configurableData']['host']["publicport"],
242+
user=self.hostConfig['username'],
243+
passwd=self.hostConfig['password'])
252244

253245
ssh = sshc.ssh
254246

@@ -354,9 +346,8 @@ def test_05_change_vm_ostype_restart(self):
354346
self.assertIsNotNone(ostypeid,
355347
"Could not find ostypeid for Ubuntu 16.0.4 (64-bit) mapped to kvm")
356348

357-
358349
self.virtual_machine.update(self.apiclient, ostypeid=ostypeid,
359-
details=[{"rootDiskController":"scsi"}])
350+
details=[{"rootDiskController": "scsi"}])
360351

361352
self.virtual_machine.start(self.apiclient)
362353

@@ -371,6 +362,7 @@ def test_06_verify_guest_lspci_again(self):
371362

372363
self.verifyGuestState(3)
373364

365+
374366
class CommandNonzeroException(Exception):
375367
def __init__(self, code, stderr):
376368
self.code = code

test/integration/smoke/test_vm_life_cycle.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ def secure_all_hosts(self):
918918
cmd = provisionCertificate.provisionCertificateCmd()
919919
cmd.hostid = host.id
920920
cmd.reconnect = True
921-
self.apiclient.updateConfiguration(cmd)
921+
self.apiclient.provisionCertificate(cmd)
922922

923923
for host in self.hosts:
924924
self.check_connection(secured='true', host=host)

0 commit comments

Comments
 (0)