/*
* Copyright (c) 2008-2013 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.api.service.impl.resource;
import static com.emc.storageos.api.mapper.DbObjectMapper.toNamedRelatedResource;
import static com.emc.storageos.api.mapper.NetworkMapper.map;
import static com.emc.storageos.api.mapper.TaskMapper.toTask;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.lang.StringUtils;
import com.emc.storageos.api.mapper.functions.MapNetworkSystem;
import com.emc.storageos.api.service.impl.resource.utils.AsyncTaskExecutorIntf;
import com.emc.storageos.api.service.impl.resource.utils.DiscoveredObjectTaskScheduler;
import com.emc.storageos.api.service.impl.resource.utils.PurgeRunnable;
import com.emc.storageos.api.service.impl.response.BulkList;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.constraint.AlternateIdConstraint;
import com.emc.storageos.db.client.constraint.ContainmentConstraint;
import com.emc.storageos.db.client.model.DiscoveredDataObject;
import com.emc.storageos.db.client.model.DiscoveredDataObject.RegistrationStatus;
import com.emc.storageos.db.client.model.DiscoveredDataObject.Type;
import com.emc.storageos.db.client.model.FCEndpoint;
import com.emc.storageos.db.client.model.FCZoneReference;
import com.emc.storageos.db.client.model.Network;
import com.emc.storageos.db.client.model.NetworkSystem;
import com.emc.storageos.db.client.model.Operation;
import com.emc.storageos.db.client.model.StoragePort;
import com.emc.storageos.db.client.model.Volume;
import com.emc.storageos.db.client.util.CustomQueryUtility;
import com.emc.storageos.db.client.util.EndpointUtility;
import com.emc.storageos.db.client.util.NullColumnValueGetter;
import com.emc.storageos.db.client.util.StringSetUtil;
import com.emc.storageos.db.client.util.WWNUtility;
import com.emc.storageos.db.exceptions.DatabaseException;
import com.emc.storageos.model.BulkIdParam;
import com.emc.storageos.model.ResourceOperationTypeEnum;
import com.emc.storageos.model.ResourceTypeEnum;
import com.emc.storageos.model.TaskList;
import com.emc.storageos.model.TaskResourceRep;
import com.emc.storageos.model.network.FCEndpointRestRep;
import com.emc.storageos.model.network.FCEndpoints;
import com.emc.storageos.model.network.FCZoneReferences;
import com.emc.storageos.model.network.Fabrics;
import com.emc.storageos.model.network.NetworkSystemBulkRep;
import com.emc.storageos.model.network.NetworkSystemCreate;
import com.emc.storageos.model.network.NetworkSystemList;
import com.emc.storageos.model.network.NetworkSystemRestRep;
import com.emc.storageos.model.network.NetworkSystemUpdate;
import com.emc.storageos.model.network.SanZone;
import com.emc.storageos.model.network.SanZoneCreateParam;
import com.emc.storageos.model.network.SanZoneMemberRestRep;
import com.emc.storageos.model.network.SanZoneRestRep;
import com.emc.storageos.model.network.SanZoneUpdateParam;
import com.emc.storageos.model.network.SanZoneUpdateParams;
import com.emc.storageos.model.network.SanZonesDeleteParam;
import com.emc.storageos.model.network.SanZonesRestRep;
import com.emc.storageos.model.network.WwnAliasParam;
import com.emc.storageos.model.network.WwnAliasUpdateParam;
import com.emc.storageos.model.network.WwnAliasUpdateParams;
import com.emc.storageos.model.network.WwnAliasesCreateParam;
import com.emc.storageos.model.network.WwnAliasesDeleteParam;
import com.emc.storageos.model.network.WwnAliasesParam;
import com.emc.storageos.model.valid.Endpoint.EndpointType;
import com.emc.storageos.networkcontroller.NetworkController;
import com.emc.storageos.networkcontroller.impl.NetworkAssociationHelper;
import com.emc.storageos.networkcontroller.impl.mds.Zone;
import com.emc.storageos.networkcontroller.impl.mds.ZoneMember;
import com.emc.storageos.networkcontroller.impl.mds.ZoneMember.ConnectivityMemberType;
import com.emc.storageos.networkcontroller.impl.mds.ZoneUpdate;
import com.emc.storageos.networkcontroller.impl.mds.ZoneWwnAlias;
import com.emc.storageos.networkcontroller.impl.mds.ZoneWwnAliasUpdate;
import com.emc.storageos.networkcontroller.impl.mds.Zoneset;
import com.emc.storageos.security.audit.AuditLogManager;
import com.emc.storageos.security.authorization.CheckPermission;
import com.emc.storageos.security.authorization.DefaultPermissions;
import com.emc.storageos.security.authorization.Role;
import com.emc.storageos.services.OperationTypeEnum;
import com.emc.storageos.svcs.errorhandling.resources.APIException;
import com.emc.storageos.svcs.errorhandling.resources.InternalException;
import com.emc.storageos.volumecontroller.AsyncTask;
import com.emc.storageos.volumecontroller.ControllerException;
import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator;
/**
* NetworkDevice resource implementation
*/
@Path("/vdc/network-systems")
@DefaultPermissions(readRoles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR },
writeRoles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public class NetworkSystemService extends TaskResourceService {
private static final Logger _log = LoggerFactory.getLogger(NetworkSystemService.class);
// how many times to retry a procedure before returning failure to the user.
// Is used with "system delete" operation.
private int _retry_attempts;
private static final String EVENT_SERVICE_TYPE = "network";
@Override
public String getServiceType() {
return EVENT_SERVICE_TYPE;
}
private static final String BROCADE_ZONE_NAME_EXP = "[a-zA-Z0-9_]+";
private static final String CISCO_ZONE_NAME_EXP = "[a-zA-Z0-9_\\-]+";
private static final int ZONE_NAME_LENGTH = 64;
private static class NetworkJobExec implements AsyncTaskExecutorIntf {
private final NetworkController _controller;
NetworkJobExec(NetworkController controller) {
_controller = controller;
}
@Override
public void executeTasks(AsyncTask[] tasks) throws ControllerException {
_controller.discoverNetworkSystems(tasks);
}
@Override
public ResourceOperationTypeEnum getOperation() {
return ResourceOperationTypeEnum.DISCOVER_NETWORK_SYSTEM;
}
}
/**
* Given a device type ("mds", or "brocade"), return the appropriate NetworkController.
*
* @param deviceType
* @return NetworkController
*/
private NetworkController getNetworkController(String deviceType) {
NetworkController controller = getController(NetworkController.class, deviceType);
return controller;
}
/**
* Invoke connect to the NetworkSystem. This will check for basic connectivity,
* support for the device, etc.
*
* @param device
* @throws InternalException
*/
private void startNetworkSystem(NetworkSystem device) throws InternalException {
NetworkController controller = getNetworkController(device.getSystemType());
controller.connectNetwork(device.getId());
}
/**
* Returns list of all network systems. Each item in the list contains
* an id, name, and link.
*
* @prereq none
* @brief List network systems
* @return NetworkSystemList for each NetworkSystem, each containing an id, name, and link.
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public NetworkSystemList getNetworkSystemList() {
NetworkSystem system;
List<URI> ids;
ids = _dbClient.queryByType(NetworkSystem.class, true);
NetworkSystemList list = new NetworkSystemList();
for (URI id : ids) {
system = _dbClient.queryObject(NetworkSystem.class, id);
if (system != null) {
list.getSystems().add(toNamedRelatedResource(system));
}
}
return list;
}
/**
* Check on creation that this is not a duplication of an existing device
*/
private void checkForDuplicateDevice(URI id, String ip_address, Integer port_number,
String smis_provider_ip, Integer smis_port_number, String name) {
List<URI> existingDevices = _dbClient.queryByType(NetworkSystem.class, true);
for (URI uri : existingDevices) {
NetworkSystem existing = _dbClient.queryObject(NetworkSystem.class, uri);
if (existing == null || existing.getId().equals(id)) {
continue;
}
if (existing.getIpAddress() != null && existing.getPortNumber() != null
&& ip_address != null && port_number != null
&& existing.getIpAddress().equalsIgnoreCase(ip_address)
&& existing.getPortNumber().equals(port_number)) {
throw APIException.badRequests.networkSystemExistsAtIPAddress(ip_address);
}
if (existing.getSmisProviderIP() != null && existing.getSmisPortNumber() != null
&& smis_provider_ip != null && smis_port_number != null
&& existing.getSmisProviderIP().equalsIgnoreCase(smis_provider_ip)
&& existing.getSmisPortNumber().equals(smis_port_number)) {
throw APIException.badRequests.networkSystemSMISProviderExistsAtIPAddress(smis_provider_ip);
}
if (existing.getLabel() != null && name != null
&& existing.getLabel().equalsIgnoreCase(name)) {
throw APIException.badRequests.resourceExistsWithSameName(NetworkSystem.class.getSimpleName());
}
}
}
/**
* Creates a new network system. This can either represent an SSH connection to a Cisco
* MDS or Nexus switch, or an SMI-S connection to the Brocade Network Advisor.
* The call will return before communication has been established, but discovery of
* the device will be initiated.
*
* @param param The NetworkSystemCreate object contains all the parameters for creation.
* @prereq none
* @brief Create network system
* @return A REST representation of the newly created network device.
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep createNetworkSystem(NetworkSystemCreate param)
throws Exception {
// check device type
ArgValidator.checkFieldValueFromSystemType(param.getSystemType(), "system_type",
Arrays.asList(NetworkSystem.Type.brocade, NetworkSystem.Type.mds));
NetworkSystem.Type deviceType = NetworkSystem.Type.valueOf(param.getSystemType());
if (NetworkSystem.Type.valueOf(param.getSystemType()) == NetworkSystem.Type.brocade) { // Validate fields required for brocade
ArgValidator.checkFieldNotNull(param.getSmisProviderIp(), "smis_provider_ip");
ArgValidator.checkFieldNotNull(param.getSmisPortNumber(), "smis_port_number");
ArgValidator.checkFieldNotNull(param.getSmisUserName(), "smis_user_name");
ArgValidator.checkFieldNotNull(param.getSmisPassword(), "smis_password");
} else if (NetworkSystem.Type.valueOf(param.getSystemType()) == NetworkSystem.Type.mds) { // Validate fields required for mds
ArgValidator.checkFieldNotNull(param.getIpAddress(), "ip_address");
ArgValidator.checkFieldNotNull(param.getPortNumber(), "port_number");
ArgValidator.checkFieldNotNull(param.getUserName(), "user_name");
ArgValidator.checkFieldNotNull(param.getPassword(), "password");
}
// Check for existing device.
checkForDuplicateDevice(null, param.getIpAddress(), param.getPortNumber(), param.getSmisProviderIp(), param.getSmisPortNumber(),
param.getName());
NetworkSystem device = new NetworkSystem();
URI id = URIUtil.createId(NetworkSystem.class);
device.setId(id);
device.setLabel(param.getName());
device.setIpAddress(param.getIpAddress());
device.setPortNumber(param.getPortNumber());
device.setUsername(param.getUserName());
device.setPassword(param.getPassword());
device.setSystemType(deviceType.name());
device.setSmisProviderIP(param.getSmisProviderIp());
device.setSmisPortNumber(param.getSmisPortNumber());
device.setSmisUserName(param.getSmisUserName());
device.setSmisPassword(param.getSmisPassword());
device.setSmisUseSSL(param.getSmisUseSsl());
device.setNativeGuid(NativeGUIDGenerator.generateNativeGuid(device));
device.setRegistrationStatus(DiscoveredDataObject.RegistrationStatus.REGISTERED.name());
_dbClient.createObject(device);
auditOp(OperationTypeEnum.CREATE_NETWORK_SYSTEM, true, null,
device.getId().toString(), device.getLabel(), device.getPortNumber(), device.getUsername(),
device.getSmisProviderIP(), device.getSmisPortNumber(), device.getSmisUserName(), device.getSmisUseSSL(),
device.getVersion(), device.getUptime());
return doDiscoverNetworkSystem(device);
}
/**
* Updates an already present network system by matching the URI. This can be used to
* change the IP address or port, change the credentials, or update the name of a
* network sytem. A refresh (discovery) is asynchronously initiated as a result of this call.
*
* @param id - the URN of a ViPR NetworkSystem
* @param param structure contains all the parameters that can be updated.
* @prereq none
* @brief Update network system
* @return The rest representation for the updated NetworkSystem
* @throws InternalException
*/
@PUT
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep updateNetworkSystem(@PathParam("id") URI id, NetworkSystemUpdate param) throws InternalException {
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
NetworkSystem device = _dbClient.queryObject(NetworkSystem.class, id);
ArgValidator.checkEntityNotNull(device, id, isIdEmbeddedInURL(id));
// Check for existing device.
checkForDuplicateDevice(device.getId(), param.getIpAddress(), param.getPortNumber(), param.getSmisProviderIp(),
param.getSmisPortNumber(), param.getName());
if (param.getName() != null) {
device.setLabel(param.getName());
}
if (param.getIpAddress() != null) {
device.setIpAddress(param.getIpAddress());
}
if (param.getPortNumber() != null) {
device.setPortNumber(param.getPortNumber());
}
if (param.getUserName() != null) {
device.setUsername(param.getUserName());
}
if (param.getPassword() != null) {
device.setPassword(param.getPassword());
}
if (param.getSmisProviderIp() != null) {
device.setSmisProviderIP(param.getSmisProviderIp());
}
if (param.getSmisPortNumber() != null) {
device.setSmisPortNumber(param.getSmisPortNumber());
}
if (param.getSmisUserName() != null) {
device.setSmisUserName(param.getSmisUserName());
}
if (param.getSmisPassword() != null) {
device.setSmisPassword(param.getSmisPassword());
}
if (param.getSmisUseSsl() != null) {
device.setSmisUseSSL(param.getSmisUseSsl());
}
device.setNativeGuid(NativeGUIDGenerator.generateNativeGuid(device));
_dbClient.persistObject(device);
startNetworkSystem(device);
auditOp(OperationTypeEnum.UPDATE_NETWORK_SYSTEM, true, null,
device.getId().toString(), device.getLabel(), device.getPortNumber(), device.getUsername(),
device.getSmisProviderIP(), device.getSmisPortNumber(), device.getSmisUserName(), device.getSmisUseSSL(),
device.getVersion(), device.getUptime());
return doDiscoverNetworkSystem(device);
}
/**
* Shows the attributes of the network system.
*
* @param id the URN of a ViPR network system.
* @prereq none
* @brief Show network system
* @return A rest representation of the attributes of the network system.
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public NetworkSystemRestRep getNetworkSystem(@PathParam("id") URI id) {
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
NetworkSystem device = queryResource(id);
return map(device);
}
/**
* Delete a network system. The method will delete the
* network system and all resources associated with it.
*
* @prereq The network system must be unregistered
* @brief Delete network system
* @return An asynchronous task.
*
* @throws DatabaseException
* When an error occurs querying the database.
*/
@POST
@Path("/{id}/deactivate")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep deleteNetworkSystem(@PathParam("id") URI id)
throws DatabaseException {
NetworkSystem system = queryObject(NetworkSystem.class, id, true);
ArgValidator.checkEntity(system, id, isIdEmbeddedInURL(id));
if (!RegistrationStatus.UNREGISTERED.toString().equals(system.getRegistrationStatus())) {
throw APIException.badRequests.invalidParameterCannotDeactivateRegisteredNetworkSystem(system.getId());
}
if (DiscoveredDataObject.DataCollectionJobStatus.IN_PROGRESS.toString().equals(system.getDiscoveryStatus()) ||
DiscoveredDataObject.DataCollectionJobStatus.SCHEDULED.toString().equals(system.getDiscoveryStatus())) {
throw APIException.serviceUnavailable.cannotDeactivateStorageSystemWhileInDiscover(system.getId());
}
List<Network> networkList = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, Network.class,
AlternateIdConstraint.Factory.getConstraint(Network.class, "networkSystems", system.getId().toString()));
for (Network network : networkList) {
if (network != null
&& network.getInactive() != true
&& network.getConnectedVirtualArrays() != null
&& !network.getConnectedVirtualArrays().isEmpty()
&& (network.getNetworkSystems() != null
&& network.getNetworkSystems().contains(system.getId().toString())
&& network.getNetworkSystems().size() == 1)) {
throw APIException.badRequests.invalidParameterNetworkMustBeUnassignedFromVirtualArray(network.getLabel(),
system.getLabel());
}
}
Map<String, List<FCZoneReference>> zonesMap = getNetworkSystemZoneRefs(system);
List<URI> nsystems = null;
List<FCZoneReference> zones = null;
// for each network handles associated objects. The network itself will be handled
// by the purge process
for (Network network : networkList) {
// remove references from ports
nsystems = StringSetUtil.stringSetToUriList(network.getNetworkSystems());
nsystems.remove(system.getId());
if (nsystems.isEmpty()) {
// This network will be removed - Remove any storage port references
List<StoragePort> netPorts = NetworkAssociationHelper.getNetworkStoragePorts(
network.getId().toString(), null, _dbClient);
NetworkAssociationHelper.clearPortAssociations(netPorts, _dbClient);
} else {
// This network will remain, update any zone references to use another network system
URI nsUri = nsystems.get(0);
zones = zonesMap.get(network.getNativeId());
if (zones != null) {
for (FCZoneReference zone : zones) {
zone.setNetworkSystemUri(nsUri);
}
_dbClient.persistObject(zones);
}
}
}
String taskId = UUID.randomUUID().toString();
Operation op = _dbClient.createTaskOpStatus(NetworkSystem.class, system.getId(),
taskId, ResourceOperationTypeEnum.DELETE_NETWORK_SYSTEM);
PurgeRunnable.executePurging(_dbClient, _dbPurger,
_asynchJobService.getExecutorService(), system,
_retry_attempts, taskId, 60);
auditOp(OperationTypeEnum.DELETE_NETWORK_SYSTEM, true, AuditLogManager.AUDITOP_BEGIN,
system.getId().toString(), system.getLabel(), system.getPortNumber(), system.getUsername(),
system.getSmisProviderIP(), system.getSmisPortNumber(), system.getSmisUserName(), system.getSmisUseSSL(),
system.getVersion(), system.getUptime());
return toTask(system, taskId, op);
}
private Map<String, List<FCZoneReference>> getNetworkSystemZoneRefs(NetworkSystem system) {
Map<String, List<FCZoneReference>> map = new HashMap<String, List<FCZoneReference>>();
List<FCZoneReference> zoneList = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, FCZoneReference.class,
AlternateIdConstraint.Factory.getConstraint(FCZoneReference.class, "networkSystemUri", system.getId().toString()));
List<FCZoneReference> zones = null;
for (FCZoneReference zone : zoneList) {
zones = map.get(zone.getFabricId());
if (zones == null) {
zones = new ArrayList<FCZoneReference>();
map.put(zone.getFabricId(), zones);
}
zones.add(zone);
}
return map;
}
/**
* Reassign the FCZoneReference to another NetworkSystem that manages the
* zone's fabric
*
* @param zone FCZoneReference that will be reassigned to another
* NetworkSystem
*/
private void reassignZoneNetworkSystem(FCZoneReference zone) {
URI networkSystemURI = NullColumnValueGetter.getNullURI();
List<Network> networkList = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, Network.class,
AlternateIdConstraint.Factory.getConstraint(Network.class, "nativeId", zone.getFabricId()));
Iterator<Network> networkIter = networkList.iterator();
while (networkIter.hasNext() && networkSystemURI.equals(NullColumnValueGetter.getNullURI())) {
Network network = networkIter.next();
for (String nsURI : network.getNetworkSystems()) {
if (!nsURI.equals(zone.getNetworkSystemUri().toString())) {
networkSystemURI = URI.create(nsURI);
break;
}
}
}
zone.setNetworkSystemUri(networkSystemURI);
_dbClient.persistObject(zone);
}
/**
* Discovers (refreshes) a network system. This is an asynchronous call.
* Currently this updates the end point (topology) information,
* which will be reconciled with the existing networks.
*
* @param id the URN of a ViPR Network System.
* @prereq none
* @brief Discover network system
* @return TaskResourceRep (asynchronous call)
*/
@POST
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/discover")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep discoverNetworkSystem(@PathParam("id") URI id) {
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
NetworkSystem device = queryObject(NetworkSystem.class, id, true);
return doDiscoverNetworkSystem(device);
}
/**
* Common code for submitting a request for discovery. The request may not be performed
* by the discovery framework if a discovery was recently performed or is ongoing for
* the network system.
*
* @param device the network system to be discovered to re-discovered.
* provided, a new taskId is generated.
* @return the task used to track the discovery job
*/
private TaskResourceRep doDiscoverNetworkSystem(NetworkSystem device) {
NetworkController controller = getNetworkController(device.getSystemType());
DiscoveredObjectTaskScheduler scheduler = new DiscoveredObjectTaskScheduler(_dbClient, new NetworkJobExec(controller));
String taskId = UUID.randomUUID().toString();
ArrayList<AsyncTask> tasks = new ArrayList<AsyncTask>(1);
tasks.add(new AsyncTask(NetworkSystem.class, device.getId(), taskId));
TaskList taskList = scheduler.scheduleAsyncTasks(tasks);
return taskList.getTaskList().iterator().next();
}
/**
* Register a network system.
*
* @param id the URN of a ViPR network system.
*
* @prereq none
* @brief Register network system
* @return A NetworkSystemRestRep reference specifying the data for the
* updated network system.
* @throws ControllerException
*
* @throws IllegalArgumentException When the network system is already
* registered.
*/
@POST
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/register")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public NetworkSystemRestRep registerNetworkSystem(@PathParam("id") URI id) throws ControllerException {
// Validate the network system.
ArgValidator.checkUri(id);
NetworkSystem networkSystem = _dbClient.queryObject(NetworkSystem.class, id);
ArgValidator.checkEntity(networkSystem, id, isIdEmbeddedInURL(id));
// If not already registered, register it now.
if (RegistrationStatus.UNREGISTERED.toString().equalsIgnoreCase(
networkSystem.getRegistrationStatus())) {
// Register all Networks for this system.
List<Network> networkList = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, Network.class,
AlternateIdConstraint.Factory.getConstraint(Network.class, "networkSystems", networkSystem.getId().toString()));
for (Network network : networkList) {
if (network.getInactive() ||
DiscoveredDataObject.RegistrationStatus.REGISTERED.toString().equals(network.getRegistrationStatus())) {
continue;
}
network.setRegistrationStatus(RegistrationStatus.REGISTERED.toString());
_dbClient.persistObject(network);
auditOp(OperationTypeEnum.REGISTER_NETWORK, true, null, network.getId().toString());
}
networkSystem.setRegistrationStatus(RegistrationStatus.REGISTERED.toString());
_dbClient.persistObject(networkSystem);
auditOp(OperationTypeEnum.REGISTER_NETWORK_SYSTEM, true, null,
networkSystem.getId().toString(), networkSystem.getLabel(), networkSystem.getPortNumber(), networkSystem.getUsername(),
networkSystem.getSmisProviderIP(), networkSystem.getSmisPortNumber(), networkSystem.getSmisUserName(),
networkSystem.getSmisUseSSL());
}
return map(networkSystem);
}
/**
* Deregister a network system.
*
* @param id the URN of a ViPR network system.
*
* @prereq none
* @brief Deregister network system
* @return A NetworkSystemRestRep reference specifying the data for the
* updated network system.
* @throws ControllerException
*
* @throws IllegalArgumentException When the network system is already
* registered.
*/
@POST
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/deregister")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public NetworkSystemRestRep deregisterNetworkSystem(@PathParam("id") URI id) throws ControllerException {
// Validate the storage system.
ArgValidator.checkUri(id);
NetworkSystem networkSystem = _dbClient.queryObject(NetworkSystem.class, id);
ArgValidator.checkEntity(networkSystem, id, isIdEmbeddedInURL(id));
if (!RegistrationStatus.UNREGISTERED.toString().equalsIgnoreCase(
networkSystem.getRegistrationStatus())) {
// Deregister all Networks for this system.
List<Network> networkList = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, Network.class,
AlternateIdConstraint.Factory.getConstraint(Network.class, "networkSystems", networkSystem.getId().toString()));
for (Network network : networkList) {
if (network.getInactive() ||
DiscoveredDataObject.RegistrationStatus.UNREGISTERED.toString().equals(network.getRegistrationStatus())) {
continue;
}
List<URI> registeredNetworkSystems = NetworkService.getRegisteredNetworkSystems(network, _dbClient);
registeredNetworkSystems.remove(networkSystem.getId());
// Only unregister Network if it is not managed by other registered NetworkSystems
if (registeredNetworkSystems.isEmpty()) {
network.setRegistrationStatus(RegistrationStatus.UNREGISTERED.toString());
_dbClient.persistObject(network);
auditOp(OperationTypeEnum.DEREGISTER_NETWORK, true, null, id.toString());
}
}
networkSystem.setRegistrationStatus(RegistrationStatus.UNREGISTERED.toString());
_dbClient.persistObject(networkSystem);
auditOp(OperationTypeEnum.DEREGISTER_NETWORK_SYSTEM, true, null,
networkSystem.getId().toString(), networkSystem.getLabel(), networkSystem.getPortNumber(), networkSystem.getUsername(),
networkSystem.getSmisProviderIP(), networkSystem.getSmisPortNumber(), networkSystem.getSmisUserName(),
networkSystem.getSmisUseSSL());
}
return map(networkSystem);
}
/**
* This returns the cached fiber channel connectivity information of a given fabric id
* between the network system and external systems, such as host initiators or storage array ports.
* If fabric id is not specified, get all connections of the network system.
* The connectivity information is periodically updated, or can be refreshed on demand
* using a POST /vdc/network-systems/{id}/refresh.
*
* @prereq none
* @param id the URN of a ViPR Network System
* @param fabricId The name of the VSAN or fabric as returned by /vdc/network-systems/{id}/san-fabrics
* or the VSAN or fabric WWN
* @brief List network system fiber channel connectivity
* @return A list of FCEndpoint structures, each containing information about one connection.
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/fc-endpoints/")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public FCEndpoints getFCEndpointsByFabric(@PathParam("id") URI id, @QueryParam("fabric-id") String fabricId) {
FCEndpoints connections = new FCEndpoints();
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
if (WWNUtility.isValidWWN(fabricId)) {
fabricId = fabricId.replaceAll(":", "");
}
NetworkSystem device = queryResource(id);
List<URI> uriList = _dbClient.queryByConstraint(ContainmentConstraint.Factory
.getNetworkSystemFCPortConnectionConstraint(device.getId()));
connections.setConnections(getFCEndPointRestReps(uriList, fabricId));
return connections;
}
/**
* This information is intended only for internal debugging.
* The FCZoneReference structure represents a use of a SAN Zone by an ExportGroup/Volume
* combination. This call allows one to check what ExportGroups/Volumes are using a given
* SAN Zone.
* Gets the FCZoneReference entries for a given wwnList (used to make the key).
*
* @param wwnList A comma separated list of wwn Zone members is used to make the search key.
* @brief INTERNAL ONLY
* @return FCZoneReferences a list of FCZoneReference structures
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/san-references/{wwnList}")
@CheckPermission(roles = { Role.SYSTEM_ADMIN })
public FCZoneReferences getReferences(@PathParam("wwnList") String wwnList) {
FCZoneReferences references = new FCZoneReferences();
List<String> wwns = Arrays.asList(wwnList.split(","));
for (int i = 0; i < wwns.size() - 1; i++) {
for (int j = i + 1; j < wwns.size(); j++) {
String key = FCZoneReference.makeEndpointsKey(Arrays.asList(new String[] {
wwns.get(i).toUpperCase(), wwns.get(j).toUpperCase() }));
List<URI> uris = _dbClient.queryByConstraint(AlternateIdConstraint.Factory.
getFCZoneReferenceKeyConstraint(key));
for (URI uri : uris) {
FCZoneReference ref = _dbClient.queryObject(FCZoneReference.class, uri);
if (ref != null) {
if (ref.getInactive() == false) {
Volume vol = _dbClient.queryObject(Volume.class, ref.getVolumeUri());
if (vol != null && vol.getInactive() == false) {
references.getReferences().add(map(ref));
}
}
}
}
}
}
return references;
}
/**
* Returns a list of the VSAN or fabric names configured on this network system.
* Note: This is a synchronous call to the device and may take a while to receive a response.
*
* @param id the URN of a ViPR network system.
* @prereq none
* @brief List network system VSANs and fabrics
* @return A list of fabric names configured on the Network System.
* @throws InternalException
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/san-fabrics")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR })
public Fabrics getFabrics(@PathParam("id") URI id) throws InternalException {
Fabrics fabrics = new Fabrics();
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
NetworkSystem device = queryResource(id);
NetworkController controller = getNetworkController(device.getSystemType());
List<String> fabricIds = controller.getFabricIds(device.getId());
fabrics.setFabricIds(fabricIds);
return fabrics;
}
/**
* Returns a list of the active zones (and their zone members) for the specified
* fabric or VSAN in a network system. E.g., ../san-fabrics/{fabric-id}/san-zones?zone-name="abc-zone"&exclude-members=true
* Note: This is a synchronous call to the device and may take a while to receive a response.
*
* @param id the URN of a ViPR network system.
* @param fabricId The name of the VSAN or fabric as returned by
* @param zoneName - only returns zone with zone name matched the given name. Return all zones, if not specified.
* @param excludeMembers - true, do not include members with zone. Include members, if not specified.
* @param excludeAliases - true, do not include aliases with zone. Include aliases, if not specified.
* @prereq none
* @brief List active zones in a network system fabric or VSAN
* @return A list of the active zones and their members. If zone name is specified, and there is a match, then only one zone is
* returned.
* If excludeMembers is true, then only zone name is present.
* @throws InternalException
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/san-fabrics/{fabricId}/san-zones")
@CheckPermission(roles = { Role.SYSTEM_ADMIN })
public SanZonesRestRep getSanZones(@PathParam("id") URI id, @PathParam("fabricId") String fabricId,
@QueryParam("zone-name") String zoneName, @QueryParam("exclude-members") boolean excludeMembers,
@QueryParam("exclude-aliases") boolean excludeAliases) throws InternalException {
SanZonesRestRep szones = new SanZonesRestRep();
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
NetworkSystem device = queryResource(id);
String fabricWwn = null;
if (WWNUtility.isValidWWN(fabricId)) {
fabricWwn = fabricId;
fabricId = fabricId.replaceAll(":", "");
}
NetworkController controller = getNetworkController(device.getSystemType());
List<Zoneset> zonesets = controller.getZonesets(device.getId(), fabricId, fabricWwn, zoneName, excludeMembers, excludeAliases);
for (Zoneset zoneset : zonesets) {
for (Zone zone : zoneset.getZones()) {
SanZoneRestRep sz = new SanZoneRestRep();
sz.setName(zone.getName());
for (ZoneMember member : zone.getMembers()) {
// convert zone member to xml aware. Only fill in alias if member is an alias type
sz.getMembers().add(new SanZoneMemberRestRep(
member.getAddress(),
member.isAliasType() ? member.getAlias() : null));
}
szones.getZones().add(sz);
}
}
return szones;
}
/**
* Returns true if valid zone name.
*
* @param name
* @return
*/
private void validateZoneName(String name) {
if (name.matches("[a-zA-Z0-9_]+")) {
return;
}
throw APIException.badRequests.illegalZoneName(name);
}
/**
* Returns true if valid zone name.
* Throw exception if zone name is invalid based on device type
*
* @param name
* @return
*/
private boolean validateZoneName(String name, String deviceType) {
boolean validZoneName = false;
if(name != null && name.length() > ZONE_NAME_LENGTH) {
_log.info("Zone name {} is not valid for device type {}", name, deviceType);
throw APIException.badRequests.nameZoneLongerThanAllowed(name, ZONE_NAME_LENGTH);
}
if(deviceType != null) {
if (deviceType.equalsIgnoreCase(Type.brocade.toString())) {
if (name.matches(BROCADE_ZONE_NAME_EXP)) {
validZoneName = true;
}
} else if (deviceType.equalsIgnoreCase(Type.mds.toString())) {
if (name.matches(CISCO_ZONE_NAME_EXP)) {
validZoneName = true;
}
}
}
if(!validZoneName) {
_log.info("Zone name {} is not valid for device type {}", name, deviceType);
throw APIException.badRequests.illegalZoneName(name);
}
_log.info("Zone name {} is valid for device type {}", name, deviceType);
return validZoneName;
}
/**
* Throw exception if alias is invalid
*
* @param alias
* @param foradd - valid address if validation is for add operation or address is not empty.
* @return
*/
private void validateAlias(WwnAliasParam alias, boolean forAdd) {
if (forAdd || !StringUtils.isEmpty(alias.getAddress())) {
validateWWN(alias.getAddress());
}
validateWWNAlias(alias.getName());
}
/**
* Throw exception if alias of wwn is invalid
*
* @param alias
* @return
*/
private void validateWWNAlias(String alias) {
if (!WWNUtility.isValidWWNAlias(alias)) {
throw APIException.badRequests.illegalWWNAlias(alias);
}
}
/**
* Throw exception if wwn is invalid
*
* @param wwn
* @return
*/
private void validateWWN(String wwn) {
if (!WWNUtility.isValidWWN(wwn)) {
throw APIException.badRequests.illegalWWN(wwn);
}
}
/**
* Adds one or more SAN zones to the active zoneset of the VSAN or fabric specified on a network system.
* This is an asynchronous call.
*
* @param sanZones A parameter structure listing the zone(s) to be added and their members.
* @param id the URN of a ViPR network system.
* @param fabricId The name of the VSAN or fabric as returned by
* /vdc/network-systems/{id}/san-fabrics or the VSAN or fabric WWN
* @prereq none
* @brief Add SAN zones to network system VSAN or fabric
* @return A task description structure.
* @throws InternalException
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/san-fabrics/{fabricId}/san-zones")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep addSanZones(SanZoneCreateParam sanZones, @PathParam("id") URI id,
@PathParam("fabricId") String fabricId) throws InternalException {
String task = UUID.randomUUID().toString();
String fabricWwn = null;
if (WWNUtility.isValidWWN(fabricId)) {
fabricWwn = fabricId;
fabricId = fabricId.replaceAll(":", "");
}
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
NetworkSystem device = queryResource(id);
List<Zone> zones = new ArrayList<Zone>();
for (SanZone sz : sanZones.getZones()) {
Zone zone = new Zone(sz.getName());
validateZoneName(sz.getName(), device.getSystemType());
zones.add(zone);
for (String szm : sz.getMembers()) {
ZoneMember member = createZoneMember(szm);
zone.getMembers().add(member);
}
ArgValidator.checkFieldNotEmpty(zone.getMembers(), "zone members");
auditOp(OperationTypeEnum.ADD_SAN_ZONE, true, AuditLogManager.AUDITOP_BEGIN, zone.getName(),
device.getId().toString(), device.getLabel(), device.getPortNumber(), device.getUsername(),
device.getSmisProviderIP(), device.getSmisPortNumber(), device.getSmisUserName(), device.getSmisUseSSL(),
device.getVersion(), device.getUptime());
}
ArgValidator.checkFieldNotEmpty(zones, "zones");
Operation op = _dbClient.createTaskOpStatus(NetworkSystem.class, device.getId(),
task, ResourceOperationTypeEnum.ADD_SAN_ZONE);
NetworkController controller = getNetworkController(device.getSystemType());
controller.addSanZones(device.getId(), fabricId, fabricWwn, zones, false, task);
return toTask(device, task, op);
}
/**
* Deletes one or more zone(s) from the active zoneset of the VSAN or fabric specified in
* the network system. This is an asynchronous call.
*
* @param sanZones A list of Zones and their zone members that should be deleted from
* the active zoneset. Note: the zone members must be included (deletion of a zone is based
* on matching both the name and the zone members).
* @param id the URN of a ViPR Network System
* @param fabricId The name of the VSAN or fabric as returned by
* /vdc/network-systems/{id}/san-fabrics or the VSAN or fabric WWN
* @prereq none
* @brief Delete zones from network system VSAN or fabric
* @return A task description structure.
* @throws InternalException
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/san-fabrics/{fabricId}/san-zones/remove")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep removeSanZones(SanZonesDeleteParam sanZones, @PathParam("id") URI id,
@PathParam("fabricId") String fabricId) throws InternalException {
String task = UUID.randomUUID().toString();
String fabricWwn = null;
if (WWNUtility.isValidWWN(fabricId)) {
fabricWwn = fabricId;
fabricId = fabricId.replaceAll(":", "");
}
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
NetworkSystem device = queryResource(id);
Operation op = _dbClient.createTaskOpStatus(NetworkSystem.class, device.getId(),
task, ResourceOperationTypeEnum.REMOVE_SAN_ZONE);
List<Zone> zones = new ArrayList<Zone>();
for (SanZone sz : sanZones.getZones()) {
Zone zone = new Zone(sz.getName());
zones.add(zone);
for (String szm : sz.getMembers()) {
ZoneMember member = createZoneMember(szm);
zone.getMembers().add(member);
}
auditOp(OperationTypeEnum.REMOVE_SAN_ZONE, true, AuditLogManager.AUDITOP_BEGIN, zone.getName(),
device.getId().toString(), device.getLabel(), device.getPortNumber(), device.getUsername(),
device.getSmisProviderIP(), device.getSmisPortNumber(), device.getSmisUserName(), device.getSmisUseSSL(),
device.getVersion(), device.getUptime());
}
ArgValidator.checkFieldNotEmpty(zones, "zones");
NetworkController controller = getNetworkController(device.getSystemType());
controller.removeSanZones(device.getId(), fabricId, fabricWwn, zones, false, task);
return toTask(device, task, op);
}
/**
* For given network system's fabric, update zones via add and/or remove their pwwns or aliases.
* This is an asynchronous call.
*
* @param updateSanZones A parameter structure listing the zone(s) to be added and their members.
* @param id the URN of a ViPR network system.
* @param fabricId The name of the VSAN or fabric as returned by /vdc/network-systems/{id}/san-fabrics
* or the VSAN or fabric WWN
* @prereq Updating zones must be exist in network system with given <code>id</code>
* @brief Update SAN zones details for network system VSAN or fabric
* @return A task description structure.
* @throws InternalException
*/
@PUT
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/san-fabrics/{fabricId}/san-zones")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep updateSanZones(SanZoneUpdateParams updateSanZones, @PathParam("id") URI id,
@PathParam("fabricId") String fabricId) throws InternalException {
String task = UUID.randomUUID().toString();
String fabricWwn = null;
if (WWNUtility.isValidWWN(fabricId)) {
fabricWwn = fabricId;
fabricId = fabricId.replaceAll(":", "");
}
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
NetworkSystem device = queryResource(id);
List<ZoneUpdate> updateZones = new ArrayList<ZoneUpdate>();
for (SanZoneUpdateParam sz : updateSanZones.getUpdateZones()) {
ZoneUpdate updateZone = new ZoneUpdate(sz.getName());
validateZoneName(sz.getName(), device.getSystemType());
for (String szm : sz.getAddMembers()) {
if (StringUtils.isEmpty(szm)) {
continue;
}
ZoneMember member = createZoneMember(szm);
updateZone.getAddZones().add(member);
}
for (String szm : sz.getRemoveMembers()) {
if (StringUtils.isEmpty(szm)) {
continue;
}
ZoneMember member = createZoneMember(szm);
updateZone.getRemoveZones().add(member);
}
updateZones.add(updateZone);
auditOp(OperationTypeEnum.UPDATE_SAN_ZONE, true, AuditLogManager.AUDITOP_BEGIN, updateZone.getName(),
device.getId().toString(), device.getLabel(), device.getPortNumber(), device.getUsername(),
device.getSmisProviderIP(), device.getSmisPortNumber(), device.getSmisUserName(), device.getSmisUseSSL(),
device.getVersion(), device.getUptime());
}
ArgValidator.checkFieldNotEmpty(updateZones, "zones");
Operation op = _dbClient.createTaskOpStatus(NetworkSystem.class, device.getId(),
task, ResourceOperationTypeEnum.UPDATE_SAN_ZONE);
NetworkController controller = getNetworkController(device.getSystemType());
controller.updateSanZones(device.getId(), fabricId, fabricWwn, updateZones, false, task);
return toTask(device, task, op);
}
/**
* Activate current active zoneset of the given fabric specified on a network system.
* This is an asynchronous call.
*
* @param sanZones A parameter structure listing the zone(s) to be added and their members.
* @param id the URN of a ViPR network system.
* @param fabricId The name of the VSAN or fabric as returned by
* /vdc/network-systems/{id}/san-fabrics or the WWN of the VSAN or fabric
* @prereq none
* @brief Activate the current active zoneset of the VSA or fabric which effect all
* zoning changes made since the last activation.
* @return A task description structure.
* @throws InternalException
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/san-fabrics/{fabricId}/san-zones/activate")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep activateSanZones(@PathParam("id") URI id,
@PathParam("fabricId") String fabricId) throws InternalException {
String task = UUID.randomUUID().toString();
String fabricWwn = null;
if (WWNUtility.isValidWWN(fabricId)) {
fabricWwn = fabricId;
fabricId = fabricId.replaceAll(":", "");
}
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
NetworkSystem device = queryResource(id);
Operation op = _dbClient.createTaskOpStatus(NetworkSystem.class, device.getId(),
task, ResourceOperationTypeEnum.ACTIVATE_SAN_ZONE);
auditOp(OperationTypeEnum.ACTIVATE_SAN_ZONE, true, AuditLogManager.AUDITOP_BEGIN,
device.getId().toString(), device.getLabel(), device.getPortNumber(), device.getUsername(),
device.getSmisProviderIP(), device.getSmisPortNumber(), device.getSmisUserName(), device.getSmisUseSSL(),
device.getVersion(), device.getUptime());
NetworkController controller = getNetworkController(device.getSystemType());
controller.activateSanZones(device.getId(), fabricId, fabricWwn, task);
return toTask(device, task, op);
}
/**
* List data of network systems based on input ids.
*
* @param param POST data containing the id list.
* @prereq none
* @brief List data of network systems
* @return list of representations.
*
* @throws DatabaseException When an error occurs querying the database.
*/
@POST
@Path("/bulk")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Override
public NetworkSystemBulkRep getBulkResources(BulkIdParam param) {
return (NetworkSystemBulkRep) super.getBulkResources(param);
}
/**
* Returns a list of aliases for the specified network system. For Brocade, aliases
* can be retrieved per fabric only and fabric-id is a required parameter. For MDS,
* the full list of device aliases for the network system is returned and fabric-id is
* ignored if provided.
*
* Note: This is a synchronous call to the device and may take a while to receive
* a response.
*
* @param id the URN of a ViPR network system.
* @param fabricId The name of the fabric as returned by
* /vdc/network-systems/{id}/san-fabrics or the WWN of the fabric
* @prereq none
* @brief List aliases in a network system or a fabric
* @return A list of aliases.
* @throws InternalException
*/
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/san-aliases")
@CheckPermission(roles = { Role.SYSTEM_ADMIN })
public WwnAliasesParam getAliases(@PathParam("id") URI id, @QueryParam("fabric-id") String fabricId) throws InternalException {
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
NetworkSystem device = queryResource(id);
if (Type.brocade.toString().equals(device.getSystemType())) {
ArgValidator.checkFieldNotEmpty(fabricId, "fabric-id");
}
String fabricWwn = null;
if (WWNUtility.isValidWWN(fabricId)) {
fabricWwn = fabricId;
fabricId = fabricId.replaceAll(":", "");
}
NetworkController controller = getNetworkController(device.getSystemType());
List<WwnAliasParam> aliases = new ArrayList<WwnAliasParam>(controller.getAliases(device.getId(), fabricId, fabricWwn));
return new WwnAliasesParam(aliases);
}
/**
* Adds one or more aliases to the specified network system. For Brocade the fabric where
* the aliases will be added must be specified. For MDS, this input is ignored if provided.
* <p>
* This is an asynchronous call.
*
* @param aliases A parameter structure listing the aliases to be added
* @param id the URN of a ViPR network system.
* @prereq none
* @brief Add aliases to a network system
* @return A task description structure.
* @throws InternalException
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/san-aliases/")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep addAliases(WwnAliasesCreateParam aliases, @PathParam("id") URI id) throws InternalException {
String task = UUID.randomUUID().toString();
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
ArgValidator.checkFieldNotEmpty(aliases.getAliases(), "aliases");
NetworkSystem device = queryResource(id);
String fabricId = aliases.getFabricId();
if (Type.brocade.toString().equals(device.getSystemType())) {
ArgValidator.checkFieldNotEmpty(fabricId, "fabric-id");
}
String fabricWwn = null;
if (WWNUtility.isValidWWN(fabricId)) {
fabricWwn = fabricId;
fabricId = fabricId.replaceAll(":", "");
}
Operation op = _dbClient.createTaskOpStatus(NetworkSystem.class, device.getId(),
task, ResourceOperationTypeEnum.ADD_ALIAS);
List<ZoneWwnAlias> zoneAliases = new ArrayList<ZoneWwnAlias>();
for (WwnAliasParam alias : aliases.getAliases()) {
ArgValidator.checkFieldNotEmpty(alias.getAddress(), "address");
validateAlias(alias, true);
zoneAliases.add(new ZoneWwnAlias(alias.getName(), alias.getAddress()));
auditOp(OperationTypeEnum.ADD_ALIAS, true, AuditLogManager.AUDITOP_BEGIN, alias.getName(),
device.getId().toString(), device.getLabel(), device.getPortNumber(), device.getUsername(),
device.getSmisProviderIP(), device.getSmisPortNumber(), device.getSmisUserName(), device.getSmisUseSSL(),
device.getVersion(), device.getUptime());
}
NetworkController controller = getNetworkController(device.getSystemType());
controller.addAliases(device.getId(), fabricId, fabricWwn, zoneAliases, task);
return toTask(device, task, op);
}
/**
* Removes one or more aliases from the specified network system. For Brocade the fabric from where
* the aliases will be removed must be specified. For MDS, this input is ignored if provided.
*
* @param aliases A parameter structure listing the aliases to be removed. The alias member is an
* optional parameter and when provided, the alias membership is checked prior to removing it.
* @param id the URN of a ViPR network system.
* @prereq none
* @brief Remove aliases to network system to VSAN or fabric
* @return A task description structure.
* @throws InternalException
*/
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/san-aliases/remove")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep removeAliases(WwnAliasesDeleteParam aliases,
@PathParam("id") URI id) throws InternalException {
String task = UUID.randomUUID().toString();
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
ArgValidator.checkFieldNotEmpty(aliases.getAliases(), "aliases");
NetworkSystem device = queryResource(id);
String fabricId = aliases.getFabricId();
if (Type.brocade.toString().equals(device.getSystemType())) {
ArgValidator.checkFieldNotEmpty(fabricId, "fabric-id");
}
String fabricWwn = null;
if (WWNUtility.isValidWWN(fabricId)) {
fabricWwn = fabricId;
fabricId = fabricId.replaceAll(":", "");
}
Operation op = _dbClient.createTaskOpStatus(NetworkSystem.class, device.getId(),
task, ResourceOperationTypeEnum.REMOVE_ALIAS);
List<ZoneWwnAlias> zoneAliases = new ArrayList<ZoneWwnAlias>();
for (WwnAliasParam alias : aliases.getAliases()) {
validateAlias(alias, false);
zoneAliases.add(new ZoneWwnAlias(alias.getName(), alias.getAddress()));
auditOp(OperationTypeEnum.REMOVE_ALIAS, true, AuditLogManager.AUDITOP_BEGIN, alias.getName(),
device.getId().toString(), device.getLabel(), device.getPortNumber(), device.getUsername(),
device.getSmisProviderIP(), device.getSmisPortNumber(), device.getSmisUserName(), device.getSmisUseSSL(),
device.getVersion(), device.getUptime());
}
NetworkController controller = getNetworkController(device.getSystemType());
controller.removeAliases(device.getId(), fabricId, fabricWwn, zoneAliases, task);
return toTask(device, task, op);
}
/**
* Changes the WWN member of one or more aliases on the specified network system. For Brocade
* the fabric of the aliases will be removed must be specified.
* For MDS, this input is ignored if provided.
* <p>
* Current address WWN is optional; however, if provided, it must match the one in system before update. If not, exception will be
* thrown.
* <p>
* This is an asynchronous call.
*
* @param aliases A parameter structure listing the aliases to be updated
* @param id the URN of a ViPR network system.
* @param fabricId The name of the VSAN or fabric. This parameter is ignored
* if network system is an MDS
* @prereq none
* @brief Update aliases in network system
* @return A task description structure.
* @throws InternalException
*/
@PUT
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Path("/{id}/san-aliases")
@CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN })
public TaskResourceRep updateAliases(WwnAliasUpdateParams updateAliasParam, @PathParam("id") URI id) throws InternalException {
String task = UUID.randomUUID().toString();
ArgValidator.checkFieldUriType(id, NetworkSystem.class, "id");
ArgValidator.checkFieldNotEmpty(updateAliasParam.getUpdateAliases(), "aliases");
NetworkSystem device = queryResource(id);
String fabricId = updateAliasParam.getFabricId();
if (Type.brocade.toString().equals(device.getSystemType())) {
ArgValidator.checkFieldNotEmpty(fabricId, "fabric-id");
}
String fabricWwn = null;
if (WWNUtility.isValidWWN(fabricId)) {
fabricWwn = fabricId;
fabricId = fabricId.replaceAll(":", "");
}
Operation op = _dbClient.createTaskOpStatus(NetworkSystem.class, device.getId(),
task, ResourceOperationTypeEnum.UPDATE_ALIAS);
List<ZoneWwnAliasUpdate> zoneAliasesUpdate = new ArrayList<ZoneWwnAliasUpdate>();
for (WwnAliasUpdateParam updateAlias : updateAliasParam.getUpdateAliases()) {
validateAlias(updateAlias, false);
// validate new address
if (!StringUtils.isEmpty(updateAlias.getNewAddress())) {
validateWWN(updateAlias.getNewAddress());
}
// validate new name
if (!StringUtils.isEmpty(updateAlias.getNewName())) {
validateWWNAlias(updateAlias.getNewName());
}
zoneAliasesUpdate.add(new ZoneWwnAliasUpdate(updateAlias.getName(), updateAlias.getNewName(), updateAlias.getNewAddress(),
updateAlias.getAddress()));
auditOp(OperationTypeEnum.UPDATE_ALIAS, true, AuditLogManager.AUDITOP_BEGIN, updateAlias.getName(),
device.getId().toString(), device.getLabel(), device.getPortNumber(), device.getUsername(),
device.getSmisProviderIP(), device.getSmisPortNumber(), device.getSmisUserName(), device.getSmisUseSSL(),
device.getVersion(), device.getUptime());
}
NetworkController controller = getNetworkController(device.getSystemType());
controller.updateAliases(device.getId(), fabricId, fabricWwn, zoneAliasesUpdate, task);
return toTask(device, task, op);
}
@Override
protected NetworkSystem queryResource(URI id) {
ArgValidator.checkUri(id);
NetworkSystem device = _dbClient.queryObject(NetworkSystem.class, id);
ArgValidator.checkEntityNotNull(device, id, isIdEmbeddedInURL(id));
return device;
}
/**
* {@inheritDoc}
*/
@Override
protected URI getTenantOwner(URI id) {
return null;
}
@Override
protected ResourceTypeEnum getResourceType() {
return ResourceTypeEnum.NETWORK_SYSTEM;
}
@SuppressWarnings("unchecked")
@Override
public Class<NetworkSystem> getResourceClass() {
return NetworkSystem.class;
}
@Override
public NetworkSystemBulkRep queryBulkResourceReps(List<URI> ids) {
Iterator<NetworkSystem> _dbIterator =
_dbClient.queryIterativeObjects(getResourceClass(), ids);
return new NetworkSystemBulkRep(BulkList.wrapping(_dbIterator, MapNetworkSystem.getInstance()));
}
@Override
public NetworkSystemBulkRep queryFilteredBulkResourceReps(List<URI> ids) {
verifySystemAdmin();
return queryBulkResourceReps(ids);
}
private ZoneMember createZoneMember(String address) {
ZoneMember member = new ZoneMember(ConnectivityMemberType.WWPN);
if (EndpointUtility.isValidEndpoint(address, EndpointType.WWN)) {
member.setAddress(EndpointUtility.changeCase(address));
} else if (WWNUtility.isValidWWNAlias(address)) {
member.setAlias(address);
} else {
throw APIException.badRequests.illegalZoneMember(address);
}
return member;
}
private List<FCEndpointRestRep> getFCEndPointRestReps(List<URI> fcEndpointURIs, String fabricId) {
List<FCEndpointRestRep> fcEndpointRestRepList = new ArrayList<FCEndpointRestRep>();
if (fcEndpointRestRepList != null) {
for (URI uri : fcEndpointURIs) {
FCEndpoint fcEndpoint = _dbClient.queryObject(FCEndpoint.class, uri);
// add to list if fabric id was not specified, or endpoint fabric id is the specified id
if (fcEndpoint != null && (StringUtils.isEmpty(fabricId) || fabricId.equals(fcEndpoint.getFabricId()))) {
fcEndpointRestRepList.add(map(fcEndpoint));
}
}
}
return fcEndpointRestRepList;
}
}