octphy (untested); fix regression test expectations

Change-Id: Ie9986e0fe49171fb616ce92c3d8652002318f94f
diff --git a/selftest/conf/resources.conf b/selftest/conf/resources.conf
index 84c85d0..c17acf5 100644
--- a/selftest/conf/resources.conf
+++ b/selftest/conf/resources.conf
@@ -8,25 +8,25 @@
 bts:
 - label: sysmoBTS 1002
   type: sysmo
-  unit_id: 1
+  ipa_unit_id: 1
   addr: 10.42.42.114
   band: GSM-1800
 
 - label: octBTS 3000
   type: oct
-  unit_id: 5
+  ipa_unit_id: 5
   addr: 10.42.42.115
   band: GSM-1800
   trx:
-  - hwaddr: 00:0c:90:32:b5:8a
+  - hw_addr: 00:0c:90:32:b5:8a
 
 - label: nanoBTS 1900
   type: nanobts
-  unit_id: 1902
+  ipa_unit_id: 1902
   addr: 10.42.42.190
   band: GSM-1900
   trx:
-  - hwaddr: 00:02:95:00:41:b3
+  - hw_addr: 00:02:95:00:41:b3
 
 arfcn:
   - arfcn: 512
diff --git a/selftest/real_suite/default-suites.conf b/selftest/real_suite/default-suites.conf
index 601076a..27a1eee 100644
--- a/selftest/real_suite/default-suites.conf
+++ b/selftest/real_suite/default-suites.conf
@@ -1 +1,3 @@
 - sms:sysmo
+- sms:trx
+- sms:octphy
diff --git a/selftest/real_suite/default.conf b/selftest/real_suite/default.conf
index 251a7b8..8c7d1e5 100644
--- a/selftest/real_suite/default.conf
+++ b/selftest/real_suite/default.conf
@@ -23,9 +23,3 @@
     - phys_chan_config: TCH/F_TCH/H_PDCH
     - phys_chan_config: TCH/F_TCH/H_PDCH
     - phys_chan_config: TCH/F_TCH/H_PDCH
-
-osmo_bts_sysmo:
-  ipa_unit_id: 1123
-
-osmo_bts_trx:
-  ipa_unit_id: 1124
diff --git a/selftest/real_suite/resources.conf b/selftest/real_suite/resources.conf
index 5fe4ca5..3a5b129 100644
--- a/selftest/real_suite/resources.conf
+++ b/selftest/real_suite/resources.conf
@@ -8,31 +8,32 @@
 bts:
 - label: sysmoBTS 1002
   type: sysmo
-  unit_id: 1
+  ipa_unit_id: 1
   addr: 10.42.42.114
   band: GSM-1800
 
 - label: octBTS 3000
   type: oct
-  unit_id: 5
+  ipa_unit_id: 5
   addr: 10.42.42.115
   band: GSM-1800
   trx:
-  - hwaddr: 00:0c:90:32:b5:8a
+  - hw_addr: 00:0c:90:32:b5:8a
+    net_device: eth0.2342
 
 - label: Ettus B210
   type: osmotrx
-  unit_id: 6
+  ipa_unit_id: 6
   addr: 10.42.42.116
   band: GSM-1800
 
 - label: nanoBTS 1900
   type: nanobts
-  unit_id: 1902
+  ipa_unit_id: 1902
   addr: 10.42.42.190
   band: GSM-1900
   trx:
-  - hwaddr: 00:02:95:00:41:b3
+  - hw_addr: 00:02:95:00:41:b3
 
 arfcn:
   - arfcn: 512
diff --git a/selftest/real_suite/scenarios/octphy.conf b/selftest/real_suite/scenarios/octphy.conf
new file mode 100644
index 0000000..02eb48b
--- /dev/null
+++ b/selftest/real_suite/scenarios/octphy.conf
@@ -0,0 +1,3 @@
+resources:
+  bts:
+  - type: octphy
diff --git a/selftest/resource_test.ok b/selftest/resource_test.ok
index 008c447..ae31d3b 100644
--- a/selftest/resource_test.ok
+++ b/selftest/resource_test.ok
@@ -40,26 +40,26 @@
            {'_hash': 'dc9ce027a257da087f31a5bc1ee6b4abd2637369',
             'arfcn': '548',
             'band': 'GSM-1900'}],
