diff --git a/server/src/com/cloud/api/BaseAsyncCreateCmd.java b/server/src/com/cloud/api/BaseAsyncCreateCmd.java index 7ddd59a0c0a..7c22f011dd8 100644 --- a/server/src/com/cloud/api/BaseAsyncCreateCmd.java +++ b/server/src/com/cloud/api/BaseAsyncCreateCmd.java @@ -1,10 +1,9 @@ package com.cloud.api; public abstract class BaseAsyncCreateCmd extends BaseAsyncCmd { + @Parameter(name="portforwardingserviceid") private Long id; - public abstract Object createObject(); - public Long getId() { return id; } diff --git a/server/src/com/cloud/api/Implementation.java b/server/src/com/cloud/api/Implementation.java index ce6a0d38d0e..bc70620fe82 100644 --- a/server/src/com/cloud/api/Implementation.java +++ b/server/src/com/cloud/api/Implementation.java @@ -11,6 +11,7 @@ import com.cloud.api.BaseCmd.Manager; @Retention(RetentionPolicy.RUNTIME) @Target({TYPE}) public @interface Implementation { + String createMethod() default ""; String method() default ""; Manager manager() default Manager.ManagementServer; } diff --git a/server/src/com/cloud/api/commands/CreatePortForwardingServiceCmd.java b/server/src/com/cloud/api/commands/CreatePortForwardingServiceCmd.java index ee202d28ec8..27b24f7dd5a 100644 --- a/server/src/com/cloud/api/commands/CreatePortForwardingServiceCmd.java +++ b/server/src/com/cloud/api/commands/CreatePortForwardingServiceCmd.java @@ -18,34 +18,20 @@ package com.cloud.api.commands; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - import org.apache.log4j.Logger; import com.cloud.api.BaseCmd; +import com.cloud.api.Implementation; import com.cloud.api.Parameter; -import com.cloud.api.ServerApiException; +import com.cloud.api.response.SecurityGroupResponse; import com.cloud.network.SecurityGroupVO; -import com.cloud.user.Account; -import com.cloud.utils.Pair; - +import com.cloud.serializer.SerializerHelper; + +@Implementation(method="createPortForwardingService") public class CreatePortForwardingServiceCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreatePortForwardingServiceCmd.class.getName()); private static final String s_name = "createportforwardingserviceresponse"; - private static final List> s_properties = new ArrayList>(); - - static { - //s_properties.add(new Pair(BaseCmd.Properties.USER_ID, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT_OBJ, Boolean.FALSE)); - - s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.DESCRIPTION, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.DOMAIN_ID, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.NAME, Boolean.TRUE)); - } ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -89,79 +75,24 @@ public class CreatePortForwardingServiceCmd extends BaseCmd { /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// + @Override public String getName() { return s_name; } - public List> getProperties() { - return s_properties; - } + + @Override + public String getResponse() { + SecurityGroupVO group = (SecurityGroupVO)getResponseObject(); + + SecurityGroupResponse response = new SecurityGroupResponse(); + response.setId(group.getId()); + response.setName(group.getName()); + response.setDescription(group.getDescription()); + response.setAccountName(group.getAccountName()); + response.setDomainId(group.getDomainId()); + // TODO: implement + //response.setDomainName(group.getDomainName()); - @Override - public List> execute(Map params) { - Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName()); - Long domainId = (Long)params.get(BaseCmd.Properties.DOMAIN_ID.getName()); - //Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName()); - String accountName = (String)params.get(BaseCmd.Properties.ACCOUNT.getName()); - String name = (String)params.get(BaseCmd.Properties.NAME.getName()); - String description = (String)params.get(BaseCmd.Properties.DESCRIPTION.getName()); - Long accountId = null; - - if (account != null) { - if (isAdmin(account.getType())) { - if (domainId != null) { - if (!getManagementServer().isChildDomain(account.getDomainId(), domainId)) { - throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied."); - } - } else { - // the admin must be creating the security group - if (account != null) { - accountId = account.getId(); - domainId = account.getDomainId(); - } - } - } else { - accountId = account.getId(); - domainId = account.getDomainId(); - } - } - - if (accountId == null) { - if ((accountName != null) && (domainId != null)) { - Account userAccount = getManagementServer().findActiveAccount(accountName, domainId); - if (userAccount != null) { - accountId = userAccount.getId(); - } else { - throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "could not find account " + accountName + " in domain " + domainId); - } - } - } - - if (accountId == null) { - throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified."); - } - - boolean isNameInUse = getManagementServer().isSecurityGroupNameInUse(domainId, accountId, name); - - if (isNameInUse) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to create port forwarding service, a service with name " + name + " already exisits."); - } - - SecurityGroupVO securityGroup = getManagementServer().createSecurityGroup(name, description, domainId, accountId); - - List> embeddedObject = new ArrayList>(); - - List> returnValues = new ArrayList>(); - returnValues.add(new Pair(BaseCmd.Properties.ID.getName(), securityGroup.getId().toString())); - returnValues.add(new Pair(BaseCmd.Properties.NAME.getName(), securityGroup.getName())); - returnValues.add(new Pair(BaseCmd.Properties.DESCRIPTION.getName(), securityGroup.getDescription())); - - Account accountTemp = getManagementServer().findAccountById(securityGroup.getAccountId()); - if (accountTemp != null) { - returnValues.add(new Pair(BaseCmd.Properties.ACCOUNT.getName(), accountTemp.getAccountName())); - returnValues.add(new Pair(BaseCmd.Properties.DOMAIN_ID.getName(), accountTemp.getDomainId())); - returnValues.add(new Pair(BaseCmd.Properties.DOMAIN.getName(), getManagementServer().findDomainIdById(accountTemp.getDomainId()).getName())); - } - embeddedObject.add(new Pair("portforwardingservice", new Object[] { returnValues } )); - return embeddedObject; + return SerializerHelper.toSerializedString(response); } } diff --git a/server/src/com/cloud/api/commands/CreatePortForwardingServiceRuleCmd.java b/server/src/com/cloud/api/commands/CreatePortForwardingServiceRuleCmd.java index 5a53d3b99fd..6ffc2f4a618 100644 --- a/server/src/com/cloud/api/commands/CreatePortForwardingServiceRuleCmd.java +++ b/server/src/com/cloud/api/commands/CreatePortForwardingServiceRuleCmd.java @@ -18,36 +18,20 @@ package com.cloud.api.commands; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - import org.apache.log4j.Logger; -import com.cloud.api.BaseCmd; +import com.cloud.api.BaseAsyncCreateCmd; +import com.cloud.api.Implementation; import com.cloud.api.Parameter; -import com.cloud.api.ServerApiException; -import com.cloud.async.executor.CreateOrUpdateRuleResultObject; -import com.cloud.network.SecurityGroupVO; +import com.cloud.api.response.PortForwardingServiceRuleResponse; +import com.cloud.network.NetworkRuleConfigVO; import com.cloud.serializer.SerializerHelper; -import com.cloud.user.Account; -import com.cloud.utils.Pair; - -public class CreatePortForwardingServiceRuleCmd extends BaseCmd { + +@Implementation(createMethod="createPortForwardingServiceRule", method="applyPortForwardingServiceRule") +public class CreatePortForwardingServiceRuleCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreatePortForwardingServiceRuleCmd.class.getName()); private static final String s_name = "createportforwardingserviceruleresponse"; - private static final List> s_properties = new ArrayList>(); - - static { - s_properties.add(new Pair(BaseCmd.Properties.ACCOUNT_OBJ, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.USER_ID, Boolean.FALSE)); - - s_properties.add(new Pair(BaseCmd.Properties.PORT_FORWARDING_SERVICE_ID, Boolean.TRUE)); - s_properties.add(new Pair(BaseCmd.Properties.PRIVATE_PORT, Boolean.TRUE)); - s_properties.add(new Pair(BaseCmd.Properties.PROTOCOL, Boolean.FALSE)); - s_properties.add(new Pair(BaseCmd.Properties.PUBLIC_PORT, Boolean.TRUE)); - } ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -91,6 +75,7 @@ public class CreatePortForwardingServiceRuleCmd extends BaseCmd { /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// + @Override public String getName() { return s_name; } @@ -98,64 +83,18 @@ public class CreatePortForwardingServiceRuleCmd extends BaseCmd { public static String getResultObjectName() { return "portforwardingservicerule"; } - - public List> getProperties() { - return s_properties; - } - - @Override - public List> execute(Map params) { - Account account = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName()); - Long userId = (Long)params.get(BaseCmd.Properties.USER_ID.getName()); - String publicPort = (String)params.get(BaseCmd.Properties.PUBLIC_PORT.getName()); - String privatePort = (String)params.get(BaseCmd.Properties.PRIVATE_PORT.getName()); - String protocol = (String)params.get(BaseCmd.Properties.PROTOCOL.getName()); - Long securityGroupId = (Long)params.get(BaseCmd.Properties.PORT_FORWARDING_SERVICE_ID.getName()); - - SecurityGroupVO sg = getManagementServer().findSecurityGroupById(securityGroupId); - if (sg == null) { - throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to find port forwarding service with id " + securityGroupId); - } - if (account != null) { - if (isAdmin(account.getType())) { - if (!getManagementServer().isChildDomain(account.getDomainId(), sg.getDomainId())) { - throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied."); - } - } else if (account.getId().longValue() != sg.getAccountId().longValue()) { - throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule."); - } - } - - // If command is executed via 8096 port, set userId to the id of System account (1) - if (userId == null) { - userId = Long.valueOf(1); - } - - long jobId = getManagementServer().createOrUpdateRuleAsync(true, userId.longValue(), sg.getAccountId().longValue(), null, securityGroupId, null, publicPort, null, privatePort, protocol, null); - long ruleId = 0; - - if (jobId == 0) { - s_logger.warn("Unable to schedule async-job for CreatePortForwardingServiceRuleCmd command"); - } else { - if (s_logger.isDebugEnabled()) - s_logger.debug("CreatePortForwardingServiceRuleCmd command has been accepted, job id: " + jobId); - - ruleId = waitInstanceCreation(jobId); - } - - List> returnValues = new ArrayList>(); - returnValues.add(new Pair(BaseCmd.Properties.JOB_ID.getName(), Long.valueOf(jobId))); - returnValues.add(new Pair(BaseCmd.Properties.RULE_ID.getName(), Long.valueOf(ruleId))); - return returnValues; - } - - protected long getInstanceIdFromJobSuccessResult(String result) { - CreateOrUpdateRuleResultObject resultObject = (CreateOrUpdateRuleResultObject)SerializerHelper.fromSerializedString(result); - if(resultObject != null) { - return resultObject.getRuleId(); - } - - return 0; - } + @Override + public String getResponse() { + NetworkRuleConfigVO netRule = (NetworkRuleConfigVO)getResponseObject(); + + PortForwardingServiceRuleResponse response = new PortForwardingServiceRuleResponse(); + response.setRuleId(netRule.getId()); + response.setPortForwardingServiceId(netRule.getSecurityGroupId()); + response.setPrivatePort(netRule.getPrivatePort()); + response.setProtocol(netRule.getProtocol()); + response.setPublicPort(netRule.getPublicPort()); + + return SerializerHelper.toSerializedString(response); + } } diff --git a/server/src/com/cloud/api/response/PortForwardingServiceRuleResponse.java b/server/src/com/cloud/api/response/PortForwardingServiceRuleResponse.java new file mode 100644 index 00000000000..5337040a3d2 --- /dev/null +++ b/server/src/com/cloud/api/response/PortForwardingServiceRuleResponse.java @@ -0,0 +1,61 @@ +package com.cloud.api.response; + +import com.cloud.api.ResponseObject; +import com.cloud.serializer.Param; + +public class PortForwardingServiceRuleResponse implements ResponseObject { + @Param(name="id") + private long ruleId; + + @Param(name="publicport") + private String publicPort; + + @Param(name="privateport") + private String privatePort; + + @Param(name="protocol") + private String protocol; + + @Param(name="portforwardingserviceid") + private Long portForwardingServiceId; + + public Long getPortForwardingServiceId() { + return portForwardingServiceId; + } + + public void setPortForwardingServiceId(Long portForwardingServiceId) { + this.portForwardingServiceId = portForwardingServiceId; + } + + public long getRuleId() { + return ruleId; + } + + public void setRuleId(long ruleId) { + this.ruleId = ruleId; + } + + public String getPublicPort() { + return publicPort; + } + + public void setPublicPort(String publicPort) { + this.publicPort = publicPort; + } + + public String getPrivatePort() { + return privatePort; + } + + public void setPrivatePort(String privatePort) { + this.privatePort = privatePort; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } +} diff --git a/server/src/com/cloud/api/response/SecurityGroupResponse.java b/server/src/com/cloud/api/response/SecurityGroupResponse.java new file mode 100644 index 00000000000..efa21a2465f --- /dev/null +++ b/server/src/com/cloud/api/response/SecurityGroupResponse.java @@ -0,0 +1,72 @@ +package com.cloud.api.response; + +import com.cloud.api.ResponseObject; +import com.cloud.serializer.Param; + +public class SecurityGroupResponse implements ResponseObject { + @Param(name="id") + private Long id; + + @Param(name="name") + private String name; + + @Param(name="description") + private String description; + + @Param(name="account") + private String accountName; + + @Param(name="domainid") + private Long domainId; + + @Param(name="domain") + private String domainName; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getAccountName() { + return accountName; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + public Long getDomainId() { + return domainId; + } + + public void setDomainId(Long domainId) { + this.domainId = domainId; + } + + public String getDomainName() { + return domainName; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } +} diff --git a/server/src/com/cloud/server/ManagementServer.java b/server/src/com/cloud/server/ManagementServer.java index bdf5ac62196..c46a5fb6ecf 100644 --- a/server/src/com/cloud/server/ManagementServer.java +++ b/server/src/com/cloud/server/ManagementServer.java @@ -26,6 +26,8 @@ import java.util.Map; import com.cloud.alert.AlertVO; import com.cloud.api.commands.CreateDomainCmd; +import com.cloud.api.commands.CreatePortForwardingServiceCmd; +import com.cloud.api.commands.CreatePortForwardingServiceRuleCmd; import com.cloud.api.commands.EnableAccountCmd; import com.cloud.api.commands.EnableUserCmd; import com.cloud.api.commands.GetCloudIdentifierCmd; @@ -1409,36 +1411,27 @@ public interface ManagementServer { * @param userId */ void logoutUser(Long userId); - - /** - * Updates a configuration value. - * @param userId - * @param name - * @param value - * @return - */ -// void updateConfiguration(long userId, String name, String value) throws InvalidParameterValueException, InternalErrorException; - + /** - * Creates or updates an IP forwarding or load balancer rule. - * @param isForwarding if true, an IP forwarding rule will be created/updated, else a load balancer rule will be created/updated - * @param address - * @param port - * @param privateIPAddress - * @param privatePort - * @param protocol - * @return the rule if it was successfully created + * Creates a network rule as part of a port forwarding service. If this port forwarding service has been applied to any virtual + * machines, the network rules will get sent to the router. + * @param cmd the command describing the port forwarding service the rule belongs to, the public port, the private port, and the protocol + * @return a new network rule that is part of the port forwarding service if successful, null otherwise * @throws InvalidParameterValueException * @throws PermissionDeniedException * @throws NetworkRuleConflictException * @throws InternalErrorException - */ - NetworkRuleConfigVO createOrUpdateRule(long userId, long securityGroupId, String address, String port, String privateIpAddress, String privatePort, String protocol, String algorithm) - throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException; - long createOrUpdateRuleAsync(boolean isForwarding, long userId, long accountId, Long domainId, long securityGroupId, String address, - String port, String privateIpAddress, String privatePort, String protocol, String algorithm); - - /** + */ + NetworkRuleConfigVO createPortForwardingServiceRule(CreatePortForwardingServiceRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException; + + /** + * Apply a port forwarding service rule to all VMs that have the port forwarding service applied + * @param ruleId the id of the created rule to apply + * @return the updated rule if successful, null otherwise + */ + NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException; + + /** * Deletes an IP forwarding or load balancer rule * @param ruleId * @param userId @@ -1873,7 +1866,7 @@ public interface ManagementServer { * @param accountId owner of the security group, can be null for domain level security groups * @return */ - SecurityGroupVO createSecurityGroup(String name, String description, Long domainId, Long accountId); + SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException; /** * Delete a security group. If the group is being actively used, it cannot be deleted. diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 6eead0a7389..b3063514fad 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -65,6 +65,7 @@ import com.cloud.api.commands.CancelMaintenanceCmd; import com.cloud.api.commands.CancelPrimaryStorageMaintenanceCmd; import com.cloud.api.commands.CopyTemplateCmd; import com.cloud.api.commands.CreateDomainCmd; +import com.cloud.api.commands.CreatePortForwardingServiceCmd; import com.cloud.api.commands.CreatePortForwardingServiceRuleCmd; import com.cloud.api.commands.CreateTemplateCmd; import com.cloud.api.commands.CreateVolumeCmd; @@ -3457,79 +3458,6 @@ public class ManagementServerImpl implements ManagementServer { return newFwRule; } - @DB - protected NetworkRuleConfigVO createNetworkRuleConfig(long userId, long securityGroupId, String port, String privatePort, String protocol, String algorithm) - throws NetworkRuleConflictException { - if (protocol == null) { - protocol = "TCP"; - } - - Long ruleId = null; - Transaction txn = Transaction.currentTxn(); - try { - List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId); - for (NetworkRuleConfigVO existingRule : existingRules) { - if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) { - throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol); - } - } - - txn.start(); - NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol); - netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating); - netRule = _networkRuleConfigDao.persist(netRule); - ruleId = netRule.getId(); - txn.commit(); - - // check if we are within context of async-execution - AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); - if (asyncExecutor != null) { - AsyncJobVO job = asyncExecutor.getJob(); - - if (s_logger.isInfoEnabled()) - s_logger.info("Created a new port forwarding service rule instance " + ruleId + ", update async job-" + job.getId() + " progress status"); - - _asyncMgr.updateAsyncJobAttachment(job.getId(), "network_rule_config", ruleId); - _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, ruleId); - } - - txn.start(); - if (ruleId != null) { - List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(securityGroupId); - if ((sgMappings != null) && !sgMappings.isEmpty()) { - for (SecurityGroupVMMapVO sgMapping : sgMappings) { - UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId()); - createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), Long.valueOf(securityGroupId)); - } - } - - NetworkRuleConfigVO rule = _networkRuleConfigDao.findById(ruleId); - rule.setCreateStatus(AsyncInstanceCreateStatus.Created); - _networkRuleConfigDao.update(ruleId, rule); - } - - txn.commit(); - } catch (Exception ex) { - txn.rollback(); - - if (ruleId != null) { - txn.start(); - NetworkRuleConfigVO rule = _networkRuleConfigDao.findById(ruleId); - rule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted); - _networkRuleConfigDao.update(ruleId, rule); - txn.commit(); - } - - if (ex instanceof NetworkRuleConflictException) { - throw (NetworkRuleConflictException) ex; - } - s_logger.error("Unexpected exception creating port forwarding service rule (pfServiceId:" + securityGroupId + ",port:" + port + ",privatePort:" + privatePort + ",protocol:" + protocol + ")", - ex); - } - - return _networkRuleConfigDao.findById(ruleId); - } - @Override public boolean deleteNetworkRuleConfig(long userId, long networkRuleId) { try { @@ -5790,10 +5718,18 @@ public class ManagementServerImpl implements ManagementServer { } @Override - public NetworkRuleConfigVO createOrUpdateRule(long userId, long securityGroupId, String address, String port, String privateIpAddress, String privatePort, String protocol, - String algorithm) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException { + public NetworkRuleConfigVO createPortForwardingServiceRule(CreatePortForwardingServiceRuleCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, NetworkRuleConflictException, InternalErrorException { NetworkRuleConfigVO rule = null; try { + Long securityGroupId = cmd.getPortForwardingServiceId(); + String port = cmd.getPublicPort(); + String privatePort = cmd.getPrivatePort(); + String protocol = cmd.getProtocol(); + Long userId = UserContext.current().getUserId(); + if (userId == null) { + userId = Long.valueOf(User.UID_SYSTEM); + } + SecurityGroupVO sg = _securityGroupDao.findById(Long.valueOf(securityGroupId)); if (sg == null) { throw new InvalidParameterValueException("port forwarding service " + securityGroupId + " does not exist"); @@ -5808,13 +5744,48 @@ public class ManagementServerImpl implements ManagementServer { if (!NetUtils.isValidProto(protocol)) { throw new InvalidParameterValueException("Invalid protocol"); } + } else { + protocol = "TCP"; } - if (algorithm != null) { - if (!NetUtils.isValidAlgorithm(algorithm)) { - throw new InvalidParameterValueException("Invalid algorithm"); + + // validate permissions + Account account = (Account)UserContext.current().getAccountObject(); + if (account != null) { + if (isAdmin(account.getType())) { + if (!_domainDao.isChildDomain(account.getDomainId(), sg.getDomainId())) { + throw new PermissionDeniedException("Unable to find rules for port forwarding service id = " + securityGroupId + ", permission denied."); + } + } else if (account.getId().longValue() != sg.getAccountId().longValue()) { + throw new PermissionDeniedException("Invalid port forwarding service (" + securityGroupId + ") given, unable to create rule."); } } - rule = createNetworkRuleConfig(userId, securityGroupId, port, privatePort, protocol, algorithm); + + List existingRules = _networkRuleConfigDao.listBySecurityGroupId(securityGroupId); + for (NetworkRuleConfigVO existingRule : existingRules) { + if (existingRule.getPublicPort().equals(port) && existingRule.getProtocol().equals(protocol)) { + throw new NetworkRuleConflictException("port conflict, port forwarding service contains a rule on public port " + port + " for protocol " + protocol); + } + } + + NetworkRuleConfigVO netRule = new NetworkRuleConfigVO(securityGroupId, port, privatePort, protocol); + netRule.setCreateStatus(AsyncInstanceCreateStatus.Creating); + rule = _networkRuleConfigDao.persist(netRule); + + /* FIXME: async job needs to be hooked up... + // check if we are within context of async-execution + AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); + if (asyncExecutor != null) { + AsyncJobVO job = asyncExecutor.getJob(); + + if (s_logger.isInfoEnabled()) + s_logger.info("Created a new port forwarding service rule instance " + rule.getId() + ", update async job-" + job.getId() + " progress status"); + + _asyncMgr.updateAsyncJobAttachment(job.getId(), "network_rule_config", rule.getId()); + _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, rule.getId()); + } + */ + +// rule = createNetworkRuleConfig(userId, securityGroupId, port, privatePort, protocol); } catch (Exception e) { if (e instanceof NetworkRuleConflictException) { throw (NetworkRuleConflictException) e; @@ -5833,21 +5804,34 @@ public class ManagementServerImpl implements ManagementServer { } @Override - public long createOrUpdateRuleAsync(boolean isForwarding, long userId, long accountId, Long domainId, long securityGroupId, String address, String port, - String privateIpAddress, String privatePort, String protocol, String algorithm) { + public NetworkRuleConfigVO applyPortForwardingServiceRule(Long ruleId) throws NetworkRuleConflictException { + NetworkRuleConfigVO netRule = null; + if (ruleId != null) { + Long userId = UserContext.current().getUserId(); + if (userId == null) { + userId = User.UID_SYSTEM; + } - CreateOrUpdateRuleParam param = new CreateOrUpdateRuleParam(isForwarding, userId, accountId, address, port, privateIpAddress, privatePort, protocol, algorithm, domainId, - securityGroupId); - Gson gson = GsonHelper.getBuilder().create(); + netRule = _networkRuleConfigDao.findById(ruleId); + List sgMappings = _securityGroupVMMapDao.listBySecurityGroup(netRule.getSecurityGroupId()); + if ((sgMappings != null) && !sgMappings.isEmpty()) { + try { + for (SecurityGroupVMMapVO sgMapping : sgMappings) { + UserVm userVm = _userVmDao.findById(sgMapping.getInstanceId()); + createFirewallRule(userId, sgMapping.getIpAddress(), userVm, netRule.getPublicPort(), netRule.getPrivatePort(), netRule.getProtocol(), netRule.getSecurityGroupId()); + } + } catch (NetworkRuleConflictException ex) { + netRule.setCreateStatus(AsyncInstanceCreateStatus.Corrupted); + _networkRuleConfigDao.update(ruleId, netRule); + throw ex; + } + } - AsyncJobVO job = new AsyncJobVO(); - job.setUserId(UserContext.current().getUserId()); - job.setAccountId(accountId); - job.setCmd("CreateOrUpdateRule"); - job.setCmdInfo(gson.toJson(param)); - job.setCmdOriginator(CreatePortForwardingServiceRuleCmd.getResultObjectName()); - - return _asyncMgr.submitAsyncJob(job); + netRule.setCreateStatus(AsyncInstanceCreateStatus.Created); + _networkRuleConfigDao.update(ruleId, netRule); + } + + return netRule; } public void deleteRule(long ruleId, long userId, long accountId) throws InvalidParameterValueException, PermissionDeniedException, InternalErrorException { @@ -6889,8 +6873,48 @@ public class ManagementServerImpl implements ManagementServer { } @Override - public SecurityGroupVO createSecurityGroup(String name, String description, Long domainId, Long accountId) { - SecurityGroupVO group = new SecurityGroupVO(name, description, domainId, accountId); + public SecurityGroupVO createPortForwardingService(CreatePortForwardingServiceCmd cmd) throws InvalidParameterValueException { + Account account = (Account)UserContext.current().getAccountObject(); + Long domainId = cmd.getDomainId(); + String accountName = cmd.getAccountName(); + Long accountId = null; + String portForwardingServiceName = cmd.getPortForwardingServiceName(); + + if (account != null) { + if (isAdmin(account.getType())) { + if ((accountName != null) && (domainId != null)) { + if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) { + throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service in domain " + domainId + ", permission denied."); + } + + Account userAccount = findActiveAccount(accountName, domainId); + if (userAccount != null) { + accountId = userAccount.getId(); + } else { + throw new InvalidParameterValueException("Unable to create port forwarding service " + portForwardingServiceName + ", could not find account " + accountName + " in domain " + domainId); + } + } else { + // the admin must be creating the security group + if (account != null) { + accountId = account.getId(); + domainId = account.getDomainId(); + } + } + } else { + accountId = account.getId(); + domainId = account.getDomainId(); + } + } + + if (accountId == null) { + throw new ServerApiException(BaseCmd.ACCOUNT_ERROR, "Unable to create port forwarding service, no account specified."); + } + + if (isSecurityGroupNameInUse(domainId, accountId, portForwardingServiceName)) { + throw new InvalidParameterValueException("Unable to create port forwarding service, a service with name " + portForwardingServiceName + " already exisits."); + } + + SecurityGroupVO group = new SecurityGroupVO(portForwardingServiceName, cmd.getDescription(), domainId, accountId); return _securityGroupDao.persist(group); }