def get_nfs_export_policy_for_volume(self, volume_name): """Get the name of the export policy for a volume.""" api_args = { 'query': { 'volume-attributes': { 'volume-id-attributes': { 'name': volume_name, }, }, }, 'desired-attributes': { 'volume-attributes': { 'volume-export-attributes': { 'policy': None, }, }, }, } result = self.send_request('volume-get-iter', api_args) attributes_list = result.get_child_by_name( 'attributes-list') or netapp_api.NaElement('none') volume_attributes = attributes_list.get_child_by_name( 'volume-attributes') or netapp_api.NaElement('none') volume_export_attributes = volume_attributes.get_child_by_name( 'volume-export-attributes') or netapp_api.NaElement('none') export_policy = volume_export_attributes.get_child_content('policy') if not export_policy: msg = _('Could not find export policy for volume %s.') raise exception.NetAppException(msg % volume_name) return export_policy
def test_setter_na_element(self): """Tests na_element gets appended as child.""" root = api.NaElement('root') root['e1'] = api.NaElement('nested') self.assertEqual(1, len(root.get_children())) e1 = root.get_child_by_name('e1') self.assertIsInstance(e1, api.NaElement) self.assertIsInstance(e1.get_child_by_name('nested'), api.NaElement)
def list_vservers(self, vserver_type='data'): """Get the names of vservers present, optionally filtered by type.""" query = { 'vserver-info': { 'vserver-type': vserver_type, } } if vserver_type else None api_args = { 'desired-attributes': { 'vserver-info': { 'vserver-name': None, }, }, } if query: api_args['query'] = query result = self.send_request('vserver-get-iter', api_args) vserver_info_list = result.get_child_by_name( 'attributes-list') or netapp_api.NaElement('none') return [ vserver_info.get_child_content('vserver-name') for vserver_info in vserver_info_list.get_children() ]
def _get_deleted_nfs_export_policies(self): api_args = { 'query': { 'export-policy-info': { 'policy-name': DELETED_PREFIX + '*', }, }, 'desired-attributes': { 'export-policy-info': { 'policy-name': None, 'vserver': None, }, }, } result = self.send_request('export-policy-get-iter', api_args) attributes_list = result.get_child_by_name( 'attributes-list') or netapp_api.NaElement('none') policy_map = {} for export_info in attributes_list.get_children(): vserver = export_info.get_child_content('vserver') policies = policy_map.get(vserver, []) policies.append(export_info.get_child_content('policy-name')) policy_map[vserver] = policies return policy_map
def get_network_interfaces(self, protocols=None): """Get available LIFs.""" protocols = na_utils.convert_to_list(protocols) protocols = [protocol.lower() for protocol in protocols] api_args = { 'query': { 'net-interface-info': { 'data-protocols': { 'data-protocol': '|'.join(protocols), } } } } if protocols else None result = self.send_request('net-interface-get-iter', api_args) lif_info_list = result.get_child_by_name( 'attributes-list') or netapp_api.NaElement('none') interfaces = [] for lif_info in lif_info_list.get_children(): lif = { 'address': lif_info.get_child_content('address'), 'home-node': lif_info.get_child_content('home-node'), 'home-port': lif_info.get_child_content('home-port'), 'interface-name': lif_info.get_child_content('interface-name'), 'netmask': lif_info.get_child_content('netmask'), 'role': lif_info.get_child_content('role'), 'vserver': lif_info.get_child_content('vserver'), } interfaces.append(lif) return interfaces
def _get_nfs_export_rule_indices(self, policy_name, rule): api_args = { 'query': { 'export-rule-info': { 'policy-name': policy_name, 'client-match': rule, }, }, 'desired-attributes': { 'export-rule-info': { 'vserver-name': None, 'policy-name': None, 'client-match': None, 'rule-index': None, }, }, } result = self.send_request('export-rule-get-iter', api_args) attributes_list = result.get_child_by_name( 'attributes-list') or netapp_api.NaElement('none') export_rule_info_list = attributes_list.get_children() rule_indices = [ int(export_rule_info.get_child_content('rule-index')) for export_rule_info in export_rule_info_list ] rule_indices.sort() return [six.text_type(rule_index) for rule_index in rule_indices]
def test_get_ontapi_version(self): version_response = netapp_api.NaElement(fake.ONTAPI_VERSION_RESPONSE) self.connection.invoke_successfully.return_value = version_response major, minor = self.client.get_ontapi_version(cached=False) self.assertEqual('1', major) self.assertEqual('19', minor)
def test_get_system_version(self): version_response = netapp_api.NaElement( fake.SYSTEM_GET_VERSION_RESPONSE) self.connection.invoke_successfully.return_value = version_response result = self.client.get_system_version(cached=False) self.assertEqual(fake.VERSION, result['version']) self.assertEqual((8, 2, 1), result['version-tuple'])
def get_system_version(self): """Gets the current Data ONTAP version.""" result = self.send_request('system-get-version') version_tuple = result.get_child_by_name( 'version-tuple') or netapp_api.NaElement('none') system_version_tuple = version_tuple.get_child_by_name( 'system-version-tuple') or netapp_api.NaElement('none') version = {} version['version'] = result.get_child_content('version') version['version-tuple'] = ( system_version_tuple.get_child_content('generation'), system_version_tuple.get_child_content('major'), system_version_tuple.get_child_content('minor')) return version
def test_get_licenses(self): api_response = netapp_api.NaElement(fake.LICENSE_V2_LIST_INFO_RESPONSE) self.mock_object(self.client, 'send_request', mock.Mock(return_value=api_response)) response = self.client.get_licenses() self.assertSequenceEqual(fake.LICENSES, response)
def test_setter_builtin_types(self): """Tests str, int, float get converted to NaElement.""" update = dict(e1='v1', e2='1', e3='2.0', e4='8') root = api.NaElement('root') for key, value in update.items(): root[key] = value for key, value in update.items(): self.assertEqual(value, root.get_child_content(key))
def test_translate_struct_dict_unique_key(self): """Tests if dict gets properly converted to NaElements.""" root = api.NaElement('root') child = {'e1': 'v1', 'e2': 'v2', 'e3': 'v3'} root.translate_struct(child) self.assertEqual(3, len(root.get_children())) for key, value in child.items(): self.assertEqual(value, root.get_child_content(key))
def test_send_request_no_tunneling(self): element = netapp_api.NaElement('fake-api') self.client.send_request('fake-api', enable_tunneling=False) self.assertEqual( element.to_string(), self.connection.invoke_successfully.call_args[0][0].to_string()) self.assertFalse(self.connection.invoke_successfully.call_args[0][1])
def test_translate_struct_tuple(self): """Tests if tuple gets properly converted to NaElements.""" root = api.NaElement('root') child = ('e1', 'e2') root.translate_struct(child) self.assertEqual(2, len(root.get_children())) self.assertIsNone(root.get_child_content('e1')) self.assertIsNone(root.get_child_content('e2'))
def get_ontapi_version(self, cached=True): """Gets the supported ontapi version.""" if cached: return self.connection.get_api_version() ontapi_version = netapp_api.NaElement('system-get-ontapi-version') res = self.connection.invoke_successfully(ontapi_version, False) major = res.get_child_content('major-version') minor = res.get_child_content('minor-version') return major, minor
def test_send_request_with_args(self): element = netapp_api.NaElement('fake-api') api_args = {'arg1': 'data1', 'arg2': 'data2'} element.translate_struct(api_args) self.client.send_request('fake-api', api_args=api_args) self.assertEqual( element.to_string(), self.connection.invoke_successfully.call_args[0][0].to_string()) self.assertTrue(self.connection.invoke_successfully.call_args[0][1])
def send_request(self, api_name, api_args=None, enable_tunneling=True, use_zapi=True): """Sends request to Ontapi.""" request = netapp_api.NaElement(api_name) return self.connection.invoke_successfully( request, api_args=api_args, enable_tunneling=enable_tunneling, use_zapi=use_zapi)
def get_vserver_aggregate_capacities(self, aggregate_names=None): """Calculates capacity of one or more aggregates for a vserver. Returns dictionary of aggregate capacity metrics. This must be called against a Vserver LIF. """ if aggregate_names is not None and len(aggregate_names) == 0: return {} api_args = { 'desired-attributes': { 'vserver-info': { 'vserver-name': None, 'vserver-aggr-info-list': { 'vserver-aggr-info': { 'aggr-name': None, 'aggr-availsize': None, }, }, }, }, } result = self.send_request('vserver-get', api_args) attributes = result.get_child_by_name('attributes') if not attributes: raise exception.NetAppException('Failed to read Vserver info') vserver_info = attributes.get_child_by_name('vserver-info') vserver_name = vserver_info.get_child_content('vserver-name') vserver_aggr_info_element = vserver_info.get_child_by_name( 'vserver-aggr-info-list') or netapp_api.NaElement('none') vserver_aggr_info_list = vserver_aggr_info_element.get_children() if not vserver_aggr_info_list: LOG.warning(_LW('No aggregates assigned to Vserver %s.'), vserver_name) # Return dict of key-value pair of aggr_name:aggr_size_available. aggr_space_dict = {} for aggr_info in vserver_aggr_info_list: aggr_name = aggr_info.get_child_content('aggr-name') if aggregate_names is None or aggr_name in aggregate_names: aggr_size = int(aggr_info.get_child_content('aggr-availsize')) aggr_space_dict[aggr_name] = {'available': aggr_size} LOG.debug('Found available Vserver aggregates: %s', aggr_space_dict) return aggr_space_dict
def test_setter_child_dict(self): """Tests dict is appended as child to root.""" root = api.NaElement('root') root['d'] = {'e1': 'v1', 'e2': 'v2'} e1 = root.get_child_by_name('d') self.assertIsInstance(e1, api.NaElement) sub_ch = e1.get_children() self.assertEqual(2, len(sub_ch)) for c in sub_ch: self.assertIn(c.get_name(), ['e1', 'e2']) if c.get_name() == 'e1': self.assertEqual('v1', c.get_content()) else: self.assertEqual('v2', c.get_content())
def test_translate_struct_dict_nonunique_key(self): """Tests if list/dict gets properly converted to NaElements.""" root = api.NaElement('root') child = [{'e1': 'v1', 'e2': 'v2'}, {'e1': 'v3'}] root.translate_struct(child) children = root.get_children() self.assertEqual(3, len(children)) for c in children: if c.get_name() == 'e1': self.assertIn(c.get_content(), ['v1', 'v3']) else: self.assertEqual('v2', c.get_content())
def get_aggregate_for_volume(self, volume_name): """Get the name of the aggregate containing a volume.""" api_args = { 'query': { 'volume-attributes': { 'volume-id-attributes': { 'name': volume_name, }, }, }, 'desired-attributes': { 'volume-attributes': { 'volume-id-attributes': { 'containing-aggregate-name': None, 'name': None, }, }, }, } result = self.send_request('volume-get-iter', api_args) attributes_list = result.get_child_by_name( 'attributes-list') or netapp_api.NaElement('none') volume_attributes = attributes_list.get_child_by_name( 'volume-attributes') or netapp_api.NaElement('none') volume_id_attributes = volume_attributes.get_child_by_name( 'volume-id-attributes') or netapp_api.NaElement('none') aggregate = volume_id_attributes.get_child_content( 'containing-aggregate-name') if not aggregate: msg = _('Could not find aggregate for volume %s.') raise exception.NetAppException(msg % volume_name) return aggregate
def list_cluster_nodes(self): """Get all available cluster nodes.""" api_args = { 'desired-attributes': { 'node-details-info': { 'node': None, }, }, } result = self.send_request('system-node-get-iter', api_args) nodes_info_list = result.get_child_by_name( 'attributes-list') or netapp_api.NaElement('none') return [ node_info.get_child_content('node') for node_info in nodes_info_list.get_children() ]
def list_network_interfaces(self): """Get the names of available LIFs.""" api_args = { 'desired-attributes': { 'net-interface-info': { 'interface-name': None, }, }, } result = self.send_request('net-interface-get-iter', api_args) lif_info_list = result.get_child_by_name( 'attributes-list') or netapp_api.NaElement('none') return [ lif_info.get_child_content('interface-name') for lif_info in lif_info_list.get_children() ]
def test_send_request(self, use_zapi): element = netapp_api.NaElement('fake-api') self.client.send_request('fake-api', use_zapi=use_zapi) self.assertEqual( element.to_string(), self.connection.invoke_successfully.call_args[0][0].to_string()) self.assertTrue( self.connection.invoke_successfully.call_args[1][ 'enable_tunneling']) self.assertEqual( use_zapi, self.connection.invoke_successfully.call_args[1][ 'use_zapi'])
def get_aggregate_disk_types(self, aggregate_names): """Get the disk type of one or more aggregates.""" aggr_disk_type_dict = {} for aggregate_name in aggregate_names: # Only get 1 disk, since apart from hybrid aggregates all disks # must be the same type. api_args = { 'max-records': 1, 'query': { 'storage-disk-info': { 'disk-raid-info': { 'disk-aggregate-info': { 'aggregate-name': aggregate_name, }, }, }, }, 'desired-attributes': { 'storage-disk-info': { 'disk-raid-info': { 'effective-disk-type': None, }, }, }, } result = self.send_request('storage-disk-get-iter', api_args) attributes_list = result.get_child_by_name( 'attributes-list') or netapp_api.NaElement('none') storage_disk_info_list = attributes_list.get_children() if len(storage_disk_info_list) >= 1: storage_disk_info = storage_disk_info_list[0] disk_raid_info = storage_disk_info.get_child_by_name( 'disk-raid-info') if disk_raid_info: disk_type = disk_raid_info.get_child_content( 'effective-disk-type') if disk_type: aggr_disk_type_dict[aggregate_name] = disk_type return aggr_disk_type_dict
def test_setter_child_list_tuple(self): """Tests list/tuple are appended as child to root.""" root = api.NaElement('root') root['l'] = ['l1', 'l2'] root['t'] = ('t1', 't2') l = root.get_child_by_name('l') self.assertIsInstance(l, api.NaElement) t = root.get_child_by_name('t') self.assertIsInstance(t, api.NaElement) self.assertEqual(2, len(l.get_children())) for le in l.get_children(): self.assertIn(le.get_name(), ['l1', 'l2']) self.assertEqual(2, len(t.get_children())) for te in t.get_children(): self.assertIn(te.get_name(), ['t1', 't2'])
def test_send_request_with_args(self, use_zapi): element = netapp_api.NaElement('fake-api') api_args = {'arg1': 'data1', 'arg2': 'data2'} self.client.send_request('fake-api', api_args=api_args, use_zapi=use_zapi) self.assertEqual( element.to_string(), self.connection.invoke_successfully.call_args[0][0].to_string()) self.assertEqual( api_args, self.connection.invoke_successfully.call_args[1][ 'api_args']) self.assertTrue( self.connection.invoke_successfully.call_args[1][ 'enable_tunneling']) self.assertEqual( use_zapi, self.connection.invoke_successfully.call_args[1][ 'use_zapi'])
def get_node_data_ports(self, node): """Get applicable data ports on the node.""" api_args = { 'query': { 'net-port-info': { 'node': node, 'link-status': 'up', 'port-type': 'physical|if_group', 'role': 'data', }, }, 'desired-attributes': { 'node-details-info': { 'port': None, 'node': None, 'operational-speed': None, 'ifgrp-port': None, }, }, } result = self.send_request('net-port-get-iter', api_args) net_port_info_list = result.get_child_by_name( 'attributes-list') or netapp_api.NaElement('none') ports = [] for port_info in net_port_info_list.get_children(): # Skip physical ports that are part of interface groups. if port_info.get_child_content('ifgrp-port'): continue port = { 'node': port_info.get_child_content('node'), 'port': port_info.get_child_content('port'), 'speed': port_info.get_child_content('operational-speed'), } ports.append(port) return self._sort_data_ports_by_speed(ports)
def test_translate_invalid_struct(self): """Tests if invalid data structure raises exception.""" root = api.NaElement('root') child = 'random child element' self.assertRaises(ValueError, root.translate_struct, child)
def test_setter_invalid_key(self): """Tests invalid value raises exception.""" self.assertRaises(KeyError, api.NaElement('root').__setitem__, None, 'value')