def test_multiple_nodes_supported(self): store = ValueProvider() def ret_values(value: str) -> Any: data = { 'cluster>server_nodes': { "blah": "srvnode_1", "zweite": "srvnode_2" }, 'cluster>srvnode_1>hostname': 'myhost', 'cluster>srvnode_1>network>data>public_interfaces': ['eth1', 'eno2'], 'cluster>srvnode_1>storage>data_devices': ['/dev/sdb'], 'cluster>srvnode_2>hostname': 'host-2', 'cluster>srvnode_2>network>data>public_interfaces': ['eno1'], 'cluster>srvnode_2>storage>data_devices': ['/dev/sdb'] } return data[value] store._raw_get = Mock(side_effect=ret_values) ret = CdfGenerator(provider=store)._create_node_descriptions() self.assertIsInstance(ret, list) self.assertEqual(2, len(ret)) self.assertEqual(Text('myhost'), ret[0].hostname) self.assertEqual(Text('eth1'), ret[0].data_iface) self.assertEqual(Text('host-2'), ret[1].hostname) self.assertEqual(Text('eno1'), ret[1].data_iface)
def _add_pool(self, pool: PoolHandle, out_list: List[PoolDesc]) -> None: conf = self.provider layout = self._get_layout(pool) if not layout: return (cid, pool_type, i) = pool.tuple() storage_set_name = conf.get(f'cluster>{cid}>storage_set[{i}]>name') pool_name = f'{storage_set_name}__{pool_type}' allowed_failure = self._calculate_allowed_failure(layout) out_list.append( PoolDesc( name=Text(pool_name), disk_refs=Maybe( DList([ DiskRef(path=Text(device), node=Maybe( Text( conf.get(f'server_node>{node}>' 'network>data>private_fqdn')), 'Text')) for node in self._get_server_nodes(pool) for device in self._get_devices(pool, node) ], 'List DiskRef'), 'List DiskRef'), data_units=layout.data, parity_units=layout.parity, spare_units=Maybe(layout.spare, 'Natural'), type=PoolType[pool_type], allowed_failures=Maybe(allowed_failure, 'AllowedFailures')))
def test_provided_values_respected(self): store = ValueProvider() def ret_values(value: str) -> Any: data = { 'cluster>server_nodes': { "blah": "srvnode_1" }, 'cluster>srvnode_1>hostname': 'myhost', 'cluster>srvnode_1>storage>data_devices': ['/dev/sdb'], 'cluster>srvnode_1>network>data>private_interfaces': ['eth1', 'eno2'], 'cluster>srvnode_1>storage>metadata_devices': ['/dev/meta'], 'cluster>srvnode_1>s3_instances': 1, 'cluster>srvnode_1>network>data>interface_type': 'o2ib', } return data[value] store._raw_get = Mock(side_effect=ret_values) ret = CdfGenerator(provider=store)._create_node_descriptions() self.assertIsInstance(ret, list) self.assertEqual(1, len(ret)) self.assertEqual(Text('myhost'), ret[0].hostname) self.assertEqual(Text('eth1'), ret[0].data_iface) self.assertEqual(1, ret[0].s3_instances)
def test_metadata_is_hardcoded(self): store = ValueProvider() motr_store = ValueProvider() def ret_values(value: str) -> Any: data = { 'server_node': { 'MACH_ID': 'stub' }, 'server_node>MACH_ID>hostname': 'myhost', 'server_node>MACH_ID>name': 'mynodename', 'server_node>MACH_ID>storage>cvg': [{'data_devices': ['/dev/sdb'], 'metadata_devices': ['/dev/meta1']}, {'data_devices': ['/dev/sdc'], 'metadata_devices': ['/dev/meta2']}], 'server_node>MACH_ID>storage>cvg[0]>data_devices': ['/dev/sdb'], 'server_node>MACH_ID>storage>cvg[1]>data_devices': ['/dev/sdc'], 'server_node>MACH_ID>network>data>private_interfaces': ['eth1', 'eno2'], 'cortx>software>s3>service>instances': 1, 'cortx>software>motr>service>client_instances': 2, 'server_node>MACH_ID>network>data>interface_type': 'o2ib', 'server_node>MACH_ID>network>data>private_fqdn': 'srvnode-1.data.private', } return data[value] store._raw_get = Mock(side_effect=ret_values) def ret_motr_mdvalues(value: str) -> Any: data = { 'server>mynodename>cvg[0]>m0d': ['/dev/vg_srvnode-1_md1/lv_raw_md1'], 'server>mynodename>cvg[0]>m0d[0]>md_seg1': '/dev/vg_srvnode-1_md1/lv_raw_md1', 'server>mynodename>cvg[1]>m0d': ['/dev/vg_srvnode-1_md2/lv_raw_md2'], 'server>mynodename>cvg[1]>m0d[0]>md_seg1': '/dev/vg_srvnode-1_md2/lv_raw_md2' } return data.get(value) motr_store._raw_get = Mock(side_effect=ret_motr_mdvalues) ret = CdfGenerator(provider=store, motr_provider=motr_store)._create_node_descriptions() self.assertIsInstance(ret, list) self.assertEqual(1, len(ret)) self.assertEqual(Text('/dev/vg_srvnode-1_md1/lv_raw_md1'), (ret[0].m0_servers.value.value)[0].io_disks.meta_data.value) self.assertEqual(Text('/dev/vg_srvnode-1_md2/lv_raw_md2'), (ret[0].m0_servers.value.value)[1].io_disks.meta_data.value)
def test_m0server_with_disks(self): val = M0ServerDesc( runs_confd=Maybe(True, 'Bool'), io_disks=DisksDesc( meta_data=Maybe(None, 'Text'), data=DList([Text('/disk1'), Text('/disk2')], 'test'))) self.assertEqual( '{ runs_confd = Some True, io_disks = { meta_data = None Text, data = ["/disk1", "/disk2"] } }', str(val))
def test_dix_pool_uses_metadata_devices(self): store = ValueProvider() def ret_values(value: str) -> Any: data = { 'server_node>MACH_ID>storage>cvg_count': 1, 'cluster>CLUSTER_ID>site>storage_set_count': 1, 'cluster>CLUSTER_ID>storage_set>server_node_count': 1, 'cluster>CLUSTER_ID>storage_set[0]>durability>dix': {'1':2}, 'cluster>CLUSTER_ID>storage_set[0]>durability>dix>data': 1, 'cluster>CLUSTER_ID>storage_set[0]>durability>dix>parity': 0, 'cluster>CLUSTER_ID>storage_set[0]>durability>dix>spare': 0, 'cluster>CLUSTER_ID>storage_set[0]>name': 'StorageSet-1', 'cluster>CLUSTER_ID>storage_set[0]>server_nodes': ['MACH_ID'], 'cluster>cluster_id': 'CLUSTER_ID', 'server_node': { 'MACH_ID': { 'cluster_id': 'CLUSTER_ID' } }, 'server_node>MACH_ID>cluster_id': 'CLUSTER_ID', 'server_node>MACH_ID>hostname': 'myhost', 'server_node>MACH_ID>network>data>interface_type': 'o2ib', 'server_node>MACH_ID>network>data>private_fqdn': 'srvnode-1.data.private', 'server_node>MACH_ID>network>data>private_interfaces': ['eth1', 'eno2'], 'cortx>software>s3>service>instances': 1, 'server_node>MACH_ID>storage>cvg_count': 2, 'cortx>software>motr>service>client_instances': 2, 'server_node>MACH_ID>storage>cvg[0]>data_devices': ['/dev/sdb'], 'server_node>MACH_ID>storage>cvg[0]>metadata_devices': ['/dev/meta'], 'server_node>MACH_ID>storage>cvg[1]>data_devices': ['/dev/sdc'], 'server_node>MACH_ID>storage>cvg[1]>metadata_devices': ['/dev/meta1'], } return data.get(value) store._raw_get = Mock(side_effect=ret_values) store.get_machine_id = Mock(return_value='MACH_ID') store.get_storage_set_nodes = Mock(return_value=['MACH_ID']) ret = CdfGenerator(provider=store, motr_provider=Mock())._create_pool_descriptions() self.assertEqual(1, len(ret)) diskrefs = ret[0].disk_refs.get() self.assertEqual(2, len(diskrefs)) self.assertEqual(Text('/dev/meta'), diskrefs[0].path)
def _get_drive_info_form_os(self, path: str) -> Disk: drive_size = 0 with open(path, 'rb') as f: drive_size = f.seek(0, io.SEEK_END) return Disk(path=Maybe(Text(path), 'Text'), size=Maybe(drive_size, 'Natural'), blksize=Maybe(os.stat(path).st_blksize, 'Natural'))
def _create_node(self, machine_id: str) -> NodeDesc: store = self.provider hostname = store.get( f'server_node>{machine_id}>network>data>private_fqdn') name = store.get(f'server_node>{machine_id}>name') iface = self._get_iface(machine_id) try: no_m0clients = int( store.get('cortx>software>motr>service>client_instances', allow_null=True)) except TypeError: no_m0clients = 2 # Currently, there is 1 m0d per cvg. # We will create 1 IO service entry in CDF per cvg. # An IO service entry will use data devices from corresponding cvg. # meta data device is taken from motr-hare shared store. servers = DList([ M0ServerDesc(io_disks=DisksDesc( data=self._get_data_devices(machine_id, cvg), meta_data=Maybe(self._get_metadata_device(name, cvg, m0d), 'Text')), runs_confd=Maybe(False, 'Bool')) for cvg in range( len(store.get(f'server_node>{machine_id}>storage>cvg'))) for m0d in range(self._get_m0d_per_cvg(name, cvg)) ], 'List M0ServerDesc') # Adding a Motr confd entry per server node in CDF. # The `runs_confd` value (true/false) determines if Motr confd process # will be started on the node or not. servers.value.append( M0ServerDesc(io_disks=DisksDesc(data=DList([], 'List Text'), meta_data=Maybe(None, 'Text')), runs_confd=Maybe(True, 'Bool'))) return NodeDesc( hostname=Text(hostname), data_iface=Text(iface), data_iface_type=Maybe(self._get_iface_type(machine_id), 'P'), m0_servers=Maybe(servers, 'List M0ServerDesc'), # # [KN] This is a hotfix for singlenode deployment # TODO in the future the value must be taken from a correct # ConfStore key (it doesn't exist now). s3_instances=int(store.get('cortx>software>s3>service>instances')), client_instances=no_m0clients)
def _get_data_devices(self, machine_id: str, cvg: int) -> DList[Text]: store = self.provider data_devices = DList([ Text(device) for device in store.get(f'server_node>{machine_id}>' f'storage>cvg[{cvg}]>data_devices') ], 'List Text') return data_devices
def _create_node(self, name: str) -> NodeDesc: store = self.provider hostname = store.get(f'cluster>{name}>hostname') iface = self._get_iface(name) return NodeDesc( hostname=Text(hostname), data_iface=Text(iface), data_iface_type=Maybe(self._get_iface_type(name), 'P'), io_disks=DList([ Text(device) for device in store.get(f'cluster>{name}>storage>data_devices') ], 'List Text'), # # [KN] This is a hotfix for singlenode deployment # TODO in the future the value must be taken from a correct # ConfStore key (it doesn't exist now). meta_data=Text('/dev/vg_metadata_srvnode-1/lv_raw_metadata'), s3_instances=int(store.get(f'cluster>{name}>s3_instances')))
def _create_profile_descriptions( self, pool_desc: List[PoolDesc]) -> List[ProfileDesc]: profiles: List[ProfileDesc] = [] profiles.append( ProfileDesc(name=Text('Profile_the_pool'), pools=DList([pool.name for pool in pool_desc], 'List Text'))) return profiles
def test_pooldesc_empty(self): val = PoolDesc(name=Text('storage_set_name'), disk_refs=Maybe(DList([], 'List DiskRef'), []), data_units=0, parity_units=0, spare_units=Maybe(0, 'Natural'), type=PoolType.sns, allowed_failures=Maybe(None, 'AllowedFailures')) self.assertEqual( '{ name = "storage_set_name", disk_refs = Some ([] : List DiskRef), ' 'data_units = 0, parity_units = 0, spare_units = Some (0), type = T.PoolType.sns, ' 'allowed_failures = None AllowedFailures }', str(val))
def test_metadata_is_hardcoded(self): store = ValueProvider() def ret_values(value: str) -> Any: data = { 'cluster>server_nodes': { "blah": "srvnode_1" }, 'cluster>srvnode_1>hostname': 'myhost', 'cluster>srvnode_1>storage>data_devices': ['/dev/sdb'], 'cluster>srvnode_1>network>data>public_interfaces': ['eth1', 'eno2'] } return data[value] store._raw_get = Mock(side_effect=ret_values) ret = CdfGenerator(provider=store)._create_node_descriptions() self.assertIsInstance(ret, list) self.assertEqual(1, len(ret)) self.assertEqual(Text('/dev/vg_metadata_srvnode-1/lv_raw_metadata'), ret[0].meta_data)
def test_provided_values_respected(self): store = ValueProvider() motr_store = ValueProvider() def ret_values(value: str) -> Any: data = { 'cluster>CLUSTER_ID>site>storage_set_count': 1, 'cluster>CLUSTER_ID>storage_set>server_node_count': 1, 'cluster>CLUSTER_ID>storage_set[0]>name': 'StorageSet-1', 'cluster>CLUSTER_ID>storage_set[0]>durability>sns': { 'a': 42 }, 'cluster>CLUSTER_ID>storage_set[0]>durability>sns>data': 1, 'cluster>CLUSTER_ID>storage_set[0]>durability>sns>parity': 0, 'cluster>CLUSTER_ID>storage_set[0]>durability>sns>spare': 0, 'cluster>CLUSTER_ID>storage_set[0]>server_nodes': ['MACH_ID'], 'cluster>CLUSTER_ID>storage_set>server_node_count': 1, 'cluster>cluster_id': 'CLUSTER_ID', 'server_node': { 'MACH_ID': { 'cluster_id': 'CLUSTER_ID' } }, 'server_node>MACH_ID>cluster_id': 'CLUSTER_ID', 'server_node>MACH_ID>storage>cvg_count': 2, 'server_node>MACH_ID>storage>cvg': [{ 'data_devices': ['/dev/sdb', '/dev/sdc'], 'metadata_devices': ['/dev/meta', '/dev/meta1'] }], 'server_node>MACH_ID>storage>cvg[0]>data_devices': ['/dev/sdb'], 'server_node>MACH_ID>storage>cvg[0]>metadata_devices': ['/dev/meta'], 'server_node>MACH_ID>storage>cvg[1]>data_devices': ['/dev/sdc'], 'server_node>MACH_ID>storage>cvg[1]>metadata_devices': ['/dev/meta1'], 'server_node>MACH_ID>hostname': 'myhost', 'server_node>MACH_ID>name': 'mynodename', 'server_node>MACH_ID>network>data>interface_type': 'o2ib', 'server_node>MACH_ID>network>data>private_fqdn': 'srvnode-1.data.private', 'server_node>MACH_ID>network>data>private_interfaces': ['eth1', 'eno2'], 'cortx>software>s3>service>instances': 1, 'cortx>software>motr>service>client_instances': 2, } return data.get(value) store._raw_get = Mock(side_effect=ret_values) store.get_machine_id = Mock(return_value='MACH_ID') store.get_storage_set_nodes = Mock(return_value=['MACH_ID']) def ret_motr_mdvalues(value: str) -> Any: data = { 'server>mynodename>cvg[0]>m0d': ['/dev/vg_srvnode-1_md1/lv_raw_md1'], 'server>mynodename>cvg[0]>m0d[0]>md_seg1': '/dev/vg_srvnode-1_md1/lv_raw_md1', 'server>mynodename>cvg[1]>m0d': ['/dev/vg_srvnode-1_md2/lv_raw_md2'], 'server>mynodename>cvg[1]>m0d[0]>md_seg1': '/dev/vg_srvnode-1_md2/lv_raw_md2' } return data.get(value) motr_store._raw_get = Mock(side_effect=ret_motr_mdvalues) ret = CdfGenerator( provider=store, motr_provider=motr_store)._create_node_descriptions() self.assertIsInstance(ret, list) self.assertEqual(1, len(ret)) self.assertEqual(Text('srvnode-1.data.private'), ret[0].hostname) self.assertEqual(Text('eth1'), ret[0].data_iface) self.assertEqual(1, ret[0].s3_instances) self.assertEqual(2, ret[0].client_instances) ret = CdfGenerator(provider=store, motr_provider=Mock())._create_pool_descriptions() self.assertIsInstance(ret, list) self.assertEqual(1, len(ret)) self.assertEqual(Text('StorageSet-1__sns'), ret[0].name) self.assertEqual(PoolType.sns, ret[0].type) self.assertEqual(1, ret[0].data_units) self.assertEqual(0, ret[0].parity_units) self.assertEqual(0, ret[0].spare_units.get()) disk_refs = ret[0].disk_refs.value self.assertEqual(Text('srvnode-1.data.private'), disk_refs.value[0].node.value) self.assertEqual(Text('/dev/sdb'), disk_refs.value[0].path) self.assertEqual(0, ret[0].allowed_failures.value.site) self.assertEqual(0, ret[0].allowed_failures.value.rack) self.assertEqual(0, ret[0].allowed_failures.value.encl) self.assertEqual(0, ret[0].allowed_failures.value.ctrl) self.assertEqual(0, ret[0].allowed_failures.value.disk) ret = CdfGenerator( provider=store, motr_provider=Mock())._create_profile_descriptions(ret) self.assertIsInstance(ret, list) self.assertEqual(1, len(ret)) self.assertEqual(Text('Profile_the_pool'), ret[0].name) self.assertEqual(1, len(ret[0].pools.value)) self.assertEqual(Text('StorageSet-1__sns'), ret[0].pools.value[0])
def get_data_devices(self, machine_id: str, cvg: int) -> DList[Text]: data_devices = DList( [Text(device) for device in self.provider.get( f'node>{machine_id}>' f'storage>cvg[{cvg}]>devices>data')], 'List Text') return data_devices
def _get_metadata_device(self, name: str, cvg: int, m0d: int) -> Text: motr_store = self.motr_provider metadata_device = Text( motr_store.get(f'server>{name}>cvg[{cvg}]>m0d[{m0d}]>md_seg1')) return metadata_device
def test_multiple_nodes_supported(self): store = ValueProvider() def ret_values(value: str) -> Any: data = { 'server_node': { 'MACH_ID': 'stub', 'MACH_2_ID': 'stub' }, 'cluster>92f444df-87cc-4137-b680-aab3b35d1695>site>storage_set_count': 1, 'cluster>92f444df-87cc-4137-b680-aab3b35d1695>storage_set>server_node_count': 2, 'cluster>92f444df-87cc-4137-b680-aab3b35d1695>storage_set[0]>name': 'StorageSet-1', 'cluster>92f444df-87cc-4137-b680-aab3b35d1695>storage_set[0]>server_nodes': ['srvnode_1', 'srvnode_2'], 'server_node>MACH_ID>hostname': 'myhost', 'server_node>MACH_ID>name': 'mynodename', 'server_node>MACH_ID>network>data>interface_type': 'o2ib', 'server_node>MACH_ID>network>data>private_fqdn': 'srvnode-1.data.private', 'server_node>MACH_ID>network>data>private_interfaces': ['eth1'], 'cortx>software>s3>service>instances': 1, 'cortx>software>motr>service>client_instances': 2, 'server_node>MACH_ID>storage>cvg': [{ 'data_devices': ['/dev/sdb'], 'metadata_devices': ['/dev/meta'] }], 'server_node>MACH_ID>storage>cvg[0]>data_devices': ['/dev/sdb'], 'server_node>MACH_ID>storage>cvg[0]>metadata_devices': ['/dev/meta'], 'server_node>MACH_2_ID>name': 'host-2', 'server_node>MACH_2_ID>hostname': 'host-2', 'server_node>MACH_2_ID>network>data>interface_type': 'tcp', 'server_node>MACH_2_ID>network>data>private_fqdn': 'srvnode-2.data.private', 'server_node>MACH_2_ID>network>data>private_interfaces': ['eno1'], 'cortx>software>s3>service>instances': 1, 'cortx>software>motr>service>client_instances': 2, 'server_node>MACH_2_ID>storage>cvg': [{ 'data_devices': ['/dev/sdb'], 'metadata_devices': ['/dev/meta'] }], 'server_node>MACH_2_ID>storage>cvg[0]>data_devices': ['/dev/sdb'], 'server_node>MACH_2_ID>storage>cvg[0]>metadata_devices': ['/dev/meta'], } return data[value] store._raw_get = Mock(side_effect=ret_values) cdf = CdfGenerator(provider=store, motr_provider=Mock()) cdf._get_m0d_per_cvg = Mock(return_value=1) ret = cdf._create_node_descriptions() self.assertIsInstance(ret, list) self.assertEqual(2, len(ret)) self.assertEqual(Text('srvnode-1.data.private'), ret[0].hostname) self.assertEqual(Text('eth1'), ret[0].data_iface) self.assertEqual(1, ret[0].s3_instances) self.assertEqual(2, ret[0].client_instances) self.assertEqual(Text('srvnode-2.data.private'), ret[1].hostname) self.assertEqual(Text('eno1'), ret[1].data_iface) self.assertEqual(1, ret[1].s3_instances) self.assertEqual(2, ret[1].client_instances) self.assertEqual('Some (P.o2ib)', str(ret[0].data_iface_type)) self.assertEqual('Some (P.tcp)', str(ret[1].data_iface_type))