def vol_size(module): cluster = module.params['cluster'] user_name = module.params['user_name'] password = module.params['password'] vserver = module.params['vserver'] volume = module.params['volume'] size = module.params['size'] results = {} results['changed'] = False s = NaServer(cluster, 1, 15) s.set_server_type("FILER") s.set_transport_type("HTTPS") s.set_port(443) s.set_style("LOGIN") s.set_admin_user(user_name, password) s.set_vserver(vserver) api = NaElement("volume-size") api.child_add_string("volume", volume) api.child_add_string("new-size", size) xo = s.invoke_elem(api) if (xo.results_errno() != 0): r = xo.results_reason() module.fail_json(msg=r) results['changed'] = False else: results['changed'] = True return results
def snmp_community_add(module): cluster = module.params['cluster'] user_name = module.params['user_name'] password = module.params['password'] vserver = module.params['vserver'] access_control = module.params['access_control'] community = module.params['community'] results = {} results['changed'] = False s = NaServer(cluster, 1 , 15) s.set_server_type("FILER") s.set_transport_type("HTTPS") s.set_port(443) s.set_style("LOGIN") s.set_admin_user(user_name, password) s.set_vserver(vserver) api = NaElement("snmp-community-add") api.child_add_string("access-control", access_control) api.child_add_string("community", community) xo = s.invoke_elem(api) if(xo.results_errno() != 0): r = xo.results_reason() module.fail_json(msg=r) results['changed'] = False else: results['changed'] = True return results
def connect_to_api(module, vserver=None): cluster = module.params['cluster'] user_name = module.params['user_name'] password = module.params['password'] validate_certs = module.params['validate_certs'] if not validate_certs: invoke_ssl_no_verify() connection = NaServer(cluster, 1, 0) connection.set_server_type("FILER") connection.set_transport_type("HTTPS") connection.set_port(443) connection.set_style("LOGIN") connection.set_admin_user(user_name, password) if vserver: connection.set_vserver(vserver) return connection
def nfs_service_create(module): cluster = module.params['cluster'] user_name = module.params['user_name'] password = module.params['password'] vserver = module.params['vserver'] nfs_access = module.params['nfs_access'] nfsv3_enabled = module.params['nfsv3_enabled'] nfsv40_enabled = module.params['nfsv40_enabled'] nfsv41_enabled = module.params['nfsv41_enabled'] vstorage_enabled = module.params['vstorage_enabled'] nfsv41_pnfs_enabled = module.params['nfsv41_pnfs_enabled'] results = {} results['changed'] = False s = NaServer(cluster, 1, 15) s.set_server_type("FILER") s.set_transport_type("HTTPS") s.set_port(443) s.set_style("LOGIN") s.set_admin_user(user_name, password) s.set_vserver(vserver) api = NaElement("nfs-service-create") api.child_add_string("is-nfs-access-enabled", nfs_access) api.child_add_string("is-nfsv3-enabled", nfsv3_enabled) api.child_add_string("is-nfsv40-enabled", nfsv40_enabled) api.child_add_string("is-nfsv41-enabled", nfsv41_enabled) api.child_add_string("is-vstorage-enabled", vstorage_enabled) api.child_add_string("is-nfsv41-pnfs-enabled", nfsv41_pnfs_enabled) xo = s.invoke_elem(api) if (xo.results_errno() != 0): r = xo.results_reason() module.fail_json(msg=r) results['changed'] = False else: results['changed'] = True return results
def main(): module = AnsibleModule( argument_spec=dict( storage=dict(default=None, required=True), user=dict(default='admin', required=False), password=dict(default='P@ssw0rd', required=False), vserver_name=dict(default=None, required=True), volume_name=dict(default=None, required=True), security_style=dict(default='unix', required=False), guarantee=dict(default='volume', required=False), aggr_name=dict(default=None, required=True), ), ) storage = module.params['storage'] user = module.params['user'] password = module.params['password'] vserver_name = module.params['vserver_name'] volume_name = module.params['volume_name'] security_style = module.params['security_style'] guarantee = module.params['guarantee'] aggr_name = module.params['aggr_name'] s = NaServer(storage, 1, 20) s.set_admin_user(user, password) s.set_vserver(vserver_name) api = NaElement('volume-create') api.child_add_string('volume', volume_name) api.child_add_string('space-reserve', guarantee) api.child_add_string('containing-aggr-name', aggr_name) output = s.invoke_elem(api) #print(output.results_status()) #print(output.sprintf()) module.exit_json(changed=True)
def export_policy_create(module): cluster = module.params['cluster'] user_name = module.params['user_name'] password = module.params['password'] vserver = module.params['vserver'] policy_name = module.params['policy_name'] return_record = module.params['return_record'] results = {} results['changed'] = False s = NaServer(cluster, 1 , 15) s.set_server_type("FILER") s.set_transport_type("HTTPS") s.set_port(443) s.set_style("LOGIN") s.set_admin_user(user_name, password) s.set_vserver(vserver) api = NaElement("export-policy-create") api.child_add_string("policy-name", policy_name) if module.params['return_record']: api.child_add_string("return-record", return_record) xo = s.invoke_elem(api) if(xo.results_errno() != 0): r = xo.results_reason() module.fail_json(msg=r) results['changed'] = False else: results['changed'] = True return results
def ntap_get_share_list(host, user, password, protocol, interface, do_svms): svm_list = [] addr = "" hostname = {} host_lookup = () # Set up NetApp API session try: _create_unverified_https_context = ssl._create_unverified_context except AttributeError: pass else: ssl._create_default_https_context = _create_unverified_https_context netapp = NaServer(host, 1, 130) out = netapp.set_transport_type('HTTPS') ntap_set_err_check(out) out = netapp.set_style('LOGIN') ntap_set_err_check(out) out = netapp.set_admin_user(user, password) ntap_set_err_check(out) # Get list of SVMs from NetApp result = netapp.invoke('vserver-get-iter') ntap_invoke_err_check(result) vs_info = result.child_get('attributes-list').children_get() for vs in vs_info: vs_type = vs.child_get_string("vserver-type") if vs_type == "data": svm_list.append(vs.child_get_string('vserver-name')) # Get list of interfaces on the NetApp. Find the an applicable interface, grab the IP, # then try to get a hostname from it via DNS result = netapp.invoke('net-interface-get-iter') ntap_invoke_err_check(result) ints = result.child_get('attributes-list').children_get() for i in ints: if interface: if i.child_get_string('interface-name') not in interface: continue protocols = i.child_get('data-protocols').children_get() # Couldn't figure out how to pull the protocols properly, nasty hack. Should clean up later for p in protocols: proto = p.sprintf() proto = proto.replace('<', '>') pf = proto.split('>') if pf[2] == protocol or (pf[2] == "cifs" and protocol == "smb"): svm = i.child_get_string('vserver') addr = i.child_get_string('address') try: host_lookup = socket.gethostbyaddr(addr) hostname[svm] = host_lookup[0] except socket.herror: hostname[svm] = addr # For each SVM, grab the NFS exports of SMB shares. Generate the share_list structure for main() dprint("HOSTNAME_ARRAY: " + str(hostname)) for svm in svm_list: svm_share_list = [] junct_point = {} if do_svms and svm not in do_svms: continue dprint("SVM = " + svm) out = netapp.set_vserver(svm) if protocol == "nfs": result = netapp.invoke('volume-get-iter') ntap_invoke_err_check(result) vol_attrs = result.child_get('attributes-list').children_get() for v in vol_attrs: vid_attrs = v.child_get('volume-id-attributes') volume = vid_attrs.child_get_string('name') junction = vid_attrs.child_get_string('junction-path') junct_point[volume] = junction dprint("JP = " + str(junct_point)) result = netapp.invoke('qtree-list-iter') ntap_invoke_err_check(result) qt_attrs = result.child_get('attributes-list').children_get() for qt in qt_attrs: volume = qt.child_get_string('volume') qtree = qt.child_get_string('qtree') dprint("VOL= " + volume) dprint("QTREE= " + qtree) try: dprint("JUNCT_P= " + junct_point[volume]) except: dprint("No Junction Point found") dprint("JUNCT = " + str(junct_point)) if qtree == "": try: vol_j = junct_point[volume] except: continue else: vol_j = junct_point[volume] + "/" + qtree if vol_j != "/": svm_share_list.append(vol_j) elif protocol == "cifs" or protocol == "smb": api = NaElement("cifs-share-get-iter") xi = NaElement("desired-attributes") api.child_add(xi) xi1 = NaElement("cifs-share") xi1.child_add_string("vserver", "") xi1.child_add_string("path", "") xi.child_add(xi1) api.child_add_string('max-records', 5000) result = netapp.invoke_elem(api) ntap_invoke_err_check(result) try: attr = result.child_get('attributes-list').children_get() except: continue for sh in attr: sh_svm = sh.child_get_string('vserver') if sh_svm != svm: continue path = sh.child_get_string('path') if path == "/": # Exclude root volumes continue svm_share_list.append(sh.child_get_string('share-name')) share_list[hostname[svm]] = svm_share_list return (share_list)
dossl = 1 vserver = sys.argv[2] else: print_usage() else: vserver = opt storage = sys.argv[2] user = sys.argv[3] password = sys.argv[4] arguments = sys.argv[5:] # open server server = NaServer(storage, 1, 15) if(not server.set_vserver(vserver)): sys.exit (1) server.set_admin_user(user, password) if (dossl) : resp = server.set_transport_type("HTTPS") if (resp and resp.results_errno() != 0) : r = resp.results_reason() print ("Unable to set HTTPS transport " + r + "\n") sys.exit (1) length = len(arguments) if(length > 0): # invoke the api with api name and any supplied key-value pairs x = NaElement(arguments[0]) k = 0
def login(): if 'username' in session: return redirect(url_for('vols')) error = None try: if request.method == 'POST': session['username'] = request.form['username'] session['pass'] = request.form['password'] session['vserver'] = request.form['vserver'] if session['vserver'] == "KW1PESANV01": IP = '10.200.5.100' elif session['vserver'] == "SG1PESANV01": IP = '10.201.18.70' try: s = NaServer(IP, 1, 30) s.set_server_type("FILER") s.set_transport_type("HTTPS") s.set_port(443) s.set_style("LOGIN") s.set_admin_user(session['username'], session['pass']) s.set_vserver(session['vserver']) s.set_server_cert_verification("False") s.set_hostname_verification("False") api = NaElement("volume-get-iter") xi = NaElement("desired-attributes") api.child_add(xi) xi = NaElement("desired-attributes") api.child_add(xi) xi1 = NaElement("volume-attributes") xi.child_add(xi1) xi11 = NaElement("volume-id-attributes") xi1.child_add(xi11) xi11.child_add_string("name", "name") xi27 = NaElement("volume-space-attributes") xi1.child_add(xi27) xi27.child_add_string("size-total", "<size-total>") xi27.child_add_string("percentage-size-used", "<percentage-size-used>") api.child_add_string("max-records", "1000") xo = s.invoke_elem(api) if (xo.results_status() == "failed"): print("Error:\n") print(xo.sprintf()) sys.exit(1) else: # print (xo.sprintf()) vols = xo.child_get("attributes-list").children_get() data = [] for vol in vols: mydict = xmltodict.parse(vol.sprintf()) if 'volume-space-attributes' not in mydict[ 'volume-attributes']: continue dicty = mydict['volume-attributes'][ 'volume-id-attributes'].copy() dicty.update(mydict['volume-attributes'] ['volume-space-attributes']) dicty['size-total'] = ( '%.0f' % (float(int(dicty['size-total'].strip())) / 1024 / 1024 / 1024)) del dicty['owning-vserver-name'] dictyy = OrderedDict() dictyy['name'] = dicty['name'] dictyy['size-total'] = dicty['size-total'] + ' GB' dictyy['percentage-size-used'] = dicty[ 'percentage-size-used'] + ' %' data.append(dictyy) except Exception, err: print "Error!" print Exception, err except ServerError as e: error = str(e) return render_template('login.html', error=error)
def export_rule_create(module): cluster = module.params['cluster'] user_name = module.params['user_name'] password = module.params['password'] vserver = module.params['vserver'] policy_name = module.params['policy_name'] client_match = module.params['client_match'] ro_rule = module.params['ro_rule'] rw_rule = module.params['rw_rule'] protocol = module.params['protocol'] super_user_security = module.params['super_user_security'] rule_index = module.params['rule_index'] allow_suid = module.params['allow_suid'] results = {} results['changed'] = False s = NaServer(cluster, 1, 15) s.set_server_type("FILER") s.set_transport_type("HTTPS") s.set_port(443) s.set_style("LOGIN") s.set_admin_user(user_name, password) s.set_vserver(vserver) api = NaElement('export-rule-create') api.child_add_string('policy-name', policy_name) api.child_add_string('client-match', client_match) if module.params['ro_rule']: xi = NaElement('ro-rule') api.child_add(xi) for flavor in ro_rule: xi.child_add_string('security-flavor', flavor) if module.params['rw_rule']: xi = NaElement("rw-rule") api.child_add(xi) for flavor in rw_rule: xi.child_add_string("security-flavor", flavor) if module.params['protocol']: xi = NaElement('protocol') api.child_add(xi) for proto in protocol: xi.child_add_string('access-protocol', proto) if module.params['super_user_security']: xi = NaElement('super-user-security') api.child_add(xi) for flavor in super_user_security: xi.child_add_string('security-flavor', flavor) if module.params['rule_index']: api.child_add_string('rule-index', rule_index) if module.params['allow_suid']: api.child_add_string('is-allow-set-uid-enabled', allow_suid) xo = s.invoke_elem(api) if (xo.results_errno() != 0): r = xo.results_reason() module.fail_json(msg=r) results['changed'] = False else: results['changed'] = True return results
except AttributeError: pass else: ssl._create_default_https_context = _create_unverified_https_context with open('config.yml') as stream: config = yaml.safe_load(stream) try: s = NaServer(config['filer'], 1, 30) s.set_server_type("FILER") s.set_transport_type("HTTPS") s.set_port(443) s.set_style("LOGIN") s.set_admin_user(config['username'], config['password']) s.set_vserver(config['vserver']) s.set_server_cert_verification("False") s.set_hostname_verification("False") api = NaElement("volume-get-iter") xi = NaElement("desired-attributes") api.child_add(xi) xi1 = NaElement("volume-attributes") xi.child_add(xi1) xi11 = NaElement("volume-id-attributes") xi1.child_add(xi11) xi11.child_add_string("name", "name")
cluster_name = cluster_info.child_get_string('cluster-name') cluster_serial = cluster_info.child_get_string('cluster-serial-number') cluster_location = cluster_info.child_get_string('cluster-location') # Pull SVMs from NTAP result = netapp.invoke('vserver-get-iter') ntap_invoke_err_check(result) vs_info = result.child_get('attributes-list').children_get() for vs in vs_info: vs_type = vs.child_get_string("vserver-type") if vs_type == "data": svm_list.append(vs.child_get_string('vserver-name')) dprint(svm_list) for svm_inst in svm_list: netapp.set_vserver(svm_inst) dprint("Processing SVM: " + svm_inst) # Discover volumes that have LUNs. Will exclude them later if NAS_ONLY: has_luns = True result = netapp.invoke('lun-get-iter') ntap_invoke_err_check(result) try: lun_info = result.child_get('attributes-list').children_get() except AttributeError: has_luns = False if has_luns: for lun in lun_info: lun_vol = lun.child_get_string('volume') lun_svm = lun.child_get_string('vserver') try:
def volume_create(module): cluster = module.params['cluster'] user_name = module.params['user_name'] password = module.params['password'] vserver = module.params['vserver'] volume = module.params['volume'] aggregate = module.params['aggregate'] size = module.params['size'] state = module.params['state'] type = module.params['type'] policy = module.params['policy'] percentage_snapshot_reserve = module.params['percentage_snapshot_reserve'] junction_path = module.params['junction_path'] snapshot_policy = module.params['snapshot_policy'] space_reserve = module.params['space_reserve'] results = {} results['changed'] = False s = NaServer(cluster, 1, 15) s.set_server_type("FILER") s.set_transport_type("HTTPS") s.set_port(443) s.set_style("LOGIN") s.set_admin_user(user_name, password) s.set_vserver(vserver) api = NaElement("volume-create") api.child_add_string("volume", volume) if module.params['aggregate']: api.child_add_string("containing-aggr-name", aggregate) if module.params['size']: api.child_add_string("size", size) if module.params['state']: api.child_add_string("volume-state", state) if module.params['type']: api.child_add_string("volume-type", type) if module.params['policy']: api.child_add_string("export-policy", policy) if module.params['percentage_snapshot_reserve']: api.child_add_string("percentage-snapshot-reserve", percentage_snapshot_reserve) if module.params['junction_path']: api.child_add_string("junction-path", junction_path) if module.params['snapshot_policy']: api.child_add_string("snapshot-policy", snapshot_policy) if module.params['space_reserve']: api.child_add_string("space-reserve", space_reserve) xo = s.invoke_elem(api) if (xo.results_errno() != 0): r = xo.results_reason() module.fail_json(msg=r) results['changed'] = False else: results['changed'] = True return results
def cluster_setup(cluster): print("> " + cluster["cluster-name"] + ": Creating Cluster ") for node in cluster["cluster-nodes"]: print("---> " + node["node-name"] + ": Working on node ") session = NaServer(node["ip"], 1, 140) session.set_server_type("Filer") session.set_admin_user(node["user"], node["password"]) session.set_transport_type("HTTPS") # STEP: Create cluster if("-01" in node["node-name"]): print("---> " + node["node-name"] + ": Creating cluster...") zapi_post = NaElement("cluster-create") zapi_post.child_add_string("cluster-name", cluster["cluster-name"]) if len(cluster["cluster-nodes"]) > 1: zapi_post.child_add_string("single-node-cluster", "false") else: zapi_post.child_add_string("single-node-cluster", "true") zapi_post_return = session.invoke_elem(zapi_post) if(zapi_post_return.results_status() == "failed"): print("--- " + node["node-name"] + ": " + zapi_post.sprintf().strip()) print("--- " + node["node-name"] + ": " + zapi_post_return.sprintf().strip()) sys.exit(1) else: zapi_get = NaElement("cluster-create-join-progress-get") is_complete = "" create_iterator = 1 while is_complete != "true" and \ create_iterator < 13: time.sleep(10) zapi_get_return = session.invoke_elem(zapi_get) is_complete = zapi_get_return.child_get("attributes").child_get("cluster-create-join-progress-info").child_get_string("is-complete") action_status = zapi_get_return.child_get("attributes").child_get("cluster-create-join-progress-info").child_get_string("status") create_iterator = create_iterator + 1 if(is_complete == "true") and (action_status == "success"): print("---> " + node["node-name"] + ": SUCCESS") else: print("---> " + node["node-name"] + ": " + zapi_get.sprintf().strip()) print("---> " + node["node-name"] + ": " + zapi_get_return.sprintf().strip()) sys.exit(1) # STEP: Create cluster management LIF if("-01" in node["node-name"]): print("--- " + node["node-name"] + ": Creating cluster management LIF...") found = False for lif in cluster["net-interfaces"]: if lif["role"] == "cluster-mgmt": found = True zapi_post = NaElement("net-interface-create") zapi_post.child_add_string("vserver", cluster["cluster-name"]) for k, v in lif.items(): zapi_post.child_add_string(k, v) break if found: zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print("---> " + node["node-name"] + ": " + zapi_post.sprintf().strip()) print("---> " + node["node-name"] + ": " + zapi_post_return.sprintf().strip()) else: print("---> " + node["node-name"] + ": SUCCESS") # STEP: Remove existing cluster LIFs print("---> " + node["node-name"] + ": Removing existing cluster LIFs...") zapi_get = NaElement("net-interface-get-iter") elementQuery = NaElement("query") elementInterfaces = NaElement("net-interface-info") elementInterfaces.child_add_string("role", "cluster") elementQuery.child_add(elementInterfaces) zapi_get.child_add(elementQuery) zapi_get_return = session.invoke_elem(zapi_get) if (zapi_get_return.results_status() == "failed"): print("---> " + node["node-name"] + ": " + zapi_get.sprintf().strip()) print("---> " + node["node-name"] + ": " + zapi_get_return.sprintf()) else: if(int(zapi_get_return.child_get_string("num-records")) > 0): for lif in zapi_get_return.child_get("attributes-list").children_get(): print(" --- " + node["node-name"] + ": Deleting " + lif.child_get_string("interface-name") + "...") zapi_post = NaElement("net-interface-delete") zapi_post.child_add_string("vserver", "Cluster") zapi_post.child_add_string("interface-name", lif.child_get_string("interface-name")) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + node["node-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + node["node-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + node["node-name"] + ": SUCCESS") else: print("---> " + node["node-name"] + ": Nothing to delete") # STEP: Modifying port configuration print("--- " + node["node-name"] + ": Modifying network ports...") zapi_get = NaElement("net-port-get-iter") zapi_get_return = session.invoke_elem(zapi_get) if(int(zapi_get_return.child_get_string("num-records")) > 1): for port in zapi_get_return.child_get("attributes-list").children_get(): if port.child_get_string("port") != "e0M": # Remove from broadcast domain if(port.child_get_string("node") != "localhost"): print(" --- " + node["node-name"] + ": Removing " + port.child_get_string("port") + " from broadcast domain...") if not port.child_get_string("broadcast-domain") is None: zapi_post = NaElement("net-port-broadcast-domain-remove-ports") elementPorts = NaElement("ports") elementPorts.child_add_string("net-qualified-port-name", port.child_get_string("node") + ":" + port.child_get_string("port")) zapi_post.child_add_string("ipspace", port.child_get_string("ipspace")) zapi_post.child_add_string("broadcast-domain", port.child_get_string("broadcast-domain")) zapi_post.child_add(elementPorts) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + node["node-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + node["node-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + node["node-name"] + ": SUCCESS") else: print(" ---> " + node["node-name"] + ": Skipping (port has no broadcast domain assigned") # Modify port print(" --- " + node["node-name"] + ": Modifying " + port.child_get_string("port") + "...") zapi_post = NaElement("net-port-modify") for params in node["net-ports"]: if params["port"] == port.child_get_string("port"): zapi_post.child_add_string("port", params["port"]) zapi_post.child_add_string("node", port.child_get_string("node")) zapi_post.child_add_string("is-administrative-auto-negotiate", params["is-administrative-auto-negotiate"]) zapi_post.child_add_string("administrative-duplex", params["administrative-duplex"]) zapi_post.child_add_string("administrative-speed", params["administrative-speed"]) zapi_post.child_add_string("administrative-flowcontrol", params["administrative-flowcontrol"]) zapi_post.child_add_string("is-administrative-up", "true") if port.child_get_string("node") == "localhost": zapi_post.child_add_string("mtu", params["mtu"]) zapi_post.child_add_string("role", params["role"]) zapi_post.child_add_string("ipspace", params["ipspace"]) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + node["node-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + node["node-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + node["node-name"] + ": SUCCESS") # Add to broadcast domain if(port.child_get_string("node") != "localhost"): for params in node["net-ports"]: if params["port"] == port.child_get_string("port"): print(" --- Adding " + port.child_get_string("port") + " to broadcast domain 'Cluster'...") if(params["broadcast-domain"] == "Cluster"): zapi_post = NaElement("net-port-broadcast-domain-add-ports") elementPorts = NaElement("ports") elementPorts.child_add_string("net-qualified-port-name", node["node-name"] + ":" + params["port"]) zapi_post.child_add_string("ipspace", params["ipspace"]) zapi_post.child_add_string("broadcast-domain", params["broadcast-domain"]) zapi_post.child_add(elementPorts) zapi_post_return = session.invoke_elem(zapi_post) if(zapi_post_return.results_status() == "failed"): print(" ---> " + node["node-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + node["node-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + node["node-name"] + ": SUCCESS") else: print(" ---> " + node["node-name"] + ": Skipping (port is not a cluster port)") time.sleep(15) # STEP: Create new cluster LIFs print("--- " + node["node-name"] + ": Creating cluster LIFs...") zapi_get = NaElement("net-port-get-iter") elementQuery = NaElement("query") elementPorts = NaElement("net-port-info") elementPorts.child_add_string("ipspace", "Cluster") elementQuery.child_add(elementPorts) zapi_get.child_add(elementQuery) zapi_get_return = session.invoke_elem(zapi_get) if(int(zapi_get_return.child_get_string("num-records")) > 0): lif_iterator = 1 lif_count = int(zapi_get_return.child_get_string("num-records")) while lif_iterator < lif_count + 1: print(" --- " + node["node-name"] + ": Creating cluster LIF #" + str(lif_iterator) + "...") zapi_post = NaElement("net-interface-create") zapi_post.child_add_string("vserver", "Cluster") zapi_post.child_add_string("interface-name", "clus" + str(lif_iterator)) zapi_post.child_add_string("role", "Cluster") zapi_post.child_add_string("home-node", zapi_get_return.child_get("attributes-list").children_get()[lif_iterator - 1].child_get_string("node")) zapi_post.child_add_string("home-port", zapi_get_return.child_get("attributes-list").children_get()[lif_iterator - 1].child_get_string("port")) zapi_post.child_add_string("is-ipv4-link-local", "true") zapi_post_return = session.invoke_elem(zapi_post) if(zapi_post_return.results_status() == "failed"): print(" ---> " + node["node-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + node["node-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + node["node-name"] + ": SUCCESS") lif_iterator = lif_iterator + 1 else: print("---> " + node["node-name"] + ": No ports found to create LIFs on!") # STEP: Reading cluster LIF IP for joining additional nodes later if("-01" in node["node-name"]): print("--- " + node["node-name"] + ": Reading cluster LIF IP for joining further nodes later...") clus_lif_ip = "" zapi_get = NaElement("net-interface-get-iter") elementQuery = NaElement("query") elementInterface = NaElement("net-interface-info") elementInterface.child_add_string("vserver", "Cluster") elementQuery.child_add(elementInterface) zapi_get.child_add_string("max-records", 1) zapi_get.child_add(elementQuery) zapi_get_return = session.invoke_elem(zapi_get) if(zapi_get_return.results_status() == "failed"): print("---> " + node["node-name"] + ": " + zapi_get.sprintf().strip()) print("---> " + node["node-name"] + ": " + zapi_get_return.sprintf().strip()) else: if(int(zapi_get_return.child_get_string("num-records")) == 0): print("---> " + node["node-name"] + ": No LIFs found") else: clus_lif_ip = zapi_get_return.child_get("attributes-list").child_get("net-interface-info").child_get_string("address") print("---> " + node["node-name"] + ": SUCCESS") # STEP: Join nodes to cluster if(not "-01" in node["node-name"]): print("--- " + node["node-name"] + ": Joining node to cluster...") zapi_post = NaElement("cluster-join") zapi_post.child_add_string("cluster-ip-address", clus_lif_ip) zapi_post_return = session.invoke_elem(zapi_post) if(zapi_post_return.results_status() == "failed"): print("---> " + node["node-name"] + ": " + zapi_post_return.sprintf().strip()) sys.exit(1) else: zapi_get = NaElement("cluster-create-join-progress-get") is_complete = "" join_iterator = 1 while is_complete != "true" and \ join_iterator < 13: time.sleep(10) zapi_get_return = session.invoke_elem(zapi_get) is_complete = zapi_get_return.child_get("attributes").child_get("cluster-create-join-progress-info").child_get_string("is-complete") action_status = zapi_get_return.child_get("attributes").child_get("cluster-create-join-progress-info").child_get_string("status") join_iterator = join_iterator + 1 if(is_complete == "true") and (action_status == "success"): print("---> " + node["node-name"] + ": SUCCESS") else: print("---> " + node["node-name"] + ": " + zapi_get.sprintf().strip()) print("---> " + node["node-name"] + ": " + zapi_get_return.sprintf().strip()) sys.exit(1) print("> " + cluster["cluster-name"] + ": Configuring Cluster") session = NaServer(cluster["ip"], 1, 140) session.set_server_type("Filer") session.set_admin_user(cluster["user"], cluster["password"]) session.set_transport_type("HTTPS") # STEP: Correcting network ports print("--- " + cluster["cluster-name"] + ": Cleaning port configuration...") zapi_get = NaElement("net-port-get-iter") zapi_get_return = session.invoke_elem(zapi_get) if(int(zapi_get_return.child_get_string("num-records")) > 0): for port in zapi_get_return.child_get("attributes-list").children_get(): if(port.child_get_string("ipspace") != "Cluster") and \ (port.child_get_string("port") != "e0M") and \ (not port.child_get_string("broadcast-domain") is None): # Remove from broadcast domain print(" --- " + cluster["cluster-name"] + ": Removing " + port.child_get_string("port") + " from broadcast domain...") zapi_post = NaElement("net-port-broadcast-domain-remove-ports") elementPorts = NaElement("ports") elementPorts.child_add_string("net-qualified-port-name", port.child_get_string("node") + ":" + port.child_get_string("port")) zapi_post.child_add_string("ipspace", port.child_get_string("ipspace")) zapi_post.child_add_string("broadcast-domain", port.child_get_string("broadcast-domain")) zapi_post.child_add(elementPorts) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Create IPspaces print("--- " + cluster["cluster-name"] + ": Creating IPspaces...") for ipspace in cluster["net-ipspaces"]: print(" --- " + cluster["cluster-name"] + ": Creating IPspace " + ipspace["ipspace"]) zapi_post = NaElement("net-ipspaces-create") for k, v in ipspace.items(): zapi_post.child_add_string(k, v) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Create VLANs print("--- " + cluster["cluster-name"] + ": Creating VLANs...") for node in cluster["cluster-nodes"]: for port in node["net-ports"]: if "-" in port["port"]: print(" --- " + cluster["cluster-name"] + ": Creating VLAN " + port["port"] + " on node " + node["node-name"]) zapi_post = NaElement("net-vlan-create") elementVLAN = NaElement("vlan-info") elementVLAN.child_add_string("node", node["node-name"]) elementVLAN.child_add_string("parent-interface", port["port"].split("-")[0]) elementVLAN.child_add_string("vlanid", port["port"].split("-")[1]) zapi_post.child_add(elementVLAN) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Create broadcast domains print("--- " + cluster["cluster-name"] + ": Creating broadcast domains...") for bcdomain in cluster["net-port-broadcast-domains"]: print(" --- " + cluster["cluster-name"] + ": Creating broadcast domain " + bcdomain["broadcast-domain"]) zapi_post = NaElement("net-port-broadcast-domain-create") for k, v in bcdomain.items(): zapi_post.child_add_string(k, v) elementPorts = NaElement("ports") for node in cluster["cluster-nodes"]: for port in node["net-ports"]: if(port["ipspace"] != "Cluster") and \ (port["port"] != "e0M") and \ (bcdomain["broadcast-domain"] == port["broadcast-domain"]): print(" --- " + cluster["cluster-name"] + ": adding " + port["port"] + " on node " + node["node-name"]) elementPorts.child_add_string("net-qualified-port-name", node["node-name"] + ":" + port["port"]) if(len(elementPorts.children_get()) > 0): zapi_post.child_add(elementPorts) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Set options print("--- " + cluster["cluster-name"] + ": Setting options...") for k, v in cluster["options"].items(): print(" --- " + cluster["cluster-name"] + ": modifying " + k) zapi_post = NaElement("options-modify-iter") elementAttributes = NaElement("attributes") elementAttributesInfo = NaElement("option-info") elementAttributesInfo.child_add_string("value", v) elementQuery = NaElement("query") elementQueryInfo = NaElement("option-info") elementQueryInfo.child_add_string("name", k) elementAttributes.child_add(elementAttributesInfo) elementQuery.child_add(elementQueryInfo) zapi_post.child_add(elementQuery) zapi_post.child_add(elementAttributes) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Set network options print("--- " + cluster["cluster-name"] + ": Setting network options...") zapi_post = NaElement("net-options-modify") elementNetOptions = NaElement("net-options") for option in cluster["net-options"]: print(" --- " + cluster["cluster-name"] + ": adding " + option) elementOption = NaElement(option) for k, v in cluster["net-options"][option].items(): elementOption.child_add_string(k, v) elementNetOptions.child_add(elementOption) zapi_post.child_add(elementNetOptions) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Create DNS session.set_vserver(cluster["cluster-name"]) print("--- " + cluster["cluster-name"] + ": Creating DNS...") zapi_post = NaElement("net-dns-create") elementDomains = NaElement("domains") for domain in cluster["net-dns"]["domains"]["string"]: elementDomains.child_add_string("string", domain) elementServers = NaElement("name-servers") for dnsserver in cluster["net-dns"]["name-servers"]["ip-address"]: elementServers.child_add_string("ip-address", dnsserver) zapi_post.child_add(elementDomains) zapi_post.child_add(elementServers) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print("---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print("---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print("---> " + cluster["cluster-name"] + ": SUCCESS") session.set_vserver("") # STEP: Create NTP print("--- " + cluster["cluster-name"] + ": Creating NTP...") for timeserver in cluster["ntp-servers"]: zapi_post = NaElement("ntp-server-create") for k, v in timeserver.items(): zapi_post.child_add_string(k, v) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print("---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print("---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print("---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Set timezone print("--- " + cluster["cluster-name"] + ": Setting timezone...") zapi_post = NaElement("system-cli") elementArgs = NaElement("args") elementArgs.child_add_string("arg", "timezone " + cluster["timezone"]) zapi_post.child_add_string("priv", "admin") zapi_post.child_add(elementArgs) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print("---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print("---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print("---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Create LIFs print("--- " + cluster["cluster-name"] + ": Creating LIFs...") for lif in cluster["net-interfaces"]: if(lif["role"] != "cluster-mgmt"): print(" --- " + cluster["cluster-name"] + ": Creating " + lif["interface-name"]) zapi_post = NaElement("net-interface-create") for k, v in lif.items(): zapi_post.child_add_string(k, v) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Install licenses print("--- " + cluster["cluster-name"] + ": Adding Licenses...") zapi_post = NaElement("license-v2-add") elementCodes = NaElement("codes") for k, v in cluster["licenses"].items(): print(" --- " + cluster["cluster-name"] + ": Adding " + k) elementCodes.child_add_string("license-code-v2", v) zapi_post.child_add(elementCodes) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print("---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print("---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print("---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Create subnets print("--- " + cluster["cluster-name"] + ": Creating subnets...") for subnet in cluster["net-subnets"]: print(" --- Creating subnet " + subnet["subnet-name"]) zapi_post = NaElement("net-subnet-create") elementIPRanges = NaElement("ip-ranges") for k, v in subnet.items(): if(k == "ip-ranges"): for range in v["ip-range"]: elementIPRanges.child_add_string("ip-range", range) else: zapi_post.child_add_string(k, v) zapi_post.child_add(elementIPRanges) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Create aggrs print("--- " + cluster["cluster-name"] + ": Creating aggregates...") for node in cluster["cluster-nodes"]: for aggregate in node["aggregates"]: print(" --- " + cluster["cluster-name"] + ": Creating aggregates " + aggregate["aggregate"]) zapi_post = NaElement("aggr-create") elementNodes = NaElement("nodes") for k, v in aggregate.items(): if(k == "nodes"): for nodename in v["node-name"]: if(nodename == ""): elementNodes.child_add_string("node-name", node["node-name"]) else: elementNodes.child_add_string("node-name", nodename) else: zapi_post.child_add_string(k, v) zapi_post.child_add(elementNodes) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + cluster["cluster-name"] + ": SUCCESS") #STEP: Disable ASUP print("--- " + cluster["cluster-name"] + ": Configuring Autosupport...") for node in cluster["cluster-nodes"]: print(" --- " + cluster["cluster-name"] + ": ASUP on node " + node["node-name"]) zapi_post = NaElement("autosupport-config-modify") zapi_post.child_add_string("node-name", node["node-name"]) for k, v in cluster["autosupport"].items(): zapi_post.child_add_string(k, v) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print(" ---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print(" ---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print(" ---> " + cluster["cluster-name"] + ": SUCCESS") #STEP: Allow ssh access for user 'admin' print("--- " + cluster["cluster-name"] + ": Allowing admin ssh access...") zapi_post = NaElement("security-login-create") zapi_post.child_add_string("vserver", cluster["cluster-name"]) zapi_post.child_add_string("user-name", "admin") zapi_post.child_add_string("application", "ssh") zapi_post.child_add_string("authentication-method", "password") zapi_post.child_add_string("role-name", "admin") zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print("---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print("---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print("---> " + cluster["cluster-name"] + ": SUCCESS") # STEP: Set special options # NOTE: The session might be closed by the ONTAP, if the option value is really changed (interrupts HTTP(S) traffic) try: print("--- " + cluster["cluster-name"] + ": Enabling HTTP...") zapi_post = NaElement("system-cli") elementArgs = NaElement("args") elementArgs.child_add_string("arg", "system services web modify -http-enabled true") zapi_post.child_add_string("priv", "advanced") zapi_post.child_add(elementArgs) zapi_post_return = session.invoke_elem(zapi_post) if (zapi_post_return.results_status() == "failed"): print("---> " + cluster["cluster-name"] + ": " + zapi_post.sprintf().strip()) print("---> " + cluster["cluster-name"] + ": " + zapi_post_return.sprintf().strip()) else: print("---> " + cluster["cluster-name"] + ": SUCCESS") except: print("---> " + cluster["cluster-name"] + ": I have modified the branch I am currently sitting on... Session gone ;-)") print("---> " + cluster["cluster-name"] + ": Waiting for 10 seconds...") # making sure, cluster recovers from HTTP(S) modification time.sleep(10)
def ntap_get_share_list(ntap_host, protocol, svm_list, config): share_list = {} dprint("SVM_LIST2: " + str(svm_list)) # Set up NetApp API session try: _create_unverified_https_context = ssl._create_unverified_context except AttributeError: pass else: ssl._create_default_https_context = _create_unverified_https_context netapp = NaServer(ntap_host, 1, 130) out = netapp.set_transport_type('HTTPS') ntap_set_err_check(out) out = netapp.set_style('LOGIN') ntap_set_err_check(out) out = netapp.set_admin_user(config['array_user'], config['array_password']) ntap_set_err_check(out) # For each SVM, grab the NFS exports of SMB shares. Generate the share_list structure for main() for svm in svm_list.keys(): svm_share_list = [] junct_point = {} out = netapp.set_vserver(svm) share_host = get_host_from_svm_list(svm_list[svm], protocol) if protocol == "nfs": api = NaElement('volume-get-iter') l1 = NaElement('desired-attributes') api.child_add(l1) l2 = NaElement('volume-attributes') l1.child_add(l2) l2_1 = NaElement('volume-id-attributes') l2.child_add(l2_1) l2_1.child_add_string('name', '<name>') l2_1.child_add_string('junction-path', '<junction-path>') l2_2 = NaElement('volume-state-attributes') l2.child_add(l2_2) l2_2.child_add_string('is-node-root', '<is-node-root>') l2_2.child_add_string('is-vserver-root', '<is-vserver-root') api.child_add_string('max-records', 5000) result = netapp.invoke_elem(api) ntap_invoke_err_check(result) vol_attrs = result.child_get('attributes-list').children_get() for v in vol_attrs: vid_attrs = v.child_get('volume-id-attributes') vst_attrs = v.child_get('volume-state-attributes') node_root = vst_attrs.child_get_string('is-node-root') svm_root = vst_attrs.child_get_string('is-vserver-root') if node_root == "false" and svm_root == "false": volume = vid_attrs.child_get_string('name') print("FOUND VOL: " + volume) junction = vid_attrs.child_get_string('junction-path') junct_point[volume] = junction dprint("JUNCTION_POINTS for " + svm + ": " + str(junct_point)) api = NaElement('qtree-list-iter') l1 = NaElement('desired-attributes') api.child_add(l1) l2 = NaElement('qtree-info') l1.child_add(l2) l2.child_add_string('qtree', '<qtree>') l2.child_add_string('volume', '<volume>') api.child_add_string('max-records', 5000) result = netapp.invoke_elem(api) ntap_invoke_err_check(result) qt_attrs = result.child_get('attributes-list').children_get() for qt in qt_attrs: volume = qt.child_get_string('volume') qtree = qt.child_get_string('qtree') if qtree == "": try: vol_j = junct_point[volume] except KeyError: print("KEY_ERROR") continue else: vol_j = junct_point[volume] + "/" + qtree if vol_j != "/" and type(vol_j) is unicode: svm_share_list.append(vol_j + ":" + vol_j) elif protocol == "cifs" or protocol == "smb": result = netapp.invoke('cifs-share-get-iter') ntap_invoke_err_check(result) try: attr = result.child_get('attributes-list').children_get() except AttributeError: continue for sh in attr: path = sh.child_get_string('path') sh_name = sh.child_get_string('share-name') if path == "/": # Exclude root volumes continue svm_share_list.append(sh_name + ":" + path) share_list[share_host] = svm_share_list if config['purge_overlaps'] != "false": dprint("SHARE_LIST: " + str(share_list)) purge_overlapping_shares(share_list, config['purge_overlaps']) return (share_list)
def ntap_get_svm_list(host, protocol, config): addr = "" hostname = {} host_lookup = () share_list = {} host_list = {} # Set up NetApp API session try: _create_unverified_https_context = ssl._create_unverified_context except AttributeError: pass else: ssl._create_default_https_context = _create_unverified_https_context netapp = NaServer(host, 1, 130) out = netapp.set_transport_type('HTTPS') ntap_set_err_check(out) out = netapp.set_style('LOGIN') ntap_set_err_check(out) out = netapp.set_admin_user(config['array_user'], config['array_password']) ntap_set_err_check(out) # Get list of SVMs from NetApp if svm_list == {}: result = netapp.invoke('vserver-get-iter') ntap_invoke_err_check(result) vs_info = result.child_get('attributes-list').children_get() for vs in vs_info: vs_type = vs.child_get_string("vserver-type") if vs_type == "data": svm_list[vs.child_get_string('vserver-name')] = "" # Get list of interfaces on the NetApp. Find the an applicable interface, grab the IP, # then try to get a hostname from it via DNS for svm in svm_list.keys(): int_list = [] netapp.set_vserver(svm) result = netapp.invoke('net-interface-get-iter') ntap_invoke_err_check(result) try: ints = result.child_get('attributes-list').children_get() except AttributeError: continue for i in ints: int_name = i.child_get_string('interface-name') protocols = i.child_get('data-protocols').children_get() addr = i.child_get_string('address') try: host_lookup = socket.gethostbyaddr(addr) addr = host_lookup[0] except socket.herror: pass # Couldn't figure out how to pull the protocols properly, nasty hack. Should clean up later proto_list = [] for p in protocols: proto = p.sprintf() proto = proto.replace('<', '>') pf = proto.split('>') proto_list.append(pf[2]) int_list.append({'address': addr, "protocols": proto_list}) cand_list = [] for int_cand in int_list: if protocol == "nfs,cifs": if int_cand['protocols'] == ['nfs', 'cifs']: cand_list = [int_cand] break elif int_cand['protocols'] == ["nfs"]: cand_list.append(int_cand) elif int_cand['protocols'] == ["cifs"]: cand_list.append(int_cand) elif protocol == "nfs": if int_cand['protocols'] == ["nfs"]: cand_list = [int_cand] break elif int_cand['protocols'] == ["nfs,cifs"]: cand_list.append(int_cand) elif protocol == "cifs": if int_cand['protocols'] == ["cifs"]: cand_list = [int_cand] break elif int_cand['protocols'] == ["nfs", "cifs"]: cand_list.append(int_cand) host_list[svm] = cand_list return (host_list)