- 'bts': [{'_hash': 'a7c6d2ebaeb139e8c2e7d45c3495d046d7439007',
+ 'bts': [{'_hash': '07d9c8aaa940b674efcbbabdd69f58a6ce4e94f9',
           'addr': '10.42.42.114',
           'band': 'GSM-1800',
+          'ipa_unit_id': '1',
           'label': 'sysmoBTS 1002',
-          'type': 'sysmo',
-          'unit_id': '1'},
-         {'_hash': '02540ab9eb556056a0b4d28443bc9f4793f6d549',
+          'type': 'sysmo'},
+         {'_hash': '76c8d2f459113cd6c99ed62d1a94bbe9a291ba94',
           'addr': '10.42.42.115',
           'band': 'GSM-1800',
+          'ipa_unit_id': '5',
           'label': 'octBTS 3000',
-          'trx': [{'hwaddr': '00:0c:90:32:b5:8a'}],
-          'type': 'oct',
-          'unit_id': '5'},
-         {'_hash': '556c954d475d12cf0dc622c0df5743cac5543fa0',
+          'trx': [{'hw_addr': '00:0c:90:32:b5:8a'}],
+          'type': 'oct'},
+         {'_hash': '0b7fabd512b36aec43d7d496abd00af4e193b0f8',
           'addr': '10.42.42.190',
           'band': 'GSM-1900',
+          'ipa_unit_id': '1902',
           'label': 'nanoBTS 1900',
-          'trx': [{'hwaddr': '00:02:95:00:41:b3'}],
-          'type': 'nanobts',
-          'unit_id': '1902'}],
+          'trx': [{'hw_addr': '00:02:95:00:41:b3'}],
+          'type': 'nanobts'}],
  'modem': [{'_hash': '19c69e45aa090fb511446bd00797690aa82ff52f',
             'imsi': '901700000007801',
             'ki': 'D620F48487B1B782DA55DF6717F08FF9',
@@ -149,10 +149,42 @@
 *** end: all resources
 
 - request some resources
---- (want='nitb_iface'): DBG: Looking for 1 x nitb_iface , candidates: 3
 --- (want='arfcn'): DBG: Looking for 2 x arfcn , candidates: 10
+--- (want='arfcn'): DBG: Picked - _hash: e620569450f8259b3f0212ec19c285dd07df063c
+  arfcn: '512'
+  band: GSM-1800
+- _hash: 022621e513c5a5bf33b77430a1e9c886be676fa1
+  arfcn: '514'
+  band: GSM-1800
 --- (want='bts'): DBG: Looking for 2 x bts , candidates: 3
+--- (want='bts'): DBG: Picked - _hash: 07d9c8aaa940b674efcbbabdd69f58a6ce4e94f9
+  addr: 10.42.42.114
+  band: GSM-1800
+  ipa_unit_id: '1'
+  label: sysmoBTS 1002
+  type: sysmo
+- _hash: 76c8d2f459113cd6c99ed62d1a94bbe9a291ba94
+  addr: 10.42.42.115
+  band: GSM-1800
+  ipa_unit_id: '5'
+  label: octBTS 3000
+  trx:
+  - hw_addr: 00:0c:90:32:b5:8a
+  type: oct
 --- (want='modem'): DBG: Looking for 2 x modem , candidates: 16
+--- (want='modem'): DBG: Picked - _hash: 19c69e45aa090fb511446bd00797690aa82ff52f
+  imsi: '901700000007801'
+  ki: D620F48487B1B782DA55DF6717F08FF9
+  label: m7801
+  path: /wavecom_0
+- _hash: e1a46516a1fb493b2617ab14fc1693a9a45ec254
+  imsi: '901700000007802'
+  ki: 47FDB2D55CE6A10A85ABDAD034A5B7B3
+  label: m7802
+  path: /wavecom_1
+--- (want='nitb_iface'): DBG: Looking for 1 x nitb_iface , candidates: 3
+--- (want='nitb_iface'): DBG: Picked - _hash: cde1debf28f07f94f92c761b4b7c6bf35785ced4
+  addr: 10.42.42.1
 ~~~ currently reserved:
 arfcn:
 - _hash: e620569450f8259b3f0212ec19c285dd07df063c
@@ -164,22 +196,22 @@
   arfcn: '514'
   band: GSM-1800
 bts:
-- _hash: a7c6d2ebaeb139e8c2e7d45c3495d046d7439007
+- _hash: 07d9c8aaa940b674efcbbabdd69f58a6ce4e94f9
   _reserved_by: testowner-123-1490837279
   addr: 10.42.42.114
   band: GSM-1800
+  ipa_unit_id: '1'
   label: sysmoBTS 1002
   type: sysmo
-  unit_id: '1'
-- _hash: 02540ab9eb556056a0b4d28443bc9f4793f6d549
+- _hash: 76c8d2f459113cd6c99ed62d1a94bbe9a291ba94
   _reserved_by: testowner-123-1490837279
   addr: 10.42.42.115
   band: GSM-1800
+  ipa_unit_id: '5'
   label: octBTS 3000
   trx:
-  - hwaddr: 00:0c:90:32:b5:8a
+  - hw_addr: 00:0c:90:32:b5:8a
   type: oct
-  unit_id: '5'
 modem:
 - _hash: 19c69e45aa090fb511446bd00797690aa82ff52f
   _reserved_by: testowner-123-1490837279
diff --git a/selftest/suite_test.ok b/selftest/suite_test.ok
index c0232dd..fe7fbcb 100644
--- a/selftest/suite_test.ok
+++ b/selftest/suite_test.ok
@@ -1,8 +1,8 @@
 - non-existing suite dir
---- -: ERR: RuntimeError: Suite not found: 'does_not_exist' in ./suite_test
+--- -: ERR: RuntimeError: Suite not found: 'does_not_exist' in ./suite_test/.
 - no suite.conf
 cnf empty_dir: DBG: reading suite.conf  [empty_dir↪empty_dir]
---- ./suite_test/empty_dir/suite.conf: ERR: FileNotFoundError: [Errno 2] No such file or directory: './suite_test/empty_dir/suite.conf'  [empty_dir↪./suite_test/empty_dir/suite.conf]
+--- ./suite_test/./empty_dir/suite.conf: ERR: FileNotFoundError: [Errno 2] No such file or directory: './suite_test/./empty_dir/suite.conf'  [empty_dir↪./suite_test/./empty_dir/suite.conf]
 - valid suite dir
 cnf test_suite: DBG: reading suite.conf  [test_suite↪test_suite]
 defaults:
@@ -17,9 +17,27 @@
 
 - run hello world test
 tst test_suite: reserving resources...
---- (want='nitb_iface'): DBG: Looking for 1 x nitb_iface , candidates: 3
---- (want='modem'): DBG: Looking for 2 x modem , candidates: 16
 --- (want='bts'): DBG: Looking for 1 x bts , candidates: 3
+--- (want='bts'): DBG: Picked - _hash: 07d9c8aaa940b674efcbbabdd69f58a6ce4e94f9
+  addr: 10.42.42.114
+  band: GSM-1800
+  ipa_unit_id: '1'
+  label: sysmoBTS 1002
+  type: sysmo
+--- (want='modem'): DBG: Looking for 2 x modem , candidates: 16
+--- (want='modem'): DBG: Picked - _hash: 19c69e45aa090fb511446bd00797690aa82ff52f
+  imsi: '901700000007801'
+  ki: D620F48487B1B782DA55DF6717F08FF9
+  label: m7801
+  path: /wavecom_0
+- _hash: e1a46516a1fb493b2617ab14fc1693a9a45ec254
+  imsi: '901700000007802'
+  ki: 47FDB2D55CE6A10A85ABDAD034A5B7B3
+  label: m7802
+  path: /wavecom_1
+--- (want='nitb_iface'): DBG: Looking for 1 x nitb_iface , candidates: 3
+--- (want='nitb_iface'): DBG: Picked - _hash: cde1debf28f07f94f92c761b4b7c6bf35785ced4
+  addr: 10.42.42.1
 tst hello_world.py: START  [test_suite↪hello_world.py]
 tst hello_world.py:3: hello world  [test_suite↪hello_world.py:3]
 tst hello_world.py:4: I am 'test_suite' / 'hello_world.py:4'  [test_suite↪hello_world.py:4]
diff --git a/selftest/suite_test.py b/selftest/suite_test.py
index 8c0e6e8..cbbd6be 100755
--- a/selftest/suite_test.py
+++ b/selftest/suite_test.py
@@ -3,7 +3,7 @@
 import _prep
 from osmo_gsm_tester import log, suite, config
 
-config.ENV_CONF = os.path.join(os.getcwd(), 'conf')
+config.ENV_CONF = './suite_test'
 
 #log.style_change(trace=True)
 
diff --git a/selftest/suite_test/paths.conf b/selftest/suite_test/paths.conf
new file mode 100644
index 0000000..2b0a274
--- /dev/null
+++ b/selftest/suite_test/paths.conf
@@ -0,0 +1,2 @@
+state_dir: ./test_work/state_dir
+suites_dir: .
diff --git a/selftest/suite_test/resources.conf b/selftest/suite_test/resources.conf
new file mode 100644
index 0000000..c17acf5
--- /dev/null
+++ b/selftest/suite_test/resources.conf
@@ -0,0 +1,133 @@
+# all hardware and interfaces available to this osmo-gsm-tester
+
+nitb_iface:
+- addr: 10.42.42.1
+- addr: 10.42.42.2
+- addr: 10.42.42.3
+
+bts:
+- label: sysmoBTS 1002
+  type: sysmo
+  ipa_unit_id: 1
+  addr: 10.42.42.114
+  band: GSM-1800
+
+- label: octBTS 3000
+  type: oct
+  ipa_unit_id: 5
+  addr: 10.42.42.115
+  band: GSM-1800
+  trx:
+  - hw_addr: 00:0c:90:32:b5:8a
+
+- label: nanoBTS 1900
+  type: nanobts
+  ipa_unit_id: 1902
+  addr: 10.42.42.190
+  band: GSM-1900
+  trx:
+  - hw_addr: 00:02:95:00:41:b3
+
+arfcn:
+  - arfcn: 512
+    band: GSM-1800
+  - arfcn: 514
+    band: GSM-1800
+  - arfcn: 516
+    band: GSM-1800
+  - arfcn: 518
+    band: GSM-1800
+  - arfcn: 520
+    band: GSM-1800
+
+  - arfcn: 540
+    band: GSM-1900
+  - arfcn: 542
+    band: GSM-1900
+  - arfcn: 544
+    band: GSM-1900
+  - arfcn: 546
+    band: GSM-1900
+  - arfcn: 548
+    band: GSM-1900
+
+modem:
+- label: m7801
+  path: '/wavecom_0'
+  imsi: 901700000007801
+  ki: D620F48487B1B782DA55DF6717F08FF9
+
+- label: m7802
+  path: '/wavecom_1'
+  imsi: 901700000007802
+  ki: 47FDB2D55CE6A10A85ABDAD034A5B7B3
+
+- label: m7803
+  path: '/wavecom_2'
+  imsi: 901700000007803
+  ki: ABBED4C91417DF710F60675B6EE2C8D2
+
+- label: m7804
+  path: '/wavecom_3'
+  imsi: 901700000007804
+  ki: 8BA541179156F2BF0918CA3CFF9351B0
+
+- label: m7805
+  path: '/wavecom_4'
+  imsi: 901700000007805
+  ki: 82BEC24B5B50C9FAA69D17DEC0883A23
+
+- label: m7806
+  path: '/wavecom_5'
+  imsi: 901700000007806
+  ki: DAF6BD6A188F7A4F09866030BF0F723D
+
+- label: m7807
+  path: '/wavecom_6'
+  imsi: 901700000007807
+  ki: AEB411CFE39681A6352A1EAE4DDC9DBA
+
+- label: m7808
+  path: '/wavecom_7'
+  imsi: 901700000007808
+  ki: F5DEF8692B305D7A65C677CA9EEE09C4
+
+- label: m7809
+  path: '/wavecom_8'
+  imsi: 901700000007809
+  ki: A644F4503E812FD75329B1C8D625DA44
+
+- label: m7810
+  path: '/wavecom_9'
+  imsi: 901700000007810
+  ki: EF663BDF3477DCD18D3D2293A2BAED67
+
+- label: m7811
+  path: '/wavecom_10'
+  imsi: 901700000007811
+  ki: E88F37F048A86A9BC4D652539228C039
+
+- label: m7812
+  path: '/wavecom_11'
+  imsi: 901700000007812
+  ki: E8D940DD66FCF6F1CD2C0F8F8C45633D
+
+- label: m7813
+  path: '/wavecom_12'
+  imsi: 901700000007813
+  ki: DBF534700C10141C49F699B0419107E3
+
+- label: m7814
+  path: '/wavecom_13'
+  imsi: 901700000007814
+  ki: B36021DEB90C4EA607E408A92F3B024D
+
+- label: m7815
+  path: '/wavecom_14'
+  imsi: 901700000007815
+  ki: 1E209F6F839F9195778C4F96BE281A24
+
+- label: m7816
+  path: '/wavecom_15'
+  imsi: 901700000007816
+  ki: BF827D219E739DD189F6F59E60D6455C
diff --git a/selftest/trial_test.ok b/selftest/trial_test.ok
index 0b3e31a..66dcff0 100644
--- a/selftest/trial_test.ok
+++ b/selftest/trial_test.ok
@@ -3,10 +3,10 @@
 [TMP]/second
 [TMP]/third
 - fetch trial dirs in order
-[TMP]/first
+first
 ['taken']
-[TMP]/second
-[TMP]/third
+second
+third
 - no more trial dirs left
 None
 - test checksum verification
diff --git a/src/osmo_gsm_tester/bts_octphy.py b/src/osmo_gsm_tester/bts_octphy.py
new file mode 100644
index 0000000..4396108
--- /dev/null
+++ b/src/osmo_gsm_tester/bts_octphy.py
@@ -0,0 +1,98 @@
+# osmo_gsm_tester: specifics for running an osmo-bts-octphy
+#
+# Copyright (C) 2016-2017 by sysmocom - s.f.m.c. GmbH
+#
+# Author: Neels Hofmeyr <neels@hofmeyr.de>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import os
+from . import log, config, util, template, process
+
+class OsmoBtsOctphy(log.Origin):
+    suite_run = None
+    nitb = None
+    run_dir = None
+    inst = None
+    env = None
+
+    BIN_BTS_OCTPHY = 'osmo-bts-octphy'
+    CONF_BTS_OCTPHY = 'osmo-bts-octphy.cfg'
+
+    def __init__(self, suite_run, conf):
+        self.suite_run = suite_run
+        self.conf = conf
+        self.set_name(OsmoBtsOctphy.BIN_BTS_OCTPHY)
+        self.set_log_category(log.C_RUN)
+        self.env = {}
+
+    def start(self):
+        if self.nitb is None:
+            raise RuntimeError('BTS needs to be added to a NITB before it can be started')
+        self.suite_run.poll()
+
+        self.log('Starting to connect to', self.nitb)
+        self.run_dir = util.Dir(self.suite_run.trial.get_run_dir().new_dir(self.name()))
+        self.configure()
+
+        self.inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst(OsmoBtsOctphy.BIN_BTS_OCTPHY)))
+        lib = self.inst.child('lib')
+        if not os.path.isdir(lib):
+            raise RuntimeError('No lib/ in %r' % self.inst)
+        self.env = { 'LD_LIBRARY_PATH': lib }
+
+        self.launch_process(OsmoBtsTrx.BIN_BTS_OCTPHY, '-r', '1', '-c', os.path.abspath(self.config_file))
+        self.suite_run.poll()
+
+    def launch_process(self, binary_name, *args):
+        binary = os.path.abspath(self.inst.child('bin', binary_name))
+        run_dir = self.run_dir.new_dir(binary_name)
+        if not os.path.isfile(binary):
+            raise RuntimeError('Binary missing: %r' % binary)
+        proc = process.Process(binary_name, run_dir,
+                               (binary,) + args,
+                               env=self.env)
+        self.suite_run.remember_to_stop(proc)
+        proc.launch()
+
+    def configure(self):
+        if self.nitb is None:
+            raise RuntimeError('BTS needs to be added to a NITB before it can be configured')
+        self.config_file = self.run_dir.new_file(OsmoBtsOctphy.CONF_BTS_OCTPHY)
+        self.dbg(config_file=self.config_file)
+
+        values = dict(osmo_bts_octphy=config.get_defaults('osmo_bts_octphy'))
+        config.overlay(values, self.suite_run.config())
+        config.overlay(values, dict(osmo_bts_octphy=dict(oml_remote_ip=self.nitb.addr())))
+        config.overlay(values, dict(osmo_bts_octphy=self.conf))
+        self.dbg(conf=values)
+
+        with open(self.config_file, 'w') as f:
+            r = template.render(OsmoBtsOctphy.CONF_BTS_OCTPHY, values)
+            self.dbg(r)
+            f.write(r)
+
+    def conf_for_nitb(self):
+        values = config.get_defaults('nitb_bts')
+        config.overlay(values, config.get_defaults('osmo_bts_octphy'))
+        config.overlay(values, self.conf)
+        # using type 'sysmobts' for osmo-bts-octphy
+        config.overlay(values, { 'type': 'sysmobts' })
+        self.dbg(conf=values)
+        return values
+
+    def set_nitb(self, nitb):
+        self.nitb = nitb
+
+# vim: expandtab tabstop=4 shiftwidth=4
diff --git a/src/osmo_gsm_tester/bts_osmotrx.py b/src/osmo_gsm_tester/bts_osmotrx.py
index 2bdacec..417fbf2 100644
--- a/src/osmo_gsm_tester/bts_osmotrx.py
+++ b/src/osmo_gsm_tester/bts_osmotrx.py
@@ -1,4 +1,4 @@
-# osmo_gsm_tester: specifics for running a sysmoBTS
+# osmo_gsm_tester: specifics for running an osmo-bts-trx
 #
 # Copyright (C) 2016-2017 by sysmocom - s.f.m.c. GmbH
 #
