/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.networkcontroller.impl.mds;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.cim.CIMArgument;
import javax.cim.CIMInstance;
import javax.cim.CIMObjectPath;
import javax.cim.CIMProperty;
import javax.cim.UnsignedInteger32;
import javax.security.auth.Subject;
import javax.wbem.CloseableIterator;
import javax.wbem.WBEMException;
import javax.wbem.client.PasswordCredential;
import javax.wbem.client.UserPrincipal;
import javax.wbem.client.WBEMClient;
import javax.wbem.client.WBEMClientConstants;
import javax.wbem.client.WBEMClientFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.cimadapter.connections.cim.CimObjectPathCreator;
import com.emc.storageos.db.client.model.FCEndpoint;
import com.emc.storageos.exceptions.DeviceControllerException;
import com.emc.storageos.networkcontroller.BaseSANCIMObject;
import com.emc.storageos.networkcontroller.exceptions.NetworkControllerSessionLockedException;
import com.emc.storageos.volumecontroller.ControllerException;
import com.emc.storageos.volumecontroller.impl.smis.CIMArgumentFactory;
public class DCNMDialog extends BaseSANCIMObject {
private static final String _namespace = "cimv2";
private static final String _fabric_path = "CISCO_AdminDomain";
private final String _wwnRegex = "([0-9A-Fa-f][0-9A-Fa-f]){8}";
private static final int _started = 2;
private static final int _ended = 3;
private static final int _notApplicable = 4;
private static final int _terminated = 4;
private static final int _noChange = 5;
private CIMArgumentFactory _cimArgumentFactory = new CIMArgumentFactory();
private static final Logger _log = LoggerFactory.getLogger(DCNMDialog.class);
WBEMClient _client = null;
/**
* Initialize the client interface.
*
* @param ipaddress
* @param username
* @param password
* @param smisport
* @return WBEMClient
*/
public WBEMClient getClient(String ipaddress, String username, String password, Integer smisport) {
try {
WBEMClient client = WBEMClientFactory.getClient(WBEMClientConstants.PROTOCOL_CIMXML);
CIMObjectPath path = CimObjectPathCreator.createInstance("http", ipaddress, smisport.toString(), _namespace, null, null);
final Subject subject = new Subject();
subject.getPrincipals().add(new UserPrincipal(username));
subject.getPrivateCredentials().add(new PasswordCredential(password));
client.initialize(path, subject, new Locale[] { Locale.US });
_client = client;
return client;
} catch (WBEMException ex) {
_log.error("Can't open client: WBEMException: " + ex.getLocalizedMessage());
return null;
}
}
public class FCProtocolEndpoint {
String wwpn;
String wwnn;
Interface iface; // interface implementing this endpoint
CIMObjectPath cimPath;
Map<String, FCProtocolEndpoint> connections = new HashMap<String, FCProtocolEndpoint>(); // key is wwpn
FCProtocolEndpoint(CIMInstance ins) {
// DCNM has a wierd format: Name = "200000059B1F06D0\\16846848\\1"
wwpn = cimStringProperty(ins, "Name").replaceAll("\\\\.*$", "");
wwnn = cimStringProperty(ins, "SystemName");
if (wwnn.matches(_wwnRegex) == false) {
wwnn = "";
}
String ifName = null;
iface = Interface.snToInterface.get(wwpn);
cimPath = ins.getObjectPath();
}
/**
* Find connections to this endpoint. Put them in the connections map.
*
* @param client WBEMClient
* @param namespace CIM namespace
*/
void findConnections(WBEMClient client, String namespace) {
CloseableIterator<CIMInstance> instances = null;
try {
connections.clear();
instances = client.associatorInstances(cimPath,
// "CISCO_ActiveConnection", "CISCO_ProtocolEndpoint", null, null, false, false, null);
// "CISCO_ActiveConnection", null, null, null, false, false, null);
null, "CISCO_ProtocolEndpoint", null, null, false, null);
while (instances.hasNext()) {
CIMInstance instance = instances.next();
// Must be of type FC WWPN
if (!instance.getProperty("ProtocolIFType").getValue().toString().equals("56")) {
continue;
}
FCProtocolEndpoint ep = new FCProtocolEndpoint(instance);
this.connections.put(ep.wwpn, ep);
}
} catch (WBEMException ex) {
_log.error("Can't find FCProtocolEndpoint connections: ", ex);
} finally {
if (instances != null) {
instances.close();
}
}
}
};
/**
* Given an instance of a CISCO_LogicalFCPort, get the system name housing this port.
*
* @param lportIns
* @return system name String
* @throws Exception
*/
private String getSystemNameFromLogicalPort(CIMInstance lportIns) throws Exception {
String systemName = null;
CloseableIterator<CIMInstance> fcportIt = null;
CloseableIterator<CIMInstance> physcomputerIt = null;
try {
fcportIt = _client.associatorInstances(lportIns
.getObjectPath(),
null, "CISCO_FCPort", null, null, false, null);
while (fcportIt.hasNext()) {
CIMInstance fcportIns = fcportIt.next();
physcomputerIt = _client.associatorInstances(fcportIns.getObjectPath(),
null, "CISCO_PhysicalComputerSystem", null, null, false, null);
while (physcomputerIt.hasNext()) {
CIMInstance physins = physcomputerIt.next();
systemName = cimStringProperty(physins, "ElementName");
}
physcomputerIt.close();
physcomputerIt = null;
}
} finally {
if (fcportIt != null) {
fcportIt.close();
}
if (physcomputerIt != null) {
physcomputerIt.close();
}
}
return systemName;
}
List<FCEndpoint> getPortConnection() throws Exception {
List<FCEndpoint> connections = new ArrayList<FCEndpoint>();
CIMObjectPath path = CimObjectPathCreator.createInstance("CISCO_LogicalComputerSystem", _namespace);
CloseableIterator<CIMInstance> lcsIt = null;
CloseableIterator<CIMInstance> lportIt = null;
CloseableIterator<CIMInstance> pepIt = null;
try {
lcsIt = _client.enumerateInstances(path, false, true, true, null);
while (lcsIt.hasNext()) {
CIMInstance lcsIns = lcsIt.next();
// Get the VSAN of this Logical COmputer System
String fabricId = null;
String[] identifyingDescriptions = (String[]) lcsIns.getProperty("IdentifyingDescriptions").getValue();
String[] otherIdentifyingInfo = (String[]) lcsIns.getProperty("OtherIdentifyingInfo").getValue();
if (identifyingDescriptions.length >= 2 && identifyingDescriptions[1].equals("VsanId")
&& otherIdentifyingInfo.length >= 2) {
fabricId = otherIdentifyingInfo[1];
}
// Find the associated CISCO_LogicalFCPort structures
lportIt = _client.associatorInstances(lcsIns.getObjectPath(),
"CISCO_FCPortsInLogicalComputerSystem", "CISCO_LogicalFCPort", null, null, false, null);
// Iterate through all the ports in this Vsan, finding connections.
while (lportIt.hasNext()) {
CIMInstance lportIns = lportIt.next();
_log.debug("logical port: " + cimStringProperty(lportIns, "Name") + " wwpn "
+ cimStringProperty(lportIns, "PermanentAddress"));
String systemName = getSystemNameFromLogicalPort(lportIns);
pepIt = _client.associatorInstances(lportIns.getObjectPath(),
"CISCO_FCPortSAPImplementation", "CISCO_ProtocolEndPoint", null, null, false, null);
while (pepIt.hasNext()) {
CIMInstance pepIns = pepIt.next();
_log.debug("endpoint: " + cimStringProperty(pepIns, "Name"));
FCProtocolEndpoint pep = new FCProtocolEndpoint(pepIns);
pep.findConnections(_client, _namespace);
for (String key : pep.connections.keySet()) {
_log.debug("connection: " + key);
FCProtocolEndpoint cep = pep.connections.get(key);
FCEndpoint conn = new FCEndpoint();
// conn.setFabricId(fabricId)
conn.setRemotePortName(formatWWN(cep.wwpn));
conn.setLabel(conn.getRemotePortName());
conn.setRemoteNodeName(formatWWN(cep.wwnn));
conn.setSwitchPortName(formatWWN(cimStringProperty(lportIns, "PermanentAddress")));
conn.setSwitchInterface(cimStringProperty(lportIns, "Name"));
conn.setFabricId(fabricId);
conn.setSwitchName(systemName);
connections.add(conn);
}
}
pepIt.close();
pepIt = null;
}
lportIt.close();
lportIt = null;
}
} finally {
if (lcsIt != null) {
lcsIt.close();
}
if (lportIt != null) {
lportIt.close();
}
if (pepIt != null) {
pepIt.close();
}
}
return connections;
}
/**
* Get the list of Vsan Ids.
*
* @return List<String>
* @throws Exception
*/
public List<String> getFabricIds() throws Exception {
// A set is used because in the case of a disconnected network the same Vsan can
// show up twice. Conerted to list at end.
Set<String> fabricIds = new HashSet<String>();
List<Zoneset> zonesets = new ArrayList<Zoneset>();
CIMObjectPath path = CimObjectPathCreator.createInstance("Cisco_Vsan", _namespace);
CloseableIterator<CIMInstance> vsanIt = null;
try {
vsanIt = _client.enumerateInstances(path, false, true, true, null);
while (vsanIt.hasNext()) {
String vsanId = null;
CIMInstance vsanIns = vsanIt.next();
CIMProperty prop = vsanIns.getProperty("OtherIdentifyingInfo");
String[] idinfoValue = (String[]) prop.getValue();
if (idinfoValue.length == 2 && idinfoValue[0].equals("Fabric")) {
vsanId = idinfoValue[1];
}
if (vsanId != null) {
fabricIds.add(vsanId);
}
}
} finally {
if (vsanIt != null) {
vsanIt.close();
}
}
List<String> alist = new ArrayList<String>();
alist.addAll(fabricIds);
return alist;
}
/**
* Make ZoneMember from ZoneMemberSettingData instance
*
* @param membershipInstance
* @return ZoneMember
* @throws WBEMException
*/
private ZoneMember makeZoneMember(CIMInstance membershipInstance) throws WBEMException {
String address = cimStringProperty(membershipInstance, "ConnectivityMemberID");
ZoneMember.ConnectivityMemberType type =
ZoneMember.ConnectivityMemberType.byValue(cimIntegerProperty(membershipInstance,
"ConnectivityMemberType"));
ZoneMember zm = new ZoneMember(address, type);
zm.setInstanceID(cimStringProperty(membershipInstance, "InstanceID"));
zm.setCimObjectPath(membershipInstance.getObjectPath());
return zm;
}
/**
* Make a Zone structure from a CIMInstance.
*
* @param zoneInstance
* @return Zone
*/
private Zone makeZone(CIMInstance zoneInstance) throws WBEMException {
String name = cimStringProperty(zoneInstance, "ElementName");
Zone zn = new Zone(name);
zn.setCimObjectPath(zoneInstance.getObjectPath());
zn.setInstanceID(cimStringProperty(zoneInstance, "InstanceID"));
zn.setActive(cimBooleanProperty(zoneInstance, "Active"));
CloseableIterator<CIMInstance> zms = null;
try {
zms = _client.associatorInstances(((CIMObjectPath) zn.getCimObjectPath()),
"CISCO_ElementSettingData", "CISCO_ZoneMemberSettingData", null,
null, false, null);
while (zms.hasNext()) {
CIMInstance zm = zms.next();
ZoneMember member = makeZoneMember(zm);
zn.getMembers().add(member);
}
} finally {
if (zms != null) {
zms.close();
}
}
return zn;
}
/**
* Make a zoneset object from a CIMInstance for the Zoneset
* Calls makeZone().
*
* @param zonesetInstance
* @return Zoneset
*/
private Zoneset makeZoneset(CIMInstance zonesetInstance) throws WBEMException {
String name = cimStringProperty(zonesetInstance, "ElementName");
Zoneset zs = new Zoneset(name);
zs.setCimObjectPath(zonesetInstance.getObjectPath());
zs.setInstanceID(cimStringProperty(zonesetInstance, "InstanceID"));
zs.setDescription(cimStringProperty(zonesetInstance, "Description"));
zs.setActive(cimBooleanProperty(zonesetInstance, "Active"));
CloseableIterator<CIMInstance> zns = null;
try {
zns = _client.associatorInstances(((CIMObjectPath) zs.getCimObjectPath()),
"CIM_MemberOfCollection", "CISCO_Zone", null, null, false,
null);
while (zns.hasNext()) {
CIMInstance zn = zns.next();
Zone zone = makeZone(zn);
zs.getZones().add(zone);
}
} finally {
if (zns != null) {
zns.close();
}
}
return zs;
}
/**
* Returns the zonesets in a VSAN as given by its CIMInstance.
* This generates the nested objects Zone and ZoneMember in the Zonesets.
*
* @param vsanIns CIMInstance of vsan
* @return List<Zoneset>
* @throws javax.wbem.WBEMException
*/
private List<Zoneset> getZonesetsInVsan(CIMInstance vsanIns) throws WBEMException {
List<Zoneset> inactiveZonesets = new ArrayList<Zoneset>();
Zoneset activeZoneset = null;
// Iterate through the zonesets.
CloseableIterator<CIMInstance> zstIt = null;
try {
zstIt = _client.associatorInstances(vsanIns.getObjectPath(),
"CIM_HostedCollection", "CISCO_Zoneset", null, null, false, null);
while (zstIt.hasNext()) {
CIMInstance zsIns = zstIt.next();
Zoneset zs = makeZoneset(zsIns);
_log.debug("zoneset: " + zs.name);
if (zs.active == true) {
activeZoneset = zs;
} else {
inactiveZonesets.add(zs);
}
}
} catch (WBEMException ex) {
// Problem where iterator isn't returned in associators();
} finally {
if (zstIt != null) {
zstIt.close();
}
}
List<Zoneset> zonesets = new ArrayList<Zoneset>();
if (activeZoneset != null) {
zonesets.add(activeZoneset);
}
zonesets.addAll(inactiveZonesets);
return zonesets;
}
/**
* Returns the Cisco_Vsan Instance for a specified Vsan.
*
* @param desiredVsan
* @return
* @throws WBEMException
*/
private CIMInstance getVsanInstance(Integer desiredVsan) throws WBEMException {
CIMObjectPath path = CimObjectPathCreator.createInstance("Cisco_Vsan", _namespace);
CloseableIterator<CIMInstance> vsanIt = null;
try {
vsanIt = _client.enumerateInstances(path,
false, true, true, null);
while (vsanIt.hasNext()) {
CIMInstance vsanIns = null;
String vsanId = null;
vsanIns = vsanIt.next();
CIMProperty prop = vsanIns.getProperty("OtherIdentifyingInfo");
String[] idinfoValue = (String[]) prop.getValue();
if (idinfoValue.length == 2 && idinfoValue[0].equals("Fabric")) {
vsanId = idinfoValue[1];
if (desiredVsan.toString().equals(vsanId)) {
return vsanIns;
}
}
}
} finally {
if (vsanIt != null) {
vsanIt.close();
}
}
return null; // not found
}
/**
* Returns all zonesets in the desiredVsan. Active zoneset is at the front of the returned list.
* This generates the nested objects Zone and ZoneMember in the Zonesets.
*
* @param desiredVsan Integer
* @return List<Zoneset>
* @throws WBEMException
*/
public List<Zoneset> getZonesets(Integer desiredVsan) throws WBEMException {
List<Zoneset> zonesets = new ArrayList<Zoneset>();
CIMObjectPath path = CimObjectPathCreator.createInstance("Cisco_Vsan", _namespace);
CloseableIterator<CIMInstance> vsanIt = null;
try {
vsanIt = _client.enumerateInstances(path, false, true, true, null);
while (vsanIt.hasNext()) {
CIMInstance vsanIns = null;
String vsanId = null;
vsanIns = vsanIt.next();
CIMProperty prop = vsanIns.getProperty("OtherIdentifyingInfo");
String[] idinfoValue = (String[]) prop.getValue();
if (idinfoValue.length == 2 && idinfoValue[0].equals("Fabric")) {
vsanId = idinfoValue[1];
if (desiredVsan.toString().equals(vsanId)) {
List<Zoneset> znsets = getZonesetsInVsan(vsanIns);
zonesets.addAll(znsets);
}
}
}
} finally {
if (vsanIt != null) {
vsanIt.close();
}
}
return zonesets;
}
/**
* @param client
* @param zonesetService -- Instance of the ZonesetService
* @return true iff session is started
* @throws NetworkControllerSessionLockedException
* @throws WBEMException
*/
@SuppressWarnings("rawtypes")
public boolean startSession(WBEMClient client, CIMInstance zonesetService)
throws NetworkControllerSessionLockedException, WBEMException {
UnsignedInteger32 result = null;
try {
int sessionState = cimIntegerProperty(zonesetService,
"SessionState");
int RequestedSessionState = cimIntegerProperty(zonesetService,
"RequestedSessionState");
if (sessionState == _notApplicable) {
// no session control implemented by this agent
return true;
}
// if (sessionState != _ended || RequestedSessionState != _noChange) {
// _log.error("Zone session is locked by another user or agent.");
// throw new NetworkControllerSessionLockedException(
// "Zone session is locked by another user or agent.");
// }
CIMArgument[] inargs = new CIMArgument[] { _cimArgumentFactory
.uint16("RequestedSessionState", _started) };
result = (UnsignedInteger32) client.invokeMethod(
zonesetService.getObjectPath(), "SessionControl", inargs,
new CIMArgument[1]);
_log.info("Start session returned code: " + result.intValue());
return (result.intValue() == 0 || result.intValue() == 32772);
} catch (WBEMException ex) {
_log.error("Encountered an exception while trying to start a zone session."
+ ex.getLocalizedMessage());
throw ex;
}
}
/**
* End a session, commit if commit == true
*
* @param client
* @param zonesetService
* @param commit
* @return true iff worked
* @throws WBEMException
*/
@SuppressWarnings("rawtypes")
public boolean endSession(WBEMClient client, CIMInstance zonesetService,
boolean commit) throws WBEMException {
UnsignedInteger32 result = null;
try {
int sessionState = cimIntegerProperty(zonesetService,
"SessionState");
if (sessionState == _notApplicable) {
// no session control implemented by this agent
return true;
}
// if (sessionState != _started) {
// // no session control implemented by this agent
// return true;
// }
int endMode = commit ? _ended : _terminated;
CIMArgument[] inargs = new CIMArgument[] { _cimArgumentFactory
.uint16("RequestedSessionState", endMode) };
result = (UnsignedInteger32) client.invokeMethod(
zonesetService.getObjectPath(), "SessionControl", inargs,
new CIMArgument[1]);
_log.info("End session returned code: " + result.intValue());
return result.intValue() == 0;
} catch (WBEMException ex) {
_log.error("Encountered an exception while trying to start a zone session."
+ ex.getLocalizedMessage());
throw ex;
}
}
@SuppressWarnings("rawtypes")
public CIMObjectPath addZone(WBEMClient client,
CIMInstance zonesetServiceIns, CIMObjectPath zonesetPath,
String zoneName) throws WBEMException {
CIMObjectPath zonePath = null;
CIMArgument[] outargs = new CIMArgument[1];
CIMArgument[] inargs = new CIMArgument[3];
inargs[0] = _cimArgumentFactory.string("ZoneName", zoneName);
inargs[1] = _cimArgumentFactory.uint16("ZoneType", 2);
// TODO - I am not sure what subtype is yet, I need to find out.
inargs[2] = _cimArgumentFactory.uint16("ZoneSubType", 1);
UnsignedInteger32 result = (UnsignedInteger32) client.invokeMethod(
zonesetServiceIns.getObjectPath(), "CreateZone", inargs,
outargs);
if (result.intValue() == 0 && outargs.length > 0) {
zonePath = (CIMObjectPath) outargs[0].getValue();
}
if (zonePath != null) {
// add zone to zoneset
outargs = new CIMArgument[1];
inargs = new CIMArgument[2];
inargs[0] = _cimArgumentFactory.reference("ZoneSet", zonesetPath);
inargs[1] = _cimArgumentFactory.reference("Zone", zonePath);
result = (UnsignedInteger32) client.invokeMethod(
zonesetServiceIns.getObjectPath(), "AddZone", inargs, outargs);
if (result.intValue() != 0) {
// TODO - I need to add more error handling
zonePath = null;
}
}
return zonePath;
}
@SuppressWarnings("rawtypes")
public CIMObjectPath addZoneMember(WBEMClient client,
CIMInstance zonesetServiceIns, CIMObjectPath zonePath, String wwn)
throws WBEMException {
CIMObjectPath zoneMemberPath = null;
CIMArgument[] outargs = new CIMArgument[1];
CIMArgument[] inargs = new CIMArgument[3];
inargs[0] = _cimArgumentFactory.uint16("ConnectivityMemberType", 2);
inargs[1] = _cimArgumentFactory.string("ConnectivityMemberID", wwn);
inargs[2] = _cimArgumentFactory.reference("SystemSpecificCollection",
zonePath);
UnsignedInteger32 result = (UnsignedInteger32) client.invokeMethod(
zonesetServiceIns.getObjectPath(),
"CreateZoneMembershipSettingData", inargs, outargs);
if (result.intValue() == 0 && outargs.length > 0) {
zoneMemberPath = (CIMObjectPath) outargs[0].getValue();
}
return zoneMemberPath;
}
/**
* Returns the ZoneSetServiceInstance used for invoking methods.
*
* @param fabricId
* @return
* @throws javax.wbem.WBEMException
*/
@SuppressWarnings("unchecked")
public CIMObjectPath getZoneService(String fabricId) throws WBEMException {
CIMInstance vsanins = getVsanInstance(new Integer(fabricId));
CloseableIterator<CIMObjectPath> rfnmIt = null;
CloseableIterator<CIMInstance> zsIt = null;
try {
rfnmIt = _client.referenceNames(vsanins
.getObjectPath(), "CISCO_ZoneServiceInVsan", null);
while (rfnmIt.hasNext()) {
CIMObjectPath rfnmins = rfnmIt.next();
_log.info(rfnmins.toString());
}
zsIt = _client.associatorInstances(vsanins.getObjectPath(),
"CISCO_ZoneServiceInVsan", "CISCO_ZoneService", null, null, false, null);
while (zsIt.hasNext()) {
CIMInstance zsins = zsIt.next();
_log.info(zsins.toString());
}
} finally {
if (rfnmIt != null) {
rfnmIt.close();
}
if (zsIt != null) {
zsIt.close();
}
}
return null;
}
public CIMInstance getFabricInstance(String fabricId)
throws WBEMException {
CIMObjectPath path = CimObjectPathCreator.createInstance(_fabric_path, _namespace);
CloseableIterator<CIMInstance> fabricIter = null;
try {
fabricIter = _client.enumerateInstances(path, false, true, true, null);
while (fabricIter.hasNext()) {
CIMInstance fabricIns = fabricIter.next();
if (fabricId.equals(cimStringProperty(fabricIns, "ElementName"))) {
return fabricIns;
}
}
} finally {
if (fabricIter != null) {
fabricIter.close();
}
}
return null;
}
/**
* Given a dialog, add one or more zones to the active zoneset of the specified vsan.
* This method is callable from with Bourne or from MDSDialogTest for stand-alone testing.
* For now the only type of zone members supported are pwwn.
*
* @param zones - List of zones to be created. Zone names will be overwritten.
* @param vsanId - Integer vsanId
* @return list of zone names that were added
* @throws ControllerException
*/
public List<String> addZonesStrategy(List<Zone> zones, Integer vsanId)
throws Exception {
List<String> addedZoneNames = new ArrayList<String>();
boolean inSession = false;
boolean commit = true;
CIMObjectPath zonesetServicePath = getZoneService(vsanId.toString());
if (zonesetServicePath == null) {
throw new DeviceControllerException("Couldn't locate ZoneSetService vsan: " + vsanId);
}
CIMInstance zonesetService = _client.getInstance(zonesetServicePath, false, false, null);
try {
// Start a session.
inSession = startSession(_client, zonesetService);
// Get the existing zones in the active zoneset.
// XXX FIXME: Need to account for creating the zoneset if none exists.
List<Zoneset> zonesets = getZonesets(vsanId);
if (zonesets == null || zonesets.isEmpty()) {
throw new DeviceControllerException("no zonesets");
}
Zoneset activeZoneset = zonesets.get(0);
if (activeZoneset.getActive() != true) {
throw new DeviceControllerException("no active zoneset");
}
for (Zone zone : zones) {
CIMObjectPath zonePath = addZone(_client, zonesetService,
((CIMObjectPath) activeZoneset.getCimObjectPath()), zone.getName());
}
} finally {
// Commit session.
if (inSession) {
endSession(_client, zonesetService, commit);
}
}
return addedZoneNames;
}
}