318
319
func (suite *environSuite) TestAcquireNodePassesPositiveAndNegativeSpaces(c *gc.C) {
320
suite.createFourSpaces(c)
319
321
env := suite.makeEnviron()
320
322
suite.testMAASObject.TestServer.NewNode(`{"system_id": "node0"}`)
322
324
_, err := env.acquireNode(
324
constraints.Value{Spaces: stringslicep("space1", "^space2", "space3", "^space4")},
326
constraints.Value{Spaces: stringslicep("space-1", "^space-2", "space-3", "^space-4")},
327
329
c.Check(err, jc.ErrorIsNil)
328
330
requestValues := suite.testMAASObject.TestServer.NodeOperationRequestValues()
329
331
nodeValues, found := requestValues["node0"]
330
332
c.Assert(found, jc.IsTrue)
331
c.Check(nodeValues[0].Get("interfaces"), gc.Equals, "0:space=space1;1:space=space3")
332
c.Check(nodeValues[0].Get("not_networks"), gc.Equals, "space:space2,space:space4")
333
c.Check(nodeValues[0].Get("interfaces"), gc.Equals, "0:space=2;1:space=4")
334
c.Check(nodeValues[0].Get("not_networks"), gc.Equals, "space:3,space:5")
337
func (suite *environSuite) createFourSpaces(c *gc.C) {
338
server := suite.testMAASObject.TestServer
339
server.SetVersionJSON(`{"capabilities": ["network-deployment-ubuntu"]}`)
340
server.NewSpace(spaceJSON(gomaasapi.CreateSpace{Name: "space-1"}))
341
suite.addSubnet(c, 1, 1, "node1")
342
server.NewSpace(spaceJSON(gomaasapi.CreateSpace{Name: "space-2"}))
343
suite.addSubnet(c, 2, 2, "node1")
344
server.NewSpace(spaceJSON(gomaasapi.CreateSpace{Name: "space-3"}))
345
suite.addSubnet(c, 3, 3, "node1")
346
server.NewSpace(spaceJSON(gomaasapi.CreateSpace{Name: "space-4"}))
347
suite.addSubnet(c, 4, 4, "node1")
335
350
func (suite *environSuite) TestAcquireNodeDisambiguatesNamedLabelsFromIndexedUpToALimit(c *gc.C) {
351
suite.createFourSpaces(c)
336
352
var shortLimit uint = 0
337
353
suite.PatchValue(&numericLabelLimit, shortLimit)
338
354
env := suite.makeEnviron()
371
388
expected: "volume-1:1234(tag1,tag2),volume-2:4567(tag1,tag3)",
373
390
c.Logf("test #%d: volumes=%v", i, test.volumes)
391
server.SetVersionJSON(`{"capabilities": []}`)
374
392
env := suite.makeEnviron()
375
suite.testMAASObject.TestServer.NewNode(`{"system_id": "node0", "hostname": "host0"}`)
393
// Make sure spaces are not supported.
394
server.NewNode(`{"system_id": "node0", "hostname": "host0"}`)
376
395
_, err := env.acquireNode("", "", constraints.Value{}, nil, test.volumes)
377
396
c.Check(err, jc.ErrorIsNil)
378
requestValues := suite.testMAASObject.TestServer.NodeOperationRequestValues()
397
requestValues := server.NodeOperationRequestValues()
379
398
nodeRequestValues, found := requestValues["node0"]
380
c.Check(found, jc.IsTrue)
381
c.Check(nodeRequestValues[0].Get("storage"), gc.Equals, test.expected)
399
if c.Check(found, jc.IsTrue) {
400
c.Check(nodeRequestValues[0].Get("storage"), gc.Equals, test.expected)
382
402
suite.testMAASObject.TestServer.Clear()
386
406
func (suite *environSuite) TestAcquireNodeInterfaces(c *gc.C) {
407
server := suite.testMAASObject.TestServer
387
408
// Add some constraints, including spaces to verify specified bindings
388
409
// always override any spaces constraints.
389
410
cons := constraints.Value{
390
411
Spaces: stringslicep("foo", "^bar"),
413
// In the tests below "space:5" means foo, "space:6" means bar.
393
414
for i, test := range []struct {
394
415
interfaces []interfaceBinding
395
416
expectedPositives string
397
418
expectedError string
398
419
}{{ // without specified bindings, spaces constraints are used instead.
400
expectedPositives: "0:space=foo",
401
expectedNegatives: "space:bar",
421
expectedPositives: "0:space=5",
422
expectedNegatives: "space:6",
402
423
expectedError: "",
404
425
interfaces: []interfaceBinding{{"name-1", "space-1"}},
405
expectedPositives: "name-1:space=space-1;0:space=foo",
406
expectedNegatives: "space:bar",
426
expectedPositives: "name-1:space=space-1;0:space=5",
427
expectedNegatives: "space:6",
408
429
interfaces: []interfaceBinding{
409
{"name-1", "space-1"},
410
{"name-2", "space-2"},
411
{"name-3", "space-3"},
413
expectedPositives: "name-1:space=space-1;name-2:space=space-2;name-3:space=space-3;0:space=foo",
414
expectedNegatives: "space:bar",
434
expectedPositives: "name-1:space=1;name-2:space=2;name-3:space=3;0:space=5",
435
expectedNegatives: "space:6",
416
437
interfaces: []interfaceBinding{{"", "anything"}},
417
438
expectedError: "interface bindings cannot have empty names",
419
interfaces: []interfaceBinding{{"shared-db", "bar"}},
440
interfaces: []interfaceBinding{{"shared-db", "6"}},
420
441
expectedError: `negative space "bar" from constraints clashes with interface bindings`,
422
443
interfaces: []interfaceBinding{
423
{"shared-db", "dup-space"},
426
expectedPositives: "shared-db:space=dup-space;db:space=dup-space;0:space=foo",
427
expectedNegatives: "space:bar",
447
expectedPositives: "shared-db:space=1;db:space=1;0:space=5",
448
expectedNegatives: "space:6",
429
450
interfaces: []interfaceBinding{{"", ""}},
430
451
expectedError: "interface bindings cannot have empty names",
449
470
expectedError: `invalid interface binding "bar": space provider ID is required`,
451
472
interfaces: []interfaceBinding{
452
{"dup-name", "space-1"},
453
{"dup-name", "space-2"},
455
476
expectedError: `duplicated interface binding "dup-name"`,
457
478
interfaces: []interfaceBinding{
458
{"valid-1", "space-0"},
459
{"dup-name", "space-1"},
460
{"dup-name", "space-2"},
461
{"valid-2", "space-3"},
463
484
expectedError: `duplicated interface binding "dup-name"`,
486
suite.testMAASObject.TestServer.Clear()
465
487
c.Logf("test #%d: interfaces=%v", i, test.interfaces)
488
suite.createFourSpaces(c)
489
server.NewSpace(spaceJSON(gomaasapi.CreateSpace{Name: "foo"}))
490
suite.addSubnetWithSpace(c, 6, 6, "foo", "node1")
491
server.NewSpace(spaceJSON(gomaasapi.CreateSpace{Name: "bar"}))
492
suite.addSubnetWithSpace(c, 7, 7, "bar", "node1")
466
493
env := suite.makeEnviron()
467
suite.testMAASObject.TestServer.NewNode(`{"system_id": "node0", "hostname": "host0"}`)
494
server.NewNode(`{"system_id": "node0", "hostname": "host0"}`)
468
495
_, err := env.acquireNode("", "", cons, test.interfaces, nil)
469
496
if test.expectedError != "" {
470
497
c.Check(err, gc.ErrorMatches, test.expectedError)
474
501
c.Check(err, jc.ErrorIsNil)
475
requestValues := suite.testMAASObject.TestServer.NodeOperationRequestValues()
502
requestValues := server.NodeOperationRequestValues()
476
503
nodeRequestValues, found := requestValues["node0"]
477
c.Check(found, jc.IsTrue)
478
c.Check(nodeRequestValues[0].Get("interfaces"), gc.Equals, test.expectedPositives)
479
c.Check(nodeRequestValues[0].Get("not_networks"), gc.Equals, test.expectedNegatives)
480
suite.testMAASObject.TestServer.Clear()
504
if c.Check(found, jc.IsTrue) {
506
c.Check(nodeRequestValues[0].Get("interfaces"), gc.Equals, test.expectedPositives)
507
c.Check(nodeRequestValues[0].Get("not_networks"), gc.Equals, test.expectedNegatives)
512
func (suite *environSuite) createFooBarSpaces(c *gc.C) {
513
server := suite.testMAASObject.TestServer
514
server.SetVersionJSON(`{"capabilities": ["network-deployment-ubuntu"]}`)
515
server.NewSpace(spaceJSON(gomaasapi.CreateSpace{Name: "foo"}))
516
suite.addSubnetWithSpace(c, 1, 2, "foo", "node1")
517
server.NewSpace(spaceJSON(gomaasapi.CreateSpace{Name: "bar"}))
518
suite.addSubnetWithSpace(c, 2, 3, "bar", "node1")
521
func (suite *environSuite) TestAcquireNodeConvertsSpaceNames(c *gc.C) {
522
server := suite.testMAASObject.TestServer
523
suite.createFooBarSpaces(c)
524
cons := constraints.Value{
525
Spaces: stringslicep("foo", "^bar"),
527
env := suite.makeEnviron()
528
server.NewNode(`{"system_id": "node0", "hostname": "host0"}`)
529
_, err := env.acquireNode("", "", cons, nil, nil)
530
c.Assert(err, jc.ErrorIsNil)
531
requestValues := server.NodeOperationRequestValues()
532
nodeRequestValues, found := requestValues["node0"]
533
c.Assert(found, jc.IsTrue)
534
c.Check(nodeRequestValues[0].Get("interfaces"), gc.Equals, "0:space=2")
535
c.Check(nodeRequestValues[0].Get("not_networks"), gc.Equals, "space:3")
538
func (suite *environSuite) TestAcquireNodeTranslatesSpaceNames(c *gc.C) {
539
server := suite.testMAASObject.TestServer
540
suite.createFooBarSpaces(c)
541
cons := constraints.Value{
542
Spaces: stringslicep("foo-1", "^bar-3"),
544
env := suite.makeEnviron()
545
server.NewNode(`{"system_id": "node0", "hostname": "host0"}`)
546
_, err := env.acquireNode("", "", cons, nil, nil)
547
c.Assert(err, jc.ErrorIsNil)
548
requestValues := server.NodeOperationRequestValues()
549
nodeRequestValues, found := requestValues["node0"]
550
c.Assert(found, jc.IsTrue)
551
c.Check(nodeRequestValues[0].Get("interfaces"), gc.Equals, "0:space=2")
552
c.Check(nodeRequestValues[0].Get("not_networks"), gc.Equals, "space:3")
555
func (suite *environSuite) TestAcquireNodeUnrecognisedSpace(c *gc.C) {
556
server := suite.testMAASObject.TestServer
557
suite.createFooBarSpaces(c)
558
cons := constraints.Value{
559
Spaces: stringslicep("baz"),
561
env := suite.makeEnviron()
562
server.NewNode(`{"system_id": "node0", "hostname": "host0"}`)
563
_, err := env.acquireNode("", "", cons, nil, nil)
564
c.Assert(err, gc.ErrorMatches, `unrecognised space in constraint "baz"`)
567
func (suite *environSuite) TestAcquireNodeSpacesIgnoredWhenNotSupported(c *gc.C) {
568
server := suite.testMAASObject.TestServer
569
suite.createFooBarSpaces(c)
570
server.SetVersionJSON(`{"capabilities": []}`)
571
cons := constraints.Value{
572
Spaces: stringslicep("baz"),
574
env := suite.makeEnviron()
575
server.NewNode(`{"system_id": "node0", "hostname": "host0"}`)
576
_, err := env.acquireNode("", "", cons, nil, nil)
577
c.Assert(err, jc.ErrorIsNil)
578
requestValues := server.NodeOperationRequestValues()
579
nodeRequestValues, found := requestValues["node0"]
580
c.Assert(found, jc.IsTrue)
581
c.Check(nodeRequestValues[0].Get("interfaces"), gc.Equals, "")
582
c.Check(nodeRequestValues[0].Get("not_networks"), gc.Equals, "")