@@ -31,10 +31,12 @@
     BIN_BTS_TRX = 'osmo-bts-trx'
     BIN_PCU = 'osmo-pcu'
 
+    CONF_BTS_TRX = 'osmo-bts-trx.cfg'
+
     def __init__(self, suite_run, conf):
         self.suite_run = suite_run
         self.conf = conf
-        self.set_name('osmo-bts-trx')
+        self.set_name(OsmoBtsTrx.BIN_BTS_TRX)
         self.set_log_category(log.C_RUN)
         self.env = {}
 
@@ -47,7 +49,7 @@
         self.run_dir = util.Dir(self.suite_run.trial.get_run_dir().new_dir(self.name()))
         self.configure()
 
-        self.inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst('osmo-bts-trx')))
+        self.inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst(OsmoBtsTrx.BIN_BTS_TRX)))
         lib = self.inst.child('lib')
         if not os.path.isdir(lib):
             raise RuntimeError('No lib/ in %r' % self.inst)
@@ -72,7 +74,7 @@
     def configure(self):
         if self.nitb is None:
             raise RuntimeError('BTS needs to be added to a NITB before it can be configured')
-        self.config_file = self.run_dir.new_file('osmo-bts-trx.cfg')
+        self.config_file = self.run_dir.new_file(OsmoBtsTrx.CONF_BTS_TRX)
         self.dbg(config_file=self.config_file)
 
         values = dict(osmo_bts_trx=config.get_defaults('osmo_bts_trx'))
