Skip to content

Commit

Permalink
Reserve ports in blocks in order to avoid collisions
Browse files Browse the repository at this point in the history
Fixes #21.
  • Loading branch information
russellcardullo committed Sep 12, 2013
1 parent 068b90b commit 7490ed4
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 4 deletions.
14 changes: 11 additions & 3 deletions src/main/scala/mesosphere/mesos/TaskBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ object TaskBuilder {
final val cpusResourceName = "cpus"
final val memResourceName = "mem"
final val portsResourceName = "ports"
final val portBlockSize = 5

def scalarResource(name: String, value: Double) = {
Resource.newBuilder
Expand Down Expand Up @@ -174,10 +175,17 @@ object TaskBuilder {
}

def getPort(resource: Resource): Option[Int] = {
if (resource.getRanges.getRangeCount > 0) {
Some(resource.getRanges.getRange(0).getBegin.toInt)
val ranges = resource.getRanges.getRangeList.asScala.map ( range => {
val portRangeBegin = range.getBegin.toInt + (range.getBegin.toInt % portBlockSize)
val blocksAvailable = (range.getEnd.toInt - portRangeBegin + 1) / portBlockSize
(portRangeBegin, blocksAvailable)
}).filter(range => (range._2 > 0))

if (ranges.size > 0) {
val range = util.Random.shuffle(ranges).head
Some((util.Random.nextInt(range._2) * 5) + range._1)
} else {
None
}
}
}
}
88 changes: 87 additions & 1 deletion src/test/scala/mesosphere/mesos/TaskBuilderTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,90 @@ class TaskBuilderTest extends AssertionsForJUnit with MockitoSugar {
.build())
.build()
}
}

@Test
def testGetPortSingleRange() = {
val maxPort = 32000L
val minPort = 31000L

val range = Value.Range.newBuilder
.setBegin(minPort)
.setEnd(maxPort)
.build
val ranges = Ranges.newBuilder
.addRange(range)
.build
val portResource = Resource.newBuilder
.setName(TaskBuilder.portsResourceName)
.setType(Value.Type.RANGES)
.setRanges(ranges)
.build

val port = TaskBuilder.getPort(portResource)

assertTrue(port.get > minPort && port.get < maxPort)
assertEquals(port.get % TaskBuilder.portBlockSize,0)
}

@Test
def testGetPortMultipleRanges() = {
val maxPort1 = 31009L
val minPort1 = 31000L

val maxPort2 = 30003L
val minPort2 = 30000L

val range1 = Value.Range.newBuilder
.setBegin(minPort1)
.setEnd(maxPort1)
.build
val range2 = Value.Range.newBuilder
.setBegin(minPort2)
.setEnd(maxPort2)
.build
val ranges = Ranges.newBuilder
.addRange(range1)
.addRange(range2)
.build
val portResource = Resource.newBuilder
.setName(TaskBuilder.portsResourceName)
.setType(Value.Type.RANGES)
.setRanges(ranges)
.build

val port = TaskBuilder.getPort(portResource)

assertTrue(port.get == 31000 || port.get == 31005)
}

@Test
def testGetPortNotEnoughBlocksInRange() = {
val maxPort1 = 31003L
val minPort1 = 31000L

val maxPort2 = 30003L
val minPort2 = 30000L

val range1 = Value.Range.newBuilder
.setBegin(minPort1)
.setEnd(maxPort1)
.build
val range2 = Value.Range.newBuilder
.setBegin(minPort2)
.setEnd(maxPort2)
.build
val ranges = Ranges.newBuilder
.addRange(range1)
.addRange(range2)
.build
val portResource = Resource.newBuilder
.setName(TaskBuilder.portsResourceName)
.setType(Value.Type.RANGES)
.setRanges(ranges)
.build

val port = TaskBuilder.getPort(portResource)

assertTrue(port.isEmpty)
}
}

0 comments on commit 7490ed4

Please sign in to comment.