@@ -82,14 +84,15 @@
         self.dbg(conf=values)
 
         with open(self.config_file, 'w') as f:
-            r = template.render('osmo-bts-trx.cfg', values)
+            r = template.render(OsmoBtsTrx.CONF_BTS_TRX, values)
             self.dbg(r)
             f.write(r)
 
     def conf_for_nitb(self):
         values = config.get_defaults('nitb_bts')
-        config.overlay(values, config.get_defaults('osmo_bts_sysmo'))
+        config.overlay(values, config.get_defaults('osmo_bts_trx'))
         config.overlay(values, self.conf)
+        # using type 'sysmobts' for osmo-bts-trx
         config.overlay(values, { 'type': 'sysmobts' })
         self.dbg(conf=values)
         return values
diff --git a/src/osmo_gsm_tester/resource.py b/src/osmo_gsm_tester/resource.py
index dc8435e..5cfbeaf 100644
--- a/src/osmo_gsm_tester/resource.py
+++ b/src/osmo_gsm_tester/resource.py
@@ -51,10 +51,10 @@
         'nitb_iface[].addr': schema.IPV4,
         'bts[].label': schema.STR,
         'bts[].type': schema.STR,
-        'bts[].unit_id': schema.INT,
+        'bts[].ipa_unit_id': schema.INT,
         'bts[].addr': schema.IPV4,
         'bts[].band': schema.BAND,
-        'bts[].trx[].hwaddr': schema.HWADDR,
+        'bts[].trx[].hw_addr': schema.HWADDR,
         'arfcn[].arfcn': schema.INT,
         'arfcn[].band': schema.BAND,
         'modem[].label': schema.STR,
@@ -270,7 +270,7 @@
 
     def find(self, want, skip_if_marked=None, do_copy=True):
         matches = {}
-        for key, want_list in want.items():
+        for key, want_list in sorted(want.items()): # sorted for deterministic test results
           with log.Origin(want=key):
             my_list = self.get(key)
 
@@ -301,7 +301,7 @@
             # figure out who gets what
             solution = solve(all_matches)
             picked = [ my_list[i] for i in solution if i is not None ]
-            log.dbg(None, None, 'Picked', pprint.pformat(picked))
+            log.dbg(None, None, 'Picked', config.tostr(picked))
             matches[key] = picked
 
         return Resources(matches, do_copy=do_copy)
diff --git a/src/osmo_gsm_tester/templates/osmo-bts-octphy.cfg.tmpl b/src/osmo_gsm_tester/templates/osmo-bts-octphy.cfg.tmpl
new file mode 100644
index 0000000..90d6092
--- /dev/null
+++ b/src/osmo_gsm_tester/templates/osmo-bts-octphy.cfg.tmpl
@@ -0,0 +1,32 @@
+!
+! OsmoBTS () configuration saved from vty
+!!
+!
+log stderr
+  logging color 1
+  logging timestamp 0
+  logging level all everything
+  logging level rsl info
+  logging level oml info
+  logging level rll notice
+  logging level rr notice
+  logging level meas notice
+  logging level pag info
+  logging level l1c info
+  logging level l1p info
+  logging level dsp info
+  logging level abis notice
+!
+line vty
+ no login
+!
+phy 0
+ octphy hw-addr ${osmo_bts_octphy.hw_addr}
+ octphy net-device ${osmo_bts_octphy.net_device}
+ instance 0
+bts 0
+ band ${osmo_bts_octphy.band}
+ ipa unit-id ${osmo_bts_octphy.ipa_unit_id} 0
+ oml remote-ip ${osmo_bts_octphy.oml_remote_ip}
+ trx 0
+  phy 0 instance 0